steamkit/util/
crypto_helper.rs1use aes::cipher::block_padding::Pkcs7;
4use aes::cipher::{BlockDecryptMut, KeyInit, KeyIvInit};
5use aes::cipher::generic_array::GenericArray;
6use cbc::Decryptor as CbcDecryptor;
7use ecb::Decryptor as EcbDecryptor;
8
9use crate::error::SteamError;
10
11const BLOCK_SIZE: usize = 16;
13
14const KEY_SIZE: usize = 32;
16
17pub fn symmetric_decrypt(input: &[u8], key: &[u8]) -> Result<Vec<u8>, SteamError> {
20 CryptoHelper::symmetric_decrypt(input, key)
21}
22
23#[derive(Debug)]
25pub struct CryptoHelper;
26
27impl CryptoHelper {
28 pub fn symmetric_decrypt(input: &[u8], key: &[u8]) -> Result<Vec<u8>, SteamError> {
34 if key.len() != KEY_SIZE {
35 crate::util::debug_log::DebugLog::assert(
36 false,
37 "CryptoHelper",
38 "SymmetricDecrypt used with non 32 byte key!",
39 );
40
41 return Err(SteamError::InvalidArgument(format!(
42 "SymmetricDecrypt used with non {KEY_SIZE} byte key (was {} bytes)!",
43 key.len()
44 )));
45 }
46
47 if input.len() < BLOCK_SIZE {
48 return Err(SteamError::Crypto(format!(
49 "SymmetricDecrypt input is too short to contain the IV (was {} bytes).",
50 input.len()
51 )));
52 }
53
54 let mut iv = [0u8; BLOCK_SIZE];
56 {
57 let mut decryptor = EcbDecryptor::<aes::Aes256>::new_from_slice(key)
58 .map_err(|_| SteamError::Crypto("Invalid AES-256 key.".to_string()))?;
59
60 let mut block = GenericArray::clone_from_slice(&input[..BLOCK_SIZE]);
61 decryptor.decrypt_block_mut(&mut block);
62 iv.copy_from_slice(block.as_slice());
63 }
64
65 let ciphertext = &input[BLOCK_SIZE..];
67
68 if ciphertext.is_empty() || ciphertext.len() % BLOCK_SIZE != 0 {
69 return Err(SteamError::Crypto(format!(
70 "SymmetricDecrypt input has an invalid length (was {} bytes).",
71 input.len()
72 )));
73 }
74
75 let mut buffer = vec![0u8; ciphertext.len()];
76 buffer.copy_from_slice(ciphertext);
77
78 let decryptor = CbcDecryptor::<aes::Aes256>::new_from_slices(key, &iv)
79 .map_err(|_| SteamError::Crypto("Invalid AES-256 key or IV.".to_string()))?;
80
81 let plaintext = decryptor
82 .decrypt_padded_mut::<Pkcs7>(&mut buffer)
83 .map_err(|_| SteamError::Crypto("Failed to decrypt the payload.".to_string()))?;
84
85 Ok(plaintext.to_vec())
86 }
87}
88