1
+ #![ allow( clippy:: all) ]
2
+ #![ deny( clippy:: hacspec) ]
3
+
4
+ extern crate hacspec;
5
+ extern crate rand;
6
+
7
+ // Import hacspec and all needed definitions.
8
+ use hacspec:: prelude:: * ;
9
+
10
+ const ROUNDS : usize = 24 ;
11
+ pub const SHA3224_RATE : usize = 144 ;
12
+ pub const SHA3256_RATE : usize = 136 ;
13
+ pub const SHA3384_RATE : usize = 104 ;
14
+ pub const SHA3512_RATE : usize = 72 ;
15
+ pub const SHAKE128_RATE : usize = 168 ;
16
+ pub const SHAKE256_RATE : usize = 136 ;
17
+
18
+ pub enum ShaRate {
19
+ Sha3224Rate = 144 ,
20
+ Sha3256Rate = 136 ,
21
+ Sha3384Rate = 104 ,
22
+ Sha3512Rate = 72 ,
23
+ }
24
+
25
+ array ! ( State , 25 , U64 ) ;
26
+ array ! ( Row , 5 , U64 ) ;
27
+ bytes ! ( Digest224 , 28 ) ;
28
+ bytes ! ( Digest256 , 32 ) ;
29
+ bytes ! ( Digest384 , 48 ) ;
30
+ bytes ! ( Digest512 , 64 ) ;
31
+
32
+ const ROUNDCONSTANTS : [ u64 ; ROUNDS ] = [
33
+ 0x0000_0000_0000_0001 , 0x0000_0000_0000_8082 , 0x8000_0000_0000_808a , 0x8000_0000_8000_8000 ,
34
+ 0x0000_0000_0000_808b , 0x0000_0000_8000_0001 , 0x8000_0000_8000_8081 , 0x8000_0000_0000_8009 ,
35
+ 0x0000_0000_0000_008a , 0x0000_0000_0000_0088 , 0x0000_0000_8000_8009 , 0x0000_0000_8000_000a ,
36
+ 0x0000_0000_8000_808b , 0x8000_0000_0000_008b , 0x8000_0000_0000_8089 , 0x8000_0000_0000_8003 ,
37
+ 0x8000_0000_0000_8002 , 0x8000_0000_0000_0080 , 0x0000_0000_0000_800a , 0x8000_0000_8000_000a ,
38
+ 0x8000_0000_8000_8081 , 0x8000_0000_0000_8080 , 0x0000_0000_8000_0001 , 0x8000_0000_8000_8008
39
+ ] ;
40
+
41
+ const ROTC : [ u32 ; 25 ] = [
42
+ 0 , 1 , 62 , 28 , 27 , 36 , 44 , 6 , 55 , 20 , 3 , 10 , 43 , 25 , 39 , 41 , 45 , 15 , 21 , 8 , 18 , 2 , 61 , 56 , 14 ,
43
+ ] ;
44
+
45
+ const PI : [ usize ; 25 ] = [
46
+ 0 , 6 , 12 , 18 , 24 , 3 , 9 , 10 , 16 , 22 , 1 , 7 , 13 , 19 , 20 , 4 , 5 , 11 , 17 , 23 , 2 , 8 , 14 , 15 , 21
47
+ ] ;
48
+
49
+
50
+ fn theta ( s : State ) -> State {
51
+ let mut s = s;
52
+ let mut b = Row :: new ( ) ;
53
+ for i in 0 ..5 {
54
+ b[ i] = s[ i] ^ s[ i + 5 ] ^ s[ i + 10 ] ^ s[ i + 15 ] ^ s[ i + 20 ] ;
55
+ }
56
+ for i in 0 ..5 {
57
+ let u: U64 = b[ ( i + 1 ) % 5 ] ;
58
+ let t = b[ ( i + 4 ) % 5 ] ^ u. rotate_left ( 1 ) ;
59
+ for j in 0 ..5 {
60
+ s[ 5 * j + i] ^= t;
61
+ }
62
+ }
63
+ s
64
+ }
65
+
66
+ fn rho ( s : State ) -> State {
67
+ let mut s = s;
68
+ for i in 0 ..25 {
69
+ let u: U64 = s[ i] ;
70
+ s[ i] = u. rotate_left ( ROTC [ i] ) ;
71
+ }
72
+ s
73
+ }
74
+
75
+ fn pi ( s : State ) -> State {
76
+ let mut v = State :: new ( ) ;
77
+ for i in 0 ..25 {
78
+ v[ i] = s[ PI [ i] ] ;
79
+ }
80
+ v
81
+ }
82
+
83
+ fn chi ( s : State ) -> State {
84
+ let mut s = s;
85
+ let mut b = Row :: new ( ) ;
86
+ for i in 0 ..5 {
87
+ for j in 0 ..5 {
88
+ b[ j] = s[ 5 * i+j] ;
89
+ }
90
+ for j in 0 ..5 {
91
+ let u: U64 = b[ ( j + 1 ) % 5 ] ;
92
+ s[ 5 * i+j] ^= ( !u) & b[ ( j + 2 ) % 5 ] ;
93
+ }
94
+ }
95
+ s
96
+ }
97
+
98
+ fn iota ( s : State , rndconst : u64 ) -> State {
99
+ let mut s = s;
100
+ s[ 0 ] ^= U64 :: classify ( rndconst) ;
101
+ s
102
+ }
103
+
104
+ fn keccakf1600 ( s : State ) -> State {
105
+ let mut s = s;
106
+ for i in 0 ..ROUNDS {
107
+ s = theta ( s) ;
108
+ s = rho ( s) ;
109
+ s = pi ( s) ;
110
+ s = chi ( s) ;
111
+ s = iota ( s, ROUNDCONSTANTS [ i] ) ;
112
+ }
113
+ s
114
+ }
115
+
116
+ fn absorb_block ( s : State , block : ByteSeq ) -> State {
117
+ let mut s = s;
118
+ for ( i, b) in block. iter ( ) . enumerate ( ) {
119
+ let w = i >> 3 ;
120
+ let o = 8 * ( ( i & 7 ) as u32 ) ;
121
+ s[ w] ^= U64 :: from ( * b) << o;
122
+ }
123
+ keccakf1600 ( s)
124
+ }
125
+
126
+ fn squeeze ( s : State , nbytes : usize , rate : usize ) -> ByteSeq {
127
+ let mut s = s;
128
+ let mut out = ByteSeq :: new ( nbytes) ;
129
+ for i in 0 ..nbytes {
130
+ let pos = i % rate;
131
+ let w = pos >> 3 ;
132
+ let o = 8 * ( ( pos & 7 ) as u32 ) ;
133
+ let b = ( s[ w] >> o) & U64 :: classify ( 0xffu64 ) ;
134
+ out[ i] = b. into ( ) ;
135
+ if ( ( i+1 ) % rate) == 0 {
136
+ s = keccakf1600 ( s) ;
137
+ }
138
+ }
139
+ out
140
+ }
141
+
142
+ fn keccak ( rate : usize , data : ByteSeq , p : u8 , outbytes : usize ) -> ByteSeq {
143
+ let mut buf = ByteSeq :: new ( rate) ;
144
+ let mut s = State :: new ( ) ;
145
+
146
+ for ( block_len, block) in data. chunks ( rate) {
147
+ if block_len == rate {
148
+ s = absorb_block ( s, block) ;
149
+ }
150
+ else {
151
+ buf = buf. push ( block) ;
152
+ }
153
+ }
154
+ buf = buf. push ( ByteSeq :: from_array ( & [ U8 :: classify ( p) ] ) ) ;
155
+ buf[ rate-1 ] |= U8 :: classify ( 128 ) ;
156
+ s = absorb_block ( s, buf) ;
157
+
158
+ squeeze ( s, outbytes, rate)
159
+ }
160
+
161
+ pub fn sha3224 ( data : ByteSeq ) -> Digest224 {
162
+ let t = keccak ( SHA3224_RATE , data, 0x06 , 28 ) ;
163
+ Digest224 :: from ( t)
164
+ }
165
+
166
+ pub fn sha3256 ( data : ByteSeq ) -> Digest256 {
167
+ let t = keccak ( SHA3256_RATE , data, 0x06 , 32 ) ;
168
+ Digest256 :: from ( t)
169
+ }
170
+
171
+ pub fn sha3384 ( data : ByteSeq ) -> Digest384 {
172
+ let t = keccak ( SHA3384_RATE , data, 0x06 , 48 ) ;
173
+ Digest384 :: from ( t)
174
+ }
175
+
176
+ pub fn sha3512 ( data : ByteSeq ) -> Digest512 {
177
+ let t = keccak ( SHA3512_RATE , data, 0x06 , 64 ) ;
178
+ Digest512 :: from ( t)
179
+ }
180
+
181
+ pub fn shake128 ( data : ByteSeq , outlen : usize ) -> ByteSeq {
182
+ keccak ( SHAKE128_RATE , data, 0x1f , outlen)
183
+ }
184
+
185
+ pub fn shake256 ( data : ByteSeq , outlen : usize ) -> ByteSeq {
186
+ keccak ( SHAKE256_RATE , data, 0x1f , outlen)
187
+ }
188
+
189
+
190
+ #[ test]
191
+ fn test_keccakf1600 ( ) {
192
+ let s: State = State ( secret_array ! ( U64 , [
193
+ 0x5ba446eba89b9b78 , 0x6ef6eb8a586fb342 , 0x85cb3d1fcec58036 , 0xa59848fabf68003d ,
194
+ 0x35fdce49db45e6c1 , 0x0cf8fad4b3c5a04c , 0x9afa06a9884be9bc , 0x1ff35d85c227b2e0 ,
195
+ 0x09ec8487110fc092 , 0xcdea358a32c0fafb , 0x74241ac11e48073a , 0x72f921a900982d03 ,
196
+ 0x676616072102dbbc , 0x2638caacb8a3a5de , 0xc603972154aa5dd8 , 0x68b2fefc9b5075e3 ,
197
+ 0x8373f072f138bdee , 0xdff378a39b99a1a0 , 0x0b4bc139e9140556 , 0x19195e7735eb1c0a ,
198
+ 0x056b896a9884cb04 , 0x68e821e02963121f , 0xce7c280b9563ae2c , 0xc88f8da33e4311d6 ,
199
+ 0xc67829e549219318 ] ) ) ;
200
+
201
+ let c: State = State ( secret_array ! ( U64 , [
202
+ 0x95bef5e1cff30a77 , 0x91857a255e178abd , 0xbf8f4cef4c33fbe9 , 0xa40655d779ecdc92 ,
203
+ 0xb17af41f3c6a6d09 , 0x9f4e56cfd932c0c7 , 0x8dedfc2eb4c43a69 , 0x92e3a4f9f54bf903 ,
204
+ 0x51eca70f0657a075 , 0x690f9af199489ab5 , 0x718748b08fba9389 , 0x2d7349b2fd3c5cbe ,
205
+ 0xc8e1c9f8a9b002aa , 0x272dfd58ff1304ec , 0x665d945446962fe5 , 0xdabb2fbc07dc0b57 ,
206
+ 0xc49e2cecb193b592 , 0x63c1c463f370e7a5 , 0xc643a20b2ffb0e52 , 0xee9f85afed7d708c ,
207
+ 0xb031433c85642b6c , 0xfbe4f94ffc73ddbe , 0xfa2a02bb934e7bb3 , 0x38025c926f7136f5 ,
208
+ 0xf83d27a7f7ec241e ] ) ) ;
209
+ let v = keccakf1600 ( s) ;
210
+
211
+ assert_secret_array_eq ! ( c, v, U64 ) ;
212
+ }
213
+
214
+
215
+
216
+ fn main ( ) {
217
+
218
+ }
0 commit comments