Skip to main content

magic_crypt/ciphers/
aes128.rs

1use alloc::vec::Vec;
2#[cfg(feature = "std")]
3use std::io::{Read, Write};
4
5#[cfg(feature = "std")]
6use aes::cipher::{
7    array::ArraySize,
8    typenum::{IsGreaterOrEqual, PartialDiv, True, U16},
9};
10use aes::{
11    Aes128,
12    cipher::{
13        BlockModeDecrypt, BlockModeEncrypt, Iv, Key, KeyIvInit, array::Array, block_padding::Pkcs7,
14    },
15};
16use md5::{Digest, Md5};
17
18#[cfg(feature = "std")]
19use crate::functions::{
20    decrypt_reader_to_writer as decrypt_stream, encrypt_reader_to_writer as encrypt_stream,
21    to_blocks,
22};
23use crate::{MagicCryptError, MagicCryptTrait};
24
25type Aes128CbcEnc = cbc::Encryptor<Aes128>;
26type Aes128CbcDec = cbc::Decryptor<Aes128>;
27
28#[cfg(feature = "std")]
29const BLOCK_SIZE: usize = 16;
30
31/// This struct can help you encrypt or decrypt data via AES-128 in a quick way.
32#[derive(Clone)]
33pub struct MagicCrypt128 {
34    key: Key<Aes128CbcEnc>,
35    iv:  Iv<Aes128CbcEnc>,
36}
37
38impl_cipher_secret_traits!(MagicCrypt128);
39
40impl MagicCryptTrait for MagicCrypt128 {
41    fn new<S: AsRef<[u8]>, V: AsRef<[u8]>>(key: S, iv: Option<V>) -> MagicCrypt128 {
42        let iv = match iv {
43            Some(s) => {
44                let mut hasher = Md5::new();
45                hasher.update(s.as_ref());
46
47                hasher.finalize()
48            },
49            None => Array::default(),
50        };
51
52        let key = {
53            let mut hasher = Md5::new();
54            hasher.update(key.as_ref());
55
56            hasher.finalize()
57        };
58
59        MagicCrypt128 {
60            key,
61            iv,
62        }
63    }
64
65    #[inline]
66    fn encrypt_to_bytes<T: ?Sized + AsRef<[u8]>>(&self, data: &T) -> Vec<u8> {
67        let data = data.as_ref();
68
69        let cipher = Aes128CbcEnc::new(&self.key, &self.iv);
70
71        cipher.encrypt_padded_vec::<Pkcs7>(data)
72    }
73
74    #[cfg(feature = "std")]
75    fn encrypt_reader_to_bytes(&self, reader: &mut dyn Read) -> Result<Vec<u8>, MagicCryptError> {
76        use aes::cipher::block_padding::NoPadding;
77
78        let mut final_result = Vec::new();
79
80        let data_length = reader.read_to_end(&mut final_result)?;
81
82        let padding_length = BLOCK_SIZE - (data_length % BLOCK_SIZE);
83        let final_length = data_length + padding_length;
84
85        // PKCS7 padding requires that the padding bytes be equal to the number of padding bytes added.
86        let padding_byte = padding_length as u8;
87
88        final_result.resize(final_length, padding_byte);
89
90        let cipher = Aes128CbcEnc::new(&self.key, &self.iv);
91
92        cipher.encrypt_padded::<NoPadding>(&mut final_result, final_length).unwrap();
93
94        Ok(final_result)
95    }
96
97    #[cfg(feature = "std")]
98    fn encrypt_reader_to_writer2<
99        N: ArraySize + PartialDiv<U16> + IsGreaterOrEqual<U16, Output = True>,
100    >(
101        &self,
102        reader: &mut dyn Read,
103        writer: &mut dyn Write,
104    ) -> Result<(), MagicCryptError> {
105        let mut cipher = Aes128CbcEnc::new(&self.key, &self.iv);
106
107        encrypt_stream::<N>(reader, writer, BLOCK_SIZE, |buffer| {
108            cipher.encrypt_blocks(to_blocks(buffer));
109        })
110    }
111
112    #[inline]
113    fn decrypt_bytes_to_bytes<T: ?Sized + AsRef<[u8]>>(
114        &self,
115        bytes: &T,
116    ) -> Result<Vec<u8>, MagicCryptError> {
117        let bytes = bytes.as_ref();
118
119        let cipher = Aes128CbcDec::new(&self.key, &self.iv);
120
121        let final_result = cipher.decrypt_padded_vec::<Pkcs7>(bytes)?;
122
123        Ok(final_result)
124    }
125
126    #[cfg(feature = "std")]
127    fn decrypt_reader_to_bytes(&self, reader: &mut dyn Read) -> Result<Vec<u8>, MagicCryptError> {
128        let mut final_result = Vec::new();
129
130        reader.read_to_end(&mut final_result)?;
131
132        let cipher = Aes128CbcDec::new(&self.key, &self.iv);
133
134        let data_length = cipher.decrypt_padded::<Pkcs7>(&mut final_result)?.len();
135
136        final_result.truncate(data_length);
137
138        Ok(final_result)
139    }
140
141    #[cfg(feature = "std")]
142    fn decrypt_reader_to_writer2<
143        N: ArraySize + PartialDiv<U16> + IsGreaterOrEqual<U16, Output = True>,
144    >(
145        &self,
146        reader: &mut dyn Read,
147        writer: &mut dyn Write,
148    ) -> Result<(), MagicCryptError> {
149        let mut cipher = Aes128CbcDec::new(&self.key, &self.iv);
150
151        decrypt_stream::<N>(reader, writer, BLOCK_SIZE, |buffer| {
152            cipher.decrypt_blocks(to_blocks(buffer));
153        })
154    }
155}