1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use chacha20poly1305::{
aead::{self, generic_array::typenum::Unsigned, Aead, NewAead},
ChaChaPoly1305,
};
use hkdf::Hkdf;
use sha2::Sha256;
pub fn aead_encrypt(key: &[u8; 32], plaintext: &[u8]) -> Vec<u8> {
let c = ChaChaPoly1305::<c2_chacha::Ietf>::new(key.into());
c.encrypt(&[0; 12].into(), plaintext)
.expect("we won't overflow the ChaCha20 block counter")
}
pub fn aead_decrypt(
key: &[u8; 32],
size: usize,
ciphertext: &[u8],
) -> Result<Vec<u8>, aead::Error> {
if ciphertext.len() != size + <ChaChaPoly1305<c2_chacha::Ietf> as Aead>::TagSize::to_usize() {
return Err(aead::Error);
}
let c = ChaChaPoly1305::<c2_chacha::Ietf>::new(key.into());
c.decrypt(&[0; 12].into(), ciphertext)
}
pub fn hkdf(salt: &[u8], label: &[u8], ikm: &[u8]) -> [u8; 32] {
let mut okm = [0; 32];
Hkdf::<Sha256>::new(Some(salt), ikm)
.expand(label, &mut okm)
.expect("okm is the correct length");
okm
}
#[cfg(test)]
mod tests {
use super::{aead_decrypt, aead_encrypt};
#[test]
fn aead_round_trip() {
let key = [14; 32];
let plaintext = b"12345678";
let encrypted = aead_encrypt(&key, plaintext);
let decrypted = aead_decrypt(&key, plaintext.len(), &encrypted).unwrap();
assert_eq!(decrypted, plaintext);
}
}