0
# Key Derivation
1
2
Key derivation functions for generating cryptographic keys from passwords, shared secrets, or other key material. Supports PBKDF2, HKDF, and HMAC operations.
3
4
## Capabilities
5
6
### PBKDF2 (Password-Based Key Derivation Function 2)
7
8
Derives cryptographic keys from passwords using iterative hashing for brute-force resistance.
9
10
```typescript { .api }
11
/**
12
* PBKDF2 key derivation parameters
13
*/
14
interface Pbkdf2Params extends Algorithm {
15
name: "PBKDF2";
16
salt: BufferSource; // Random salt (minimum 64 bits recommended)
17
iterations: number; // Iteration count (minimum 10,000 recommended)
18
hash: "SHA-1" | "SHA-256" | "SHA-384" | "SHA-512"; // Hash algorithm
19
}
20
```
21
22
**Usage Example:**
23
24
```typescript
25
// Import password as key material
26
const password = new TextEncoder().encode("user-password");
27
const passwordKey = await crypto.subtle.importKey(
28
"raw",
29
password,
30
{ name: "PBKDF2" },
31
false,
32
["deriveKey", "deriveBits"]
33
);
34
35
// Generate random salt
36
const salt = crypto.getRandomValues(new Uint8Array(16));
37
38
// Derive AES key from password
39
const derivedKey = await crypto.subtle.deriveKey(
40
{
41
name: "PBKDF2",
42
salt: salt,
43
iterations: 100000,
44
hash: "SHA-256"
45
},
46
passwordKey,
47
{ name: "AES-GCM", length: 256 },
48
false,
49
["encrypt", "decrypt"]
50
);
51
52
// Alternative: derive raw bits
53
const derivedBits = await crypto.subtle.deriveBits(
54
{
55
name: "PBKDF2",
56
salt: salt,
57
iterations: 100000,
58
hash: "SHA-256"
59
},
60
passwordKey,
61
256 // 256 bits output
62
);
63
```
64
65
### HKDF (HMAC-based Key Derivation Function)
66
67
Extracts and expands key material using HMAC for key agreement and key stretching.
68
69
```typescript { .api }
70
/**
71
* HKDF key derivation parameters
72
*/
73
interface HkdfParams extends Algorithm {
74
name: "HKDF";
75
hash: "SHA-1" | "SHA-256" | "SHA-384" | "SHA-512"; // Hash algorithm
76
salt: BufferSource; // Salt value (can be empty)
77
info: BufferSource; // Application-specific context information
78
}
79
```
80
81
**Usage Example:**
82
83
```typescript
84
// Import shared secret as key material
85
const sharedSecret = crypto.getRandomValues(new Uint8Array(32));
86
const baseKey = await crypto.subtle.importKey(
87
"raw",
88
sharedSecret,
89
{ name: "HKDF" },
90
false,
91
["deriveKey", "deriveBits"]
92
);
93
94
// Derive multiple keys from shared secret
95
const salt = new TextEncoder().encode("unique-salt");
96
const info = new TextEncoder().encode("application-context");
97
98
// Derive encryption key
99
const encryptionKey = await crypto.subtle.deriveKey(
100
{
101
name: "HKDF",
102
hash: "SHA-256",
103
salt: salt,
104
info: new TextEncoder().encode("encryption-key")
105
},
106
baseKey,
107
{ name: "AES-GCM", length: 256 },
108
false,
109
["encrypt", "decrypt"]
110
);
111
112
// Derive MAC key
113
const macKey = await crypto.subtle.deriveKey(
114
{
115
name: "HKDF",
116
hash: "SHA-256",
117
salt: salt,
118
info: new TextEncoder().encode("mac-key")
119
},
120
baseKey,
121
{ name: "HMAC", hash: "SHA-256" },
122
false,
123
["sign", "verify"]
124
);
125
```
126
127
### HMAC (Hash-based Message Authentication Code)
128
129
Provides message authentication and integrity verification using cryptographic hash functions.
130
131
```typescript { .api }
132
/**
133
* HMAC key generation parameters
134
*/
135
interface HmacKeyGenParams extends Algorithm {
136
name: "HMAC";
137
hash: "SHA-1" | "SHA-256" | "SHA-384" | "SHA-512";
138
length?: number; // Key length in bits (optional)
139
}
140
141
/**
142
* HMAC operation parameters
143
*/
144
interface HmacParams extends Algorithm {
145
name: "HMAC";
146
}
147
```
148
149
**Usage Example:**
150
151
```typescript
152
// Generate HMAC key
153
const hmacKey = await crypto.subtle.generateKey(
154
{ name: "HMAC", hash: "SHA-256", length: 256 },
155
true,
156
["sign", "verify"]
157
);
158
159
// Create HMAC signature
160
const data = new TextEncoder().encode("Message to authenticate");
161
const signature = await crypto.subtle.sign(
162
{ name: "HMAC" },
163
hmacKey,
164
data
165
);
166
167
// Verify HMAC signature
168
const isValid = await crypto.subtle.verify(
169
{ name: "HMAC" },
170
hmacKey,
171
signature,
172
data
173
);
174
175
// Import HMAC key from raw bytes
176
const keyMaterial = crypto.getRandomValues(new Uint8Array(32));
177
const importedKey = await crypto.subtle.importKey(
178
"raw",
179
keyMaterial,
180
{ name: "HMAC", hash: "SHA-256" },
181
false,
182
["sign", "verify"]
183
);
184
```
185
186
## Key Classes
187
188
### PBKDF2 Key Class
189
190
```typescript { .api }
191
/**
192
* PBKDF2 key for deriving other keys from passwords
193
*/
194
class PbkdfCryptoKey extends SymmetricKey {
195
public algorithm: PbkdfKeyAlgorithm;
196
public type: "secret";
197
public usages: ("deriveKey" | "deriveBits")[];
198
public extractable: boolean;
199
}
200
201
interface PbkdfKeyAlgorithm extends KeyAlgorithm {
202
name: "PBKDF2";
203
}
204
```
205
206
### HKDF Key Class
207
208
```typescript { .api }
209
/**
210
* HKDF key for expanding key material
211
*/
212
class HkdfCryptoKey extends SymmetricKey {
213
public algorithm: HkdfKeyAlgorithm;
214
public type: "secret";
215
public usages: ("deriveKey" | "deriveBits")[];
216
public extractable: boolean;
217
}
218
219
interface HkdfKeyAlgorithm extends KeyAlgorithm {
220
name: "HKDF";
221
}
222
```
223
224
### HMAC Key Class
225
226
```typescript { .api }
227
/**
228
* HMAC key for message authentication
229
*/
230
class HmacCryptoKey extends SymmetricKey {
231
public algorithm: HmacKeyAlgorithm;
232
public type: "secret";
233
public usages: ("sign" | "verify")[];
234
public extractable: boolean;
235
}
236
237
interface HmacKeyAlgorithm extends KeyAlgorithm {
238
name: "HMAC";
239
hash: KeyAlgorithm;
240
length: number;
241
}
242
```
243
244
## Advanced Usage Patterns
245
246
### Key Stretching with PBKDF2
247
248
```typescript
249
async function stretchPassword(
250
password: string,
251
salt: Uint8Array,
252
iterations: number = 100000
253
) {
254
const passwordKey = await crypto.subtle.importKey(
255
"raw",
256
new TextEncoder().encode(password),
257
{ name: "PBKDF2" },
258
false,
259
["deriveBits"]
260
);
261
262
return await crypto.subtle.deriveBits(
263
{
264
name: "PBKDF2",
265
salt: salt,
266
iterations: iterations,
267
hash: "SHA-256"
268
},
269
passwordKey,
270
256
271
);
272
}
273
```
274
275
### Key Expansion with HKDF
276
277
```typescript
278
async function expandKey(
279
masterKey: ArrayBuffer,
280
salt: string,
281
info: string,
282
keyLength: number = 256
283
) {
284
const baseKey = await crypto.subtle.importKey(
285
"raw",
286
masterKey,
287
{ name: "HKDF" },
288
false,
289
["deriveBits"]
290
);
291
292
return await crypto.subtle.deriveBits(
293
{
294
name: "HKDF",
295
hash: "SHA-256",
296
salt: new TextEncoder().encode(salt),
297
info: new TextEncoder().encode(info)
298
},
299
baseKey,
300
keyLength
301
);
302
}
303
```
304
305
### HMAC Chain for Sequential Authentication
306
307
```typescript
308
async function createHmacChain(
309
key: CryptoKey,
310
messages: string[]
311
): Promise<ArrayBuffer[]> {
312
const signatures: ArrayBuffer[] = [];
313
314
for (const message of messages) {
315
const data = new TextEncoder().encode(message);
316
const signature = await crypto.subtle.sign(
317
{ name: "HMAC" },
318
key,
319
data
320
);
321
signatures.push(signature);
322
}
323
324
return signatures;
325
}
326
```
327
328
## Security Best Practices
329
330
### PBKDF2 Recommendations
331
- **Minimum iterations**: 100,000 for SHA-256 (2023 recommendations)
332
- **Salt length**: At least 128 bits (16 bytes) of random data
333
- **Unique salts**: Use different salt for each password
334
- **Hash algorithm**: SHA-256 or stronger
335
336
### HKDF Recommendations
337
- **Salt usage**: Use random salt when possible, empty salt is acceptable
338
- **Info parameter**: Include application context to prevent key reuse
339
- **Hash algorithm**: SHA-256 or stronger for most applications
340
341
### HMAC Recommendations
342
- **Key length**: At least as long as hash output (256 bits for SHA-256)
343
- **Key generation**: Use cryptographically secure random generation
344
- **Hash algorithm**: SHA-256 or stronger, avoid SHA-1
345
346
## Error Handling
347
348
```typescript
349
async function safeDeriveKey(
350
algorithm: any,
351
baseKey: CryptoKey,
352
derivedKeyType: any,
353
extractable: boolean,
354
keyUsages: KeyUsage[]
355
) {
356
try {
357
return await crypto.subtle.deriveKey(
358
algorithm,
359
baseKey,
360
derivedKeyType,
361
extractable,
362
keyUsages
363
);
364
} catch (error) {
365
if (error.name === "InvalidAccessError") {
366
throw new Error("Base key doesn't support key derivation");
367
}
368
if (error.name === "NotSupportedError") {
369
throw new Error("Key derivation algorithm not supported");
370
}
371
if (error.name === "OperationError") {
372
throw new Error("Key derivation failed - check parameters");
373
}
374
throw error;
375
}
376
}
377
```
378
379
## Performance Considerations
380
381
- **PBKDF2**: Higher iteration counts increase security but reduce performance
382
- **HKDF**: Fast operation, suitable for real-time key derivation
383
- **HMAC**: Very fast, suitable for high-throughput authentication
384
- **Caching**: Consider caching derived keys when appropriate for performance