RC 4生成一个伪随机流(pseduorandom stream of bits) 来同 明文 进行 按位异或(bit-wise exclusive-or) 来 实现加密和解密
KSA(key-scheduling algorithm)
初始化数组S. 键长 1 ≤ keylength ≤ 256, 典型值为 5~ 16, 也就是 40bits ~ 128bits
for i from 0 to 255
S[i] := i
endfor
j := 0
for i from 0 to 255
j := (j + S[i] + key[i mod keylength]) mod 256
swap(&S[i],&S[j])
endfor
PRGA
使用上一步生成的S 数组来生成 伪随机流
i := 0
j := 0
while GeneratingOutput:
i := (i + 1) mod 256
j := (j + S[i]) mod 256
swap(&S[i],&S[j])
output S[(S[i] + S[j]) mod 256]
endwhile
一个C实现
unsigned char S[256]; unsigned int i, j; void swap(unsigned char *s, unsigned int i, unsigned int j) { unsigned char temp = s[i]; s[i] = s[j]; s[j] = temp; } /* KSA */ void rc4_init(unsigned char *key, unsigned int key_length) { for (i = 0; i < 256; i++) S[i] = i; for (i = j = 0; i < 256; i++) { j = (j + key[i % key_length] + S[i]) & 255; swap(S, i, j); } i = j = 0; } /* PRGA */ unsigned char rc4_output() { i = (i + 1) & 255; j = (j + S[i]) & 255; swap(S, i, j); return S[(S[i] + S[j]) & 255]; } #include < stdio.h > #include < string.h > #include < stdlib.h > #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) int main() { unsigned char *test_vectors[][2] = { {"Key", "Plaintext"}, {"Wiki", "pedia"}, {"Secret", "Attack at dawn"} }; int x; for (x = 0; x < ARRAY_SIZE(test_vectors); x++) { int y; rc4_init(test_vectors[x][0], strlen((char*)test_vectors[x][0])); for (y = 0; y < strlen((char*)test_vectors[x][1]); y++) printf("%02X", test_vectors[x][1][y] ^ rc4_output()); printf("n"); } return 0; }
Python实现
def initialize(key): """Produce a 256-entry list based on `key` (a sequence of numbers) as the first step in RC4. Note: indices in key greater than 255 will be ignored. """ k = range(256) j = 0 for i in range(256): j = (j + k[i] + key[i % len(key)]) % 256 k[i], k[j] = k[j], k[i] return k def gen_random_bytes(k): """Yield a pseudo-random stream of bytes based on 256-byte array `k`.""" i = 0 j = 0 while True: i = (i + 1) % 256 j = (j + k[i]) % 256 k[i], k[j] = k[j], k[i] yield k[(k[i] + k[j]) % 256] def run_rc4(k, text): cipher_chars = [] random_byte_gen = gen_random_bytes(k) for char in text: byte = ord(char) cipher_byte = byte ^ random_byte_gen.next() cipher_chars.append(chr(cipher_byte)) return ''.join(cipher_chars) 以上是一种实现方式, run_rc4(k, text) 输入 key 和 待加密的 text, 返回 已经加密的串 class RC4: def __init__(self, key = ""): if key: self._rc4_init(key) def _rc4_init(self, key): (self.x,self.y) = (0,0) key_len = len(key) if key_len > 256 or key_len < 1: raise IndexError, 'Invalid key length' + key_len self.state_array = [i for i in xrange(0,256)] #self.stat_array = range(0,256) for i in xrange(0,256): self.x = ((ord(key[i%key_len]) & 0xff) + self.state_array[i] + self.x) & 0xff self.state_array[i], self.state_array[self.x] = self.state_array[self.x], self.state_array[i] self.x = 0 def engine_crypt(self, input): self.out = [] for i in xrange(0,len(input)): self.x = (self.x + 1) & 0xff self.y = (self.state_array[self.x] + self.y) & 0xff self.state_array[self.x], self.state_array[self.y] = self.state_array[self.y], self.state_array[self.x] self.out.append(chr((ord(input[i]) ^ self.state_array[(self.state_array[self.x] + self.state_array[self.y]) & 0xff]))) return "".join(self.out) 以上是第2种实现,使用了class 使用方法 RC4(key).engine_crypt(text) ,返回的是加密后的串 def rc4crypt(data, key): x = 0 box = range(256) for i in range(256): x = (x + box[i] + ord(key[i % len(key)])) % 256 box[i], box[x] = box[x], box[i] x = 0 y = 0 out = [] for char in data: x = (x + 1) % 256 y = (y + box[x]) % 256 box[x], box[y] = box[y], box[x] out.append(chr(ord(char) ^ box[(box[x] + box[y]) % 256])) return ''.join(out) Python3版本 def rc4crypt(data: bytes, key: bytes) -> bytes: x = 0 box = list(range(256)) for i in range(256): x = (x + box[i] + key[i % len(key)]) % 256 box[i], box[x] = box[x], box[i] x = y = 0 out = [] for char in data: x = (x + 1) % 256 y = (y + box[x]) % 256 box[x], box[y] = box[y], box[x] out.append((char ^ box[(box[x] + box[y]) % 256])) return bytes(out) mykey = b'softs.im!' mydata = b'android/telephony/TelephonyManager' x = rc4crypt(mydata, mykey) import binascii print(x) print(binascii.hexlify(x)) y = rc4crypt(x, mykey) print(y) print(binascii.hexlify(y))
以上是一个单个函数形式的实现
PHP实现
function Encrypt($key, $pt) { $s = array(); for ($i=0; $i<256; $i++) { $s[$i] = $i; } $j = 0; $key_len = strlen($key); for ($i=0; $i<256; $i++) { $j = ($j + $s[$i] + ord($key[$i % $key_len])) % 256; //swap $x = $s[$i]; $s[$i] = $s[$j]; $s[$j] = $x; } $i = 0; $j = 0; $ct = ''; $data_len = strlen($pt); for ($y=0; $y< $data_len; $y++) { $i = ($i + 1) % 256; $j = ($j + $s[$i]) % 256; //swap $x = $s[$i]; $s[$i] = $s[$j]; $s[$j] = $x; $ct .= $pt[$y] ^ chr($s[($s[$i] + $s[$j]) % 256]); } return $ct; }
Java也可以实现
private static byte[] rc4_encrypt(byte[] key, byte[] plaintext) { byte[] S = new byte[256]; byte[] T = new byte[256]; int keylen = key.length; for (int i = 0; i < 256; i++) { S[i] = (byte) i; T[i] = key[i % keylen]; } int j = 0; for (int i = 0; i < 256; i++) { j = (j + S[i] + T[i]) & 0xFF; S[i] ^= S[j]; S[j] ^= S[i]; S[i] ^= S[j]; } byte[] ciphertext = new byte[plaintext.length]; int i = 0, k, t; j = 0; for (int counter = 0; counter < plaintext.length; counter++) { i = (i + 1) & 0xFF; j = (j + S[i]) & 0xFF; S[i] ^= S[j]; S[j] ^= S[i]; S[i] ^= S[j]; t = (S[i] + S[j]) & 0xFF; k = S[t]; ciphertext[counter] = (byte) (plaintext[counter] ^ k); } return ciphertext; }