[kgm] feat #2: basic kgm support

This commit is contained in:
鲁树人
2024-09-15 22:15:02 +01:00
parent 2222e7bc50
commit 7b4464bacd
16 changed files with 273 additions and 3 deletions

48
um_crypto/kgm/src/v3.rs Normal file
View File

@@ -0,0 +1,48 @@
use crate::header::Header;
use crate::{Decipher, KugouError};
pub struct DecipherV3 {
slot_key: [u8; 16],
file_key: [u8; 17],
}
impl DecipherV3 {
fn hash_key<T: AsRef<[u8]>>(data: T) -> [u8; 16] {
let digest = umc_utils::md5(data);
let mut result = [0u8; 16];
for (result, digest) in result.rchunks_exact_mut(2).zip(digest.chunks_exact(2)) {
result[0] = digest[0];
result[1] = digest[1];
}
result
}
pub fn new(header: &Header, slot_key: &[u8]) -> Result<Self, KugouError> {
let slot_key = Self::hash_key(slot_key);
let mut file_key = [0x6b; 17];
file_key[..16].copy_from_slice(&Self::hash_key(header.file_key));
Ok(Self { slot_key, file_key })
}
}
impl Decipher for DecipherV3 {
fn decrypt(&self, buffer: &mut [u8], offset: usize) {
let slot_key_stream = self.slot_key.iter().cycle().skip(offset);
let file_key_stream = self.file_key.iter().cycle().skip(offset);
let mut offset = offset as u32;
let key_stream = slot_key_stream.zip(file_key_stream);
for (datum, (&slot_key, &file_key)) in buffer.iter_mut().zip(key_stream) {
let mut temp = *datum;
temp ^= file_key;
temp ^= temp.wrapping_shl(4);
temp ^= slot_key;
temp ^= offset.to_ne_bytes().iter().fold(0, |acc, &x| acc ^ x);
*datum = temp;
offset = offset.wrapping_add(1);
}
}
}