1pub const HASH224: usize = 28;
21pub const HASH256: usize = 32;
22pub const HASH384: usize = 48;
23pub const HASH512: usize = 64;
24pub const SHAKE128: usize = 16;
25pub const SHAKE256: usize = 32;
26
27const ROUNDS: usize = 24;
28
29const RC: [u64; 24] = [
30 0x0000000000000001,
31 0x0000000000008082,
32 0x800000000000808A,
33 0x8000000080008000,
34 0x000000000000808B,
35 0x0000000080000001,
36 0x8000000080008081,
37 0x8000000000008009,
38 0x000000000000008A,
39 0x0000000000000088,
40 0x0000000080008009,
41 0x000000008000000A,
42 0x000000008000808B,
43 0x800000000000008B,
44 0x8000000000008089,
45 0x8000000000008003,
46 0x8000000000008002,
47 0x8000000000000080,
48 0x000000000000800A,
49 0x800000008000000A,
50 0x8000000080008081,
51 0x8000000000008080,
52 0x0000000080000001,
53 0x8000000080008008,
54];
55
56pub struct SHA3 {
57 length: u64,
58 rate: usize,
59 len: usize,
60 s: [[u64; 5]; 5],
61}
62
63impl SHA3 {
64 fn rotl(x: u64, n: u64) -> u64 {
65 return ((x) << n) | ((x) >> (64 - n));
66 }
67
68 fn transform(&mut self) {
69 let mut c: [u64; 5] = [0; 5];
71 let mut d: [u64; 5] = [0; 5];
72 let mut b: [[u64; 5]; 5] = [[0; 5]; 5];
73
74 for k in 0..ROUNDS {
75 c[0] = self.s[0][0] ^ self.s[0][1] ^ self.s[0][2] ^ self.s[0][3] ^ self.s[0][4];
76 c[1] = self.s[1][0] ^ self.s[1][1] ^ self.s[1][2] ^ self.s[1][3] ^ self.s[1][4];
77 c[2] = self.s[2][0] ^ self.s[2][1] ^ self.s[2][2] ^ self.s[2][3] ^ self.s[2][4];
78 c[3] = self.s[3][0] ^ self.s[3][1] ^ self.s[3][2] ^ self.s[3][3] ^ self.s[3][4];
79 c[4] = self.s[4][0] ^ self.s[4][1] ^ self.s[4][2] ^ self.s[4][3] ^ self.s[4][4];
80
81 d[0] = c[4] ^ SHA3::rotl(c[1], 1);
82 d[1] = c[0] ^ SHA3::rotl(c[2], 1);
83 d[2] = c[1] ^ SHA3::rotl(c[3], 1);
84 d[3] = c[2] ^ SHA3::rotl(c[4], 1);
85 d[4] = c[3] ^ SHA3::rotl(c[0], 1);
86
87 for i in 0..5 {
88 for j in 0..5 {
89 self.s[i][j] ^= d[i];
90 }
91 }
92
93 b[0][0] = self.s[0][0];
94 b[1][3] = SHA3::rotl(self.s[0][1], 36);
95 b[2][1] = SHA3::rotl(self.s[0][2], 3);
96 b[3][4] = SHA3::rotl(self.s[0][3], 41);
97 b[4][2] = SHA3::rotl(self.s[0][4], 18);
98
99 b[0][2] = SHA3::rotl(self.s[1][0], 1);
100 b[1][0] = SHA3::rotl(self.s[1][1], 44);
101 b[2][3] = SHA3::rotl(self.s[1][2], 10);
102 b[3][1] = SHA3::rotl(self.s[1][3], 45);
103 b[4][4] = SHA3::rotl(self.s[1][4], 2);
104
105 b[0][4] = SHA3::rotl(self.s[2][0], 62);
106 b[1][2] = SHA3::rotl(self.s[2][1], 6);
107 b[2][0] = SHA3::rotl(self.s[2][2], 43);
108 b[3][3] = SHA3::rotl(self.s[2][3], 15);
109 b[4][1] = SHA3::rotl(self.s[2][4], 61);
110
111 b[0][1] = SHA3::rotl(self.s[3][0], 28);
112 b[1][4] = SHA3::rotl(self.s[3][1], 55);
113 b[2][2] = SHA3::rotl(self.s[3][2], 25);
114 b[3][0] = SHA3::rotl(self.s[3][3], 21);
115 b[4][3] = SHA3::rotl(self.s[3][4], 56);
116
117 b[0][3] = SHA3::rotl(self.s[4][0], 27);
118 b[1][1] = SHA3::rotl(self.s[4][1], 20);
119 b[2][4] = SHA3::rotl(self.s[4][2], 39);
120 b[3][2] = SHA3::rotl(self.s[4][3], 8);
121 b[4][0] = SHA3::rotl(self.s[4][4], 14);
122
123 for i in 0..5 {
124 for j in 0..5 {
125 self.s[i][j] = b[i][j] ^ (!b[(i + 1) % 5][j] & b[(i + 2) % 5][j]);
126 }
127 }
128
129 self.s[0][0] ^= RC[k];
130 }
131 }
132
133 pub fn init(&mut self, olen: usize) {
135 for i in 0..5 {
137 for j in 0..5 {
138 self.s[i][j] = 0;
139 }
140 }
141 self.length = 0;
142 self.len = olen;
143 self.rate = 200 - 2 * olen;
144 }
145
146 pub fn new(olen: usize) -> SHA3 {
147 let mut nh = SHA3 {
148 length: 0,
149 rate: 0,
150 len: 0,
151 s: [[0; 5]; 5],
152 };
153 nh.init(olen);
154 return nh;
155 }
156
157 pub fn process(&mut self, byt: u8) {
159 let cnt = (self.length % (self.rate as u64)) as usize;
161 let b = cnt % 8;
162 let ind = cnt / 8;
163 let i = ind % 5;
164 let j = ind / 5;
165 self.s[i][j] ^= ((byt & 0xff) as u64) << (8 * b);
166 self.length += 1;
167 if cnt + 1 == self.rate {
168 self.transform();
169 }
170 }
171
172 pub fn squeeze(&mut self, buff: &mut [u8], olen: usize) {
173 let mut done = false;
175 let mut m = 0;
176 loop {
177 for j in 0..5 {
178 for i in 0..5 {
179 let mut el = self.s[i][j];
180 for _ in 0..8 {
181 buff[m] = (el & 0xff) as u8;
182 m += 1;
183 if m >= olen || (m % self.rate) == 0 {
184 done = true;
185 break;
186 }
187 el >>= 8;
188 }
189 if done {
190 break;
191 }
192 }
193 if done {
194 break;
195 }
196 }
197 if m >= olen {
198 break;
199 }
200 done = false;
201 self.transform();
202 }
203 }
204
205 pub fn hash(&mut self, digest: &mut [u8]) {
207 let q = self.rate - (self.length % (self.rate as u64)) as usize;
209 if q == 1 {
210 self.process(0x86);
211 } else {
212 self.process(0x06);
213 while (self.length % (self.rate as u64)) as usize != self.rate - 1 {
214 self.process(0x00)
215 }
216 self.process(0x80);
217 }
218 let hlen = self.len as usize;
219 self.squeeze(digest, hlen);
220 }
221
222 pub fn shake(&mut self, digest: &mut [u8], olen: usize) {
223 let q = self.rate - (self.length % (self.rate as u64)) as usize;
224 if q == 1 {
225 self.process(0x9f);
226 } else {
227 self.process(0x1f);
228 while (self.length % (self.rate as u64)) as usize != self.rate - 1 {
229 self.process(0x00)
230 }
231 self.process(0x80);
232 }
233 self.squeeze(digest, olen);
234 }
235}
236
237