1#![no_std]
2#![doc = include_str!("../README.md")]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4#![warn(missing_docs, unreachable_pub)]
5#![allow(clippy::needless_range_loop)]
6
7#[rustfmt::skip]
8mod consts;
9
10#[cfg(any(feature = "sha256", feature = "sha256_224"))]
11mod sha256;
12
13#[cfg(all(feature = "compress", any(feature = "sha256", feature = "sha256_224")))]
14#[cfg_attr(docsrs, doc(cfg(feature = "compress")))]
15pub use sha256::compress256;
16
17#[cfg(any(
18 feature = "sha512",
19 feature = "sha512_224",
20 feature = "sha512_256",
21 feature = "sha512_384"
22))]
23mod sha512;
24
25#[cfg(all(
26 feature = "compress",
27 any(
28 feature = "sha512",
29 feature = "sha512_224",
30 feature = "sha512_256",
31 feature = "sha512_384"
32 )
33))]
34#[cfg_attr(docsrs, doc(cfg(feature = "compress")))]
35pub use sha512::compress512;
36
37#[cfg(any(feature = "sha256", feature = "sha256_224"))]
42fn sha256_inner(iv: [u32; 8], data: &[u8]) -> [u8; 32] {
43 let mut state = iv;
44 let blocks: usize = data.len() >> 6;
45 let remaining: usize = data.len() & 63;
46
47 for i in 0..blocks {
49 let block: &[u8; 64] = data[i * 64..][..64].try_into().unwrap();
50 sha256::compress256(&mut state, &[*block]);
51 }
52
53 let total_bits = (data.len() as u64) << 3;
55 let mut final_block: [u8; 64] = [0u8; 64];
56 final_block[..remaining].copy_from_slice(&data[blocks * 64..]);
57 final_block[remaining] = 0x80;
58
59 if remaining >= 56 {
61 sha256::compress256(&mut state, &[final_block]);
62 final_block = [0u8; 64];
63 }
64
65 final_block[56..64].copy_from_slice(&total_bits.to_be_bytes());
67 sha256::compress256(&mut state, &[final_block]);
68
69 let mut out = [0u8; 32];
71 for i in 0..8 {
72 let bytes = state[i].to_be_bytes();
73 out[i * 4] = bytes[0];
74 out[i * 4 + 1] = bytes[1];
75 out[i * 4 + 2] = bytes[2];
76 out[i * 4 + 3] = bytes[3];
77 }
78 out
79}
80
81#[cfg(any(
82 feature = "sha512",
83 feature = "sha512_224",
84 feature = "sha512_256",
85 feature = "sha512_384"
86))]
87fn sha512_inner(iv: [u64; 8], data: &[u8]) -> [u8; 64] {
88 let mut state = iv;
89 let blocks: usize = data.len() >> 7;
90 let remaining: usize = data.len() & 127;
91
92 for i in 0..blocks {
94 let block: &[u8; 128] = data[i * 128..][..128].try_into().unwrap();
95 sha512::compress512(&mut state, &[*block]);
96 }
97
98 let total_bits = (data.len() as u128) << 3;
100 let mut final_block: [u8; 128] = [0u8; 128];
101 final_block[..remaining].copy_from_slice(&data[blocks * 128..]);
102 final_block[remaining] = 0x80;
103
104 if remaining >= 112 {
106 sha512::compress512(&mut state, &[final_block]);
107 final_block = [0u8; 128];
108 }
109
110 final_block[112..128].copy_from_slice(&total_bits.to_be_bytes());
112 sha512::compress512(&mut state, &[final_block]);
113
114 let mut out = [0u8; 64];
116 for i in 0..8 {
117 let bytes = state[i].to_be_bytes();
118 out[i * 8] = bytes[0];
119 out[i * 8 + 1] = bytes[1];
120 out[i * 8 + 2] = bytes[2];
121 out[i * 8 + 3] = bytes[3];
122 out[i * 8 + 4] = bytes[4];
123 out[i * 8 + 5] = bytes[5];
124 out[i * 8 + 6] = bytes[6];
125 out[i * 8 + 7] = bytes[7];
126 }
127 out
128}
129
130#[cfg(feature = "sha256")]
146#[cfg_attr(docsrs, doc(cfg(feature = "sha256")))]
147#[must_use]
148pub fn sha256(data: &[u8]) -> [u8; 32] {
149 sha256_inner(consts::H256_256, data)
150}
151
152#[cfg(feature = "sha256_224")]
164#[cfg_attr(docsrs, doc(cfg(feature = "sha256_224")))]
165#[must_use]
166pub fn sha224(data: &[u8]) -> [u8; 28] {
167 let out = sha256_inner(consts::H256_224, data);
168 out[..28].try_into().unwrap()
169}
170
171#[cfg(feature = "sha512")]
186#[cfg_attr(docsrs, doc(cfg(feature = "sha512")))]
187#[must_use]
188pub fn sha512(data: &[u8]) -> [u8; 64] {
189 sha512_inner(consts::H512_512, data)
190}
191
192#[cfg(feature = "sha512_224")]
204#[cfg_attr(docsrs, doc(cfg(feature = "sha512_224")))]
205#[must_use]
206pub fn sha512_224(data: &[u8]) -> [u8; 28] {
207 let out = sha512_inner(consts::H512_224, data);
208 out[..28].try_into().unwrap()
209}
210
211#[cfg(feature = "sha512_256")]
223#[cfg_attr(docsrs, doc(cfg(feature = "sha512_256")))]
224#[must_use]
225pub fn sha512_256(data: &[u8]) -> [u8; 32] {
226 let out = sha512_inner(consts::H512_256, data);
227 out[..32].try_into().unwrap()
228}
229
230#[cfg(feature = "sha512_384")]
245#[cfg_attr(docsrs, doc(cfg(feature = "sha512_384")))]
246#[must_use]
247pub fn sha384(data: &[u8]) -> [u8; 48] {
248 let out = sha512_inner(consts::H512_384, data);
249 out[..48].try_into().unwrap()
250}