1use rand::prelude::*;
2use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut,KeyInit, generic_array::GenericArray,};
3
4use aes::Aes128;
5use ccm::{
6 aead::AeadMutInPlace,
7 consts::{U8, U16},
8 Ccm, Nonce,
9};
10
11use crate::errors::ClientError;
12
13type Aes128Ccm = Ccm<Aes128, U16, U8>;
14
15type Aes128EcbEnc = ecb::Encryptor<aes::Aes128>;
16type Aes128EcbDec = ecb::Decryptor<aes::Aes128>;
17
18pub struct DataDecrypt;
19
20impl DataDecrypt {
21 pub fn decrypt(enc_data: DataEncrypt, master_key: &[u8]) -> Result<Vec<u8>, ClientError>{
22 let mut enc_key = enc_data.enc_key.clone();
23 let data_key = if let Ok(dk) = Aes128EcbDec::new(&GenericArray::clone_from_slice(&master_key))
24 .decrypt_padded_vec_mut::<Pkcs7>(&mut enc_key) {
25 dk
26 } else {
27 return Err(ClientError::FailureToDecrypt);
28 };
29
30 let (data_key, nonce) = deobfuscate_file_key(&data_key, &enc_data.condensed_mac);
31
32 let condensed_mac = enc_data.condensed_mac.clone();
33 let enc_data = enc_data.enc_data.clone();
34
35 let mut cipher = Aes128Ccm::new(&GenericArray::clone_from_slice(&data_key));
36
37 let chunks = enc_data.chunks(16);
38 let mut res = Vec::new();
39
40 let nonce = Nonce::from_slice(&nonce);
41
42 let mut condensed_mac = GenericArray::clone_from_slice(&condensed_mac);
43
44 for blk in chunks {
45 Aes128EcbDec::new(&GenericArray::from_slice(master_key))
46 .decrypt_block_mut(&mut condensed_mac);
47
48 let mut buf: Vec<u8> = Vec::new().into();
49 if let Err(_) = cipher.decrypt_in_place_detached(nonce, blk , &mut buf, &condensed_mac) {
50 return Err(ClientError::FailureToDecryptData);
51 };
52
53 res.push(blk.to_vec());
54 }
55
56 Ok(res.into_iter().flatten().collect())
57 }
58}
59
60#[derive(Debug, Clone)]
61pub struct DataEncrypt{
62 pub enc_data: Vec<u8>,
63 pub enc_key: Vec<u8>,
64 pub condensed_mac: Vec<u8>,
65}
66
67impl DataEncrypt {
68 pub fn new(data: &[u8], master_key: &[u8; 16]) -> Result<Self, ClientError> {
69 let mut rng = rand::thread_rng();
70
71 let mut data_key = [0u8;16];
72 rng.fill_bytes(&mut data_key);
73
74 let mut nonce = [0u8;8];
75 rng.fill_bytes(&mut nonce);
76 let nonce = Nonce::from_slice(&nonce);
77
78 let mut cipher = Aes128Ccm::new(&data_key.into());
79
80 let chunks = data.chunks(16);
81 let mut ct = Vec::new();
82 let mut mac_tags = Vec::new();
83
84 for blk in chunks {
85 let mut buf: Vec<u8> = Vec::new().into();
86 let mac = if let Ok(m) = cipher.encrypt_in_place_detached(nonce, blk , &mut buf) { m }
87 else { return Err(ClientError::FailureToEncryptData) };
88
89 ct.push(blk.to_vec());
90 mac_tags.push(mac.to_vec());
91 }
92
93 let enc_data = ct.into_iter().flatten().collect();
94
95 let mut condensed_mac = GenericArray::clone_from_slice(&[0u8; 16]);
96
97 for tag in mac_tags {
98 assert_eq!(condensed_mac.len(), tag.len(), "Slices must have the same length");
99 for (x, y) in condensed_mac.iter_mut().zip(tag.iter()) {
100 *x ^= y;
101 }
102
103 Aes128EcbEnc::new(&GenericArray::from_slice(master_key))
104 .encrypt_block_mut(&mut condensed_mac);
105 }
106
107
108 let iv: [u8; 8] = nonce.clone().into();
109 let mut obs_data_key = obfuscate_file_key(data_key, iv, condensed_mac.as_slice());
110
111 let enc_key = Aes128EcbEnc::new(&GenericArray::from_slice(master_key))
112 .encrypt_padded_vec_mut::<Pkcs7>(&mut obs_data_key);
113
114 Ok(Self{
115 enc_data,
116 enc_key,
117 condensed_mac: condensed_mac.to_vec(),
118 })
119 }
120}
121
122fn xor_slices(a: &[u8], b: &[u8]) -> Vec<u8> {
123 let mut v = Vec::new();
124 for (x, y) in a.iter().zip(b.iter()) {
125 v.push(x ^ y);
126 }
127 v
128}
129
130fn obfuscate_file_key(
131 file_key: [u8; 16],
132 iv: [u8; 8],
133 condensed_mac: &[u8],
134) -> Vec<u8> {
135 let file_key_chunks: Vec<&[u8]> = file_key.chunks(4).into_iter().collect();
136 let iv_chunks: Vec<&[u8]> = iv.chunks(4).into_iter().collect();
137 let condensed_mac_chunks: Vec<&[u8]> = condensed_mac.chunks(4).into_iter().collect();
138
139 let xcm0 = xor_slices(condensed_mac_chunks[0], condensed_mac_chunks[1]);
140 let xcm1 = xor_slices(condensed_mac_chunks[2], condensed_mac_chunks[3]);
141 let k = vec![
142 xor_slices(file_key_chunks[0], iv_chunks[0]),
143 xor_slices(file_key_chunks[1], iv_chunks[1]),
144 xor_slices(file_key_chunks[2], xcm0.as_slice()),
145 xor_slices(file_key_chunks[3], xcm1.as_slice()),
146 iv_chunks[0].to_vec(),
147 iv_chunks[1].to_vec(),
148 xcm0,
149 xcm1,
150 ];
151
152 k.into_iter().flatten().collect()
153}
154
155fn deobfuscate_file_key(
156 obfuscated_key: &[u8],
157 condensed_mac: &[u8],
158) -> (Vec<u8>, Vec<u8>) {
159 let obfuscated_key_chunks: Vec<&[u8]> = obfuscated_key.chunks(4).into_iter().collect();
160 let condensed_mac_chunks: Vec<&[u8]> = condensed_mac.chunks(4).into_iter().collect();
161
162 let xcm0 = xor_slices(condensed_mac_chunks[0], condensed_mac_chunks[1]);
163 let xcm1 = xor_slices(condensed_mac_chunks[2], condensed_mac_chunks[3]);
164
165 let iv = vec![obfuscated_key_chunks[4].to_vec(), obfuscated_key_chunks[5].to_vec()];
166
167 let fk = vec![
168 xor_slices(&iv[0], obfuscated_key_chunks[0]),
169 xor_slices(&iv[1], obfuscated_key_chunks[1]),
170 xor_slices(&xcm0, obfuscated_key_chunks[2]),
171 xor_slices(&xcm1, obfuscated_key_chunks[3]),
172 ];
173
174 (fk.into_iter().flatten().collect(), iv.into_iter().flatten().collect())
175}
176