From 4cb2532c2595674053b8abebb8b8f337f4977876 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=81=E6=A0=91=E4=BA=BA?= Date: Wed, 4 Sep 2024 19:01:49 +0100 Subject: [PATCH] fix: qmc2_rc4 impl --- um_crypto/qmc/src/v2_rc4/cipher.rs | 47 ++++++++++++++++++++++--- um_crypto/qmc/src/v2_rc4/segment_key.rs | 4 +-- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/um_crypto/qmc/src/v2_rc4/cipher.rs b/um_crypto/qmc/src/v2_rc4/cipher.rs index 43fdd51..6069e82 100644 --- a/um_crypto/qmc/src/v2_rc4/cipher.rs +++ b/um_crypto/qmc/src/v2_rc4/cipher.rs @@ -31,7 +31,7 @@ impl QMC2RC4 { let n = self.key.len(); for (value, offset) in dst.iter_mut().zip(offset..) { - let idx = get_segment_key(offset as u64, self.key[offset % n], self.hash); + let idx = get_segment_key(offset as u64, self.key[offset % n], self.hash) as usize; *value ^= self.key[idx % n]; } } @@ -42,10 +42,11 @@ impl QMC2RC4 { let id = offset / OTHER_SEGMENT_SIZE; let block_offset = offset % OTHER_SEGMENT_SIZE; - let skip = get_segment_key(id as u64, self.key[block_offset % n], self.hash); + let seed = self.key[id % n]; + let skip = get_segment_key(id as u64, seed, self.hash) % 512; debug_assert!(data.len() <= OTHER_SEGMENT_SIZE - block_offset); - let key_stream = self.key_stream.iter().skip(skip + block_offset); + let key_stream = self.key_stream.iter().skip(skip as usize + block_offset); for (datum, &key) in data.iter_mut().zip(key_stream) { *datum ^= key; } @@ -83,4 +84,42 @@ impl QMC2RC4 { } } -// TODO: Add tests here +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_qmc2_header() { + let mut data = [ + 0x39, 0x5a, 0x4f, 0x75, 0x38, 0x71, 0x37, 0x6b, 0x36, 0x51, 0x53, 0x6d, 0x7a, 0x66, + 0x53, 0x4b, 0x66, 0x50, 0x69, 0x34, 0x67, 0x6c, 0x33, 0x7a, 0x55, 0x62, 0x35, 0x5a, + 0x32, 0x75, 0x4f, 0x68, 0x44, 0x52, 0x6d, 0x65, 0x75, 0x6e, 0x39, 0x52, 0x30, 0x7a, + 0x68, 0x62, 0x73, 0x59, 0x39, 0x48, 0x55, 0x57, 0x73, 0x32, 0x5a, 0x70, 0x64, 0x50, + 0x4e, 0x52, 0x6a, 0x63, 0x4d, 0x39, 0x37, 0x76, 0x72, 0x47, 0x64, 0x4d, 0x62, 0x6d, + 0x58, 0x68, 0x75, 0x47, 0x37, 0x56, 0x69, 0x6b, 0x4a, 0x79, 0x66, 0x63, 0x70, 0x39, + 0x59, 0x34, 0x43, 0x6b, 0x45, 0x32, 0x5a, 0x31, 0x38, 0x77, 0x70, 0x43, 0x51, 0x79, + 0x6a, 0x62, 0x32, 0x33, 0x65, 0x58, 0x4a, 0x4d, 0x33, 0x4e, 0x70, 0x62, 0x62, 0x67, + 0x4c, 0x54, 0x78, 0x64, 0x64, 0x77, 0x6e, 0x72, 0x37, 0x41, 0x54, 0x39, 0x42, 0x52, + 0x47, 0x32, 0x1a, 0xe4, 0x1b, 0x71, 0x68, 0x29, 0xb3, 0x6e, 0xad, 0xc5, 0x28, 0x12, + 0xd6, 0xa4, 0x4b, 0x06, 0x7a, 0xdc, 0x90, 0x15, 0x99, 0xd6, 0xbf, 0x72, 0xa2, 0x30, + 0x37, 0x6b, 0x5c, 0xd6, 0x2f, 0x35, 0x14, 0x8a, 0xd6, 0xfb, 0x9f, 0xee, 0x7d, 0x2d, + 0xb7, 0x37, 0xf2, 0x0b, 0x6e, 0x00, 0xfb, 0xa0, 0x3c, 0x40, 0xf3, 0x36, 0xb2, 0x76, + 0x20, 0x0f, 0x9e, 0xa5, 0xa3, 0x15, 0x60, 0x23, 0x15, 0x29, 0xa1, 0x91, 0xbf, 0xfb, + 0x12, 0x95, 0xaa, 0x8d, 0x92, 0xc6, 0x0b, 0x8d, 0x49, 0x99, 0xa5, 0xe0, 0x05, 0xcf, + 0xb6, 0xac, 0x07, 0x54, 0x58, 0x28, 0xf9, 0x96, 0xd1, 0x9a, 0xfe, 0x0b, 0x3c, 0xfb, + 0x0b, 0x25, 0x7a, 0x43, 0x5a, 0x33, 0xc3, 0x7a, 0xfc, 0x33, 0xa3, 0xc2, 0x65, 0x48, + 0x29, 0x8d, 0x2c, 0x8f, 0x4e, 0x88, 0xfd, 0x44, 0xfd, 0xd5, 0xca, 0xb9, 0x8d, 0x62, + 0x4a, 0x48, 0x20, 0x1du8, + ]; + let key = (b'a'..=b'z') + .chain(b'A'..=b'Z') + .chain(b'0'..=b'9') + .cycle() + .take(512) + .collect::>(); + + let mut cipher = QMC2RC4::new(&key); + cipher.transform(0, &mut data); + assert_eq!(data, [0u8; 256]); + } +} diff --git a/um_crypto/qmc/src/v2_rc4/segment_key.rs b/um_crypto/qmc/src/v2_rc4/segment_key.rs index b4ed76b..104af3a 100644 --- a/um_crypto/qmc/src/v2_rc4/segment_key.rs +++ b/um_crypto/qmc/src/v2_rc4/segment_key.rs @@ -1,9 +1,9 @@ -pub fn get_segment_key(id: u64, seed: u8, hash: f64) -> usize { +pub fn get_segment_key(id: u64, seed: u8, hash: f64) -> u32 { match seed { 0 => 0, seed => { let result = hash / ((id + 1).wrapping_mul(seed.into()) as f64) * 100.0; - result as usize + result as u32 } } }