Skip to content

Commit

Permalink
impl Write, from_reader for Argon2i hashing
Browse files Browse the repository at this point in the history
  • Loading branch information
Vince Mutolo committed Oct 17, 2021
1 parent a32d250 commit e9b0158
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
36 changes: 36 additions & 0 deletions src/hazardous/hash/blake2b.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@
//! [`verify()`]: blake2b::Blake2b::verify
//! [`as_ref()`]: blake2b::Digest::as_ref

use std::io::{Read, Write};

use crate::{errors::UnknownCryptoError, util::endianness::load_u64_into_le, util::u64x4::U64x4};

/// The blocksize for the hash function BLAKE2b.
Expand Down Expand Up @@ -216,6 +218,23 @@ impl Hasher {
state.finalize()
}

#[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."]
/// Return a digest selected by the given Blake2b variant, where the digest
/// is the result of hashing *all* the data available from the passed `Read` type.
/// This will read from `reader` until it is exhausted. Note that internally
/// we use [`std::io::copy`](std::io::copy)..
pub fn from_reader<R: Read>(&self, mut reader: R) -> Result<Digest, UnknownCryptoError> {
let size: usize = match *self {
Hasher::Blake2b256 => 32,
Hasher::Blake2b384 => 48,
Hasher::Blake2b512 => 64,
};

let mut state = Blake2b::new(None, size)?;
std::io::copy(&mut reader, &mut state).map_err(|_| UnknownCryptoError)?;
state.finalize()
}

#[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."]
/// Return a `Blake2b` state selected by the given Blake2b variant.
pub fn init(&self) -> Result<Blake2b, UnknownCryptoError> {
Expand Down Expand Up @@ -472,6 +491,23 @@ impl Blake2b {
}
}

impl Write for Blake2b {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
use std::io::{Error as IoError, ErrorKind};
self.update(buf).map_err(|_| {
dbg!("hi");
IoError::new(ErrorKind::Other, UnknownCryptoError)
})?;
Ok(buf.len())
}

fn flush(&mut self) -> std::io::Result<()> {
// This function doesn't have to do anything because the `write`
// implementation writes everything immediately.
Ok(())
}
}

// Testing public functions in the module.
#[cfg(test)]
mod public {
Expand Down
25 changes: 25 additions & 0 deletions src/high_level/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
//! # Ok::<(), orion::errors::UnknownCryptoError>(())
//! ```

use std::io::Read;

pub use crate::hazardous::hash::blake2b::Digest;
use crate::{errors::UnknownCryptoError, hazardous::hash::blake2b};

Expand All @@ -63,6 +65,20 @@ pub fn digest(data: &[u8]) -> Result<Digest, UnknownCryptoError> {
blake2b::Hasher::Blake2b256.digest(data)
}

/// Hash all data from an object implementing `Read`. Note that internally
/// this calls [`std::io::copy`](std::io::copy) and will consume *all* data
/// available in the reader.
///
/// ```rust
/// use orion::hash::{self, Digest};
/// let data = std::io::Cursor::new(vec![1, 2, 3]);
/// let digest: Digest = hash::from_reader(data).unwrap();
/// ```
#[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."]
pub fn from_reader<R: Read>(reader: R) -> Result<Digest, UnknownCryptoError> {
blake2b::Hasher::Blake2b256.from_reader(reader)
}

// Testing public functions in the module.
#[cfg(feature = "safe_api")]
#[cfg(test)]
Expand All @@ -80,4 +96,13 @@ mod public {
fn prop_digest_diff_result(input: Vec<u8>) -> bool {
digest(&input[..]).unwrap() != digest(b"Completely wrong input").unwrap()
}

#[quickcheck]
/// Hashing with `from_reader` should always return the same as a `digest` of the data.
fn prop_digest_reader_same_result(input: Vec<u8>) -> bool {
use std::io::Cursor;
let expected = digest(input.as_slice()).unwrap();
let using_reader = from_reader(Cursor::new(input)).unwrap();
expected == using_reader
}
}

0 comments on commit e9b0158

Please sign in to comment.