Skip to main content

sentc_crypto_std_keys/core/sym/
aes_gcm.rs

1use 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
91//__________________________________________________________________________________________________
92//internally function
93
94fn generate_key_internally<R: CryptoRng + RngCore>(rng: &mut R) -> Result<[u8; 32], Error>
95{
96	let mut key = [0u8; 32]; //aes 256
97
98	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	//IV
110	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	//put the IV in front of the ciphertext
129	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}