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;
38 public Keccak1600(
int Capacity,
byte Suffix,
int DigestSize)
41 this.r = 1600 - this.c;
42 this.r8 = this.r >> 3;
43 this.r8m1 = this.r8 - 1;
44 this.dByteSize = DigestSize / 8;
48 if ((DigestSize & 7) != 0)
49 throw new ArgumentException(
"Invalid digest size.", nameof(DigestSize));
51 if (this.c <= 0 || this.r <= 0 || this.r8m1 < 0 || (Capacity & 7) != 0)
52 throw new ArgumentException(
"Invalid capacity.", nameof(Capacity));
60 if (this.suffixBits > 6)
61 throw new ArgumentException(
"Invalid suffix.", nameof(Suffix));
63 this.suffix |= (byte)(1 << this.suffixBits);
72 if (Data.Length != 200)
73 throw new ArgumentException(
"Expected array of 200 bytes.", nameof(Data));
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);
108 byte[] Data =
new byte[200];
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);
144 private static bool Rc(
int t)
168 private static bool[] GetRcs()
170 bool[] Result =
new bool[255];
173 for (t = 0; t < 255; t++)
179 private static ulong[] GetRcIr()
181 ulong[] Result =
new ulong[24];
184 for (ir = 0; ir < 24; ir++)
188 for (j = 0; j <= 6; j++)
190 i = (j + 7 * ir) % 255;
216 if (this.reportStates)
220 h(
this, EventArgs.Empty);
223 for (ir = 0; ir < 24; ir++)
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;
234 v = this.C_4 ^ ((this.C_1 << 1) | ((this.C_1 >> 63) & 1));
241 v = this.C_0 ^ ((this.C_2 << 1) | ((this.C_2 >> 63) & 1));
248 v = this.C_1 ^ ((this.C_3 << 1) | ((this.C_3 >> 63) & 1));
255 v = this.C_2 ^ ((this.C_4 << 1) | ((this.C_4 >> 63) & 1));
262 v = this.C_3 ^ ((this.C_0 << 1) | ((this.C_0 >> 63) & 1));
269 if (this.reportStates)
273 h(
this, EventArgs.Empty);
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);
303 if (this.reportStates)
307 h(
this, EventArgs.Empty);
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;
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;
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;
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;
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;
342 if (this.reportStates)
348 h(
this, EventArgs.Empty);
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);
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);
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);
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);
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);
383 if (this.reportStates)
389 h(
this, EventArgs.Empty);
394 this.A_0 ^= RC_ir[ir];
396 if (this.reportStates)
400 h(
this, EventArgs.Empty);
414 this.reportStates = !(this.NewState is
null);
418 int nm1 = m / this.r;
419 byte[] S =
new byte[200];
423 for (i = 0; i < nm1; i++)
425 for (k = 0; k < this.r8; k++)
436 S[this.r8m1] ^= 0x80;
439 byte[] Z =
new byte[this.dByteSize];
444 i = Math.Min(this.r8, this.dByteSize - Pos);
445 Array.Copy(S, 0, Z, Pos, i);
448 if (Pos >= this.dByteSize)
462 this.reportStates = !(this.NewState is
null);
466 long nm1 = m / this.r;
467 byte[] S =
new byte[200];
468 byte[] r8Buf =
new byte[this.r8];
473 for (i = 0; i < nm1; i++)
475 N.ReadAll(r8Buf, 0, this.r8);
477 for (k = 0; k < this.r8; k++)
483 int Rest = (int)(Len - N.Position);
486 N.ReadAll(r8Buf, 0, Rest);
488 for (k = 0; k < Rest; k++)
495 S[this.r8m1] ^= 0x80;
498 byte[] Z =
new byte[this.dByteSize];
503 i = Math.Min(this.r8, this.dByteSize - Pos);
504 Array.Copy(S, 0, Z, Pos, i);
507 if (Pos >= this.dByteSize)
Implementation of the KECCAK-p permutations, with a bitsize of 1600 bits, as defined in section 3 in ...
byte[] GetState()
Gets a copy of the internal state.
EventHandler NewState
Event raised when the internal state has changed. You can use this event in unit tests to validate th...
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 ...
void InitState(byte[] Data)
Initializes the internal state.
byte[] ComputeVariable(Stream N)
Computes the SPONGE function, as defined in section 4 of NIST FIPS 202.
byte[] ComputeFixed(byte[] S)
Computes the KECCAK-p[b, nr=24] algorithm, as defined in section 3.3 of NIST FIPS 202.
byte[] ComputeVariable(byte[] N)
Computes the SPONGE function, as defined in section 4 of NIST FIPS 202.