2024-09-15 21:15:02 +00:00
|
|
|
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 })
|
|
|
|
}
|
2024-09-15 22:25:19 +00:00
|
|
|
|
|
|
|
fn offset_key(offset: usize) -> u8 {
|
|
|
|
let offset_key = (offset as u32).to_ne_bytes();
|
|
|
|
offset_key[0] ^ offset_key[1] ^ offset_key[2] ^ offset_key[3]
|
|
|
|
}
|
2024-09-15 21:15:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Decipher for DecipherV3 {
|
|
|
|
fn decrypt(&self, buffer: &mut [u8], offset: usize) {
|
2024-09-15 22:25:19 +00:00
|
|
|
for (datum, offset) in buffer.iter_mut().zip(offset..) {
|
|
|
|
let offset_key = Self::offset_key(offset);
|
|
|
|
|
|
|
|
let file_key = self.file_key[offset % self.file_key.len()];
|
|
|
|
let slot_key = self.slot_key[offset % self.slot_key.len()];
|
2024-09-15 21:20:18 +00:00
|
|
|
|
2024-09-15 21:15:02 +00:00
|
|
|
let mut temp = *datum;
|
|
|
|
temp ^= file_key;
|
2024-09-15 22:25:19 +00:00
|
|
|
temp ^= temp << 4;
|
2024-09-15 21:15:02 +00:00
|
|
|
temp ^= slot_key;
|
2024-09-15 21:20:18 +00:00
|
|
|
temp ^= offset_key;
|
2024-09-15 21:15:02 +00:00
|
|
|
*datum = temp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|