-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathpbkdf2.js
122 lines (108 loc) · 3.17 KB
/
pbkdf2.js
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 {
Base,
WordArray,
} from './core.js';
import { SHA1Algo } from './sha1.js';
import { HMAC } from './hmac.js';
/**
* Password-Based Key Derivation Function 2 algorithm.
*/
export class PBKDF2Algo extends Base {
/**
* Initializes a newly created key derivation function.
*
* @param {Object} cfg (Optional) The configuration options to use for the derivation.
*
* @example
*
* const kdf = CryptoJS.algo.PBKDF2.create();
* const kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8 });
* const kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8, iterations: 1000 });
*/
constructor(cfg) {
super();
/**
* Configuration options.
*
* @property {number} keySize The key size in words to generate. Default: 4 (128 bits)
* @property {Hasher} hasher The hasher to use. Default: SHA1
* @property {number} iterations The number of iterations to perform. Default: 1
*/
this.cfg = Object.assign(
new Base(),
{
keySize: 128 / 32,
hasher: SHA1Algo,
iterations: 1,
},
cfg,
);
}
/**
* Computes the Password-Based Key Derivation Function 2.
*
* @param {WordArray|string} password The password.
* @param {WordArray|string} salt A salt.
*
* @return {WordArray} The derived key.
*
* @example
*
* const key = kdf.compute(password, salt);
*/
compute(password, salt) {
// Shortcut
const { cfg } = this;
// Init HMAC
const hmac = HMAC.create(cfg.hasher, password);
// Initial values
const derivedKey = WordArray.create();
const blockIndex = WordArray.create([0x00000001]);
// Shortcuts
const derivedKeyWords = derivedKey.words;
const blockIndexWords = blockIndex.words;
const { keySize, iterations } = cfg;
// Generate key
while (derivedKeyWords.length < keySize) {
const block = hmac.update(salt).finalize(blockIndex);
hmac.reset();
// Shortcuts
const blockWords = block.words;
const blockWordsLength = blockWords.length;
// Iterations
let intermediate = block;
for (let i = 1; i < iterations; i += 1) {
intermediate = hmac.finalize(intermediate);
hmac.reset();
// Shortcut
const intermediateWords = intermediate.words;
// XOR intermediate with block
for (let j = 0; j < blockWordsLength; j += 1) {
blockWords[j] ^= intermediateWords[j];
}
}
derivedKey.concat(block);
blockIndexWords[0] += 1;
}
derivedKey.sigBytes = keySize * 4;
return derivedKey;
}
}
/**
* Computes the Password-Based Key Derivation Function 2.
*
* @param {WordArray|string} password The password.
* @param {WordArray|string} salt A salt.
* @param {Object} cfg (Optional) The configuration options to use for this computation.
*
* @return {WordArray} The derived key.
*
* @static
*
* @example
*
* var key = CryptoJS.PBKDF2(password, salt);
* var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 });
* var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 });
*/
export const PBKDF2 = (password, salt, cfg) => PBKDF2Algo.create(cfg).compute(password, salt);