#include<stdio.h>
#include<memory.h>
#include<string.h>
#include<stdlib.h>
#define buf_size 1024
typedef struct rc4_key
{
unsigned char state[256];
unsigned char x;
unsigned char y;
} rc4_key;
#define swap_byte(x,y) t = *(x); *(x) = *(y); *(y) = t
void prepare_key(unsigned char *key_data_ptr, int key_data_len, rc4_key *key)
{
int i;
unsigned char t;
unsigned char swapByte;
unsigned char index1;
unsigned char index2;
unsigned char* state;
short counter;
state = &key->state[0];
for(counter = 0; counter < 256; counter++)
state[counter] = counter;
key->x = 0;
key->y = 0;
index1 = 0;
index2 = 0;
for(counter = 0; counter < 256; counter++)
{
index2 = (key_data_ptr[index1] + state[counter] + index2) % 256;
swap_byte(&state[counter], &state[index2]);
index1 = (index1 + 1) % key_data_len;
}
}
void rc4(unsigned char *buffer_ptr, int buffer_len, rc4_key *key)
{
unsigned char t;
unsigned char x;
unsigned char y;
unsigned char* state;
unsigned char xorIndex;
short counter;
x = key->x;
y = key->y;
state = &key->state[0];
for(counter = 0; counter < buffer_len; counter++)
{
x = (x + 1) % 256;
y = (state[x] + y) % 256;
swap_byte(&state[x], &state[y]);
xorIndex = (state[x] + state[y]) % 256;
buffer_ptr[counter] ^= state[xorIndex];
}
key->x = x;
key->y = y;
}
int main()
{
char seed[256]; //key in fact
char data[512];
char fname[512];
char *tn;
char buf[buf_size];
char digit[5];
int hex, rd,i;
int n;
rc4_key key;
FILE *fp,*des;
memset(fname,0,512*sizeof(char));
if((fp=fopen("key.txt","r"))==NULL)
exit(1);
fscanf(fp,"%s %s",data,fname);
fclose(fp);
if(strcmp(fname,"")==0)
{
fprintf(stderr,"can't find the name of the file for encryption.\n");
return 1;
}
n = strlen(data);
if(n>512)
{
fprintf(stderr,"can't tolerate key longer than 512 characters.\n");
return 1;
}
if (n&1) //n is odd number
{
strcat(data,"0");
n++; //convert n to even number
}
n/=2;
memset(digit,0,5*sizeof(char));
strcpy(digit,"AA");
for (i=0;i<n;i++)
{
digit[2] = data[i*2];
digit[3] = data[i*2+1];
sscanf(digit,"%x",&hex); //characters in the file key.txt are better to be recognizable hex numbers
seed[i] = hex; //only reserve the two lower hex numbers in varible 'hex'
}
prepare_key(seed,n,&key);
if((fp=fopen(fname,"r"))==NULL)
exit(1);
tn=strdup(fname);
strcat(fname,".en");
if((des=fopen(fname,"w"))==NULL)
exit(1);
rd = fread(buf,1,buf_size,fp);
while (rd>0)
{
rc4(buf,rd,&key);
fwrite(buf,1,rd,des);
rd = fread(buf,1,buf_size,fp);
}
fclose(fp);
fclose(des);
sprintf(fname,"rm %s",tn);
system(fname);
sprintf(fname,"mv %s.en %s",tn,tn);
system(fname);
}
旁注:
1. 此代码是在UNIX下编写调试的,其中用到了函数system()来调用系统命令,所以要在windows下运行可能需要一些修改。
2. 运行该代码需要先创建文件key.txt,文件格式如下:
key filename
其中key可以是任何字符串(如 “64M便当”),它是用来加密的原始密钥。
Filename是需要加密的文件的文件路径(绝对相对路径均可)(如 1.mpg或/home/chensj/2.jpg)。
3. 由于算法使用XOR对原始数据进行处理,所以只要用相同的密钥,对同一文件再次运行本程序即是对文件的解密。
4. 由衷的希望使用该程序的兄弟们,不要忘了宣传一下我“64M便当”的blog,多谢了:)。