Skip to main content

encryption/hash/
sha3.rs

1// Copyright (c) 2026 erik <erik@erik.xyz> — https://erik.xyz
2
3//! SHA-3(FIPS 202):SHA3-256 输出 32 字节、SHA3-512 输出 64 字节。
4//!
5//! 是 FIPS 202 标准化的 SHA-3(域分隔符 0x06),不是 Keccak 提交版
6//! (0x01 填充,SHAKE 的前身)——两者对同一输入给出不同摘要。
7
8use sha3::{Sha3_256, Sha3_512};
9
10use crate::hash::{NamedDigest, hasher};
11
12hasher!(
13    Sha3_256Hasher,
14    "sha3-256",
15    "SHA3-256 哈希器(无状态,可复用)。"
16);
17hasher!(
18    Sha3_512Hasher,
19    "sha3-512",
20    "SHA3-512 哈希器(无状态,可复用)。"
21);
22
23impl NamedDigest for Sha3_256Hasher {
24    type Core = Sha3_256;
25}
26
27impl NamedDigest for Sha3_512Hasher {
28    type Core = Sha3_512;
29}
30
31#[cfg(test)]
32mod tests {
33    use super::*;
34    use crate::contract::Hasher;
35
36    /// FIPS 202 发布时给出的 "abc" 示例摘要(NIST SHA-3 标准示例值)。
37    #[test]
38    fn matches_nist_example_vectors() {
39        assert_eq!(
40            Sha3_256Hasher::new().digest_hex(b"abc").unwrap(),
41            "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532"
42        );
43        assert_eq!(
44            Sha3_512Hasher::new().digest_hex(b"abc").unwrap(),
45            "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e\
46             10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0"
47        );
48        assert_eq!(Sha3_256Hasher::new().digest(b"abc").unwrap().len(), 32);
49        assert_eq!(Sha3_512Hasher::new().digest(b"abc").unwrap().len(), 64);
50    }
51
52    /// digest_hex 输出为 2×摘要长度的小写十六进制。
53    #[test]
54    fn digest_hex_is_lowercase_hex() {
55        let hex = Sha3_256Hasher::new().digest_hex(b"abc").unwrap();
56        assert_eq!(hex.len(), 64);
57        assert!(
58            hex.bytes()
59                .all(|b| b.is_ascii_hexdigit() && !b.is_ascii_uppercase())
60        );
61
62        let hex = Sha3_512Hasher::new().digest_hex(b"abc").unwrap();
63        assert_eq!(hex.len(), 128);
64        assert!(
65            hex.bytes()
66                .all(|b| b.is_ascii_hexdigit() && !b.is_ascii_uppercase())
67        );
68    }
69
70    /// 弱检查:不同输入给出不同摘要。
71    #[test]
72    fn distinct_inputs_distinct_digests() {
73        let hasher = Sha3_256Hasher::new();
74        assert_ne!(
75            hasher.digest(b"abc").unwrap(),
76            hasher.digest(b"abd").unwrap()
77        );
78
79        let hasher = Sha3_512Hasher::new();
80        assert_ne!(
81            hasher.digest(b"abc").unwrap(),
82            hasher.digest(b"abd").unwrap()
83        );
84    }
85}