kychacha_crypto/encryption.rs
1//! Symmetric cypher using ChaCha20Poly1305 (AEAD).
2
3use anyhow::{anyhow, Context, Result};
4use chacha20poly1305::{
5 aead::{AeadCore, AeadMutInPlace, KeyInit, OsRng},
6 ChaCha20Poly1305, Nonce,
7};
8
9/// Encrypt a message with ChaCha20Poly1305.
10///
11/// # Example
12/// ```
13/// use kychacha_crypto::encrypt_with_key;
14///
15/// // do not use this on your code, instead use encrypt fn
16/// let key = [0u8; 32];
17/// let (nonce, cifrado) = encrypt_with_key(&key, b"mensaje").unwrap();
18/// ```
19///
20/// # Errores
21/// - key ≠ 32 bytes
22/// - Error while encrypting
23pub fn encrypt_with_key(key: &[u8; 32], plaintext: &[u8]) -> Result<(Vec<u8>, Vec<u8>)> {
24 let mut cipher = ChaCha20Poly1305::new_from_slice(key)
25 .context("Invalid key length")?;
26
27 let nonce = ChaCha20Poly1305::generate_nonce(&mut OsRng);
28 let mut buffer = plaintext.to_vec();
29
30 cipher
31 .encrypt_in_place(&nonce, b"", &mut buffer)
32 .map_err(|e| anyhow!("Encryption failed: {}", e))?;
33
34 Ok((nonce.to_vec(), buffer))
35}
36
37/// Decrypt a message with ChaCha20Poly1305.
38///
39/// # Example
40/// ```
41/// use kychacha_crypto::{decrypt_with_key, encrypt_with_key};
42///
43/// let key = [0u8; 32];
44/// // do not use this on your code, instead use encrypt fn
45/// let (nonce, encrypted) = encrypt_with_key(&key, b"mensaje").unwrap();
46/// // do not use this on your code, instead use decrypt fn
47/// let decrypted_text = decrypt_with_key(&key, &nonce, &encrypted).unwrap();
48/// ```
49///
50/// # Errores
51/// - Key ≠ 32 bytes or nonce ≠ 12 bytes
52/// - Failed auth or corruption on the data
53pub fn decrypt_with_key(key: &[u8; 32], nonce: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>> {
54 let mut cipher = ChaCha20Poly1305::new_from_slice(key).context("Invalid key length")?;
55
56 let nonce = Nonce::from_slice(nonce);
57 let mut buffer = ciphertext.to_vec();
58
59 cipher
60 .decrypt_in_place(nonce, b"", &mut buffer)
61 .map_err(|e| anyhow!("Decryption failed: {}", e))?;
62
63 Ok(buffer)
64}