Skip to main content

starkom_poseidon2/
cipher.rs

1use crate::poseidon::{Config, permutation};
2use anyhow::{Result, anyhow};
3use primitive_types::H512;
4use sha3::{self, Digest};
5use starkom_ff::PrimeField256;
6use std::marker::PhantomData;
7
8fn iv_element<F: PrimeField256>(index: usize) -> F {
9    let mut hasher = sha3::Sha3_512::new();
10    hasher.update(format!("starkom/poseidon/cipher/{}", index).as_bytes());
11    F::from_h512(H512::from_slice(hasher.finalize().as_slice()))
12}
13
14fn get_initial_state<F: PrimeField256, const T: usize, const R: usize>(key: F, nonce: F) -> [F; T] {
15    let mut state = [F::ZERO; T];
16    for i in 0..R {
17        state[i] = iv_element::<F>(i) + nonce;
18    }
19    state[T - 1] = key;
20    state
21}
22
23/// Encrypts an arbitrary number of field elements in batches of `R` using the Poseidon permutation
24/// with state size `T`.
25///
26/// `R` must be `T - 1` (the last element is reserved for capacity).
27///
28/// This symmetric cipher is implemented using the Poseidon PRP as a block cipher in duplex sponge
29/// mode, which is similar to CFB. The key lives in the capacity element.
30#[derive(Debug)]
31pub struct Encryptor<C: Config<F, T>, F: PrimeField256, const T: usize, const R: usize> {
32    nonce: F,
33    state: [F; T],
34    _data: PhantomData<C>,
35}
36
37impl<C: Config<F, T>, F: PrimeField256, const T: usize, const R: usize> Encryptor<C, F, T, R> {
38    /// Constructs an `Encryptor` with the specified `key` and `nonce`.
39    ///
40    /// WARNING: NEVER reuse the same (key, nonce) pair to encrypt two or more different messages,
41    /// as doing so would leak information about the plaintexts!
42    pub fn with_nonce(key: F, nonce: F) -> Self {
43        assert_eq!(R, T - 1);
44        Self {
45            nonce,
46            state: get_initial_state::<F, T, R>(key, nonce),
47            _data: PhantomData::default(),
48        }
49    }
50
51    /// Constructs an `Encryptor` with the specified `key` and a securely generated fresh nonce.
52    ///
53    /// You can retrieve the nonce by calling [`Self::nonce`].
54    pub fn new(key: F) -> Self {
55        Self::with_nonce(key, F::random_default())
56    }
57
58    /// Returns the nonce used by the `Encryptor`.
59    ///
60    /// This can be transmitted publicly along with the ciphertext and will be needed to construct
61    /// the [`Decryptor`].
62    pub fn nonce(&self) -> F {
63        self.nonce
64    }
65
66    /// Encrypts a block of `R` field elements.
67    pub fn encrypt(&mut self, block: [F; R]) -> [F; R] {
68        self.state = permutation::<C, F, T>(self.state);
69        for i in 0..R {
70            self.state[i] += block[i];
71        }
72        std::array::from_fn(|i| self.state[i])
73    }
74
75    /// Performs the final checksumming.
76    pub fn finalize(mut self) -> F {
77        self.state = permutation::<C, F, T>(self.state);
78        self.state[T - 1]
79    }
80}
81
82/// Decrypts an arbitrary number of field elements in batches of `R` using the Poseidon permutation
83/// with state size `T`.
84///
85/// `R` must be `T - 1` (the last element is reserved for capacity).
86///
87/// This symmetric cipher is implemented using the Poseidon PRP as a block cipher in duplex sponge
88/// mode, which is similar to CFB. The key lives in the capacity element.
89#[derive(Debug)]
90pub struct Decryptor<C: Config<F, T>, F: PrimeField256, const T: usize, const R: usize> {
91    state: [F; T],
92    _data: PhantomData<C>,
93}
94
95impl<C: Config<F, T>, F: PrimeField256, const T: usize, const R: usize> Decryptor<C, F, T, R> {
96    /// Constructs a `Decryptor` with the specified `key` and `nonce`.
97    pub fn new(key: F, nonce: F) -> Self {
98        assert_eq!(R, T - 1);
99        Self {
100            state: get_initial_state::<F, T, R>(key, nonce),
101            _data: PhantomData::default(),
102        }
103    }
104
105    /// Decrypts a block of `R` field elements.
106    pub fn decrypt(&mut self, mut block: [F; R]) -> [F; R] {
107        self.state = permutation::<C, F, T>(self.state);
108        for i in 0..R {
109            let key = self.state[i];
110            self.state[i] = block[i];
111            block[i] -= key;
112        }
113        block
114    }
115
116    /// Performs the final authentication.
117    pub fn finalize(mut self, checksum: F) -> Result<()> {
118        self.state = permutation::<C, F, T>(self.state);
119        if self.state[T - 1].ct_ne(&checksum).into() {
120            return Err(anyhow!("invalid checksum {}", checksum));
121        }
122        Ok(())
123    }
124}
125
126#[cfg(test)]
127mod tests {
128    use super::*;
129    use crate::bluesky::{BlueSkyConfig3, BlueSkyConfig4};
130    use starkom_bluesky::{Scalar, from_const, parse_scalar};
131
132    fn key1() -> Scalar {
133        parse_scalar("0x1a06314aa2caec8bb0b56bee3c47cf459318e72181320ac9d1f3199c1704b236")
134    }
135
136    fn key2() -> Scalar {
137        parse_scalar("0x02084699c3ba63bf94afa8d0830338aa8c16087f8587517d29748744a6606101")
138    }
139
140    #[test]
141    fn test_encrypt_one_block_t3_key1() {
142        let key = key1();
143        let nonce = from_const(42);
144        let mut encryptor = Encryptor::<BlueSkyConfig3, Scalar, 3, 2>::with_nonce(key, nonce);
145        let block = encryptor.encrypt([from_const(12), from_const(34)]);
146        let checksum = encryptor.finalize();
147        assert_eq!(
148            block,
149            [
150                parse_scalar("0x517b930ab3b2a386dc4d12d0bb7ad791fbedc97fe1efa5f1b9973da58119611a"),
151                parse_scalar("0x543e4f94b8d8a4268890523ced9d826318a9d21ccb347548a97621546d8f0dc2")
152            ]
153        );
154        assert_eq!(
155            checksum,
156            parse_scalar("0x5b6391b694f558e11ddaad4a677d08925cfd111ea23249cc8d1872bfc3a99994")
157        );
158    }
159
160    #[test]
161    fn test_encrypt_one_block_t3_key2() {
162        let key = key2();
163        let nonce = from_const(42);
164        let mut encryptor = Encryptor::<BlueSkyConfig3, Scalar, 3, 2>::with_nonce(key, nonce);
165        let block = encryptor.encrypt([from_const(12), from_const(34)]);
166        let checksum = encryptor.finalize();
167        assert_eq!(
168            block,
169            [
170                parse_scalar("0x1c673a9c9d388a227b8662b85ff9b54daca3d0d9276b53e1a76ccee13ae622bf"),
171                parse_scalar("0x7f299cd405489e55c46f2924202c99241eb461e4fc94ceaec16e03f969c428c0")
172            ]
173        );
174        assert_eq!(
175            checksum,
176            parse_scalar("0x226a7e017bb1d16d0ae023561228fe28916c0355350b0b79e735797afe369d9d")
177        );
178    }
179
180    #[test]
181    fn test_encrypt_one_block_t3_different_nonces() {
182        let key = key1();
183        let mut encryptor1 = Encryptor::<BlueSkyConfig3, Scalar, 3, 2>::new(key);
184        let block1 = encryptor1.encrypt([from_const(12), from_const(34)]);
185        let checksum1 = encryptor1.finalize();
186        let mut encryptor2 = Encryptor::<BlueSkyConfig3, Scalar, 3, 2>::new(key);
187        let block2 = encryptor2.encrypt([from_const(12), from_const(34)]);
188        let checksum2 = encryptor2.finalize();
189        assert_ne!(block1, block2);
190        assert_ne!(checksum1, checksum2);
191    }
192
193    #[test]
194    fn test_encrypt_two_blocks_t3_key1() {
195        let key = key1();
196        let nonce = from_const(42);
197        let mut encryptor = Encryptor::<BlueSkyConfig3, Scalar, 3, 2>::with_nonce(key, nonce);
198        let block1 = encryptor.encrypt([from_const(34), from_const(56)]);
199        let block2 = encryptor.encrypt([from_const(78), from_const(90)]);
200        let checksum = encryptor.finalize();
201        assert_eq!(
202            block1,
203            [
204                parse_scalar("0x517b930ab3b2a386dc4d12d0bb7ad791fbedc97fe1efa5f1b9973da581196130"),
205                parse_scalar("0x543e4f94b8d8a4268890523ced9d826318a9d21ccb347548a97621546d8f0dd8")
206            ]
207        );
208        assert_eq!(
209            block2,
210            [
211                parse_scalar("0x71277f403f436a8e360a10d242fdad26ca65caf5cc0076ff92c07b81ec9c396d"),
212                parse_scalar("0x2036c558e00f301f5c355c2b8e8e2d6b932fddc8d383d3bae9a75a9dabd6f7c5")
213            ]
214        );
215        assert_eq!(
216            checksum,
217            parse_scalar("0x3d5bb7eba76c1e722c80915577d8f55e5b50a5ccae43c45381779c7cdf989a60")
218        );
219    }
220
221    #[test]
222    fn test_encrypt_two_blocks_t3_key2() {
223        let key = key2();
224        let nonce = from_const(42);
225        let mut encryptor = Encryptor::<BlueSkyConfig3, Scalar, 3, 2>::with_nonce(key, nonce);
226        let block1 = encryptor.encrypt([from_const(34), from_const(56)]);
227        let block2 = encryptor.encrypt([from_const(78), from_const(90)]);
228        let checksum = encryptor.finalize();
229        assert_eq!(
230            block1,
231            [
232                parse_scalar("0x1c673a9c9d388a227b8662b85ff9b54daca3d0d9276b53e1a76ccee13ae622d5"),
233                parse_scalar("0x7f299cd405489e55c46f2924202c99241eb461e4fc94ceaec16e03f969c428d6")
234            ]
235        );
236        assert_eq!(
237            block2,
238            [
239                parse_scalar("0x560a95e67eabeaeec74d5c178b57d2794c7b75b0d4d51a98f41f2f22da5da7bf"),
240                parse_scalar("0x7f26d8b7e713a10ae871c1e8fa401c6fb5056181352dc2665389df962bc1746f")
241            ]
242        );
243        assert_eq!(
244            checksum,
245            parse_scalar("0x18c0c56f25355b3af90260075a31df63af7a08903c64f74626663e27bc92b254")
246        );
247    }
248
249    #[test]
250    fn test_encrypt_two_blocks_t3_different_nonces() {
251        let key = key1();
252        let mut encryptor1 = Encryptor::<BlueSkyConfig3, Scalar, 3, 2>::new(key);
253        let block11 = encryptor1.encrypt([from_const(34), from_const(56)]);
254        let block12 = encryptor1.encrypt([from_const(78), from_const(90)]);
255        let checksum1 = encryptor1.finalize();
256        let mut encryptor2 = Encryptor::<BlueSkyConfig3, Scalar, 3, 2>::new(key);
257        let block21 = encryptor2.encrypt([from_const(34), from_const(56)]);
258        let block22 = encryptor2.encrypt([from_const(78), from_const(90)]);
259        let checksum2 = encryptor2.finalize();
260        assert_ne!(block11, block21);
261        assert_ne!(block12, block22);
262        assert_ne!(checksum1, checksum2);
263    }
264
265    #[test]
266    fn test_encrypt_one_block_t4_key1() {
267        let key = key1();
268        let nonce = from_const(42);
269        let mut encryptor = Encryptor::<BlueSkyConfig4, Scalar, 4, 3>::with_nonce(key, nonce);
270        let block = encryptor.encrypt([from_const(12), from_const(34), from_const(56)]);
271        let checksum = encryptor.finalize();
272        assert_eq!(
273            block,
274            [
275                parse_scalar("0x697acc6998455b102280a6197bf54d75cf403bfc3fde514fcb4db16d9abad8d6"),
276                parse_scalar("0x20881f62c68cf86615d6da56bf25a0de6a1389e81f05747fc2cd380b4c3f79a9"),
277                parse_scalar("0x5b71078ecb5a379b4024fed43d3cb4589cbead9951cd322271a80f1b42ddc338")
278            ]
279        );
280        assert_eq!(
281            checksum,
282            parse_scalar("0x6f5cfb84280a92e1c21cb784b4c309fd2d5e616c9871f10562051f43c189ab9e")
283        );
284    }
285
286    #[test]
287    fn test_encrypt_one_block_t4_key2() {
288        let key = key2();
289        let nonce = from_const(42);
290        let mut encryptor = Encryptor::<BlueSkyConfig4, Scalar, 4, 3>::with_nonce(key, nonce);
291        let block = encryptor.encrypt([from_const(12), from_const(34), from_const(56)]);
292        let checksum = encryptor.finalize();
293        assert_eq!(
294            block,
295            [
296                parse_scalar("0x63e00ef04a2b788de94cd0a9c2bf95b84c24842739cb242027d4697405271193"),
297                parse_scalar("0x5affa0dfe232d32a1562f92f29c1b2b2c41634bf780a65bfde1da41e8a171e89"),
298                parse_scalar("0x663685c0033b4ad98ad30accb5843d04205cefcfed2c2db31433173c6785e905")
299            ]
300        );
301        assert_eq!(
302            checksum,
303            parse_scalar("0x69c5e38879841004f277b589fe7ca54fdc64ab735b7e810d583e3ff2ba13a627")
304        );
305    }
306
307    #[test]
308    fn test_encrypt_one_block_t4_different_nonces() {
309        let key = key1();
310        let mut encryptor1 = Encryptor::<BlueSkyConfig4, Scalar, 4, 3>::new(key);
311        let block1 = encryptor1.encrypt([from_const(12), from_const(34), from_const(56)]);
312        let checksum1 = encryptor1.finalize();
313        let mut encryptor2 = Encryptor::<BlueSkyConfig4, Scalar, 4, 3>::new(key);
314        let block2 = encryptor2.encrypt([from_const(12), from_const(34), from_const(56)]);
315        let checksum2 = encryptor2.finalize();
316        assert_ne!(block1, block2);
317        assert_ne!(checksum1, checksum2);
318    }
319
320    #[test]
321    fn test_encrypt_two_blocks_t4_key1() {
322        let key = key1();
323        let nonce = from_const(42);
324        let mut encryptor = Encryptor::<BlueSkyConfig4, Scalar, 4, 3>::with_nonce(key, nonce);
325        let block1 = encryptor.encrypt([from_const(34), from_const(56), from_const(78)]);
326        let block2 = encryptor.encrypt([from_const(90), from_const(112), from_const(134)]);
327        let checksum = encryptor.finalize();
328        assert_eq!(
329            block1,
330            [
331                parse_scalar("0x697acc6998455b102280a6197bf54d75cf403bfc3fde514fcb4db16d9abad8ec"),
332                parse_scalar("0x20881f62c68cf86615d6da56bf25a0de6a1389e81f05747fc2cd380b4c3f79bf"),
333                parse_scalar("0x5b71078ecb5a379b4024fed43d3cb4589cbead9951cd322271a80f1b42ddc34e")
334            ]
335        );
336        assert_eq!(
337            block2,
338            [
339                parse_scalar("0x21740083f8b867fe8019d70c7b747c510b2781803aabe3b2c5c97e9926e1b0a8"),
340                parse_scalar("0x46c79bf95f11972dda3e0aa33cc6a44de0f1d00f593cb36693c8821b63a9eefe"),
341                parse_scalar("0x1bcd1ec59363c5089ead0cda525aeb540d7f611744aa54d2540b89f112829fe9"),
342            ]
343        );
344        assert_eq!(
345            checksum,
346            parse_scalar("0x4bb9448b23695d5cc8990e21bda2369e75952addb31447210386714a5833bbea")
347        );
348    }
349
350    #[test]
351    fn test_encrypt_two_blocks_t4_key2() {
352        let key = key2();
353        let nonce = from_const(42);
354        let mut encryptor = Encryptor::<BlueSkyConfig4, Scalar, 4, 3>::with_nonce(key, nonce);
355        let block1 = encryptor.encrypt([from_const(34), from_const(56), from_const(78)]);
356        let block2 = encryptor.encrypt([from_const(90), from_const(112), from_const(134)]);
357        let checksum = encryptor.finalize();
358        assert_eq!(
359            block1,
360            [
361                parse_scalar("0x63e00ef04a2b788de94cd0a9c2bf95b84c24842739cb242027d46974052711a9"),
362                parse_scalar("0x5affa0dfe232d32a1562f92f29c1b2b2c41634bf780a65bfde1da41e8a171e9f"),
363                parse_scalar("0x663685c0033b4ad98ad30accb5843d04205cefcfed2c2db31433173c6785e91b")
364            ]
365        );
366        assert_eq!(
367            block2,
368            [
369                parse_scalar("0x7e5da887f98421930029cfb9e3845ce64fb0376e72a614a71bd25a6e9aaa7615"),
370                parse_scalar("0x4b7025a627765857a0a2c8143a10ff69b2cff544a1ed9939f48d9e62fc39eeea"),
371                parse_scalar("0x74a366c61fe140125e7d3275b0f34489e3e1d885a25bc2e8f0f5967da99a2efd")
372            ]
373        );
374        assert_eq!(
375            checksum,
376            parse_scalar("0x0f132cd0744ab5311ae1fff1b8f254fda8c203a0e9d709299ef32c6bafa5d547")
377        );
378    }
379
380    #[test]
381    fn test_encrypt_two_blocks_t4_different_nonces() {
382        let key = key1();
383        let mut encryptor1 = Encryptor::<BlueSkyConfig4, Scalar, 4, 3>::new(key);
384        let block11 = encryptor1.encrypt([from_const(34), from_const(56), from_const(78)]);
385        let block12 = encryptor1.encrypt([from_const(90), from_const(112), from_const(134)]);
386        let checksum1 = encryptor1.finalize();
387        let mut encryptor2 = Encryptor::<BlueSkyConfig4, Scalar, 4, 3>::new(key);
388        let block21 = encryptor2.encrypt([from_const(34), from_const(56), from_const(78)]);
389        let block22 = encryptor2.encrypt([from_const(90), from_const(112), from_const(134)]);
390        let checksum2 = encryptor2.finalize();
391        assert_ne!(block11, block21);
392        assert_ne!(block12, block22);
393        assert_ne!(checksum1, checksum2);
394    }
395
396    #[test]
397    fn test_decrypt_one_block_t3_key1() {
398        let key = key1();
399        let nonce = from_const(42);
400        let mut encryptor = Encryptor::<BlueSkyConfig3, Scalar, 3, 2>::with_nonce(key, nonce);
401        let ciphertext = encryptor.encrypt([from_const(12), from_const(34)]);
402        let checksum = encryptor.finalize();
403        let mut decryptor = Decryptor::<BlueSkyConfig3, Scalar, 3, 2>::new(key, nonce);
404        let plaintext = decryptor.decrypt(ciphertext);
405        assert!(decryptor.finalize(checksum).is_ok());
406        assert_eq!(plaintext, [from_const(12), from_const(34)]);
407    }
408
409    #[test]
410    fn test_decrypt_one_block_t3_key2() {
411        let key = key2();
412        let nonce = from_const(42);
413        let mut encryptor = Encryptor::<BlueSkyConfig3, Scalar, 3, 2>::with_nonce(key, nonce);
414        let ciphertext = encryptor.encrypt([from_const(12), from_const(34)]);
415        let checksum = encryptor.finalize();
416        let mut decryptor = Decryptor::<BlueSkyConfig3, Scalar, 3, 2>::new(key, nonce);
417        let plaintext = decryptor.decrypt(ciphertext);
418        assert!(decryptor.finalize(checksum).is_ok());
419        assert_eq!(plaintext, [from_const(12), from_const(34)]);
420    }
421
422    #[test]
423    fn test_decrypt_one_block_t3_automatic_nonce() {
424        let key = key1();
425        let mut encryptor = Encryptor::<BlueSkyConfig3, Scalar, 3, 2>::new(key);
426        let nonce = encryptor.nonce();
427        let ciphertext = encryptor.encrypt([from_const(12), from_const(34)]);
428        let checksum = encryptor.finalize();
429        let mut decryptor = Decryptor::<BlueSkyConfig3, Scalar, 3, 2>::new(key, nonce);
430        let plaintext = decryptor.decrypt(ciphertext);
431        assert!(decryptor.finalize(checksum).is_ok());
432        assert_eq!(plaintext, [from_const(12), from_const(34)]);
433    }
434
435    #[test]
436    fn test_decrypt_two_blocks_t3_key1() {
437        let key = key1();
438        let nonce = from_const(42);
439        let mut encryptor = Encryptor::<BlueSkyConfig3, Scalar, 3, 2>::with_nonce(key, nonce);
440        let ciphertext1 = encryptor.encrypt([from_const(34), from_const(56)]);
441        let ciphertext2 = encryptor.encrypt([from_const(78), from_const(90)]);
442        let checksum = encryptor.finalize();
443        let mut decryptor = Decryptor::<BlueSkyConfig3, Scalar, 3, 2>::new(key, nonce);
444        let plaintext1 = decryptor.decrypt(ciphertext1);
445        let plaintext2 = decryptor.decrypt(ciphertext2);
446        assert!(decryptor.finalize(checksum).is_ok());
447        assert_eq!(plaintext1, [from_const(34), from_const(56)]);
448        assert_eq!(plaintext2, [from_const(78), from_const(90)]);
449    }
450
451    #[test]
452    fn test_decrypt_two_blocks_t3_key2() {
453        let key = key2();
454        let nonce = from_const(42);
455        let mut encryptor = Encryptor::<BlueSkyConfig3, Scalar, 3, 2>::with_nonce(key, nonce);
456        let ciphertext1 = encryptor.encrypt([from_const(34), from_const(56)]);
457        let ciphertext2 = encryptor.encrypt([from_const(78), from_const(90)]);
458        let checksum = encryptor.finalize();
459        let mut decryptor = Decryptor::<BlueSkyConfig3, Scalar, 3, 2>::new(key, nonce);
460        let plaintext1 = decryptor.decrypt(ciphertext1);
461        let plaintext2 = decryptor.decrypt(ciphertext2);
462        assert!(decryptor.finalize(checksum).is_ok());
463        assert_eq!(plaintext1, [from_const(34), from_const(56)]);
464        assert_eq!(plaintext2, [from_const(78), from_const(90)]);
465    }
466
467    #[test]
468    fn test_decrypt_two_blocks_t3_automatic_nonce() {
469        let key = key1();
470        let mut encryptor = Encryptor::<BlueSkyConfig3, Scalar, 3, 2>::new(key);
471        let nonce = encryptor.nonce();
472        let ciphertext1 = encryptor.encrypt([from_const(34), from_const(56)]);
473        let ciphertext2 = encryptor.encrypt([from_const(78), from_const(90)]);
474        let checksum = encryptor.finalize();
475        let mut decryptor = Decryptor::<BlueSkyConfig3, Scalar, 3, 2>::new(key, nonce);
476        let plaintext1 = decryptor.decrypt(ciphertext1);
477        let plaintext2 = decryptor.decrypt(ciphertext2);
478        assert!(decryptor.finalize(checksum).is_ok());
479        assert_eq!(plaintext1, [from_const(34), from_const(56)]);
480        assert_eq!(plaintext2, [from_const(78), from_const(90)]);
481    }
482
483    #[test]
484    fn test_decrypt_one_block_t4_key1() {
485        let key = key1();
486        let nonce = from_const(42);
487        let mut encryptor = Encryptor::<BlueSkyConfig4, Scalar, 4, 3>::with_nonce(key, nonce);
488        let ciphertext = encryptor.encrypt([from_const(12), from_const(34), from_const(56)]);
489        let checksum = encryptor.finalize();
490        let mut decryptor = Decryptor::<BlueSkyConfig4, Scalar, 4, 3>::new(key, nonce);
491        let plaintext = decryptor.decrypt(ciphertext);
492        assert!(decryptor.finalize(checksum).is_ok());
493        assert_eq!(plaintext, [from_const(12), from_const(34), from_const(56)]);
494    }
495
496    #[test]
497    fn test_decrypt_one_block_t4_key2() {
498        let key = key2();
499        let nonce = from_const(42);
500        let mut encryptor = Encryptor::<BlueSkyConfig4, Scalar, 4, 3>::with_nonce(key, nonce);
501        let ciphertext = encryptor.encrypt([from_const(12), from_const(34), from_const(56)]);
502        let checksum = encryptor.finalize();
503        let mut decryptor = Decryptor::<BlueSkyConfig4, Scalar, 4, 3>::new(key, nonce);
504        let plaintext = decryptor.decrypt(ciphertext);
505        assert!(decryptor.finalize(checksum).is_ok());
506        assert_eq!(plaintext, [from_const(12), from_const(34), from_const(56)]);
507    }
508
509    #[test]
510    fn test_decrypt_one_block_t4_automatic_nonce() {
511        let key = key1();
512        let mut encryptor = Encryptor::<BlueSkyConfig4, Scalar, 4, 3>::new(key);
513        let nonce = encryptor.nonce();
514        let ciphertext = encryptor.encrypt([from_const(12), from_const(34), from_const(56)]);
515        let checksum = encryptor.finalize();
516        let mut decryptor = Decryptor::<BlueSkyConfig4, Scalar, 4, 3>::new(key, nonce);
517        let plaintext = decryptor.decrypt(ciphertext);
518        assert!(decryptor.finalize(checksum).is_ok());
519        assert_eq!(plaintext, [from_const(12), from_const(34), from_const(56)]);
520    }
521
522    #[test]
523    fn test_decrypt_two_blocks_t4_key1() {
524        let key = key1();
525        let nonce = from_const(42);
526        let mut encryptor = Encryptor::<BlueSkyConfig4, Scalar, 4, 3>::with_nonce(key, nonce);
527        let ciphertext1 = encryptor.encrypt([from_const(34), from_const(56), from_const(78)]);
528        let ciphertext2 = encryptor.encrypt([from_const(90), from_const(112), from_const(134)]);
529        let checksum = encryptor.finalize();
530        let mut decryptor = Decryptor::<BlueSkyConfig4, Scalar, 4, 3>::new(key, nonce);
531        let plaintext1 = decryptor.decrypt(ciphertext1);
532        let plaintext2 = decryptor.decrypt(ciphertext2);
533        assert!(decryptor.finalize(checksum).is_ok());
534        assert_eq!(plaintext1, [from_const(34), from_const(56), from_const(78)]);
535        assert_eq!(
536            plaintext2,
537            [from_const(90), from_const(112), from_const(134)]
538        );
539    }
540
541    #[test]
542    fn test_decrypt_two_blocks_t4_key2() {
543        let key = key2();
544        let nonce = from_const(42);
545        let mut encryptor = Encryptor::<BlueSkyConfig4, Scalar, 4, 3>::with_nonce(key, nonce);
546        let ciphertext1 = encryptor.encrypt([from_const(34), from_const(56), from_const(78)]);
547        let ciphertext2 = encryptor.encrypt([from_const(90), from_const(112), from_const(134)]);
548        let checksum = encryptor.finalize();
549        let mut decryptor = Decryptor::<BlueSkyConfig4, Scalar, 4, 3>::new(key, nonce);
550        let plaintext1 = decryptor.decrypt(ciphertext1);
551        let plaintext2 = decryptor.decrypt(ciphertext2);
552        assert!(decryptor.finalize(checksum).is_ok());
553        assert_eq!(plaintext1, [from_const(34), from_const(56), from_const(78)]);
554        assert_eq!(
555            plaintext2,
556            [from_const(90), from_const(112), from_const(134)]
557        );
558    }
559
560    #[test]
561    fn test_decrypt_two_blocks_t4_automatic_nonce() {
562        let key = key1();
563        let mut encryptor = Encryptor::<BlueSkyConfig4, Scalar, 4, 3>::new(key);
564        let nonce = encryptor.nonce();
565        let ciphertext1 = encryptor.encrypt([from_const(34), from_const(56), from_const(78)]);
566        let ciphertext2 = encryptor.encrypt([from_const(90), from_const(112), from_const(134)]);
567        let checksum = encryptor.finalize();
568        let mut decryptor = Decryptor::<BlueSkyConfig4, Scalar, 4, 3>::new(key, nonce);
569        let plaintext1 = decryptor.decrypt(ciphertext1);
570        let plaintext2 = decryptor.decrypt(ciphertext2);
571        assert!(decryptor.finalize(checksum).is_ok());
572        assert_eq!(plaintext1, [from_const(34), from_const(56), from_const(78)]);
573        assert_eq!(
574            plaintext2,
575            [from_const(90), from_const(112), from_const(134)]
576        );
577    }
578}