Skip to content

Commit e1cfd53

Browse files
committed
migrate to the latest version of sponge-cursor
1 parent 167bea9 commit e1cfd53

4 files changed

Lines changed: 133 additions & 240 deletions

File tree

Cargo.lock

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

bash-prg-hash/src/lib.rs

Lines changed: 90 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -14,117 +14,110 @@ pub use digest::{self, Digest};
1414
mod oids;
1515
mod variants;
1616

17-
use crate::variants::Rate;
17+
pub use variants::*;
18+
1819
use bash_f::{STATE_WORDS, bash_f};
1920
use core::fmt;
2021
use digest::{
2122
ExtendableOutput, ExtendableOutputReset, Reset, TryCustomizedInit, Update, XofReader,
22-
typenum::{U1, U2, U16, U24, U32},
2323
};
2424
use sponge_cursor::SpongeCursor;
25-
pub use variants::{Capacity, SecurityLevel};
26-
27-
/// Invalid header length error
28-
#[derive(Debug)]
29-
pub struct InvalidHeaderLength;
3025

3126
/// Data type codes from Table 3 of STB 34.101.77-2020
3227
const DATA: u8 = 0b000010;
3328
/// Data type codes from Table 3 of STB 34.101.77-2020
3429
const OUT: u8 = 0b000100;
3530

