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);