Add StripeCrypt (untested)

This commit is contained in:
2026-04-10 13:52:00 +08:00
parent 5b817b1899
commit bf11009b1f
2 changed files with 68 additions and 35 deletions

View File

@@ -1974,6 +1974,11 @@
"$type": "HashCrypt", "$type": "HashCrypt",
"Title": "双性の姫君 ~ふたなり姉妹と魔王の求愛~" "Title": "双性の姫君 ~ふたなり姉妹と魔王の求愛~"
}, },
"Specialite!": {
"$type": "StripeCrypt",
"Key": 175,
"Title": "すぺしゃりて!"
},
"Suiheisen made Nan Mile?": { "Suiheisen made Nan Mile?": {
"$type": "CxEncryption", "$type": "CxEncryption",
"Mask": 610, "Mask": 610,

View File

@@ -176,6 +176,10 @@ enum CryptType {
seed: u32, seed: u32,
}, },
HaikuoCrypt, HaikuoCrypt,
#[serde(rename_all = "PascalCase")]
StripeCrypt {
key: u8,
},
} }
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
@@ -276,6 +280,7 @@ impl Schema {
CryptType::HibikiCrypt => Box::new(HibikiCrypt::new(self.base.clone())), CryptType::HibikiCrypt => Box::new(HibikiCrypt::new(self.base.clone())),
CryptType::AkabeiCrypt { seed } => Box::new(AkabeiCrypt::new(self.base.clone(), *seed)), CryptType::AkabeiCrypt { seed } => Box::new(AkabeiCrypt::new(self.base.clone(), *seed)),
CryptType::HaikuoCrypt => Box::new(HaikuoCrypt::new(self.base.clone())), CryptType::HaikuoCrypt => Box::new(HaikuoCrypt::new(self.base.clone())),
CryptType::StripeCrypt { key } => Box::new(StripeCrypt::new(self.base.clone(), *key)),
}) })
} }
} }
@@ -604,45 +609,54 @@ impl<R: Read> Read for HashCryptReader<R> {
} }
} }
#[derive(Debug)] macro_rules! seek_crypt_key_base_impl {
pub struct XorCrypt { ($crypt:ident, $reader:ident, $typ:ty) => {
base: BaseSchema, #[derive(Debug)]
key: u8, pub struct $crypt {
base: BaseSchema,
key: $typ,
}
impl $crypt {
pub fn new(base: BaseSchema, key: $typ) -> Self {
Self { base, key }
}
}
impl Crypt for $crypt {
base_schema_impl!();
fn decrypt_supported(&self) -> bool {
true
}
fn decrypt_seek_supported(&self) -> bool {
true
}
fn decrypt<'a>(
&self,
_entry: &Xp3Entry,
cur_seg: &Segment,
stream: Box<dyn Read + 'a>,
) -> Result<Box<dyn ReadDebug + 'a>> {
Ok(Box::new($reader::new(stream, cur_seg, self.key)))
}
fn decrypt_with_seek<'a>(
&self,
_entry: &Xp3Entry,
cur_seg: &Segment,
stream: Box<dyn ReadSeek + 'a>,
) -> Result<Box<dyn ReadSeek + 'a>> {
Ok(Box::new($reader::new(stream, cur_seg, self.key)))
}
}
};
} }
impl XorCrypt { macro_rules! seek_crypt_key_impl {
pub fn new(base: BaseSchema, key: u8) -> Self { ($crypt:ident, $reader:ident<$t:ident>, $typ:ty) => {
Self { base, key } seek_crypt_key_base_impl!($crypt, $reader, $typ);
} seek_reader_key_impl!($reader<$t>, $typ);
};
} }
impl Crypt for XorCrypt { seek_crypt_key_impl!(XorCrypt, XorCryptReader<T>, u8);
base_schema_impl!();
fn decrypt_supported(&self) -> bool {
true
}
fn decrypt_seek_supported(&self) -> bool {
true
}
fn decrypt<'a>(
&self,
_entry: &Xp3Entry,
cur_seg: &Segment,
stream: Box<dyn Read + 'a>,
) -> Result<Box<dyn ReadDebug + 'a>> {
Ok(Box::new(XorCryptReader::new(stream, cur_seg, self.key)))
}
fn decrypt_with_seek<'a>(
&self,
_entry: &Xp3Entry,
cur_seg: &Segment,
stream: Box<dyn ReadSeek + 'a>,
) -> Result<Box<dyn ReadSeek + 'a>> {
Ok(Box::new(XorCryptReader::new(stream, cur_seg, self.key)))
}
}
seek_reader_key_impl!(XorCryptReader<T>, u8);
impl<R: Read> Read for XorCryptReader<R> { impl<R: Read> Read for XorCryptReader<R> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> { fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
@@ -1164,6 +1178,20 @@ impl<R: Read> Read for HaikuoCryptReader<R> {
} }
} }
seek_crypt_key_impl!(StripeCrypt, StripeCryptReader<T>, u8);
impl<R: Read> Read for StripeCryptReader<R> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let readed = self.inner.read(buf)?;
for t in (&mut buf[..readed]).iter_mut() {
*t ^= self.key;
w!(*t += 1);
}
self.pos += readed as u64;
Ok(readed)
}
}
#[test] #[test]
fn test_deserialize_crypt() { fn test_deserialize_crypt() {
for (key, schema) in CRYPT_SCHEMA.iter() { for (key, schema) in CRYPT_SCHEMA.iter() {