fix: qmc2_rc4 impl

This commit is contained in:
鲁树人 2024-09-04 19:01:49 +01:00
parent 6f9ed3d9cb
commit 4cb2532c25
2 changed files with 45 additions and 6 deletions

View File

@ -31,7 +31,7 @@ impl QMC2RC4 {
let n = self.key.len(); let n = self.key.len();
for (value, offset) in dst.iter_mut().zip(offset..) { 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]; *value ^= self.key[idx % n];
} }
} }
@ -42,10 +42,11 @@ impl QMC2RC4 {
let id = offset / OTHER_SEGMENT_SIZE; let id = offset / OTHER_SEGMENT_SIZE;
let block_offset = 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); 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) { for (datum, &key) in data.iter_mut().zip(key_stream) {
*datum ^= key; *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::<Vec<u8>>();
let mut cipher = QMC2RC4::new(&key);
cipher.transform(0, &mut data);
assert_eq!(data, [0u8; 256]);
}
}

View File

@ -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 { match seed {
0 => 0, 0 => 0,
seed => { seed => {
let result = hash / ((id + 1).wrapping_mul(seed.into()) as f64) * 100.0; let result = hash / ((id + 1).wrapping_mul(seed.into()) as f64) * 100.0;
result as usize result as u32
} }
} }
} }