diff options
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 28 |
1 files changed, 20 insertions, 8 deletions
@@ -1,4 +1,5 @@ #![cfg_attr(feature = "simd", feature(portable_simd))] +#![cfg_attr(not(feature = "std"), no_std)] //! AEZ *\[sic!\]* v5 encryption implemented in Rust. //! //! # ☣️ Cryptographic hazmat ☣️ @@ -67,6 +68,8 @@ //! //! ``` //! # use zears::*; +//! # #[cfg(feature = "std")] +//! # fn main() { //! let aez = Aez::new(b"my secret key!"); //! let cipher = aez.encrypt(b"nonce", &[b"associated data"], 16, b"message"); //! let plaintext = aez.decrypt(b"nonce", &[b"associated data"], 16, &cipher); @@ -82,6 +85,9 @@ //! let cipher = aez.encrypt(b"nonce", &[b"foo"], 16, b"message"); //! let plaintext = aez.decrypt(b"nonce", &[b"bar"], 16, &cipher); //! assert!(plaintext.is_none()); +//! # } +//! # #[cfg(not(feature = "std"))] +//! # fn main() {} //! ``` //! //! # Feature flags & compilation hints @@ -102,6 +108,9 @@ //! | +simd, target-cpu=native | 3.3272 GiB/s | +592.01% | //! | `aez` crate | 4.8996 GiB/s | | +#[cfg(not(feature = "std"))] +use core::iter; +#[cfg(feature = "std")] use std::iter; use constant_time_eq::constant_time_eq; @@ -188,6 +197,7 @@ impl Aez { /// provides a "hash" that verifies the integrity of the associated data. /// /// Returns the ciphertext, which will be of length `data.len() + tau`. + #[cfg(feature = "std")] pub fn encrypt( &self, nonce: &[u8], @@ -208,6 +218,7 @@ impl Aez { /// If `tau == 0`, the vector will not be expanded. /// /// The parameters are the same as for [`Aez::encrypt`]. + #[cfg(feature = "std")] pub fn encrypt_vec( &self, nonce: &[u8], @@ -270,6 +281,7 @@ impl Aez { /// /// Returns the decrypted content. If the integrity check fails, returns `None` instead. The /// returned vector has length `data.len() - tau`. + #[cfg(feature = "std")] pub fn decrypt( &self, nonce: &[u8], @@ -380,14 +392,14 @@ fn decrypt<'a, 't, A: AsRef<[u8]> + 't, T: IntoIterator<Item = &'t A>>( } fn is_zeroes(data: &[u8]) -> bool { - let comparator = if data.len() <= ZEROES.len() { - &ZEROES[..data.len()] - } else { - // We should find a way to do this without allocating a separate buffer full of zeroes, but - // I don't want to hand-roll my constant-time-is-zeroes yet. - &vec![0; data.len()] - }; - constant_time_eq(data, comparator) + const PATTERN: u32 = 0xDEADBABE; + let mut accum = 0u32; + for chunk in data.chunks(ZEROES.len()) { + // this is accum = accum | !(chunk == 0...0) + // basically, accum will say if one chunk was not zeroes + accum |= (1 - (constant_time_eq(chunk, &ZEROES[..chunk.len()]) as u32)) * PATTERN; + } + accum == 0 } fn encipher<A: AsRef<[u8]>, T: IntoIterator<Item = A>>(aez: &Aez, tweaks: T, message: &mut [u8]) { |