網絡信息安全:RC4加密算法的實現

前言

這次記錄下RC4加密算法的C++實現過程。

RC4知識儲備

RC4於1987年提出,和DES算法一樣,是一種對稱加密算法,也就是說使用的密鑰爲單鑰(或稱爲私鑰)。但不同於DES的是,RC4不是對明文進行分組處理,而是字節流的方式依次加密明文中的每一個字節,解密的時候也是依次對密文中的每一個字節進行解密。
RC4算法的特點是算法簡單,運行速度快,而且密鑰長度是可變的,可變範圍爲1-256字節(8-2048比特),在如今技術支持的前提下,當密鑰長度爲128比特時,用暴力法搜索密鑰已經不太可行,所以可以預見RC4的密鑰範圍任然可以在今後相當長的時間裏抵禦暴力搜索密鑰的攻擊。實際上,如今也沒有找到對於128bit密鑰長度的RC4加密算法的有效攻擊方法。
總的來說,適合初學者、學生實踐,

代碼

話不多說,上代碼:

#include <iostream>
#include <bitset>
#include<fstream>
using namespace std;
void swap(unsigned char &a,unsigned char &b){
	unsigned char temp = a;
	a = b;
	b = temp;
	return;

}
//返回明文的字節長度
int getSecret(unsigned char key[],unsigned char data[],unsigned char k[]){
	unsigned char S[256];
	unsigned char T[256];
	int keylen;
	int datalen;
	int i,j = 0;
	//檢測密鑰長度
	for (i = 0;; i++){
		if (key[i] == '\0'){ 
			keylen = i; 
			break;
		}
	}
	//檢測明文長度
	for (i = 0;; i++){
		if (data[i] == '\0'){
			datalen = i;
			break;
		}
	}
	//KSA key scheduling算法初始化S
	for (i = 0; i < 256; i++){
		S[i] = i;
	}
	i = 0;
	if (keylen >= 256){
		for (i = 0; i < 256; i++){
			T[i] = key[i];
		}
	}
	else{
		while (1){
			for (j = 0; j < keylen; j++){
				T[i++] = key[j];
				if (i >= 256)break;
			}
			if (i >= 256)break;
		}
	}
	i = 0;
	j = 0;
	for (i = 0; i < 256; i++){
		j = (j + S[i] + T[i]) % 256;
		swap(S[i], S[j]);
	}
	//PRGA僞隨機生成算法,生成密鑰流
	int t;
	int m = 0;
	int times = datalen;
	while (times-->0){//相當於執行明文長度次,這樣生成的祕鑰流也是明文長度個字節
		i = (i + 1) % 256;
		j = (j + S[i]) % 256;
		swap(S[i], S[j]);
		t = (S[i] + S[j]) % 256;
		k[m++] = S[t];//生成密鑰流並存儲
	}
	cout << "The secret key is: ";
	for (i = 0; i < datalen;i++){
		cout << (bitset<8>)k[i] << " ";
	}
	cout << endl;
	return datalen;
}
void encrypt(unsigned char data[],unsigned char k[],int datalen){
	//異或加密
	for (int i = 0; i < datalen;i++){
		data[i] = data[i] ^ k[i];
	}
	ofstream ofile("rc4_encrypted.txt",ios::app);
	ofile << "The secret message is: ";
	cout << "The secret message is: ";
	//指定8位2進制輸出
	for (int i = 0; i < datalen; i++){
		ofile << (bitset<8>)data[i] << " ";
		cout << (bitset<8>)data[i] << " ";
	}
	ofile << endl;
	ofile.close();
	cout << endl;
}
void decrypt(unsigned char data[], unsigned char k[],int datalen){
	//異或解密
	for (int i = 0; i < datalen; i++){
		data[i] = data[i] ^ k[i];
	}
	ofstream ofile("rc4_decrypted.txt", ios::app);
	ofile << "The decrypted message is: ";
	cout << "The decrypted message is: ";
	//指定8位2進制輸出
	for (int i = 0; i < datalen; i++){
		ofile << data[i];
		cout << data[i];
	}
	ofile << endl;
	ofile.close();
	cout << endl;
}
int main(){
	unsigned char key[] = {"hello world"};
	unsigned char data[] = {"北京時間十八點實施轟炸!北京時間十八點實施轟炸!北京時間十八點實施轟炸!"};
	unsigned char k[1024] ;
	int datalen=getSecret(key, data, k);
	encrypt(data, k,datalen);
	decrypt(data, k,datalen);
}

原理概述

首先上一張圖,這張圖生動地詮釋了RC4加密流程。
流程
我們用到了256字節的S向量,T向量以及長度不定、人爲設定的密鑰,以及明文。

1. KSA Key-Scheduling Algorithm

KSA算法用來初始化S向量。首先初始化S,從S[0]到S[255]填入0到255,然後初始化T向量。初始化T的具體方法是,用密鑰滾動填充T到滿,再執行對應的換位操作,生成向量S。

2. PRGA Pseudo-Random Generation Algorithm

PRGA僞隨機生成算法是生成最終密鑰流的算法。對每個明文字節,做出對應算法的操作,從向量S中挑出一個字節作密鑰字節。最後得到和明文字節長度一樣的密鑰流。

3.加密

密鑰流和明文異或,進行加密/解密。

注意點

1.異或

真的慚愧,竟然現在才知道異或符號是^…… 異或就不多說了,即相應位的值相同的,結果爲 0,不相同的結果爲 1。例如,013 ^ 035結果爲026。
順帶說一下,與&;或|;按位取反~。按位取反額外說一下:

按位取反

按位取反運算是單目運算,用來求一個位串信息按位的反,即哪些爲0的位,結果是1,而哪些爲1的位,結果是0。例如, ~7的結果爲0xfff8。
取反運算常用來生成與系統實現無關的常數。如要將變量x最低6位置成0,其餘位不變,可用代碼x = x & ~077實現。以上代碼與整數x用2個字節還是用4個字節實現無關。
當兩個長度不同的數據進行位運算時(例如long型數據與int型數據),將兩個運算分量的右端對齊進行位運算。如果短的數爲正數,高位用0補滿;如果短的數爲負數,高位用1補滿。如果短的爲無符號整數,則高位總是用0補滿。
位運算用來對位串信息進行運算,得到位串信息結果。如以下代碼能取下整型變量k的位串信息的最右邊爲1的信息位:((k-1)^k) & k。
當你輸入cout<<~3,得到的是-4。 3的符號數爲011,按位取反得100,符號數1,爲負數,在計算機中以補碼形式存在,100是-4的補碼(3位長度),所以結果是-4。這裏在求補碼的時候不能逆“求反加1”,建議用原理求。
補碼=模 - 真值
比如-2如果按補碼的定義來求的話,它真值二進制表示爲-10,原碼爲110,那麼它求補碼用到的模就是2^3二進制爲1000,
-2的補碼=1000-10 = 110

2. unsigned char

unsigned char的範圍是0-255,char是-128-127 。本次實踐unsigned char向量S和T的長度皆已取到最長(256)。

3.文件流變量的傳遞

寫代碼發現的,雖然研究不深,但是起碼直接往函數裏面傳ofstream這樣的文件流變量會報錯無法引用函數,它是已刪除的函數。

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