vitaminc_aead/ciphertext/
mod.rs

1mod read_monads;
2mod write_monads;
3use bytes::Bytes;
4use read_monads::CipherTextReader;
5use serde::{Deserialize, Serialize};
6pub use write_monads::CipherTextBuilder;
7
8#[derive(Debug, Serialize, Deserialize)]
9#[serde(transparent)]
10pub struct LocalCipherText(Bytes);
11
12impl LocalCipherText {
13    pub fn into_inner(self) -> Bytes {
14        self.0
15    }
16
17    pub fn into_reader(self) -> CipherTextReader {
18        CipherTextReader::new(self.0)
19    }
20}
21
22impl AsRef<[u8]> for LocalCipherText {
23    fn as_ref(&self) -> &[u8] {
24        self.0.as_ref()
25    }
26}
27
28impl From<Vec<u8>> for LocalCipherText {
29    fn from(bytes: Vec<u8>) -> Self {
30        LocalCipherText(Bytes::from(bytes))
31    }
32}
33
34#[cfg(test)]
35mod tests {
36    use super::*;
37    use crate::Nonce;
38    use vitaminc_protected::{Controlled, Protected};
39
40    #[test]
41    fn test_ciphertext_builder_with_plaintext_in_place() -> Result<(), ()> {
42        let nonce = Nonce::new([1u8; 12]);
43        let plaintext = vec![0u8; 10];
44        let ciphertext = CipherTextBuilder::new()
45            .append_nonce(nonce)
46            .append_target_plaintext(plaintext)
47            .accepts_ciphertext_and_tag_ok(|mut ciphertext| {
48                ciphertext.copy_from_slice(&[2u8; 10]);
49                ciphertext.extend([3u8; 16]);
50                Ok(ciphertext)
51            })
52            .build()?;
53
54        assert_eq!(ciphertext.0.len(), 38);
55        assert_eq!(&ciphertext.0[..12], &[1u8; 12]);
56        assert_eq!(&ciphertext.0[12..22], &[2u8; 10]);
57        assert_eq!(&ciphertext.0[22..], &[3u8; 16]);
58
59        Ok(())
60    }
61
62    #[test]
63    fn test_ciphertext_reader() -> Result<(), ()> {
64        let nonce = Nonce::new([1u8; 12]);
65        let plaintext: Protected<Vec<u8>> = Protected::new(vec![0u8; 10]);
66
67        let ciphertext = CipherTextBuilder::new()
68            .append_nonce(nonce)
69            .append_target_plaintext(plaintext)
70            .accepts_ciphertext_and_tag_ok(|mut ciphertext| {
71                ciphertext.copy_from_slice(&[2u8; 10]);
72                ciphertext.extend([3u8; 16]);
73                Ok(ciphertext)
74            })
75            .build()?;
76
77        let (nonce, reader) = ciphertext.into_reader().read_nonce::<12>();
78
79        let plaintext = reader
80            .accepts_plaintext_ok(|data| {
81                assert_eq!(data.len(), 26);
82                assert_eq!(&data[..10], [2u8; 10]);
83                assert_eq!(&data[10..], [3u8; 16]);
84                // Write in the same way as AWS-LC/Ring does
85                data[..10].copy_from_slice(&[0u8; 10]);
86                Ok(10)
87            })
88            .read()?;
89
90        assert_eq!(nonce.into_inner(), [1u8; 12]);
91        assert_eq!(plaintext.risky_unwrap()[..10], vec![0u8; 10]);
92
93        Ok(())
94    }
95}