generated from TBD54566975/tbd-project-template
-
Notifications
You must be signed in to change notification settings - Fork 57
/
pbkdf2.ts
122 lines (113 loc) · 4.29 KB
/
pbkdf2.ts
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
import { crypto } from '@noble/hashes/crypto';
/**
* The object that should be passed into `Pbkdf2.deriveKey()`, when using the PBKDF2 algorithm.
*/
export type Pbkdf2DeriveKeyParams = {
/**
* A string representing the digest algorithm to use. This may be one of:
* - 'SHA-256'
* - 'SHA-384'
* - 'SHA-512'
*/
hash: 'SHA-256' | 'SHA-384' | 'SHA-512';
/**
* The password from which to derive the key, represented as a Uint8Array.
*/
password: Uint8Array;
/**
* The salt value to use in the derivation process, as a Uint8Array. This should be a random or
* pseudo-random value of at least 16 bytes. Unlike the `password`, `salt` does not need to be
* kept secret.
*/
salt: Uint8Array;
/**
* A `Number` representing the number of iterations the hash function will be executed in
* `deriveKey()`. This impacts the computational cost of the `deriveKey()` operation, making it
* more resistant to dictionary attacks. The higher the number, the more secure, but also slower,
* the operation. Choose a value that balances security needs and performance for your
* application.
*/
iterations: number;
/**
* The desired length of the derived key in bits. To be compatible with all browsers, the number
* should be a multiple of 8.
*/
length: number;
};
/**
* The `Pbkdf2` class provides a secure way to derive cryptographic keys from a password
* using the PBKDF2 (Password-Based Key Derivation Function 2) algorithm.
*
* The PBKDF2 algorithm is widely used for generating keys from passwords, as it applies
* a pseudorandom function to the input password along with a salt value and iterates the
* process multiple times to increase the key's resistance to brute-force attacks.
*
* This class offers a single static method `deriveKey` to perform key derivation.
*
* @example
* ```ts
* // Key Derivation
* const derivedKey = await Pbkdf2.deriveKey({
* hash: 'SHA-256', // The hash function to use ('SHA-256', 'SHA-384', 'SHA-512')
* password: new TextEncoder().encode('password'), // The password as a Uint8Array
* salt: new Uint8Array([...]), // The salt value
* iterations: 1000, // The number of iterations
* length: 256 // The length of the derived key in bits
* });
* ```
*
* @remarks
* This class relies on the availability of the Web Crypto API.
*/
export class Pbkdf2 {
/**
* Derives a cryptographic key from a password using the PBKDF2 algorithm.
*
* @remarks
* This method applies the PBKDF2 algorithm to the provided password along with
* a salt value and iterates the process a specified number of times. It uses
* a cryptographic hash function to enhance security and produce a key of the
* desired length. The method is capable of utilizing either the Web Crypto API
* or the Node.js Crypto module, depending on the environment's support.
*
* @example
* ```ts
* const derivedKey = await Pbkdf2.deriveKey({
* hash: 'SHA-256',
* password: new TextEncoder().encode('password'),
* salt: new Uint8Array([...]),
* iterations: 1000,
* length: 256
* });
* ```
*
* @param params - The parameters for key derivation.
* @param params.hash - The hash function to use, such as 'SHA-256', 'SHA-384', or 'SHA-512'.
* @param params.password - The password from which to derive the key, represented as a Uint8Array.
* @param params.salt - The salt value to use in the derivation process, as a Uint8Array.
* @param params.iterations - The number of iterations to apply in the PBKDF2 algorithm.
* @param params.length - The desired length of the derived key in bits.
*
* @returns A Promise that resolves to the derived key as a Uint8Array.
*/
public static async deriveKey({ hash, password, salt, iterations, length }:
Pbkdf2DeriveKeyParams
): Promise<Uint8Array> {
// Import the password as a raw key for use with the Web Crypto API.
const webCryptoKey = await crypto.subtle.importKey(
'raw',
password,
{ name: 'PBKDF2' },
false,
['deriveBits']
);
const derivedKeyBuffer = await crypto.subtle.deriveBits(
{ name: 'PBKDF2', hash, salt, iterations },
webCryptoKey,
length
);
// Convert from ArrayBuffer to Uint8Array.
const derivedKey = new Uint8Array(derivedKeyBuffer);
return derivedKey;
}
}