RC4流加密的基本流程

1、由隨機數生成16位根密鑰k

2、通過+,-和位置移動,把16位密鑰k擴充爲256位的中間變量S和T

3、根據明文的長度Length,生成Length長度的密鑰流K

4、按Length,將密鑰流K和明文按字符異或。

具體代碼如下:

//參考huangyimo博客,《RC4加密算法的原理及實現》
#include <vector>
#include <iostream>
#include <fstream>
#include "time.h"

using namespace std;
/*
	加密類
*/
class RC4 {
public:
	/*
		構造函數,參數爲密鑰長度
	*/
	RC4(int kl) :keylen(kl) {
		srand((unsigned)time(NULL));
		for (int i = 0; i < kl; ++i) {  //隨機生產長度爲keylen字節的密鑰
			int tmp = rand() % 256;
			K.push_back(char(tmp));
		}
	}
	/*
		由明文產生密文
	*/
	void encryption(const string &, const string &, const string &);

private:
	unsigned char S[256]; //狀態向量,共256字節
	unsigned char T[256]; //臨時向量,共256字節
	int keylen;        //密鑰長度,keylen個字節,取值範圍爲1-256
	vector<char> K;      //可變長度密鑰
	vector<char> k;      //密鑰流

	/*
		初始化狀態向量S和臨時向量T,供keyStream方法調用
	*/
	void initial() {
		for (int i = 0; i < 256; ++i) {
			S[i] = i;
			T[i] = K[i%keylen];
		}
	}
	/*
		初始排列狀態向量S,供keyStream方法調用
	*/
	void rangeS() {
		int j = 0;
		for (int i = 0; i < 256; ++i) {
			j = (j + S[i] + T[i]) % 256;
			//cout<<"j="<<j<<endl;
			S[i] = S[i] + S[j];
			S[j] = S[i] - S[j];
			S[i] = S[i] - S[j];
		}
	}
	/*
		生成密鑰流
		len:明文爲len個字節
	*/
	void keyStream(int len);

};
void RC4::keyStream(int len) {
	initial();
	rangeS();

	int i = 0, j = 0, t;
	while (len--) {
		i = (i + 1) % 256;
		j = (j + S[i]) % 256;

		S[i] = S[i] + S[j];
		S[j] = S[i] - S[j];
		S[i] = S[i] - S[j];

		t = (S[i] + S[j]) % 256;
		k.push_back(S[t]);
	}
}
void RC4::encryption(const string &plaintext, const string &ks, const string &ciphertext) {
	ifstream in;
	ofstream out, outks;

	in.open(plaintext);
	//獲取輸入流的長度
	in.seekg(0, ios::end);
	int lenFile = in.tellg();
	if (lenFile == -1)
	{
		printf("please input file\n");
		return;
	}
	in.seekg(0, ios::beg);

	//生產密鑰流
	keyStream(lenFile);
	outks.open(ks);
	for (int i = 0; i < lenFile; ++i) {
		outks << (k[i]);
	}
	outks.close();

	//明文內容讀入bits中
	unsigned char *bits = new unsigned char[lenFile];
	in.read((char *)bits, lenFile);
	in.close();


	out.open(ciphertext);
	//將明文按字節依次與密鑰流異或後輸出到密文文件中
	for (int i = 0; i < lenFile; ++i) {
		out << (unsigned char)(bits[i] ^ k[i]);
	}
	out.close();

	delete[]bits;
}
///////////////////////////////////////////////////////////
/*
	解密類
*/
class RC4_decryption {
public:
	/*
		構造函數,參數爲密鑰流文件和密文文件
	*/
	RC4_decryption(const string ks, const string ct) :keystream(ks), ciphertext(ct) {}
	/*
		解密方法,參數爲解密文件名
	*/
	void decryption(const string &);

private:
	string ciphertext, keystream;
};
void RC4_decryption::decryption(const string &res) {
	ifstream inks, incp;
	ofstream out;

	inks.open(keystream);
	incp.open(ciphertext);

	//計算密文長度
	inks.seekg(0, ios::end);
	const int lenFile = inks.tellg();
	inks.seekg(0, ios::beg);
	//讀入密鑰流
	unsigned char *bitKey = new unsigned char[lenFile];
	inks.read((char *)bitKey, lenFile);
	inks.close();
	//讀入密文
	unsigned char *bitCip = new unsigned char[lenFile];
	incp.read((char *)bitCip, lenFile);
	incp.close();

	//解密後結果輸出到解密文件
	out.open(res);
	for (int i = 0; i < lenFile; ++i)
		out << (unsigned char)(bitKey[i] ^ bitCip[i]);

	out.close();
}
///////////////////////////////////////////////////////////
int main() {
	RC4 rc4(16); //密鑰長16字節
	rc4.encryption("明文.txt", "密鑰流.txt", "密文.txt");

	RC4_decryption decrypt("密鑰流.txt", "密文.txt");
	decrypt.decryption("解密文件.txt");

}

明文.txt爲預先準備好的文本變量。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章