1 module blake3; 2 3 version (Have_dynamic) { 4 import blake3.binding; 5 import dynamic; 6 7 __gshared mixin dynamicBinding!(blake3.binding) libblake3; 8 9 shared static this() { 10 version (Windows) 11 libblake3.loadBinding("libblake3"); 12 else 13 libblake3.loadBinding("libblake3.so"); 14 } 15 } else 16 import blake3.binding; 17 18 @safe: 19 20 alias Hasher = blake3_hasher; 21 22 /// The hash value of empty input. 23 enum ubyte[32] emptyHash = cast(const(ubyte)[])x"af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262"; 24 25 /// A BLAKE3 hasher. 26 auto BLAKE3() @trusted { 27 Hasher hasher = void; 28 blake3_hasher_init(&hasher); 29 return hasher; 30 } 31 32 /// A BLAKE3 hasher with a key. 33 auto BLAKE3(in ubyte[BLAKE3_KEY_LEN] key) @trusted { 34 Hasher hasher = void; 35 blake3_hasher_init_keyed(&hasher, key); 36 return hasher; 37 } 38 39 /// A BLAKE3 hasher with a derived key. 40 auto BLAKE3(const char* context) @trusted { 41 Hasher hasher = void; 42 blake3_hasher_init_derive_key(&hasher, context); 43 return hasher; 44 } 45 46 /// A BLAKE3 hasher with a raw derived key. 47 auto BLAKE3(const(void)* context, size_t contextLen) @trusted { 48 Hasher hasher = void; 49 blake3_hasher_init_derive_key_raw(&hasher, context, contextLen); 50 return hasher; 51 } 52 53 /// Update the hasher with data. 54 void put(ref Hasher hasher, in void[] data) @trusted pure nothrow @nogc { 55 blake3_hasher_update(&hasher, data.ptr, data.length); 56 } 57 58 /// Finalize the hasher and return the hash value. 59 ubyte[L] finish(size_t L = BLAKE3_OUT_LEN)(const ref Hasher hasher) @trusted 60 if (L > 0 && L < 4096) { 61 ubyte[L] output = void; 62 blake3_hasher_finalize(&hasher, output.ptr, L); 63 return output; 64 } 65 66 /// ditto 67 ubyte[L] finish(size_t L = BLAKE3_OUT_LEN)(const ref Hasher hasher, ulong seek) @trusted 68 if (L > 0 && L < 4096) { 69 ubyte[L] output = void; 70 blake3_hasher_finalize_seek(&hasher, seek, output.ptr, L); 71 return output; 72 } 73 74 /// ditto 75 void finish(const ref Hasher hasher, ubyte[] output) @trusted { 76 blake3_hasher_finalize(&hasher, output.ptr, output.length); 77 } 78 79 /// ditto 80 void finish(const ref Hasher hasher, ubyte[] output, ulong seek) @trusted { 81 blake3_hasher_finalize_seek(&hasher, seek, output.ptr, output.length); 82 } 83 84 /// Reset the hasher to its initial state. 85 void reset(ref Hasher hasher) @trusted pure nothrow @nogc { 86 blake3_hasher_reset(&hasher); 87 } 88 89 /// Compute the BLAKE3 hash value of data. 90 ubyte[L] blake3Of(size_t L = BLAKE3_OUT_LEN)(in void[] data) 91 if (L > 0 && L < 4096) { 92 auto hasher = BLAKE3(); 93 hasher.put(data); 94 return hasher.finish!L(); 95 } 96 97 /// 98 unittest { 99 assert(blake3Of([]) == emptyHash); 100 assert(blake3Of("Hello world!") == x"793c10bc0b28c378330d39edace7260af9da81d603b8ffede2706a21eda893f4"); 101 } 102 103 ubyte[L] blake3Of(size_t L = 32)(in void[] data, in ubyte[32] key) { 104 auto hasher = BLAKE3(key); 105 hasher.put(data); 106 return hasher.finish!L(); 107 }