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
138impl Drop for Rar4Crypto {
139 fn drop(&mut self) {
140 for byte in &mut self.key {
142 unsafe { std::ptr::write_volatile(byte, 0) };
143 }
144 for byte in &mut self.iv {
145 unsafe { std::ptr::write_volatile(byte, 0) };
146 }
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153
154 #[test]
155 fn test_derive_key() {
156 let salt = [0x72, 0x8b, 0xe5, 0x8c, 0x22, 0x7f, 0x8d, 0xb4];
158 let crypto = Rar4Crypto::derive_key("hello", &salt);
159
160 assert_eq!(crypto.iv.len(), 16);
162 assert_eq!(crypto.key.len(), 32);
163
164 let crypto2 = Rar4Crypto::derive_key("hello", &salt);
166 assert_eq!(crypto.key, crypto2.key);
167 assert_eq!(crypto.iv, crypto2.iv);
168 }
169
170 #[test]
171 fn test_different_passwords_different_keys() {
172 let salt = [0x72, 0x8b, 0xe5, 0x8c, 0x22, 0x7f, 0x8d, 0xb4];
173 let crypto1 = Rar4Crypto::derive_key("hello", &salt);
174 let crypto2 = Rar4Crypto::derive_key("world", &salt);
175
176 assert_ne!(crypto1.key, crypto2.key);
177 assert_ne!(crypto1.iv, crypto2.iv);
178 }
179
180 #[test]
181 fn test_different_salts_different_keys() {
182 let salt1 = [0x72, 0x8b, 0xe5, 0x8c, 0x22, 0x7f, 0x8d, 0xb4];
183 let salt2 = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];
184 let crypto1 = Rar4Crypto::derive_key("hello", &salt1);
185 let crypto2 = Rar4Crypto::derive_key("hello", &salt2);
186
187 assert_ne!(crypto1.key, crypto2.key);
188 assert_ne!(crypto1.iv, crypto2.iv);
189 }
190}