sha2_const_stable/
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_stable::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#![no_std]
45
46mod constants;
47mod sha;
48mod util;
49
50use constants::{H224, H256, H384, H512, H512_224, H512_256};
51use util::memcpy;
52
53macro_rules! sha {
54    (
55        $(#[$doc:meta])* $name:ident,
56        $size:literal,
57        $inner:ty,
58        $iv:ident
59    ) => {
60        $(#[$doc])*
61        #[derive(Clone)]
62        pub struct $name {
63            inner: $inner,
64        }
65
66        impl $name {
67            /// The internal block size of the hash function.
68            pub const BLOCK_SIZE: usize = <$inner>::BLOCK_SIZE;
69            /// The digest size of the hash function.
70            pub const DIGEST_SIZE: usize = $size;
71
72            /// Construct a new instance.
73            pub const fn new() -> Self {
74                Self {
75                    inner: <$inner>::new($iv),
76                }
77            }
78
79            /// Add input data to the hash context.
80            #[must_use]
81            pub const fn update(mut self, input: &[u8]) -> Self {
82                self.inner = self.inner.update(&input);
83                self
84            }
85
86            /// Finalize the context and compute the digest.
87            #[must_use]
88            pub const fn finalize(self) -> [u8; Self::DIGEST_SIZE] {
89                let digest = self.inner.finalize();
90                let mut truncated = [0; Self::DIGEST_SIZE];
91                truncated = memcpy(truncated, 0, &digest, 0, Self::DIGEST_SIZE);
92                truncated
93            }
94        }
95    };
96}
97
98sha!(
99    /// The SHA-224 hash function.
100    ///
101    /// The SHA-256 algorithm with the SHA-224 initialization vector, truncated
102    /// to 224 bits.
103    ///
104    /// # Examples
105    ///
106    /// ```rust
107    /// # use sha2_const_stable::Sha224;
108    /// const DIGEST: [u8; 28] = Sha224::new()
109    ///     .update(b"The quick brown fox ")
110    ///     .update(b"jumps over the lazy dog")
111    ///     .finalize();
112    ///
113    /// assert_eq!(
114    ///     hex::encode(&DIGEST[..]),
115    ///     "730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525"
116    /// );
117    /// ```
118    Sha224,
119    28,
120    sha::Sha256,
121    H224
122);
123
124sha!(
125    /// The SHA-256 hash function.
126    ///
127    /// # Examples
128    ///
129    /// ```rust
130    /// # use sha2_const_stable::Sha256;
131    /// const DIGEST: [u8; 32] = Sha256::new()
132    ///     .update(b"The quick brown fox ")
133    ///     .update(b"jumps over the lazy dog")
134    ///     .finalize();
135    ///
136    /// assert_eq!(
137    ///     hex::encode(&DIGEST[..]),
138    ///     "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592"
139    /// );
140    /// ```
141    Sha256,
142    32,
143    sha::Sha256,
144    H256
145);
146
147sha!(
148    /// The SHA-384 hash function.
149    ///
150    /// The SHA-512 algorithm with the SHA-384 initialization vector, truncated
151    /// to 384 bits.
152    ///
153    /// # Examples
154    ///
155    /// ```rust
156    /// # use sha2_const_stable::Sha384;
157    /// const DIGEST: [u8; 48] = Sha384::new()
158    ///     .update(b"The quick brown fox ")
159    ///     .update(b"jumps over the lazy dog")
160    ///     .finalize();
161    ///
162    /// assert_eq!(
163    ///     hex::encode(&DIGEST[..]),
164    ///     concat!(
165    ///         "ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c49",
166    ///         "4011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1"
167    ///     )
168    /// );
169    /// ```
170    Sha384,
171    48,
172    sha::Sha512,
173    H384
174);
175
176sha!(
177    /// The SHA-512 hash function.
178    ///
179    /// # Examples
180    ///
181    /// ```rust
182    /// # use sha2_const_stable::Sha512;
183    /// const DIGEST: [u8; 64] = Sha512::new()
184    ///     .update(b"The quick brown fox ")
185    ///     .update(b"jumps over the lazy dog")
186    ///     .finalize();
187    ///
188    /// assert_eq!(
189    ///     hex::encode(&DIGEST[..]),
190    ///     concat!(
191    ///         "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb64",
192    ///         "2e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6"
193    ///     )
194    /// );
195    /// ```
196    Sha512,
197    64,
198    sha::Sha512,
199    H512
200);
201
202sha!(
203    /// The SHA-512/224 hash function.
204    ///
205    /// The SHA-512 algorithm with the SHA-512/224 initialization vector,
206    /// truncated to 224 bits.
207    ///
208    /// # Examples
209    ///
210    /// ```rust
211    /// # use sha2_const_stable::Sha512_224;
212    /// const DIGEST: [u8; 28] = Sha512_224::new()
213    ///     .update(b"The quick brown fox ")
214    ///     .update(b"jumps over the lazy dog")
215    ///     .finalize();
216    ///
217    /// assert_eq!(
218    ///     hex::encode(&DIGEST[..]),
219    ///     "944cd2847fb54558d4775db0485a50003111c8e5daa63fe722c6aa37"
220    /// );
221    /// ```
222    Sha512_224,
223    28,
224    sha::Sha512,
225    H512_224
226);
227
228sha!(
229    /// The SHA-512/256 hash function.
230    ///
231    /// The SHA-512 algorithm with the SHA-512/256 initialization vector,
232    /// truncated to 256 bits.
233    ///
234    /// # Examples
235    ///
236    /// ```rust
237    /// # use sha2_const_stable::Sha512_256;
238    /// const DIGEST: [u8; 32] = Sha512_256::new()
239    ///     .update(b"The quick brown fox ")
240    ///     .update(b"jumps over the lazy dog")
241    ///     .finalize();
242    ///
243    /// assert_eq!(
244    ///     hex::encode(&DIGEST[..]),
245    ///     "dd9d67b371519c339ed8dbd25af90e976a1eeefd4ad3d889005e532fc5bef04d"
246    /// );
247    /// ```
248    Sha512_256,
249    32,
250    sha::Sha512,
251    H512_256
252);