prople_crypto/aead/
mod.rs1use rst_common::with_cryptography::chacha20poly1305::{
5 aead::{Aead, AeadCore, KeyInit},
6 XChaCha20Poly1305,
7};
8
9use rst_common::with_cryptography::rand::{rngs::adapter::ReseedingRng, SeedableRng};
10use rst_common::with_cryptography::rand_chacha::{rand_core::OsRng as RandCoreOsRng, ChaCha20Core};
11
12mod key;
13pub use key::Key;
14
15mod types;
16pub use types::{KeyEncryption, KeyNonce, MessageCipher, MessagePlain, Nonce};
17
18use crate::{passphrase::prelude::errors::CommonError, types::VectorValue};
19
20pub mod errors {
21 use rst_common::with_errors::thiserror::{self, Error};
22
23 #[derive(Debug, Error)]
26 pub enum AeadError {
27 #[error("aead: unable to parse bytes: `{0}`")]
28 CipherGeneratorError(String),
29 }
30}
31
32pub struct AEAD;
35
36impl AEAD {
37 pub fn nonce() -> Nonce {
38 let prng = ChaCha20Core::from_entropy();
39 let reseeding_rng = ReseedingRng::new(prng, 0, RandCoreOsRng);
40 let nonce = XChaCha20Poly1305::generate_nonce(reseeding_rng);
41 Nonce::from(nonce.to_vec())
42 }
43
44 pub fn encrypt(key: &Key, message: &MessagePlain) -> Result<MessageCipher, errors::AeadError> {
45 let (key_bytes, nonce_bytes) = AEAD::key_extractor(key)
46 .map_err(|err| errors::AeadError::CipherGeneratorError(err.to_string()))?;
47
48 let cipher = XChaCha20Poly1305::new(&key_bytes.into());
49 cipher
50 .encrypt(&nonce_bytes.into(), message.vec().as_slice())
51 .map(MessageCipher::from)
52 .map_err(|err| errors::AeadError::CipherGeneratorError(err.to_string()))
53 }
54
55 pub fn decrypt(
56 key: &Key,
57 encrypted: &MessageCipher,
58 ) -> Result<MessagePlain, errors::AeadError> {
59 let (key_bytes, nonce_bytes) = AEAD::key_extractor(key)
60 .map_err(|err| errors::AeadError::CipherGeneratorError(err.to_string()))?;
61
62 let cipher = XChaCha20Poly1305::new(&key_bytes.into());
63 cipher
64 .decrypt(&nonce_bytes.into(), encrypted.vec().as_ref())
65 .map(MessagePlain::from)
66 .map_err(|err| errors::AeadError::CipherGeneratorError(err.to_string()))
67 }
68
69 fn key_extractor(key: &Key) -> Result<([u8; 32], [u8; 24]), CommonError> {
70 let nonce_bytes = key.get_nonce_bytes()?;
71 let key_bytes = key.get_key_bytes()?;
72
73 Ok((key_bytes, nonce_bytes))
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80 use crate::{ecdh::keypair::KeyPair, types::BytesValue};
81
82 #[test]
83 fn test_nonce() {
84 let nonce = AEAD::nonce();
85 let nonce_value: Result<[u8; 24], _> = nonce.vec().try_into();
86 assert!(!nonce_value.is_err())
87 }
88
89 #[test]
90 fn test_encrypt_decrypt() {
91 let keypair_alice = KeyPair::generate();
92 let keypair_bob = KeyPair::generate();
93
94 let pubkey_bob = keypair_bob.pub_key();
95 let public_bob_hex = pubkey_bob.to_hex();
96
97 let secret_alice = keypair_alice.secret(public_bob_hex);
98 let shared_secret_alice_blake3 = secret_alice.to_blake3();
99
100 let nonce = AEAD::nonce();
101 let nonce_value: Result<[u8; 24], _> = nonce.vec().try_into();
102
103 let alice_key = shared_secret_alice_blake3.unwrap();
104 let alice_key_bytes = alice_key.bytes();
105
106 let alice_key_encryption_builder = KeyEncryption::try_from(alice_key_bytes);
107 assert!(!alice_key_encryption_builder.is_err());
108
109 let key = Key::new(
110 alice_key_encryption_builder.as_ref().unwrap().to_owned(),
111 KeyNonce::from(nonce_value.unwrap()),
112 );
113
114 let message = String::from("plaintext");
115 let encrypted = AEAD::encrypt(&key, &MessagePlain::from(message.clone()));
116 assert!(!encrypted.is_err());
117
118 let encrypted_str = encrypted.unwrap();
119 let decrypted = AEAD::decrypt(&key, &encrypted_str);
120 assert!(!decrypted.is_err());
121
122 let decrypted_value = decrypted.unwrap();
123 let result = String::from_utf8(decrypted_value.vec());
124 assert!(!result.is_err());
125 assert_eq!(result.unwrap(), message);
126 assert_eq!(decrypted_value.vec(), message.clone().as_bytes().to_vec());
127
128 let nonce_missed = AEAD::nonce();
129 let nonce_missed_value: Result<[u8; 24], _> = nonce_missed.vec().try_into();
130
131 let key_invalid = Key::new(
132 alice_key_encryption_builder.unwrap(),
133 KeyNonce::from(nonce_missed_value.unwrap()),
134 );
135 let encrypted2 = AEAD::encrypt(&key, &MessagePlain::from(message));
136 let decrypted_unmatched = AEAD::decrypt(&key_invalid, &encrypted2.unwrap());
137
138 assert!(decrypted_unmatched.is_err());
139 assert!(matches!(
140 decrypted_unmatched,
141 Err(errors::AeadError::CipherGeneratorError(_))
142 ))
143 }
144}