msg_tool\scripts\kirikiri\archive\xp3\crypt/
nvl.rs1use super::*;
2
3#[derive(Debug)]
4pub struct NVLCrypt {
5 base: BaseSchema,
6 key: [u8; 8],
7}
8
9impl NVLCrypt {
10 pub fn new(base: BaseSchema, key: &[u8]) -> Result<Self> {
11 if key.len() != 8 {
12 anyhow::bail!("Key must be 8 bytes.");
13 }
14 Ok(Self {
15 base,
16 key: key.try_into()?
17 })
18 }
19
20 fn get_key(&self, hash: u32) -> [u8; 12] {
21 let mut key = [0; 12];
22 key[..4].copy_from_slice(&hash.to_le_bytes());
23 key[4..].copy_from_slice(&self.key);
24 key
25 }
26}
27
28impl Crypt for NVLCrypt {
29 fn hash_after_crypt(&self) -> bool {
30 self.base.hash_after_crypt
31 }
32 fn startup_tjs_not_encrypted(&self) -> bool {
33 self.base.startup_tjs_not_encrypted
34 }
35 fn obfuscated_index(&self) -> bool {
36 self.base.obfuscated_index
37 }
38 fn read_name<'a>(&self, reader: &mut Box<dyn Read + 'a>) -> Result<(String, u64)> {
39 let hash_key = reader.read_u32()?;
40 let name_hash = reader.read_u32()?;
41 let extension_hash = reader.read_u32()?;
42 Ok((format!("{:08x}.{:08x}", hash_key ^ name_hash, hash_key ^ extension_hash), 12))
43 }
44 fn decrypt_supported(&self) -> bool {
45 true
46 }
47 fn decrypt_seek_supported(&self) -> bool {
48 true
49 }
50 fn decrypt<'a>(
51 &self,
52 entry: &Xp3Entry,
53 cur_seg: &Segment,
54 stream: Box<dyn Read + Send + Sync + 'a>,
55 ) -> Result<Box<dyn ReadDebug + Send + Sync + 'a>> {
56 Ok(Box::new(NVLCryptReader::new(
57 stream,
58 cur_seg,
59 self.get_key(entry.file_hash),
60 )))
61 }
62 fn decrypt_with_seek<'a>(
63 &self,
64 entry: &Xp3Entry,
65 cur_seg: &Segment,
66 stream: Box<dyn ReadSeek + Send + Sync + 'a>,
67 ) -> Result<Box<dyn ReadSeek + Send + Sync + 'a>> {
68 Ok(Box::new(NVLCryptReader::new(
69 stream,
70 cur_seg,
71 self.get_key(entry.file_hash),
72 )))
73 }
74}
75
76impl<R: Read> Read for NVLCryptReader<R> {
77 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
78 let readed = self.inner.read(buf)?;
79 let mut offset = ((self.pos + self.seg_start) % 12) as usize;
80 for t in (&mut buf[..readed]).iter_mut() {
81 *t ^= self.key[offset];
82 offset = (offset + 1) % 12;
83 }
84 self.pos += readed as u64;
85 Ok(readed)
86 }
87}