diff --git a/.github/workflows/balloon-hash.yml b/.github/workflows/balloon-hash.yml index 8f40a6f7..3ccd8130 100644 --- a/.github/workflows/balloon-hash.yml +++ b/.github/workflows/balloon-hash.yml @@ -61,4 +61,6 @@ jobs: toolchain: ${{ matrix.rust }} override: true - run: cargo test --release + - run: cargo test --release --no-default-features --features alloc + - run: cargo test --release --no-default-features --features alloc,zeroize - run: cargo test --release --all-features diff --git a/Cargo.lock b/Cargo.lock index feacbdb6..cf20b13b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,6 +30,7 @@ dependencies = [ "password-hash", "rayon", "sha2", + "zeroize", ] [[package]] diff --git a/balloon-hash/Cargo.toml b/balloon-hash/Cargo.toml index 7f83333e..c5cf89d6 100644 --- a/balloon-hash/Cargo.toml +++ b/balloon-hash/Cargo.toml @@ -19,6 +19,7 @@ crypto-bigint = { version = "0.4", default-features = false, features = ["generi # optional dependencies password-hash = { version = "0.4", default-features = false, optional = true } rayon = { version = "1.5", optional = true } +zeroize = { version = "1", default-features = false, optional = true } [dev-dependencies] hex-literal = "0.3" diff --git a/balloon-hash/src/balloon.rs b/balloon-hash/src/balloon.rs index 7fe3dbb5..e86bc570 100644 --- a/balloon-hash/src/balloon.rs +++ b/balloon-hash/src/balloon.rs @@ -131,7 +131,7 @@ where // for m from 1 to s_cost-1: for m in 1..s_cost { // buf[m] = hash(cnt++, buf[m-1]) - Digest::update(&mut digest, &cnt.to_le_bytes()); + Digest::update(&mut digest, cnt.to_le_bytes()); cnt += 1; Digest::update(&mut digest, &buf[m - 1]); buf[m] = digest.finalize_reset(); @@ -151,7 +151,7 @@ where }; // buf[m] = hash(cnt++, prev, buf[m]) - Digest::update(&mut digest, &cnt.to_le_bytes()); + Digest::update(&mut digest, cnt.to_le_bytes()); cnt += 1; Digest::update(&mut digest, prev); Digest::update(&mut digest, &buf[m]); @@ -161,13 +161,13 @@ where // for i from 0 to delta-1: for i in 0..DELTA { // block_t idx_block = ints_to_block(t, m, i) - Digest::update(&mut digest, &t.to_le_bytes()); - Digest::update(&mut digest, &(m as u64).to_le_bytes()); - Digest::update(&mut digest, &i.to_le_bytes()); + Digest::update(&mut digest, t.to_le_bytes()); + Digest::update(&mut digest, (m as u64).to_le_bytes()); + Digest::update(&mut digest, i.to_le_bytes()); let idx_block = digest.finalize_reset(); // int other = to_int(hash(cnt++, salt, idx_block)) mod s_cost - Digest::update(&mut digest, &cnt.to_le_bytes()); + Digest::update(&mut digest, cnt.to_le_bytes()); cnt += 1; Digest::update(&mut digest, salt); @@ -188,7 +188,7 @@ where ); // buf[m] = hash(cnt++, buf[m], buf[other]) - Digest::update(&mut digest, &cnt.to_le_bytes()); + Digest::update(&mut digest, cnt.to_le_bytes()); cnt += 1; Digest::update(&mut digest, &buf[m]); Digest::update(&mut digest, &buf[other]); diff --git a/balloon-hash/src/lib.rs b/balloon-hash/src/lib.rs index 1d78dc9e..f63e746b 100644 --- a/balloon-hash/src/lib.rs +++ b/balloon-hash/src/lib.rs @@ -22,6 +22,10 @@ //! sha2 = "0.9" //! ``` //! +//! The `zeroize` crate feature will zeroize allocated memory created when +//! using the [`Balloon::hash`] function. It will do nothing when the `alloc` +//! crate feature is not active. +//! //! The following example demonstrates the high-level password hashing API: //! //! ``` @@ -85,6 +89,9 @@ use digest::{Digest, FixedOutputReset}; #[cfg(all(feature = "alloc", feature = "password-hash"))] use password_hash::{Decimal, Ident, ParamsString, Salt}; +#[cfg(feature = "zeroize")] +use zeroize::Zeroize; + /// Balloon context. /// /// This is the primary type of this crate's API, and contains the following: @@ -128,7 +135,12 @@ where let mut memory = alloc::vec![GenericArray::default(); self.params.s_cost.get() as usize]; #[cfg(feature = "parallel")] let mut memory = alloc::vec![GenericArray::default(); (self.params.s_cost.get() * self.params.p_cost.get()) as usize]; - self.hash_with_memory(pwd, salt, &mut memory) + + #[cfg_attr(not(feature = "zeroize"), allow(clippy::let_and_return))] + let output = self.hash_with_memory(pwd, salt, &mut memory); + #[cfg(feature = "zeroize")] + memory.iter_mut().for_each(|block| block.zeroize()); + output } /// Hash a password and associated parameters.