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}