Skip to content

Commit 702bcd8

Browse files
authored
Migrate to closure-based keccak (#796)
1 parent 827c043 commit 702bcd8

5 files changed

Lines changed: 65 additions & 59 deletions

File tree

Cargo.lock

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,5 @@ opt-level = 2
3434
sha1 = { path = "sha1" }
3535
sha3 = { path = "sha3" }
3636
whirlpool = { path = "whirlpool" }
37+
38+
keccak = { git = "https://github.com/RustCrypto/sponges" }

sha3/src/block_api.rs

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use crate::{DEFAULT_ROUND_COUNT, PLEN};
21
use core::{fmt, marker::PhantomData};
32
use digest::{
43
HashMarker, Output,
@@ -11,22 +10,19 @@ use digest::{
1110
common::hazmat::{DeserializeStateError, SerializableState, SerializedState},
1211
typenum::{IsLessOrEqual, True, U0, U200},
1312
};
14-
use keccak::KeccakP1600;
13+
use keccak::{F1600_ROUNDS, Keccak, State1600};
1514

1615
pub use crate::cshake::{CShake128Core, CShake256Core};
1716

1817
/// Core Sha3 fixed output hasher state.
1918
#[derive(Clone)]
20-
pub struct Sha3HasherCore<
21-
Rate,
22-
OutputSize,
23-
const PAD: u8,
24-
const ROUNDS: usize = DEFAULT_ROUND_COUNT,
25-
> where
19+
pub struct Sha3HasherCore<Rate, OutputSize, const PAD: u8, const ROUNDS: usize = F1600_ROUNDS>
20+
where
2621
Rate: BlockSizes + IsLessOrEqual<U200, Output = True>,
2722
OutputSize: ArraySize + IsLessOrEqual<U200, Output = True>,
2823
{
29-
state: KeccakP1600,
24+
state: State1600,
25+
keccak: Keccak,
3026
_pd: PhantomData<(Rate, OutputSize)>,
3127
}
3228

@@ -73,10 +69,12 @@ where
7369
{
7470
#[inline]
7571
fn update_blocks(&mut self, blocks: &[Block<Self>]) {
76-
for block in blocks {
77-
xor_block(self.state.as_mut(), block);
78-
self.state.p1600(ROUNDS);
79-
}
72+
self.keccak.with_p1600::<ROUNDS>(|p1600| {
73+
for block in blocks {
74+
xor_block(&mut self.state, block);
75+
p1600(&mut self.state);
76+
}
77+
});
8078
}
8179
}
8280

@@ -94,12 +92,14 @@ where
9492
let n = block.len();
9593
block[n - 1] |= 0x80;
9694

97-
xor_block(self.state.as_mut(), &block);
98-
self.state.p1600(ROUNDS);
95+
self.keccak.with_p1600::<ROUNDS>(|p1600| {
96+
xor_block(&mut self.state, &block);
97+
p1600(&mut self.state);
9998

100-
for (o, s) in out.chunks_mut(8).zip(self.state.as_mut().iter()) {
101-
o.copy_from_slice(&s.to_le_bytes()[..o.len()]);
102-
}
99+
for (o, s) in out.chunks_mut(8).zip(self.state.as_mut().iter()) {
100+
o.copy_from_slice(&s.to_le_bytes()[..o.len()]);
101+
}
102+
});
103103
}
104104
}
105105

@@ -118,10 +118,12 @@ where
118118
let n = block.len();
119119
block[n - 1] |= 0x80;
120120

121-
xor_block(self.state.as_mut(), &block);
122-
self.state.p1600(ROUNDS);
121+
self.keccak.with_p1600::<ROUNDS>(|p1600| {
122+
xor_block(&mut self.state, &block);
123+
p1600(&mut self.state);
124+
});
123125

124-
Sha3ReaderCore::new(self.state.as_ref())
126+
Sha3ReaderCore::new(&self.state, self.keccak)
125127
}
126128
}
127129

@@ -135,6 +137,7 @@ where
135137
fn default() -> Self {
136138
Self {
137139
state: Default::default(),
140+
keccak: Keccak::new(),
138141
_pd: PhantomData,
139142
}
140143
}
@@ -219,38 +222,38 @@ where
219222
fn deserialize(
220223
serialized_state: &SerializedState<Self>,
221224
) -> Result<Self, DeserializeStateError> {
222-
let mut state = [0; PLEN];
225+
let mut state = State1600::default();
223226
let chunks = serialized_state.chunks_exact(8);
224227
for (val, chunk) in state.iter_mut().zip(chunks) {
225228
*val = u64::from_le_bytes(chunk.try_into().unwrap());
226229
}
227230

228231
Ok(Self {
229-
state: KeccakP1600::from(state),
232+
state,
233+
keccak: Keccak::new(),
230234
_pd: PhantomData,
231235
})
232236
}
233237
}
234238

235239
/// Core Sha3 XOF reader.
236240
#[derive(Clone)]
237-
pub struct Sha3ReaderCore<Rate, const ROUNDS: usize = DEFAULT_ROUND_COUNT>
241+
pub struct Sha3ReaderCore<Rate, const ROUNDS: usize = F1600_ROUNDS>
238242
where
239243
Rate: BlockSizes + IsLessOrEqual<U200, Output = True>,
240244
{
241-
state: [u64; PLEN],
245+
state: State1600,
246+
keccak: Keccak,
242247
_pd: PhantomData<Rate>,
243248
}
244249

