BLAKE3 是一种密码学哈希函数,其特点如下:
下图 是 2019 年 Cascade Lake-SP 8275CL 服务器 CPU 上对 16 KiB 输入进行基准测试的示例。详细的基准测试结果请参阅 BLAKE3 论文。
BLAKE3 基于成熟哈希函数 BLAKE2 的优化实例以及 原始 Bao 树模式。其规范和设计原理详见 BLAKE3 论文。默认输出大小为 256 位。当前版本的 Bao 实现了基于 BLAKE3 的验证流式处理。
此仓库是 BLAKE3 的官方实现,包含:
blake3 Rust crate,包含针对 SSE2、SSE4.1、AVX2、AVX-512、NEON 和 WASM 的优化实现,并在 x86 上实现了自动运行时 CPU 特性检测。rayon 特性提供了多线程支持。
b3sum Rust crate,提供命令行界面。默认使用多线程,在典型桌面硬件上比例如 sha256sum 快一个数量级。
C 实现,与 Rust 实现一样包含 SIMD 优化(除 WASM 外)、x86 上的 CPU 特性检测以及可选的多线程支持。详见 c/README.md。
Rust 参考实现,在 BLAKE3 论文 第 5.1 节中讨论。该实现比上述优化实现更小、更简单。如果你想了解 BLAKE3 的工作原理,或者正在编写不需要多线程或 SIMD 优化的移植版本,建议从这里开始。参考实现的其他语言移植版本托管在独立的仓库中(C、Python)。
一组测试向量,涵盖扩展输出、所有三种模式以及各种输入长度。
BLAKE3 由以下人员设计:
BLAKE3 的开发由 Electric Coin Company 赞助。
BLAKE3 也已在社区密码学规范项目(C2SP)中进行规范。
注意:BLAKE3 不是密码哈希算法,因为它设计为快速,而密码哈希不应快速。如果你对密码进行哈希存储或从密码派生密钥,建议使用 Argon2。
b3sum 工具b3sum 命令行工具用于打印文件或标准输入的 BLAKE3 哈希值。预构建的二进制文件适用于 Linux、Windows 和 macOS(需要解决未识别开发者问题),可在发布页面获取。如果你已安装 Rust 和 Cargo,也可以通过以下命令自行构建 b3sum:
cargo install b3sum
如果 rustup 没有为你配置 PATH,你可能需要手动查找安装的二进制文件,例如在 ~/.cargo/bin 目录下。你可以通过创建一个大文件并计算其哈希值来测试 BLAKE3 在你的机器上的速度,例如:
# 创建一个 1 GB 的文件。
head -c 1000000000 /dev/zero > /tmp/bigfile
# 使用 SHA-256 计算哈希。
time openssl sha256 /tmp/bigfile
# 使用 BLAKE3 计算哈希。
time b3sum /tmp/bigfile
blake3 crate 要在 Rust 代码中使用 BLAKE3,请将 blake3 crate 添加为依赖项到你的 Cargo.toml。以下是一个对输入字节进行哈希的示例:
// 一次性哈希输入。
let hash1 = blake3::hash(b"foobarbaz");
// 增量式哈希输入。
let mut hasher = blake3::Hasher::new();
hasher.update(b"foo");
hasher.update(b"bar");
hasher.update(b"baz");
let hash2 = hasher.finalize();
assert_eq!(hash1, hash2);
// 扩展输出。OutputReader 也实现了 Read 和 Seek。
let mut output = [0; 1000];
let mut output_reader = hasher.finalize_xof();
output_reader.fill(&mut output);
assert_eq!(hash1, output[..32]);
// 将哈希值以十六进制格式打印。
println!("{}", hash1);
除了 hash,BLAKE3 还提供另外两种模式:keyed_hash 和 derive_key。keyed_hash 模式接受一个 256 位的密钥:
// 一次性进行 MAC 计算。
let example_key = [42u8; 32];
let mac1 = blake3::keyed_hash(&example_key, b"example input");
// 增量式 MAC 计算。
let mut hasher = blake3::Hasher::new_keyed(&example_key);
hasher.update(b"example input");
let mac2 = hasher.finalize();
assert_eq!(mac1, mac2);
derive_key 模式接受一个上下文字符串和密钥材料(不是密码)。上下文字符串应为硬编码、全局唯一且与应用相关的。推荐的上下文字符串格式为 "[application] [commit timestamp] [purpose]":
// 为不同目的派生多个子密钥。
const EMAIL_CONTEXT: &str = "BLAKE3 example 2020-01-07 17:10:44 email key";
const API_CONTEXT: &str = "BLAKE3 example 2020-01-07 17:11:21 API key";
let input_key_material = b"usually at least 32 random bytes, not a password";
let email_key = blake3::derive_key(EMAIL_CONTEXT, input_key_material);
let api_key = blake3::derive_key(API_CONTEXT, input_key_material);
assert_ne!(email_key, api_key);
详见 c/README.md。
现有的实现数量众多,我们难以全部跟踪,但一些亮点包括:优化的 Go 实现、用于 Node.js 和浏览器的 Wasm 绑定、Python 的二进制 wheel、.NET 绑定 以及 纯 Java 实现。
请参阅 CONTRIBUTING.md。
本项目以 CC0 1.0 发布到公共领域。或者,你也可以选择以下任意许可证: