sentc_crypto_std_keys/core/sym/
aes_gcm.rs1use alloc::vec::Vec;
2
3use aes_gcm::aead::generic_array::GenericArray;
4use aes_gcm::aead::{Aead, NewAead, Payload};
5use aes_gcm::{Aes256Gcm, Key};
6use rand_core::{CryptoRng, RngCore};
7use sentc_crypto_core::cryptomat::{SymKey, SymKeyGen};
8use sentc_crypto_core::{as_ref_bytes_single_value, crypto_alg_str_impl, try_from_bytes_owned_single_value, Error};
9
10use crate::core::sym::SymmetricKey;
11use crate::get_rand;
12
13const AES_IV_LENGTH: usize = 12;
14
15pub const AES_GCM_OUTPUT: &str = "AES-GCM-256";
16
17pub(crate) type AesKey = [u8; 32];
18
19pub struct Aes256GcmKey(AesKey);
20
21impl Aes256GcmKey
22{
23 pub(crate) fn from_raw_key(raw: AesKey) -> Self
24 {
25 Self(raw)
26 }
27}
28
29try_from_bytes_owned_single_value!(Aes256GcmKey);
30as_ref_bytes_single_value!(Aes256GcmKey);
31crypto_alg_str_impl!(Aes256GcmKey, AES_GCM_OUTPUT);
32
33impl Into<SymmetricKey> for Aes256GcmKey
34{
35 fn into(self) -> SymmetricKey
36 {
37 SymmetricKey::Aes(self)
38 }
39}
40
41impl SymKey for Aes256GcmKey
42{
43 fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>, Error>
44 {
45 encrypt_internally(&self.0, data, None, &mut get_rand())
46 }
47
48 fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>, Error>
49 {
50 decrypt_internally(&self.0, ciphertext, None)
51 }
52
53 fn encrypt_with_aad(&self, data: &[u8], aad: &[u8]) -> Result<Vec<u8>, Error>
54 {
55 encrypt_internally(&self.0, data, Some(aad), &mut get_rand())
56 }
57
58 fn decrypt_with_aad(&self, ciphertext: &[u8], aad: &[u8]) -> Result<Vec<u8>, Error>
59 {
60 decrypt_internally(&self.0, ciphertext, Some(aad))
61 }
62}
63
64impl SymKeyGen for Aes256GcmKey
65{
66 type SymmetricKey = Self;
67
68 fn generate() -> Result<Self::SymmetricKey, Error>
69 {
70 let key = generate_key_internally(&mut get_rand())?;
71
72 Ok(Aes256GcmKey(key))
73 }
74}
75
76pub fn raw_encrypt(key: &AesKey, data: &[u8]) -> Result<Vec<u8>, Error>
77{
78 encrypt_internally(key, data, None, &mut get_rand())
79}
80
81pub fn raw_decrypt(key: &AesKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error>
82{
83 decrypt_internally(key, ciphertext, None)
84}
85
86pub fn raw_generate() -> Result<AesKey, Error>
87{
88 generate_key_internally(&mut get_rand())
89}
90
91fn generate_key_internally<R: CryptoRng + RngCore>(rng: &mut R) -> Result<[u8; 32], Error>
95{
96 let mut key = [0u8; 32]; rng.try_fill_bytes(&mut key)
99 .map_err(|_| Error::KeyCreationFailed)?;
100
101 Ok(key)
102}
103
104fn encrypt_internally<R: CryptoRng + RngCore>(key: &AesKey, data: &[u8], aad: Option<&[u8]>, rng: &mut R) -> Result<Vec<u8>, Error>
105{
106 let key = Key::from_slice(key);
107 let aead = Aes256Gcm::new(key);
108
109 let mut nonce = [0u8; AES_IV_LENGTH];
111 rng.try_fill_bytes(&mut nonce)
112 .map_err(|_| Error::EncryptionFailedRng)?;
113 let nonce = GenericArray::from_slice(&nonce);
114
115 let plaintext = if let Some(a) = aad {
116 Payload {
117 aad: a,
118 msg: data,
119 }
120 } else {
121 Payload::from(data)
122 };
123
124 let ciphertext = aead
125 .encrypt(nonce, plaintext)
126 .map_err(|_| Error::EncryptionFailed)?;
127
128 let mut output = Vec::with_capacity(AES_IV_LENGTH + ciphertext.len());
130 output.extend_from_slice(nonce);
131 output.extend_from_slice(&ciphertext);
132
133 Ok(output)
134}
135
136fn decrypt_internally(key: &AesKey, ciphertext: &[u8], aad: Option<&[u8]>) -> Result<Vec<u8>, Error>
137{
138 let key = Key::from_slice(key);
139 let aead = Aes256Gcm::new(key);
140
141 let nonce = GenericArray::from_slice(&ciphertext[..AES_IV_LENGTH]);
142 let encrypted = &ciphertext[AES_IV_LENGTH..];
143
144 let encrypted = if let Some(a) = aad {
145 Payload {
146 aad: a,
147 msg: encrypted,
148 }
149 } else {
150 Payload::from(encrypted)
151 };
152
153 let decrypted = aead
154 .decrypt(nonce, encrypted)
155 .map_err(|_| Error::DecryptionFailed)?;
156
157 Ok(decrypted)
158}
159
160#[cfg(test)]
161mod test
162{
163 use core::str::from_utf8;
164
165 use sentc_crypto_core::Error::DecryptionFailed;
166
167 use super::*;
168
169 #[test]
170 fn test_key_generated()
171 {
172 let _output = Aes256GcmKey::generate().unwrap();
173 }
174
175 #[test]
176 fn test_plain_encrypt_decrypt()
177 {
178 let text = "Hello world üöäéèßê°";
179
180 let output = Aes256GcmKey::generate().unwrap();
181
182 let encrypted = output.encrypt(text.as_bytes()).unwrap();
183
184 let decrypted = output.decrypt(&encrypted).unwrap();
185
186 assert_eq!(text.as_bytes(), decrypted);
187
188 let decrypted_text = from_utf8(&decrypted).unwrap();
189
190 assert_eq!(text, decrypted_text);
191 }
192
193 #[test]
194 fn test_not_decrypt_with_wrong_key()
195 {
196 let text = "Hello world üöäéèßê°";
197
198 let output1 = Aes256GcmKey::generate().unwrap();
199 let output2 = Aes256GcmKey::generate().unwrap();
200
201 let encrypted = output1.encrypt(text.as_bytes()).unwrap();
202
203 let decrypt_result = output2.decrypt(&encrypted);
204
205 assert!(matches!(decrypt_result, Err(DecryptionFailed)));
206 }
207
208 #[test]
209 fn test_encrypt_decrypt_with_payload()
210 {
211 let text = "Hello world üöäéèßê°";
212 let payload = b"payload1234567891011121314151617";
213
214 let output = Aes256GcmKey::generate().unwrap();
215
216 let encrypted = output.encrypt_with_aad(text.as_bytes(), payload).unwrap();
217
218 let decrypted = output.decrypt_with_aad(&encrypted, payload).unwrap();
219
220 assert_eq!(text.as_bytes(), decrypted);
221
222 let decrypted_text = from_utf8(&decrypted).unwrap();
223
224 assert_eq!(text, decrypted_text);
225 }
226
227 #[test]
228 fn test_encrypt_decrypt_with_wrong_payload()
229 {
230 let text = "Hello world üöäéèßê°";
231 let payload = b"payload1234567891011121314151617";
232 let payload2 = b"payload1234567891011121314151618";
233
234 let output = Aes256GcmKey::generate().unwrap();
235
236 let encrypted = output.encrypt_with_aad(text.as_bytes(), payload).unwrap();
237
238 let decrypted = output.decrypt_with_aad(&encrypted, payload2);
239
240 assert!(matches!(decrypted, Err(DecryptionFailed)));
241 }
242}