Home

Awesome

Blake3<font color="A80016">.NET</span> Build Status Build Status NuGet

<img align="right" width="160px" height="160px" src="img/logo.png">

Blake3.NET is a fast managed wrapper around the SIMD Rust implementations of the BLAKE3 cryptographic hash function.

The current native version of BLAKE3 used by Blake3.NET is 1.4.1

Features

Usage

Hash a buffer directly:

var hash = Blake3.Hasher.Hash(Encoding.UTF8.GetBytes("BLAKE3"));
Console.WriteLine(hash);
// Prints f890484173e516bfd935ef3d22b912dc9738de38743993cfedf2c9473b3216a4

Or use the Hasher struct for incremental updates:

// Hasher is a disposable struct!
using var hasher = Blake3.Hasher.New();
hasher.Update(Encoding.UTF8.GetBytes("BLAKE3"));
var hash = hasher.Finalize();

Or seek in the output "stream" to any position:

using var hasher = Blake3.Hasher.New();
hasher.Update(Encoding.UTF8.GetBytes("BLAKE3"));
var hashAtPosition = new byte[1024];
var hash = hasher.Finalize(4242, hashAtPosition);

Or hash a stream on the go with Blake3Stream:

using var blake3Stream = new Blake3Stream(new MemoryStream());
blake3Stream.Write(Encoding.UTF8.GetBytes("BLAKE3"));
var hash = blake3Stream.ComputeHash();

Or produce a message authentication code using a 256-bit key:

using var blake3 = Hasher.NewKeyed(macKey);
blake3.UpdateWithJoin(message);
var tag = blake3.Finalize();
byte[] authenticationTag = tag.AsSpan().ToArray();

Or derive a subkey from a master key:

const string context = "[application] [commit timestamp] [purpose]";
using var blake3 = Hasher.NewDeriveKey(Encoding.UTF8.GetBytes(context));
blake3.Update(inputKeyingMaterial);
var derivedKey = blake3.Finalize();
byte[] subkey = derivedKey.AsSpan().ToArray();

Platforms

Blake3.NET is supported on the following platforms:

Benchmarks

The benchmarks are running with BenchmarkDotNet .NET 5.0 and done on multiple different sizes compared with the following implementations:

For the 1,000,000 bytes test, Blake3 is using the multi-threading version provided by Blake3 (Hasher.UpdateWithJoin method).

Results

Results

The CPU before Intel Ice Lake or AMD Zen don't have the Intel SHA CPU extensions.

In that case, Blake3 is around 5x to 10x times faster than the built-in SHA256.

The following benchmark was ran on an Intel Core i7-4980HQ CPU 2.80GHz (Haswell):

Benchmarks


BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.1139 (1909/November2018Update/19H2)
Intel Core i7-4980HQ CPU 2.80GHz (Haswell), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=5.0.100
  [Host]     : .NET Core 5.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT
  DefaultJob : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT

MethodNMeanErrorStdDevMedian
Blake3485.06 ns1.704 ns2.154 ns83.55 ns
Blake2Fast4138.30 ns0.755 ns0.670 ns138.36 ns
SHA2564531.82 ns0.842 ns0.788 ns531.85 ns
Blake3100145.12 ns2.899 ns4.064 ns142.56 ns
Blake2Fast100153.41 ns3.057 ns4.760 ns150.66 ns
SHA256100803.32 ns11.420 ns8.916 ns797.37 ns
Blake31000999.01 ns19.658 ns26.908 ns984.60 ns
Blake2Fast1000789.41 ns15.814 ns18.825 ns784.82 ns
SHA25610004,489.81 ns84.032 ns78.603 ns4,525.27 ns
Blake3100004,099.92 ns49.985 ns46.756 ns4,121.94 ns
Blake2Fast100007,593.55 ns127.193 ns112.753 ns7,609.07 ns
SHA2561000040,799.82 ns769.102 ns1,386.850 ns41,460.32 ns
Blake310000028,491.58 ns394.692 ns369.195 ns28,498.05 ns
Blake2Fast10000078,732.84 ns648.124 ns606.255 ns78,887.56 ns
SHA256100000408,581.45 ns2,359.416 ns2,207.000 ns409,059.91 ns
Blake31000000138,481.22 ns1,300.797 ns1,216.767 ns138,460.16 ns
Blake2Fast1000000724,092.30 ns6,995.547 ns6,543.639 ns720,115.33 ns
SHA25610000003,699,812.03 ns37,739.460 ns35,301.514 ns3,678,276.17 ns

Results with SHA CPU extensions

If your CPU has Intel SHA CPU extensions, then Blake3 is on average ~2x times faster than SHA256.

The following benchmarks was ran on a AMD Ryzen 9 3900X:

Benchmarks


BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19041.630 (2004/?/20H1)
AMD Ryzen 9 3900X, 1 CPU, 24 logical and 12 physical cores
.NET Core SDK=5.0.100
  [Host]     : .NET Core 5.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT
  DefaultJob : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT


MethodNMeanErrorStdDev
Blake3477.86 ns0.332 ns0.310 ns
Blake2Fast4123.57 ns0.939 ns0.879 ns
SHA2564244.31 ns1.157 ns1.082 ns
Blake3100125.60 ns0.497 ns0.440 ns
Blake2Fast100124.48 ns1.053 ns0.985 ns
SHA256100279.82 ns1.853 ns1.734 ns
Blake31000888.90 ns0.873 ns0.681 ns
Blake2Fast1000790.85 ns4.364 ns3.645 ns
SHA2561000700.81 ns2.078 ns1.842 ns
Blake3100003,508.37 ns23.411 ns21.899 ns
Blake2Fast100007,569.91 ns40.661 ns38.034 ns
SHA256100004,922.90 ns14.360 ns13.432 ns
Blake310000022,109.48 ns47.699 ns39.830 ns
Blake2Fast10000075,937.97 ns223.972 ns209.503 ns
SHA25610000048,655.78 ns102.273 ns95.666 ns
Blake31000000117,936.94 ns263.454 ns246.435 ns
Blake2Fast1000000768,752.03 ns1,836.783 ns1,718.128 ns
SHA2561000000485,944.26 ns1,326.657 ns1,240.956 ns

How to Build?

You need to install the .NET 7 SDK or latest Visual Studio 2022. Then from the root folder:

$ dotnet build src -c Release

In order to rebuild the native binaries, you need to run the build scripts from lib/blake3_dotnet

License

This software is released under the BSD-Clause 2 license.

Author

Alexandre Mutel aka xoofx.