shadow_crypt_core/v1/
crypt.rs1use chacha20poly1305::{KeyInit, XChaCha20Poly1305, aead::Aead};
2
3use crate::{algorithm::Algorithm, errors::CryptError, memory::SecureBytes};
4
5pub fn encrypt_bytes(
6 plaintext: &[u8],
7 key: &[u8; 32],
8 nonce: &[u8; 24],
9) -> Result<(Vec<u8>, Algorithm), CryptError> {
10 let cipher = XChaCha20Poly1305::new(key.into());
11 let ciphertext = cipher
12 .encrypt(nonce.into(), plaintext)
13 .map_err(|e| CryptError::EncryptionError(format!("Encryption failed: {}", e)))?;
14
15 Ok((ciphertext, Algorithm::XChaCha20Poly1305))
16}
17
18pub fn decrypt_bytes(
20 ciphertext: &[u8],
21 key: &[u8; 32],
22 nonce: &[u8; 24],
23) -> Result<(SecureBytes, Algorithm), CryptError> {
24 let cipher = XChaCha20Poly1305::new(key.into());
25 let plaintext = cipher
26 .decrypt(nonce.into(), ciphertext)
27 .map_err(|e| CryptError::DecryptionError(format!("Decryption failed: {}", e)))?;
28
29 Ok((SecureBytes::new(plaintext), Algorithm::XChaCha20Poly1305))
30}
31
32#[cfg(test)]
33mod tests {
34 use super::*;
35
36 #[test]
37 fn test_encrypt_decrypt_round_trip() {
38 let plaintext = b"Hello, world!";
39 let key = [0u8; 32];
40 let nonce = [0u8; 24];
41
42 let (ciphertext, algorithm) = encrypt_bytes(plaintext, &key, &nonce).unwrap();
43 assert_eq!(algorithm, Algorithm::XChaCha20Poly1305);
44 assert_ne!(ciphertext, plaintext);
45
46 let (decrypted, algorithm) = decrypt_bytes(&ciphertext, &key, &nonce).unwrap();
47 assert_eq!(algorithm, Algorithm::XChaCha20Poly1305);
48 assert_eq!(decrypted.as_slice(), plaintext);
49 }
50
51 #[test]
52 fn test_encrypt_different_nonce_produces_different_ciphertext() {
53 let plaintext = b"Test message";
54 let key = [1u8; 32];
55 let nonce1 = [0u8; 24];
56 let nonce2 = [1u8; 24];
57
58 let (ciphertext1, _) = encrypt_bytes(plaintext, &key, &nonce1).unwrap();
59 let (ciphertext2, _) = encrypt_bytes(plaintext, &key, &nonce2).unwrap();
60
61 assert_ne!(ciphertext1, ciphertext2);
62 }
63
64 #[test]
65 fn test_encrypt_same_inputs_produce_same_output() {
66 let plaintext = b"Deterministic test";
67 let key = [2u8; 32];
68 let nonce = [2u8; 24];
69
70 let (ciphertext1, _) = encrypt_bytes(plaintext, &key, &nonce).unwrap();
71 let (ciphertext2, _) = encrypt_bytes(plaintext, &key, &nonce).unwrap();
72
73 assert_eq!(ciphertext1, ciphertext2);
74 }
75
76 #[test]
77 fn test_decrypt_with_wrong_key_fails() {
78 let plaintext = b"Secret message";
79 let key = [3u8; 32];
80 let wrong_key = [4u8; 32];
81 let nonce = [3u8; 24];
82
83 let (ciphertext, _) = encrypt_bytes(plaintext, &key, &nonce).unwrap();
84 let result = decrypt_bytes(&ciphertext, &wrong_key, &nonce);
85
86 assert!(result.is_err());
87 }
88
89 #[test]
90 fn test_decrypt_with_wrong_nonce_fails() {
91 let plaintext = b"Secret message";
92 let key = [5u8; 32];
93 let nonce = [5u8; 24];
94 let wrong_nonce = [6u8; 24];
95
96 let (ciphertext, _) = encrypt_bytes(plaintext, &key, &nonce).unwrap();
97 let result = decrypt_bytes(&ciphertext, &key, &wrong_nonce);
98
99 assert!(result.is_err());
100 }
101
102 #[test]
103 fn test_encrypt_empty_plaintext() {
104 let plaintext = b"";
105 let key = [7u8; 32];
106 let nonce = [7u8; 24];
107
108 let (ciphertext, algorithm) = encrypt_bytes(plaintext, &key, &nonce).unwrap();
109 assert_eq!(algorithm, Algorithm::XChaCha20Poly1305);
110
111 let (decrypted, algorithm) = decrypt_bytes(&ciphertext, &key, &nonce).unwrap();
112 assert_eq!(algorithm, Algorithm::XChaCha20Poly1305);
113 assert_eq!(decrypted.as_slice(), plaintext);
114 }
115}