sha3 improvements. fixed #42

This commit is contained in:
newpavlov
2017-11-17 20:03:06 +03:00
parent 127a6d4957
commit 5a5688c2b8
5 changed files with 68 additions and 79 deletions

View File

@@ -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"

View File

@@ -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);

View File

@@ -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())
}
}

View File

@@ -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]);
});
}
}
}

View File

@@ -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);
}
}