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}