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;
40 public Keccak1600(
int Capacity,
byte Suffix,
byte SuffixBits,
int DigestSize)
43 this.r = 1600 - this.c;
44 this.r8 = this.r >> 3;
45 this.r8m1 = this.r8 - 1;
46 this.dByteSize = DigestSize / 8;
48 this.suffixBits = SuffixBits;
50 if ((DigestSize & 7) != 0)
51 throw new ArgumentException(
"Invalid digest size.", nameof(DigestSize));
53 if (this.c <= 0 || this.r <= 0 || this.r8m1 < 0 || (Capacity & 7) != 0)
54 throw new ArgumentException(
"Invalid capacity.", nameof(Capacity));
56 if (this.suffixBits > 6)
57 throw new ArgumentException(
"Invalid suffix.", nameof(Suffix));
59 this.suffix |= (byte)(1 << this.suffixBits);
68 if (Data.Length != 200)
69 throw new ArgumentException(
"Expected array of 200 bytes.", nameof(Data));
71 this.A_0 = BitConverter.ToUInt64(Data, 0);
72 this.A_1 = BitConverter.ToUInt64(Data, 8);
73 this.A_2 = BitConverter.ToUInt64(Data, 16);
74 this.A_3 = BitConverter.ToUInt64(Data, 24);
75 this.A_4 = BitConverter.ToUInt64(Data, 32);
76 this.A_5 = BitConverter.ToUInt64(Data, 40);
77 this.A_6 = BitConverter.ToUInt64(Data, 48);
78 this.A_7 = BitConverter.ToUInt64(Data, 56);
79 this.A_8 = BitConverter.ToUInt64(Data, 64);
80 this.A_9 = BitConverter.ToUInt64(Data, 72);
81 this.A_10 = BitConverter.ToUInt64(Data, 80);
82 this.A_11 = BitConverter.ToUInt64(Data, 88);
83 this.A_12 = BitConverter.ToUInt64(Data, 96);
84 this.A_13 = BitConverter.ToUInt64(Data, 104);
85 this.A_14 = BitConverter.ToUInt64(Data, 112);
86 this.A_15 = BitConverter.ToUInt64(Data, 120);
87 this.A_16 = BitConverter.ToUInt64(Data, 128);
88 this.A_17 = BitConverter.ToUInt64(Data, 136);
89 this.A_18 = BitConverter.ToUInt64(Data, 144);
90 this.A_19 = BitConverter.ToUInt64(Data, 152);
91 this.A_20 = BitConverter.ToUInt64(Data, 160);
92 this.A_21 = BitConverter.ToUInt64(Data, 168);
93 this.A_22 = BitConverter.ToUInt64(Data, 176);
94 this.A_23 = BitConverter.ToUInt64(Data, 184);
95 this.A_24 = BitConverter.ToUInt64(Data, 192);
104 byte[] Data =
new byte[200];
106 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_0 :
this.A_0), 0, Data, 0, 8);
107 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_1 :
this.A_1), 0, Data, 8, 8);
108 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_2 :
this.A_2), 0, Data, 16, 8);
109 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_3 :
this.A_3), 0, Data, 24, 8);
110 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_4 :
this.A_4), 0, Data, 32, 8);
111 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_5 :
this.A_5), 0, Data, 40, 8);
112 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_6 :
this.A_6), 0, Data, 48, 8);
113 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_7 :
this.A_7), 0, Data, 56, 8);
114 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_8 :
this.A_8), 0, Data, 64, 8);
115 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_9 :
this.A_9), 0, Data, 72, 8);
116 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_10 :
this.A_10), 0, Data, 80, 8);
117 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_11 :
this.A_11), 0, Data, 88, 8);
118 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_12 :
this.A_12), 0, Data, 96, 8);
119 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_13 :
this.A_13), 0, Data, 104, 8);
120 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_14 :
this.A_14), 0, Data, 112, 8);
121 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_15 :
this.A_15), 0, Data, 120, 8);
122 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_16 :
this.A_16), 0, Data, 128, 8);
123 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_17 :
this.A_17), 0, Data, 136, 8);
124 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_18 :
this.A_18), 0, Data, 144, 8);
125 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_19 :
this.A_19), 0, Data, 152, 8);
126 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_20 :
this.A_20), 0, Data, 160, 8);
127 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_21 :
this.A_21), 0, Data, 168, 8);
128 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_22 :
this.A_22), 0, Data, 176, 8);
129 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_23 :
this.A_23), 0, Data, 184, 8);
130 Buffer.BlockCopy(BitConverter.GetBytes(
this.inA2 ?
this.A2_24 :
this.A_24), 0, Data, 192, 8);
140 private static bool Rc(
int t)
164 private static bool[] GetRcs()
166 bool[] Result =
new bool[255];
169 for (t = 0; t < 255; t++)
175 private static ulong[] GetRcIr()
177 ulong[] Result =
new ulong[24];
180 for (ir = 0; ir < 24; ir++)
184 for (j = 0; j <= 6; j++)
186 i = (j + 7 * ir) % 255;
212 if (this.reportStates)
216 h(
this, EventArgs.Empty);
219 for (ir = 0; ir < 24; ir++)
224 this.C_0 = this.A_0 ^ this.A_5 ^ this.A_10 ^ this.A_15 ^ this.A_20;
225 this.C_1 = this.A_1 ^ this.A_6 ^ this.A_11 ^ this.A_16 ^ this.A_21;
226 this.C_2 = this.A_2 ^ this.A_7 ^ this.A_12 ^ this.A_17 ^ this.A_22;
227 this.C_3 = this.A_3 ^ this.A_8 ^ this.A_13 ^ this.A_18 ^ this.A_23;
228 this.C_4 = this.A_4 ^ this.A_9 ^ this.A_14 ^ this.A_19 ^ this.A_24;
230 v = this.C_4 ^ ((this.C_1 << 1) | ((this.C_1 >> 63) & 1));
237 v = this.C_0 ^ ((this.C_2 << 1) | ((this.C_2 >> 63) & 1));
244 v = this.C_1 ^ ((this.C_3 << 1) | ((this.C_3 >> 63) & 1));
251 v = this.C_2 ^ ((this.C_4 << 1) | ((this.C_4 >> 63) & 1));
258 v = this.C_3 ^ ((this.C_0 << 1) | ((this.C_0 >> 63) & 1));
265 if (this.reportStates)
269 h(
this, EventArgs.Empty);
274 this.A_1 = ((v = this.A_1) << 1) | (v >> 63);
275 this.A_10 = ((v = this.A_10) << 3) | (v >> 61);
276 this.A_7 = ((v = this.A_7) << 6) | (v >> 58);
277 this.A_11 = ((v = this.A_11) << 10) | (v >> 54);
278 this.A_17 = ((v = this.A_17) << 15) | (v >> 49);
279 this.A_18 = ((v = this.A_18) << 21) | (v >> 43);
280 this.A_3 = ((v = this.A_3) << 28) | (v >> 36);
281 this.A_5 = ((v = this.A_5) << 36) | (v >> 28);
282 this.A_16 = ((v = this.A_16) << 45) | (v >> 19);
283 this.A_8 = ((v = this.A_8) << 55) | (v >> 9);
284 this.A_21 = ((v = this.A_21) << 2) | (v >> 62);
285 this.A_24 = ((v = this.A_24) << 14) | (v >> 50);
286 this.A_4 = ((v = this.A_4) << 27) | (v >> 37);
287 this.A_15 = ((v = this.A_15) << 41) | (v >> 23);
288 this.A_23 = ((v = this.A_23) << 56) | (v >> 8);
289 this.A_19 = ((v = this.A_19) << 8) | (v >> 56);
290 this.A_13 = ((v = this.A_13) << 25) | (v >> 39);
291 this.A_12 = ((v = this.A_12) << 43) | (v >> 21);
292 this.A_2 = ((v = this.A_2) << 62) | (v >> 2);
293 this.A_20 = ((v = this.A_20) << 18) | (v >> 46);
294 this.A_14 = ((v = this.A_14) << 39) | (v >> 25);
295 this.A_22 = ((v = this.A_22) << 61) | (v >> 3);
296 this.A_9 = ((v = this.A_9) << 20) | (v >> 44);
297 this.A_6 = ((v = this.A_6) << 44) | (v >> 20);
299 if (this.reportStates)
303 h(
this, EventArgs.Empty);
308 this.A2_0 = this.A_0;
309 this.A2_5 = this.A_3;
310 this.A2_10 = this.A_1;
311 this.A2_15 = this.A_4;
312 this.A2_20 = this.A_2;
314 this.A2_1 = this.A_6;
315 this.A2_6 = this.A_9;
316 this.A2_11 = this.A_7;
317 this.A2_16 = this.A_5;
318 this.A2_21 = this.A_8;
320 this.A2_2 = this.A_12;
321 this.A2_7 = this.A_10;
322 this.A2_12 = this.A_13;
323 this.A2_17 = this.A_11;
324 this.A2_22 = this.A_14;
326 this.A2_3 = this.A_18;
327 this.A2_8 = this.A_16;
328 this.A2_13 = this.A_19;
329 this.A2_18 = this.A_17;
330 this.A2_23 = this.A_15;
332 this.A2_4 = this.A_24;
333 this.A2_9 = this.A_22;
334 this.A2_14 = this.A_20;
335 this.A2_19 = this.A_23;
336 this.A2_24 = this.A_21;
338 if (this.reportStates)
344 h(
this, EventArgs.Empty);
349 this.A_0 = this.A2_0 ^ (this.A2_2 & ~this.A2_1);
350 this.A_5 = this.A2_5 ^ (this.A2_7 & ~this.A2_6);
351 this.A_10 = this.A2_10 ^ (this.A2_12 & ~this.A2_11);
352 this.A_15 = this.A2_15 ^ (this.A2_17 & ~this.A2_16);
353 this.A_20 = this.A2_20 ^ (this.A2_22 & ~this.A2_21);
355 this.A_1 = this.A2_1 ^ (this.A2_3 & ~this.A2_2);
356 this.A_6 = this.A2_6 ^ (this.A2_8 & ~this.A2_7);
357 this.A_11 = this.A2_11 ^ (this.A2_13 & ~this.A2_12);
358 this.A_16 = this.A2_16 ^ (this.A2_18 & ~this.A2_17);
359 this.A_21 = this.A2_21 ^ (this.A2_23 & ~this.A2_22);
361 this.A_2 = this.A2_2 ^ (this.A2_4 & ~this.A2_3);
362 this.A_7 = this.A2_7 ^ (this.A2_9 & ~this.A2_8);
363 this.A_12 = this.A2_12 ^ (this.A2_14 & ~this.A2_13);
364 this.A_17 = this.A2_17 ^ (this.A2_19 & ~this.A2_18);
365 this.A_22 = this.A2_22 ^ (this.A2_24 & ~this.A2_23);
367 this.A_3 = this.A2_3 ^ (this.A2_0 & ~this.A2_4);
368 this.A_8 = this.A2_8 ^ (this.A2_5 & ~this.A2_9);
369 this.A_13 = this.A2_13 ^ (this.A2_10 & ~this.A2_14);
370 this.A_18 = this.A2_18 ^ (this.A2_15 & ~this.A2_19);
371 this.A_23 = this.A2_23 ^ (this.A2_20 & ~this.A2_24);
373 this.A_4 = this.A2_4 ^ (this.A2_1 & ~this.A2_0);
374 this.A_9 = this.A2_9 ^ (this.A2_6 & ~this.A2_5);
375 this.A_14 = this.A2_14 ^ (this.A2_11 & ~this.A2_10);
376 this.A_19 = this.A2_19 ^ (this.A2_16 & ~this.A2_15);
377 this.A_24 = this.A2_24 ^ (this.A2_21 & ~this.A2_20);
379 if (this.reportStates)
385 h(
this, EventArgs.Empty);
390 this.A_0 ^= RC_ir[ir];
392 if (this.reportStates)
396 h(
this, EventArgs.Empty);
410 this.reportStates = !(this.NewState is
null);
414 int nm1 = m / this.r;
415 byte[] S =
new byte[200];
419 for (i = 0; i < nm1; i++)
421 for (k = 0; k < this.r8; k++)
432 S[this.r8m1] ^= 0x80;
435 byte[] Z =
new byte[this.dByteSize];
440 i = Math.Min(this.r8, this.dByteSize - Pos);
441 Buffer.BlockCopy(S, 0, Z, Pos, i);
444 if (Pos >= this.dByteSize)
458 this.reportStates = !(this.NewState is
null);
462 long nm1 = m / this.r;
463 byte[] S =
new byte[200];
464 byte[] r8Buf =
new byte[this.r8];
469 for (i = 0; i < nm1; i++)
471 N.ReadAll(r8Buf, 0, this.r8);
473 for (k = 0; k < this.r8; k++)
479 int Rest = (int)(Len - N.Position);
482 N.ReadAll(r8Buf, 0, Rest);
484 for (k = 0; k < Rest; k++)
491 S[this.r8m1] ^= 0x80;
494 byte[] Z =
new byte[this.dByteSize];
499 i = Math.Min(this.r8, this.dByteSize - Pos);
500 Buffer.BlockCopy(S, 0, Z, Pos, i);
503 if (Pos >= this.dByteSize)
526 this.reportStates = !(this.NewState is
null);
530 int nm1 = m / this.r;
531 byte[] S =
new byte[200];
535 for (i = 0; i < nm1; i++)
537 for (k = 0; k < this.r8; k++)
548 S[this.r8m1] ^= 0x80;
560 private byte[] state;
561 private int statePosition;
571 this.hashFunction = H;
572 this.statePosition = 0;
583 byte[] Z =
new byte[NrBytes];
587 if (this.statePosition >= this.hashFunction.r8)
589 this.state = this.hashFunction.ComputeFixed(this.state);
590 this.statePosition = 0;
595 i = Math.Min(this.hashFunction.r8 -
this.statePosition, NrBytes - Pos);
596 Buffer.BlockCopy(this.state, this.statePosition, Z, Pos, i);
598 this.statePosition += i;
603 this.state = this.hashFunction.ComputeFixed(this.state);
604 this.statePosition = 0;
614 if (this.statePosition >= this.hashFunction.r8)
616 this.state = this.hashFunction.ComputeFixed(this.state);
617 this.statePosition = 0;
620 return this.state[this.statePosition++];
Hash digest computation context.
Context(byte[] S, Keccak1600 H)
Hash digest computation context.
byte[] Squeeze(int NrBytes)
Calculates another NrBytes number of bytes of the digest.
byte Squeeze1()
Calculates another byte of the digest.
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...
void InitState(byte[] Data)
Initializes the internal state.
Context Absorb(byte[] N)
Initiates a variable length digest computation using the SPONGE function, absorbing the input data,...
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.
Keccak1600(int Capacity, byte Suffix, byte SuffixBits, int DigestSize)
Implementation of the KECCAK-p permutations, with a bitsize of 1600 bits, as defined in section 3 in ...
byte[] ComputeVariable(byte[] N)
Computes the SPONGE function, as defined in section 4 of NIST FIPS 202.