0
# Key Derivation Functions
1
2
Password-based key derivation functions for generating cryptographic keys from passwords and salts, including PBKDF2 and Scrypt algorithms.
3
4
## Capabilities
5
6
### PBKDF2 Key Derivation
7
8
Password-Based Key Derivation Function 2 (PBKDF2) for deriving cryptographic keys from passwords.
9
10
```typescript { .api }
11
/**
12
* Derives key using PBKDF2
13
* @param data - Password data as Uint8Array
14
* @param salt - Salt as Uint8Array (recommended: at least 16 bytes)
15
* @param rounds - Number of iterations (recommended: at least 10,000)
16
* @returns 64-byte derived key as Uint8Array
17
*/
18
function pbkdf2(data: Uint8Array, salt: Uint8Array, rounds: number): Uint8Array;
19
```
20
21
**Usage Example:**
22
23
```typescript
24
import { waitReady, pbkdf2 } from "@polkadot/wasm-crypto";
25
26
await waitReady();
27
28
const password = new TextEncoder().encode("my-secure-password");
29
const salt = new Uint8Array(16);
30
crypto.getRandomValues(salt); // Generate random salt
31
32
// Derive key with different iteration counts
33
const key10k = pbkdf2(password, salt, 10000);
34
const key100k = pbkdf2(password, salt, 100000);
35
36
console.log("PBKDF2 key length:", key10k.length); // 64
37
console.log("Keys are different:",
38
Array.from(key10k).join(',') !== Array.from(key100k).join(',')
39
); // true
40
```
41
42
### Scrypt Key Derivation
43
44
Scrypt key derivation function designed to be memory-hard and resist hardware attacks.
45
46
```typescript { .api }
47
/**
48
* Derives key using Scrypt
49
* @param password - Password as Uint8Array
50
* @param salt - Salt as Uint8Array (recommended: at least 16 bytes)
51
* @param log2n - CPU/memory cost parameter (power of 2, e.g., 14 = 2^14 = 16384)
52
* @param r - Block size parameter (typically 8)
53
* @param p - Parallelization parameter (typically 1)
54
* @returns 64-byte derived key as Uint8Array
55
*/
56
function scrypt(password: Uint8Array, salt: Uint8Array, log2n: number, r: number, p: number): Uint8Array;
57
```
58
59
**Usage Example:**
60
61
```typescript
62
import { waitReady, scrypt } from "@polkadot/wasm-crypto";
63
64
await waitReady();
65
66
const password = new TextEncoder().encode("my-secure-password");
67
const salt = new Uint8Array(16);
68
crypto.getRandomValues(salt); // Generate random salt
69
70
// Common Scrypt parameters
71
const log2n = 14; // N = 2^14 = 16384 (memory cost)
72
const r = 8; // Block size
73
const p = 1; // Parallelization
74
75
const derivedKey = scrypt(password, salt, log2n, r, p);
76
77
console.log("Scrypt key length:", derivedKey.length); // 64
78
```
79
80
## Parameter Guidelines
81
82
### PBKDF2 Parameters
83
84
- **Rounds**: Minimum 10,000, recommended 100,000+ for high security
85
- **Salt**: At least 16 bytes, preferably 32 bytes of random data
86
- **Output**: Always 64 bytes
87
88
### Scrypt Parameters
89
90
- **log2n**: Common values are 12-16 (N = 4096-65536)
91
- 12: Low security, fast (N = 4096)
92
- 14: Medium security (N = 16384) - good default
93
- 16: High security, slower (N = 65536)
94
- **r**: Usually 8 (block size parameter)
95
- **p**: Usually 1 (parallelization parameter)
96
- **Salt**: At least 16 bytes, preferably 32 bytes of random data
97
- **Output**: Always 64 bytes
98
99
## Security Considerations
100
101
```typescript
102
import { waitReady, pbkdf2, scrypt } from "@polkadot/wasm-crypto";
103
104
async function demonstrateSecureKeyDerivation() {
105
await waitReady();
106
107
const password = new TextEncoder().encode("user-password");
108
109
// Generate cryptographically secure salt
110
const salt = new Uint8Array(32);
111
crypto.getRandomValues(salt);
112
113
// PBKDF2 with high iteration count
114
const pbkdf2Key = pbkdf2(password, salt, 100000);
115
116
// Scrypt with recommended parameters
117
const scryptKey = scrypt(password, salt, 14, 8, 1);
118
119
// Store salt alongside derived key for later verification
120
const storedData = {
121
salt: Array.from(salt),
122
pbkdf2Key: Array.from(pbkdf2Key),
123
scryptKey: Array.from(scryptKey)
124
};
125
126
console.log("Salt length:", salt.length); // 32
127
console.log("Both keys derived successfully");
128
129
return storedData;
130
}
131
132
demonstrateSecureKeyDerivation();
133
```
134
135
## Performance Comparison
136
137
```typescript
138
import { waitReady, pbkdf2, scrypt } from "@polkadot/wasm-crypto";
139
140
async function compareKeyDerivationPerformance() {
141
await waitReady();
142
143
const password = new TextEncoder().encode("test-password");
144
const salt = new Uint8Array(32).fill(1); // Fixed salt for consistent timing
145
146
// Time PBKDF2
147
console.time("PBKDF2 (100k iterations)");
148
const pbkdf2Key = pbkdf2(password, salt, 100000);
149
console.timeEnd("PBKDF2 (100k iterations)");
150
151
// Time Scrypt
152
console.time("Scrypt (N=16384, r=8, p=1)");
153
const scryptKey = scrypt(password, salt, 14, 8, 1);
154
console.timeEnd("Scrypt (N=16384, r=8, p=1)");
155
156
console.log("PBKDF2 result length:", pbkdf2Key.length); // 64
157
console.log("Scrypt result length:", scryptKey.length); // 64
158
159
return { pbkdf2Key, scryptKey };
160
}
161
162
compareKeyDerivationPerformance();
163
```
164
165
## Complete Key Derivation Workflow
166
167
```typescript
168
import { waitReady, pbkdf2, scrypt, hmacSha256 } from "@polkadot/wasm-crypto";
169
170
async function demonstrateKeyDerivationWorkflow() {
171
await waitReady();
172
173
// Simulate user registration
174
const userPassword = "user-secure-password-123";
175
const passwordBytes = new TextEncoder().encode(userPassword);
176
177
// Generate unique salt for this user
178
const userSalt = new Uint8Array(32);
179
crypto.getRandomValues(userSalt);
180
181
// Derive master key using Scrypt (more secure for password storage)
182
const masterKey = scrypt(passwordBytes, userSalt, 14, 8, 1);
183
184
// Derive application-specific keys using HMAC
185
const encryptionKey = hmacSha256(masterKey, new TextEncoder().encode("encryption"));
186
const authKey = hmacSha256(masterKey, new TextEncoder().encode("authentication"));
187
188
// For comparison, also show PBKDF2 derivation
189
const pbkdf2MasterKey = pbkdf2(passwordBytes, userSalt, 100000);
190
191
console.log("User salt:", Array.from(userSalt.slice(0, 8)).map(b => b.toString(16).padStart(2, '0')).join(''));
192
console.log("Scrypt master key:", Array.from(masterKey.slice(0, 8)).map(b => b.toString(16).padStart(2, '0')).join(''));
193
console.log("PBKDF2 master key:", Array.from(pbkdf2MasterKey.slice(0, 8)).map(b => b.toString(16).padStart(2, '0')).join(''));
194
console.log("Encryption key:", Array.from(encryptionKey.slice(0, 8)).map(b => b.toString(16).padStart(2, '0')).join(''));
195
console.log("Auth key:", Array.from(authKey.slice(0, 8)).map(b => b.toString(16).padStart(2, '0')).join(''));
196
197
return {
198
userSalt,
199
masterKey,
200
pbkdf2MasterKey,
201
encryptionKey,
202
authKey
203
};
204
}
205
206
demonstrateKeyDerivationWorkflow();
207
```