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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
pub use aead::{self, Aead, AeadCore, AeadInPlace, Error, NewAead, Payload};
use aead::{
consts::{U0, U12, U16, U32},
generic_array::GenericArray,
};
use hacspec_chacha20::{ChaChaIV as IV, ChaChaKey as HacspecKey};
use hacspec_chacha20poly1305::*;
use hacspec_lib::prelude::*;
use hacspec_poly1305::Poly1305Tag as HacspecTag;
pub struct Chacha20Poly1305 {
key: Key,
}
pub type Key = GenericArray<u8, U32>;
pub type Nonce = GenericArray<u8, U12>;
pub type Tag = GenericArray<u8, U16>;
impl NewAead for Chacha20Poly1305 {
type KeySize = U32;
fn new(key: &Key) -> Self {
Self { key: *key }
}
}
impl AeadCore for Chacha20Poly1305 {
type NonceSize = U12;
type TagSize = U16;
type CiphertextOverhead = U0;
}
impl AeadInPlace for Chacha20Poly1305 {
fn encrypt_in_place_detached(
&self,
nonce: &Nonce,
associated_data: &[u8],
buffer: &mut [u8],
) -> Result<Tag, Error> {
let nonce = IV::from_public_slice(&(nonce.as_slice()));
let key = HacspecKey::from_public_slice(&self.key.as_slice());
let (ctxt, tag) = chacha20_poly1305_encrypt(
key,
nonce,
&ByteSeq::from_public_slice(&associated_data),
&ByteSeq::from_public_slice(buffer),
);
buffer
.iter_mut()
.zip(ctxt.iter())
.for_each(|(dst, &src)| *dst = src.declassify());
let tag = Tag::clone_from_slice(&tag.iter().map(|&b| b.declassify()).collect::<Vec<u8>>());
Ok(tag)
}
fn decrypt_in_place_detached(
&self,
nonce: &Nonce,
associated_data: &[u8],
buffer: &mut [u8],
tag: &Tag,
) -> Result<(), Error> {
let ptxt = chacha20_poly1305_decrypt(
HacspecKey::from_public_slice(self.key.as_slice()),
IV::from_public_slice(nonce),
&ByteSeq::from_public_slice(associated_data),
&ByteSeq::from_public_slice(buffer),
HacspecTag::from_public_slice(tag),
);
match ptxt {
Ok(ptxt) => {
buffer
.iter_mut()
.zip(ptxt.iter())
.for_each(|(dst, &src)| *dst = src.declassify());
Ok(())
}
Err(_) => Err(Error),
}
}
}