Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
Keccak1600.cs
1using System;
2using System.IO;
4
6{
12 public abstract class Keccak1600
13 {
14 private static readonly bool[] rcs = GetRcs();
15 private static readonly ulong[] RCs = new ulong[] { 0x01, 0x02, 0x08, 0x80, 0x8000, 0x80000000, 0x8000000000000000 };
16 private static readonly ulong[] RC_ir = GetRcIr();
17 private ulong A_0, A_1, A_2, A_3, A_4, A_5, A_6, A_7, A_8, A_9, A_10, A_11, A_12, A_13, A_14, A_15, A_16, A_17, A_18, A_19, A_20, A_21, A_22, A_23, A_24;
18 private ulong A2_0, A2_1, A2_2, A2_3, A2_4, A2_5, A2_6, A2_7, A2_8, A2_9, A2_10, A2_11, A2_12, A2_13, A2_14, A2_15, A2_16, A2_17, A2_18, A2_19, A2_20, A2_21, A2_22, A2_23, A2_24;
19 private ulong C_0, C_1, C_2, C_3, C_4;
20 private readonly int r;
21 private readonly int c;
22 private readonly int r8;
23 private readonly int r8m1;
24 private readonly int dByteSize;
25 private readonly byte suffix;
26 private readonly byte suffixBits;
27 private bool reportStates = false;
28 private bool inA2 = false;
29
38 public Keccak1600(int Capacity, byte Suffix, int DigestSize)
39 {
40 this.c = Capacity;
41 this.r = 1600 - this.c;
42 this.r8 = this.r >> 3;
43 this.r8m1 = this.r8 - 1;
44 this.dByteSize = DigestSize / 8;
45 this.suffix = Suffix;
46 this.suffixBits = 0;
47
48 if ((DigestSize & 7) != 0)
49 throw new ArgumentException("Invalid digest size.", nameof(DigestSize));
50
51 if (this.c <= 0 || this.r <= 0 || this.r8m1 < 0 || (Capacity & 7) != 0)
52 throw new ArgumentException("Invalid capacity.", nameof(Capacity));
53
54 while (Suffix > 0)
55 {
56 Suffix >>= 1;
57 this.suffixBits++;
58 }
59
60 if (this.suffixBits > 6)
61 throw new ArgumentException("Invalid suffix.", nameof(Suffix));
62
63 this.suffix |= (byte)(1 << this.suffixBits); // First bit of pad10*1
64 }
65
70 public void InitState(byte[] Data)
71 {
72 if (Data.Length != 200)
73 throw new ArgumentException("Expected array of 200 bytes.", nameof(Data));
74
75 this.A_0 = BitConverter.ToUInt64(Data, 0);
76 this.A_1 = BitConverter.ToUInt64(Data, 8);
77 this.A_2 = BitConverter.ToUInt64(Data, 16);
78 this.A_3 = BitConverter.ToUInt64(Data, 24);
79 this.A_4 = BitConverter.ToUInt64(Data, 32);
80 this.A_5 = BitConverter.ToUInt64(Data, 40);
81 this.A_6 = BitConverter.ToUInt64(Data, 48);
82 this.A_7 = BitConverter.ToUInt64(Data, 56);
83 this.A_8 = BitConverter.ToUInt64(Data, 64);
84 this.A_9 = BitConverter.ToUInt64(Data, 72);
85 this.A_10 = BitConverter.ToUInt64(Data, 80);
86 this.A_11 = BitConverter.ToUInt64(Data, 88);
87 this.A_12 = BitConverter.ToUInt64(Data, 96);
88 this.A_13 = BitConverter.ToUInt64(Data, 104);
89 this.A_14 = BitConverter.ToUInt64(Data, 112);
90 this.A_15 = BitConverter.ToUInt64(Data, 120);
91 this.A_16 = BitConverter.ToUInt64(Data, 128);
92 this.A_17 = BitConverter.ToUInt64(Data, 136);
93 this.A_18 = BitConverter.ToUInt64(Data, 144);
94 this.A_19 = BitConverter.ToUInt64(Data, 152);
95 this.A_20 = BitConverter.ToUInt64(Data, 160);
96 this.A_21 = BitConverter.ToUInt64(Data, 168);
97 this.A_22 = BitConverter.ToUInt64(Data, 176);
98 this.A_23 = BitConverter.ToUInt64(Data, 184);
99 this.A_24 = BitConverter.ToUInt64(Data, 192);
100 }
101
106 public byte[] GetState()
107 {
108 byte[] Data = new byte[200]; // this.byteSize
109
110 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_0 : this.A_0), 0, Data, 0, 8);
111 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_1 : this.A_1), 0, Data, 8, 8);
112 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_2 : this.A_2), 0, Data, 16, 8);
113 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_3 : this.A_3), 0, Data, 24, 8);
114 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_4 : this.A_4), 0, Data, 32, 8);
115 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_5 : this.A_5), 0, Data, 40, 8);
116 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_6 : this.A_6), 0, Data, 48, 8);
117 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_7 : this.A_7), 0, Data, 56, 8);
118 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_8 : this.A_8), 0, Data, 64, 8);
119 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_9 : this.A_9), 0, Data, 72, 8);
120 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_10 : this.A_10), 0, Data, 80, 8);
121 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_11 : this.A_11), 0, Data, 88, 8);
122 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_12 : this.A_12), 0, Data, 96, 8);
123 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_13 : this.A_13), 0, Data, 104, 8);
124 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_14 : this.A_14), 0, Data, 112, 8);
125 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_15 : this.A_15), 0, Data, 120, 8);
126 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_16 : this.A_16), 0, Data, 128, 8);
127 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_17 : this.A_17), 0, Data, 136, 8);
128 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_18 : this.A_18), 0, Data, 144, 8);
129 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_19 : this.A_19), 0, Data, 152, 8);
130 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_20 : this.A_20), 0, Data, 160, 8);
131 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_21 : this.A_21), 0, Data, 168, 8);
132 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_22 : this.A_22), 0, Data, 176, 8);
133 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_23 : this.A_23), 0, Data, 184, 8);
134 Array.Copy(BitConverter.GetBytes(this.inA2 ? this.A2_24 : this.A_24), 0, Data, 192, 8);
135
136 return Data;
137 }
138
144 private static bool Rc(int t)
145 {
146 int i = t % 255;
147 if (i == 0)
148 return true;
149 else if (i < 0)
150 i += 255;
151
152 byte R = 1;
153
154 while (i-- > 0)
155 {
156 if ((R & 0x80) != 0)
157 {
158 R <<= 1;
159 R ^= 0b01110001;
160 }
161 else
162 R <<= 1;
163 }
164
165 return (R & 1) != 0;
166 }
167
168 private static bool[] GetRcs()
169 {
170 bool[] Result = new bool[255];
171 int t;
172
173 for (t = 0; t < 255; t++)
174 Result[t] = Rc(t);
175
176 return Result;
177 }
178
179 private static ulong[] GetRcIr()
180 {
181 ulong[] Result = new ulong[24];
182 int ir, i, j;
183
184 for (ir = 0; ir < 24; ir++)
185 {
186 ulong RC = 0;
187
188 for (j = 0; j <= 6; j++)
189 {
190 i = (j + 7 * ir) % 255;
191 if (i < 0)
192 i += 255;
193
194 if (rcs[i])
195 RC |= RCs[j];
196 }
197
198 Result[ir] = RC;
199 }
200
201 return Result;
202 }
203
209 public byte[] ComputeFixed(byte[] S)
210 {
211 ulong v;
212 int ir;
213
214 this.InitState(S);
215
216 if (this.reportStates)
217 {
218 EventHandler h = this.NewState;
219 if (!(h is null))
220 h(this, EventArgs.Empty);
221 }
222
223 for (ir = 0; ir < 24; ir++)
224 {
225 // Rnd function, as defined in section 3.3 of NIST FIPS 202.
226 // θ function, as defined in section 3.2.1 of NIST FIPS 202.
227
228 this.C_0 = this.A_0 ^ this.A_5 ^ this.A_10 ^ this.A_15 ^ this.A_20;
229 this.C_1 = this.A_1 ^ this.A_6 ^ this.A_11 ^ this.A_16 ^ this.A_21;
230 this.C_2 = this.A_2 ^ this.A_7 ^ this.A_12 ^ this.A_17 ^ this.A_22;
231 this.C_3 = this.A_3 ^ this.A_8 ^ this.A_13 ^ this.A_18 ^ this.A_23;
232 this.C_4 = this.A_4 ^ this.A_9 ^ this.A_14 ^ this.A_19 ^ this.A_24;
233
234 v = this.C_4 ^ ((this.C_1 << 1) | ((this.C_1 >> 63) & 1));
235 this.A_0 ^= v;
236 this.A_5 ^= v;
237 this.A_10 ^= v;
238 this.A_15 ^= v;
239 this.A_20 ^= v;
240
241 v = this.C_0 ^ ((this.C_2 << 1) | ((this.C_2 >> 63) & 1));
242 this.A_1 ^= v;
243 this.A_6 ^= v;
244 this.A_11 ^= v;
245 this.A_16 ^= v;
246 this.A_21 ^= v;
247
248 v = this.C_1 ^ ((this.C_3 << 1) | ((this.C_3 >> 63) & 1));
249 this.A_2 ^= v;
250 this.A_7 ^= v;
251 this.A_12 ^= v;
252 this.A_17 ^= v;
253 this.A_22 ^= v;
254
255 v = this.C_2 ^ ((this.C_4 << 1) | ((this.C_4 >> 63) & 1));
256 this.A_3 ^= v;
257 this.A_8 ^= v;
258 this.A_13 ^= v;
259 this.A_18 ^= v;
260 this.A_23 ^= v;
261
262 v = this.C_3 ^ ((this.C_0 << 1) | ((this.C_0 >> 63) & 1));
263 this.A_4 ^= v;
264 this.A_9 ^= v;
265 this.A_14 ^= v;
266 this.A_19 ^= v;
267 this.A_24 ^= v;
268
269 if (this.reportStates)
270 {
271 EventHandler h = this.NewState;
272 if (!(h is null))
273 h(this, EventArgs.Empty);
274 }
275
276 // ρ function, as defined in section 3.2.2 of NIST FIPS 202.
277
278 this.A_1 = ((v = this.A_1) << 1) | (v >> 63);
279 this.A_10 = ((v = this.A_10) << 3) | (v >> 61);
280 this.A_7 = ((v = this.A_7) << 6) | (v >> 58);
281 this.A_11 = ((v = this.A_11) << 10) | (v >> 54);
282 this.A_17 = ((v = this.A_17) << 15) | (v >> 49);
283 this.A_18 = ((v = this.A_18) << 21) | (v >> 43);
284 this.A_3 = ((v = this.A_3) << 28) | (v >> 36);
285 this.A_5 = ((v = this.A_5) << 36) | (v >> 28);
286 this.A_16 = ((v = this.A_16) << 45) | (v >> 19);
287 this.A_8 = ((v = this.A_8) << 55) | (v >> 9);
288 this.A_21 = ((v = this.A_21) << 2) | (v >> 62);
289 this.A_24 = ((v = this.A_24) << 14) | (v >> 50);
290 this.A_4 = ((v = this.A_4) << 27) | (v >> 37);
291 this.A_15 = ((v = this.A_15) << 41) | (v >> 23);
292 this.A_23 = ((v = this.A_23) << 56) | (v >> 8);
293 this.A_19 = ((v = this.A_19) << 8) | (v >> 56);
294 this.A_13 = ((v = this.A_13) << 25) | (v >> 39);
295 this.A_12 = ((v = this.A_12) << 43) | (v >> 21);
296 this.A_2 = ((v = this.A_2) << 62) | (v >> 2);
297 this.A_20 = ((v = this.A_20) << 18) | (v >> 46);
298 this.A_14 = ((v = this.A_14) << 39) | (v >> 25);
299 this.A_22 = ((v = this.A_22) << 61) | (v >> 3);
300 this.A_9 = ((v = this.A_9) << 20) | (v >> 44);
301 this.A_6 = ((v = this.A_6) << 44) | (v >> 20);
302
303 if (this.reportStates)
304 {
305 EventHandler h = this.NewState;
306 if (!(h is null))
307 h(this, EventArgs.Empty);
308 }
309
310 // π function, as defined in section 3.2.3 of NIST FIPS 202.
311
312 this.A2_0 = this.A_0;
313 this.A2_5 = this.A_3;
314 this.A2_10 = this.A_1;
315 this.A2_15 = this.A_4;
316 this.A2_20 = this.A_2;
317
318 this.A2_1 = this.A_6;
319 this.A2_6 = this.A_9;
320 this.A2_11 = this.A_7;
321 this.A2_16 = this.A_5;
322 this.A2_21 = this.A_8;
323
324 this.A2_2 = this.A_12;
325 this.A2_7 = this.A_10;
326 this.A2_12 = this.A_13;
327 this.A2_17 = this.A_11;
328 this.A2_22 = this.A_14;
329
330 this.A2_3 = this.A_18;
331 this.A2_8 = this.A_16;
332 this.A2_13 = this.A_19;
333 this.A2_18 = this.A_17;
334 this.A2_23 = this.A_15;
335
336 this.A2_4 = this.A_24;
337 this.A2_9 = this.A_22;
338 this.A2_14 = this.A_20;
339 this.A2_19 = this.A_23;
340 this.A2_24 = this.A_21;
341
342 if (this.reportStates)
343 {
344 this.inA2 = true;
345
346 EventHandler h = this.NewState;
347 if (!(h is null))
348 h(this, EventArgs.Empty);
349 }
350
351 // χ function, as defined in section 3.2.4 of NIST FIPS 202.
352
353 this.A_0 = this.A2_0 ^ (this.A2_2 & ~this.A2_1);
354 this.A_5 = this.A2_5 ^ (this.A2_7 & ~this.A2_6);
355 this.A_10 = this.A2_10 ^ (this.A2_12 & ~this.A2_11);
356 this.A_15 = this.A2_15 ^ (this.A2_17 & ~this.A2_16);
357 this.A_20 = this.A2_20 ^ (this.A2_22 & ~this.A2_21);
358
359 this.A_1 = this.A2_1 ^ (this.A2_3 & ~this.A2_2);
360 this.A_6 = this.A2_6 ^ (this.A2_8 & ~this.A2_7);
361 this.A_11 = this.A2_11 ^ (this.A2_13 & ~this.A2_12);
362 this.A_16 = this.A2_16 ^ (this.A2_18 & ~this.A2_17);
363 this.A_21 = this.A2_21 ^ (this.A2_23 & ~this.A2_22);
364
365 this.A_2 = this.A2_2 ^ (this.A2_4 & ~this.A2_3);
366 this.A_7 = this.A2_7 ^ (this.A2_9 & ~this.A2_8);
367 this.A_12 = this.A2_12 ^ (this.A2_14 & ~this.A2_13);
368 this.A_17 = this.A2_17 ^ (this.A2_19 & ~this.A2_18);
369 this.A_22 = this.A2_22 ^ (this.A2_24 & ~this.A2_23);
370
371 this.A_3 = this.A2_3 ^ (this.A2_0 & ~this.A2_4);
372 this.A_8 = this.A2_8 ^ (this.A2_5 & ~this.A2_9);
373 this.A_13 = this.A2_13 ^ (this.A2_10 & ~this.A2_14);
374 this.A_18 = this.A2_18 ^ (this.A2_15 & ~this.A2_19);
375 this.A_23 = this.A2_23 ^ (this.A2_20 & ~this.A2_24);
376
377 this.A_4 = this.A2_4 ^ (this.A2_1 & ~this.A2_0);
378 this.A_9 = this.A2_9 ^ (this.A2_6 & ~this.A2_5);
379 this.A_14 = this.A2_14 ^ (this.A2_11 & ~this.A2_10);
380 this.A_19 = this.A2_19 ^ (this.A2_16 & ~this.A2_15);
381 this.A_24 = this.A2_24 ^ (this.A2_21 & ~this.A2_20);
382
383 if (this.reportStates)
384 {
385 this.inA2 = false;
386
387 EventHandler h = this.NewState;
388 if (!(h is null))
389 h(this, EventArgs.Empty);
390 }
391
392 // ι function, as defined in section 3.2.5 of NIST FIPS 202.
393
394 this.A_0 ^= RC_ir[ir];
395
396 if (this.reportStates)
397 {
398 EventHandler h = this.NewState;
399 if (!(h is null))
400 h(this, EventArgs.Empty);
401 }
402 }
403
404 return this.GetState();
405 }
406
412 public byte[] ComputeVariable(byte[] N)
413 {
414 this.reportStates = !(this.NewState is null);
415
416 int Len = N.Length;
417 int m = Len << 3;
418 int nm1 = m / this.r;
419 byte[] S = new byte[200];
420 int Pos = 0;
421 int i, k;
422
423 for (i = 0; i < nm1; i++)
424 {
425 for (k = 0; k < this.r8; k++)
426 S[k] ^= N[Pos++];
427
428 S = this.ComputeFixed(S);
429 }
430
431 k = 0;
432 while (Pos < Len)
433 S[k++] ^= N[Pos++];
434
435 S[k] ^= this.suffix;
436 S[this.r8m1] ^= 0x80; // Last bit of pad10*1
437 S = this.ComputeFixed(S);
438
439 byte[] Z = new byte[this.dByteSize];
440
441 Pos = 0;
442 while (true)
443 {
444 i = Math.Min(this.r8, this.dByteSize - Pos);
445 Array.Copy(S, 0, Z, Pos, i);
446 Pos += i;
447
448 if (Pos >= this.dByteSize)
449 return Z;
450
451 S = this.ComputeFixed(S);
452 }
453 }
454
460 public byte[] ComputeVariable(Stream N)
461 {
462 this.reportStates = !(this.NewState is null);
463
464 long Len = N.Length;
465 long m = Len << 3;
466 long nm1 = m / this.r;
467 byte[] S = new byte[200];
468 byte[] r8Buf = new byte[this.r8];
469 int i, k;
470
471 N.Position = 0;
472
473 for (i = 0; i < nm1; i++)
474 {
475 N.ReadAll(r8Buf, 0, this.r8);
476
477 for (k = 0; k < this.r8; k++)
478 S[k] ^= r8Buf[k];
479
480 S = this.ComputeFixed(S);
481 }
482
483 int Rest = (int)(Len - N.Position);
484 if (Len > 0)
485 {
486 N.ReadAll(r8Buf, 0, Rest);
487
488 for (k = 0; k < Rest; k++)
489 S[k] ^= r8Buf[k];
490 }
491 else
492 k = 0;
493
494 S[k] ^= this.suffix;
495 S[this.r8m1] ^= 0x80; // Last bit of pad10*1
496 S = this.ComputeFixed(S);
497
498 byte[] Z = new byte[this.dByteSize];
499
500 int Pos = 0;
501 while (true)
502 {
503 i = Math.Min(this.r8, this.dByteSize - Pos);
504 Array.Copy(S, 0, Z, Pos, i);
505 Pos += i;
506
507 if (Pos >= this.dByteSize)
508 return Z;
509
510 S = this.ComputeFixed(S);
511 }
512 }
513
518 public event EventHandler NewState = null;
519 }
520}
Implementation of the KECCAK-p permutations, with a bitsize of 1600 bits, as defined in section 3 in ...
Definition: Keccak1600.cs:13
byte[] GetState()
Gets a copy of the internal state.
Definition: Keccak1600.cs:106
EventHandler NewState
Event raised when the internal state has changed. You can use this event in unit tests to validate th...
Definition: Keccak1600.cs:518
Keccak1600(int Capacity, byte Suffix, int DigestSize)
Implementation of the KECCAK-p permutations, with a bitsize of 1600 bits, as defined in section 3 in ...
Definition: Keccak1600.cs:38
void InitState(byte[] Data)
Initializes the internal state.
Definition: Keccak1600.cs:70
byte[] ComputeVariable(Stream N)
Computes the SPONGE function, as defined in section 4 of NIST FIPS 202.
Definition: Keccak1600.cs:460
byte[] ComputeFixed(byte[] S)
Computes the KECCAK-p[b, nr=24] algorithm, as defined in section 3.3 of NIST FIPS 202.
Definition: Keccak1600.cs:209
byte[] ComputeVariable(byte[] N)
Computes the SPONGE function, as defined in section 4 of NIST FIPS 202.
Definition: Keccak1600.cs:412