36-
/// `bash-prg-hash` hasher generic over security level and capacity.
31+
/// `bash-prg-hash` hasher generic over rate and capacity.
3732
///
3833
/// # Generic Parameters
3934
///
40-
/// - `L`: Security level ℓ ∈ {128, 192, 256}. Use `U16`, `U24`, or `U32` from `digest::typenum`.
41-
/// - `D`: Capacity d ∈ {1, 2}. Use `U1` or `U2` from `digest::typenum`.
35+
/// Only the following combinations of rate and capacity with
36+
/// the resulting security level are supported:
4237
///
43-
/// # Examples
38+
/// | Rate, bytes | Capacity | Security level, bits |
39+
/// |:-----------:|:--------:|:--------------------:|
40+
/// | 160 | 1 | 128 |
41+
/// | 128 | 2 | 128 |
42+
/// | 144 | 1 | 192 |
43+
/// | 96 | 2 | 192 |
44+
/// | 128 | 1 | 256 |
45+
/// | 64 | 2 | 256 |
4446
///
45-
/// ```
46-
/// use bash_prg_hash::{BashPrgHash1281, digest::{ExtendableOutput, Update, XofReader}};
47+
/// Trying to initialize hasher state with a different pair of parameters will
48+
/// result in a compilation error.
4749
///
48-
/// let mut hasher = BashPrgHash1281::default();
49-
/// hasher.update(b"hello world");
50-
/// let mut reader = hasher.finalize_xof();
51-
/// let mut output = [0u8; 32];
52-
/// reader.read(&mut output);
53-
/// ```
50+
/// Users are recommended to use type aliases (e.g. [`BashPrgHash1281`]) instead of using
51+
/// this type directly.
52+
// Note: Ideally, we would use `LEVEL` instead of `RATE` and define the `cursor` field as
53+
// `SpongeCursor<{192-2*CAPACITY*LEVEL}>`, but it requires stabilized `generic_const_exprs`.
5454
#[derive(Clone)]
55-
pub struct BashPrgHash<L: SecurityLevel, D: Capacity>
56-
where
57-
(L, D): Rate,
58-
{
55+
pub struct BashPrgHash<const RATE: usize, const CAPACITY: usize> {
5956
state: [u64; STATE_WORDS],
60-
cursor: SpongeCursor<<(L, D) as Rate>::Rate>,
57+
cursor: SpongeCursor<RATE>,
6158
}
6259

63-
impl<L: SecurityLevel, D: Capacity> Default for BashPrgHash<L, D>
64-
where
65-
(L, D): Rate,
66-
{
60+
impl<const RATE: usize, const CAPACITY: usize> Default for BashPrgHash<RATE, CAPACITY> {
61+
#[inline]
6762
fn default() -> Self {
68-
Self::try_new_customized(&[][..]).expect("Always correct")
63+
Self::try_new_customized(&[]).expect("Always correct")
6964
}
7065
}
7166

72-
impl<L: SecurityLevel, D: Capacity> TryCustomizedInit for BashPrgHash<L, D>
73-
where
74-
(L, D): Rate,
75-
{
76-
type Error = InvalidHeaderLength;
67+
impl<const RATE: usize, const CAPACITY: usize> TryCustomizedInit for BashPrgHash<RATE, CAPACITY> {
68+
type Error = InvalidHeaderError;
7769

70+
#[inline]
7871
fn try_new_customized(header: &[u8]) -> Result<Self, Self::Error> {
7972
const MAX_HEADER_LEN: usize = 60;
8073

8174
if header.len() > MAX_HEADER_LEN || header.len() % 4 != 0 {
82-
return Err(InvalidHeaderLength);
75+
return Err(InvalidHeaderError);
8376
}
8477

85-
let mut this = Self {
78+
let mut s = Self {
8679
state: [0u64; STATE_WORDS],
8780
cursor: SpongeCursor::default(),
8881
};
8982

90-
this.start(header);
91-
this.commit(DATA);
83+
s.start(header);
84+
s.commit(DATA);
9285

93-
Ok(this)
86+
Ok(s)
9487
}
9588
}
9689

97-
impl<L: SecurityLevel, D: Capacity> Update for BashPrgHash<L, D>
98-
where
99-
(L, D): Rate,
100-
{
90+
impl<const RATE: usize, const CAPACITY: usize> BashPrgHash<RATE, CAPACITY> {}
91+
92+
impl<const RATE: usize, const CAPACITY: usize> Update for BashPrgHash<RATE, CAPACITY> {
93+
#[inline]
10194
fn update(&mut self, data: &[u8]) {
102-
self.absorb(data);
95+
// `absorb[ℓ, d](X)` (Section 8.6.2)
96+
self.cursor.absorb_u64_le(&mut self.state, bash_f, data);
10397
}
10498
}
10599

106-
impl<L: SecurityLevel, D: Capacity> ExtendableOutput for BashPrgHash<L, D>
107-
where
108-
(L, D): Rate,
109-
{
110-
type Reader = BashPrgHashReader<L, D>;
100+
impl<const RATE: usize, const CAPACITY: usize> ExtendableOutput for BashPrgHash<RATE, CAPACITY> {
101+
type Reader = BashPrgHashReader<RATE, CAPACITY>;
111102

103+
#[inline]
112104
fn finalize_xof(mut self) -> Self::Reader {
113-
self.finalize();
105+
// `squeezePrep[ℓ, d]()` / output preparation: `commit(OUT)` (Section 8.7).
106+
self.commit(OUT);
114107
BashPrgHashReader {
115108
state: self.state,
116109
cursor: self.cursor.clone(),
117110
}
118111
}
119112
}
120113

121-
impl<L: SecurityLevel, D: Capacity> ExtendableOutputReset for BashPrgHash<L, D>
122-
where
123-
(L, D): Rate,
114+
impl<const RATE: usize, const CAPACITY: usize> ExtendableOutputReset
115+
for BashPrgHash<RATE, CAPACITY>
124116
{
117+
#[inline]
125118
fn finalize_xof_reset(&mut self) -> Self::Reader {
126119
let mut hasher_clone = self.clone();
127-
hasher_clone.finalize();
120+
hasher_clone.commit(OUT);
128121
self.reset();
129122
BashPrgHashReader {
130123
state: hasher_clone.state,
@@ -133,66 +126,47 @@ where
133126
}
134127
}
135128

136-
impl<L: SecurityLevel, D: Capacity> Reset for BashPrgHash<L, D>
137-
where
138-
(L, D): Rate,
139-
{
129+
impl<const RATE: usize, const CAPACITY: usize> Reset for BashPrgHash<RATE, CAPACITY> {
130+
#[inline]
140131
fn reset(&mut self) {
141132
*self = Self::default();
142133
}
143134
}
144135

145-
impl<L: SecurityLevel, D: Capacity> fmt::Debug for BashPrgHash<L, D>
146-
where
147-
(L, D): Rate,
148-
{
136+
impl<const RATE: usize, const CAPACITY: usize> fmt::Debug for BashPrgHash<RATE, CAPACITY> {
137+
#[inline]
149138
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150139
f.write_str("BashPrgHash { ... }")
151140
}
152141
}
153142

154-
impl<L: SecurityLevel, D: Capacity> digest::CollisionResistance for BashPrgHash<L, D>
155-
where
156-
(L, D): Rate,
157-
{
158-
type CollisionResistance = L;
159-
}
160-
161143
#[cfg(feature = "zeroize")]
162-
impl<L: SecurityLevel, D: Capacity> digest::zeroize::ZeroizeOnDrop for BashPrgHash<L, D> where
163-
(L, D): Rate
144+
impl<const RATE: usize, const CAPACITY: usize> digest::zeroize::ZeroizeOnDrop
145+
for BashPrgHash<RATE, CAPACITY>
164146
{
165147
}
166148

167149
/// Reader for bash-prg-hash XOF output.
168150
#[derive(Clone)]
169-
pub struct BashPrgHashReader<L: SecurityLevel, D: Capacity>
170-
where
171-
(L, D): Rate,
172-
{
151+
pub struct BashPrgHashReader<const RATE: usize, const CAPACITY: usize> {
173152
state: [u64; STATE_WORDS],
174-
cursor: SpongeCursor<<(L, D) as Rate>::Rate>,
153+
cursor: SpongeCursor<RATE>,
175154
}
176155

177-
impl<L: SecurityLevel, D: Capacity> XofReader for BashPrgHashReader<L, D>
178-
where
179-
(L, D): Rate,
180-
{
156+
impl<const RATE: usize, const CAPACITY: usize> XofReader for BashPrgHashReader<RATE, CAPACITY> {
157+
#[inline]
181158
fn read(&mut self, buffer: &mut [u8]) {
182159
self.squeeze(buffer);
183160
}
184161
}
185162

186163
#[cfg(feature = "zeroize")]
187-
impl<L: SecurityLevel, D: Capacity> digest::zeroize::ZeroizeOnDrop for BashPrgHashReader<L, D> where
188-
(L, D): Rate
164+
impl<const RATE: usize, const CAPACITY: usize> digest::zeroize::ZeroizeOnDrop
165+
for BashPrgHashReader<RATE, CAPACITY>
189166
{
190167
}
191168

192-
impl<L: SecurityLevel, D: Capacity> BashPrgHash<L, D>
193-
where
194-
(L, D): Rate,
195-
{
169+
impl<const RATE: usize, const CAPACITY: usize> BashPrgHash<RATE, CAPACITY> {
196170
/// Modify byte at position in state
197171
fn modify_byte(state: &mut [u64; STATE_WORDS], pos: usize, f: impl FnOnce(&mut u8)) {
198172
let word_idx = pos / 8;
@@ -218,21 +192,10 @@ where
218192
self.cursor = SpongeCursor::new(pos).expect("pos within bounds");
219193

220194
// Step 6: S[1472...) <- <ℓ/4 + d>_64
221-
self.state[23] = (L::USIZE * 2 + D::USIZE) as u64;
195+
let level = (192 - RATE) / (2 * CAPACITY);
196+
self.state[23] = (level * 2 + CAPACITY) as u64;
222197
}
223198

224-
/// `squeezePrep[ℓ, d]()` / output preparation: `commit(OUT)` (Section 8.7).
225-
fn finalize(&mut self) {
226-
self.commit(OUT);
227-
}
228-
}
229-
230-
impl<L: SecurityLevel, D: Capacity> BashPrgHash<L, D>
231-
where
232-
(L, D): Rate,
233-
{
234-
const RATE: usize = 192 - 2 * D::USIZE * L::USIZE;
235-
236199
fn get_byte(state: &[u64; STATE_WORDS], pos: usize) -> u8 {
237200
let word_idx = pos / 8;
238201
let byte_in_word = pos % 8;
@@ -245,12 +208,6 @@ where
245208
}
246209
}
247210

248-
/// `absorb[ℓ, d](X)` (Section 8.6.2)
249-
fn absorb(&mut self, data: &[u8]) {
250-
self.cursor
251-
.absorb_u64_le::<STATE_WORDS>(&mut self.state, bash_f, data);
252-
}
253-
254211
/// `commit[ℓ, d](t)` (Section 8.4.2)
255212
fn commit(&mut self, t: u8) {
256213
let pos = self.cursor.pos();
@@ -260,10 +217,8 @@ where
260217
Self::modify_byte(&mut self.state, pos, |b| *b ^= tag);
261218

262219
// Step 2: S[r] <- S[r] ⊕ 1, where r = 1536 - 2 d ℓ (bit index).
263-
let r_bit_in_byte = (Self::RATE * 8) % 8;
264-
Self::modify_byte(&mut self.state, Self::RATE, |b| {
265-
*b ^= 1u8 << (7 - r_bit_in_byte)
266-
});
220+
let r_bit_in_byte = (RATE * 8) % 8;
221+
Self::modify_byte(&mut self.state, RATE, |b| *b ^= 1u8 << (7 - r_bit_in_byte));
267222

268223
// Step 3: S <- bash-f(S).
269224
bash_f(&mut self.state);
@@ -272,24 +227,25 @@ where
272227
}
273228
}
274229

275-
impl<L: SecurityLevel, D: Capacity> BashPrgHashReader<L, D>
276-
where
277-
(L, D): Rate,
278-
{
230+
impl<const RATE: usize, const CAPACITY: usize> BashPrgHashReader<RATE, CAPACITY> {
279231
/// `squeeze[ℓ, d](Y)` (Section 8.7.2)
280232
fn squeeze(&mut self, output: &mut [u8]) {
281233
let mut remaining = output;
282234

283235
while !remaining.is_empty() {
284236
// Step 1: Split Y into the next chunk Yi with |Yi| <= r - pos.
285237
let pos = self.cursor.pos();
286-
let to_squeeze = remaining.len().min(BashPrgHash::<L, D>::RATE - pos);
238+
let to_squeeze = remaining.len().min(RATE - pos);
287239

288240
// Step 2: Yi <- S[pos..pos+|Yi|), pos <- pos + |Yi|.
289-
BashPrgHash::<L, D>::extract_bytes(&self.state, pos, &mut remaining[..to_squeeze]);
241+
BashPrgHash::<RATE, CAPACITY>::extract_bytes(
242+
&self.state,
243+
pos,
244+
&mut remaining[..to_squeeze],
245+
);
290246
remaining = &mut remaining[to_squeeze..];
291247

292-
if pos + to_squeeze == BashPrgHash::<L, D>::RATE {
248+
if pos + to_squeeze == RATE {
293249
// Step 3: If pos = r then S <- bash-f(S), pos <- 0.
294250
bash_f(&mut self.state);
295251
self.cursor = SpongeCursor::default();
@@ -301,10 +257,8 @@ where
301257
}
302258
}
303259

304-
impl<L: SecurityLevel, D: Capacity> Drop for BashPrgHash<L, D>
305-
where
306-
(L, D): Rate,
307-
{
260+
impl<const RATE: usize, const CAPACITY: usize> Drop for BashPrgHash<RATE, CAPACITY> {
261+
#[inline]
308262
fn drop(&mut self) {
309263
#[cfg(feature = "zeroize")]
310264
{
@@ -314,10 +268,8 @@ where
314268
}
315269
}
316270

317-
impl<L: SecurityLevel, D: Capacity> Drop for BashPrgHashReader<L, D>
318-
where
319-
(L, D): Rate,
320-
{
271+
impl<const RATE: usize, const CAPACITY: usize> Drop for BashPrgHashReader<RATE, CAPACITY> {
272+
#[inline]
321273
fn drop(&mut self) {
322274
#[cfg(feature = "zeroize")]
323275
{
@@ -327,15 +279,17 @@ where
327279
}
328280
}
329281

330-
/// bash-prg-hash with ℓ = 128 and d = 1
331-
pub type BashPrgHash1281 = BashPrgHash<U16, U1>;
332-
/// bash-prg-hash with ℓ = 128 and d = 2
333-
pub type BashPrgHash1282 = BashPrgHash<U16, U2>;
334-
/// bash-prg-hash with ℓ = 192 and d = 1
335-
pub type BashPrgHash1921 = BashPrgHash<U24, U1>;
336-
/// bash-prg-hash with ℓ = 192 and d = 2
337-
pub type BashPrgHash1922 = BashPrgHash<U24, U2>;
338-
/// bash-prg-hash with ℓ = 256 and d = 1
339-
pub type BashPrgHash2561 = BashPrgHash<U32, U1>;
340-
/// bash-prg-hash with ℓ = 256 and d = 2
341-
pub type BashPrgHash2562 = BashPrgHash<U32, U2>;
282+
/// Invalid `bash-prg-hash` header error.
283+
#[derive(Debug)]
284+
pub struct InvalidHeaderError;
285+
286+
impl fmt::Display for InvalidHeaderError {
287+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
288+
f.write_str(
289+
"Invalid `bash-prg-hash` header. \
290+
Header length must be a multiple of 4 bytes and not greater than 60 bytes.",
291+
)
292+
}
293+
}
294+
295+
impl core::error::Error for InvalidHeaderError {}

0 commit comments

Comments
 (0)