chacha20_poly1305_stream/
lib.rs1#![warn(missing_docs)]
27
28#![cfg_attr(feature = "clippy", feature(plugin))]
29#![cfg_attr(feature = "clippy", plugin(clippy))]
30#![cfg_attr(feature = "clippy", warn(clippy_pedantic))]
31
32#![cfg_attr(all(feature = "bench", test), feature(test))]
33#![cfg_attr(feature = "simd", feature(platform_intrinsics, repr_simd))]
34#![cfg_attr(feature = "simd_opt", feature(cfg_target_feature))]
35
36extern crate constant_time_eq;
37#[cfg(all(feature = "bench", test))]
38extern crate test;
39
40pub use stream_decryptor::ChaCha20Poly1305StreamDecryptor;
41pub use stream_encryptor::ChaCha20Poly1305StreamEncryptor;
42
43mod as_bytes;
44
45mod simdty;
46mod simdint;
47mod simdop;
48mod simd_opt;
49mod simd;
50
51mod chacha20;
52mod poly1305;
53mod stream_util;
55mod stream_encryptor;
56mod stream_decryptor;
57
58pub fn chacha20_poly1305_encrypt(key: &[u8], nonce: &[u8], message: &[u8]) -> Result<Vec<u8>, String> {
60 chacha20_poly1305_aad_encrypt(key, nonce, &[], message)
61}
62
63pub fn chacha20_poly1305_decrypt(key: &[u8], nonce: &[u8], message: &[u8]) -> Result<Vec<u8>, String> {
65 chacha20_poly1305_aad_decrypt(key, nonce, &[], message)
66}
67
68pub fn chacha20_poly1305_aad_encrypt(key: &[u8], nonce: &[u8], aad: &[u8], message: &[u8]) -> Result<Vec<u8>, String> {
70 let mut encryptor = ChaCha20Poly1305StreamEncryptor::new(key, nonce)?;
71 if !aad.is_empty() { encryptor.init_adata(aad); }
72 let mut b1 = encryptor.update(message);
73 let (last_block, tag) = encryptor.finalize();
74 b1.extend_from_slice(&last_block);
75 b1.extend_from_slice(&tag);
76 Ok(b1)
77}
78
79pub fn chacha20_poly1305_aad_decrypt(key: &[u8], nonce: &[u8], aad: &[u8], message: &[u8]) -> Result<Vec<u8>, String> {
81 let mut decryptor = ChaCha20Poly1305StreamDecryptor::new(key, nonce)?;
82 if !aad.is_empty() { decryptor.init_adata(aad); }
83 let mut b1 = decryptor.update(message);
84 let last_block = decryptor.finalize()?;
85 b1.extend_from_slice(&last_block);
86 Ok(b1)
87}
88
89#[cold]
91pub fn selftest() {
92 chacha20::selftest();
93 poly1305::selftest();
94}
95
96#[test]
97fn test_enc_dec() {
98 let key = [0u8; 32];
99 let nonce = [0u8; 12];
100 let aad = b"hello world";
101 let plaintext = [0u8; 1000];
102
103 let ciphertext = chacha20_poly1305_aad_encrypt(&key, &nonce, aad, &plaintext).unwrap();
104
105 let mut output = vec![];
106 let mut plaintext = plaintext.to_vec();
107 let tag = chacha20_poly1305_aead::encrypt(
108 &key, &nonce, &aad[..], &mut plaintext, &mut output).unwrap();
109 output.extend_from_slice(&tag);
110
111 assert_eq!(ciphertext, output);
112
113 let plaintext_decrypted = chacha20_poly1305_aad_decrypt(&key, &nonce, aad, &ciphertext).unwrap();
114 assert_eq!(plaintext, plaintext_decrypted);
115}
116
117#[test]
118fn test_rfc_7539() {
119 let key = hex::decode(
120 "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f").unwrap();
121 let nonce = hex::decode("070000004041424344454647").unwrap();
122 let aad = hex::decode("50515253c0c1c2c3c4c5c6c7").unwrap();
123 let plaintext = hex::decode(
124 "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f6620\
125 2739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666\
126 f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e").unwrap();
127
128 let expected_ciphertext = hex::decode(
129 "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca\
130 9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091\
131 b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116").unwrap();
132 let expected_tag = hex::decode("1ae10b594f09e26a7e902ecbd0600691").unwrap();
133
134 let mut encryptor = ChaCha20Poly1305StreamEncryptor::new(&key, &nonce).unwrap();
135 encryptor.init_adata(&aad);
136 let mut ciphertext = encryptor.update(&plaintext);
137 let (last_block, tag) = encryptor.finalize();
138 ciphertext.extend_from_slice(&last_block);
139
140 assert_eq!(expected_ciphertext, ciphertext);
141 assert_eq!(expected_tag, tag);
142}