1 /// Computes SHA-3 hashes of arbitary data. 2 /// Reference: NIST FIPS PUB 202 3 /// License: $(LINK2 www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 4 /// Authors: $(LINK2 github.com/dd86k, dd86k) 5 module sha3d; 6 7 private import std.digest; 8 private import core.bitop : rol, bswap; 9 10 private immutable ulong[24] K_RC = [ 11 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000, 12 0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009, 13 0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, 14 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003, 15 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a, 16 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 17 ]; 18 private immutable int[24] K_ROTC = [ 19 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 20 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 21 ]; 22 private immutable int[24] K_PI = [ 23 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 24 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 25 ]; 26 27 /// Template API SHA-3/SHAKE implementation using the Keccak[1600] function. 28 /// 29 /// Supports SHA-3-224, SHA-3-256, SHA-3-384, SHA-3-512, SHAKE-128, and SHAKE-256. 30 /// It is recommended to use the SHA3_224, SHA3_256, SHA3_384, SHA3_512, SHAKE128, 31 /// and SHAKE256 aliases. 32 /// Params: 33 /// digestSize = Digest size in bits 34 /// shake = Set to true for SHAKE; Otherwise false for SHA-3 35 public struct KECCAK(uint digestSize, bool shake = false) 36 { 37 static if (shake) 38 static assert(digestSize == 128 || digestSize == 256, 39 "digest size must be 128 or 256 bits for SHAKE"); 40 else 41 static assert(digestSize == 224 || digestSize == 256 || 42 digestSize == 384 || digestSize == 512, 43 "digest size must be 224, 256, 384, or 512 bits for SHA-3"); 44 45 @safe @nogc pure nothrow: 46 47 enum blockSize = 1600 - digestSize * 2; /// Sponge rate in bits 48 49 private enum 50 { 51 digestSizeBytes = digestSize / 8, /// Digest size in bytes 52 delim = shake ? 0x1f : 0x06, /// Delimiter when finishing 53 rate = blockSize / 8 /// Sponge rate in bytes 54 } 55 56 union 57 { 58 private ubyte[200] st; // state (8bit) 59 private ulong[25] st64; // state (64bit) 60 private size_t[200 / size_t.sizeof] stz; // state (size_t) 61 } 62 63 static assert(st64.sizeof == st.sizeof); 64 static assert(stz.sizeof == st.sizeof); 65 66 private size_t pt; // left-over pointer 67 68 /// Initiates the structure. Begins the SHA-3/SHAKE operation. 69 /// This is better used when restarting the operation (e.g., 70 /// for a file). 71 void start() 72 { 73 this = typeof(this).init; 74 } 75 76 /// Feed the algorithm with data 77 /// Also implements the $(REF isOutputRange, std,range,primitives) 78 /// interface for `ubyte` and `const(ubyte)[]`. 79 /// Params: input = Input data to digest 80 void put(scope const(ubyte)[] input...) @trusted 81 { 82 size_t j = pt; 83 84 // Process wordwise if properly aligned. 85 if ((j | cast(size_t) input.ptr) % size_t.alignof == 0) 86 { 87 static assert(rate % size_t.sizeof == 0); 88 foreach (const word; (cast(size_t*) input.ptr)[0 .. input.length / size_t.sizeof]) 89 { 90 stz.ptr[j / size_t.sizeof] ^= word; 91 j += size_t.sizeof; 92 if (j >= rate) 93 { 94 transform; 95 j = 0; 96 } 97 } 98 input = input.ptr[input.length - (input.length % size_t.sizeof) .. input.length]; 99 } 100 101 // Process remainder bytewise. 102 foreach (const b; input) 103 { 104 st.ptr[j++] ^= b; 105 if (j >= rate) 106 { 107 transform; 108 j = 0; 109 } 110 } 111 112 pt = j; 113 } 114 115 /// Returns the finished hash. This also clears part of the state, 116 /// leaving just the final digest. 117 ubyte[digestSizeBytes] finish() 118 { 119 st[pt] ^= delim; 120 st[rate - 1] ^= 0x80; 121 transform; 122 123 st[digestSizeBytes .. $] = 0; // Zero possible sensitive data 124 return st[0 .. digestSizeBytes]; 125 } 126 127 private: 128 void transform() 129 { 130 ulong[5] bc = void; 131 132 version (BigEndian) swap; 133 134 ROUND(bc, st64, 0); 135 ROUND(bc, st64, 1); 136 ROUND(bc, st64, 2); 137 ROUND(bc, st64, 3); 138 ROUND(bc, st64, 4); 139 ROUND(bc, st64, 5); 140 ROUND(bc, st64, 6); 141 ROUND(bc, st64, 7); 142 ROUND(bc, st64, 8); 143 ROUND(bc, st64, 9); 144 ROUND(bc, st64, 10); 145 ROUND(bc, st64, 11); 146 ROUND(bc, st64, 12); 147 ROUND(bc, st64, 13); 148 ROUND(bc, st64, 14); 149 ROUND(bc, st64, 15); 150 ROUND(bc, st64, 16); 151 ROUND(bc, st64, 17); 152 ROUND(bc, st64, 18); 153 ROUND(bc, st64, 19); 154 ROUND(bc, st64, 20); 155 ROUND(bc, st64, 21); 156 ROUND(bc, st64, 22); 157 ROUND(bc, st64, 23); 158 159 version (BigEndian) swap; 160 } 161 } 162 163 private: 164 @safe: 165 pure: 166 nothrow: 167 168 static void THETA1(ref ulong[5] bc, ref ulong[25] st64, size_t i) @nogc 169 { 170 bc[i] = st64[i] ^ st64[i + 5] ^ st64[i + 10] ^ st64[i + 15] ^ st64[i + 20]; 171 } 172 173 static void THETA2(ref ulong[5] bc, ref ulong[25] st64, ref ulong t, size_t i) @nogc 174 { 175 t = bc[(i + 4) % 5] ^ rol(bc[(i + 1) % 5], 1); 176 st64[ i] ^= t; 177 st64[ 5 + i] ^= t; 178 st64[10 + i] ^= t; 179 st64[15 + i] ^= t; 180 st64[20 + i] ^= t; 181 } 182 183 static void RHO(ref ulong[5] bc, ref ulong[25] st64, ref ulong t, size_t i) @nogc 184 { 185 int j = K_PI[i]; 186 bc[0] = st64[j]; 187 st64[j] = rol(t, K_ROTC[i]); 188 t = bc[0]; 189 } 190 191 static void CHI(ref ulong[5] bc, ref ulong[25] st64, size_t j) @nogc 192 { 193 bc[0] = st64[j]; 194 bc[1] = st64[j + 1]; 195 bc[2] = st64[j + 2]; 196 bc[3] = st64[j + 3]; 197 bc[4] = st64[j + 4]; 198 199 st64[j] ^= (~bc[1]) & bc[2]; 200 st64[j + 1] ^= (~bc[2]) & bc[3]; 201 st64[j + 2] ^= (~bc[3]) & bc[4]; 202 st64[j + 3] ^= (~bc[4]) & bc[0]; 203 st64[j + 4] ^= (~bc[0]) & bc[1]; 204 } 205 206 static void ROUND(ref ulong[5] bc, ref ulong[25] st64, size_t r) @nogc 207 { 208 ulong t = void; 209 // Theta 210 THETA1(bc, st64, 0); 211 THETA1(bc, st64, 1); 212 THETA1(bc, st64, 2); 213 THETA1(bc, st64, 3); 214 THETA1(bc, st64, 4); 215 THETA2(bc, st64, t, 0); 216 THETA2(bc, st64, t, 1); 217 THETA2(bc, st64, t, 2); 218 THETA2(bc, st64, t, 3); 219 THETA2(bc, st64, t, 4); 220 t = st64[1]; 221 // Rho 222 RHO(bc, st64, t, 0); 223 RHO(bc, st64, t, 1); 224 RHO(bc, st64, t, 2); 225 RHO(bc, st64, t, 3); 226 RHO(bc, st64, t, 4); 227 RHO(bc, st64, t, 5); 228 RHO(bc, st64, t, 6); 229 RHO(bc, st64, t, 7); 230 RHO(bc, st64, t, 8); 231 RHO(bc, st64, t, 9); 232 RHO(bc, st64, t, 10); 233 RHO(bc, st64, t, 11); 234 RHO(bc, st64, t, 12); 235 RHO(bc, st64, t, 13); 236 RHO(bc, st64, t, 14); 237 RHO(bc, st64, t, 15); 238 RHO(bc, st64, t, 16); 239 RHO(bc, st64, t, 17); 240 RHO(bc, st64, t, 18); 241 RHO(bc, st64, t, 19); 242 RHO(bc, st64, t, 20); 243 RHO(bc, st64, t, 21); 244 RHO(bc, st64, t, 22); 245 RHO(bc, st64, t, 23); 246 // Chi 247 CHI(bc, st64, 0); 248 CHI(bc, st64, 5); 249 CHI(bc, st64, 10); 250 CHI(bc, st64, 15); 251 CHI(bc, st64, 20); 252 // Iota 253 st64[0] ^= K_RC[r]; 254 } 255 256 version (BigEndian) 257 void swap() @nogc 258 { 259 st64[ 0] = bswap(st64[ 0]); 260 st64[ 1] = bswap(st64[ 1]); 261 st64[ 2] = bswap(st64[ 2]); 262 st64[ 3] = bswap(st64[ 3]); 263 st64[ 4] = bswap(st64[ 4]); 264 st64[ 5] = bswap(st64[ 5]); 265 st64[ 6] = bswap(st64[ 6]); 266 st64[ 7] = bswap(st64[ 7]); 267 st64[ 8] = bswap(st64[ 8]); 268 st64[ 9] = bswap(st64[ 9]); 269 st64[10] = bswap(st64[10]); 270 st64[11] = bswap(st64[11]); 271 st64[12] = bswap(st64[12]); 272 st64[13] = bswap(st64[13]); 273 st64[14] = bswap(st64[14]); 274 st64[15] = bswap(st64[15]); 275 st64[16] = bswap(st64[16]); 276 st64[17] = bswap(st64[17]); 277 st64[18] = bswap(st64[18]); 278 st64[19] = bswap(st64[19]); 279 st64[20] = bswap(st64[20]); 280 st64[21] = bswap(st64[21]); 281 st64[22] = bswap(st64[22]); 282 st64[23] = bswap(st64[23]); 283 } 284 285 /// Test against empty datasets 286 @safe unittest 287 { 288 assert(toHexString(sha3_224Of("")) == 289 "6B4E03423667DBB73B6E15454F0EB1ABD4597F9A1B078E3F5B5A6BC7"); 290 291 assert(toHexString(sha3_256Of("")) == 292 "A7FFC6F8BF1ED76651C14756A061D662F580FF4DE43B49FA82D80A4B80F8434A"); 293 294 assert(toHexString(sha3_384Of("")) == 295 "0C63A75B845E4F7D01107D852E4C2485C51A50AAAA94FC61995E71BBEE983A2AC37138"~ 296 "31264ADB47FB6BD1E058D5F004"); 297 298 assert(toHexString(sha3_512Of("")) == 299 "A69F73CCA23A9AC5C8B567DC185A756E97C982164FE25859E0D1DCC1475C80A615B212"~ 300 "3AF1F5F94C11E3E9402C3AC558F500199D95B6D3E301758586281DCD26"); 301 } 302 303 /// Of wrappers + toHexString 304 @safe unittest 305 { 306 assert(toHexString(sha3_224Of("abc")) == 307 "E642824C3F8CF24AD09234EE7D3C766FC9A3A5168D0C94AD73B46FDF"); 308 309 assert(toHexString(sha3_256Of("abc")) == 310 "3A985DA74FE225B2045C172D6BD390BD855F086E3E9D525B46BFE24511431532"); 311 312 assert(toHexString(sha3_384Of("abc")) == 313 "EC01498288516FC926459F58E2C6AD8DF9B473CB0FC08C2596DA7CF0E49BE4B298D88C"~ 314 "EA927AC7F539F1EDF228376D25"); 315 316 assert(toHexString(sha3_512Of("abc")) == 317 "B751850B1A57168A5693CD924B6B096E08F621827444F70D884F5D0240D2712E10E116"~ 318 "E9192AF3C91A7EC57647E3934057340B4CF408D5A56592F8274EEC53F0"); 319 } 320 321 /// Structure functions 322 @safe unittest 323 { 324 SHA3_224 hash; 325 hash.start(); 326 ubyte[1024] data; 327 hash.put(data); 328 ubyte[28] result = hash.finish(); 329 } 330 331 /// Template usage 332 @safe unittest 333 { 334 // Let's use the template features: 335 // NOTE: When passing a SHA3 to a function, it must be passed by reference! 336 void doSomething(T)(ref T hash) 337 if (isDigest!T) 338 { 339 hash.put(cast(ubyte) 0); 340 } 341 SHA3_224 sha; 342 sha.start(); 343 doSomething(sha); 344 assert(toHexString(sha.finish()) == 345 "BDD5167212D2DC69665F5A8875AB87F23D5CE7849132F56371A19096"); 346 } 347 348 /// Alias for SHA-3-224. Recommended to use over the $(D KECCAK) structure. 349 public alias SHA3_224 = KECCAK!(224, false); 350 /// Alias for SHA-3-256. Recommended to use over the $(D KECCAK) structure. 351 public alias SHA3_256 = KECCAK!(256, false); 352 /// Alias for SHA-3-384. Recommended to use over the $(D KECCAK) structure. 353 public alias SHA3_384 = KECCAK!(384, false); 354 /// Alias for SHA-3-512. Recommended to use over the $(D KECCAK) structure. 355 public alias SHA3_512 = KECCAK!(512, false); 356 /// Alias for SHAKE-128. Recommended to use over the $(D KECCAK) structure. 357 public alias SHAKE128 = KECCAK!(128, true); 358 /// Alias for SHAKE-256. Recommended to use over the $(D KECCAK) structure. 359 public alias SHAKE256 = KECCAK!(256, true); 360 361 @safe unittest 362 { 363 assert(isDigest!SHA3_224); 364 assert(isDigest!SHA3_256); 365 assert(isDigest!SHA3_384); 366 assert(isDigest!SHA3_512); 367 assert(isDigest!SHAKE128); 368 assert(isDigest!SHAKE256); 369 } 370 371 /// Convience alias for $(REF digest, std,digest) using the SHA-3 implementation. 372 auto sha3_224Of(T...)(T data) 373 { 374 return digest!(SHA3_224, T)(data); 375 } 376 /// Ditto 377 auto sha3_256Of(T...)(T data) 378 { 379 return digest!(SHA3_256, T)(data); 380 } 381 /// Ditto 382 auto sha3_384Of(T...)(T data) 383 { 384 return digest!(SHA3_384, T)(data); 385 } 386 /// Ditto 387 auto sha3_512Of(T...)(T data) 388 { 389 return digest!(SHA3_512, T)(data); 390 } 391 /// Ditto 392 auto shake128Of(T...)(T data) 393 { 394 return digest!(SHAKE128, T)(data); 395 } 396 /// Ditto 397 auto shake256Of(T...)(T data) 398 { 399 return digest!(SHAKE256, T)(data); 400 } 401 402 /// digest! wrappers 403 @safe unittest 404 { 405 ubyte[28] hash224 = sha3_224Of("abc"); 406 assert(hash224 == digest!SHA3_224("abc")); 407 408 ubyte[32] hash256 = sha3_256Of("abc"); 409 assert(hash256 == digest!SHA3_256("abc")); 410 411 ubyte[48] hash384 = sha3_384Of("abc"); 412 assert(hash384 == digest!SHA3_384("abc")); 413 414 ubyte[64] hash512 = sha3_512Of("abc"); 415 assert(hash512 == digest!SHA3_512("abc")); 416 417 ubyte[16] shakeHash128 = shake128Of("abc"); 418 assert(shakeHash128 == digest!SHAKE128("abc")); 419 420 ubyte[32] shakeHash256 = shake256Of("abc"); 421 assert(shakeHash256 == digest!SHAKE256("abc")); 422 } 423 424 /// Structures 425 @system unittest 426 { 427 import std.conv : hexString; 428 429 SHA3_224 dgst_sha3_224; 430 dgst_sha3_224.put(cast(ubyte[]) "abcdef"); 431 dgst_sha3_224.start(); 432 dgst_sha3_224.put(cast(ubyte[]) ""); 433 assert(dgst_sha3_224.finish() == 434 cast(ubyte[]) hexString!"6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7"); 435 436 SHA3_256 dgst_sha3_256; 437 dgst_sha3_256.put(cast(ubyte[]) "abcdef"); 438 dgst_sha3_256.start(); 439 dgst_sha3_256.put(cast(ubyte[]) ""); 440 assert(dgst_sha3_256.finish() == 441 cast(ubyte[]) hexString!"a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"); 442 443 SHA3_384 dgst_sha3_384; 444 dgst_sha3_384.put(cast(ubyte[]) "abcdef"); 445 dgst_sha3_384.start(); 446 dgst_sha3_384.put(cast(ubyte[]) ""); 447 assert(dgst_sha3_384.finish() == 448 cast(ubyte[]) hexString!("0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2a" 449 ~"c3713831264adb47fb6bd1e058d5f004")); 450 451 SHA3_512 dgst_sha3_512; 452 dgst_sha3_512.put(cast(ubyte[]) "abcdef"); 453 dgst_sha3_512.start(); 454 dgst_sha3_512.put(cast(ubyte[]) ""); 455 assert(dgst_sha3_512.finish() == 456 cast(ubyte[]) hexString!("a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a6" 457 ~"15b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26")); 458 459 SHAKE128 dgst_shake128; 460 dgst_shake128.put(cast(ubyte[]) "abcdef"); 461 dgst_shake128.start(); 462 dgst_shake128.put(cast(ubyte[]) ""); 463 assert(dgst_shake128.finish() == cast(ubyte[]) hexString!"7f9c2ba4e88f827d616045507605853e"); 464 465 SHAKE256 dgst_shake256; 466 dgst_shake256.put(cast(ubyte[]) "abcdef"); 467 dgst_shake256.start(); 468 dgst_shake256.put(cast(ubyte[]) ""); 469 assert(dgst_shake256.finish() == 470 cast(ubyte[]) hexString!"46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762f"); 471 } 472 473 /// Of wrappers 474 @system unittest 475 { 476 import std.conv : hexString; 477 478 immutable string a = "a"; 479 480 auto digest224 = sha3_224Of(a); 481 assert(digest224 == cast(ubyte[]) hexString!"9e86ff69557ca95f405f081269685b38e3a819b309ee942f482b6a8b"); 482 auto digest256 = sha3_256Of(a); 483 assert(digest256 == cast(ubyte[]) hexString!"80084bf2fba02475726feb2cab2d8215eab14bc6bdd8bfb2c8151257032ecd8b"); 484 auto digest384 = sha3_384Of(a); 485 assert(digest384 == cast(ubyte[]) hexString!("1815f774f320491b48569efec794d" 486 ~"249eeb59aae46d22bf77dafe25c5edc28d7ea44f93ee1234aa88f61c91912a4ccd9")); 487 auto digest512 = sha3_512Of(a); 488 assert(digest512 == cast(ubyte[]) hexString!("697f2d856172cb8309d6b8b97dac4de344b549d4dee61edfb4962d8698b7fa8" 489 ~"03f4f93ff24393586e28b5b957ac3d1d369420ce53332712f997bd336d09ab02a")); 490 auto digestshake128 = shake128Of(a); 491 assert(digestshake128 == cast(ubyte[]) hexString!"85c8de88d28866bf0868090b3961162b"); 492 auto digestshake256 = shake256Of(a); 493 assert(digestshake256 == cast(ubyte[]) hexString!("867e2cb04f5a04dcbd592501a5e8fe9ceaafca50255626ca736c138042" 494 ~"530ba4")); 495 496 immutable string abc = "abc"; 497 498 digest224 = sha3_224Of(abc); 499 assert(digest224 == cast(ubyte[]) hexString!"e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf"); 500 digest256 = sha3_256Of(abc); 501 assert(digest256 == cast(ubyte[]) hexString!"3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532"); 502 digest384 = sha3_384Of(abc); 503 assert(digest384 == cast(ubyte[]) hexString!("ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b" 504 ~"298d88cea927ac7f539f1edf228376d25")); 505 digest512 = sha3_512Of(abc); 506 assert(digest512 == cast(ubyte[]) hexString!("b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712" 507 ~"e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0")); 508 digestshake128 = shake128Of(abc); 509 assert(digestshake128 == cast(ubyte[]) hexString!"5881092dd818bf5cf8a3ddb793fbcba7"); 510 digestshake256 = shake256Of(abc); 511 assert(digestshake256 == cast(ubyte[]) hexString!("483366601360a8771c6863080cc4114d8db44530f8f1e1ee4f94ea37e7" 512 ~"8b5739")); 513 514 immutable string longString = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; 515 516 digest224 = sha3_224Of(longString); 517 assert(digest224 == cast(ubyte[]) hexString!"8a24108b154ada21c9fd5574494479ba5c7e7ab76ef264ead0fcce33"); 518 digest256 = sha3_256Of(longString); 519 assert(digest256 == cast(ubyte[]) hexString!"41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376"); 520 digest384 = sha3_384Of(longString); 521 assert(digest384 == cast(ubyte[]) hexString!("991c665755eb3a4b6bbdfb75c78a492e8c56a22c5c4d7e429bfdbc32b9d4ad5" 522 ~"aa04a1f076e62fea19eef51acd0657c22")); 523 digest512 = sha3_512Of(longString); 524 assert(digest512 == cast(ubyte[]) hexString!("04a371e84ecfb5b8b77cb48610fca8182dd457ce6f326a0fd3d7ec2f1e91636" 525 ~"dee691fbe0c985302ba1b0d8dc78c086346b533b49c030d99a27daf1139d6e75e")); 526 digestshake128 = shake128Of(longString); 527 assert(digestshake128 == cast(ubyte[]) hexString!"1a96182b50fb8c7e74e0a707788f55e9"); 528 digestshake256 = shake256Of(longString); 529 assert(digestshake256 == cast(ubyte[]) hexString!("4d8c2dd2435a0128eefbb8c36f6f87133a7911e18d979ee1ae6be5d4fd" 530 ~"2e3329")); 531 532 ubyte[] onemilliona = new ubyte[1_000_000]; 533 onemilliona[] = 'a'; 534 535 digest224 = sha3_224Of(onemilliona); 536 assert(digest224 == cast(ubyte[]) hexString!"d69335b93325192e516a912e6d19a15cb51c6ed5c15243e7a7fd653c"); 537 digest256 = sha3_256Of(onemilliona); 538 assert(digest256 == cast(ubyte[]) hexString!"5c8875ae474a3634ba4fd55ec85bffd661f32aca75c6d699d0cdcb6c115891c1"); 539 digest384 = sha3_384Of(onemilliona); 540 assert(digest384 == cast(ubyte[]) hexString!("eee9e24d78c1855337983451df97c8ad9eedf256c6334f8e948d252d5e0e768" 541 ~"47aa0774ddb90a842190d2c558b4b8340")); 542 digest512 = sha3_512Of(onemilliona); 543 assert(digest512 == cast(ubyte[]) hexString!("3c3a876da14034ab60627c077bb98f7e120a2a5370212dffb3385a18d4f3885" 544 ~"9ed311d0a9d5141ce9cc5c66ee689b266a8aa18ace8282a0e0db596c90b0a7b87")); 545 digestshake128 = shake128Of(onemilliona); 546 assert(digestshake128 == cast(ubyte[]) hexString!"9d222c79c4ff9d092cf6ca86143aa411"); 547 digestshake256 = shake256Of(onemilliona); 548 assert(digestshake256 == cast(ubyte[]) hexString!("3578a7a4ca9137569cdf76ed617d31bb994fca9c1bbf8b184013de8234" 549 ~"dfd13a")); 550 } 551 552 /// An OOP API SHA-3 implementation. See `std.digest` for differences between 553 /// the templates and the OOP API. This is similar to 554 /// $(D $(REF WrapperDigest, std,digest)!SHA1Digest). 555 public alias SHA3_224Digest = WrapperDigest!SHA3_224; 556 /// Ditto 557 public alias SHA3_256Digest = WrapperDigest!SHA3_256; 558 /// Ditto 559 public alias SHA3_384Digest = WrapperDigest!SHA3_384; 560 /// Ditto 561 public alias SHA3_512Digest = WrapperDigest!SHA3_512; 562 /// Ditto 563 public alias SHAKE128Digest = WrapperDigest!SHAKE128; 564 /// Ditto 565 public alias SHAKE256Digest = WrapperDigest!SHAKE256;