この記事では、シンプルだが実用的な暗号化方式を実装する方法を紹介します。 実際のプロジェクト開発におけるデータ暗号化のプロセスを誰もが理解できるようにします。 1. ネットワーク通信のための一般的な暗号化プロセス暗号化アルゴリズムは数多く存在し、実際の実装プロセスも大きく異なります。 下の図は、ネットワーク通信暗号化の一般的な応用シナリオです。 暗号機に関するいくつかの指示: - クライアントとサーバーの両方が暗号化マシンをセットアップできます(キーを生成できる限り、ソフトウェアでもハードウェアでも、ローカルでもサーバー上でもかまいません)。
- キー生成コードと同期コードの両方が暗号マシンによって生成されるキーシーケンスに影響します。
- キー生成コードと同期コードが同じ場合、暗号は同じキーシーケンスを生成します。暗号化側と復号化側の両方が、キーが生成された順序を覚えておき、復号化するデータと同じ数のキーを申請する必要があります。
上図に示すように、C/Sアーキテクチャに基づくサーバーとクライアントの通信モデルは、 以下は、クライアントが暗号化された暗号文をサーバーに送信する場合の C/S 対話のプロセスです。 1サーバーは鍵暗号文を送信するまず、サーバーとクライアントの両方がデフォルトのキーを保存します サーバーはランダムにキーキージェネレータを生成し、デフォルトのキーを使用してキージェネレータを暗号化し、キー暗号文を生成します。 クライアントはコマンドを通じて定期的に鍵暗号文を要求するか、サーバーが定期的に鍵暗号文を送信することができる。 クライアントはキー暗号文を受け取った後、デフォルトのキーを使用してそれを復号化し、平文のキー生成を取得することもできます。 2. クライアントがデータを暗号化するデータを送信する前に、クライアントはまず同期コードを生成する。 同期コードとキージェネレータを暗号機に設定し、暗号機から特定の長さのキーを申請します。 平文とキーを特定のアルゴリズム(通常はXOR)で暗号化し、データ暗号文を生成します。 3. クライアントは同期コードとデータ暗号文を送信するクライアントはデータの暗号文と同期コードの平文をサーバーに送信する サーバーは同期コードを抽出する 4. サーバーはデータを受信し、復号化するサーバーは暗号機にキージェネレータと同期コードを設定し、一定数のキーを申請する。 サーバーは鍵に従って暗号文を復号し、対応する平文を取得する。 現時点では、サーバーとクライアントは同じキージェネレータと同期コードを使用しているため、両者が適用するキーシーケンスは同じである必要があります。 2. 関数の実装以下は、Yikoujun によって実装された暗号化アルゴリズムのいくつかの関数プロトタイプと機能説明です。これらの関数は基本的に、最初のセクションの機能を実装します。 1. 暗号化キー関数request_keyを申請する- int request_key( int sync, int key_num, char 鍵[])
- 関数:
- データを暗号化するための鍵を一定数暗号機に申請します。新しいキージェネレータが設定されていない場合、生成されたパスワードは順番に生成されます。鍵が申請されるたびに、最後に生成された鍵のオフセットが記録されます。次に鍵が申請されると、前回の位置から鍵が割り当てられ続けます。
- パラメータ:
- sync: 同期コード。暗号はこの同期に基づいてランダムなキーシーケンスを生成します。
- key_num: 要求されたキーの数
- key : 要求されたキーストレージのキャッシュ
- 戻り値:
- 返されたキーの実際の数
2. キーシーケンス関数set_keygenを設定する- void set_keygen( int 鍵)
- 関数:
- keygen を暗号に設定すると、生成されるランダムなキーシーケンスに影響します。
- パラメータ:
- キー: キー
- 戻り値:
- なし
3. 乱数を生成する born_seed- int born_seed( int sync, int 鍵)
- 関数:
- 同期コードとキージェネレータに基づいてランダムキーシードを生成する
- パラメータ:
- sync: 同期コード
- キー: キー
- 戻り値:
- シード
4. キージェネレータをリセットする reset_keygen()- void リセットキー生成()
- 関数:
- キージェネレータをリセットすると、生成された乱数シーケンスに影響します。
3. テストコードの例最終的なファイルは次のとおりです。 - キー.cキー.h main.c
例1: 生成されたランダムシーケンスの検出 - int main( int argc, char *argv[])
- {
- 整数i;
- 符号なし整数長さ;
- 整数j、r、キー番号;
- 符号なし整数同期 = 0;
- 符号なし文字 キー[MAX_KEY_REQUEST];
-
-
- キー番号 = 10;
-
- printf( "\n--------------デフォルトのキー生成同期コード = 0 を使用して暗号文を生成します----------------\n" );
- リセットキー生成();
-
- memset(キー,0, sizeof(キー));
- len = request_key(sync,key_num, key );
-
- print_array( "キー0-9:" , key ,len);
-
- memset(キー,0, sizeof(キー));
- len = request_key(sync,key_num, key );
-
- print_array( "キー10-19:" , key ,len);
-
- printf( "\n--------------keygen=1234 同期コード=0 を使用して暗号文を生成します----------------\n" );
- set_keygen(1234);
-
- memset(キー,0, sizeof(キー));
- len = request_key(sync,key_num, key );
-
- print_array( "キー0-9:" , key ,len);
-
- memset(キー,0, sizeof(キー));
- len = request_key(sync,key_num, key );
-
- print_array( "キー10-19:" , key ,len);
- }
実行結果: -
- キー0-9:
- a5 52 c8 14 5d f7 46 5b 89 42
- キー10-19:
- 38 69 6f a6 08 d2 69 39 cd 29
-
-
- キー0-9:
- 0e 83 0b 73 ec f5 4b 4a 74 35
- キー10-19:
- e7 f1 06 41 c8 6b aa df 0c 3d
異なるキージェネレータによって生成されたランダムシーケンスが異なることがわかります。 異なる同期コードを設定すると、シーケンスは異なります。 例2: デフォルトのキージェネレータを使用した暗号化と復号化 - 文字データ0[10]={
- 0x1、0x2、0x3、0x4、0x5、0x6、0x7、0x8、0x9、0x10、
- };
- int main( int argc, char *argv[])
- {
- 整数i;
- 符号なし整数長さ;
- 整数j、r、キー番号;
- 符号なし整数同期 = 0;
- 符号なし文字 キー[MAX_KEY_REQUEST];
- char buf[120]={0};
-
- キー番号 = 10;
- printf( "\n--------------デフォルトのキー生成を使用して暗号化を開始します----------------\n" );
- リセットキー生成();
- print_array( "\nプレーンテキスト:" , data0, key_num);
-
- memset(キー,0, sizeof(キー));
- len = request_key(sync,key_num, key );
-
- print_array( "キー:" ,キー, 長さ);
- (i=0;i<len;i++)の場合
- {
- buf[i] = data0[i]^キー[i];
- }
- print_array( "\n暗号文:" , buf, len);
-
- printf( "\n-------------------- 復号化を開始します--------------------\n" );
- リセットキー生成();
-
- memset(キー,0, sizeof(キー));
- len = request_key(sync,key_num, key );
-
-
- (i=0;i<len;i++)の場合
- {
- buf[i] = buf[i]^キー[i];
- }
-
- print_array( "\nプレーンテキスト:" , buf, len);
- }
テスト結果 -
-
- プレーンテキスト:
- 01 02 03 04 05 06 07 08 09 10
- キー:
- a5 52 c8 14 5d f7 46 5b 89 42
-
- 暗号文:
- a4 50 CB 10 58 F1 41 53 80 52
-
-
-
- プレーンテキスト:
- 01 02 03 04 05 06 07 08 09 10
例3 異なるキージェネレータと同期コードを使用した暗号化と復号化 - int main( int argc, char *argv[])
- {
- 整数i;
- 符号なし整数長さ;
- 整数j、r、キー番号;
- 符号なし整数同期 = 0;
- 符号なし文字 キー[MAX_KEY_REQUEST];
- char buf[120]={0};
- 符号なし整数mykeygen;
-
-
- (引数が4ではない場合){
- fprintf(stderr, "使用法: %s <seed> <key num> <keygen>\n" , argv[0]);
- 終了(EXIT_FAILURE);
- }
-
- 同期 = atoi(argv[1]);
- key_num = atoi(argv[2]);
- mykeygen = atoi(argv[3]);
-
- printf( "\n--------------カスタムキー生成と同期コードを使用して暗号化を開始します----------------\n" );
- set_keygen(mykeygen);
- print_array( "\nプレーンテキスト:" , data0, key_num);
-
- memset(キー,0, sizeof(キー));
- len = request_key(sync,key_num, key );
- print_array( "キー:" ,キー, 長さ);
-
- (i=0;i<len;i++)の場合
- {
- buf[i] = data0[i]^キー[i];
- }
- print_array( "\n暗号文:" , buf, len);
-
-
- printf( "\n-------------------- 復号化を開始します--------------------\n" );
- set_keygen(mykeygen);
-
- memset(キー,0, sizeof(キー));
- len = request_key(sync,key_num, key );
- (i=0;i<len;i++)の場合
- {
- buf[i] = buf[i]^キー[i];
- }
- print_array( "\nプレーンテキスト:" , buf, len);
- 終了(EXIT_SUCCESS);
- }
実行結果は次のとおりです。 -
-
- プレーンテキスト:
- 01 02 03 04 05 06 07 08 09 10
- キー:
- 53 00 29 cd 27 eb cc 80 1a d7
-
- 暗号文:
- 52 02 2a c9 22 ed cb 88 13 c7
-
-
-
- プレーンテキスト:
- 01 02 03 04 05 06 07 08 09 10
実際にデータの暗号化と復号化が実現できたことがわかります。 4. データ暗号化の実用化上記のサンプルコードを使用し、対応する関数を両方の C/S エンドに移植すると仮定します。 完全なデータ暗号化とデータ転送の参照プロセスは次のとおりです。 両者が同じキージェネレータと同期コードを設定する限り、暗号マシンによって吐き出されるキーは同じシーケンスになることを覚えておいてください。 クライアントがメッセージを送信するたびに、独自のプレーンテキスト同期コードがサーバーに送信されます。 サーバーは、事前にクライアントに送信されたキー生成コードと同期コードに基づいて復号化操作を実行できます。 プレーンテキストの同期コードは確認できますが、 ただし、暗号化マシンのアルゴリズムとサーバーから送信されたキー生成暗号文を解読する必要があります。 5. 原則暗号化アルゴリズムを実装する際の主な問題は、キーとしてランダムなシーケンスを生成する方法です。 この例では、プロトタイプが次のライブラリ関数 rand() を使用します。 - #含む
-
- 整数rand(void);
rand() 関数はランダムなシーケンスを生成できますが、生成されるシーケンスの順序は実際には毎回同じです。 - #include <stdio.h>
-
- 主要()
- {
- 整数i = 0;
-
- (i=0;i<10;i++)の場合
- {
- printf( "%d " ,rand());
- }
- putchar( '\n' );
- }
結果は次のとおりです。 - ペン@peng-virtual-machine:/mnt/hgfs/peng/rand/code$ ./a.out
- 1804289383 846930886 1681692777 1714636915 1957747793 424238335 719885386 1649760492 596516649 1189641421
- peng@peng-virtual-machine:/mnt/hgfs/peng/rand/code$ ./a.out
- 1804289383 846930886 1681692777 1714636915 1957747793 424238335 719885386 1649760492 596516649 1189641421
毎回異なるランダムシーケンスを生成したい場合はどうすればいいでしょうか?srand()関数を使用する必要があります。 - void srand(符号なしintシード);
この関数を通じてシードを設定するだけで、結果のシーケンスは完全に異なります。 通常、time() の戻り値をシードとして使用します。 ここで関数をテストするためのデータをいくつか書きます - #include <stdio.h>
-
- 主要()
- {
- 整数i = 0;
-
- srand(111);
- (i=0;i<10;i++)の場合
- {
- printf( "%d " ,rand());
- }
- putchar( '\n' );
- srand(1111);
- (i=0;i<10;i++)の場合
- {
- printf( "%d " ,rand());
- }
- putchar( '\n' );
- }
実行結果は次のとおりです。 - ペン@peng-virtual-machine:/mnt/hgfs/peng/rand/code$ ./a.out
- 1629905861 708017477 1225010071 14444113 324837614 2112273117 1166384513 1539134273 1883039818 779189906
- 1383711924 882432674 1555165704 1334863495 1474679554 676796645 154721979 534868285 1892754119 100411878
異なるシードを入力すると、異なるシーケンスが生成されることがわかります。 関数のプロトタイプは次のとおりです。 この例の原理は比較的単純であり、複雑なアプリケーション (多方向キー管理など) やデータ セキュリティは考慮されていません。 暗号化と復号化のプロセスのみを説明します。これは、暗号化と復号化のプロセスを学習して理解するためにのみ使用されます。この暗号化アルゴリズムは対称暗号化に属し、比較的単純で解読が容易です。 現在、暗号化および復号化機能は、市場で専門の企業やチームによって実装されています。 この記事はWeChat公式アカウント「Yikou Linux」から転載したものです。下のQRコードからフォローできます。この記事を転載する場合は、Yikou Linux パブリックアカウントにご連絡ください。 |