1use crate::stdlib::{future::Future, pin::Pin};
2use rand::Rng;
3use std::sync::OnceLock;
4use std::sync::atomic::{AtomicU64, Ordering};
5
6use super::crypto::{CryptoError, CryptoTrait};
7use uuid::Uuid;
8
9use openssl::{
10 aes::{AesKey, unwrap_key, wrap_key},
11 derive::Deriver,
12 pkey::PKey,
13 sign::{Signer, Verifier},
14 symm::{Cipher, Crypter, Mode},
15};
16
17static UUID_COUNTER: OnceLock<AtomicU64> = OnceLock::new();
18
19fn init_counter() -> &'static AtomicU64 {
20 UUID_COUNTER.get_or_init(|| AtomicU64::new(1))
21}
22fn generate_pseudo_uuid() -> String {
23 let counter = init_counter();
24 let count = counter.fetch_add(1, Ordering::Relaxed);
25
26 format!("00000000-0000-0000-0000-{count:012x}")
28}
29
30#[derive(Debug, Clone, PartialEq)]
31pub struct CryptoNative;
32impl CryptoTrait for CryptoNative {
33 fn create_uuid(&self) -> String {
34 cfg_if::cfg_if! {
36 if #[cfg(feature = "debug")] {
37 use crate::runtime::global_context::get_global_context;
38 if get_global_context().debug_flags.enable_deterministic_behavior {
39 generate_pseudo_uuid()
40 }
41 else {
42 Uuid::new_v4().to_string()
43 }
44 }
45 else {
46 Uuid::new_v4().to_string()
47 }
48 }
49 }
50
51 fn random_bytes(&self, length: usize) -> Vec<u8> {
52 let mut rng = rand::thread_rng();
53 (0..length).map(|_| rng.r#gen()).collect()
54 }
55
56 fn gen_ed25519(
58 &self,
59 ) -> Pin<
60 Box<
61 dyn Future<Output = Result<(Vec<u8>, Vec<u8>), CryptoError>>
62 + 'static,
63 >,
64 > {
65 Box::pin(async move {
66 let key = PKey::generate_ed25519()
67 .map_err(|_| CryptoError::KeyGeneratorFailed)?;
68
69 let public_key: Vec<u8> = key
70 .public_key_to_der()
71 .map_err(|_| CryptoError::KeyGeneratorFailed)?;
72 let private_key: Vec<u8> = key
73 .private_key_to_pkcs8()
74 .map_err(|_| CryptoError::KeyGeneratorFailed)?;
75 Ok((public_key, private_key))
76 })
77 }
78
79 fn sig_ed25519<'a>(
81 &'a self,
82 pri_key: &'a [u8],
83 data: &'a [u8],
84 ) -> Pin<Box<dyn Future<Output = Result<[u8; 64], CryptoError>> + 'a>> {
85 Box::pin(async move {
86 let sig_key = PKey::private_key_from_pkcs8(pri_key)
87 .map_err(|_| CryptoError::KeyImportFailed)?;
88 let mut signer = Signer::new_without_digest(&sig_key)
89 .map_err(|_| CryptoError::SigningError)?;
90 let signature = signer
91 .sign_oneshot_to_vec(data)
92 .map_err(|_| CryptoError::SigningError)?;
93 let signature: [u8; 64] =
94 signature.try_into().expect("Invalid signature length");
95 Ok(signature)
96 })
97 }
98
99 fn ver_ed25519<'a>(
101 &'a self,
102 pub_key: &'a [u8],
103 sig: &'a [u8],
104 data: &'a [u8],
105 ) -> Pin<Box<dyn Future<Output = Result<bool, CryptoError>> + 'a>> {
106 Box::pin(async move {
107 let public_key = PKey::public_key_from_der(pub_key)
108 .map_err(|_| CryptoError::KeyImportFailed)?;
109 let mut verifier = Verifier::new_without_digest(&public_key)
110 .map_err(|_| CryptoError::KeyImportFailed)?;
111 verifier
112 .verify_oneshot(sig, data)
113 .map_err(|_| CryptoError::VerificationError)
114 })
115 }
116
117 fn aes_ctr_encrypt<'a>(
119 &'a self,
120 key: &'a [u8; 32],
121 iv: &'a [u8; 16],
122 plaintext: &'a [u8],
123 ) -> Pin<Box<dyn Future<Output = Result<Vec<u8>, CryptoError>> + 'a>> {
124 Box::pin(async move {
125 let cipher = Cipher::aes_256_ctr();
126 let mut enc = Crypter::new(cipher, Mode::Encrypt, key, Some(iv))
127 .map_err(|_| CryptoError::EncryptionError)?;
128
129 let mut out = vec![0u8; plaintext.len()];
130 let count = enc
131 .update(plaintext, &mut out)
132 .map_err(|_| CryptoError::EncryptionError)?;
133 out.truncate(count);
134 Ok(out)
135 })
136 }
137
138 fn aes_ctr_decrypt<'a>(
139 &'a self,
140 key: &'a [u8; 32],
141 iv: &'a [u8; 16],
142 ciphertext: &'a [u8],
143 ) -> Pin<Box<dyn Future<Output = Result<Vec<u8>, CryptoError>> + 'a>> {
144 self.aes_ctr_encrypt(key, iv, ciphertext)
145 }
146
147 fn key_upwrap<'a>(
149 &'a self,
150 kek_bytes: &'a [u8; 32],
151 rb: &'a [u8; 32],
152 ) -> Pin<Box<dyn Future<Output = Result<[u8; 40], CryptoError>> + 'a>> {
153 Box::pin(async move {
154 let kek = AesKey::new_encrypt(kek_bytes)
156 .map_err(|_| CryptoError::EncryptionError)?;
157
158 let mut wrapped = [0u8; 40];
160 let _length = wrap_key(&kek, None, &mut wrapped, rb);
161
162 Ok(wrapped)
163 })
164 }
165
166 fn key_unwrap<'a>(
167 &'a self,
168 kek_bytes: &'a [u8; 32],
169 cipher: &'a [u8; 40],
170 ) -> Pin<Box<dyn Future<Output = Result<[u8; 32], CryptoError>> + 'a>> {
171 Box::pin(async move {
172 let kek = AesKey::new_decrypt(kek_bytes)
174 .map_err(|_| CryptoError::DecryptionError)?;
175
176 let mut unwrapped: [u8; 32] = [0u8; 32];
178 let _length = unwrap_key(&kek, None, &mut unwrapped, cipher);
179 Ok(unwrapped)
180 })
181 }
182
183 fn gen_x25519(
185 &self,
186 ) -> Pin<Box<dyn Future<Output = Result<([u8; 44], [u8; 48]), CryptoError>>>>
187 {
188 Box::pin(async move {
189 let key = PKey::generate_x25519()
190 .map_err(|_| CryptoError::KeyGeneratorFailed)?;
191 let public_key: [u8; 44] = key
192 .public_key_to_der()
193 .map_err(|_| CryptoError::KeyGeneratorFailed)?
194 .try_into()
195 .map_err(|_| CryptoError::KeyGeneratorFailed)?;
196 let private_key: [u8; 48] = key
197 .private_key_to_pkcs8()
198 .map_err(|_| CryptoError::KeyGeneratorFailed)?
199 .try_into()
200 .map_err(|_| CryptoError::KeyGeneratorFailed)?;
201 Ok((public_key, private_key))
202 })
203 }
204
205 fn derive_x25519<'a>(
207 &'a self,
208 pri_key: &'a [u8; 48],
209 peer_pub: &'a [u8; 44],
210 ) -> Pin<Box<dyn Future<Output = Result<Vec<u8>, CryptoError>> + 'a>> {
211 Box::pin(async move {
212 let peer_pub = PKey::public_key_from_der(peer_pub)
213 .map_err(|_| CryptoError::KeyImportFailed)?;
214 let my_priv = PKey::private_key_from_pkcs8(pri_key)
215 .map_err(|_| CryptoError::KeyImportFailed)?;
216
217 let mut deriver = Deriver::new(&my_priv)
218 .map_err(|_| CryptoError::KeyGeneratorFailed)?;
219 deriver
220 .set_peer(&peer_pub)
221 .map_err(|_| CryptoError::KeyGeneratorFailed)?;
222 deriver
223 .derive_to_vec()
224 .map_err(|_| CryptoError::KeyGeneratorFailed)
225 })
226 }
227}
228
229#[cfg(test)]
230mod tests {
231 use super::*;
232 static CRYPTO: CryptoNative = CryptoNative {};
233
234 #[tokio::test]
236 pub async fn test_dsa_ed2519() {
237 let data = b"Some message to sign".to_vec();
238
239 let (pub_key, pri_key) = CRYPTO.gen_ed25519().await.unwrap();
240
241 let sig: [u8; 64] = CRYPTO.sig_ed25519(&pri_key, &data).await.unwrap();
242 assert!(CRYPTO.ver_ed25519(&pub_key, &sig, &data).await.unwrap());
243 }
244
245 #[tokio::test]
247 pub async fn aes_ctr_roundtrip() {
248 let key = [0u8; 32];
249 let iv = [0u8; 16];
250
251 let data = b"Some message to encrypt".to_vec();
252
253 let ciphered = CRYPTO.aes_ctr_encrypt(&key, &iv, &data).await.unwrap();
254 let deciphered =
255 CRYPTO.aes_ctr_decrypt(&key, &iv, &ciphered).await.unwrap();
256
257 assert_ne!(ciphered, data);
258 assert_eq!(data, deciphered.to_vec());
259 }
260
261 #[tokio::test]
262 pub async fn test_keywrapping() {
263 let kek_bytes = [1u8; 32];
264 let sym_key: [u8; 32] =
265 CRYPTO.random_bytes(32_usize).try_into().unwrap();
266 let arand = CRYPTO.key_upwrap(&kek_bytes, &sym_key).await.unwrap();
267 let brand = CRYPTO.key_unwrap(&kek_bytes, &arand).await.unwrap();
268
269 assert_ne!(arand.to_vec(), brand.to_vec());
270 assert_eq!(arand.len(), brand.len() + 8);
271 }
272
273 #[tokio::test]
274 pub async fn test_keywrapping_more() {
275 let kek: [u8; 32] = [
277 176, 213, 29, 202, 131, 45, 220, 153, 250, 120, 219, 65, 177, 117,
278 244, 172, 38, 107, 221, 109, 160, 134, 15, 195, 23, 22, 143, 238,
279 242, 222, 38, 248,
280 ];
281
282 let web_wrapped: [u8; 40] = [
283 140, 223, 207, 46, 9, 105, 205, 24, 174, 238, 109, 5, 96, 4, 51,
284 132, 54, 187, 251, 167, 105, 131, 109, 246, 123, 238, 160, 139,
285 180, 59, 185, 8, 191, 57, 139, 133, 19, 40, 15, 210,
286 ];
287
288 let wrapped = CRYPTO.key_upwrap(&kek, &kek).await.unwrap();
289
290 let unwrapped = CRYPTO.key_unwrap(&kek, &wrapped).await.unwrap();
291 let web_unwrapped =
292 CRYPTO.key_unwrap(&kek, &web_wrapped).await.unwrap();
293
294 assert_eq!(kek, unwrapped);
295 assert_eq!(kek, web_unwrapped);
296 }
297
298 #[tokio::test]
299 async fn test_dh_x25519() {
300 let (ser_pub, ser_pri) = CRYPTO.gen_x25519().await.unwrap();
301 let (cli_pub, cli_pri) = CRYPTO.gen_x25519().await.unwrap();
302
303 let cli_shared =
304 CRYPTO.derive_x25519(&cli_pri, &ser_pub).await.unwrap();
305 let ser_shared =
306 CRYPTO.derive_x25519(&ser_pri, &cli_pub).await.unwrap();
307
308 assert_eq!(cli_shared, ser_shared);
309 assert_eq!(cli_shared.len(), 32);
310 }
311
312 #[tokio::test]
313 pub async fn test_multi_roundtrip() {
314 let mut client_list = Vec::new();
316
317 let sym_key: [u8; 32] = CRYPTO.random_bytes(32).try_into().unwrap();
319
320 for _ in 0..10 {
321 let (cli_pub, cli_pri) = CRYPTO.gen_x25519().await.unwrap();
322 client_list.push((cli_pri, cli_pub));
323 }
324
325 let data = b"Some message to encrypt".to_vec();
327 let iv = [0u8; 16];
328 let cipher =
329 CRYPTO.aes_ctr_encrypt(&sym_key, &iv, &data).await.unwrap();
330
331 let mut payloads = Vec::new();
333 for (_, peer_pub) in client_list.iter().take(10) {
334 let (ser_pub, ser_pri) = CRYPTO.gen_x25519().await.unwrap();
335 let ser_kek_bytes: [u8; 32] = CRYPTO
336 .derive_x25519(&ser_pri, peer_pub)
337 .await
338 .unwrap()
339 .try_into()
340 .unwrap();
341
342 let wrapped =
343 CRYPTO.key_upwrap(&ser_kek_bytes, &sym_key).await.unwrap();
344
345 payloads.push((ser_pub, wrapped));
346 }
347
348 for i in 0..10 {
350 let cli_kek_bytes: [u8; 32] = CRYPTO
352 .derive_x25519(&client_list[i].0, &payloads[i].0)
353 .await
354 .unwrap()
355 .try_into()
356 .unwrap();
357 let unwrapped = CRYPTO
358 .key_unwrap(&cli_kek_bytes, &payloads[i].1)
359 .await
360 .unwrap();
361 let plain = CRYPTO
362 .aes_ctr_decrypt(&unwrapped, &iv, &cipher)
363 .await
364 .unwrap();
365
366 assert_ne!(payloads[i].1.to_vec(), unwrapped.to_vec());
368 assert_eq!(payloads[i].1.len(), unwrapped.len() + 8);
369
370 assert_ne!(data, cipher);
372 assert_eq!(plain, data);
373 }
374 }
375}