RC 4(Rivest Cipher 4)暗号化原理--(C++説明)

5447 ワード

バッグをつかんだ後、何気なくrc 4 codedの文字を見て、とても好奇心があって、そこでインターネットで探して、とても有名な暗号化アルゴリズムであることを知りました.アルゴリズムの原理を勉強する時、私は多くの資料が似ていることを発見して、本料理の鶏がアルゴリズムの過程を理解していないことを示しています.最終的にwikiで出典を見つけて、ここでメモをとります.
まずwikiのrc 4について説明します.
RC4 generates a pseudorandom stream of bits (a keystream). As with any stream cipher, these can be used for encryption by combining it with the plaintext using bit-wise exclusive-or; decryption is performed the same way (since exclusive-or with given data is an involution). This is similar to the one-time pad except that generated pseudorandom bits, rather than a prepared stream, are used.
このアルゴリズムはまず一連の擬似乱数(keystream)を生成し、他のストリームパスワードのようにkeystreamと明文を操作によって暗号化することができる.復号化も同様であり、操作は復帰操作(involution)であるため、2回やっても元の形態になる.このアルゴリズムは,準備されたストリームではなく生成された擬似ランダムシーケンスを用いる以外は,OTPアルゴリズムと同様である.
他のブログの方法を参照して、まず以下で使う変数を紹介して、理解しやすいようにします.
wikiの紹介によると:
1組の0〜255組のシーケンスはSで表される.
擬似乱数シーケンスを生成するためのパスワードはkeyで表される.
keyの長さはkeylengthである.
i,jは2つの8 bitのインデックスポインタである.
私たちは自分でT擬似乱数シーケンスを設定します.
これらの準備ができて、アルゴリズムの原理を紹介し始めました.
The permutation is initialized with a variable length key, typically between 40 and 2048 bits, using the key-scheduling algorithm (KSA). Once this has been completed, the stream of bits is generated using the pseudo-random generation algorithm (PRGA).
シーケンスSは可変長のkeyで初期化され、一般的なkeyの長さは40−2048 bits(5 Byte−256 Byte)である.初期化はKSAアルゴリズムを用いた.このステップが完了すると、PRGAアルゴリズムを使用して、このシーケンスで擬似乱数シーケンスを生成します.
疑似乱数シーケンスがあれば、明文とそのシーケンスをバイト単位で実行するか、または操作(生成された疑似乱数シーケンスの長さは明文の長さと同じ)が残ります.だからrc 4の最大の難点はKSAとPRGAの2つのアルゴリズムにあります.見てみましょう
 
Key-scheduling algorithm (KSA)
The key-scheduling algorithm is used to initialize the permutation in the array "S". "keylength"is defined as the number of bytes in the key and can be in the range 1 ≤ keylength ≤ 256, typically between 5 and 16, corresponding to a key length of 40 – 128 bits. First, the array "S"is initialized to the identity permutation. S is then processed for 256 iterations in a similar way to the main PRGA, but also mixes in bytes of the key at the same time.
このアルゴリズムは、Sのシーケンスを初期化するために使用される.keylengthはkeyのバイト長を表すために使用され、変更長は1〜256の間で値を取ることができ、通常5〜16の間で、key lengthの40〜128 bitsに対応する.まず、Sは、秩序化シーケンス(0〜255)として初期化される.そして、PRGAトピックと同様のループ処理Sを用いるが、keyのコンテンツも処理に加わる(この一節は少し理解し難いが、大まかな過程は、key中のコンテンツとS中のコンテンツを合わせて256で型を取り、その結果を配列インデックスとしてS中の要素を入れ替え、秩序あるSを乱すことを目的とする).
次はアルゴリズムの疑似コードです.
for i from 0 to 255
    S[i] := i
endfor
j := 0
for i from 0 to 255
    j := (j + S[i] + key[i mod keylength]) mod 256
    swap values of S[i] and S[j]
endfor

 
  •             Pseudo-random generation algorithm (PRGA)

  • ​​​​​​​
    For as many iterations as are needed, the PRGA modifies the state and outputs a byte of the keystream. In each iteration, the PRGA:
  • increments i
  • looks up the ith element of S, S[i], and adds that to j
  • exchanges the values of S[i] and S[j] then uses the sum S[i] + S[j] (modulo 256) as an index to fetch a third element of S (the keystream value K below)
  • then bitwise exclusive ORed (XORed) with the next byte of the message to produce the next byte of either ciphertext or plaintext.

  • Each element of S is swapped with another element at least once every 256 iterations.
    この段落は翻訳されず、全体の方向はアルゴリズムによってSの各要素を少なくとも1回移動し、すなわち再びSシーケンスを乱すことである.さらにその中の要素を擬似ランダムに抽出し、擬似乱数シーケンスTを構成する(原文は、抽出した要素kをkeystream[i]として明文に直接対応するバイトとしてもよい).
    疑似コード:
    i := 0
    j := 0
    while GeneratingOutput:
        i := (i + 1) mod 256
        j := (j + S[i]) mod 256
        swap values of S[i] and S[j]
        K := S[(S[i] + S[j]) mod 256]
        output K
    endwhile

    アルゴリズムの中で最も重要な2つの部分は完成して、以下は明文とTをバイト単位であるいは.あるいは復帰の性質のため,復号の原理は暗号化の原理と同じであり,議論されていない.
    以下に自分のコード(C++実装)を貼り付け、そのうちSはstate_arr表示、T用temp_arrは、keystreamが偽乱数シーケンスを格納し、keyが鍵であり、contentが明文または密文であることを示す.
    ユーザは、rc 4クラスの宣言およびその他の必要な要素を含むために、自分のソースコードにinclude「RC 4.h」を追加する必要がある.デフォルトの初期化により、ユーザーはget_を通過する必要があります.info()メンバーは鍵と処理対象テキストを追加し、rc 4_を呼び出します.encrypt/rc 4 decrypt()は暗号解読を行う.送信値を使用して初期化されたユーザは、直接暗号化復号化することができる.
    RC4.h
    #ifndef RC4
    #define RC4
    #define SIZE_MAX_RC4 256
    using uchar_t=unsigned char;
    class rc4;
    #include 
    #include 
    class rc4{
    	friend void swap_rc4(uchar_t&,uchar_t&);
    	public:
    		rc4()=default;
    		rc4(const std::string&,const std::string&);
    		void get_info(const std::string&,const std::string&);
    		std::string rc4_encrypt();
    		std::string rc4_decrypt();
    		//void debug();
    	private:
    		uchar_t state_arr[SIZE_MAX_RC4];
    		uchar_t temp_arr[SIZE_MAX_RC4];
    		std::string keystream;
    		std::string key;
    		std::string content;
    		void initialize();
    		void spawn_stream();
    };
    void swap_rc4(uchar_t&,uchar_t&);
    #include "RC4.cpp"
    #endif

     
    RC4.cpp
    void swap_rc4(uchar_t &a,uchar_t &b){
    	uchar_t temp=a;
    	a=b;
    	b=temp;
    }
    void rc4::initialize(){
    	int len=key.length();
    	for(int i=0;i