Skip to main content

mega_security_rs/
data.rs

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