1 /* 2 * ------------------------------------------------------------------------- 3 * Works when compiled for either 32-bit or 64-bit targets, optimized for 4 * 64 bit. 5 * 6 * Canonical implementation of Init/Update/Finalize for SHA-3 byte input. 7 * 8 * SHA3-256, SHA3-384, SHA-512 are implemented. SHA-224 can easily be added. 9 * 10 * Based on code from http://keccak.noekeon.org/ . 11 * 12 * I place the code that I wrote into public domain, free to use. 13 * 14 * I would appreciate if you give credits to this work if you used it to 15 * write or test * your code. 16 * 17 * Aug 2015. Andrey Jivsov. crypto@brainhub.org 18 * ---------------------------------------------------------------------- 19 */ 20 module sha3iuf_d.sha3; 21 22 23 version (WebAssembly) { 24 } else { 25 version = SHA3IUF_D_ENABLE_UNITTEST; 26 } 27 28 /* 'Words' here refers to ulong */ 29 /// 30 extern (C) 31 public enum SHA3_KECCAK_SPONGE_WORDS = (1600 / 8 /*bits to byte*/) / ulong.sizeof; 32 33 /// 34 extern (C) 35 public struct sha3_context 36 { 37 /* 38 * the portion of the input message that we 39 * didn't consume yet 40 */ 41 ulong saved; 42 43 union u_ 44 { 45 /* Keccak's state */ 46 ulong[.SHA3_KECCAK_SPONGE_WORDS] s; 47 ubyte[.SHA3_KECCAK_SPONGE_WORDS * 8] sb; 48 } 49 50 u_ u; 51 52 /* 53 * 0..7--the next byte after the set one 54 * (starts from 0; 0--none are buffered) 55 */ 56 uint byteIndex; 57 58 /* 59 * 0..24--the next word to integrate input 60 * (starts from 0) 61 */ 62 uint wordIndex; 63 64 /* 65 * the double size of the hash output in 66 * words (e.g. 16 for Keccak 512) 67 */ 68 uint capacityWords; 69 } 70 71 /// 72 extern (C) 73 public enum SHA3_FLAGS 74 { 75 SHA3_FLAGS_NONE = 0, 76 SHA3_FLAGS_KECCAK = 1, 77 } 78 79 //Declaration name in C language 80 public enum 81 { 82 SHA3_FLAGS_NONE = .SHA3_FLAGS.SHA3_FLAGS_NONE, 83 SHA3_FLAGS_KECCAK = .SHA3_FLAGS.SHA3_FLAGS_KECCAK, 84 } 85 86 /// 87 extern (C) 88 public enum SHA3_RETURN 89 { 90 SHA3_RETURN_OK = 0, 91 SHA3_RETURN_BAD_PARAMS = 1, 92 } 93 94 //Declaration name in C language 95 public enum 96 { 97 SHA3_RETURN_OK = .SHA3_RETURN.SHA3_RETURN_OK, 98 SHA3_RETURN_BAD_PARAMS = .SHA3_RETURN.SHA3_RETURN_BAD_PARAMS, 99 } 100 101 /// 102 public alias sha3_return_t = .SHA3_RETURN; 103 104 //#define SHA3_TRACE(format, ...) 105 //#define SHA3_TRACE_BUF(format, buf, l) 106 107 /* 108 * This flag is used to configure "pure" Keccak, as opposed to NIST SHA3. 109 */ 110 private enum SHA3_USE_KECCAK_FLAG = 0x80000000; 111 112 pragma(inline, true) 113 pure nothrow @safe @nogc @live 114 private ulong SHA3_CW(uint x) 115 116 do 117 { 118 return x & ~SHA3_USE_KECCAK_FLAG; 119 } 120 121 pragma(inline, true) 122 pure nothrow @safe @nogc @live 123 private ulong SHA3_ROTL64(ulong x, ulong y) 124 125 do 126 { 127 return (x << y) | (x >> ((ulong.sizeof * 8) - y)); 128 } 129 130 private static immutable ulong[24] keccakf_rndc = [0x0000000000000001UL, 0x0000000000008082UL, 0x800000000000808AUL, 0x8000000080008000UL, 0x000000000000808BUL, 0x0000000080000001UL, 0x8000000080008081UL, 0x8000000000008009UL, 0x000000000000008AUL, 0x0000000000000088UL, 0x0000000080008009UL, 0x000000008000000AUL, 0x000000008000808BUL, 0x800000000000008BUL, 0x8000000000008089UL, 0x8000000000008003UL, 0x8000000000008002UL, 0x8000000000000080UL, 0x000000000000800AUL, 0x800000008000000AUL, 0x8000000080008081UL, 0x8000000000008080UL, 0x0000000080000001UL, 0x8000000080008008UL]; 131 132 private static immutable uint[24] keccakf_rotc = [1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44]; 133 134 private static immutable uint[24] keccakf_piln = [10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1]; 135 136 /* 137 * generally called after SHA3_KECCAK_SPONGE_WORDS-ctx.capacityWords words 138 * are XORed into the state s 139 */ 140 pure nothrow @safe @nogc @live 141 private void keccakf(ref ulong[25] s) 142 143 do 144 { 145 enum KECCAK_ROUNDS = 24; 146 ulong t = void; 147 ulong[5] bc = void; 148 149 for (size_t round = 0; round < KECCAK_ROUNDS; round++) { 150 /* Theta */ 151 for (size_t i = 0; i < 5; i++) { 152 bc[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20]; 153 } 154 155 for (size_t i = 0; i < 5; i++) { 156 t = bc[(i + 4) % 5] ^ SHA3_ROTL64(bc[(i + 1) % 5], 1); 157 158 for (size_t j = 0; j < 25; j += 5) { 159 s[j + i] ^= t; 160 } 161 } 162 163 /* Rho Pi */ 164 t = s[1]; 165 166 for (size_t i = 0; i < 24; i++) { 167 size_t j = keccakf_piln[i]; 168 bc[0] = s[j]; 169 s[j] = SHA3_ROTL64(t, keccakf_rotc[i]); 170 t = bc[0]; 171 } 172 173 /* Chi */ 174 for (size_t j = 0; j < 25; j += 5) { 175 for (size_t i = 0; i < 5; i++) { 176 bc[i] = s[j + i]; 177 } 178 179 for (size_t i = 0; i < 5; i++) { 180 s[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5]; 181 } 182 } 183 184 /* Iota */ 185 s[0] ^= keccakf_rndc[round]; 186 } 187 } 188 189 /* *************************** Public Inteface ************************ */ 190 191 /* For Init or Reset call these: */ 192 /// 193 extern (C) 194 pure nothrow @trusted @nogc @live 195 public .sha3_return_t sha3_Init(scope void* priv, uint bitSize) 196 197 in 198 { 199 assert(priv != null); 200 } 201 202 do 203 { 204 .sha3_context* ctx = cast(.sha3_context*)(priv); 205 206 if ((bitSize != 256) && (bitSize != 384) && (bitSize != 512)) { 207 return .SHA3_RETURN.SHA3_RETURN_BAD_PARAMS; 208 } 209 210 *ctx = (*ctx).init; 211 ctx.capacityWords = 2 * bitSize / (8 * ulong.sizeof); 212 213 return .SHA3_RETURN.SHA3_RETURN_OK; 214 } 215 216 /// 217 extern (C) 218 pure nothrow @trusted @nogc @live 219 public void sha3_Init256(scope void* priv) 220 221 do 222 { 223 .sha3_Init(priv, 256); 224 } 225 226 /// 227 extern (C) 228 pure nothrow @trusted @nogc @live 229 public void sha3_Init384(scope void* priv) 230 231 do 232 { 233 .sha3_Init(priv, 384); 234 } 235 236 /// 237 extern (C) 238 pure nothrow @trusted @nogc @live 239 public void sha3_Init512(scope void* priv) 240 241 do 242 { 243 .sha3_Init(priv, 512); 244 } 245 246 /// 247 extern (C) 248 pure nothrow @trusted @nogc @live 249 public .SHA3_FLAGS sha3_SetFlags(scope void* priv, .SHA3_FLAGS flags) 250 251 in 252 { 253 assert(priv != null); 254 } 255 256 do 257 { 258 .sha3_context* ctx = cast(.sha3_context*)(priv); 259 flags &= .SHA3_FLAGS.SHA3_FLAGS_KECCAK; 260 ctx.capacityWords |= (flags == .SHA3_FLAGS.SHA3_FLAGS_KECCAK) ? (SHA3_USE_KECCAK_FLAG) : (0); 261 262 return flags; 263 } 264 265 /// 266 extern (C) 267 pure nothrow @trusted @nogc @live 268 public void sha3_Update(scope void* priv, scope const void* bufIn, size_t len) 269 270 in 271 { 272 assert(priv != null); 273 assert(bufIn != null); 274 275 .sha3_context* ctx = cast(.sha3_context*)(priv); 276 assert(ctx.byteIndex < 8); 277 assert(ctx.wordIndex < (ctx.u.s.sizeof / ctx.u.s[0].sizeof)); 278 } 279 280 do 281 { 282 .sha3_context* ctx = cast(.sha3_context*)(priv); 283 284 /* 0...7 -- how much is needed to have a word */ 285 uint old_tail = (8 - ctx.byteIndex) & 7; 286 287 const (ubyte)* buf = cast(const (ubyte)*)(bufIn); 288 289 //SHA3_TRACE_BUF("called to update with:", buf, len); 290 291 if (len < old_tail) { 292 /* 293 * have no complete word or haven't started 294 * the word yet 295 */ 296 //SHA3_TRACE("because %d<%d, store it and return", cast(uint)(len), cast(uint)(old_tail)); 297 298 /* endian-independent code follows: */ 299 while (len--) { 300 ctx.saved |= cast(ulong)(*(buf++)) << ((ctx.byteIndex++) * 8); 301 } 302 303 assert(ctx.byteIndex < 8); 304 305 return; 306 } 307 308 if (old_tail != 0) { /* will have one word to process */ 309 //SHA3_TRACE("completing one word with %d bytes", cast(uint)(old_tail)); 310 /* endian-independent code follows: */ 311 len -= old_tail; 312 313 while (old_tail--) { 314 ctx.saved |= cast(ulong)(*(buf++)) << ((ctx.byteIndex++) * 8); 315 } 316 317 /* now ready to add saved to the sponge */ 318 ctx.u.s[ctx.wordIndex] ^= ctx.saved; 319 assert(ctx.byteIndex == 8); 320 ctx.byteIndex = 0; 321 ctx.saved = 0; 322 323 if (++ctx.wordIndex == (.SHA3_KECCAK_SPONGE_WORDS - SHA3_CW(ctx.capacityWords))) { 324 keccakf(ctx.u.s); 325 ctx.wordIndex = 0; 326 } 327 } 328 329 /* now work in full words directly from input */ 330 331 assert(ctx.byteIndex == 0); 332 333 size_t words = len / ulong.sizeof; 334 uint tail = cast(uint)(len - (words * ulong.sizeof)); 335 336 //SHA3_TRACE("have %d full words to process", cast(uint)(words)); 337 338 for (size_t i = 0; i < words; i++, buf += ulong.sizeof) { 339 const ulong t = cast(ulong)(buf[0]) | (cast(ulong)(buf[1]) << (8 * 1)) | (cast(ulong)(buf[2]) << (8 * 2)) | (cast(ulong)(buf[3]) << (8 * 3)) | (cast(ulong)(buf[4]) << (8 * 4)) | (cast(ulong)(buf[5]) << (8 * 5)) | (cast(ulong)(buf[6]) << (8 * 6)) | (cast(ulong)(buf[7]) << (8 * 7)); 340 341 //#if defined(__x86_64__) || defined(__i386__) 342 // assert(core.stdc.string.memcmp(&t, buf, 8) == 0); 343 //#endif 344 345 ctx.u.s[ctx.wordIndex] ^= t; 346 347 if (++ctx.wordIndex == (.SHA3_KECCAK_SPONGE_WORDS - SHA3_CW(ctx.capacityWords))) { 348 keccakf(ctx.u.s); 349 ctx.wordIndex = 0; 350 } 351 } 352 353 //SHA3_TRACE("have %d bytes left to process, save them", cast(uint)(tail)); 354 355 /* finally, save the partial word */ 356 assert((ctx.byteIndex == 0) && (tail < 8)); 357 358 while (tail--) { 359 //SHA3_TRACE("Store byte %02x '%c'", *buf, *buf); 360 ctx.saved |= cast(ulong)(*(buf++)) << ((ctx.byteIndex++) * 8); 361 } 362 363 assert(ctx.byteIndex < 8); 364 //SHA3_TRACE("Have saved=0x%016" PRIx64 " at the end", ctx.saved); 365 } 366 367 /** 368 * This is simply the 'update' with the padding block. 369 * The padding block is 0x01 || 0x00* || 0x80. First 0x01 and last 0x80 370 * bytes are always present, but they can be the same byte. 371 */ 372 extern (C) 373 pure nothrow @trusted @nogc @live 374 public const (void)* sha3_Finalize(return scope void* priv) 375 376 in 377 { 378 assert(priv != null); 379 } 380 381 do 382 { 383 .sha3_context* ctx = cast(.sha3_context*)(priv); 384 385 //SHA3_TRACE("called with %d bytes in the buffer", ctx.byteIndex); 386 387 /* 388 * Append 2-bit suffix 01, per SHA-3 spec. Instead of 1 for padding we 389 * use 1<<2 below. The 0x02 below corresponds to the suffix 01. 390 * Overall, we feed 0, then 1, and finally 1 to start padding. Without 391 * M || 01, we would simply use 1 to start padding. 392 */ 393 394 ulong t = void; 395 396 if (ctx.capacityWords & SHA3_USE_KECCAK_FLAG) { 397 /* Keccak version */ 398 t = cast(ulong)((cast(ulong)(1)) << (ctx.byteIndex * 8)); 399 } else { 400 /* SHA3 version */ 401 t = cast(ulong)((cast(ulong)(0x02 | (1 << 2))) << ((ctx.byteIndex) * 8)); 402 } 403 404 ctx.u.s[ctx.wordIndex] ^= ctx.saved ^ t; 405 406 ctx.u.s[cast(size_t)(.SHA3_KECCAK_SPONGE_WORDS - SHA3_CW(ctx.capacityWords) - 1)] ^= 0x8000000000000000UL; 407 keccakf(ctx.u.s); 408 409 /* 410 * Return first bytes of the ctx.s. This conversion is not needed for 411 * little-endian platforms e.g. wrap with #if !defined(__BYTE_ORDER__) 412 * || !defined(__ORDER_LITTLE_ENDIAN__) || __BYTE_ORDER__!=__ORDER_LITTLE_ENDIAN__ 413 * ... the conversion below ... 414 * #endif 415 */ 416 { 417 for (uint i = 0; i < .SHA3_KECCAK_SPONGE_WORDS; i++) { 418 const uint t1 = cast(uint)(ctx.u.s[i]); 419 const uint t2 = cast(uint)((ctx.u.s[i] >> 16) >> 16); 420 ctx.u.sb[(i * 8) + 0] = cast(ubyte)(t1); 421 ctx.u.sb[(i * 8) + 1] = cast(ubyte)(t1 >> 8); 422 ctx.u.sb[(i * 8) + 2] = cast(ubyte)(t1 >> 16); 423 ctx.u.sb[(i * 8) + 3] = cast(ubyte)(t1 >> 24); 424 ctx.u.sb[(i * 8) + 4] = cast(ubyte)(t2); 425 ctx.u.sb[(i * 8) + 5] = cast(ubyte)(t2 >> 8); 426 ctx.u.sb[(i * 8) + 6] = cast(ubyte)(t2 >> 16); 427 ctx.u.sb[(i * 8) + 7] = cast(ubyte)(t2 >> 24); 428 } 429 } 430 431 //SHA3_TRACE_BUF("Hash: (first 32 bytes)", ctx.u.sb, 256 / 8); 432 433 return &(ctx.u.sb[0]); 434 } 435 436 437 438 /* Single-call hashing */ 439 /** 440 * ? 441 * 442 * Params: 443 * bitSize = 256, 384, 512 444 * flags = .SHA3_FLAGS.SHA3_FLAGS_NONE or .SHA3_FLAGS.SHA3_FLAGS_KECCAK 445 * in_ = ? 446 * inBytes = ? 447 * out_ = ? 448 * outBytes = up to bitSize / 8; truncation OK 449 * 450 * Returns: ? 451 */ 452 extern (C) 453 pure nothrow @trusted @nogc @live 454 public .sha3_return_t sha3_HashBuffer(uint bitSize, .SHA3_FLAGS flags, scope const void* in_, size_t inBytes, return scope void* out_, uint outBytes) 455 456 in 457 { 458 assert(in_ != null); 459 assert(out_ != null); 460 } 461 462 do 463 { 464 .sha3_context c = void; 465 .sha3_return_t err = .sha3_Init(&c, bitSize); 466 467 if (err != .SHA3_RETURN.SHA3_RETURN_OK) { 468 return err; 469 } 470 471 if (.sha3_SetFlags(&c, flags) != flags) { 472 return .SHA3_RETURN.SHA3_RETURN_BAD_PARAMS; 473 } 474 475 .sha3_Update(&c, in_, inBytes); 476 const void* h = .sha3_Finalize(&c); 477 uint out_length = bitSize / 8; 478 479 if (outBytes < out_length) { 480 return .SHA3_RETURN.SHA3_RETURN_BAD_PARAMS; 481 } 482 483 out_[0 .. out_length] = h[0 .. out_length]; 484 485 return .SHA3_RETURN.SHA3_RETURN_OK; 486 } 487 488 /* *************************** Self Tests ************************ */ 489 490 /* 491 * There are two set of mutually exclusive tests, based on SHA3_USE_KECCAK, 492 * which is undefined in the production version. 493 * 494 * Known answer tests are from NIST SHA3 test vectors at 495 * http://csrc.nist.gov/groups/ST/toolkit/examples.html 496 * 497 * SHA3-256: 498 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA3-256_Msg0.pdf 499 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA3-256_1600.pdf 500 * SHA3-384: 501 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA3-384_1600.pdf 502 * SHA3-512: 503 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA3-512_1600.pdf 504 * 505 * These are refered to as [FIPS 202] tests. 506 * 507 * ----- 508 * 509 * A few Keccak algorithm tests (when M and not M||01 is hashed) are 510 * added here. These are from http://keccak.noekeon.org/KeccakKAT-3.zip, 511 * ShortMsgKAT_256.txt for sizes even to 8. There is also one test for 512 * ExtremelyLongMsgKAT_256.txt. 513 * 514 * These will work with this code when SHA3_USE_KECCAK converts Finalize 515 * to use "pure" Keccak algorithm. 516 * 517 * 518 * These are referred to as [Keccak] test. 519 * 520 * ----- 521 * 522 * In one case the input from [Keccak] test was used to test SHA3 523 * implementation. In this case the calculated hash was compared with 524 * the output of the sha3sum on Fedora Core 20 (which is Perl's based). 525 * 526 */ 527 528 version (SHA3IUF_D_ENABLE_UNITTEST) 529 unittest 530 { 531 static import core.stdc.stdio; 532 static import core.stdc.string; 533 534 /* [FIPS 202] KAT follow */ 535 static immutable ubyte[256 / 8] sha3_256_empty = [0xA7, 0xFF, 0xC6, 0xF8, 0xBF, 0x1E, 0xD7, 0x66, 0x51, 0xC1, 0x47, 0x56, 0xA0, 0x61, 0xD6, 0x62, 0xF5, 0x80, 0xFF, 0x4D, 0xE4, 0x3B, 0x49, 0xFA, 0x82, 0xD8, 0x0A, 0x4B, 0x80, 0xF8, 0x43, 0x4A]; 536 static immutable ubyte[256 / 8] sha3_256_0xa3_200_times = [0x79, 0xF3, 0x8A, 0xDE, 0xC5, 0xC2, 0x03, 0x07, 0xA9, 0x8E, 0xF7, 0x6E, 0x83, 0x24, 0xAF, 0xBF, 0xD4, 0x6C, 0xFD, 0x81, 0xB2, 0x2E, 0x39, 0x73, 0xC6, 0x5F, 0xA1, 0xBD, 0x9D, 0xE3, 0x17, 0x87]; 537 static immutable ubyte[384 / 8] sha3_384_0xa3_200_times = [0x18, 0x81, 0xDE, 0x2C, 0xA7, 0xE4, 0x1E, 0xF9, 0x5D, 0xC4, 0x73, 0x2B, 0x8F, 0x5F, 0x00, 0x2B, 0x18, 0x9C, 0xC1, 0xE4, 0x2B, 0x74, 0x16, 0x8E, 0xD1, 0x73, 0x26, 0x49, 0xCE, 0x1D, 0xBC, 0xDD, 0x76, 0x19, 0x7A, 0x31, 0xFD, 0x55, 0xEE, 0x98, 0x9F, 0x2D, 0x70, 0x50, 0xDD, 0x47, 0x3E, 0x8F]; 538 static immutable ubyte[512 / 8] sha3_512_0xa3_200_times = [0xE7, 0x6D, 0xFA, 0xD2, 0x20, 0x84, 0xA8, 0xB1, 0x46, 0x7F, 0xCF, 0x2F, 0xFA, 0x58, 0x36, 0x1B, 0xEC, 0x76, 0x28, 0xED, 0xF5, 0xF3, 0xFD, 0xC0, 0xE4, 0x80, 0x5D, 0xC4, 0x8C, 0xAE, 0xEC, 0xA8, 0x1B, 0x7C, 0x13, 0xC3, 0x0A, 0xDF, 0x52, 0xA3, 0x65, 0x95, 0x84, 0x73, 0x9A, 0x2D, 0xF4, 0x6B, 0xE5, 0x89, 0xC5, 0x1C, 0xA1, 0xA4, 0xA8, 0x41, 0x6D, 0xF6, 0x54, 0x5A, 0x1C, 0xE8, 0xBA, 0x00]; 539 540 /* ---- "pure" Keccak algorithm begins; from [Keccak] ----- */ 541 542 ubyte[200] buf = void; 543 .sha3_HashBuffer(256, .SHA3_FLAGS.SHA3_FLAGS_KECCAK, &("abc\0"[0]), 3, &(buf[0]), buf.length); 544 545 assert(core.stdc..string.memcmp(&(buf[0]), &("\x4e\x03\x65\x7a\xea\x45\xa9\x4f\xc7\xd4\x7b\xa8\x26\xc8\xd6\x67\xc0\xd1\xe6\xe3\x3a\x64\xa0\x36\xec\x44\xf5\x8f\xa1\x2d\x6c\x45\0"[0]), 256 / 8) == 0, "SHA3-256(abc) doesn't match known answer (single buffer)\n"); 546 547 .sha3_context c = void; 548 const (ubyte)* hash = void; 549 550 { 551 .sha3_Init256(&c); 552 .sha3_SetFlags(&c, .SHA3_FLAGS.SHA3_FLAGS_KECCAK); 553 .sha3_Update(&c, &("\xcc\0"[0]), 1); 554 hash = cast(const (ubyte)*)(.sha3_Finalize(&c)); 555 556 assert(core.stdc..string.memcmp(hash, &("\xee\xad\x6d\xbf\xc7\x34\x0a\x56\xca\xed\xc0\x44\x69\x6a\x16\x88\x70\x54\x9a\x6a\x7f\x6f\x56\x96\x1e\x84\xa5\x4b\xd9\x97\x0b\x8a\0"[0]), 256 / 8) == 0, "SHA3-256(cc) doesn't match known answer (single buffer)\n"); 557 } 558 559 { 560 .sha3_Init256(&c); 561 .sha3_SetFlags(&c, .SHA3_FLAGS.SHA3_FLAGS_KECCAK); 562 .sha3_Update(&c, &("\x41\xfb\0"[0]), 2); 563 hash = cast(const (ubyte)*)(.sha3_Finalize(&c)); 564 565 assert(core.stdc..string.memcmp(hash, &("\xa8\xea\xce\xda\x4d\x47\xb3\x28\x1a\x79\x5a\xd9\xe1\xea\x21\x22\xb4\x07\xba\xf9\xaa\xbc\xb9\xe1\x8b\x57\x17\xb7\x87\x35\x37\xd2\0"[0]), 256 / 8) == 0, "SHA3-256(41fb) doesn't match known answer (single buffer)\n"); 566 } 567 568 { 569 .sha3_Init256(&c); 570 .sha3_SetFlags(&c, .SHA3_FLAGS.SHA3_FLAGS_KECCAK); 571 .sha3_Update(&c, &("\x52\xa6\x08\xab\x21\xcc\xdd\x8a\x44\x57\xa5\x7e\xde\x78\x21\x76\0"[0]), 128 / 8); 572 hash = cast(const (ubyte)*)(.sha3_Finalize(&c)); 573 574 assert(core.stdc..string.memcmp(hash, &("\x0e\x32\xde\xfa\x20\x71\xf0\xb5\xac\x0e\x6a\x10\x8b\x84\x2e\xd0\xf1\xd3\x24\x97\x12\xf5\x8e\xe0\xdd\xf9\x56\xfe\x33\x2a\x5f\x95\0"[0]), 256 / 8) == 0, "SHA3-256(52a6...76) doesn't match known answer (single buffer)\n"); 575 } 576 577 { 578 .sha3_Init256(&c); 579 .sha3_SetFlags(&c, .SHA3_FLAGS.SHA3_FLAGS_KECCAK); 580 .sha3_Update(&c, &("\x43\x3c\x53\x03\x13\x16\x24\xc0\x02\x1d\x86\x8a\x30\x82\x54\x75\xe8\xd0\xbd\x30\x52\xa0\x22\x18\x03\x98\xf4\xca\x44\x23\xb9\x82\x14\xb6\xbe\xaa\xc2\x1c\x88\x07\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0\x92\xcc\x1b\x06\xce\xdf\x32\x24\xd5\xed\x1e\xc2\x97\x84\x44\x4f\x22\xe0\x8a\x55\xaa\x58\x54\x2b\x52\x4b\x02\xcd\x3d\x5d\x5f\x69\x07\xaf\xe7\x1c\x5d\x74\x62\x22\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84\x6d\xcb\xb4\xce\0"[0]), 800 / 8); 581 hash = cast(const (ubyte)*)(.sha3_Finalize(&c)); 582 583 assert(core.stdc..string.memcmp(hash, &("\xce\x87\xa5\x17\x3b\xff\xd9\x23\x99\x22\x16\x58\xf8\x01\xd4\x5c\x29\x4d\x90\x06\xee\x9f\x3f\x9d\x41\x9c\x8d\x42\x77\x48\xdc\x41\0"[0]), 256 / 8) == 0, "SHA3-256(433C...CE) doesn't match known answer (single buffer)\n"); 584 } 585 586 /* 587 * SHA3-256 byte-by-byte: 16777216 steps. ExtremelyLongMsgKAT_256 588 * [Keccak] 589 */ 590 version (SHA3IUF_D_ALL_UNITTEST) { 591 { 592 uint i = 16777216; 593 .sha3_Init256(&c); 594 .sha3_SetFlags(&c, .SHA3_FLAGS.SHA3_FLAGS_KECCAK); 595 596 while (i--) { 597 core.stdc.stdio.printf("%u\n", i); 598 .sha3_Update(&c, &("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno\0"[0]), 64); 599 } 600 601 hash = cast(const (ubyte)*)(.sha3_Finalize(&c)); 602 603 assert(core.stdc..string.memcmp(hash, &("\x5f\x31\x3c\x39\x96\x3d\xcf\x79\x2b\x54\x70\xd4\xad\xe9\xf3\xa3\x56\xa3\xe4\x02\x17\x48\x69\x0a\x95\x83\x72\xe2\xb0\x6f\x82\xa4\0"[0]), 256 / 8) == 0, "SHA3-256( abcdefgh...[16777216 times] ) doesn't match known answer\n"); 604 605 core.stdc.stdio.printf("Keccak-256 tests passed OK\n"); 606 } 607 } 608 609 /* ----- SHA3 testing begins ----- */ 610 611 /* SHA-256 on an empty buffer */ 612 { 613 .sha3_Init256(&c); 614 hash = cast(const (ubyte)*)(.sha3_Finalize(&c)); 615 616 assert(core.stdc..string.memcmp(&(sha3_256_empty[0]), hash, sha3_256_empty.length) == 0, "SHA3-256() doesn't match known answer\n"); 617 618 .sha3_HashBuffer(256, .SHA3_FLAGS.SHA3_FLAGS_NONE, &("abc\0"[0]), 3, &(buf[0]), buf.length); 619 620 assert(core.stdc..string.memcmp(&(buf[0]), &("\x3a\x98\x5d\xa7\x4f\xe2\x25\xb2\x04\x5c\x17\x2d\x6b\xd3\x90\xbd\x85\x5f\x08\x6e\x3e\x9d\x52\x5b\x46\xbf\xe2\x45\x11\x43\x15\x32\0"[0]), 256 / 8) == 0, "SHA3-256(abc) doesn't match known answer (single buffer)\n"); 621 } 622 623 /* set to value c1 */ 624 const ubyte c1 = 0xA3; 625 buf[] = c1; 626 627 /* SHA3-256 as a single buffer. [FIPS 202] */ 628 { 629 .sha3_Init256(&c); 630 .sha3_Update(&c, &(buf[0]), buf.length); 631 hash = cast(const (ubyte)*)(.sha3_Finalize(&c)); 632 633 assert(core.stdc..string.memcmp(&(sha3_256_0xa3_200_times[0]), hash, sha3_256_0xa3_200_times.length) == 0, "SHA3-256( 0xA3 ... [200 times] ) doesn't match known answer (1 buffer)\n"); 634 } 635 636 /* SHA3-256 in two steps. [FIPS 202] */ 637 { 638 .sha3_Init256(&c); 639 .sha3_Update(&c, &(buf[0]), buf.length / 2); 640 .sha3_Update(&c, &(buf[0]) + (buf.length / 2), buf.length / 2); 641 hash = cast(const (ubyte)*)(.sha3_Finalize(&c)); 642 643 assert(core.stdc..string.memcmp(&(sha3_256_0xa3_200_times[0]), hash, sha3_256_0xa3_200_times.length) == 0, "SHA3-256( 0xA3 ... [200 times] ) doesn't match known answer (2 steps)\n"); 644 } 645 646 /* SHA3-256 byte-by-byte: 200 steps. [FIPS 202] */ 647 { 648 uint i = 200; 649 .sha3_Init256(&c); 650 651 while (i--) { 652 .sha3_Update(&c, &c1, 1); 653 } 654 655 hash = cast(const (ubyte)*)(.sha3_Finalize(&c)); 656 657 assert(core.stdc..string.memcmp(&(sha3_256_0xa3_200_times[0]), hash, sha3_256_0xa3_200_times.length) == 0, "SHA3-256( 0xA3 ... [200 times] ) doesn't match known answer (200 steps)\n"); 658 } 659 660 /* 661 * SHA3-256 byte-by-byte: 135 bytes. Input from [Keccak]. Output 662 * matched with sha3sum. 663 */ 664 { 665 .sha3_Init256(&c); 666 .sha3_Update(&c, &("\xb7\x71\xd5\xce\xf5\xd1\xa4\x1a\x93\xd1\x56\x43\xd7\x18\x1d\x2a\x2e\xf0\xa8\xe8\x4d\x91\x81\x2f\x20\xed\x21\xf1\x47\xbe\xf7\x32\xbf\x3a\x60\xef\x40\x67\xc3\x73\x4b\x85\xbc\x8c\xd4\x71\x78\x0f\x10\xdc\x9e\x82\x91\xb5\x83\x39\xa6\x77\xb9\x60\x21\x8f\x71\xe7\x93\xf2\x79\x7a\xea\x34\x94\x06\x51\x28\x29\x06\x5d\x37\xbb\x55\xea\x79\x6f\xa4\xf5\x6f\xd8\x89\x6b\x49\xb2\xcd\x19\xb4\x32\x15\xad\x96\x7c\x71\x2b\x24\xe5\x03\x2d\x06\x52\x32\xe0\x2c\x12\x74\x09\xd2\xed\x41\x46\xb9\xd7\x5d\x76\x3d\x52\xdb\x98\xd9\x49\xd3\xb0\xfe\xd6\xa8\x05\x2f\xbb\0"[0]), 1080 / 8); 667 hash = cast(const (ubyte)*)(.sha3_Finalize(&c)); 668 669 assert(core.stdc..string.memcmp(hash, &("\xa1\x9e\xee\x92\xbb\x20\x97\xb6\x4e\x82\x3d\x59\x77\x98\xaa\x18\xbe\x9b\x7c\x73\x6b\x80\x59\xab\xfd\x67\x79\xac\x35\xac\x81\xb5\0"[0]), 256 / 8) == 0, "SHA3-256( b771 ... ) doesn't match the known answer\n"); 670 } 671 672 /* SHA3-384 as a single buffer. [FIPS 202] */ 673 { 674 .sha3_Init384(&c); 675 .sha3_Update(&c, &(buf[0]), buf.length); 676 hash = cast(const (ubyte)*)(.sha3_Finalize(&c)); 677 678 assert(core.stdc..string.memcmp(&(sha3_384_0xa3_200_times[0]), hash, sha3_384_0xa3_200_times.length) == 0, "SHA3-384( 0xA3 ... [200 times] ) doesn't match known answer (1 buffer)\n"); 679 } 680 681 /* SHA3-384 in two steps. [FIPS 202] */ 682 { 683 .sha3_Init384(&c); 684 .sha3_Update(&c, &(buf[0]), buf.length / 2); 685 .sha3_Update(&c, &(buf[0]) + (buf.length / 2), buf.length / 2); 686 hash = cast(const (ubyte)*)(.sha3_Finalize(&c)); 687 688 assert(core.stdc..string.memcmp(&(sha3_384_0xa3_200_times[0]), hash, sha3_384_0xa3_200_times.length) == 0, "SHA3-384( 0xA3 ... [200 times] ) doesn't match known answer (2 steps)\n"); 689 } 690 691 /* SHA3-384 byte-by-byte: 200 steps. [FIPS 202] */ 692 { 693 uint i = 200; 694 .sha3_Init384(&c); 695 696 while (i--) { 697 .sha3_Update(&c, &c1, 1); 698 } 699 700 hash = cast(const (ubyte)*)(.sha3_Finalize(&c)); 701 702 assert(core.stdc..string.memcmp(&(sha3_384_0xa3_200_times[0]), hash, sha3_384_0xa3_200_times.length) == 0, "SHA3-384( 0xA3 ... [200 times] ) doesn't match known answer (200 steps)\n"); 703 } 704 705 /* SHA3-512 as a single buffer. [FIPS 202] */ 706 { 707 .sha3_Init512(&c); 708 .sha3_Update(&c, &(buf[0]), buf.length); 709 hash = cast(const (ubyte)*)(.sha3_Finalize(&c)); 710 711 assert(core.stdc..string.memcmp(&(sha3_512_0xa3_200_times[0]), hash, sha3_512_0xa3_200_times.length) == 0, "SHA3-512( 0xA3 ... [200 times] ) doesn't match known answer (1 buffer)\n"); 712 } 713 714 /* SHA3-512 in two steps. [FIPS 202] */ 715 { 716 .sha3_Init512(&c); 717 .sha3_Update(&c, &(buf[0]), buf.length / 2); 718 .sha3_Update(&c, &(buf[0]) + (buf.length / 2), buf.length / 2); 719 hash = cast(const (ubyte)*)(.sha3_Finalize(&c)); 720 721 assert(core.stdc..string.memcmp(&(sha3_512_0xa3_200_times[0]), hash, sha3_512_0xa3_200_times.length) == 0, "SHA3-512( 0xA3 ... [200 times] ) doesn't match known answer (2 steps)\n"); 722 } 723 724 /* SHA3-512 byte-by-byte: 200 steps. [FIPS 202] */ 725 { 726 uint i = 200; 727 .sha3_Init512(&c); 728 729 while (i--) { 730 .sha3_Update(&c, &c1, 1); 731 } 732 733 hash = cast(const (ubyte)*)(.sha3_Finalize(&c)); 734 735 assert(core.stdc..string.memcmp(&(sha3_512_0xa3_200_times[0]), hash, sha3_512_0xa3_200_times.length) == 0, "SHA3-512( 0xA3 ... [200 times] ) doesn't match known answer (200 steps)\n"); 736 } 737 738 core.stdc.stdio.printf("SHA3-256, SHA3-384, SHA3-512 tests passed OK\n"); 739 }