RC4算法
RC4是一种对称密码算法,它属于对称密码算法中的序列密码(streamcipher,也称为流密码),它是可变**长度,面向字节操作的流密码。
RC4是流密码streamcipher中的一种,为序列密码。RC4加密算法是Ron Rivest在1987年设计出的**长度可变的加密算法簇。起初该算法是商业机密,直到1994年,它才公诸于众。由于RC4具有算法简单,运算速度快,软硬件实现都十分容易等优点,使其在一些协议和标准里得到了广泛应用。
流密码也属于对称密码,但与分组加密算法不同的是,流密码不对明文数据进行分组,而是用**生成与明文一样长短的密码流对明文进行加密,加解密使用相同的**。
RC4算法特点:(1)、算法简洁易于软件实现,加密速度快,安全性比较高;(2)、**长度可变,一般用256个字节。
对称密码算法的工作方式有四种:电子密码本(ECB, electronic codebook)方式、密码分组链接(CBC, cipherblock chaining)方式、密文反馈(CFB, cipher-feedback)方式、输出反馈(OFB, output-feedback)方式。
RC4算法采用的是输出反馈工作方式,所以可以用一个短的**产生一个相对较长的**序列。
OFB方式的最大的优点是消息如果发生错误(这里指的是消息的某一位发生了改变,而不是消息的某一位丢失),错误不会传递到产生的**序列上;缺点是对插入攻击很敏感,并且对同步的要求比较高。
RC4的执行速度相当快,它大约是分块密码算法DES的5倍,是3DES的15倍,且比高级加密算法AES也快很多。RC4算法简单,实现容易。RC4的安全保证主要在于输入**的产生途径,只要在这方面不出现漏洞,采用128bit的**是非常安全的。
RC4算法加密流程:包括**调度算法KSA和伪随机子密码生成算法PRGA两大部分(以**长度为256个字节为例)。
**调度算法:首先初始化状态矢量S,矢量S中元素的值被按升序从0到255排列,即S[0]=00, S[1]=1, …, S[255]=255.同时建立一个临时矢量T,如果**K的长度为256字节,则将K赋给T。否则,若**长度为keylen字节,则将K的值赋给T的前keylen个元素,并循环重复用K的值赋给T剩下的元素,直到T的所有元素都被赋值。
#include <stdio.h>
#define MAX_CHAR_LEN 10000
void produceKeystream(int textlength, unsigned char key[],
int keylength, unsigned char keystream[])
{
unsigned int S[256];
int i, j = 0, k;
unsigned char tmp;
for (i = 0; i<256; i++)
S[i] = i;
for (i = 0; i<256; i++) {
j = (j + S[i] + key[i % keylength]) % 256;
tmp = S[i];
S[i] = S[j];
S[j] = tmp;
}
i = j = k = 0;
while (k < textlength) {
i = (i + 1) % 256;
j = (j + S[i]) % 256;
tmp = S[i];
S[i] = S[j];
S[j] = tmp;
keystream[k++] = S[(S[i] + S[j]) % 256];
}
}
void encrypt(int textlength, unsigned char plaintext[],
unsigned char keystream[],
unsigned char ciphertext[])
{
int i;
for (i = 0; i<textlength; i++)
ciphertext[i] = keystream[i] ^ plaintext[i];
}
int main(int argc, char* argv[])
{
if (argc != 2) {
printf("Please use one and only one filename as a parameter\n");
return 0;
}
unsigned char plaintext[MAX_CHAR_LEN];
unsigned char key[32];
unsigned char keystream[MAX_CHAR_LEN];
unsigned char ciphertext[MAX_CHAR_LEN];
unsigned c;
int i = 0, textlength, keylength;
FILE *fp;
if ((fp = fopen(*++argv, "r")) == NULL) {
printf("file \"%s\" not found!\n", *argv);
return 0;
}
while ((c = getc(fp)) != EOF)
plaintext[i++] = c;
textlength = i;
fclose(fp);
/* input a key */
printf("passwd: ");
for (i = 0; (c = getchar()) != '\n'; i++)
key[i] = c;
key[i] = '\0';
keylength = i;
/* use key to generate a keystream */
produceKeystream(textlength, key, keylength, keystream);
/* use the keystream and plaintext to generate ciphertext */
encrypt(textlength, plaintext, keystream, ciphertext);
fp = fopen(*argv, "w");
for (int i = 0; i<textlength; i++)
putc(ciphertext[i], fp);
fclose(fp);
return 0;
}
使用:cmd: 文件路径 文件名