1use super::crypto::{CryptoError, CryptoResult, CryptoTrait};
2use crate::stdlib::sync::OnceLock;
3use crate::stdlib::sync::atomic::{AtomicU64, Ordering};
4use core::prelude::rust_2024::*;
5use openssl::{
6 aes::{AesKey, unwrap_key, wrap_key},
7 derive::Deriver,
8 md::Md,
9 pkey::{Id, PKey},
10 pkey_ctx::{HkdfMode, PkeyCtx},
11 sha::sha256,
12 sign::{Signer, Verifier},
13 symm::{Cipher, Crypter, Mode},
14};
15use rand::Rng;
16use uuid::Uuid;
17
18static UUID_COUNTER: OnceLock<AtomicU64> = OnceLock::new();
19
20fn init_counter() -> &'static AtomicU64 {
21 UUID_COUNTER.get_or_init(|| AtomicU64::new(1))
22}
23fn generate_pseudo_uuid() -> String {
24 let counter = init_counter();
25 let count = counter.fetch_add(1, Ordering::Relaxed);
26
27 format!("00000000-0000-0000-0000-{count:012x}")
29}
30
31#[derive(Debug, Clone, PartialEq)]
32pub struct CryptoNative;
33impl CryptoTrait for CryptoNative {
34 fn create_uuid(&self) -> String {
35 cfg_if::cfg_if! {
37 if #[cfg(feature = "debug")] {
38 use crate::runtime::global_context::get_global_context;
39 if get_global_context().debug_flags.enable_deterministic_behavior {
40 generate_pseudo_uuid()
41 }
42 else {
43 Uuid::new_v4().to_string()
44 }
45 }
46 else {
47 Uuid::new_v4().to_string()
48 }
49 }
50 }
51
52 fn random_bytes(&self, length: usize) -> Vec<u8> {
53 let mut rng = rand::thread_rng();
54 (0..length).map(|_| rng.r#gen()).collect()
55 }
56
57 fn hash_sha256<'a>(
58 &'a self,
59 to_digest: &'a [u8],
60 ) -> CryptoResult<'a, [u8; 32]> {
61 Box::pin(async move {
62 let hash = sha256(to_digest);
63 Ok(hash)
64 })
65 }
66
67 fn hkdf_sha256<'a>(
68 &'a self,
69 ikm: &'a [u8],
70 salt: &'a [u8],
71 ) -> CryptoResult<'a, [u8; 32]> {
72 Box::pin(async move {
73 let info = b"";
74 let mut ctx = PkeyCtx::new_id(Id::HKDF)
75 .map_err(|_| CryptoError::KeyGeneration)?;
76 ctx.derive_init().map_err(|_| CryptoError::KeyGeneration)?;
77 ctx.set_hkdf_mode(HkdfMode::EXTRACT_THEN_EXPAND)
78 .map_err(|_| CryptoError::KeyGeneration)?;
79 ctx.set_hkdf_md(Md::sha256())
80 .map_err(|_| CryptoError::KeyGeneration)?;
81 ctx.set_hkdf_salt(salt)
82 .map_err(|_| CryptoError::KeyGeneration)?;
83 ctx.set_hkdf_key(ikm)
84 .map_err(|_| CryptoError::KeyGeneration)?;
85 ctx.add_hkdf_info(info)
86 .map_err(|_| CryptoError::KeyGeneration)?;
87 let mut okm = [0u8; 32_usize];
88 ctx.derive(Some(&mut okm))
89 .map_err(|_| CryptoError::KeyGeneration)?;
90 Ok(okm)
91 })
92 }
93 fn gen_ed25519<'a>(&'a self) -> CryptoResult<'a, (Vec<u8>, Vec<u8>)> {
95 Box::pin(async move {
96 let key = PKey::generate_ed25519()
97 .map_err(|_| CryptoError::KeyGeneration)?;
98
99 let public_key: Vec<u8> = key
100 .public_key_to_der()
101 .map_err(|_| CryptoError::KeyGeneration)?;
102 let private_key: Vec<u8> = key
103 .private_key_to_pkcs8()
104 .map_err(|_| CryptoError::KeyGeneration)?;
105 Ok((public_key, private_key))
106 })
107 }
108
109 fn sig_ed25519<'a>(
111 &'a self,
112 pri_key: &'a [u8],
113 data: &'a [u8],
114 ) -> CryptoResult<'a, [u8; 64]> {
115 Box::pin(async move {
116 let sig_key = PKey::private_key_from_pkcs8(pri_key)
117 .map_err(|_| CryptoError::KeyImport)?;
118 let mut signer = Signer::new_without_digest(&sig_key)
119 .map_err(|_| CryptoError::Signing)?;
120 let signature = signer
121 .sign_oneshot_to_vec(data)
122 .map_err(|_| CryptoError::Signing)?;
123 let signature: [u8; 64] =
124 signature.try_into().expect("Invalid signature length");
125 Ok(signature)
126 })
127 }
128
129 fn ver_ed25519<'a>(
131 &'a self,
132 pub_key: &'a [u8],
133 sig: &'a [u8],
134 data: &'a [u8],
135 ) -> CryptoResult<'a, bool> {
136 Box::pin(async move {
137 let public_key = PKey::public_key_from_der(pub_key)
138 .map_err(|_| CryptoError::KeyImport)?;
139 let mut verifier = Verifier::new_without_digest(&public_key)
140 .map_err(|_| CryptoError::KeyImport)?;
141 let verification = verifier
142 .verify_oneshot(sig, data)
143 .map_err(|_| CryptoError::Verification)?;
144 Ok(verification)
145 })
146 }
147
148 fn aes_ctr_encrypt<'a>(
150 &'a self,
151 key: &'a [u8; 32],
152 iv: &'a [u8; 16],
153 plaintext: &'a [u8],
154 ) -> CryptoResult<'a, Vec<u8>> {
155 Box::pin(async move {
156 let cipher = Cipher::aes_256_ctr();
157 let mut enc = Crypter::new(cipher, Mode::Encrypt, key, Some(iv))
158 .map_err(|_| CryptoError::Encryption)?;
159
160 let mut out = vec![0u8; plaintext.len()];
161 let count = enc
162 .update(plaintext, &mut out)
163 .map_err(|_| CryptoError::Encryption)?;
164 out.truncate(count);
165 Ok(out)
166 })
167 }
168
169 fn aes_ctr_decrypt<'a>(
170 &'a self,
171 key: &'a [u8; 32],
172 iv: &'a [u8; 16],
173 ciphertext: &'a [u8],
174 ) -> CryptoResult<'a, Vec<u8>> {
175 self.aes_ctr_encrypt(key, iv, ciphertext)
176 }
177
178 fn key_upwrap<'a>(
180 &'a self,
181 kek_bytes: &'a [u8; 32],
182 rb: &'a [u8; 32],
183 ) -> CryptoResult<'a, [u8; 40]> {
184 Box::pin(async move {
185 let kek = AesKey::new_encrypt(kek_bytes)
187 .map_err(|_| CryptoError::Encryption)?;
188
189 let mut wrapped = [0u8; 40];
191 let _length = wrap_key(&kek, None, &mut wrapped, rb);
192
193 Ok(wrapped)
194 })
195 }
196
197 fn key_unwrap<'a>(
198 &'a self,
199 kek_bytes: &'a [u8; 32],
200 cipher: &'a [u8; 40],
201 ) -> CryptoResult<'a, [u8; 32]> {
202 Box::pin(async move {
203 let kek = AesKey::new_decrypt(kek_bytes)
205 .map_err(|_| CryptoError::Decryption)?;
206
207 let mut unwrapped: [u8; 32] = [0u8; 32];
209 let _length = unwrap_key(&kek, None, &mut unwrapped, cipher);
210 Ok(unwrapped)
211 })
212 }
213
214 fn gen_x25519<'a>(&'a self) -> CryptoResult<'a, ([u8; 44], [u8; 48])> {
216 Box::pin(async move {
217 let key = PKey::generate_x25519()
218 .map_err(|_| CryptoError::KeyGeneration)?;
219 let public_key: [u8; 44] = key
220 .public_key_to_der()
221 .map_err(|_| CryptoError::KeyGeneration)?
222 .try_into()
223 .map_err(|_| CryptoError::KeyGeneration)?;
224 let private_key: [u8; 48] = key
225 .private_key_to_pkcs8()
226 .map_err(|_| CryptoError::KeyGeneration)?
227 .try_into()
228 .map_err(|_| CryptoError::KeyGeneration)?;
229 Ok((public_key, private_key))
230 })
231 }
232
233 fn derive_x25519<'a>(
235 &'a self,
236 pri_key: &'a [u8; 48],
237 peer_pub: &'a [u8; 44],
238 ) -> CryptoResult<'a, Vec<u8>> {
239 Box::pin(async move {
240 let peer_pub = PKey::public_key_from_der(peer_pub)
241 .map_err(|_| CryptoError::KeyImport)?;
242 let my_priv = PKey::private_key_from_pkcs8(pri_key)
243 .map_err(|_| CryptoError::KeyImport)?;
244
245 let mut deriver = Deriver::new(&my_priv)
246 .map_err(|_| CryptoError::KeyGeneration)?;
247 deriver
248 .set_peer(&peer_pub)
249 .map_err(|_| CryptoError::KeyGeneration)?;
250 let derived = deriver
251 .derive_to_vec()
252 .map_err(|_| CryptoError::KeyGeneration)?;
253 Ok(derived)
254 })
255 }
256}
257
258#[cfg(test)]
259mod tests {
260 use super::*;
261 static CRYPTO: CryptoNative = CryptoNative {};
262
263 #[tokio::test]
264 pub async fn hash_sha256() {
265 let ikm = Vec::from([0u8; 32]);
266 let hash = CRYPTO.hash_sha256(&ikm).await.unwrap();
267 assert_eq!(
268 hash,
269 [
270 102, 104, 122, 173, 248, 98, 189, 119, 108, 143, 193, 139, 142,
271 159, 142, 32, 8, 151, 20, 133, 110, 226, 51, 179, 144, 42, 89,
272 29, 13, 95, 41, 37
273 ]
274 );
275 }
276
277 #[tokio::test]
278 pub async fn hash_sha256_key_derivation() {
279 let mut ikm = Vec::from([0u8; 32]);
280 let salt = Vec::from([0u8; 16]);
281 let hash_a = CRYPTO.hkdf_sha256(&ikm, &salt).await.unwrap();
282 ikm[0] = 1u8;
283 let hash_b = CRYPTO.hkdf_sha256(&ikm, &salt).await.unwrap();
284 assert_ne!(hash_a, hash_b);
285 assert_ne!(hash_a.to_vec(), ikm);
286 assert_eq!(
287 hash_a,
288 [
289 223, 114, 4, 84, 111, 27, 238, 120, 184, 83, 36, 167, 137, 140,
290 161, 25, 179, 135, 224, 19, 134, 209, 174, 240, 55, 120, 29,
291 74, 138, 3, 106, 238
292 ]
293 );
294 }
295
296 #[test]
297 pub fn base58() {
298 let something = b"yellow submarineyellow submarine".to_owned();
299 let some_check =
300 b"9At2nzU19GjL8F4WFRyB7RZSGLemMGUMVBZAMChfndF2".to_owned();
301
302 let based = CRYPTO.enc_b58(&something).unwrap();
303 let unbased = CRYPTO.dec_b58(&some_check).unwrap();
304 assert_eq!(something, unbased);
305 assert_eq!(some_check, based);
306 }
307
308 #[tokio::test]
310 pub async fn dsa_ed25519() {
311 let data = b"Some message to sign".to_vec();
313 let other_data = b"Some message to sign".to_vec();
314
315 let (pub_key, pri_key) = CRYPTO.gen_ed25519().await.unwrap();
317 assert_eq!(pub_key.len(), 44_usize);
318 assert_eq!(pri_key.len(), 48_usize);
319
320 let sig = CRYPTO.sig_ed25519(&pri_key, &data).await.unwrap();
321 assert_eq!(sig.len(), 64_usize);
322
323 let ver = CRYPTO.ver_ed25519(&pub_key, &sig, &data).await.unwrap();
325 assert!(ver);
326
327 let ver = CRYPTO
329 .ver_ed25519(&pub_key, &sig, &other_data)
330 .await
331 .unwrap();
332 assert!(!ver);
333
334 let (other_pub_key, other_pri_key) =
336 CRYPTO.gen_ed25519().await.unwrap();
337 let ver = CRYPTO
338 .ver_ed25519(&other_pub_key, &sig, &data)
339 .await
340 .unwrap();
341 assert!(!ver);
342
343 let other_sig =
345 CRYPTO.sig_ed25519(&other_pri_key, &data).await.unwrap();
346 let ver = CRYPTO
347 .ver_ed25519(&pub_key, &other_sig, &data)
348 .await
349 .unwrap();
350 assert!(!ver);
351 }
352
353 #[tokio::test]
354 pub async fn aes_ctr() {
355 let key = [0u8; 32];
356 let iv = [0u8; 16];
357
358 let data = b"Some message to encrypt".to_vec();
359
360 let ciphered = CRYPTO.aes_ctr_encrypt(&key, &iv, &data).await.unwrap();
361 let deciphered =
362 CRYPTO.aes_ctr_decrypt(&key, &iv, &ciphered).await.unwrap();
363
364 assert_ne!(ciphered, data);
365 assert_eq!(data, deciphered.to_vec());
366 }
367
368 #[tokio::test]
369 pub async fn key_wrap() {
370 let kek_bytes = [1u8; 32];
371 let sym_key: [u8; 32] =
372 CRYPTO.random_bytes(32_usize).try_into().unwrap();
373 let arand = CRYPTO.key_upwrap(&kek_bytes, &sym_key).await.unwrap();
374 let brand = CRYPTO.key_unwrap(&kek_bytes, &arand).await.unwrap();
375
376 assert_ne!(arand.to_vec(), brand.to_vec());
377 assert_eq!(arand.len(), brand.len() + 8);
378 }
379
380 #[tokio::test]
381 async fn dh_x25519() {
382 let (ser_pub, ser_pri) = CRYPTO.gen_x25519().await.unwrap();
383 let (cli_pub, cli_pri) = CRYPTO.gen_x25519().await.unwrap();
384
385 let cli_shared =
386 CRYPTO.derive_x25519(&cli_pri, &ser_pub).await.unwrap();
387 let ser_shared =
388 CRYPTO.derive_x25519(&ser_pri, &cli_pub).await.unwrap();
389
390 assert_eq!(cli_shared, ser_shared);
391 assert_eq!(cli_shared.len(), 32);
392 }
393
394 #[tokio::test]
395 pub async fn crypto_multi_roundtrip() {
396 let mut client_list = Vec::new();
398
399 let sym_key: [u8; 32] = CRYPTO.random_bytes(32).try_into().unwrap();
401
402 for _ in 0..10 {
403 let (cli_pub, cli_pri) = CRYPTO.gen_x25519().await.unwrap();
404 client_list.push((cli_pri, cli_pub));
405 }
406
407 let data = b"Some message to encrypt".to_vec();
409 let iv = [0u8; 16];
410 let cipher =
411 CRYPTO.aes_ctr_encrypt(&sym_key, &iv, &data).await.unwrap();
412
413 let mut payloads = Vec::new();
415 for (_, peer_pub) in client_list.iter().take(10) {
416 let (ser_pub, ser_pri) = CRYPTO.gen_x25519().await.unwrap();
417 let ser_kek_bytes: [u8; 32] = CRYPTO
418 .derive_x25519(&ser_pri, peer_pub)
419 .await
420 .unwrap()
421 .try_into()
422 .unwrap();
423
424 let wrapped =
425 CRYPTO.key_upwrap(&ser_kek_bytes, &sym_key).await.unwrap();
426
427 payloads.push((ser_pub, wrapped));
428 }
429
430 for i in 0..10 {
432 let cli_kek_bytes: [u8; 32] = CRYPTO
434 .derive_x25519(&client_list[i].0, &payloads[i].0)
435 .await
436 .unwrap()
437 .try_into()
438 .unwrap();
439 let unwrapped = CRYPTO
440 .key_unwrap(&cli_kek_bytes, &payloads[i].1)
441 .await
442 .unwrap();
443 let plain = CRYPTO
444 .aes_ctr_decrypt(&unwrapped, &iv, &cipher)
445 .await
446 .unwrap();
447
448 assert_ne!(payloads[i].1.to_vec(), unwrapped.to_vec());
450 assert_eq!(payloads[i].1.len(), unwrapped.len() + 8);
451
452 assert_ne!(data, cipher);
454 assert_eq!(plain, data);
455 }
456 }
457}