Skip to main content

encryption/hash/
blake2.rs

1// Copyright (c) 2026 erik <erik@erik.xyz> — https://erik.xyz
2
3//! BLAKE2(RFC 7693):BLAKE2b-512 输出 64 字节、BLAKE2s-256 输出 32 字节。
4//!
5//! 均为无密钥(unkeyed)模式;带密钥 / 加盐的 BLAKE2 不在本库范围。
6
7use blake2::{Blake2b512, Blake2s256};
8
9use crate::hash::{NamedDigest, hasher};
10
11hasher!(
12    Blake2b512Hasher,
13    "blake2b-512",
14    "BLAKE2b-512 哈希器(无状态,可复用)。"
15);
16hasher!(
17    Blake2s256Hasher,
18    "blake2s-256",
19    "BLAKE2s-256 哈希器(无状态,可复用)。"
20);
21
22impl NamedDigest for Blake2b512Hasher {
23    type Core = Blake2b512;
24}
25
26impl NamedDigest for Blake2s256Hasher {
27    type Core = Blake2s256;
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33    use crate::contract::Hasher;
34
35    /// RFC 7693 附录 A 的 "abc" 向量:A.1 BLAKE2b-512、A.2 BLAKE2s-256。
36    #[test]
37    fn matches_rfc7693_appendix_vectors() {
38        assert_eq!(
39            Blake2b512Hasher::new().digest_hex(b"abc").unwrap(),
40            "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1\
41             7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923"
42        );
43        assert_eq!(
44            Blake2s256Hasher::new().digest_hex(b"abc").unwrap(),
45            "508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982"
46        );
47        assert_eq!(Blake2b512Hasher::new().digest(b"abc").unwrap().len(), 64);
48        assert_eq!(Blake2s256Hasher::new().digest(b"abc").unwrap().len(), 32);
49    }
50
51    /// digest_hex 输出为 2×摘要长度的小写十六进制。
52    #[test]
53    fn digest_hex_is_lowercase_hex() {
54        let hex = Blake2b512Hasher::new().digest_hex(b"abc").unwrap();
55        assert_eq!(hex.len(), 128);
56        assert!(
57            hex.bytes()
58                .all(|b| b.is_ascii_hexdigit() && !b.is_ascii_uppercase())
59        );
60
61        let hex = Blake2s256Hasher::new().digest_hex(b"abc").unwrap();
62        assert_eq!(hex.len(), 64);
63        assert!(
64            hex.bytes()
65                .all(|b| b.is_ascii_hexdigit() && !b.is_ascii_uppercase())
66        );
67    }
68
69    /// 弱检查:不同输入给出不同摘要。
70    #[test]
71    fn distinct_inputs_distinct_digests() {
72        let hasher = Blake2b512Hasher::new();
73        assert_ne!(
74            hasher.digest(b"abc").unwrap(),
75            hasher.digest(b"abd").unwrap()
76        );
77
78        let hasher = Blake2s256Hasher::new();
79        assert_ne!(
80            hasher.digest(b"abc").unwrap(),
81            hasher.digest(b"abd").unwrap()
82        );
83    }
84}