Using the OOP API.
import std.conv : hexString; SHA3_224Digest sha3_224 = new SHA3_224Digest(); assert(sha3_224.finish() == cast(ubyte[]) hexString! "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7"); SHA3_256Digest sha3_256 = new SHA3_256Digest(); assert(sha3_256.finish() == cast(ubyte[]) hexString! "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"); SHA3_384Digest sha3_384 = new SHA3_384Digest(); assert(sha3_384.finish() == cast(ubyte[]) hexString!( "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2a"~ "c3713831264adb47fb6bd1e058d5f004")); SHA3_512Digest sha3_512 = new SHA3_512Digest(); assert(sha3_512.finish() == cast(ubyte[]) hexString!( "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a6"~ "15b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26")); SHAKE128Digest shake128 = new SHAKE128Digest(); assert(shake128.finish() == cast(ubyte[]) hexString!( "7f9c2ba4e88f827d616045507605853e")); SHAKE256Digest shake256 = new SHAKE256Digest(); assert(shake256.finish() == cast(ubyte[]) hexString!( "46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762f"));
Testing with HMAC
// NOTE: OpenSSL (3.0.1) seems to be incapable of producing a hash // using SHAKE and HMAC. However, this should work since // unittests for SHAKE-related hashes are passing. import std.ascii : LetterCase; import std.string : representation; import std.digest.hmac : hmac; immutable string input = "The quick brown fox jumps over the lazy dog"; auto secret = "secret".representation; assert(input .representation .hmac!SHA3_256(secret) .toHexString!(LetterCase.lower) == "93379fab68fae6d0fde0c816ea8a49fbd3c80f136c6af08bc61df5268d01b4d8"); assert(input .representation .hmac!SHA3_512(secret) .toHexString!(LetterCase.lower) == "394e52da72b28bab49174a0d22cd48eac415de750027e6485ceb945b9948d8ae"~ "e656e61e217ac1352a41c66454e2a9ae830fddbdf4f8aa6215c586b88e158ee8");
Testing out various SHAKE XOFs.
import std.conv : hexString; // Define SHAKE-128/256 alias SHAKE128_256 = KECCAK!(128, 256); alias SHAKE128_256Digest = WrapperDigest!SHAKE128_256; auto shake128_256Of(T...)(T data) { return digest!(SHAKE128_256, T)(data); } // SHAKE128("", 256) = auto shake128_256empty = hexString!( "7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef26"); // Using convenience alias assert(shake128_256Of("") == shake128_256empty); // Using OOP API Digest shake128_256 = new SHAKE128_256Digest(); assert(shake128_256.finish() == shake128_256empty); // Define SHAKE-256/512 alias SHAKE256_512 = KECCAK!(256, 512); alias SHAKE256_512Digest = WrapperDigest!SHAKE256_512; auto shake256_512Of(T...)(T data) { return digest!(SHAKE256_512, T)(data); } // SHAKE256("", 512) = auto shake256_512empty = hexString!( "46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762f"~ "d75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be"); // Convenience alias assert(shake256_512Of("") == shake256_512empty); // OOP API Digest shake256_512 = new SHAKE256_512Digest(); assert(shake256_512.finish() == shake256_512empty);
Stretching out XOFs functions to extremes.
import std.conv : hexString; // Define SHAKE-256/2048 alias SHAKE256_2048 = KECCAK!(256, 2048); auto shake256_2048Of(T...)(T data) { return digest!(SHAKE256_2048, T)(data); } // SHAKE-256/2048('abc') assert(shake256_2048Of("abc") == hexString!( "483366601360a8771c6863080cc4114d8db44530f8f1e1ee4f94ea37e78b5739"~ "d5a15bef186a5386c75744c0527e1faa9f8726e462a12a4feb06bd8801e751e4"~ "1385141204f329979fd3047a13c5657724ada64d2470157b3cdc288620944d78"~ "dbcddbd912993f0913f164fb2ce95131a2d09a3e6d51cbfc622720d7a75c6334"~ "e8a2d7ec71a7cc29cf0ea610eeff1a588290a53000faa79932becec0bd3cd0b3"~ "3a7e5d397fed1ada9442b99903f4dcfd8559ed3950faf40fe6f3b5d710ed3b67"~ "7513771af6bfe11934817e8762d9896ba579d88d84ba7aa3cdc7055f6796f195"~ "bd9ae788f2f5bb96100d6bbaff7fbc6eea24d4449a2477d172a5507dcc931412"));
OOP API SHA-3/SHAKE implementation alias.