From aca72df20f9518689fe2300193b85c4e25a6a83b Mon Sep 17 00:00:00 2001 From: lifegpc Date: Thu, 7 May 2026 22:04:53 +0800 Subject: [PATCH] Fix previous filter key not updated bug --- msg_tool_xp3data/crypt.json | 30 ++++++++++++++++++- msg_tool_xp3data/cx_cb/mashiro.bin | Bin 0 -> 4096 bytes src/scripts/kirikiri/archive/xp3/crypt/cx.rs | 23 ++++++++++---- 3 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 msg_tool_xp3data/cx_cb/mashiro.bin diff --git a/msg_tool_xp3data/crypt.json b/msg_tool_xp3data/crypt.json index 97e8d4e..d8c3c6e 100644 --- a/msg_tool_xp3data/crypt.json +++ b/msg_tool_xp3data/crypt.json @@ -1554,7 +1554,8 @@ }, { "Key": "kHMdDweFjeDFVTwQA10XQAPUAOfXzKp2ukygeLzGzHg=", - "Nonce": "CSBjzSXQNTioPhDp710WCQ==" + "Nonce": "CSBjzSXQNTioPhDp710WCQ==", + "FilterKey": 13089994567570788352 } ], "FilterKey": 8093658935271803197, @@ -1668,6 +1669,33 @@ "$type": "HashCrypt", "Title": "愛娘は、マゾ性隷 ~娘だからって遠慮しないでね?~" }, + "Mashiro-iro Symphony": { + "$type": "HxCrypt", + "Mask": 284, + "Offset": 389, + "PrologOrder": "AQIA", + "OddBranchOrder": "BQABBAID", + "EvenBranchOrder": "AQYFAAcCBAM=", + "IndexKey1": { + "Key": "pWVnGBsl5MFeR3EH2yJwHx2ZvHkWDxQhIhODqqdxMMo=", + "Nonce": "JClYlfgFkP8dN6oa3iOrAw==" + }, + "IndexKey2": [ + { + "Key": "q0lPvHOK7Qa4OM615uOvyTInTJf8aYpS/jcpM1uNnuo=", + "Nonce": "1KoS7cnIicdp1hZ0bjlduw==" + }, + { + "Key": "kUUY3z8D94i85yssB5xRBZmSiKRNABPPAl88Qtf7Ix0=", + "Nonce": "+Hg91OLLC9E4ET7YbHMHsA==", + "FilterKey": 14361241883570560968 + } + ], + "FilterKey": 1449527129867772322, + "RandomType": 1, + "ControlBlockName": "mashiro.bin", + "Title": "Mashiro-iro Symphony -Love is pure white- Remake for FHD | Mashiro-iro Symphony: Sana Edition | ましろ色シンフォニー -Love is pure white- Remake for FHD | 纯白交响曲 -Love is pure white- HD Remake | 純白交響曲 -Love is pure white- HD Remake | ましろ色シンフォニー SANA EDITION | 纯白交响曲 SANA EDITION | 純白交響曲 SANA EDITION" + }, "Me ga Sametara Seieki ga 100 Bai...": { "$type": "DieselmineCrypt", "Title": "目が覚めたら精液が100倍溜まる身体になってた→大量注入!" diff --git a/msg_tool_xp3data/cx_cb/mashiro.bin b/msg_tool_xp3data/cx_cb/mashiro.bin new file mode 100644 index 0000000000000000000000000000000000000000..43ddb720c86723aff6291d567f347386e3afc8f9 GIT binary patch literal 4096 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 literal 0 HcmV?d00001 diff --git a/src/scripts/kirikiri/archive/xp3/crypt/cx.rs b/src/scripts/kirikiri/archive/xp3/crypt/cx.rs index bf2bcf2..b50e2cc 100644 --- a/src/scripts/kirikiri/archive/xp3/crypt/cx.rs +++ b/src/scripts/kirikiri/archive/xp3/crypt/cx.rs @@ -1,4 +1,5 @@ use super::*; +use crate::ext::atomic::AtomicQuick; use crate::ext::mutex::MutexExt; use crate::utils::files::*; use crate::utils::struct_pack::*; @@ -8,6 +9,7 @@ use serde::{Deserializer, de}; use std::collections::HashSet; use std::ops::{Deref, DerefMut, Index}; use std::path::PathBuf; +use std::sync::atomic::AtomicU64; use std::sync::{Mutex, Weak}; const S_CTL_BLOCK_SIGNATURE: &[u8] = b" Encryption control block"; @@ -2032,7 +2034,7 @@ pub struct HxCrypt { base: CxEncryption, key1: IndexKey, key2: IndexKeys, - filter_key: u64, + filter_key: AtomicU64, file_mapping: HashMap, path_mapping: HashMap, info_map: Mutex>, @@ -2042,6 +2044,7 @@ pub struct HxCrypt { pub struct IndexKey { key: [u8; 32], nonce: [u8; 16], + filter_key: Option, } impl std::fmt::Debug for IndexKey { @@ -2049,6 +2052,7 @@ impl std::fmt::Debug for IndexKey { f.debug_struct("IndexKey") .field("key", &hex::encode(&self.key)) .field("nonce", &hex::encode(&self.nonce)) + .field("filter_key", &self.filter_key) .finish() } } @@ -2058,6 +2062,8 @@ impl std::fmt::Debug for IndexKey { struct IndexKeyTmp { key: String, nonce: String, + #[serde(default)] + filter_key: Option, } impl<'de> Deserialize<'de> for IndexKey { @@ -2081,7 +2087,11 @@ impl<'de> Deserialize<'de> for IndexKey { bytes.len() )) })?; - Ok(Self { key, nonce }) + Ok(Self { + key, + nonce, + filter_key: s.filter_key, + }) } } @@ -2168,7 +2178,7 @@ impl HxCrypt { )?, key1: index_key1.clone(), key2: index_key2.clone(), - filter_key, + filter_key: AtomicU64::new(filter_key), file_mapping: file_map, path_mapping: path_map, info_map: Mutex::new(HashMap::new()), @@ -2262,6 +2272,9 @@ impl HxCrypt { 1 => &self.key1, _ => anyhow::bail!("Unknown hxv4 flags: {}", flags), }; + if let Some(filter_key) = &key.filter_key { + self.filter_key.qsave(*filter_key); + } let mut nonce = [0; 8]; nonce.copy_from_slice(&key.nonce[..8]); let mut crypt = ChaCha20Legacy::new((&key.key).into(), (&nonce).into()); @@ -2494,7 +2507,7 @@ impl Crypt for HxCrypt { .ok_or_else(|| anyhow::anyhow!("extra info is not hx entry."))?; let mut entry_key = info.key; if (info.id & 0x100000000) == 0 { - entry_key ^= self.filter_key; + entry_key ^= self.filter_key.qload(); } let header_key = !entry_key; let key = self.create_filter_key(entry_key, header_key)?; @@ -2521,7 +2534,7 @@ impl Crypt for HxCrypt { .ok_or_else(|| anyhow::anyhow!("extra info is not hx entry."))?; let mut entry_key = info.key; if (info.id & 0x100000000) == 0 { - entry_key ^= self.filter_key; + entry_key ^= self.filter_key.qload(); } let header_key = !entry_key; let key = self.create_filter_key(entry_key, header_key)?;