11use crate :: encoding:: { left_encode, right_encode} ;
2- use crate :: traits:: { CShake , EagerHash } ;
3- use core:: fmt;
4- use digest:: block_api:: {
5- AlgorithmName , Block , BlockSizeUser , Buffer , BufferKindUser , Eager , ExtendableOutputCore ,
6- FixedOutputCore , UpdateCore , XofReaderCore ,
7- } ;
2+ use cshake:: CShake ;
3+ use digest:: block_api:: BlockSizeUser ;
84use digest:: common:: KeySizeUser ;
9- use digest:: { InvalidLength , Key , KeyInit , MacMarker , Output , OutputSizeUser } ;
5+ use digest:: typenum:: Unsigned ;
6+ use digest:: { ExtendableOutput , InvalidLength , Key , KeyInit , MacMarker , Update , XofReader } ;
107
11- pub struct KmacCore < D : EagerHash > {
12- digest : D :: Core ,
8+ /// Trait alias for CShake types usable with KMAC.
9+ pub trait CShakeUser : BlockSizeUser + Update + ExtendableOutput + Clone {
10+ fn new_kmac ( customization : & [ u8 ] ) -> Self ;
1311}
1412
15- impl < D : EagerHash > Clone for KmacCore < D > {
13+ impl CShakeUser for cshake:: CShake128 {
14+ fn new_kmac ( customization : & [ u8 ] ) -> Self {
15+ CShake :: new_with_function_name ( b"KMAC" , customization)
16+ }
17+ }
18+
19+ impl CShakeUser for cshake:: CShake256 {
20+ fn new_kmac ( customization : & [ u8 ] ) -> Self {
21+ CShake :: new_with_function_name ( b"KMAC" , customization)
22+ }
23+ }
24+
25+ pub struct KmacInner < D : CShakeUser > {
26+ cshake : D ,
27+ }
28+
29+ impl < D : CShakeUser > Clone for KmacInner < D > {
1630 #[ inline( always) ]
1731 fn clone ( & self ) -> Self {
1832 Self {
19- digest : self . digest . clone ( ) ,
33+ cshake : self . cshake . clone ( ) ,
2034 }
2135 }
2236}
2337
24- impl < D : EagerHash > MacMarker for KmacCore < D > { }
25-
26- impl < D : EagerHash > BufferKindUser for KmacCore < D > {
27- type BufferKind = Eager ;
28- }
38+ impl < D : CShakeUser > MacMarker for KmacInner < D > { }
2939
30- impl < D : EagerHash > KeySizeUser for KmacCore < D > {
31- type KeySize = < D :: Core as BlockSizeUser > :: BlockSize ;
40+ impl < D : CShakeUser > KeySizeUser for KmacInner < D > {
41+ type KeySize = D :: BlockSize ;
3242}
3343
34- impl < D : EagerHash > BlockSizeUser for KmacCore < D > {
35- type BlockSize = < D :: Core as BlockSizeUser > :: BlockSize ;
44+ impl < D : CShakeUser > BlockSizeUser for KmacInner < D > {
45+ type BlockSize = D :: BlockSize ;
3646}
3747
38- impl < D : EagerHash > KmacCore < D > {
48+ impl < D : CShakeUser > KmacInner < D > {
3949 #[ inline( always) ]
4050 pub fn new_customization ( key : & [ u8 ] , customisation : & [ u8 ] ) -> Self {
41- // digest: bufpad(encode_string(K), bufsize) || X || right_encode(L)
42- // where bufpad(X, w) = left_encode(len(w)) || X || zeros
43- // where encode_string(K) = left_encode(len(K)) || K
44- let mut digest = D :: Core :: new_cshake ( customisation) ;
45- let mut buffer = Buffer :: < Self > :: default ( ) ;
51+ let mut cshake = D :: new_kmac ( customisation) ;
52+ let block_size = D :: BlockSize :: USIZE ;
4653 let mut encode_buffer = [ 0u8 ; 9 ] ;
4754
48- // bytepad, left_encode(w)
49- buffer. digest_blocks (
50- left_encode ( D :: block_size ( ) as u64 , & mut encode_buffer) ,
51- |blocks| digest. update_blocks ( blocks) ,
52- ) ;
53-
54- // encode_string(K), left_encode(len(K)) -- length is in bits
55- buffer. digest_blocks (
56- left_encode ( 8 * key. len ( ) as u64 , & mut encode_buffer) ,
57- |blocks| digest. update_blocks ( blocks) ,
58- ) ;
59-
60- // encode_string(K) copy K into blocks
61- buffer. digest_blocks ( key, |blocks| digest. update_blocks ( blocks) ) ;
62-
63- // bytepad, pad the key to the block size
64- digest. update_blocks ( & [ buffer. pad_with_zeros ( ) ] ) ;
55+ // bytepad: left_encode(w)
56+ let le_w = left_encode ( block_size as u64 , & mut encode_buffer) ;
57+ let mut total = le_w. len ( ) ;
58+ cshake. update ( le_w) ;
59+
60+ // encode_string(K): left_encode(8*len(K)) || K
61+ let le_k = left_encode ( 8 * key. len ( ) as u64 , & mut encode_buffer) ;
62+ total += le_k. len ( ) ;
63+ cshake. update ( le_k) ;
64+
65+ total += key. len ( ) ;
66+ cshake. update ( key) ;
67+
68+ // pad to block boundary
69+ let pad_len = ( block_size - ( total % block_size) ) % block_size;
70+ if pad_len > 0 {
71+ let zeros = [ 0u8 ; 168 ] ; // max block size
72+ let mut remaining = pad_len;
73+ while remaining > 0 {
74+ let chunk = core:: cmp:: min ( remaining, zeros. len ( ) ) ;
75+ cshake. update ( & zeros[ ..chunk] ) ;
76+ remaining -= chunk;
77+ }
78+ }
6579
66- Self { digest }
80+ Self { cshake }
6781 }
6882}
6983
70- impl < D : EagerHash > KeyInit for KmacCore < D > {
84+ impl < D : CShakeUser > KeyInit for KmacInner < D > {
7185 #[ inline]
7286 fn new ( key : & Key < Self > ) -> Self {
7387 Self :: new_customization ( key. as_slice ( ) , & [ ] )
@@ -79,68 +93,34 @@ impl<D: EagerHash> KeyInit for KmacCore<D> {
7993 }
8094}
8195
82- impl < D : EagerHash > UpdateCore for KmacCore < D > {
96+ impl < D : CShakeUser > Update for KmacInner < D > {
8397 #[ inline( always) ]
84- fn update_blocks ( & mut self , blocks : & [ Block < Self > ] ) {
85- self . digest . update_blocks ( blocks ) ;
98+ fn update ( & mut self , data : & [ u8 ] ) {
99+ self . cshake . update ( data ) ;
86100 }
87101}
88102
89- impl < D : EagerHash > KmacCore < D > {
90- /// Finalizes the KMAC for any output array size.
103+ impl < D : CShakeUser > KmacInner < D > {
104+ /// Finalizes the KMAC for any output array size (fixed-length output) .
91105 #[ inline( always) ]
92- pub fn finalize_core ( & mut self , buffer : & mut Buffer < Self > , out : & mut [ u8 ] ) {
106+ pub fn finalize_fixed_inner ( mut self , out : & mut [ u8 ] ) {
93107 // right_encode(L), where L = output length in bits
94- buffer. digest_blocks (
95- right_encode ( 8 * out. len ( ) as u64 , & mut [ 0u8 ; 9 ] ) ,
96- |blocks| self . update_blocks ( blocks) ,
97- ) ;
98-
99- let mut reader = self . digest . finalize_xof_core ( buffer) ;
100-
101- let mut pos = 0 ;
102- while pos < out. len ( ) {
103- let block = reader. read_block ( ) ;
104- let to_copy = core:: cmp:: min ( out. len ( ) - pos, block. len ( ) ) ;
105- out[ pos..pos + to_copy] . copy_from_slice ( & block[ ..to_copy] ) ;
106- pos += to_copy;
107- }
108- }
109- }
108+ let mut encode_buffer = [ 0u8 ; 9 ] ;
109+ let re = right_encode ( 8 * out. len ( ) as u64 , & mut encode_buffer) ;
110+ self . cshake . update ( re) ;
110111
111- impl < D : EagerHash > FixedOutputCore for KmacCore < D >
112- where
113- KmacCore < D > : OutputSizeUser ,
114- {
115- #[ inline( always) ]
116- fn finalize_fixed_core ( & mut self , buffer : & mut Buffer < Self > , out : & mut Output < Self > ) {
117- self . finalize_core ( buffer, out. as_mut_slice ( ) ) ;
112+ let mut reader = self . cshake . finalize_xof ( ) ;
113+ reader. read ( out) ;
118114 }
119- }
120-
121- impl < D : EagerHash > ExtendableOutputCore for KmacCore < D > {
122- type ReaderCore = <D :: Core as ExtendableOutputCore >:: ReaderCore ;
123115
116+ /// Finalizes the KMAC for extendable output (XOF).
124117 #[ inline( always) ]
125- fn finalize_xof_core ( & mut self , buffer : & mut Buffer < Self > ) -> Self :: ReaderCore {
118+ pub fn finalize_xof_inner ( mut self ) -> D :: Reader {
126119 // right_encode(0), as L = 0 for extendable output
127- buffer. digest_blocks ( right_encode ( 0 , & mut [ 0u8 ; 9 ] ) , |blocks| {
128- self . update_blocks ( blocks)
129- } ) ;
130- self . digest . finalize_xof_core ( buffer)
131- }
132- }
133-
134- impl < D : EagerHash + AlgorithmName > AlgorithmName for KmacCore < D > {
135- fn write_alg_name ( f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
136- f. write_str ( "Kmac<" ) ?;
137- <D as AlgorithmName >:: write_alg_name ( f) ?;
138- f. write_str ( ">" )
139- }
140- }
120+ let mut encode_buffer = [ 0u8 ; 9 ] ;
121+ let re = right_encode ( 0 , & mut encode_buffer) ;
122+ self . cshake . update ( re) ;
141123
142- impl < D : EagerHash + fmt:: Debug > fmt:: Debug for KmacCore < D > {
143- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
144- f. write_str ( "KmacCore { ... }" )
124+ self . cshake . finalize_xof ( )
145125 }
146126}
0 commit comments