Skip to main content

crypto_dispatch/algorithms/
chacha20_poly1305.rs

1// SPDX-FileCopyrightText: Copyright © 2026 ReallyMe LLC. All rights reserved
2//
3// SPDX-License-Identifier: Apache-2.0
4
5use zeroize::Zeroizing;
6
7use crate::traits::{AeadCipherAlgorithm, AeadParams};
8use crate::AlgorithmError;
9use crypto_core::AeadAlgorithm;
10
11/// ChaCha20-Poly1305 AEAD adapter.
12pub struct ChaCha20Poly1305Algo;
13
14impl AeadCipherAlgorithm for ChaCha20Poly1305Algo {
15    const ALG: AeadAlgorithm = AeadAlgorithm::ChaCha20Poly1305;
16
17    fn encrypt(params: &AeadParams<'_>, plaintext: &[u8]) -> Result<Vec<u8>, AlgorithmError> {
18        #[cfg(any(feature = "native", feature = "wasm"))]
19        {
20            let key = crypto_chacha20_poly1305::ChaCha20Poly1305Key::from_slice(params.key)?;
21            let nonce = crypto_chacha20_poly1305::ChaCha20Poly1305Nonce::from_slice(params.nonce)?;
22            let request = crypto_chacha20_poly1305::EncryptRequest {
23                key: &key,
24                nonce,
25                aad: params.aad,
26                plaintext,
27            };
28            let sealed = crypto_chacha20_poly1305::encrypt(&request)?;
29            Ok(sealed.into_vec())
30        }
31
32        #[cfg(not(any(feature = "native", feature = "wasm")))]
33        {
34            let _ = (params, plaintext);
35            Err(AlgorithmError::UnsupportedAeadAlgorithm(Self::ALG))
36        }
37    }
38
39    fn decrypt(
40        params: &AeadParams<'_>,
41        ciphertext_with_tag: &[u8],
42    ) -> Result<Zeroizing<Vec<u8>>, AlgorithmError> {
43        #[cfg(any(feature = "native", feature = "wasm"))]
44        {
45            let key = crypto_chacha20_poly1305::ChaCha20Poly1305Key::from_slice(params.key)?;
46            let nonce = crypto_chacha20_poly1305::ChaCha20Poly1305Nonce::from_slice(params.nonce)?;
47            let ciphertext = crypto_chacha20_poly1305::CiphertextWithTag::from_vec(
48                ciphertext_with_tag.to_vec(),
49            )?;
50            let request = crypto_chacha20_poly1305::DecryptRequest {
51                key: &key,
52                nonce,
53                aad: params.aad,
54                ciphertext: &ciphertext,
55            };
56            let plaintext = crypto_chacha20_poly1305::decrypt(&request)?;
57            Ok(Zeroizing::new(plaintext))
58        }
59
60        #[cfg(not(any(feature = "native", feature = "wasm")))]
61        {
62            let _ = (params, ciphertext_with_tag);
63            Err(AlgorithmError::UnsupportedAeadAlgorithm(Self::ALG))
64        }
65    }
66}
67
68/// XChaCha20-Poly1305 AEAD adapter.
69pub struct XChaCha20Poly1305Algo;
70
71impl AeadCipherAlgorithm for XChaCha20Poly1305Algo {
72    const ALG: AeadAlgorithm = AeadAlgorithm::XChaCha20Poly1305;
73
74    fn encrypt(params: &AeadParams<'_>, plaintext: &[u8]) -> Result<Vec<u8>, AlgorithmError> {
75        #[cfg(any(feature = "native", feature = "wasm"))]
76        {
77            let key = crypto_chacha20_poly1305::ChaCha20Poly1305Key::from_slice(params.key)?;
78            let nonce = crypto_chacha20_poly1305::XChaCha20Poly1305Nonce::from_slice(params.nonce)?;
79            let request = crypto_chacha20_poly1305::XChaCha20Poly1305EncryptRequest {
80                key: &key,
81                nonce,
82                aad: params.aad,
83                plaintext,
84            };
85            let sealed = crypto_chacha20_poly1305::encrypt_xchacha20_poly1305(&request)?;
86            Ok(sealed.into_vec())
87        }
88
89        #[cfg(not(any(feature = "native", feature = "wasm")))]
90        {
91            let _ = (params, plaintext);
92            Err(AlgorithmError::UnsupportedAeadAlgorithm(Self::ALG))
93        }
94    }
95
96    fn decrypt(
97        params: &AeadParams<'_>,
98        ciphertext_with_tag: &[u8],
99    ) -> Result<Zeroizing<Vec<u8>>, AlgorithmError> {
100        #[cfg(any(feature = "native", feature = "wasm"))]
101        {
102            let key = crypto_chacha20_poly1305::ChaCha20Poly1305Key::from_slice(params.key)?;
103            let nonce = crypto_chacha20_poly1305::XChaCha20Poly1305Nonce::from_slice(params.nonce)?;
104            let ciphertext = crypto_chacha20_poly1305::CiphertextWithTag::from_vec(
105                ciphertext_with_tag.to_vec(),
106            )?;
107            let request = crypto_chacha20_poly1305::XChaCha20Poly1305DecryptRequest {
108                key: &key,
109                nonce,
110                aad: params.aad,
111                ciphertext: &ciphertext,
112            };
113            let plaintext = crypto_chacha20_poly1305::decrypt_xchacha20_poly1305(&request)?;
114            Ok(Zeroizing::new(plaintext))
115        }
116
117        #[cfg(not(any(feature = "native", feature = "wasm")))]
118        {
119            let _ = (params, ciphertext_with_tag);
120            Err(AlgorithmError::UnsupportedAeadAlgorithm(Self::ALG))
121        }
122    }
123}