rar_stream/crypto/
rar4.rs1use aes::cipher::{block_padding::NoPadding, BlockDecryptMut, KeyIvInit};
10use sha1::{Digest, Sha1};
11
12use super::CryptoError;
13
14type Aes128CbcDec = cbc::Decryptor<aes::Aes128>;
15
16#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct Rar4EncryptionInfo {
19 pub salt: [u8; 8],
21}
22
23#[derive(Clone, Debug)]
25pub struct Rar4Crypto {
26 key: [u8; 32],
28 iv: [u8; 16],
30}
31
32impl Rar4Crypto {
33 pub fn derive_key(password: &str, salt: &[u8; 8]) -> Self {
42 let seed: Vec<u8> = password
44 .encode_utf16()
45 .flat_map(|c| c.to_le_bytes())
46 .chain(salt.iter().copied())
47 .collect();
48
49 let mut hasher = Sha1::new();
50 let mut iv = [0u8; 16];
51
52 for i in 0..16 {
54 for j in 0..0x4000u32 {
55 let cnt = i * 0x4000 + j;
56 let cnt_bytes = [cnt as u8, (cnt >> 8) as u8, (cnt >> 16) as u8];
57
58 hasher.update(&seed);
59 hasher.update(cnt_bytes);
60
61 if j == 0 {
63 let temp_digest = hasher.clone().finalize();
64 iv[i as usize] = temp_digest[19];
65 }
66 }
67 }
68
69 let digest = hasher.finalize();
71 let key_be: [u8; 16] = digest[..16].try_into().unwrap();
72
73 let key16 = Self::swap_key_endianness(&key_be);
76
77 let mut key = [0u8; 32];
79 key[..16].copy_from_slice(&key16);
80 key[16..32].copy_from_slice(&key16);
81
82 Self { key, iv }
83 }
84
85 fn swap_key_endianness(key_be: &[u8; 16]) -> [u8; 16] {
87 let mut key_le = [0u8; 16];
88 for i in 0..4 {
89 key_le[i * 4] = key_be[i * 4 + 3];
91 key_le[i * 4 + 1] = key_be[i * 4 + 2];
92 key_le[i * 4 + 2] = key_be[i * 4 + 1];
93 key_le[i * 4 + 3] = key_be[i * 4];
94 }
95 key_le
96 }
97
98 pub fn decrypt(&self, data: &mut [u8]) -> Result<(), CryptoError> {
100 if data.is_empty() {
101 return Ok(());
102 }
103
104 if data.len() % 16 != 0 {
106 return Err(CryptoError::DecryptionFailed);
107 }
108
109 let decryptor = Aes128CbcDec::new_from_slices(&self.key[..16], &self.iv)
111 .map_err(|_| CryptoError::DecryptionFailed)?;
112
113 decryptor
114 .decrypt_padded_mut::<NoPadding>(data)
115 .map_err(|_| CryptoError::DecryptionFailed)?;
116
117 Ok(())
118 }
119
120 pub fn decrypt_to_vec(&self, data: &[u8]) -> Result<Vec<u8>, CryptoError> {
122 let mut decrypted = data.to_vec();
123 self.decrypt(&mut decrypted)?;
124 Ok(decrypted)
125 }
126
127 pub fn iv(&self) -> &[u8; 16] {
129 &self.iv
130 }
131
132 pub fn key(&self) -> &[u8; 32] {
134 &self.key
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141
142 #[test]
143 fn test_derive_key() {
144 let salt = [0x72, 0x8b, 0xe5, 0x8c, 0x22, 0x7f, 0x8d, 0xb4];
146 let crypto = Rar4Crypto::derive_key("hello", &salt);
147
148 assert_eq!(crypto.iv.len(), 16);
150 assert_eq!(crypto.key.len(), 32);
151
152 let crypto2 = Rar4Crypto::derive_key("hello", &salt);
154 assert_eq!(crypto.key, crypto2.key);
155 assert_eq!(crypto.iv, crypto2.iv);
156 }
157
158 #[test]
159 fn test_different_passwords_different_keys() {
160 let salt = [0x72, 0x8b, 0xe5, 0x8c, 0x22, 0x7f, 0x8d, 0xb4];
161 let crypto1 = Rar4Crypto::derive_key("hello", &salt);
162 let crypto2 = Rar4Crypto::derive_key("world", &salt);
163
164 assert_ne!(crypto1.key, crypto2.key);
165 assert_ne!(crypto1.iv, crypto2.iv);
166 }
167
168 #[test]
169 fn test_different_salts_different_keys() {
170 let salt1 = [0x72, 0x8b, 0xe5, 0x8c, 0x22, 0x7f, 0x8d, 0xb4];
171 let salt2 = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];
172 let crypto1 = Rar4Crypto::derive_key("hello", &salt1);
173 let crypto2 = Rar4Crypto::derive_key("hello", &salt2);
174
175 assert_ne!(crypto1.key, crypto2.key);
176 assert_ne!(crypto1.iv, crypto2.iv);
177 }
178}