use cipher::{ BlockDecryptMut as _, BlockEncryptMut as _, BlockSizeUser as _, KeyIvInit as _, block_padding::Pkcs7, generic_array::GenericArray, }; use nyquest::{ AsyncClient, r#async::{Body, Request}, header::USER_AGENT, }; use crate::error::ApiError; const AES_IV: &[u8; 16] = b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; pub trait Delivery { const AES_KEY: &[u8; 16]; const TITLE_ID: &str; const USER_AGENT: &str; } /// only for fun pub struct SDHJ; pub struct SDGB; impl Delivery for SDHJ { const AES_KEY: &[u8; 16] = b"-a57UX4y9/h(ImAQ"; const TITLE_ID: &str = "SDHJ"; const USER_AGENT: &str = "SDHJ;Windows/Lite"; } impl Delivery for SDGB { const AES_KEY: &[u8; 16] = br#"/?jo+"L&\Cr9(=kG"#; const TITLE_ID: &str = "SDGB"; const USER_AGENT: &str = "SDGB;Windows/Lite"; } pub async fn delivery_raw( client: &AsyncClient, title_ver: impl AsRef, ) -> Result, ApiError> where D: Delivery, { let title_ver = title_ver.as_ref(); let params = format!( "title_id={}&title_ver={title_ver}&client_id=A63E01C2805", D::TITLE_ID ); let enc_data = encrypt(params, D::AES_KEY, AES_IV)?; let req = Request::post("http://at.sys-allnet.cn/net/delivery/instruction") .with_body(Body::bytes(enc_data, "application/xxx-form-urlencoded")) .with_header(USER_AGENT, D::USER_AGENT) .with_header("Pragma", "DFI"); let mut resp = client.request(req).await?.bytes().await?; let dec_len = decrypt(&mut resp, D::AES_KEY, AES_IV)?.len(); Ok(resp[16..dec_len].to_vec()) } type Aes128CbcEnc = cbc::Encryptor; type Aes128CbcDec = cbc::Decryptor; fn encrypt(data: impl AsRef<[u8]>, key: &[u8; 16], iv: &[u8; 16]) -> Result, ApiError> { let mut headed_data = vec![0u8; 16]; headed_data.extend_from_slice(data.as_ref()); let key = GenericArray::from_slice(key); let iv = GenericArray::from_slice(iv); let encryptor = Aes128CbcEnc::new(key, iv); let bs = aes::Aes128::block_size(); let pad_len = bs - headed_data.len() % bs; let mut buf = vec![0; pad_len + headed_data.len()]; buf[..headed_data.len()].copy_from_slice(&headed_data); encryptor.encrypt_padded_mut::(&mut buf, headed_data.len())?; Ok(buf) } fn decrypt<'ct>( data: &'ct mut impl AsMut<[u8]>, key: &[u8; 16], iv: &[u8; 16], ) -> Result<&'ct [u8], ApiError> { let key = GenericArray::from_slice(key); let iv = GenericArray::from_slice(iv); let decryptor = Aes128CbcDec::new(key, iv); let result = decryptor.decrypt_padded_mut::(data.as_mut())?; Ok(result) }