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 }