Skip to main content

grain_128aeadv2/
lib.rs

1#![no_std]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![doc(
4    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
5    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
6)]
7#![deny(unsafe_code)]
8#![warn(missing_docs)]
9
10
11
12//! ## Quickstart
13//!
14//! Basic usage (with default `vec` feature):
15//!
16//! If you don't want to use the module to generate the keys :
17#![cfg_attr(feature = "vec", doc = "```")]
18#![cfg_attr(not(feature = "vec"), doc = "```ignore")]
19//! use grain_128aeadv2::{
20//!     Grain128, Key, Nonce,
21//!     aead::{KeyInit, AeadCore}
22//! };
23//!
24//! // PLEASE use a RANDOM key/nonce (don't copy-paste this...)
25//! let key = [12, 33, 91, 88, 1, 0, 132, 11, 231, 28, 1, 3, 5, 1, 5, 1];
26//! let nonce = [91, 88, 1, 0, 132, 11, 231, 1, 23, 32, 22, 33];
27//! let cipher = Grain128::new(&key.into());
28//!
29//! let (ciphertext, tag) = cipher.encrypt_aead(
30//!     &nonce.into(),
31//!     b"Some additionnal data",
32//!     b"this is a secret message"
33//! );
34//!
35//! let plaintext = cipher.decrypt_aead(
36//!     &nonce.into(),
37//!     b"Some additionnal data",
38//!     &ciphertext,
39//!     &tag
40//! ).expect("Tag verification failed");
41//!
42//! assert_eq!(&plaintext, b"this is a secret message"); 
43//!
44//! ```
45//! With randomly sampled keys and nonces (requires `getrandom` feature):
46//!
47#![cfg_attr(all(feature = "vec", feature = "getrandom"), doc = "```")]
48#![cfg_attr(not(all(feature = "vec", feature = "getrandom")), doc = "```ignore")]
49//! use grain_128aeadv2::{Grain128, aead::{Aead, AeadCore, KeyInit}};
50//!
51//! let key = Grain128::generate_key().expect("Unable to generate key");
52//! let cipher = Grain128::new(&key);
53//!
54//! // A nonce must be USED ONLY ONCE !
55//! let nonce = Grain128::generate_nonce().expect("Unable to generate nonce");
56//! let (ciphertext, tag) = cipher.encrypt_aead(
57//!     &nonce,
58//!     b"Some additionnal data",
59//!     b"this is a secret message"
60//! );
61//!
62//! let plaintext = cipher.decrypt_aead(
63//!     &nonce,
64//!     b"Some additionnal data",
65//!     &ciphertext,
66//!     &tag
67//! ).expect("Tag verification failed");
68//!
69//! assert_eq!(&plaintext, b"this is a secret message"); 
70//! ```
71//!
72//! ## In-place encryption (`arrayvec` or `alloc`)
73//!
74//! The [`AeadInOut::encrypt_in_place`] and [`AeadInOut::decrypt_in_place`]
75//! methods accept any type that impls the [`aead::Buffer`] trait which
76//! contains the plaintext for encryption or ciphertext for decryption.
77//!
78//! Enabling the `arrayvec` feature of this crate will provide an impl of
79//! [`aead::Buffer`] for `arrayvec::ArrayVec` (re-exported from the [`aead`] crate as
80//! [`aead::arrayvec::ArrayVec`]).
81//! Enabling the `alloc` feature of this crate will provide an impl of
82//! [`aead::Buffer`] for `Vec`.
83//!
84//! It can then be passed as the `buffer` parameter to the in-place encrypt
85//! and decrypt methods:
86//!
87#![cfg_attr(all(feature = "getrandom", feature = "arrayvec"), doc = "```")]
88#![cfg_attr(
89    not(all(feature = "getrandom", feature = "arrayvec")),
90    doc = "```ignore"
91)]
92//! use grain_128aeadv2::{
93//!     Grain128, Key, Nonce,
94//!     aead::{AeadCore, AeadInOut, KeyInit, arrayvec::ArrayVec}
95//! };
96//!
97//! let key = Grain128::generate_key().expect("Unable to generate key");
98//! let cipher = Grain128::new(&key);
99//!
100//! // A nonce must be USED ONLY ONCE !
101//! let nonce = Grain128::generate_nonce().expect("Unable to generate nonce");
102//! // Take care : 8 bytes overhead to store the tag
103//! let mut buffer: ArrayVec<u8, 24> = ArrayVec::new();
104//! buffer.try_extend_from_slice(b"a secret message").unwrap();
105//!
106//! // Perform in place encryption inside 'buffer'
107//! cipher.encrypt_in_place(&nonce, b"Some AD", &mut buffer).expect("Unable to encrypt");
108//!
109//! // Perform in place decryption
110//! cipher.decrypt_in_place(&nonce, b"Some AD", &mut buffer).expect("Tag verification failed");
111//!
112//! assert_eq!(buffer.as_ref(), b"a secret message");
113//! ```
114#![cfg_attr(all(feature = "getrandom", feature = "alloc"), doc = "```")]
115#![cfg_attr(
116    not(all(feature = "getrandom", feature = "alloc")),
117    doc = "```ignore"
118)]
119//! use grain_128aeadv2::{
120//!     Grain128, Key, Nonce,
121//!     aead::{AeadCore, AeadInOut, KeyInit, arrayvec::ArrayVec}
122//! };
123//!
124//! let key = Grain128::generate_key().expect("Unable to generate key");
125//! let cipher = Grain128::new(&key);
126//!
127//! // A nonce must be USED ONLY ONCE !
128//! let nonce = Grain128::generate_nonce().expect("Unable to generate nonce");
129//! // Take care : 8 bytes overhead to store the tag
130//! let mut buffer: Vec<u8> = vec![];
131//! buffer.extend_from_slice(b"a secret message");
132//!
133//! // Perform in place encryption inside 'buffer'
134//! cipher.encrypt_in_place(&nonce, b"Some AD", &mut buffer).expect("Unable to encrypt");
135//!
136//! // Perform in place decryption
137//! cipher.decrypt_in_place(&nonce, b"Some AD", &mut buffer).expect("Tag verification failed");
138//!
139//! assert_eq!(&buffer, b"a secret message");
140//! ```
141
142#[cfg(feature = "vec")]
143extern crate alloc;
144#[cfg(feature = "vec")]
145use alloc::vec::Vec;
146
147pub use aead::{self, Tag, AeadCore, AeadInOut, Error, Key, KeyInit, KeySizeUser, Nonce, array::Array, inout::InOutBuf, consts::{U1, U8, U12, U16}, Buffer};
148use aead::TagPosition;
149
150#[cfg(feature = "zeroize")]
151pub use zeroize;
152
153
154mod grain_core;
155mod fsr;
156mod utils;
157mod traits;
158
159use grain_core::GrainCore;
160
161
162/// Grain-128AEADv2 cipher.
163#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize, zeroize::ZeroizeOnDrop))]
164pub struct Grain128 {
165    pub(crate) key: u128,
166}
167
168
169// Implement to define key/iv size 
170impl KeySizeUser for Grain128{
171    type KeySize = U16;
172}
173
174impl KeyInit for Grain128 {
175    fn new(key: &Key<Self>) -> Self {
176
177        let mut key_int: u128 = 0;
178        for i in 0..key.len() {
179            key_int |= (key[i] as u128) << (i * 8);
180        }
181
182        Grain128 { key: key_int}
183    }
184}
185
186
187impl AeadCore for Grain128 {
188    type NonceSize = U12;
189    type TagSize = U8;
190    const TAG_POSITION: TagPosition = TagPosition::Postfix;
191}
192
193
194#[cfg(feature = "vec")]
195impl Grain128 {
196    /// Init a new grain128-AEADv2 cipher for the given nonce
197    /// and encrypts the plaintext. One may provide associated
198    /// data that will be authenticated too.
199    ///
200    /// ```
201    /// use grain_128aeadv2::{Grain128, KeyInit};
202    /// 
203    /// let key = b"my secret key !!";
204    /// let cipher = Grain128::new(key.into());
205    ///
206    /// // A nonce must be USED ONLY ONCE !
207    /// let (ciphertext, tag) = cipher.encrypt_aead(
208    ///     b"super nonce!".into(),
209    ///     b"this is associated data",
210    ///     b"my secret"
211    /// );
212    /// ```
213    pub fn encrypt_aead(&self, nonce: &Nonce<Self>, associated_data: &[u8], plaintext: &[u8]) -> (Vec<u8>, Tag<Self>){
214        let mut nonce_int: u128 = 0;
215        for i in 0..nonce.len() {
216            nonce_int |= (nonce[i] as u128) << (i * 8);
217        }
218
219        let mut cipher = GrainCore::new(self.key, nonce_int);
220
221        let (ct, tag) = cipher.encrypt_aead(associated_data, plaintext);
222
223        (ct, Tag::<Self>::from(tag))
224    }
225
226    /// Init a new grain128-AEADv2 cipher for the given nonce
227    /// and decrypts the ciphertext. You need to provide the 
228    /// associated data if any.
229    ///
230    /// ```
231    /// use grain_128aeadv2::{Grain128, KeyInit};
232    /// 
233    /// let key = b"my secret key !!";
234    /// let cipher = Grain128::new(key.into());
235    ///
236    /// // A nonce must be USED ONLY ONCE !
237    /// let (ciphertext, tag) = cipher.encrypt_aead(
238    ///     b"super nonce!".into(),
239    ///     b"this is associated data",
240    ///     b"my secret"
241    /// );
242    /// let decrypted = cipher.decrypt_aead(
243    ///     b"super nonce!".into(),
244    ///     b"this is associated data",
245    ///     &ciphertext,
246    ///     &tag
247    /// ).expect("Unable to decrypt");
248    ////
249    /// assert_eq!(decrypted, b"my secret");
250    /// ```
251    pub fn decrypt_aead(&self, nonce: &Nonce<Self>, associated_data: &[u8], ciphertext: &[u8], expected_tag: &Tag<Self>) -> Result<Vec<u8>, Error> {
252        let mut nonce_int: u128 = 0;
253        for i in 0..nonce.len() {
254            nonce_int |= (nonce[i] as u128) << (i * 8);
255        }
256
257        let mut cipher = GrainCore::new(self.key, nonce_int);
258
259        cipher.decrypt_aead(associated_data, ciphertext, expected_tag.as_slice())
260    }
261}
262
263
264impl AeadInOut for Grain128 {
265    fn encrypt_inout_detached(
266        &self,
267        nonce: &Nonce<Self>,
268        associated_data: &[u8],
269        buffer: InOutBuf<'_, '_, u8>,
270    ) -> Result<Tag<Self>, Error> {
271
272        let mut nonce_int: u128 = 0;
273        for i in 0..nonce.len() {
274            nonce_int |= (nonce[i] as u128) << (i * 8);
275        }
276
277        let mut cipher = GrainCore::new(self.key, nonce_int);
278
279        let tag = Tag::<Self>::from(cipher.encrypt_auth_aead_inout(associated_data, buffer));
280
281        Ok(tag)
282    }
283
284    fn decrypt_inout_detached(
285        &self,
286        nonce: &Nonce<Self>,
287        associated_data: &[u8],
288        mut buffer: InOutBuf<'_, '_, u8>,
289        tag: &Tag<Self>,
290    ) -> Result<(), Error> {
291
292        let mut nonce_int: u128 = 0;
293        for i in 0..nonce.len() {
294            nonce_int |= (nonce[i] as u128) << (i * 8);
295        }
296
297        let mut cipher = GrainCore::new(self.key, nonce_int);
298
299        let decrypt_res = cipher.decrypt_auth_aead_inout(associated_data, buffer.reborrow(), tag.as_slice());
300
301        match decrypt_res {
302            Ok(()) => Ok(()),
303            _ => {
304                // Avoid leaking the decrypted ciphertext
305                buffer.get_out().fill(0);
306                // Then return the error
307                Err(Error)
308            }
309        }
310        
311
312    }
313}