RC4:对称加密算法(加解密使用同一个密钥)。
特点:算法简单,运行速度快,密钥长度可变(范围1-256字节)。
原理:1.初始化密匙盒子。
2.伪随机密码生成。
1、先初始化状态向量rc_key(256个字节,用来作为密钥流生成的种子1)
按照升序,给每个字节赋值0,1,2,3,4,5,6…..,254,255
2、初始密钥(由用户输入),长度任意
如果输入长度小于256个字节,则进行轮转,直到填满
例如输入密钥的是1,2,3,4,5 , 那么填入的是1,2,3,4,5,1,2,3,4,5,1,2,3,4,5……..
由上述轮转过程得到256个字节的向量T(用来作为密钥流生成的种子2)
3、开始对状态向量S进行置换操作(用来打乱初始种子1)
按照下列规则进行
从第零个字节开始,执行256次,保证每个字节都得到处理
解密:把密钥流重新拿过来异或一次就能得到原文。
密文数据的长度正好是明文数据长度的两倍。
注意:
网页上的加解密可能是加盐的,比如该网页:在线RC4加密 | RC4解密- 在线工具 (sojson.com)
例如:明文:AB54425D,1670334432,0 密钥:To7QG3yWupCfcWNWcMSbWWpnmFJDSlWWqUsArPwH16gaagsK 密文:U2FsdGVkX187INtjwgSpj27WtcyeCbgOjdBhBGHuCv1/5wx4Tw==
但是,这个密文数据在如下代码下是解密不出来的,因为该网页的RC4加解密有盐值,不知道该加解密盐值的话不能解密。这个密文数据通过如下RC4算法是不能解密的。
C语言代码如下:
1 #include "stdio.h" 2 #include "string.h" 3 void rc4_set_key(unsigned char* rc_key, unsigned char* key, int keylen); 4 void rc4_transform(unsigned char* rc_key, unsigned char* input, int len); 5 void asc_hex(unsigned char* asc_buf, unsigned char* hex_buf, unsigned int length); 6 void hex_asc(unsigned char* hex_buf, unsigned char* asc_buf, unsigned short length); 7 8 char key_buf[] = {"TONGYU123456@#"}; 9 unsigned char str_buf1[300]; 10 unsigned char s2[300]; 11 char In_data[300] = {"[18487118765,,20211008103230,,,]"}; 12 char out_data[300]={0}; 13 14 int main(void) 15 { 16 char tmp_buff_A[100]; 17 short keylen,In_len,i; 18 keylen = strlen("TONGYU123456@#"); 19 In_len = strlen("[18487118765,,20211008103230,,,]"); 20 /********************RC4加密 ***************************/ 21 rc4_set_key(str_buf1,key_buf,keylen); 22 rc4_transform(str_buf1,(char *)In_data,In_len); 23 printf("In_data转化前:%x\n",In_data[0]); //加密后是一堆16进制数据 24 hex_asc(In_data, tmp_buff_A,In_len); //将加密的16进制数据转化为ASCII码 ----方便显示 25 In_len = In_len*2; 26 memcpy(In_data,tmp_buff_A,In_len); 27 printf("In_data十六进制转ASCII:%s\n",In_data);//In_data:7B66237D3006EC0791E40F241220F2A8A003A226356299DBEE972E2E193E3A5C 28 29 /********************RC4解密 ***************************/ 30 asc_hex((char *)In_data,tmp_buff_A,In_len); //加解密的数据必须保持一致,加密后是16进制,所以解密也要用16进制 31 In_len = In_len/2; 32 memcpy(In_data,tmp_buff_A,In_len); 33 rc4_set_key(str_buf1,key_buf,keylen); 34 rc4_transform(str_buf1,(char *)In_data,In_len); 35 printf("In_data解密:%s\n",In_data); //In_data:[18487118765,,20211008103230,,,]A003A226356299DBEE972E2E193E3A5C 36 return 0; 37 } 38 39 void rc4_set_key(unsigned char* rc_key, unsigned char* key, int keylen) 40 { 41 int i = 0, j = 0; 42 unsigned char tmp; 43 for (i = 0; i < 256; i++) 44 { 45 rc_key[i] = i; 46 } 47 for (i = 0; i < 256; i++) 48 { 49 j = (j + rc_key[i] + key[i % keylen]) % 256; 50 tmp = rc_key[i]; 51 rc_key[i] = rc_key[j]; 52 rc_key[j] = tmp; 53 } 54 } 55 56 void rc4_transform(unsigned char* rc_key, unsigned char* input, int len) 57 { 58 int i = 0, j = 0, k = 0; 59 char tmp; 60 unsigned char subkey; 61 for (k = 0; k < len; k++) 62 { 63 i = (i + 1) % 256; 64 j = (j + rc_key[i]) % 256; 65 66 tmp = rc_key[i]; 67 rc_key[i] = rc_key[j]; 68 rc_key[j] = tmp; 69 subkey = rc_key[(rc_key[i] + rc_key[j]) % 256]; 70 input[k] ^= subkey; 71 } 72 } 73 //ASCII码转换为16进制 74 void asc_hex(unsigned char* asc_buf, unsigned char* hex_buf, unsigned int length) 75 { 76 int i,j; 77 for (i = 0, j = 0; i < length ; i++) 78 { 79 if (asc_buf[i] > '9') 80 { 81 hex_buf[j] = 9 + (asc_buf[i] & 0x0F); 82 } 83 else 84 { 85 hex_buf[j] = asc_buf[i] & 0x0F; 86 } 87 88 hex_buf[j] <<= 4; 89 i++; 90 if (asc_buf[i] > '9') 91 { 92 hex_buf[j] |= 9 + (asc_buf[i] & 0x0F); 93 } 94 else 95 { 96 hex_buf[j] |= asc_buf[i] & 0x0F; 97 } 98 j++; 99 } 100 } 101 //16进制转换为ASCII码 102 void hex_asc(unsigned char* hex_buf, unsigned char* asc_buf, unsigned short length) 103 { 104 unsigned short i; 105 unsigned char byte; 106 for (i = 0; i < length; i++) 107 { 108 byte = hex_buf[i] >> 4; 109 if (byte > 9) 110 { 111 asc_buf[i*2] = 'A' + byte - 10; 112 } 113 else 114 { 115 asc_buf[i*2] = '0' + byte; 116 } 117 118 byte = hex_buf[i] & 0x0F; 119 if (byte > 9) 120 { 121 asc_buf[i*2+1] = 'A' + byte - 10; 122 } 123 else 124 { 125 asc_buf[i*2+1] = '0' + byte; 126 } 127 } 128 }