literate_crypto/cipher/block/modes/
ctr.rs1use {
2 crate::{BlockEncrypt, BlockMode, Cipher, CipherDecrypt, CipherEncrypt, OneTimePad},
3 docext::docext,
4 std::{convert::Infallible, fmt, iter, mem},
5};
6
7#[docext]
37#[derive(Debug, Clone)]
38pub struct Ctr<Enc> {
39 enc: Enc,
40 nonce: u64,
41}
42
43impl<Enc> Cipher for Ctr<Enc>
44where
45 Enc: BlockEncrypt,
46 Enc::EncryptionBlock: IntoIterator<Item = u8> + AsMut<[u8]> + Default,
47 Enc::EncryptionKey: 'static + Clone,
48{
49 type Key = Enc::EncryptionKey;
50}
51
52impl<Enc> BlockMode for Ctr<Enc>
53where
54 Enc: BlockEncrypt,
55 Enc::EncryptionBlock: IntoIterator<Item = u8> + AsMut<[u8]> + Default,
56 Enc::EncryptionKey: 'static + Clone,
57{
58}
59
60impl<Enc, const BLOCK_SIZE: usize> Ctr<Enc>
61where
62 Enc: BlockEncrypt<EncryptionBlock = [u8; BLOCK_SIZE]>,
63{
64 pub fn new(enc: Enc, nonce: u64) -> Result<Self, BlockSizeTooSmall> {
65 if BLOCK_SIZE < mem::size_of_val(&nonce) {
66 Err(BlockSizeTooSmall)
67 } else {
68 Ok(Self { enc, nonce })
69 }
70 }
71}
72
73impl<Enc> CipherEncrypt for Ctr<Enc>
74where
75 Enc: BlockEncrypt,
76 Enc::EncryptionBlock: IntoIterator<Item = u8> + AsMut<[u8]> + Default,
77 Enc::EncryptionKey: 'static + Clone,
78{
79 type EncryptionErr = Infallible;
80 type EncryptionKey = Enc::EncryptionKey;
81
82 fn encrypt(
83 &self,
84 data: Vec<u8>,
85 key: Self::EncryptionKey,
86 ) -> Result<Vec<u8>, Self::EncryptionErr> {
87 Ok(OneTimePad::default()
88 .encrypt(data, keystream(&self.enc, key, self.nonce))
89 .expect("infinite keystream"))
90 }
91}
92
93impl<Enc> CipherDecrypt for Ctr<Enc>
94where
95 Enc: BlockEncrypt,
96 Enc::EncryptionBlock: IntoIterator<Item = u8> + AsMut<[u8]> + Default,
97 Enc::EncryptionKey: 'static + Clone,
98{
99 type DecryptionErr = Infallible;
100 type DecryptionKey = Enc::EncryptionKey;
101
102 fn decrypt(
103 &self,
104 data: Vec<u8>,
105 key: Self::DecryptionKey,
106 ) -> Result<Vec<u8>, Self::DecryptionErr> {
107 Ok(OneTimePad::default()
108 .decrypt(data, keystream(&self.enc, key, self.nonce))
109 .expect("infinite keystream"))
110 }
111}
112
113fn keystream<Enc>(enc: &Enc, key: Enc::EncryptionKey, nonce: u64) -> impl Iterator<Item = u8> + '_
114where
115 Enc: BlockEncrypt,
116 Enc::EncryptionBlock: IntoIterator<Item = u8> + AsMut<[u8]> + Default,
117 Enc::EncryptionKey: 'static + Clone,
118{
119 iter::successors(Some(nonce), |ctr| Some(ctr.wrapping_add(1))).flat_map(move |ctr| {
120 let mut ctr_block = Enc::EncryptionBlock::default();
122 ctr_block
123 .as_mut()
124 .iter_mut()
125 .zip(ctr.to_le_bytes())
126 .for_each(|(b, n)| *b = n);
127 enc.encrypt(ctr_block, key.clone()).into_iter()
128 })
129}
130
131#[derive(Debug)]
132pub struct BlockSizeTooSmall;
133
134impl fmt::Display for BlockSizeTooSmall {
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 f.write_str("block size too small to fit counter")
137 }
138}