2024-09-05 23:52:13 +00:00
|
|
|
use crate::v2_map::QMC2Map;
|
|
|
|
use crate::v2_rc4::cipher::QMC2RC4;
|
|
|
|
use anyhow::Result;
|
2024-09-04 00:12:20 +00:00
|
|
|
use thiserror::Error;
|
|
|
|
|
2024-09-05 23:52:13 +00:00
|
|
|
pub mod ekey;
|
2024-09-05 22:37:55 +00:00
|
|
|
pub mod footer;
|
2024-09-04 00:12:20 +00:00
|
|
|
pub mod v1;
|
2024-09-04 18:13:03 +00:00
|
|
|
pub mod v2_map;
|
2024-09-04 00:12:20 +00:00
|
|
|
pub mod v2_rc4;
|
|
|
|
|
|
|
|
#[derive(Error, Debug)]
|
2024-09-04 18:13:03 +00:00
|
|
|
pub enum QmcCryptoError {
|
|
|
|
#[error("QMC V2/Map Cipher: Key is empty")]
|
|
|
|
QMCV2MapKeyEmpty,
|
|
|
|
}
|
2024-09-04 21:24:34 +00:00
|
|
|
|
2024-09-05 23:52:13 +00:00
|
|
|
pub enum QMCv2Cipher {
|
|
|
|
MapL(QMC2Map),
|
|
|
|
RC4(QMC2RC4),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl QMCv2Cipher {
|
|
|
|
pub fn new<T>(key: T) -> Result<Self>
|
|
|
|
where
|
|
|
|
T: AsRef<[u8]>,
|
|
|
|
{
|
|
|
|
let key = key.as_ref();
|
|
|
|
let cipher = match key.len() {
|
|
|
|
0 => Err(QmcCryptoError::QMCV2MapKeyEmpty)?,
|
|
|
|
..=300 => QMCv2Cipher::MapL(QMC2Map::new(key)?),
|
|
|
|
_ => QMCv2Cipher::RC4(QMC2RC4::new(key)),
|
|
|
|
};
|
|
|
|
Ok(cipher)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn decrypt<T>(&self, data: &mut T, offset: usize)
|
|
|
|
where
|
|
|
|
T: AsMut<[u8]> + ?Sized,
|
|
|
|
{
|
|
|
|
match self {
|
|
|
|
QMCv2Cipher::MapL(cipher) => cipher.decrypt(data, offset),
|
|
|
|
QMCv2Cipher::RC4(cipher) => cipher.decrypt(data, offset),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-04 21:24:34 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
pub fn generate_key(len: usize) -> Vec<u8> {
|
|
|
|
(1..=len).map(|i| i as u8).collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
pub fn generate_key_128() -> [u8; 128] {
|
|
|
|
generate_key(128)
|
|
|
|
.try_into()
|
|
|
|
.expect("failed to make test key")
|
|
|
|
}
|
|
|
|
}
|