crypto_permutation/lib.rs
1//! Abstractions for permutation based cryptography in Rust.
2//!
3//! This crate provides abstractions for generic permutation based cryptography.
4//! This allows other crates to build constructions generic over the concrete
5//! cryptographic permutation or a deck-function. The API can be considered to
6//! consist of three main parts:
7//!
8//! 1. Cryptographic IO abstractions
9//! 2. Cryptographic permutation abstraction
10//! 3. Deck function abstraction
11//!
12//! The cryptographic IO abstractions are foundational for this entire crate.
13//! The other abstractions build on top of it.
14//!
15//! # IO
16//! The cryptographic IO abstractions give generic ways to input data into
17//! cryptographic functions (like hash or dec/deck functions) or get output from
18//! cryptographic functions (like stream ciphers, extendable output functions or
19//! dec/deck functions). The same traits can also be used to abstract over
20//! (fixed or variable sized) buffers, which is for example useful for
21//! abstracting over low-level primitives like permutations.
22//!
23//! The API consists of two core traits:
24//! * [`Writer`]: A buffer or construction data can be written to. This is used
25//! for example for inputting data into a deck function.
26//! * [`Reader`]: A buffer that can be read from or a construction that can
27//! generate an output stream. This is used for example for generating an
28//! output stream from a deck function.
29//!
30//! # Permutations
31//! Cryptographic permutations are abstracted over using two traits:
32//! * [`PermutationState`]: A fixed size buffer cryptographic permutations can
33//! act on. It can have specific data layout (e.g. byteorder) requirements, as
34//! long as it is possible to clone states, xor states together and xor and
35//! write bytes into (using the [`Writer`] trait) and read bytes from (using
36//! the [`Reader`] trait).
37//! * [`Permutation`]: A cryptographic permutation. It acts on a specific
38//! [`PermutationState`].
39//!
40//! # Deck functions
41//! A deck function is a Doubly Extendable Cryptographic Keyed function. It is
42//! abstracted over by the [`DeckFunction`] trait. It allows repeatedly
43//! inputting and outputting variable length streams of data. For inputting
44//! data, the [`Writer`] trait is used, and for outputting the [`Reader`] trait
45//! is used.
46
47#![cfg_attr(not(feature = "std"), no_std)]
48#![allow(clippy::needless_lifetimes)]
49
50#[cfg(feature = "alloc")]
51extern crate alloc;
52
53pub mod buffer;
54pub use buffer::BufMut;
55
56pub mod io;
57pub use io::{CryptoReader, Reader, WriteTooLargeError, Writer};
58
59/// A state where a cryptographic permutation acts upon.
60///
61/// The API of this trait consists of two parts: the generic and the specific
62/// part. The generic part aims at users of permutation, that want to be generic
63/// over the specific permutation used in the construction (e.g. in a Sponge or
64/// Farfalle construction). The specific part aims at [`Permutation`]
65/// implementers. It allows to directly access the state representation.
66///
67/// # Generic API
68/// The generic API gives abstract ways to read, write and xor bytes from/to the
69/// state. It consists of
70/// * [`Self::SIZE`] (constant)
71/// * [`Self::StateReader`] (type)
72/// * [`Self::CopyWriter`] (type)
73/// * [`Self::XorWriter`] (type)
74/// * [`Self::reader`] (method)
75/// * [`Self::copy_writer`] (method)
76/// * [`Self::xor_writer`] (method)
77///
78/// Besides these trait items, there are also the [`Default`], [`Clone`] and
79/// [`BitXorAssign`] trait bounds.
80///
81/// # Specific API
82/// The specific API gives direct read and write access to the state
83/// representation underlying the [`PermutationState`]. It consists of
84/// * [`Self::Representation`] (type)
85/// * [`Self::from_state`] (constructor function)
86/// * [`Self::get_state`] (method)
87/// * [`Self::get_state_mut`] (method)
88///
89/// [`BitXorAssign`]: core::ops::BitXorAssign
90pub trait PermutationState: Default + Clone + for<'a> core::ops::BitXorAssign<&'a Self> {
91 // # Generic API
92
93 /// Number of bytes of the state.
94 const SIZE: usize;
95 /// [`Reader`] to read bytes from the state.
96 type StateReader<'a>: Reader
97 where
98 Self: 'a;
99 /// [`Writer`] to write into the state.
100 type CopyWriter<'a>: Writer
101 where
102 Self: 'a;
103 /// [`Writer`] to xor into the state.
104 type XorWriter<'a>: Writer
105 where
106 Self: 'a;
107
108 /// Create a [`Reader`] to read bytes from the state.
109 fn reader<'a>(&'a self) -> Self::StateReader<'a>;
110 /// Create a [`Writer`] to write into the state.
111 fn copy_writer<'a>(&'a mut self) -> Self::CopyWriter<'a>;
112 /// Create a [`Writer`] to xor into the state.
113 fn xor_writer<'a>(&'a mut self) -> Self::XorWriter<'a>;
114
115 // # Specific API
116
117 /// Representation of the state the permutation works on.
118 ///
119 /// This should generally be an array of integers, e.g. `[u64; 25]` for
120 /// Keccak-f\[1600\].
121 type Representation;
122
123 /// Initialise the permutation from the given state.
124 fn from_state(state: Self::Representation) -> Self;
125 /// Read from the state buffer.
126 fn get_state(&self) -> &Self::Representation;
127 /// Write into the state buffer.
128 fn get_state_mut(&mut self) -> &mut Self::Representation;
129}
130
131/// A cryptographic permutation.
132pub trait Permutation: Copy + Default {
133 /// The state this permutation acts upon.
134 ///
135 /// Splitting this type out allows for different permutations to act on the
136 /// same state. For example, keccak-p[1600, n] can act on the same state
137 /// regardless the number of rounds `n`.
138 type State: PermutationState;
139
140 /// Apply the permutation to the state.
141 fn apply(self, state: &mut Self::State);
142}
143
144/// A doubly-ended cryptographic keyed function.
145///
146/// A deck function is a Doubly Extendable Cryptographic Keyed function. It
147/// allows repeatedly inputting and outputting variable length streams of data.
148/// To input a stream of data, create an input writer using
149/// [`Self::input_writer`]. Data can then be written to it using the methods of
150/// the [`Writer`] trait. Writes to separate input writers are domain separated;
151/// writes to a single input writer are concatenated. To generate an output
152/// stream, create an output generator using [`Self::output_reader`]. An output
153/// stream can be generated from it using the methods of the [`Reader`] trait.
154/// Creating an output reader and reading from it does not mutate the state of
155/// the original deck function. Inputting new data into the deck function does
156/// not change an already existing output generator.
157///
158/// # Crypto
159/// When a secret uniformly chosen key is used to initialise the deck function
160/// (using [`Self::init`]), the output the output generator generates should be
161/// secure as a pseudo-random function from on the input data, i.e.
162/// indistinguishable from a truly random function. Identical `(key, input)`
163/// pairs give identical output (determinism).
164///
165/// # Warning
166/// This is a relatively low-level API and very flexible so you can easily
167/// create many modes on top of it, but it is not misuse resistant. In
168/// particular calling the `output` method doesn't modify the state, and calling
169/// it twice on the same state gives identical output streams.
170pub trait DeckFunction {
171 type OutputGenerator: CryptoReader;
172 /// [`Writer`] that inputs data that is written to it to the deck function.
173 type InputWriter<'a>: Writer
174 where
175 Self: 'a;
176
177 /// Create a deck function from a 256 bit secret key.
178 fn init(key: &[u8; 32]) -> Self;
179 /// Create a writer that inputs data into the deck function.
180 ///
181 /// Every input writer starts writing a new stream, i.e. domain separation
182 /// between input streams is applied. Separate writes to the same
183 /// input writer are not domain separated, but just concatenated.
184 /// In code:
185 /// ```compile_fail
186 /// # use crypto_permutation::{DeckFunction, Writer};
187 /// # fn deck() -> impl DeckFunction + Clone + PartialEq + core::fmt::Debug {
188 /// # unimplemented!()
189 /// # }
190 /// # let mut deck1 = deck();
191 /// // assume `deck1` is a `DeckFunction`
192 /// let mut deck2 = deck1.clone();
193 /// let mut deck3 = deck1.clone();
194 ///
195 /// let mut writer1 = deck1.input_writer();
196 /// writer1.write_bytes(b"hello world");
197 /// writer1.finish();
198 ///
199 /// let mut writer2 = deck2.input_writer();
200 /// writer2.write_bytes(b"hello");
201 /// writer2.write_bytes(b" world");
202 /// writer2.finish();
203 ///
204 /// let mut writer3 = deck3.input_writer();
205 /// writer3.write_bytes(b"hello");
206 /// writer3.finish();
207 /// let mut writer3 = deck3.input_writer();
208 /// writer3.write_bytes(b" world");
209 /// writer3.finish();
210 ///
211 /// assert_eq!(deck1, deck2);
212 /// assert_ne!(deck2, deck3);
213 /// ```
214 fn input_writer<'a>(&'a mut self) -> Self::InputWriter<'a>;
215
216 /// Create an output generator from the current state.
217 ///
218 /// # Warning
219 /// Never create an output generator from the same state twice, without
220 /// inputting new data in between. These would generate identical output
221 /// streams.
222 fn output_reader(&self) -> Self::OutputGenerator;
223}