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
//! # HKDF-SHA512 (RFC 5869)
//!
//! This module implements the HMAC-based Extract-and-Expand Key Derivation Function
//! (HKDF) as specified in [RFC 5869](https://datatracker.ietf.org/doc/html/rfc5869),
//! using SHA-512 as the underlying hash function.
//!
//! ## Overview
//!
//! HKDF is a simple, well-analyzed key derivation function that transforms
//! initial keying material (IKM) — which may be a non-uniformly random or
//! partially compromised secret — into one or more cryptographically strong
//! secret keys. The process consists of two stages:
//!
//! 1. **Extract**: concentrate the entropy from the IKM into a fixed-length
//! pseudorandom key (PRK). A salt (optional but recommended) helps to
//! randomise the extraction and can make even a weak IKM produce a strong
//! PRK.
//!
//! 2. **Expand**: take the PRK and an optional context string (info) to
//! produce an arbitrary amount of output keying material (OKM). The same
//! PRK can be used with different info values to generate multiple
//! independent keys from a single IKM.
//!
//! This separation provides both **entropy extraction** and **domain
//! separation**, two essential requirements for a robust KDF.
//!
//! ## Why SHA-512?
//!
//! SHA-512 offers a large block size (128 bytes) and a large internal state
//! (512 bits). In the context of HKDF:
//!
//! - A 64-byte hash output length allows the extract phase to accommodate
//! high-entropy inputs (e.g., DH shared secrets) without truncation loss.
//! - The high security margin of SHA-512 (preimage resistance, collision
//! resistance) makes the derived keys resilient even against future
//! cryptanalytic advances.
//! - On 64-bit platforms, SHA-512 is often faster than SHA-256 because it
//! processes twice as many bytes per round.
//!
//! ## Security Properties
//!
//! HKDF-SHA512 inherits the security properties of HMAC-SHA512:
//!
//! - **Pseudorandomness**: if the IKM has sufficient min-entropy, the PRK is
//! computationally indistinguishable from a random string of the same
//! length.
//! - **Independence**: different `info` strings produce independent output
//! keys; an attacker who learns one OKM gains no information about another
//! derived from the same PRK but a different info.
//! - **Resistance to related-key attacks**: the nested HMAC construction
//! prevents known attacks against simple concatenation KDFs.
//!
//! ## Usage Recommendations
//!
//! - **Salt**: a random, non-secret salt should be used whenever possible.
//! Even a salt derived from protocol constants is better than an empty salt.
//! - **Info**: always use a unique `info` string per key purpose (e.g.,
//! `b"encryption-key"` vs `b"mac-key"`). This provides domain separation.
//! - **PRK reuse**: the PRK may be reused with many different info values to
//! derive multiple keys without sacrificing security, **provided** the
//! underlying IKM remains the same and the salt is fixed.
//! - **Long output**: RFC 5869 limits the total output length to
//! `255 * HashLen` bytes (i.e., 16 320 bytes for SHA-512). This module
//! enforces that limit with a panic.
//!
//! ## Input Validation
//!
//! To prevent silent misuse, this implementation **validates** the length of
//! the PRK in `expand`:
//!
//! - For SHA-512, the PRK **must** be exactly 64 bytes. Passing a slice of
//! any other length causes a panic with a clear error message.
//! - The maximum output length is checked against the RFC limit and also
//! causes a panic on violation.
//!
//! While panicking on invalid input is not always idiomatic for general
//! libraries, in the context of a cryptographic library a clear panic is
//! preferable to silently producing weak or incorrect output.
//!
//! ## Examples
//!
//! ### Basic key derivation
//! ```rust
//! use libvctrl_sha512::HKDF;
//!
//! let ikm = b"shared-secret";
//! let salt = b"random-salt";
//! let info = b"encryption-key";
//!
//! // Extract PRK
//! let prk = HKDF::extract(salt, ikm);
//! assert_eq!(prk.len(), 64);
//!
//! // Expand to a 32-byte AES key
//! let mut aes_key = [0u8; 32];
//! HKDF::expand(&mut aes_key, prk, info);
//! ```
//!
//! ### Deriving multiple keys from one IKM
//! ```rust
//! use libvctrl_sha512::HKDF;
//!
//! let ikm = b"master-secret";
//! let salt = b"protocol-v1";
//! let prk = HKDF::extract(salt, ikm);
//!
//! // Two separate keys with different contexts
//! let mut enc_key = [0u8; 32];
//! let mut mac_key = [0u8; 64];
//! HKDF::expand(&mut enc_key, prk, b"encryption");
//! HKDF::expand(&mut mac_key, prk, b"authentication");
//! ```
//!
//! ### Empty salt and info
//! Although not recommended for production, the API supports empty slices:
//! ```rust
//! use libvctrl_sha512::HKDF;
//!
//! let prk = HKDF::extract([], b"some-input");
//! let mut okm = [0u8; 16];
//! HKDF::expand(&mut okm, prk, []);
//! ```
//!
//! ## Performance
//!
//! Each call to `expand` requires one HMAC-SHA512 computation per 64-byte
//! output block. The `extract` step performs a single HMAC-SHA512 operation.
//! For typical key lengths (e.g., 32 bytes) the overhead is negligible.
use crateHMAC;
/// HKDF-SHA512 implementation.
///
/// This is a zero-sized struct whose methods implement the HKDF operations.
/// Because it holds no state, all methods are stateless and can be called
/// freely.
;