sha2_const/lib.rs
1//! `const fn` implementation of the SHA-2 family of hash functions.
2//!
3//! This crate allows you to use the SHA-2 hash functions as constant
4//! expressions in Rust. For all other usages, the [`sha2`] crate includes more
5//! optimized implementations of these hash functions.
6//!
7//! [`sha2`]: https://crates.io/crates/sha2
8//!
9//! # Examples
10//!
11//! Compute the SHA-256 hash of the Bitcoin genesis block at compile time:
12//!
13//! ```rust
14//! # use sha2_const::Sha256;
15//! const VERSION: u32 = 1;
16//! const HASH_PREV_BLOCK: [u8; 32] = [0; 32];
17//! const HASH_MERKLE_ROOT: [u8; 32] = [
18//! 0x3b, 0xa3, 0xed, 0xfd, 0x7a, 0x7b, 0x12, 0xb2, 0x7a, 0xc7, 0x2c, 0x3e, 0x67, 0x76, 0x8f,
19//! 0x61, 0x7f, 0xc8, 0x1b, 0xc3, 0x88, 0x8a, 0x51, 0x32, 0x3a, 0x9f, 0xb8, 0xaa, 0x4b, 0x1e,
20//! 0x5e, 0x4a,
21//! ];
22//! const TIME: u32 = 1231006505;
23//! const BITS: u32 = 0x1d00ffff;
24//! const NONCE: u32 = 0x7c2bac1d;
25//!
26//! const BLOCK_HASH: [u8; 32] = Sha256::new()
27//! .update(
28//! &Sha256::new()
29//! .update(&VERSION.to_le_bytes())
30//! .update(&HASH_PREV_BLOCK)
31//! .update(&HASH_MERKLE_ROOT)
32//! .update(&TIME.to_le_bytes())
33//! .update(&BITS.to_le_bytes())
34//! .update(&NONCE.to_le_bytes())
35//! .finalize(),
36//! )
37//! .finalize();
38//!
39//! assert_eq!(
40//! hex::encode(&BLOCK_HASH[..]),
41//! "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000"
42//! );
43//! ```
44#![feature(const_mut_refs)]
45#![no_std]
46
47mod constants;
48mod sha;
49mod util;
50
51use constants::{H224, H256, H384, H512, H512_224, H512_256};
52use util::memcpy;
53
54macro_rules! sha {
55 (
56 $(#[$doc:meta])* $name:ident,
57 $size:literal,
58 $inner:ty,
59 $iv:ident
60 ) => {
61 $(#[$doc])*
62 #[derive(Clone)]
63 pub struct $name {
64 inner: $inner,
65 }
66
67 impl $name {
68 /// The internal block size of the hash function.
69 pub const BLOCK_SIZE: usize = <$inner>::BLOCK_SIZE;
70 /// The digest size of the hash function.
71 pub const DIGEST_SIZE: usize = $size;
72
73 /// Construct a new instance.
74 pub const fn new() -> Self {
75 Self {
76 inner: <$inner>::new($iv),
77 }
78 }
79
80 /// Add input data to the hash context.
81 #[must_use]
82 pub const fn update(mut self, input: &[u8]) -> Self {
83 self.inner.update(&input);
84 self
85 }
86
87 /// Finalize the context and compute the digest.
88 #[must_use]
89 pub const fn finalize(self) -> [u8; Self::DIGEST_SIZE] {
90 let digest = self.inner.finalize();
91 let mut truncated = [0; Self::DIGEST_SIZE];
92 memcpy(&mut truncated, 0, &digest, 0, Self::DIGEST_SIZE);
93 truncated
94 }
95 }
96 };
97}
98
99sha!(
100 /// The SHA-224 hash function.
101 ///
102 /// The SHA-256 algorithm with the SHA-224 initialization vector, truncated
103 /// to 224 bits.
104 ///
105 /// # Examples
106 ///
107 /// ```rust
108 /// # use sha2_const::Sha224;
109 /// const DIGEST: [u8; 28] = Sha224::new()
110 /// .update(b"The quick brown fox ")
111 /// .update(b"jumps over the lazy dog")
112 /// .finalize();
113 ///
114 /// assert_eq!(
115 /// hex::encode(&DIGEST[..]),
116 /// "730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525"
117 /// );
118 /// ```
119 Sha224,
120 28,
121 sha::Sha256,
122 H224
123);
124
125sha!(
126 /// The SHA-256 hash function.
127 ///
128 /// # Examples
129 ///
130 /// ```rust
131 /// # use sha2_const::Sha256;
132 /// const DIGEST: [u8; 32] = Sha256::new()
133 /// .update(b"The quick brown fox ")
134 /// .update(b"jumps over the lazy dog")
135 /// .finalize();
136 ///
137 /// assert_eq!(
138 /// hex::encode(&DIGEST[..]),
139 /// "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592"
140 /// );
141 /// ```
142 Sha256,
143 32,
144 sha::Sha256,
145 H256
146);
147
148sha!(
149 /// The SHA-384 hash function.
150 ///
151 /// The SHA-512 algorithm with the SHA-384 initialization vector, truncated
152 /// to 384 bits.
153 ///
154 /// # Examples
155 ///
156 /// ```rust
157 /// # use sha2_const::Sha384;
158 /// const DIGEST: [u8; 48] = Sha384::new()
159 /// .update(b"The quick brown fox ")
160 /// .update(b"jumps over the lazy dog")
161 /// .finalize();
162 ///
163 /// assert_eq!(
164 /// hex::encode(&DIGEST[..]),
165 /// concat!(
166 /// "ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c49",
167 /// "4011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1"
168 /// )
169 /// );
170 /// ```
171 Sha384,
172 48,
173 sha::Sha512,
174 H384
175);
176
177sha!(
178 /// The SHA-512 hash function.
179 ///
180 /// # Examples
181 ///
182 /// ```rust
183 /// # use sha2_const::Sha512;
184 /// const DIGEST: [u8; 64] = Sha512::new()
185 /// .update(b"The quick brown fox ")
186 /// .update(b"jumps over the lazy dog")
187 /// .finalize();
188 ///
189 /// assert_eq!(
190 /// hex::encode(&DIGEST[..]),
191 /// concat!(
192 /// "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb64",
193 /// "2e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6"
194 /// )
195 /// );
196 /// ```
197 Sha512,
198 64,
199 sha::Sha512,
200 H512
201);
202
203sha!(
204 /// The SHA-512/224 hash function.
205 ///
206 /// The SHA-512 algorithm with the SHA-512/224 initialization vector,
207 /// truncated to 224 bits.
208 ///
209 /// # Examples
210 ///
211 /// ```rust
212 /// # use sha2_const::Sha512_224;
213 /// const DIGEST: [u8; 28] = Sha512_224::new()
214 /// .update(b"The quick brown fox ")
215 /// .update(b"jumps over the lazy dog")
216 /// .finalize();
217 ///
218 /// assert_eq!(
219 /// hex::encode(&DIGEST[..]),
220 /// "944cd2847fb54558d4775db0485a50003111c8e5daa63fe722c6aa37"
221 /// );
222 /// ```
223 Sha512_224,
224 28,
225 sha::Sha512,
226 H512_224
227);
228
229sha!(
230 /// The SHA-512/256 hash function.
231 ///
232 /// The SHA-512 algorithm with the SHA-512/256 initialization vector,
233 /// truncated to 256 bits.
234 ///
235 /// # Examples
236 ///
237 /// ```rust
238 /// # use sha2_const::Sha512_256;
239 /// const DIGEST: [u8; 32] = Sha512_256::new()
240 /// .update(b"The quick brown fox ")
241 /// .update(b"jumps over the lazy dog")
242 /// .finalize();
243 ///
244 /// assert_eq!(
245 /// hex::encode(&DIGEST[..]),
246 /// "dd9d67b371519c339ed8dbd25af90e976a1eeefd4ad3d889005e532fc5bef04d"
247 /// );
248 /// ```
249 Sha512_256,
250 32,
251 sha::Sha512,
252 H512_256
253);