Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,3 @@ exclude = ["benches", "fuzz"]

[profile.dev]
opt-level = 2

[patch.crates-io.blake2]
git = "https://github.com/RustCrypto/hashes"
branch = "blake2/restore-blake-var"
55 changes: 25 additions & 30 deletions argon2/src/blake2b_long.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
use crate::{Error, Result};

use blake2::{
Blake2b512, Blake2bVar,
digest::{self, Digest},
Blake2b512, Blake2bVarCore,
digest::{
Digest,
block_api::{UpdateCore, VariableOutputCore},
block_buffer::LazyBuffer,
},
};

use core::convert::TryFrom;

pub fn blake2b_long(inputs: &[&[u8]], out: &mut [u8]) -> Result<()> {
if out.is_empty() {
return Err(Error::OutputTooShort);
Expand All @@ -19,19 +21,17 @@ pub fn blake2b_long(inputs: &[&[u8]], out: &mut [u8]) -> Result<()> {
.map_err(|_| Error::OutputTooLong)?;

// Use blake2b directly if the output is small enough.
if out.len() <= Blake2b512::output_size() {
let mut digest = Blake2bVar::new(out.len()).map_err(|_| Error::OutputTooLong)?;

// Conflicting method name from `Digest` and `Update` traits
digest::Update::update(&mut digest, &len_bytes);
if let Ok(mut hasher) = Blake2bVarCore::new(out.len()) {
let mut buf = LazyBuffer::new(&len_bytes);

for input in inputs {
digest::Update::update(&mut digest, input);
buf.digest_blocks(input, |blocks| hasher.update_blocks(blocks));
}

digest
.finalize_variable(out)
.map_err(|_| Error::OutputTooLong)?;
let mut full_out = Default::default();
hasher.finalize_variable_core(&mut buf, &mut full_out);
let out_src = &full_out[..out.len()];
out.copy_from_slice(out_src);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be worth to add a helper method to VariableOutputCore for this.


return Ok(());
}
Expand All @@ -47,33 +47,28 @@ pub fn blake2b_long(inputs: &[&[u8]], out: &mut [u8]) -> Result<()> {
let mut last_output = digest.finalize();

// Then we write the first 32 bytes of this hash to the output
out[..half_hash_len].copy_from_slice(&last_output[..half_hash_len]);
let (first_chunk, mut out) = out.split_at_mut(half_hash_len);
first_chunk.copy_from_slice(&last_output[..half_hash_len]);

// Next, we write a number of 32 byte blocks to the output.
// Each block is the first 32 bytes of the hash of the last block.
// The very last block of the output is excluded, and has a variable
// length in range [1, 32].
let mut counter = 0;
let out_len = out.len();
for chunk in out[half_hash_len..]
.chunks_exact_mut(half_hash_len)
.take_while(|_| {
counter += half_hash_len;
out_len - counter > 64
})
{
while out.len() > 64 {
let (chunk, tail) = out.split_at_mut(half_hash_len);
out = tail;
last_output = Blake2b512::digest(last_output);
chunk.copy_from_slice(&last_output[..half_hash_len]);
}

// Calculate the last block with VarBlake2b.
let last_block_size = out.len() - counter;
let mut digest = Blake2bVar::new(last_block_size).map_err(|_| Error::OutputTooLong)?;

digest::Update::update(&mut digest, &last_output);
digest
.finalize_variable(&mut out[counter..])
.expect("invalid Blake2bVar out length");
let mut hasher = Blake2bVarCore::new(out.len())
.expect("`out.len()` is guaranteed to be smaller or equal to 64");
let mut buf = LazyBuffer::new(&last_output);
let mut full_out = Default::default();
hasher.finalize_variable_core(&mut buf, &mut full_out);
let out_src = &full_out[..out.len()];
out.copy_from_slice(out_src);

Ok(())
}