0
# Password Hashing
1
2
Secure password hashing using Argon2 and scrypt algorithms for password verification, key derivation, and protection against brute-force attacks.
3
4
## Capabilities
5
6
### Argon2 Password Hashing
7
8
Modern password hashing using Argon2i or Argon2id algorithms.
9
10
```javascript { .api }
11
/**
12
* Hash password using Argon2
13
* @param out - Output buffer for derived key
14
* @param passwd - Password buffer to hash
15
* @param salt - Salt buffer (must be SALTBYTES long)
16
* @param opslimit - Operations limit (computational cost)
17
* @param memlimit - Memory limit in bytes
18
* @param alg - Algorithm ID (ALG_ARGON2I13 or ALG_ARGON2ID13)
19
* @throws Error if parameters are out of bounds or hashing fails
20
*/
21
function crypto_pwhash(
22
out: Buffer,
23
passwd: Buffer,
24
salt: Buffer,
25
opslimit: number,
26
memlimit: number,
27
alg: number
28
): void;
29
```
30
31
### Argon2 Async Password Hashing
32
33
Non-blocking password hashing for server applications.
34
35
```javascript { .api }
36
/**
37
* Hash password using Argon2 (async)
38
* @param out - Output buffer for derived key
39
* @param passwd - Password buffer to hash
40
* @param salt - Salt buffer (must be SALTBYTES long)
41
* @param opslimit - Operations limit (computational cost)
42
* @param memlimit - Memory limit in bytes
43
* @param alg - Algorithm ID (ALG_ARGON2I13 or ALG_ARGON2ID13)
44
* @param callback - Optional callback function
45
* @returns Promise<void> if no callback provided
46
* @throws Error if parameters are out of bounds
47
*/
48
function crypto_pwhash_async(
49
out: Buffer,
50
passwd: Buffer,
51
salt: Buffer,
52
opslimit: number,
53
memlimit: number,
54
alg: number,
55
callback?: (error: Error | null) => void
56
): Promise<void> | undefined;
57
```
58
59
**Usage Example:**
60
61
```javascript
62
const sodium = require('sodium-native');
63
64
async function hashPassword(password) {
65
const salt = Buffer.alloc(sodium.crypto_pwhash_SALTBYTES);
66
sodium.randombytes_buf(salt);
67
68
const derivedKey = Buffer.alloc(32);
69
70
// Using async version (recommended for servers)
71
await sodium.crypto_pwhash_async(
72
derivedKey,
73
Buffer.from(password),
74
salt,
75
sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE,
76
sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE,
77
sodium.crypto_pwhash_ALG_ARGON2ID13
78
);
79
80
return { derivedKey, salt };
81
}
82
```
83
84
### Argon2 String Format
85
86
Password hashing with string encoding for easy storage.
87
88
```javascript { .api }
89
/**
90
* Hash password to string format
91
* @param out - Output buffer for password string (must be STRBYTES long)
92
* @param passwd - Password buffer to hash
93
* @param opslimit - Operations limit (computational cost)
94
* @param memlimit - Memory limit in bytes
95
* @throws Error if parameters are out of bounds or hashing fails
96
*/
97
function crypto_pwhash_str(
98
out: Buffer,
99
passwd: Buffer,
100
opslimit: number,
101
memlimit: number
102
): void;
103
104
/**
105
* Hash password to string format (async)
106
* @param out - Output buffer for password string (must be STRBYTES long)
107
* @param passwd - Password buffer to hash
108
* @param opslimit - Operations limit (computational cost)
109
* @param memlimit - Memory limit in bytes
110
* @param callback - Optional callback function
111
* @returns Promise<void> if no callback provided
112
*/
113
function crypto_pwhash_str_async(
114
out: Buffer,
115
passwd: Buffer,
116
opslimit: number,
117
memlimit: number,
118
callback?: (error: Error | null) => void
119
): Promise<void> | undefined;
120
```
121
122
### Argon2 String Verification
123
124
Verify passwords against stored string hashes.
125
126
```javascript { .api }
127
/**
128
* Verify password against string hash
129
* @param str - Password string hash to verify against (must be STRBYTES long)
130
* @param passwd - Password buffer to verify
131
* @returns true if password matches, false otherwise
132
*/
133
function crypto_pwhash_str_verify(str: Buffer, passwd: Buffer): boolean;
134
135
/**
136
* Verify password against string hash (async)
137
* @param str - Password string hash to verify against (must be STRBYTES long)
138
* @param passwd - Password buffer to verify
139
* @param callback - Optional callback function
140
* @returns Promise<boolean> if no callback provided
141
*/
142
function crypto_pwhash_str_verify_async(
143
str: Buffer,
144
passwd: Buffer,
145
callback?: (error: Error | null, result?: boolean) => void
146
): Promise<boolean> | undefined;
147
```
148
149
### Argon2 Rehash Check
150
151
Check if a password hash needs to be updated due to changed parameters.
152
153
```javascript { .api }
154
/**
155
* Check if password hash needs rehashing with new parameters
156
* @param str - Password string hash to check (must be STRBYTES long)
157
* @param opslimit - New operations limit to compare against
158
* @param memlimit - New memory limit to compare against
159
* @returns true if rehashing needed, false otherwise
160
*/
161
function crypto_pwhash_str_needs_rehash(
162
str: Buffer,
163
opslimit: number,
164
memlimit: number
165
): boolean;
166
```
167
168
**Usage Example:**
169
170
```javascript
171
const sodium = require('sodium-native');
172
173
class PasswordManager {
174
async hashPassword(password) {
175
const hash = Buffer.alloc(sodium.crypto_pwhash_STRBYTES);
176
177
await sodium.crypto_pwhash_str_async(
178
hash,
179
Buffer.from(password),
180
sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE,
181
sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE
182
);
183
184
return hash;
185
}
186
187
async verifyPassword(password, hash) {
188
return await sodium.crypto_pwhash_str_verify_async(
189
hash,
190
Buffer.from(password)
191
);
192
}
193
194
needsRehash(hash) {
195
return sodium.crypto_pwhash_str_needs_rehash(
196
hash,
197
sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE,
198
sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE
199
);
200
}
201
}
202
```
203
204
### Scrypt Password Hashing
205
206
Legacy scrypt algorithm support for compatibility.
207
208
```javascript { .api }
209
/**
210
* Hash password using scrypt
211
* @param out - Output buffer for derived key
212
* @param passwd - Password buffer to hash
213
* @param salt - Salt buffer (must be SALTBYTES long)
214
* @param opslimit - Operations limit (computational cost)
215
* @param memlimit - Memory limit in bytes
216
* @throws Error if parameters are out of bounds or hashing fails
217
*/
218
function crypto_pwhash_scryptsalsa208sha256(
219
out: Buffer,
220
passwd: Buffer,
221
salt: Buffer,
222
opslimit: number,
223
memlimit: number
224
): void;
225
226
/**
227
* Hash password using scrypt (async)
228
* @param out - Output buffer for derived key
229
* @param passwd - Password buffer to hash
230
* @param salt - Salt buffer (must be SALTBYTES long)
231
* @param opslimit - Operations limit (computational cost)
232
* @param memlimit - Memory limit in bytes
233
* @param callback - Optional callback function
234
* @returns Promise<void> if no callback provided
235
*/
236
function crypto_pwhash_scryptsalsa208sha256_async(
237
out: Buffer,
238
passwd: Buffer,
239
salt: Buffer,
240
opslimit: number,
241
memlimit: number,
242
callback?: (error: Error | null) => void
243
): Promise<void> | undefined;
244
```
245
246
### Scrypt String Format
247
248
Scrypt password hashing with string encoding.
249
250
```javascript { .api }
251
/**
252
* Hash password to string format using scrypt
253
* @param out - Output buffer for password string (must be STRBYTES long)
254
* @param passwd - Password buffer to hash
255
* @param opslimit - Operations limit (computational cost)
256
* @param memlimit - Memory limit in bytes
257
* @throws Error if parameters are out of bounds or hashing fails
258
*/
259
function crypto_pwhash_scryptsalsa208sha256_str(
260
out: Buffer,
261
passwd: Buffer,
262
opslimit: number,
263
memlimit: number
264
): void;
265
266
/**
267
* Verify password against scrypt string hash
268
* @param str - Password string hash to verify against (must be STRBYTES long)
269
* @param passwd - Password buffer to verify
270
* @returns true if password matches, false otherwise
271
*/
272
function crypto_pwhash_scryptsalsa208sha256_str_verify(str: Buffer, passwd: Buffer): boolean;
273
274
/**
275
* Check if scrypt password hash needs rehashing
276
* @param str - Password string hash to check (must be STRBYTES long)
277
* @param opslimit - New operations limit to compare against
278
* @param memlimit - New memory limit to compare against
279
* @returns true if rehashing needed, false otherwise
280
*/
281
function crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(
282
str: Buffer,
283
opslimit: number,
284
memlimit: number
285
): boolean;
286
```
287
288
## Constants
289
290
```javascript { .api }
291
// Argon2 algorithm constants
292
const crypto_pwhash_ALG_ARGON2I13: number;
293
const crypto_pwhash_ALG_ARGON2ID13: number;
294
const crypto_pwhash_ALG_DEFAULT: number;
295
296
// Argon2 size constants
297
const crypto_pwhash_BYTES_MIN: number;
298
const crypto_pwhash_BYTES_MAX: number;
299
const crypto_pwhash_PASSWD_MIN: number;
300
const crypto_pwhash_PASSWD_MAX: number;
301
const crypto_pwhash_SALTBYTES: number;
302
const crypto_pwhash_STRBYTES: number;
303
304
// Argon2 cost constants
305
const crypto_pwhash_OPSLIMIT_MIN: number;
306
const crypto_pwhash_OPSLIMIT_MAX: number;
307
const crypto_pwhash_OPSLIMIT_INTERACTIVE: number;
308
const crypto_pwhash_OPSLIMIT_MODERATE: number;
309
const crypto_pwhash_OPSLIMIT_SENSITIVE: number;
310
const crypto_pwhash_MEMLIMIT_MIN: number;
311
const crypto_pwhash_MEMLIMIT_MAX: number;
312
const crypto_pwhash_MEMLIMIT_INTERACTIVE: number;
313
const crypto_pwhash_MEMLIMIT_MODERATE: number;
314
const crypto_pwhash_MEMLIMIT_SENSITIVE: number;
315
316
// Scrypt size constants
317
const crypto_pwhash_scryptsalsa208sha256_BYTES_MIN: number;
318
const crypto_pwhash_scryptsalsa208sha256_BYTES_MAX: number;
319
const crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN: number;
320
const crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX: number;
321
const crypto_pwhash_scryptsalsa208sha256_SALTBYTES: number;
322
const crypto_pwhash_scryptsalsa208sha256_STRBYTES: number;
323
324
// Scrypt cost constants
325
const crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN: number;
326
const crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX: number;
327
const crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE: number;
328
const crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE: number;
329
const crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN: number;
330
const crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX: number;
331
const crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE: number;
332
const crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE: number;
333
```
334
335
## Security Considerations
336
337
- **Algorithm Choice**: Use Argon2id (ALG_ARGON2ID13) for new applications; it's more resistant to GPU attacks.
338
- **Cost Parameters**: Choose appropriate opslimit/memlimit based on your security requirements and hardware.
339
- **Salt Uniqueness**: Always use unique, random salts for each password.
340
- **Timing**: Use async versions in server applications to prevent blocking.
341
342
## Common Patterns
343
344
### User Authentication System
345
346
```javascript
347
const sodium = require('sodium-native');
348
349
class UserAuth {
350
constructor() {
351
this.users = new Map();
352
}
353
354
async registerUser(username, password) {
355
const hash = Buffer.alloc(sodium.crypto_pwhash_STRBYTES);
356
357
await sodium.crypto_pwhash_str_async(
358
hash,
359
Buffer.from(password),
360
sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE,
361
sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE
362
);
363
364
this.users.set(username, hash);
365
return true;
366
}
367
368
async loginUser(username, password) {
369
const storedHash = this.users.get(username);
370
if (!storedHash) return false;
371
372
// Check if hash needs updating
373
if (sodium.crypto_pwhash_str_needs_rehash(
374
storedHash,
375
sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE,
376
sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE
377
)) {
378
// Rehash password with new parameters after successful verification
379
const isValid = await sodium.crypto_pwhash_str_verify_async(
380
storedHash,
381
Buffer.from(password)
382
);
383
384
if (isValid) {
385
await this.registerUser(username, password); // Update hash
386
}
387
388
return isValid;
389
}
390
391
return await sodium.crypto_pwhash_str_verify_async(
392
storedHash,
393
Buffer.from(password)
394
);
395
}
396
}
397
```
398
399
### Key Derivation from Password
400
401
```javascript
402
const sodium = require('sodium-native');
403
404
async function deriveEncryptionKey(password, salt) {
405
const key = Buffer.alloc(32); // 256-bit key
406
407
await sodium.crypto_pwhash_async(
408
key,
409
Buffer.from(password),
410
salt,
411
sodium.crypto_pwhash_OPSLIMIT_SENSITIVE,
412
sodium.crypto_pwhash_MEMLIMIT_SENSITIVE,
413
sodium.crypto_pwhash_ALG_ARGON2ID13
414
);
415
416
return key;
417
}
418
419
// Usage for file encryption
420
async function encryptFileWithPassword(filename, password) {
421
const salt = Buffer.alloc(sodium.crypto_pwhash_SALTBYTES);
422
sodium.randombytes_buf(salt);
423
424
const key = await deriveEncryptionKey(password, salt);
425
426
// Use key with crypto_secretbox_easy
427
// Store salt alongside encrypted file for decryption
428
}
429
```