序列密码(RC4)
RC4
发展历史
❝RC4是 Ron Rivest
在1987年为RSA数据安全公司开发的可变密钥长度的序列密码。
RC4加密密钥生成
加密/解密流程
- 初始化
s_box
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 values of S[i] and S[j] endfor
- 生成随机的密钥流
i := 0 j := 0 while GeneratingOutput: i := (i + 1) mod 256 j := (j + S[i]) mod 256 swap values of S[i] and S[j] K := S[(S[i] + S[j]) mod 256] output K endwhile
- 加密/解密算法
将明文当中的每一个字节和生成的密钥流进行异或, 即可得到加密之后的字节流。
❝对于RC4而言,加密过程真的很简洁,用代码实现起来也不是太复杂,因为我正在学习rust, 因此贴一个rust版的代码实现 哈哈 学以致用了。
❞代码实现
pub struct RC4 { i: u8, j: u8, s_box: [u8; 256], } impl RC4 { pub fn init(key: &[u8]) -> RC4 { let mut rc4 = RC4 { i: 0, j: 0, s_box: [0; 256] }; for (i, x) in rc4.s_box.iter_mut().enumerate() { *x = i as u8; } let mut j = 0u8; for i in 0..256 { j = j.wrapping_add(rc4.s_box[i]).wrapping_add(key[i % key.len()]); rc4.s_box.swap(i, j as usize); } return rc4; } fn next(&mut self) -> u8 { self.i = self.i.wrapping_add(1); self.j = self.j.wrapping_add(self.s_box[self.i as usize]); self.s_box.swap(self.i as usize, self.j as usize); self.s_box[(self.s_box[self.i as usize].wrapping_add(self.s_box[self.j as usize])) as usize] } fn crypt(&mut self, input: &[u8], output: &mut [u8]) { for (i, j) in input.iter().zip(output.iter_mut()) { *j = *i ^ self.next(); } } } #[cfg(test)] mod test { use crate::rc4::RC4; use std::iter::repeat; #[test] fn test() { let mut rc4 = RC4::init("key".as_bytes()); let plaintext = "plaintext"; let mut result: Vec<u8> = repeat(0).take(plaintext.len()).collect(); rc4.crypt(plaintext.as_bytes(), &mut result); println!("{:?}", result); } }
RC4的变种
对于RC4也出现了不少的变种算法,下面给出几个变种算法以及对应的实现, 具体的算法描述不展开了,有感兴趣的可以参考一下文章后面的参考资料。
RC4A
pub struct RC4A { i: u8, j1: u8, j2: u8, s1: [u8; 256], s2: [u8; 256], } impl RC4A { pub fn init(key: &[u8]) -> RC4A { let mut rc4a = RC4A { i: 0, j1: 0, j2: 0, s1: [0; 256], s2: [0; 256] }; // init s1 for (i, x) in rc4a.s1.iter_mut().enumerate() { *x = i as u8; } let mut j = 0u8; for i in 0..256 { j = j.wrapping_add(rc4a.s1[i]).wrapping_add(key[i % key.len()]); rc4a.s1.swap(i, j as usize); } // init s2 for (i, x) in rc4a.s2.iter_mut().enumerate() { *x = i as u8; } let mut j = 0u8; for i in 0..256 { j = j.wrapping_add(rc4a.s2[i]).wrapping_add(key[i % key.len()]); rc4a.s2.swap(i, j as usize); } return rc4a; } fn next1(&mut self) -> u8 { self.i = self.i.wrapping_add(1); self.j1 = self.j1.wrapping_add(self.s1[self.i as usize]); self.s1.swap(self.i as usize, self.j1 as usize); self.s2[(self.s1[self.i as usize].wrapping_add(self.s1[self.j1 as usize])) as usize] } fn next2(&mut self) -> u8 { self.i = self.i.wrapping_add(1); self.j2 = self.j2.wrapping_add(self.s2[self.i as usize]); self.s2.swap(self.i as usize, self.j2 as usize); self.s1[(self.s2[self.i as usize].wrapping_add(self.s2[self.j2 as usize])) as usize] } fn crypt(&mut self, input: &[u8], output: &mut [u8]) { for (i, j) in input.iter().zip(output.iter_mut()) { *j = *i ^ self.next1(); } for (i, j) in input.iter().zip(output.iter_mut()) { *j = *i ^ self.next2(); } } } #[cfg(test)] mod test { use crate::rc4a::RC4A; use std::iter::repeat; #[test] fn test() { let mut rc4a = RC4A::init("Key".as_bytes()); let plaintext = "plaintext"; let mut result: Vec<u8> = repeat(0).take(plaintext.len()).collect(); rc4a.crypt(plaintext.as_bytes(), &mut result); println!("{:?}", result); let mut rc4a = RC4A::init("Key".as_bytes()); let mut output: Vec<u8> = repeat(0).take(plaintext.len()).collect(); rc4a.crypt(&result, &mut output); println!("{:?}", output); } }
VMPC
pub struct VMPC { s: u8, p: [u8; 256], } impl VMPC { pub fn init(key: &[u8], iv: &[u8]) -> VMPC { let mut vmpc = VMPC { s: 0, p: [0; 256] }; for (i, x) in vmpc.p.iter_mut().enumerate() { *x = i as u8; } for i in 0..768 { vmpc.s = vmpc.p[(vmpc.s.wrapping_add(vmpc.p[i % 256]).wrapping_add(key[i % key.len()])) as usize]; vmpc.p.swap(i % 256, vmpc.s as usize); } for i in 0..768 { vmpc.s = vmpc.p[(vmpc.s.wrapping_add(vmpc.p[i % 256]).wrapping_add(iv[i % key.len()])) as usize]; vmpc.p.swap(i % 256, vmpc.s as usize); } return vmpc; } fn crypt(&mut self, input: &[u8], output: &mut [u8]) { let mut n = 0u8; for i in 0..input.len() { self.s = self.p[(self.s.wrapping_add(self.p[n as usize])) as usize]; output[i] = input[i] ^ self.p[(self.p[(self.p[self.s as usize].wrapping_add(1)) as usize]) as usize]; self.p.swap(n as usize, self.s as usize); n = n.wrapping_add(1); } return; } } #[cfg(test)] mod test { use crate::vmpc::VMPC; use std::iter::repeat; #[test] fn test() { let mut vmpc = VMPC::init("Key".as_bytes(), "iv00".as_bytes()); let plaintext = "plaintext"; let mut result: Vec<u8> = repeat(0).take(plaintext.len()).collect(); vmpc.crypt(plaintext.as_bytes(), &mut result); println!("{:?}", result); let mut vmpc = VMPC::init("Key".as_bytes(), "iv00".as_bytes()); let mut output: Vec<u8> = repeat(0).take(plaintext.len()).collect(); vmpc.crypt(&result, &mut output); println!("{:?}", output); } }
Spritz
pub struct Spritz { i: u8, j: u8, k: u8, z: u8, a: u8, w: u8, s: [u8; 256], } impl Spritz { pub fn init() -> Spritz { // INITIALIZE_STATE let mut spritz = Spritz { i: 0, j: 0, k: 0, z: 0, a: 0, w: 1, s: [0; 256] }; for (i, x) in spritz.s.iter_mut().enumerate() { *x = i as u8; } return spritz; } pub fn absorb(&mut self, buff: &[u8]) { for byte in buff { self.absorb_byte(&byte) } } fn absorb_byte(&mut self, b: &u8) { // absorb low self.absorb_nibble(b & 0xf); // absorb high self.absorb_nibble(b >> 4); } fn absorb_nibble(&mut self, x: u8) { if self.a >= 128 { self.shuffle() } // swap(S[s], S[N/2 + x]) self.s.swap(self.a as usize, (128 + x) as usize); self.a += 1; } fn absorb_stop(&mut self) { if self.a >= 128 { self.shuffle() } self.a += 1; } fn shuffle(&mut self) { self.whip(); self.crush(); self.whip(); self.crush(); self.whip(); self.a = 0; } fn whip(&mut self) { for _ in 0..512 { self.update(); } self.w = self.w.wrapping_add(2); } fn crush(&mut self) { for v in 0..128 { let mut a = self.s[v]; let mut b = self.s[255 - v]; if a > b { self.s.swap(v as usize, (255 - v) as usize); } } } fn drip(&mut self) -> u8 { if self.a > 0 { self.shuffle() } self.update(); return self.output(); } fn update(&mut self) { // i = i + w self.i = self.i.wrapping_add(self.w); // j = k + S[j + S[i]] self.j = self.k.wrapping_add(self.s[self.j.wrapping_add(self.s[self.i as usize]) as usize]); // k = i + k + S[j] self.k = self.i.wrapping_add(self.k).wrapping_add(self.s[self.j as usize]); // swap S[i], S[j] self.s.swap(self.i as usize, self.j as usize); } fn output(&mut self) -> u8 { // z = S[j + S[i + S[z + k]]] self.z = self.s[self.j.wrapping_add(self.s[self.i.wrapping_add(self.s[self.z.wrapping_add(self.k) as usize]) as usize]) as usize]; return self.z; } fn crypt(&mut self, input: &[u8], output: &mut [u8]) { if self.a > 0 { self.shuffle() } for (i, j) in input.iter().zip(output.iter_mut()) { *j = *i ^ self.drip(); } } } #[cfg(test)] mod test { use crate::spritz::Spritz; use std::iter::repeat; #[test] fn test() { let mut spritz = Spritz::init(); spritz.absorb("Key".as_bytes()); let mut result: Vec<u8> = repeat(0).take("plaintext".len()).collect(); spritz.crypt("plaintext".as_bytes(), &mut result); println!("{:?}", result); let mut spritz = Spritz::init(); let mut output: Vec<u8> = repeat(0).take("plaintext".len()).collect(); spritz.absorb("Key".as_bytes()); spritz.crypt(&result, &mut output); println!("{:?}", output); } }
代码仅供参考学习使用(简单的实现),未经过严格测试,请不要直接用于生产用途,避免造成损失。