Of course they correspond to the digest API!
assert(isDigest!BLAKE2b512); assert(isDigest!BLAKE2s256);
Of course they have a blockSize!
assert(hasBlockSize!BLAKE2b512); assert(hasBlockSize!BLAKE2s256);
Testing "Of" wrappers against digest wrappers.
enum TEXT = "abc"; assert(blake2b_Of(TEXT) == digest!BLAKE2b512(TEXT)); assert(blake2s_Of(TEXT) == digest!BLAKE2s256(TEXT));
Testing template API
import std.conv : hexString; ubyte[] s = [ 'a', 'b', 'c' ]; BLAKE2s256 b2s; b2s.put(s); assert(b2s.finish() == cast(ubyte[])hexString!( "508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982"));
Test against empty input
assert(toHexString!(LetterCase.lower)(blake2b_Of("")) == "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419"~ "d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce"); assert(toHexString!(LetterCase.lower)(blake2s_Of("")) == "69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9");
Test against "abc"
assert(toHexString!(LetterCase.lower)(blake2b_Of("abc")) == "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1"~ "7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923"); assert(toHexString!(LetterCase.lower)(blake2s_Of("abc")) == "508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982");
Testing template API against one million 'a'
import std.conv : hexString; ubyte[] onemilliona = new ubyte[1_000_000]; onemilliona[] = 'a'; BLAKE2b512 b2b; b2b.put(onemilliona); assert(b2b.finish() == cast(ubyte[]) hexString!( "98fb3efb7206fd19ebf69b6f312cf7b64e3b94dbe1a17107913975a793f177e1"~ "d077609d7fba363cbba00d05f7aa4e4fa8715d6428104c0a75643b0ff3fd3eaf")); BLAKE2s256 b2s; b2s.put(onemilliona); assert(b2s.finish() == cast(ubyte[]) hexString!( "bec0c0e6cde5b67acb73b81f79a67a4079ae1c60dac9d2661af18e9f8b50dfa5"));
Testing OOP API
import std.conv : hexString; ubyte[] s = ['a', 'b', 'c']; Digest b2b = new BLAKE2b512Digest(); b2b.put(s); assert(b2b.finish() == cast(ubyte[]) hexString!( "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1"~ "7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923")); Digest b2s = new BLAKE2s256Digest(); b2s.put(s); assert(b2s.finish() == cast(ubyte[]) hexString!( "508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982"));
BLAKE2s Template usage
import std.conv : hexString; // Let's use the template features: // NOTE: When passing a digest to a function, it must be passed by reference! void doSomething(T)(ref T hash) if (isDigest!T) { hash.put([ 'a', 'b', 'c' ]); } BLAKE2b512 b2b; b2b.start(); doSomething(b2b); assert(b2b.finish() == cast(ubyte[]) hexString!( "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1"~ "7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923")); BLAKE2s256 b2s; b2s.start(); doSomething(b2s); assert(b2s.finish() == cast(ubyte[]) hexString!( "508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982"));
Keying digests
// NOTE: BLAKE2 is a keyed hash and therefore not compatible with // the hmac/HMAC templates, or OpenSSL does it differently. import std.ascii : LetterCase; import std.string : representation; import std.conv : hexString; auto secret2b = hexString!( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"~ "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f") .representation; auto secret2s = hexString!( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") .representation; auto data = hexString!("000102").representation; BLAKE2b512 b2b; b2b.key(secret2b); b2b.put(data); assert(b2b.finish().toHexString!(LetterCase.lower) == "33d0825dddf7ada99b0e7e307104ad07ca9cfd9692214f1561356315e784f3e5"~ "a17e364ae9dbb14cb2036df932b77f4b292761365fb328de7afdc6d8998f5fc1" , "BLAKE2b+secret failed"); BLAKE2s256 b2s; b2s.key(secret2s); b2s.put(data); assert(b2s.finish().toHexString!(LetterCase.lower) == "1d220dbe2ee134661fdf6d9e74b41704710556f2f6e5a091b227697445dbea6b" , "BLAKE2s+secret failed");
OOP API BLAKE2 implementation aliases.