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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
//! SHA-384 hash function implementation.
//!
//! This module provides the SHA-384 algorithm as defined in FIPS 180-4. SHA-384
//! is structurally identical to SHA-512 but produces a 384-bit (48-byte) digest
//! instead of 512 bits, and uses a different initial vector (IV). The algorithm
//! operates on 1024-bit message blocks and uses the same 64-bit word operations
//! as SHA-512.
//!
//! # Availability
//!
//! This module is only compiled when the `sha384` feature is enabled. It is part
//! of the default feature set.
//!
//! # Design Rationale
//!
//! SHA-384 is implemented as a thin wrapper around the core SHA-512
//! [`crate::sha512::Hash`] and [`crate::sha512::State`] types. This reuse avoids
//! code duplication because the message schedule, compression function, and
//! block processing are identical. The differences are:
//!
//! - A distinct initial vector (`new_state()`) replaces the SHA-512 IV.
//! - The final digest is truncated to the first 48 bytes of the 64-byte SHA-512
//! output.
//!
//! This approach follows the official specification and guarantees that SHA-384
//! results are exactly the leftmost 384 bits of the SHA-512 hash computed with
//! the SHA-384 IV.
//!
//! The module also instantiates HMAC-SHA-384 and HKDF-SHA-384 via the crate’s
//! [`impl_hmac!`] and [`impl_hkdf!`] macros, providing ready-to-use keyed-hash
//! and key-derivation functions with 48-byte output and 128-byte block size.
//!
//! # Examples
//!
//! Computing a SHA-384 hash in one shot:
//!
//! ```
//! # use libvctrl_sha512::sha384::Hash;
//! let digest = Hash::hash(b"hello world");
//! assert_eq!(digest.len(), 48);
//! ```
//!
//! Verifying against a known test vector:
//!
//! ```
//! # use libvctrl_sha512::sha384::Hash;
//! let digest = Hash::hash(b"abc");
//! let expected: [u8; 48] = [
//! 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
//! 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
//! 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
//! 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,
//! 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23,
//! 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7,
//! ];
//! assert_eq!(digest, expected);
//! ```
use crate;
use crateload_be;
/// Constructs the SHA-384 initial state vector as defined in FIPS 180-4.
///
/// This function builds the 8×64-bit IV by loading the constant big-endian bytes
/// specified for SHA-384. The values are the first 64 bits of the fractional
/// parts of the square roots of the 9th through 16th primes, which differ from
/// those used for SHA-512.
///
/// The resulting [`State`] is then used to initialise the inner [`Sha512Hash`]
/// when a new SHA-384 hasher is created.
///
/// # Rationale
///
/// Using a distinct IV is what makes SHA-384 a separate function from SHA-512
/// while sharing the same compression logic. This design ensures the two
/// algorithms produce unrelated outputs even for identical inputs.
/// SHA-384 hasher.
///
/// Wraps the full SHA-512 hasher ([`Sha512Hash`]) but initialises it with the
/// SHA-384 IV and truncates the final digest to 48 bytes. All update operations
/// are delegated to the inner hasher, so the performance characteristics are
/// identical to SHA-512.
///
/// # Examples
///
/// Incremental hashing:
///
/// ```
/// # use libvctrl_sha512::sha384::Hash;
/// let mut h = Hash::new();
/// h.update(b"hello ");
/// h.update(b"world");
/// let result = h.finalize();
/// assert_eq!(result.len(), 48);
/// ```
///
/// One-shot hashing with a known answer:
///
/// ```
/// # use libvctrl_sha512::sha384::Hash;
/// let digest = Hash::hash(b"abc");
/// assert_eq!(digest, [
/// 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
/// 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
/// 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
/// 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,
/// 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23,
/// 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7,
/// ]);
/// ```
;
// The following macro invocations generate HMAC-SHA-384 and HKDF-SHA-384
// structures directly inside this module. See the crate-level documentation for
// the `impl_hmac!` and `impl_hkdf!` macros for details on usage.
impl_hmac!;
impl_hkdf!;