From 1133dba14f58d212883084c06687944d463a6be1 Mon Sep 17 00:00:00 2001 From: Vincent Hanquez Date: Thu, 18 Nov 2021 20:47:22 +0800 Subject: [PATCH] rework mac --- src/hkdf.rs | 53 +++--- src/hmac.rs | 450 +++++++++++++++++++++++++++++++++++++++----------- src/pbkdf2.rs | 47 +++--- src/scrypt.rs | 9 +- 4 files changed, 400 insertions(+), 159 deletions(-) diff --git a/src/hkdf.rs b/src/hkdf.rs index a8b86d5..04cd758 100644 --- a/src/hkdf.rs +++ b/src/hkdf.rs @@ -6,12 +6,12 @@ //! # Examples //! //! ``` -//! use cryptoxide::{sha2::Sha256, hkdf::{hkdf_extract, hkdf_expand}}; +//! use cryptoxide::{hmac, hkdf}; //! //! let salt = b"salt"; //! let input = b"input"; //! let mut prk = [0u8; 32]; -//! hkdf_extract(Sha256::new(), salt, input, &mut prk); +//! hkdf::extract::(salt, input, &mut prk); //! ``` //! //! [1]: @@ -19,9 +19,7 @@ use alloc::vec::Vec; use core::iter::repeat; -use crate::digest::Digest; -use crate::hmac::Hmac; -use crate::mac::Mac; +use crate::hmac; /// Execute the HKDF-Extract function. Applications MUST NOT use this for /// password hashing. @@ -32,14 +30,12 @@ use crate::mac::Mac; /// * ikm - The input keying material to use. /// * prk - The output buffer to fill with a `digest.output_bytes()` length /// pseudo random key. -pub fn hkdf_extract(mut digest: D, salt: &[u8], ikm: &[u8], prk: &mut [u8]) { - assert!(prk.len() == digest.output_bytes()); - digest.reset(); +pub fn extract(salt: &[u8], ikm: &[u8], prk: &mut [u8]) { + assert!(prk.len() == D::OUTPUT_SIZE); - let mut mac = Hmac::new(digest, salt); - mac.input(ikm); - mac.raw_result(prk); - mac.reset(); + let mut context = hmac::Context::::new(salt); + context.update(ikm); + context.finalize_at(prk); } /// Execute the HKDF-Expand function. Applications MUST NOT use this for @@ -50,26 +46,24 @@ pub fn hkdf_extract(mut digest: D, salt: &[u8], ikm: &[u8], prk: &mut /// * prk - The pseudorandom key of at least `digest.output_bytes()` octets. /// * info - The optional context and application specific information to use. /// * okm - The output buffer to fill with the derived key value. -pub fn hkdf_expand(mut digest: D, prk: &[u8], info: &[u8], okm: &mut [u8]) { - digest.reset(); - - let mut mac = Hmac::new(digest, prk); - let os = mac.output_bytes(); +pub fn expand(prk: &[u8], info: &[u8], okm: &mut [u8]) { + let context = hmac::Context::::new(prk); + let os = context.output_bytes(); let mut t: Vec = repeat(0).take(os).collect(); let mut n: u8 = 0; for chunk in okm.chunks_mut(os) { + let mut context = context.clone(); // The block index starts at 1. So, this is supposed to run on the first execution. n = n.checked_add(1).expect("HKDF size limit exceeded."); if n != 1 { - mac.input(&t[..]); + context.update(&t[..]); } let nbuf = [n]; - mac.input(info); - mac.input(&nbuf); - mac.raw_result(&mut t); - mac.reset(); + context.update(info); + context.update(&nbuf); + context.finalize_at(&mut t); let chunk_len = chunk.len(); chunk[0..chunk_len].copy_from_slice(&t[..chunk_len]); } @@ -80,12 +74,10 @@ mod test { use alloc::vec::Vec; use core::iter::repeat; - use crate::digest::Digest; - use crate::hkdf::{hkdf_expand, hkdf_extract}; - use crate::sha2::Sha256; + use crate::hkdf; + use crate::hmac::SHA256; - struct TestVector { - digest: D, + struct TestVector { ikm: Vec, salt: Vec, info: Vec, @@ -99,7 +91,6 @@ mod test { fn test_hkdf_rfc5869_sha256_vectors() { let test_vectors = vec![ TestVector { - digest: Sha256::new(), ikm: repeat(0x0b).take(22).collect(), salt: (0x00..=0x0c).collect(), info: (0xf0..=0xf9).collect(), @@ -117,7 +108,6 @@ mod test { ], }, TestVector { - digest: Sha256::new(), ikm: (0x00..=0x4f).collect(), salt: (0x60..=0xaf).collect(), info: (0xb0..=0xff).map(|x| x as u8).collect(), @@ -138,7 +128,6 @@ mod test { ], }, TestVector { - digest: Sha256::new(), ikm: repeat(0x0b).take(22).collect(), salt: vec![], info: vec![], @@ -159,12 +148,12 @@ mod test { for t in test_vectors.iter() { let mut prk: Vec = repeat(0).take(t.prk.len()).collect(); - hkdf_extract(t.digest.clone(), &t.salt[..], &t.ikm[..], &mut prk); + hkdf::extract::(&t.salt[..], &t.ikm[..], &mut prk); assert!(prk == t.prk); let mut okm: Vec = repeat(0).take(t.okm.len()).collect(); assert!(okm.len() == t.l); - hkdf_expand(t.digest.clone(), &prk[..], &t.info[..], &mut okm); + hkdf::expand::(&prk[..], &t.info[..], &mut okm); assert!(okm == t.okm); } } diff --git a/src/hmac.rs b/src/hmac.rs index 6ee06ff..484bfda 100644 --- a/src/hmac.rs +++ b/src/hmac.rs @@ -2,135 +2,387 @@ //! //! # Examples //! -//! HMAC-SHA256 using a 16 bytes key of a simple input data +//! HMAC-SHA256 using a 16 bytes key and the incremental interface: //! //! ``` -//! use cryptoxide::{hmac::Hmac, mac::Mac, sha2::Sha256}; +//! use cryptoxide::{hmac, hmac::SHA256}; //! -//! let input = b"data"; //! let key = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]; -//! let mut h = Hmac::new(Sha256::new(), &key); -//! h.input(input); -//! let mac = h.result(); +//! let mut context = hmac::Context::::new(&key); +//! context.update(b"my "); +//! context.update(b"message"); +//! let mac = context.finalize(); //! ``` +//! +//! or using the more concise one-shot interface: +//! +//! ``` +//! use cryptoxide::hmac::{hmac, SHA256}; +//! +//! let key = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]; +//! let mac = hmac::(&key, b"my message"); +//! ``` +//! -use core::iter::repeat; +#![allow(missing_docs)] +use crate::constant_time::{Choice, CtEqual}; +use crate::cryptoutil::zero; use crate::digest::Digest; -use crate::mac::{Mac, MacResult}; -use alloc::vec::Vec; +use core::convert::TryFrom; -/// HMAC context parametrized by the hashing function -pub struct Hmac { - digest: D, - i_key: Vec, - o_key: Vec, - finished: bool, +// HMAC is implemented using the following operations: +// +// HMAC(K, m) = H( (K' ⊕ opad) || H( (K' ⊕ ipad) || m ) ) +// where +// K' = H(K) if length K > block size +// | K otherwise +// H is a cryptographic hash function +// m is the message to be authenticated +// K is the secret key +// K' is a block-sized key derived from the secret key, K; either by padding to the right with 0s up to the block size, or by hashing down to less than or equal to the block size first and then padding to the right with zeros +// || denotes concatenation +// ⊕ denotes bitwise exclusive or (XOR) +// opad is the block-sized outer padding, consisting of repeated bytes valued 0x5c +// ipad is the block-sized inner padding, consisting of repeated bytes valued 0x36 + +macro_rules! init_key { + ($key:ident, $new:expr, $digest_len:path, $block_size:path) => {{ + const OPAD: u8 = 0x5c; + const IPAD: u8 = 0x36; + + assert!($digest_len <= $block_size); + + let mut k = [0u8; $block_size]; + let mut mix = [0u8; $block_size]; + let mut digest_out = [0u8; $digest_len]; + + let mut inner_ctx = $new; + let mut outer_ctx = $new; + + // set k' either as a hash of the key or as the key itself. + if $key.len() <= $block_size { + k[0..$key.len()].copy_from_slice($key) + } else { + // use inner_ctx to just hash into k + let k_as_digestlen = + <&mut [u8; $digest_len]>::try_from(&mut k[0..$digest_len]).unwrap(); + inner_ctx.input($key); + inner_ctx.result(k_as_digestlen); + inner_ctx.reset(); + } + + // input the keyed-ipad in the inner-context (the one hashing the message) + for (m, k_byte) in mix.iter_mut().zip(k.iter()) { + *m = k_byte ^ IPAD; + } + inner_ctx.input(&mix); + + // input the keyed-opad in the outer-context (the one hashing the final result) + for (m, k_byte) in mix.iter_mut().zip(k.iter()) { + *m = k_byte ^ OPAD; + } + outer_ctx.input(&mix); + + // zero the objects + zero(&mut k); + zero(&mut mix); + zero(&mut digest_out); + + (inner_ctx, outer_ctx) + }}; } -fn derive_key(key: &mut [u8], mask: u8) { - for elem in key.iter_mut() { - *elem ^= mask; - } +macro_rules! algorithm_impl { + ($name:ident, $module:ident, $digest_new:ident) => { + impl Algorithm for $name { + const BLOCK_SIZE: usize = Self::BLOCK_SIZE; + const OUTPUT_SIZE: usize = Self::OUTPUT_SIZE; + + type Context = crate::$module::$digest_new; + type Output = [u8; Self::OUTPUT_SIZE]; + type MacOutput = Tag<{ Self::OUTPUT_SIZE }>; + + fn init(key: &[u8]) -> (Self::Context, Self::Context) { + init_key!( + key, + crate::$module::$digest_new::new(), + Self::OUTPUT_SIZE, + Self::BLOCK_SIZE + ) + } + fn update(_context: &mut Self::Context, _input: &[u8]) { + _context.input(_input); + } + fn finalize(_context: &mut Self::Context) -> Self::MacOutput { + let mut output = [0u8; Self::OUTPUT_SIZE]; + _context.result(&mut output); + _context.reset(); + Tag(output) + } + fn finalize_at(_context: &mut Self::Context, out: &mut [u8]) { + _context.result(out); + _context.reset(); + } + fn feed(context: &mut Self::Context, other: &mut Self::Context) { + let mut output = [0u8; Self::OUTPUT_SIZE]; + other.result(&mut output); + other.reset(); + context.input(&output); + } + } + }; } -// The key that Hmac processes must be the same as the block size of the underlying Digest. If the -// provided key is smaller than that, we just pad it with zeros. If its larger, we hash it and then -// pad it with zeros. -fn expand_key(digest: &mut D, key: &[u8]) -> Vec { - let bs = digest.block_size(); - let mut expanded_key: Vec = repeat(0).take(bs).collect(); - - if key.len() <= bs { - expanded_key[0..key.len()].copy_from_slice(key); - } else { - let output_size = digest.output_bytes(); - digest.input(key); - digest.result(&mut expanded_key[..output_size]); - digest.reset(); - } - expanded_key +macro_rules! algorithm2_impl { + ($name:ident, $module:ident, $digest_new:ident) => { + impl Algorithm for $name { + const BLOCK_SIZE: usize = Self::BLOCK_SIZE; + const OUTPUT_SIZE: usize = Self::OUTPUT_SIZE; + + type Context = crate::$module::$digest_new; + type Output = [u8; Self::OUTPUT_SIZE]; + type MacOutput = Tag<{ Self::OUTPUT_SIZE }>; + + fn init(key: &[u8]) -> (Self::Context, Self::Context) { + init_key!( + key, + crate::$module::$digest_new::new(Self::OUTPUT_SIZE), + Self::OUTPUT_SIZE, + Self::BLOCK_SIZE + ) + } + fn update(_context: &mut Self::Context, _input: &[u8]) { + _context.input(_input); + } + fn finalize(_context: &mut Self::Context) -> Self::MacOutput { + let mut output = [0u8; Self::OUTPUT_SIZE]; + _context.result(&mut output); + _context.reset(); + Tag(output) + } + fn finalize_at(_context: &mut Self::Context, out: &mut [u8]) { + _context.result(out); + _context.reset(); + } + fn feed(context: &mut Self::Context, other: &mut Self::Context) { + let mut output = [0u8; Self::OUTPUT_SIZE]; + other.result(&mut output); + other.reset(); + context.input(&output); + } + } + }; } -// Hmac uses two keys derived from the provided key - one by xoring every byte with 0x36 and another -// with 0x5c. -fn create_keys(digest: &mut D, key: &[u8]) -> (Vec, Vec) { - let mut i_key = expand_key(digest, key); - let mut o_key = i_key.clone(); - derive_key(&mut i_key, 0x36); - derive_key(&mut o_key, 0x5c); - (i_key, o_key) +/// Algorithm defined to do HMAC +pub trait Algorithm { + const BLOCK_SIZE: usize; + const OUTPUT_SIZE: usize; + + type Context: Clone; + + // Output and MacOutput should not be needed, but there's current compiler + // limitation in composing the associated type and the constants + type Output; + type MacOutput; + + fn init(key: &[u8]) -> (Self::Context, Self::Context); + fn update(context: &mut Self::Context, input: &[u8]); + fn feed(context: &mut Self::Context, other: &mut Self::Context); + fn finalize(context: &mut Self::Context) -> Self::MacOutput; + fn finalize_at(_context: &mut Self::Context, out: &mut [u8]); } -impl Hmac { - /// Create a new Hmac instance. - /// - /// # Arguments - /// * digest - The Digest to use. - /// * key - The key to use. - /// - pub fn new(mut digest: D, key: &[u8]) -> Hmac { - let (i_key, o_key) = create_keys(&mut digest, key); - digest.input(&i_key[..]); - Hmac { - digest: digest, - i_key: i_key, - o_key: o_key, - finished: false, +#[cfg(feature = "sha1")] +#[derive(Clone, Debug)] +pub struct SHA1; + +#[cfg(feature = "sha1")] +impl SHA1 { + pub const BLOCK_SIZE: usize = 64; + pub const OUTPUT_SIZE: usize = 20; +} + +#[cfg(feature = "sha1")] +algorithm_impl!(SHA1, sha1, Sha1); + +#[cfg(feature = "sha2")] +#[derive(Clone, Debug)] +pub struct SHA256; + +#[cfg(feature = "sha2")] +impl SHA256 { + pub const BLOCK_SIZE: usize = 64; + pub const OUTPUT_SIZE: usize = 32; +} + +#[cfg(feature = "sha2")] +algorithm_impl!(SHA256, sha2, Sha256); + +#[cfg(feature = "sha2")] +#[derive(Clone, Debug)] +pub struct SHA512; + +#[cfg(feature = "sha2")] +impl SHA512 { + pub const BLOCK_SIZE: usize = 128; + pub const OUTPUT_SIZE: usize = 64; +} + +#[cfg(feature = "sha2")] +algorithm_impl!(SHA512, sha2, Sha512); + +#[cfg(feature = "blake2")] +#[derive(Clone, Debug)] +pub struct Blake2b256; + +#[cfg(feature = "blake2")] +impl Blake2b256 { + pub const BLOCK_SIZE: usize = 128; + pub const OUTPUT_SIZE: usize = 32; +} + +#[cfg(feature = "blake2")] +algorithm2_impl!(Blake2b256, blake2b, Blake2b); + +#[cfg(feature = "blake2")] +#[derive(Clone, Debug)] +pub struct Blake2b512; + +#[cfg(feature = "blake2")] +impl Blake2b512 { + pub const BLOCK_SIZE: usize = 128; + pub const OUTPUT_SIZE: usize = 64; +} + +#[cfg(feature = "blake2")] +algorithm2_impl!(Blake2b512, blake2b, Blake2b); + +#[cfg(feature = "blake2")] +#[derive(Clone, Debug)] +pub struct Blake2s256; + +#[cfg(feature = "blake2")] +impl Blake2s256 { + pub const BLOCK_SIZE: usize = 64; + pub const OUTPUT_SIZE: usize = 32; +} + +#[cfg(feature = "blake2")] +algorithm2_impl!(Blake2s256, blake2s, Blake2s); + +/// HMAC context parametrized by the hashing function +/// +/// It is composed of 2 hashing contextes, and the construction +/// is meant to hide the initial key from its context, by forcing +/// the key component to be processed by an initial compress step +/// rendering the key not recoverable from the context memory. +/// +/// It may not be true for every type of hashing context, specially if they +/// have a buffering / last buffer capability. +pub struct Context { + inner: A::Context, + outer: A::Context, +} + +impl Clone for Context { + fn clone(&self) -> Self { + Context { + inner: self.inner.clone(), + outer: self.outer.clone(), } } } -impl Mac for Hmac { - fn input(&mut self, data: &[u8]) { - assert!(!self.finished); - self.digest.input(data); - } +/// HMAC Tag with the number of bytes associated as const type parameter +/// +/// This type is equiped with a constant time equality, either using the constant time +/// trait (`CtEqual`) but also using the standard equality trait (`Eq`), so +/// if this is used in a equality check it doesn't leak timing information. +/// +/// The inner component of the tag, an array of bytes, is exposed publicly +/// and the `Tag` type can be constructed from the component. +pub struct Tag(pub [u8; N]); - fn reset(&mut self) { - self.digest.reset(); - self.digest.input(&self.i_key[..]); - self.finished = false; +impl<'a, const N: usize> From<&'a Tag> for &'a [u8] { + fn from(tag: &'a Tag) -> Self { + &tag.0 } +} - fn result(&mut self) -> MacResult { - let output_size = self.digest.output_bytes(); - let mut code: Vec = repeat(0).take(output_size).collect(); +impl CtEqual for &Tag { + fn ct_eq(self, other: Self) -> Choice { + self.0.ct_eq(&other.0) + } - self.raw_result(&mut code); + fn ct_ne(self, other: Self) -> Choice { + self.0.ct_ne(&other.0) + } +} - MacResult::new_from_owned(code) +impl PartialEq for Tag { + fn eq(&self, other: &Self) -> bool { + self.ct_eq(other).is_true() } +} - fn raw_result(&mut self, output: &mut [u8]) { - if !self.finished { - self.digest.result(output); +impl Eq for Tag {} - self.digest.reset(); - self.digest.input(&self.o_key[..]); - self.digest.input(output); +impl Context { + pub(crate) fn output_bytes(&self) -> usize { + H::OUTPUT_SIZE + } - self.finished = true; - } + /// Create a new HMAC context instance with the given key + /// + /// The key to use can be any sequence of bytes + pub fn new(key: &[u8]) -> Self { + let (inner, outer) = H::init(key); + Self { inner, outer } + } - self.digest.result(output); + /// Update the context with message + /// + /// This can be called multiple times + pub fn update(&mut self, message: &[u8]) { + H::update(&mut self.inner, message) } - fn output_bytes(&self) -> usize { - self.digest.output_bytes() + /// Finalize the context and get the associated HMAC Tag output + pub fn finalize(mut self) -> H::MacOutput { + H::feed(&mut self.outer, &mut self.inner); + H::finalize(&mut self.outer) + } + + /// Finalize the context and get the associated HMAC Tag output + pub fn finalize_at(&mut self, out: &mut [u8]) { + H::feed(&mut self.outer, &mut self.inner); + H::finalize_at(&mut self.outer, out) } } +/// Generate a HMAC Tag for a given key and message +/// +/// ``` +/// # #[cfg(feature = "sha2")] +/// use cryptoxide::hmac::{hmac, SHA256}; +/// +/// # #[cfg(feature = "sha2")] +/// hmac::(&[1,2,3], b"message"); +/// ``` +pub fn hmac(key: &[u8], message: &[u8]) -> D::MacOutput { + let mut context: Context = Context::new(key); + context.update(message); + context.finalize() +} + #[cfg(test)] mod test { - use crate::hmac::Hmac; - use crate::mac::Mac; - - #[cfg(feature = "blake2")] - use crate::blake2s::Blake2s; + use crate::hmac; - #[cfg(feature = "sha2")] - use crate::sha2::Sha256; + //#[cfg(feature = "blake2")] + //use crate::blake2s::Blake2s; struct Test { key: &'static [u8], @@ -186,11 +438,10 @@ mod test { #[test] fn hmac_sha256() { for t in tests().iter() { - let mut h = Hmac::new(Sha256::new(), &t.key[..]); - let mut output = [0u8; 32]; - h.input(&t.data[..]); - h.raw_result(&mut output); - assert_eq!(&output[..], &t.expected[..]); + let mut h: hmac::Context = hmac::Context::new(&t.key[..]); + h.update(&t.data[..]); + let output = h.finalize(); + assert_eq!(&output.0[..], &t.expected[..]); } } @@ -209,10 +460,9 @@ mod test { 0xaf, 0x28, 0xa6, 0x7a, ]; - let mut h = Hmac::new(Blake2s::new(32), &key[..]); - let mut output = [0u8; 32]; - h.input(&data[..]); - h.raw_result(&mut output); - assert_eq!(&output[..], &expected[..]); + let mut h: hmac::Context = hmac::Context::new(&key[..]); + h.update(&data[..]); + let output = h.finalize(); + assert_eq!(&output.0[..], &expected[..]); } } diff --git a/src/pbkdf2.rs b/src/pbkdf2.rs index 86ec158..a81615d 100644 --- a/src/pbkdf2.rs +++ b/src/pbkdf2.rs @@ -3,13 +3,13 @@ //! # Examples //! //! ``` -//! use cryptoxide::{pbkdf2::pbkdf2, hmac::Hmac, sha2::Sha256}; +//! use cryptoxide::{pbkdf2::pbkdf2, hmac}; //! //! let password = b"password"; //! let salt = b"salt"; //! let c = 2; //! let mut out = [0u8; 64]; -//! pbkdf2(&mut Hmac::new(Sha256::new(), password), salt, c, &mut out); +//! pbkdf2::(password, salt, c, &mut out); //! ``` //! //! [1]: @@ -20,7 +20,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::mac::Mac; +use crate::hmac; use alloc::vec::Vec; use core::iter::repeat; @@ -31,27 +31,29 @@ use core::iter::repeat; // `idx` - the 1 based index of the block // `scratch` - a temporary variable the same length as the block // `block` - the block of the output to calculate -fn calculate_block( - mac: &mut M, +fn calculate_block( + keyed_mac: &hmac::Context, salt: &[u8], c: u32, idx: u32, scratch: &mut [u8], block: &mut [u8], ) { + let mut mac = keyed_mac.clone(); + // Perform the 1st iteration. The output goes directly into block - mac.input(salt); - mac.input(&idx.to_be_bytes()); - mac.raw_result(block); - mac.reset(); + mac.update(salt); + mac.update(&idx.to_be_bytes()); + mac.finalize_at(block); + mac.clone_from(keyed_mac); // Perform the 2nd iteration. The input comes from block and is output into scratch. scratch is // then exclusive-or added into block. After all this, the input to the next step is now in // scratch and block is left to just accumulate the exclusive-of sum of remaining iterations. if c > 1 { - mac.input(block); - mac.raw_result(scratch); - mac.reset(); + mac.update(block); + mac.finalize_at(scratch); + mac.clone_from(keyed_mac); for (output, &input) in block.iter_mut().zip(scratch.iter()) { *output ^= input; } @@ -59,9 +61,9 @@ fn calculate_block( // Perform all remaining iterations for _ in 2..c { - mac.input(scratch); - mac.raw_result(scratch); - mac.reset(); + mac.update(scratch); + mac.finalize_at(scratch); + mac.clone_from(keyed_mac); for (output, &input) in block.iter_mut().zip(scratch.iter()) { *output ^= input; } @@ -81,10 +83,12 @@ fn calculate_block( * * `output` - The output buffer to fill with the derived key value. * */ -pub fn pbkdf2(mac: &mut M, salt: &[u8], c: u32, output: &mut [u8]) { +pub fn pbkdf2(password: &[u8], salt: &[u8], c: u32, output: &mut [u8]) { assert!(c > 0); - let os = mac.output_bytes(); + let context = hmac::Context::::new(password); + + let os = context.output_bytes(); // A temporary storage array needed by calculate_block. This is really only necessary if c > 1. // Most users of pbkdf2 should use a value much larger than 1, so, this allocation should almost @@ -99,10 +103,10 @@ pub fn pbkdf2(mac: &mut M, salt: &[u8], c: u32, output: &mut [u8]) { idx = idx.checked_add(1).expect("PBKDF2 size limit exceeded."); if chunk.len() == os { - calculate_block(mac, salt, c, idx, &mut scratch, chunk); + calculate_block(&context, salt, c, idx, &mut scratch, chunk); } else { let mut tmp: Vec = repeat(0).take(os).collect(); - calculate_block(mac, salt, c, idx, &mut scratch[..], &mut tmp[..]); + calculate_block(&context, salt, c, idx, &mut scratch[..], &mut tmp[..]); let chunk_len = chunk.len(); chunk[0..chunk_len].copy_from_slice(&tmp[..chunk_len]); } @@ -112,8 +116,7 @@ pub fn pbkdf2(mac: &mut M, salt: &[u8], c: u32, output: &mut [u8]) { #[cfg(test)] mod test { use super::pbkdf2; - use crate::hmac::Hmac; - use crate::sha1::Sha1; + use crate::hmac; #[test] fn test1() { @@ -121,7 +124,7 @@ mod test { let salt = b"salt"; let c = 2; let mut out = [0u8; 20]; - pbkdf2(&mut Hmac::new(Sha1::new(), password), salt, c, &mut out); + pbkdf2::(password, salt, c, &mut out); assert_eq!( out, [ diff --git a/src/scrypt.rs b/src/scrypt.rs index 7efa5bd..571075b 100644 --- a/src/scrypt.rs +++ b/src/scrypt.rs @@ -21,9 +21,8 @@ use core::iter::repeat; use core::mem::size_of; use crate::cryptoutil::{read_u32_le, read_u32v_le, write_u32_le}; -use crate::hmac::Hmac; +use crate::hmac; use crate::pbkdf2::pbkdf2; -use crate::sha2::Sha256; // The salsa20/8 core function. fn salsa20_8(input: &[u8], output: &mut [u8]) { @@ -241,10 +240,10 @@ pub fn scrypt(password: &[u8], salt: &[u8], params: &ScryptParams, output: &mut let pr128 = (params.p as usize) * r128; let nr128 = n * r128; - let mut mac = Hmac::new(Sha256::new(), password); + //let mut mac = hmac::Context::::new(password); let mut b: Vec = repeat(0).take(pr128).collect(); - pbkdf2(&mut mac, salt, 1, &mut b); + pbkdf2::(password, salt, 1, &mut b); let mut v: Vec = repeat(0).take(nr128).collect(); let mut t: Vec = repeat(0).take(r128).collect(); @@ -253,7 +252,7 @@ pub fn scrypt(password: &[u8], salt: &[u8], params: &ScryptParams, output: &mut scrypt_ro_mix(chunk, &mut v, &mut t, n); } - pbkdf2(&mut mac, &*b, 1, output); + pbkdf2::(password, &*b, 1, output); } #[cfg(test)]