1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use {
core::fmt::{self, Display, Formatter},
crate::Keccak,
super::bits::Bits,
};
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
pub enum Hash {
Sha3_224,
Sha3_256,
Sha3_384,
Sha3_512,
Shake128,
Shake256,
}
impl Hash {
pub fn name(&self) -> &str {
match self {
Hash::Sha3_224 => "SHA3-224",
Hash::Sha3_256 => "SHA3-256",
Hash::Sha3_384 => "SHA3-384",
Hash::Sha3_512 => "SHA3-512",
Hash::Shake128 => "SHAKE128",
Hash::Shake256 => "SHAKE256",
}
}
pub fn new_keccak(&self) -> Keccak {
Keccak::new(self.clone())
}
pub (crate) const fn capacity(&self) -> usize {
match self {
Hash::Sha3_224 => 448,
Hash::Sha3_256 => 512,
Hash::Sha3_384 => 768,
Hash::Sha3_512 => 1024,
Hash::Shake128 => 256,
Hash::Shake256 => 512,
}
}
pub (crate) const fn output_bytes(&self) -> usize {
match self {
Hash::Sha3_224 => 28,
Hash::Sha3_256 => 32,
Hash::Sha3_384 => 48,
Hash::Sha3_512 => 64,
Hash::Shake128 => 16,
Hash::Shake256 => 32,
}
}
pub (crate) const fn suffix(&self) -> &[bool] {
match self {
Hash::Sha3_224 => &[false, true],
Hash::Sha3_256 => &[false, true],
Hash::Sha3_384 => &[false, true],
Hash::Sha3_512 => &[false, true],
Hash::Shake128 => &[true, true, true, true],
Hash::Shake256 => &[true, true, true, true],
}
}
pub (crate) const fn rate(&self) -> usize {
Bits::B1600.bits() - self.capacity()
}
}
impl Display for Hash {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
f.write_str(self.name())
}
}
#[test]
fn test_hashes() {
for h in &[Hash::Sha3_224, Hash::Sha3_256, Hash::Sha3_384, Hash::Sha3_512, Hash::Shake128, Hash::Shake256] {
assert!(h.capacity() < Bits::B1600.bits());
assert_eq!(h.output_bytes().checked_mul(16).unwrap(), h.capacity());
let capacity = h.capacity();
assert!(capacity > 0 && capacity % 64 == 0);
let rate = h.rate();
assert!(rate > 0 && rate % 64 == 0);
}
}