use base64::{engine::general_purpose, Engine as _}; use dmzj_proto::comic; use protobuf::Message; use rsa::{pkcs8::DecodePrivateKey, Pkcs1v15Encrypt, RsaPrivateKey}; const PRIVATE_KEY_STR: &'static str = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAK8nNR1lTnIfIes6oRWJNj3mB6OssDGx0uGMpgpbVCpf6+VwnuI2stmhZNoQcM417Iz7WqlPzbUmu9R4dEKmLGEEqOhOdVaeh9Xk2IPPjqIu5TbkLZRxkY3dJM1htbz57d/roesJLkZXqssfG5EJauNc+RcABTfLb4IiFjSMlTsnAgMBAAECgYEAiz/pi2hKOJKlvcTL4jpHJGjn8+lL3wZX+LeAHkXDoTjHa47g0knYYQteCbv+YwMeAGupBWiLy5RyyhXFoGNKbbnvftMYK56hH+iqxjtDLnjSDKWnhcB7089sNKaEM9Ilil6uxWMrMMBH9v2PLdYsqMBHqPutKu/SigeGPeiB7VECQQDizVlNv67go99QAIv2n/ga4e0wLizVuaNBXE88AdOnaZ0LOTeniVEqvPtgUk63zbjl0P/pzQzyjitwe6HoCAIpAkEAxbOtnCm1uKEp5HsNaXEJTwE7WQf7PrLD4+BpGtNKkgja6f6F4ld4QZ2TQ6qvsCizSGJrjOpNdjVGJ7bgYMcczwJBALvJWPLmDi7ToFfGTB0EsNHZVKE66kZ/8Stx+ezueke4S556XplqOflQBjbnj2PigwBN/0afT+QZUOBOjWzoDJkCQClzo+oDQMvGVs9GEajS/32mJ3hiWQZrWvEzgzYRqSf3XVcEe7PaXSd8z3y3lACeeACsShqQoc8wGlaHXIJOHTcCQQCZw5127ZGs8ZDTSrogrH73Kw/HvX55wGAeirKYcv28eauveCG7iyFR0PFB/P/EDZnyb+ifvyEFlucPUI0+Y87F"; const MAX_DECRYPT_BLOCK: usize = 128; fn get_private_key() -> RsaPrivateKey { let key_bytes = general_purpose::STANDARD.decode(PRIVATE_KEY_STR).unwrap(); let key = RsaPrivateKey::from_pkcs8_der(&key_bytes).unwrap(); key } fn decrypt(encrypted: String, key: RsaPrivateKey) -> Vec { let mut result = vec![]; let encrypted_data = general_purpose::STANDARD.decode(encrypted).unwrap(); for chunk in encrypted_data.chunks(MAX_DECRYPT_BLOCK) { let dec = key.decrypt(Pkcs1v15Encrypt, chunk).unwrap(); result.extend_from_slice(&dec); } result } #[tokio::main] async fn main() { let res = reqwest::get("https://nnv4api.dmzj.com/comic/chapter/71857/146271") .await .unwrap(); let text = res.text().await.unwrap(); let cipher = get_private_key(); let b = decrypt(text, cipher); let r = comic::ComicChapterResponse::parse_from_bytes(&b).unwrap(); println!("{:?}", r.data); }