Skip to content

digest: v0.10.0 improvements #479

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 18, 2021
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
14 changes: 12 additions & 2 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion digest/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "digest"
description = "Traits for cryptographic hash functions"
version = "0.10.0-pre"
version = "0.10.0-pre.1"
authors = ["RustCrypto Developers"]
license = "MIT OR Apache-2.0"
readme = "README.md"
Expand All @@ -21,6 +21,7 @@ alloc = []
std = ["alloc"]
dev = ["blobby"]
core-api = ["block-buffer"]
block-padding = ["block-buffer/block-padding"]

[package.metadata.docs.rs]
all-features = true
Expand Down
66 changes: 48 additions & 18 deletions digest/src/core_api.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
use crate::{ExtendableOutput, FixedOutput, Reset, Update, XofReader};
use block_buffer::BlockBuffer;
use core::fmt;
use generic_array::{ArrayLength, GenericArray};

/// Trait which stores algorithm name constant, used in `Debug` implementations.
pub trait AlgorithmName {
/// Algorithm name.
const NAME: &'static str;
}

/// Trait for updating hasher state with input data divided into blocks.
pub trait UpdateCore {
/// Block size in bytes.
Expand All @@ -15,9 +22,9 @@ pub trait UpdateCore {
/// hash output.
///
/// Usage of this trait in user code is discouraged. Instead use core algorithm
/// wrapped by [`crate::CoreWrapper`], which implements the [`FixedOutput`]
/// wrapped by [`BlockBufferWrapper`], which implements the [`FixedOutput`]
/// trait.
pub trait FixedOutputCore: crate::UpdateCore {
pub trait FixedOutputCore: UpdateCore {
/// Digest output size in bytes.
type OutputSize: ArrayLength<u8>;

Expand All @@ -38,9 +45,9 @@ pub trait FixedOutputCore: crate::UpdateCore {
/// retrieve the hash output.
///
/// Usage of this trait in user code is discouraged. Instead use core algorithm
/// wrapped by [`crate::CoreWrapper`], which implements the
/// wrapped by [`BlockBufferWrapper`], which implements the
/// [`ExtendableOutput`] trait.
pub trait ExtendableOutputCore: crate::UpdateCore {
pub trait ExtendableOutputCore: UpdateCore {
/// XOF reader core state.
type ReaderCore: XofReaderCore;

Expand All @@ -65,32 +72,55 @@ pub trait XofReaderCore {
fn read_block(&mut self) -> GenericArray<u8, Self::BlockSize>;
}

/// Wrapper around core trait implementations.
/// Wrapper around [`UpdateCore`] implementations.
///
/// It handles data buffering and implements the mid-level traits.
#[derive(Clone, Default)]
pub struct UpdateCoreWrapper<T: UpdateCore> {
core: T,
buffer: BlockBuffer<T::BlockSize>,
}

/// Wrapper around [`XofReaderCore`] implementations.
///
/// It handles data buffering and implements the mid-level traits.
#[derive(Clone, Default)]
pub struct CoreWrapper<C, BlockSize: ArrayLength<u8>> {
core: C,
buffer: BlockBuffer<BlockSize>,
pub struct XofReaderCoreWrapper<T: XofReaderCore> {
core: T,
buffer: BlockBuffer<T::BlockSize>,
}

impl<T: UpdateCore + AlgorithmName> fmt::Debug for UpdateCoreWrapper<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.write_str(T::NAME)?;
f.write_str(" { .. }")
}
}

impl<T: XofReaderCore + AlgorithmName> fmt::Debug for XofReaderCoreWrapper<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.write_str(T::NAME)?;
f.write_str(" { .. }")
}
}

impl<D: Reset + UpdateCore> Reset for CoreWrapper<D, D::BlockSize> {
impl<D: Reset + UpdateCore> Reset for UpdateCoreWrapper<D> {
#[inline]
fn reset(&mut self) {
self.core.reset();
self.buffer.reset();
}
}

impl<D: UpdateCore> Update for CoreWrapper<D, D::BlockSize> {
impl<D: UpdateCore> Update for UpdateCoreWrapper<D> {
#[inline]
fn update(&mut self, input: &[u8]) {
let Self { core, buffer } = self;
buffer.digest_blocks(input, |blocks| core.update_blocks(blocks));
}
}

impl<D: FixedOutputCore + Reset> FixedOutput for CoreWrapper<D, D::BlockSize> {
impl<D: FixedOutputCore + Reset> FixedOutput for UpdateCoreWrapper<D> {
type OutputSize = D::OutputSize;

#[inline]
Expand All @@ -107,22 +137,22 @@ impl<D: FixedOutputCore + Reset> FixedOutput for CoreWrapper<D, D::BlockSize> {
}
}

impl<R: XofReaderCore> XofReader for CoreWrapper<R, R::BlockSize> {
impl<R: XofReaderCore> XofReader for XofReaderCoreWrapper<R> {
#[inline]
fn read(&mut self, buffer: &mut [u8]) {
let Self { core, buffer: buf } = self;
buf.set_data(buffer, || core.read_block());
}
}

impl<D: ExtendableOutputCore + Reset> ExtendableOutput for CoreWrapper<D, D::BlockSize> {
type Reader = CoreWrapper<D::ReaderCore, <D::ReaderCore as XofReaderCore>::BlockSize>;
impl<D: ExtendableOutputCore + Reset> ExtendableOutput for UpdateCoreWrapper<D> {
type Reader = XofReaderCoreWrapper<D::ReaderCore>;

#[inline]
fn finalize_xof(mut self) -> Self::Reader {
let Self { core, buffer } = &mut self;
let reader_core = core.finalize_xof_core(buffer);
CoreWrapper {
XofReaderCoreWrapper {
core: reader_core,
buffer: Default::default(),
}
Expand All @@ -133,15 +163,15 @@ impl<D: ExtendableOutputCore + Reset> ExtendableOutput for CoreWrapper<D, D::Blo
let Self { core, buffer } = self;
let reader_core = core.finalize_xof_core(buffer);
self.reset();
CoreWrapper {
XofReaderCoreWrapper {
core: reader_core,
buffer: Default::default(),
}
}
}

#[cfg(feature = "std")]
impl<D: UpdateCore> std::io::Write for CoreWrapper<D, D::BlockSize> {
impl<D: UpdateCore> std::io::Write for UpdateCoreWrapper<D> {
#[inline]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
Update::update(self, buf);
Expand All @@ -155,7 +185,7 @@ impl<D: UpdateCore> std::io::Write for CoreWrapper<D, D::BlockSize> {
}

#[cfg(feature = "std")]
impl<R: XofReaderCore> std::io::Read for CoreWrapper<R, R::BlockSize> {
impl<R: XofReaderCore> std::io::Read for XofReaderCoreWrapper<R> {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
XofReader::read(self, buf);
Expand Down
15 changes: 9 additions & 6 deletions digest/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
//! These traits atomically describe available functionality of hash function
//! implementations.
//! - **Low-level traits**: [`UpdateCore`], [`FixedOutputCore`],
//! [`ExtendableOutputCore`]. These traits operate at a block-level and do not
//! contain any built-in buffering. They are intended to be implemented
//! by low-level algorithm providers only and simplify the amount of work
//! implementers need to do and therefore usually shouldn't be used in
//! application-level code.
//! [`ExtendableOutputCore`], [`AlgorithmName`]. These traits operate at
//! a block-level and do not contain any built-in buffering. They are intended
//! to be implemented by low-level algorithm providers only and simplify
//! the amount of work implementers need to do and therefore usually shouldn't
//! be used in application-level code.
//!
//! Additionally hash functions implement traits from the standard library:
//! [`Default`], [`Clone`], [`Write`][std::io::Write]. The latter is
Expand Down Expand Up @@ -54,7 +54,10 @@ mod digest;
mod dyn_digest;

#[cfg(feature = "core-api")]
pub use crate::core_api::{CoreWrapper, ExtendableOutputCore, FixedOutputCore, UpdateCore};
pub use crate::core_api::{
AlgorithmName, ExtendableOutputCore, FixedOutputCore, UpdateCore, UpdateCoreWrapper,
XofReaderCoreWrapper,
};
pub use crate::digest::{Digest, Output};
#[cfg(feature = "core-api")]
pub use block_buffer;
Expand Down