1+ use crate :: variants:: { Capacity , SecurityLevel } ;
12use bash_f:: { STATE_WORDS , bash_f} ;
23use core:: { fmt, marker:: PhantomData } ;
3- use digest:: block_api:: BlockSizeUser ;
4- use digest:: core_api:: AlgorithmName ;
5-
6- use crate :: variants:: { Cap1 , Cap2 , Capacity , Level128 , Level192 , Level256 , SecurityLevel } ;
7-
8- /// A constant representing the maximum size of a header in bytes.
9- pub const MAX_HEADER_LEN : usize = 60 ;
4+ use digest:: {
5+ CustomizedInit , block_api:: BlockSizeUser , core_api:: AlgorithmName , typenum:: Unsigned ,
6+ } ;
107
118/// Data type codes from Table 3 of STB 34.101.77-2020
129const DATA : u8 = 0b000010 ;
1310/// Data type codes from Table 3 of STB 34.101.77-2020
1411const OUT : u8 = 0b000100 ;
1512
16- /// Core bash-prg-hash hasher state generic over security level and capacity.
13+ /// bash-prg-hash hasher state generic over security level and capacity.
1714///
1815/// Specified in Section 8.12 of STB 34.101.77-2020.
19- pub struct BashPrgHashCore < L : SecurityLevel , D : Capacity > {
16+ pub struct BashPrgHashState < L : SecurityLevel , D : Capacity > {
2017 state : [ u64 ; STATE_WORDS ] ,
21- rate_bytes : usize , // r/8 - buffer size in bytes
22- offset : usize , // current offset in bytes
23- header : [ u8 ; MAX_HEADER_LEN ] , // max header size (480 bits = 60 bytes)
24- header_len : usize , // header length in bytes
25- data_committed : bool , // whether commit(DATA) was called in
26- _level : PhantomData < L > ,
27- _capacity : PhantomData < D > ,
18+ / // r/8 - buffer size in bytes
19+ rate_bytes : usize ,
20+ /// current offset in bytes
21+ offset : usize ,
22+ /// whether commit(DATA) was called
23+ data_committed : bool ,
24+ _pd : PhantomData < ( L , D ) > ,
2825}
2926
3027macro_rules! impl_block_sizes {
3128 ( $( $level: ty, $cap: ty) ,* $( , ) ?) => {
3229 $(
33- impl BlockSizeUser for BashPrgHashCore <$level, $cap> {
30+ impl BlockSizeUser for BashPrgHashState <$level, $cap> {
3431 type BlockSize = digest:: typenum:: U <{
35- ( 1536 - 2 * <$cap as Capacity >:: CAPACITY * <$level as SecurityLevel >:: LEVEL ) / 8
32+ ( 1536 - 2 * <$cap as Unsigned >:: USIZE * <$level as Unsigned >:: USIZE ) / 8
3633 } >;
3734 }
3835 ) *
3936 } ;
4037}
4138
4239impl_block_sizes ! {
43- Level128 , Cap1 ,
44- Level192 , Cap1 ,
45- Level256 , Cap1 ,
46- Level128 , Cap2 ,
47- Level192 , Cap2 ,
48- Level256 , Cap2 ,
40+ digest :: typenum :: U128 , digest :: typenum :: U1 ,
41+ digest :: typenum :: U192 , digest :: typenum :: U1 ,
42+ digest :: typenum :: U256 , digest :: typenum :: U1 ,
43+ digest :: typenum :: U128 , digest :: typenum :: U2 ,
44+ digest :: typenum :: U192 , digest :: typenum :: U2 ,
45+ digest :: typenum :: U256 , digest :: typenum :: U2 ,
4946}
5047
51- impl < L : SecurityLevel , D : Capacity > BashPrgHashCore < L , D > {
52- /// Calculate buffer size r = 1536 - 2dℓ (in bytes)
53- const fn calculate_rate_bytes ( ) -> usize {
54- ( 1536 - 2 * D :: CAPACITY * L :: LEVEL ) / 8
55- }
48+ impl < L : SecurityLevel , D : Capacity > CustomizedInit for BashPrgHashState < L , D > {
49+ fn new_customized ( header : & [ u8 ] ) -> Self {
50+ const MAX_HEADER_LEN : usize = 60 ; // 480 bits = 60 bytes
5651
57- /// Create a new hasher with an announcement (header).
58- pub fn new ( header : & [ u8 ] ) -> Self {
5952 assert ! (
6053 header. len( ) <= MAX_HEADER_LEN ,
6154 "Header length must not exceed 480 bits (60 bytes)"
@@ -66,19 +59,24 @@ impl<L: SecurityLevel, D: Capacity> BashPrgHashCore<L, D> {
6659 "Header length must be multiple of 32 bits (4 bytes)"
6760 ) ;
6861
69- let mut header_buf = [ 0u8 ; 60 ] ;
70- header_buf[ ..header. len ( ) ] . copy_from_slice ( header) ;
71-
72- Self {
62+ let mut state = Self {
7363 state : [ 0u64 ; STATE_WORDS ] ,
7464 rate_bytes : Self :: calculate_rate_bytes ( ) ,
7565 offset : 0 ,
76- header : header_buf,
77- header_len : header. len ( ) ,
7866 data_committed : false ,
79- _level : PhantomData ,
80- _capacity : PhantomData ,
81- }
67+ _pd : PhantomData ,
68+ } ;
69+
70+ // Immediately consume header during initialization
71+ state. start ( header) ;
72+ state
73+ }
74+ }
75+
76+ impl < L : SecurityLevel , D : Capacity > BashPrgHashState < L , D > {
77+ /// Calculate buffer size r = 1536 - 2dℓ (in bytes)
78+ const fn calculate_rate_bytes ( ) -> usize {
79+ ( 1536 - 2 * D :: USIZE * L :: USIZE ) / 8
8280 }
8381
8482 /// Helper: modify byte at position in state
@@ -114,9 +112,10 @@ impl<L: SecurityLevel, D: Capacity> BashPrgHashCore<L, D> {
114112 }
115113
116114 /// Execute start command (Section 8.3)
117- fn start ( & mut self ) {
115+ fn start ( & mut self , header : & [ u8 ] ) {
116+ let header_len = header. len ( ) ;
117+
118118 // Step 3: pos ← 8 + |A| + |K| (in bits) = 1 + header_len (in bytes)
119- let header_len = self . header_len ;
120119 self . offset = 1 + header_len;
121120
122121 // Step 4: S[...pos) ← ⟨|A|/2 + |K|/32⟩_8 || A || K
@@ -125,13 +124,12 @@ impl<L: SecurityLevel, D: Capacity> BashPrgHashCore<L, D> {
125124 self . modify_byte ( 0 , |b| * b = first_byte) ;
126125
127126 // Copy header bytes
128- for i in 0 ..header_len {
129- let byte = self . header [ i] ;
127+ for ( i, & byte) in header. iter ( ) . enumerate ( ) {
130128 self . modify_byte ( 1 + i, |b| * b = byte) ;
131129 }
132130
133131 // Step 6: S[1472...) ← ⟨ℓ/4 + d⟩_64
134- self . state [ 23 ] = ( L :: LEVEL / 4 + D :: CAPACITY ) as u64 ;
132+ self . state [ 23 ] = ( L :: USIZE / 4 + D :: USIZE ) as u64 ;
135133 }
136134
137135 /// Execute commit command (Section 8.4)
@@ -154,17 +152,7 @@ impl<L: SecurityLevel, D: Capacity> BashPrgHashCore<L, D> {
154152
155153 /// Execute absorb command (Section 8.6)
156154 pub ( crate ) fn absorb ( & mut self , data : & [ u8 ] ) {
157- // Check if initialized: state[23] == 0 means not initialized
158- if self . state [ 23 ] == 0 {
159- self . start ( ) ;
160- }
161-
162155 // Step 1: commit(DATA) - only once per absorption session
163- // We need data_committed because offset == 0 can happen multiple times:
164- // - After finalize() (need commit(DATA))
165- // - After commit(DATA) but before absorbing (already did commit)
166- // - After full block during absorption (offset resets to 0)
167- // - After empty data calls (offset stays 0)
168156 if !self . data_committed {
169157 self . commit ( DATA ) ;
170158 self . data_committed = true ;
@@ -188,10 +176,6 @@ impl<L: SecurityLevel, D: Capacity> BashPrgHashCore<L, D> {
188176
189177 /// Prepare for reading output (squeeze)
190178 pub ( crate ) fn finalize ( & mut self ) {
191- if self . state [ 23 ] == 0 {
192- self . start ( ) ;
193- }
194-
195179 self . commit ( OUT ) ;
196180 self . data_committed = false ; // Reset for next absorption session
197181 }
@@ -213,40 +197,37 @@ impl<L: SecurityLevel, D: Capacity> BashPrgHashCore<L, D> {
213197 }
214198}
215199
216- impl < L : SecurityLevel , D : Capacity > Clone for BashPrgHashCore < L , D > {
200+ impl < L : SecurityLevel , D : Capacity > Clone for BashPrgHashState < L , D > {
217201 fn clone ( & self ) -> Self {
218202 Self {
219203 state : self . state ,
220204 rate_bytes : self . rate_bytes ,
221205 offset : self . offset ,
222- header : self . header ,
223- header_len : self . header_len ,
224206 data_committed : self . data_committed ,
225- _level : PhantomData ,
226- _capacity : PhantomData ,
207+ _pd : PhantomData ,
227208 }
228209 }
229210}
230211
231- impl < L : SecurityLevel , D : Capacity > Default for BashPrgHashCore < L , D > {
212+ impl < L : SecurityLevel , D : Capacity > Default for BashPrgHashState < L , D > {
232213 fn default ( ) -> Self {
233- Self :: new ( & [ ] )
214+ Self :: new_customized ( & [ ] )
234215 }
235216}
236217
237- impl < L : SecurityLevel , D : Capacity > AlgorithmName for BashPrgHashCore < L , D > {
218+ impl < L : SecurityLevel , D : Capacity > AlgorithmName for BashPrgHashState < L , D > {
238219 fn write_alg_name ( f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
239- write ! ( f, "BashPrgHash{}-{}" , L :: LEVEL , D :: CAPACITY )
220+ write ! ( f, "BashPrgHash{}-{}" , L :: USIZE , D :: USIZE )
240221 }
241222}
242223
243- impl < L : SecurityLevel , D : Capacity > fmt:: Debug for BashPrgHashCore < L , D > {
224+ impl < L : SecurityLevel , D : Capacity > fmt:: Debug for BashPrgHashState < L , D > {
244225 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
245- f. write_str ( "BashPrgHashCore { ... }" )
226+ f. write_str ( "BashPrgHashState { ... }" )
246227 }
247228}
248229
249- impl < L : SecurityLevel , D : Capacity > Drop for BashPrgHashCore < L , D > {
230+ impl < L : SecurityLevel , D : Capacity > Drop for BashPrgHashState < L , D > {
250231 fn drop ( & mut self ) {
251232 #[ cfg( feature = "zeroize" ) ]
252233 {
@@ -257,4 +238,4 @@ impl<L: SecurityLevel, D: Capacity> Drop for BashPrgHashCore<L, D> {
257238}
258239
259240#[ cfg( feature = "zeroize" ) ]
260- impl < L : SecurityLevel , D : Capacity > digest:: zeroize:: ZeroizeOnDrop for BashPrgHashCore < L , D > { }
241+ impl < L : SecurityLevel , D : Capacity > digest:: zeroize:: ZeroizeOnDrop for BashPrgHashState < L , D > { }
0 commit comments