245250
impl<Rate, const ROUNDS: usize> Sha3ReaderCore<Rate, ROUNDS>
246251
where
247252
Rate: BlockSizes + IsLessOrEqual<U200, Output = True>,
248253
{
249-
pub(crate) fn new(state: &[u64; PLEN]) -> Self {
250-
Self {
251-
state: *state,
252-
_pd: PhantomData,
253-
}
254+
pub(crate) fn new(&state: &State1600, keccak: Keccak) -> Self {
255+
let _pd = PhantomData;
256+
Self { state, keccak, _pd }
254257
}
255258
}
256259

@@ -271,7 +274,8 @@ where
271274
for (src, dst) in self.state.iter().zip(block.chunks_mut(8)) {
272275
dst.copy_from_slice(&src.to_le_bytes()[..dst.len()]);
273276
}
274-
keccak::p1600(&mut self.state, ROUNDS);
277+
self.keccak
278+
.with_p1600::<ROUNDS>(|p1600| p1600(&mut self.state));
275279
block
276280
}
277281
}
@@ -304,8 +308,8 @@ impl<Rate, const ROUNDS: usize> digest::zeroize::ZeroizeOnDrop for Sha3ReaderCor
304308
{
305309
}
306310

307-
pub(crate) fn xor_block(state: &mut [u64; PLEN], block: &[u8]) {
308-
assert!(block.len() < 8 * PLEN);
311+
pub(crate) fn xor_block(state: &mut State1600, block: &[u8]) {
312+
assert!(size_of_val(block) < size_of_val(state));
309313

310314
let mut chunks = block.chunks_exact(8);
311315
for (s, chunk) in state.iter_mut().zip(&mut chunks) {

sha3/src/cshake.rs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
use crate::{
2-
CSHAKE_PAD, DEFAULT_ROUND_COUNT as ROUNDS, PLEN, SHAKE_PAD, Sha3ReaderCore,
3-
block_api::xor_block,
4-
};
1+
use crate::{CSHAKE_PAD, SHAKE_PAD, Sha3ReaderCore, block_api::xor_block};
52
use core::fmt;
63
use digest::{
74
CollisionResistance, CustomizedInit, HashMarker, Reset,
@@ -13,6 +10,7 @@ use digest::{
1310
consts::{U16, U32, U136, U168, U400},
1411
typenum::Unsigned,
1512
};
13+
use keccak::{F1600_ROUNDS as ROUNDS, Keccak, State1600};
1614

1715
macro_rules! impl_cshake {
1816
(
@@ -22,8 +20,9 @@ macro_rules! impl_cshake {
2220
#[doc = " core hasher."]
2321
#[derive(Clone, Default)]
2422
pub struct $name {
25-
state: [u64; PLEN],
26-
initial_state: [u64; PLEN],
23+
state: State1600,
24+
initial_state: State1600,
25+
keccak: Keccak,
2726
}
2827

2928
impl $name {
@@ -87,10 +86,12 @@ macro_rules! impl_cshake {
8786
impl UpdateCore for $name {
8887
#[inline]
8988
fn update_blocks(&mut self, blocks: &[Block<Self>]) {
90-
for block in blocks {
91-
xor_block(&mut self.state, block);
92-
keccak::p1600(&mut self.state, ROUNDS);
93-
}
89+
self.keccak.with_p1600::<ROUNDS>(|p1600| {
90+
for block in blocks {
91+
xor_block(&mut self.state, block);
92+
p1600(&mut self.state);
93+
}
94+
})
9495
}
9596
}
9697

@@ -101,7 +102,7 @@ macro_rules! impl_cshake {
101102
fn finalize_xof_core(&mut self, buffer: &mut Buffer<Self>) -> Self::ReaderCore {
102103
let pos = buffer.get_pos();
103104
let mut block = buffer.pad_with_zeros();
104-
let pad = if self.initial_state == [0; PLEN] {
105+
let pad = if self.initial_state == State1600::default() {
105106
SHAKE_PAD
106107
} else {
107108
CSHAKE_PAD
@@ -110,10 +111,12 @@ macro_rules! impl_cshake {
110111
let n = block.len();
111112
block[n - 1] |= 0x80;
112113

113-
xor_block(&mut self.state, &block);
114-
keccak::p1600(&mut self.state, ROUNDS);
114+
self.keccak.with_p1600::<ROUNDS>(|p1600| {
115+
xor_block(&mut self.state, &block);
116+
p1600(&mut self.state);
117+
});
115118

116-
Sha3ReaderCore::new(&self.state)
119+
Sha3ReaderCore::new(&self.state, self.keccak)
117120
}
118121
}
119122

@@ -179,7 +182,7 @@ macro_rules! impl_cshake {
179182
let chunk = initial_state_src[8 * i..][..8].try_into().unwrap();
180183
u64::from_le_bytes(chunk)
181184
});
182-
Ok(Self{ state, initial_state })
185+
Ok(Self{ state, initial_state, keccak: Keccak::new() })
183186
}
184187
}
185188

sha3/src/lib.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ const SHA3_PAD: u8 = 0x06;
2828
const SHAKE_PAD: u8 = 0x1f;
2929
const CSHAKE_PAD: u8 = 0x04;
3030

31-
const PLEN: usize = 25;
32-
const DEFAULT_ROUND_COUNT: usize = 24;
33-
3431
digest::buffer_fixed!(
3532
/// SHA-3-224 hasher.
3633
pub struct Sha3_224(Sha3HasherCore<U144, U28, SHA3_PAD>);

0 commit comments

Comments
 (0)