mirror of
https://github.com/RustCrypto/hashes.git
synced 2026-01-25 04:18:20 +00:00
sha3 improvements. fixed #42
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "sha3"
|
||||
version = "0.7.0"
|
||||
version = "0.7.1"
|
||||
authors = ["RustCrypto Developers"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "SHA-3 (Keccak) hash function"
|
||||
|
||||
@@ -30,12 +30,14 @@
|
||||
//! println!("{:x}", out);
|
||||
//! ```
|
||||
|
||||
#![no_std]
|
||||
//#![no_std]
|
||||
extern crate byte_tools;
|
||||
#[macro_use]
|
||||
extern crate digest;
|
||||
extern crate block_buffer;
|
||||
|
||||
use std as core;
|
||||
|
||||
pub use digest::Digest;
|
||||
use block_buffer::{
|
||||
BlockBuffer576, BlockBuffer832, BlockBuffer1152, BlockBuffer1088,
|
||||
@@ -46,9 +48,6 @@ use digest::generic_array::typenum::{
|
||||
U28, U32, U48, U64, U72, U104, U136, U144, U168, Unsigned,
|
||||
};
|
||||
|
||||
use byte_tools::write_u64v_le;
|
||||
use core::mem::transmute;
|
||||
|
||||
mod keccak;
|
||||
mod consts;
|
||||
mod paddings;
|
||||
@@ -58,7 +57,6 @@ mod reader;
|
||||
mod state;
|
||||
|
||||
pub use reader::Sha3XofReader;
|
||||
use consts::PLEN;
|
||||
use state::Sha3State;
|
||||
|
||||
sha3_impl!(Keccak224, U28, U144, BlockBuffer1152, paddings::Keccak);
|
||||
|
||||
@@ -7,7 +7,7 @@ macro_rules! impl_state {
|
||||
state: Sha3State,
|
||||
buffer: $buffer,
|
||||
}
|
||||
|
||||
|
||||
impl $state {
|
||||
fn absorb(&mut self, input: &[u8]) {
|
||||
let self_state = &mut self.state;
|
||||
@@ -44,21 +44,13 @@ macro_rules! sha3_impl {
|
||||
type OutputSize = $output_size;
|
||||
|
||||
fn fixed_result(mut self) -> GenericArray<u8, Self::OutputSize> {
|
||||
let mut out = GenericArray::default();
|
||||
self.apply_padding();
|
||||
|
||||
let mut state_copy;
|
||||
let state_ref: &[u8; PLEN*8] = if cfg!(target_endian = "little") {
|
||||
unsafe { transmute(&self.state) }
|
||||
} else if cfg!(target_endian = "big") {
|
||||
state_copy = [0u8; PLEN*8];
|
||||
write_u64v_le(&mut state_copy, &self.state.state);
|
||||
&state_copy
|
||||
} else { unreachable!() };
|
||||
|
||||
let mut out = GenericArray::default();
|
||||
let n = out.len();
|
||||
out.copy_from_slice(&state_ref[..n]);
|
||||
|
||||
self.state.as_bytes(|state| {
|
||||
out.copy_from_slice(&state[..n]);
|
||||
});
|
||||
out
|
||||
}
|
||||
}
|
||||
@@ -83,7 +75,7 @@ macro_rules! shake_impl {
|
||||
fn xof_result(mut self) -> Sha3XofReader
|
||||
{
|
||||
self.apply_padding();
|
||||
Sha3XofReader::new(self.state.state, $rate::to_usize())
|
||||
Sha3XofReader::new(self.state, $rate::to_usize())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,71 +1,52 @@
|
||||
use digest;
|
||||
use byte_tools::write_u64v_le;
|
||||
use consts::PLEN;
|
||||
use core::mem::transmute;
|
||||
use core::cmp::min;
|
||||
use keccak;
|
||||
use state::Sha3State;
|
||||
|
||||
/// Reader state for extracting extendable output.
|
||||
pub struct Sha3XofReader {
|
||||
state: [u64; PLEN],
|
||||
state: Sha3State,
|
||||
rate: usize,
|
||||
pos: usize,
|
||||
}
|
||||
|
||||
impl Sha3XofReader {
|
||||
pub(crate) fn new(state: [u64; PLEN], rate: usize) -> Self {
|
||||
Sha3XofReader{ state: state, rate: rate }
|
||||
pub(crate) fn new(state: Sha3State, rate: usize) -> Self {
|
||||
Sha3XofReader{ state: state, rate: rate, pos: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl digest::XofReader for Sha3XofReader {
|
||||
fn read(&mut self, buffer: &mut [u8]) {
|
||||
let mut offset = 0;
|
||||
|
||||
let buffer_len = buffer.len();
|
||||
|
||||
let in_len = buffer.len();
|
||||
let mut in_pos: usize = 0;
|
||||
|
||||
// Squeeze
|
||||
while in_pos < in_len {
|
||||
let rate = self.rate;
|
||||
let off_n = offset % rate;
|
||||
let mut nread = min(rate - off_n, in_len - in_pos);
|
||||
if buffer_len != 0 {
|
||||
nread = min(nread, buffer_len - offset);
|
||||
}
|
||||
|
||||
|
||||
let mut state_copy;
|
||||
let state_ref: &[u8; PLEN*8] = if cfg!(target_endian = "little") {
|
||||
unsafe { transmute(&mut self.state) }
|
||||
} else if cfg!(target_endian = "big") {
|
||||
state_copy = [0u8; PLEN*8];
|
||||
write_u64v_le(&mut state_copy, &self.state);
|
||||
&state_copy
|
||||
} else { unreachable!() };
|
||||
|
||||
|
||||
let off = offset % self.rate;
|
||||
let part = &state_ref[off..off+nread];
|
||||
buffer[in_pos..in_pos+nread].copy_from_slice(part);
|
||||
|
||||
in_pos += nread;
|
||||
|
||||
if off_n + nread != rate {
|
||||
offset += nread;
|
||||
break;
|
||||
}
|
||||
|
||||
if buffer_len == 0 {
|
||||
offset = 0;
|
||||
} else {
|
||||
offset += nread;
|
||||
}
|
||||
|
||||
keccak::f(&mut self.state);
|
||||
fn read(&mut self, mut buffer: &mut [u8]) {
|
||||
let rem = self.rate - self.pos;
|
||||
let n = buffer.len();
|
||||
if n >= rem {
|
||||
let (l, r) = {buffer}.split_at_mut(rem);
|
||||
buffer = r;
|
||||
self.state.as_bytes(|state| {
|
||||
l.copy_from_slice(&state[self.pos..self.rate]);
|
||||
});
|
||||
self.state.apply_f();
|
||||
} else {
|
||||
self.state.as_bytes(|state| {
|
||||
buffer.copy_from_slice(&state[self.pos..self.pos+n]);
|
||||
});
|
||||
self.pos += n;
|
||||
return;
|
||||
}
|
||||
|
||||
assert!(buffer_len != 0 && buffer_len == offset, "Not everything squeezed");
|
||||
while buffer.len() >= self.rate {
|
||||
let (l, r) = {buffer}.split_at_mut(self.rate);
|
||||
buffer = r;
|
||||
|
||||
self.state.as_bytes(|state| {
|
||||
l.copy_from_slice(&state[..self.rate]);
|
||||
});
|
||||
self.state.apply_f();
|
||||
}
|
||||
|
||||
let n = buffer.len();
|
||||
self.pos = n;
|
||||
self.state.as_bytes(|state| {
|
||||
buffer.copy_from_slice(&state[..n]);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use keccak;
|
||||
use consts::PLEN;
|
||||
use byte_tools::read_u64v_le;
|
||||
use core::mem::transmute;
|
||||
use byte_tools::{read_u64v_le, write_u64v_le};
|
||||
use core::mem;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub(crate) struct Sha3State {
|
||||
@@ -16,7 +16,7 @@ impl Sha3State {
|
||||
|
||||
let mut buf;
|
||||
let buf: &[u64] = if cfg!(target_endian = "little") {
|
||||
unsafe { transmute(block) }
|
||||
unsafe { mem::transmute(block) }
|
||||
} else if cfg!(target_endian = "big") {
|
||||
buf = [0u64; 21];
|
||||
let buf = &mut buf[..n];
|
||||
@@ -30,4 +30,22 @@ impl Sha3State {
|
||||
|
||||
keccak::f(&mut self.state);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn as_bytes<F: FnOnce(&[u8; 8*PLEN])>(&self, f: F) {
|
||||
let mut data_copy;
|
||||
let data_ref: &[u8; 8*PLEN] = if cfg!(target_endian = "little") {
|
||||
unsafe { mem::transmute(&self.state) }
|
||||
} else {
|
||||
data_copy = [0u8; 8*PLEN];
|
||||
write_u64v_le(&mut data_copy, &self.state);
|
||||
&data_copy
|
||||
};
|
||||
f(data_ref);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn apply_f(&mut self) {
|
||||
keccak::f(&mut self.state);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user