chore: implement decryption of SDGB
This commit is contained in:
@@ -17,3 +17,6 @@ nyquest = { version = "0.2.0", features = ["async", "json"] }
|
||||
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
serde_json = "1.0.141"
|
||||
flate2 = "1.1.2"
|
||||
cbc = "0.1.2"
|
||||
aes = "0.8.4"
|
||||
|
||||
4
sdgb-api/src/title/encryption/constants/mod.rs
Normal file
4
sdgb-api/src/title/encryption/constants/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
pub const SDGB_1_50_KEY: &[u8; 32] = b"a>32bVP7v<63BVLkY[xM>daZ1s9MBP<R";
|
||||
pub const SDGB_1_50_IV: &[u8; 16] = b"d6xHIKq]1J]Dt^ue";
|
||||
pub const SDGB_1_40_KEY: &[u8; 32] = b"n7bx6:@Fg_:2;5E89Phy7AyIcpxEQ:R@";
|
||||
pub const SDGB_1_40_IV: &[u8; 16] = b";;KjR1C3hgB1ovXa";
|
||||
73
sdgb-api/src/title/encryption/mod.rs
Normal file
73
sdgb-api/src/title/encryption/mod.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
use std::io::Read;
|
||||
|
||||
use aes::cipher::{BlockDecryptMut, KeyIvInit, block_padding::Pkcs7};
|
||||
use digest::generic_array::GenericArray;
|
||||
use flate2::read::ZlibDecoder;
|
||||
|
||||
use crate::title::error::ApiError;
|
||||
|
||||
pub mod constants;
|
||||
|
||||
// type Aes256CbcEnc = cbc::Encryptor<aes::Aes256>;
|
||||
type Aes256CbcDec = cbc::Decryptor<aes::Aes256>;
|
||||
|
||||
pub fn decompress(data: impl AsRef<[u8]>) -> Vec<u8> {
|
||||
let mut buf = Vec::with_capacity(data.as_ref().len() * 2);
|
||||
let mut decode = ZlibDecoder::new(data.as_ref());
|
||||
_ = decode.read_to_end(&mut buf);
|
||||
buf
|
||||
}
|
||||
|
||||
pub fn decrypt<'ct>(
|
||||
data: &'ct mut impl AsMut<[u8]>,
|
||||
key: &[u8; 32],
|
||||
iv: &[u8; 16],
|
||||
) -> Result<&'ct [u8], ApiError> {
|
||||
let key = GenericArray::from_slice(key);
|
||||
let iv = GenericArray::from_slice(iv);
|
||||
let decryptor = Aes256CbcDec::new(key, iv);
|
||||
let result = decryptor.decrypt_padded_mut::<Pkcs7>(data.as_mut())?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod _tests {
|
||||
|
||||
use crate::title::encryption::{constants::*, *};
|
||||
|
||||
#[test]
|
||||
fn test_sdgb_140_dec() {
|
||||
let data = [
|
||||
120_u8, 156, 171, 77, 91, 233, 184, 108, 2, 71, 125, 142, 118, 135, 112, 181, 85, 217,
|
||||
239, 243, 159, 153, 248, 98, 159, 185, 63, 43, 173, 106, 221, 115, 104, 105, 221, 107,
|
||||
0, 241, 176, 16, 37,
|
||||
];
|
||||
let mut decompressed = decompress(data);
|
||||
let data =
|
||||
decrypt(&mut decompressed, SDGB_1_40_KEY, SDGB_1_40_IV).expect("decryption failed!");
|
||||
assert_eq!(&data, br#"{"result":"Pong"}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sdgb_150_dec() {
|
||||
let mut data = [
|
||||
161, 166, 3, 157, 202, 233, 151, 73, 40, 113, 186, 162, 177, 46, 118, 113, 98, 231, 67,
|
||||
185, 246, 180, 109, 253, 1, 152, 0, 31, 81, 211, 28, 137, 95, 12, 110, 105, 181, 246,
|
||||
177, 1, 45, 59, 182, 113, 56, 97, 56, 100, 34, 168, 27, 51, 228, 77, 192, 194, 248, 45,
|
||||
118, 80, 21, 159, 37, 248, 54, 85, 94, 61, 48, 59, 117, 163, 161, 165, 206, 36, 23, 71,
|
||||
73, 231, 214, 81, 82, 117, 115, 32, 122, 8, 161, 213, 252, 125, 35, 131, 144, 147, 74,
|
||||
27, 138, 26, 133, 240, 73, 197, 25, 173, 213, 237, 216, 76, 101, 210, 202, 172, 216,
|
||||
91, 83, 87, 243, 79, 143, 42, 149, 130, 210, 13, 63, 98, 198, 165, 122, 58, 254, 39,
|
||||
150, 71, 155, 231, 55, 142, 5, 102, 253, 148, 191, 9, 212, 188, 69, 236, 60, 152, 13,
|
||||
40, 111, 219, 162, 160, 34, 150, 211, 85, 190, 176, 137, 60, 25, 228, 218, 163, 240,
|
||||
143, 44, 238, 77, 92, 12, 166, 209, 238, 100, 92, 98, 142, 10, 104, 213, 12, 89, 236,
|
||||
114, 212, 222, 0, 237, 1, 208, 216, 114, 114, 71, 135, 21, 213, 61, 6, 162, 155, 119,
|
||||
143, 70, 83, 136, 136, 136, 251, 94, 137, 244, 26, 125, 15, 132, 207, 60, 57, 105, 78,
|
||||
177, 84, 85, 152, 183, 77, 67, 163, 61, 165, 144, 125, 255, 89, 108, 58, 137, 142, 9,
|
||||
8, 54, 228, 34, 55, 124, 158, 83, 36,
|
||||
];
|
||||
let decrypted = decrypt(&mut data, SDGB_1_50_KEY, SDGB_1_50_IV).expect("decryption failed");
|
||||
let decompressed = decompress(decrypted);
|
||||
assert_eq!(decompressed, r#"{"userId":10103750,"userName":"舞萌","isLogin":false,"lastGameId":null,"lastRomVersion":"1.01.00","lastDataVersion":"1.05.03","lastLoginDate":"1970-01-01 00:00:00","lastPlayDate":"1970-01-01 00:00:00","playerRating":1024,"nameplateId":0,"iconId":11,"trophyId":0,"isNetMember":1,"isInherit":false,"totalAwake":5,"dispRate":0,"dailyBonusDate":"1970-01-01 09:00:00","headPhoneVolume":null,"banState":0}"#.as_bytes())
|
||||
}
|
||||
}
|
||||
14
sdgb-api/src/title/error/mod.rs
Normal file
14
sdgb-api/src/title/error/mod.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
use aes::cipher::block_padding::UnpadError;
|
||||
use snafu::Snafu;
|
||||
|
||||
#[derive(Debug, Snafu)]
|
||||
pub enum ApiError {
|
||||
#[snafu(display("unpad data: {error}"))]
|
||||
UnpadError { error: UnpadError },
|
||||
}
|
||||
|
||||
impl From<UnpadError> for ApiError {
|
||||
fn from(error: UnpadError) -> Self {
|
||||
Self::UnpadError { error }
|
||||
}
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
|
||||
pub mod encryption;
|
||||
mod error;
|
||||
|
||||
Reference in New Issue
Block a user