Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/crypt/pbkdf2.js
2868 views
1
// Copyright 2012 The Closure Library Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
* @fileoverview Implementation of PBKDF2 in JavaScript.
17
* @see http://en.wikipedia.org/wiki/PBKDF2
18
*
19
* Currently we only support HMAC-SHA1 as the underlying hash function. To add a
20
* new hash function, add a static method similar to deriveKeyFromPasswordSha1()
21
* and implement the specific computeBlockCallback() using the hash function.
22
*
23
* Usage:
24
* var key = pbkdf2.deriveKeySha1(
25
* stringToByteArray('password'), stringToByteArray('salt'), 1000, 128);
26
*
27
*/
28
29
goog.provide('goog.crypt.pbkdf2');
30
31
goog.require('goog.array');
32
goog.require('goog.asserts');
33
goog.require('goog.crypt');
34
goog.require('goog.crypt.Hmac');
35
goog.require('goog.crypt.Sha1');
36
37
38
/**
39
* Derives key from password using PBKDF2-SHA1
40
* @param {!Array<number>} password Byte array representation of the password
41
* from which the key is derived.
42
* @param {!Array<number>} initialSalt Byte array representation of the salt.
43
* @param {number} iterations Number of interations when computing the key.
44
* @param {number} keyLength Length of the output key in bits.
45
* Must be multiple of 8.
46
* @return {!Array<number>} Byte array representation of the output key.
47
*/
48
goog.crypt.pbkdf2.deriveKeySha1 = function(
49
password, initialSalt, iterations, keyLength) {
50
// Length of the HMAC-SHA1 output in bits.
51
var HASH_LENGTH = 160;
52
53
/**
54
* Compute each block of the key using HMAC-SHA1.
55
* @param {!Array<number>} index Byte array representation of the index of
56
* the block to be computed.
57
* @return {!Array<number>} Byte array representation of the output block.
58
*/
59
var computeBlock = function(index) {
60
// Initialize the result to be array of 0 such that its xor with the first
61
// block would be the first block.
62
var result = goog.array.repeat(0, HASH_LENGTH / 8);
63
// Initialize the salt of the first iteration to initialSalt || i.
64
var salt = initialSalt.concat(index);
65
var hmac = new goog.crypt.Hmac(new goog.crypt.Sha1(), password, 64);
66
// Compute and XOR each iteration.
67
for (var i = 0; i < iterations; i++) {
68
// The salt of the next iteration is the result of the current iteration.
69
salt = hmac.getHmac(salt);
70
result = goog.crypt.xorByteArray(result, salt);
71
}
72
return result;
73
};
74
75
return goog.crypt.pbkdf2.deriveKeyFromPassword_(
76
computeBlock, HASH_LENGTH, keyLength);
77
};
78
79
80
/**
81
* Compute each block of the key using PBKDF2.
82
* @param {Function} computeBlock Function to compute each block of the output
83
* key.
84
* @param {number} hashLength Length of each block in bits. This is determined
85
* by the specific hash function used. Must be multiple of 8.
86
* @param {number} keyLength Length of the output key in bits.
87
* Must be multiple of 8.
88
* @return {!Array<number>} Byte array representation of the output key.
89
* @private
90
*/
91
goog.crypt.pbkdf2.deriveKeyFromPassword_ = function(
92
computeBlock, hashLength, keyLength) {
93
goog.asserts.assert(keyLength % 8 == 0, 'invalid output key length');
94
95
// Compute and concactate each block of the output key.
96
var numBlocks = Math.ceil(keyLength / hashLength);
97
goog.asserts.assert(numBlocks >= 1, 'invalid number of blocks');
98
var result = [];
99
for (var i = 1; i <= numBlocks; i++) {
100
var indexBytes = goog.crypt.pbkdf2.integerToByteArray_(i);
101
result = result.concat(computeBlock(indexBytes));
102
}
103
104
// Trim the last block if needed.
105
var lastBlockSize = keyLength % hashLength;
106
if (lastBlockSize != 0) {
107
var desiredBytes = ((numBlocks - 1) * hashLength + lastBlockSize) / 8;
108
result.splice(desiredBytes, (hashLength - lastBlockSize) / 8);
109
}
110
return result;
111
};
112
113
114
/**
115
* Converts an integer number to a 32-bit big endian byte array.
116
* @param {number} n Integer number to be converted.
117
* @return {!Array<number>} Byte Array representation of the 32-bit big endian
118
* encoding of n.
119
* @private
120
*/
121
goog.crypt.pbkdf2.integerToByteArray_ = function(n) {
122
var result = new Array(4);
123
result[0] = n >> 24 & 0xFF;
124
result[1] = n >> 16 & 0xFF;
125
result[2] = n >> 8 & 0xFF;
126
result[3] = n & 0xFF;
127
return result;
128
};
129
130