您的位置:首页 > 其它

Alleged RC4密码算法分析与实现

2017-07-20 19:17 330 查看
Alleged RC4密码算法即所谓RC4密码算法,由RSA算法(Ronald Rivest,Adi Shamir,Leonard Adleman)发明者之一的Ronald Rivest设计。RC4之所以加上Alleged是起初在RSADSI(RSA数据安全有限公司),该算法是被保密的,想要了解该算法的细节需要与其签署保密协议后才能得到。但是后来,该算法被匿名公开,并迅速传遍全世界的FTP网点,最后在密码学课上被讲解。而RSADSI却从未正式公布该算法,并且宣称即使代码公开,它依旧是商业机密。这也就是为什么说它也叫Alleged RC4(所谓的RC4)。

1、RC4算法的细节:

RC4算法包括两部分:

①初始化算法(Key-scheduling algorithm ,KSA)

②伪随机子生成算法(Pseudo-random generation algorithm ,PRGA)

伪随机子k是由初始化的S向量所生成的。

(1)、初始化算法:

首先RC4以OFB模式(Output-Feedback,输出反馈模式)工作:即所谓初始化向量加密后与明文分组直接异或得到密文分组(密钥序列和明文序列独立)。但是由于RC4和DES不同,DES的分组是64bit即8字节为一组,而RC4是以8bit为一组,即以字节流方式进行加密(流密码)。而初始化向量IV(Initialization Vector)是一个长度为256的单字节数组S。S的初始化是0~255的索引直接赋给索引到的内存,即线性填充::

for i from 0 to 255

S[i] = i;

然后用可变长度的密钥(40~2048 bits,即最小5字节最大256字节),填充另一个256字节的数组K。由于密钥长度不一定为256字节,所以不断重复密钥,直至填满256字节的K数组:

for i from 0 to 255

K[i] = key[i] % len; //len = strlen(key);

最后用两个计数器进行S盒的混乱置换:

for i from o to 255

j = (j + S[i] + K[i]) mod 256; //key不一样则K[i]不同,j也就不同

swap(S[i],S[j]); //置换,打乱原有线性规律

完成以上三步,向量S(S盒)就初始化完毕了。初始化S其实就是将Key密钥经过运算分散到S盒中去,并打乱原有S盒顺序(i保证每个元素的改变、j保证元素随机(伪随机)的改变),不同密钥就对应不同的S盒。

(2)、伪随机子生成算法:

有了S向量,就可以进行加密操作了,加密操作只是对明文字节流和向量生成的伪随机算子进行异或操作就得到密文流。而伪随机算子的产生算法如下(注意i和j是计数器,不是数组向量的索引):

len = strlen(plaintext); //明文的长度

i = 0, j = 0; //计数器i和j初始化为0

for n from 0 to len

i = (i + 1) mod 256;

j = (j + S[i]) mod 256;

swap(S[i], S[j]); //加密过程中继续打乱,提高混乱度

t = (S[i] + S[j]) mod 256;

K = S[t]; //得伪到随机算子



伪随机算子字节K与明文一个字节异或得到密文字节,循环len次则明文加密完毕。解密则是K与密文的异或得到明文(Plaintext ⊕ K = Ciphertext, Ciphertext ⊕ K = Plaintext)。

2、RC4代码实现与测试:

(1)算法实现:

由于RC4算法的结构简单,分析过程和编码过程基本相差无几。代码如下:

#include "rc4.h"

void rc4_algorithm(unsigned char * data, unsigned char * key)
{
unsigned char s[256] = {0};//向量(S盒)
size_t len_data = strlen((const char *)data);
size_t len_key = strlen((const char *)key);

vector_init(s, key, len_key);//先根据key密钥初始化向量
encrypt(s, data, len_data);//再用初始化的向量对data数据加密
}
//初始化向量
void vector_init(unsigned char *s, unsigned char *key, size_t len)
{
int i = 0, j = 0;
unsigned char k[256] = {0};
for(i = 0; i < 256; i++){
s[i] = i;
k[i] = key[i % len];
}
//使线性的向量经过key的变换处理为非线性
for(i = 0; i < 256; i++){
j = (j + s[i] + k[i]) % 256;
swap(&s[i],&s[j]);
}
}
void encrypt(unsigned char *s, unsigned char *data, size_t len)
{
size_t i = 0, j = 0, n = 0, t = 0;
for(n = 0; n < len; n++){
i = (i + 1) % 256;
j = (j + s[i]) % 256;
swap(&s[i], &s[j]);
t = (s[i] + s[j]) % 256;

data
^= s[t];//字节流异或加密
}
}

void swap(unsigned char * a, unsigned char * b)
{
// *a ^= *b ^= *a ^= *b;//注意:种做法有一个弊端。当a和b是一块内存,则该内存的值经过交换操作后被置为0
unsigned char temp;
temp = *a;
*a = *b;
*b = temp;
}


(2)测试:

/*
*Author:Kangruojin
*Time:2017年7月20日15:11:28
*Mail:mailbox_krj@163.com
*versionL:v1.1
*/
#include "rc4.h"

int main(int argc, char * argv[])
{
unsigned char message[] = "I love you!";
//打印明文字符串与明文字节流
printf("明文:%s\n",message);
int len = strlen((const char*)message);
for(int i = 0; i < len; i++){
printf("%02x",message[i]);
}
printf("\n");
//打印密文字符串与密文字节流
rc4_algorithm(message, (unsigned char *)argv[1]);
printf("秘文:%s\n",message);
for(int i = 0; i < len; i++){
printf("%02x",message[i]);
}
printf("\n");
//打印解密后明文字符串与明文字节流
rc4_algorithm(message, (unsigned char *)argv[1]);
printf("明文:%s\n",message);
for(int i = 0; i < len; i++){
printf("%02x",message[i]);
}
printf("\n");
return 0;
}


不同密钥得出的加密结果的密文流不同:



参考资料:《应用密码学–协议算法与C源程序》[美]Bruce Schneier著 ,机械工业出版社。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  密码 数据安全 算法