Skip to main content

encryption/hash/
blake3.rs

1// Copyright (c) 2026 erik <erik@erik.xyz> — https://erik.xyz
2
3//! BLAKE3 哈希;默认输出 32 字节。
4//!
5//! BLAKE3 支持任意长度扩展输出(XOF),但 [`Hasher`] 契约返回固定长度摘要,
6//! 本库统一走官方默认的 32 字节(即扩展输出流的前 32 字节),不提供可变长度
7//! 接口。blake3 crate 为独立实现,不依赖 RustCrypto digest trait 代际。
8
9use crate::contract::Hasher;
10use crate::error::Result;
11use crate::hash::hasher;
12
13hasher!(Blake3Hasher, "blake3", "BLAKE3 哈希器(无状态,可复用)。");
14
15impl Hasher for Blake3Hasher {
16    fn digest(&self, data: &[u8]) -> Result<Vec<u8>> {
17        Ok(blake3::hash(data).as_bytes().to_vec())
18    }
19}
20
21#[cfg(test)]
22mod tests {
23    use super::*;
24
25    /// 官方仓库 BLAKE3-team/BLAKE3 的 test_vectors/test_vectors.json 条目:
26    /// input_len 0(空输入)与 input_len 1(单字节 0x00)。官方文件给出 131 字节
27    /// 扩展输出,本库取默认 32 字节 = 其前 32 字节(两个文件字段的前 64 个十六
28    /// 进制字符)。
29    #[test]
30    fn matches_official_test_vectors() {
31        let hasher = Blake3Hasher::new();
32        assert_eq!(
33            hasher.digest_hex(b"").unwrap(),
34            "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262"
35        );
36        assert_eq!(
37            hasher.digest_hex(&[0x00]).unwrap(),
38            "2d3adedff11b61f14c886e35afa036736dcd87a74d27b5c1510225d0f592e213"
39        );
40        assert_eq!(hasher.digest(b"").unwrap().len(), 32);
41    }
42
43    /// digest_hex 输出为 2×摘要长度的小写十六进制。
44    #[test]
45    fn digest_hex_is_lowercase_hex() {
46        let hex = Blake3Hasher::new().digest_hex(b"abc").unwrap();
47        assert_eq!(hex.len(), 64);
48        assert!(
49            hex.bytes()
50                .all(|b| b.is_ascii_hexdigit() && !b.is_ascii_uppercase())
51        );
52    }
53
54    /// 弱检查:不同输入给出不同摘要。
55    #[test]
56    fn distinct_inputs_distinct_digests() {
57        let hasher = Blake3Hasher::new();
58        assert_ne!(
59            hasher.digest(b"abc").unwrap(),
60            hasher.digest(b"abd").unwrap()
61        );
62    }
63}