Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ultraviolet
GitHub Repository: ultraviolet/bitaddress.org
Path: blob/master/src/crypto-scrypt.js
248 views
1
/*
2
* Copyright (c) 2010-2011 Intalio Pte, All Rights Reserved
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining a copy
5
* of this software and associated documentation files (the "Software"), to deal
6
* in the Software without restriction, including without limitation the rights
7
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
* copies of the Software, and to permit persons to whom the Software is
9
* furnished to do so, subject to the following conditions:
10
*
11
* The above copyright notice and this permission notice shall be included in
12
* all copies or substantial portions of the Software.
13
*
14
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
* THE SOFTWARE.
21
*/
22
// https://github.com/cheongwy/node-scrypt-js
23
(function () {
24
25
var MAX_VALUE = 2147483647;
26
var workerUrl = null;
27
28
//function scrypt(byte[] passwd, byte[] salt, int N, int r, int p, int dkLen)
29
/*
30
* N = Cpu cost
31
* r = Memory cost
32
* p = parallelization cost
33
*
34
*/
35
window.Crypto_scrypt = function (passwd, salt, N, r, p, dkLen, callback) {
36
if (N == 0 || (N & (N - 1)) != 0) throw Error("N must be > 0 and a power of 2");
37
38
if (N > MAX_VALUE / 128 / r) throw Error("Parameter N is too large");
39
if (r > MAX_VALUE / 128 / p) throw Error("Parameter r is too large");
40
41
var PBKDF2_opts = { iterations: 1, hasher: Crypto.SHA256, asBytes: true };
42
43
var B = Crypto.PBKDF2(passwd, salt, p * 128 * r, PBKDF2_opts);
44
45
try {
46
var i = 0;
47
var worksDone = 0;
48
var makeWorker = function () {
49
if (!workerUrl) {
50
var code = '(' + scryptCore.toString() + ')()';
51
var blob;
52
try {
53
blob = new Blob([code], { type: "text/javascript" });
54
} catch (e) {
55
window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
56
blob = new BlobBuilder();
57
blob.append(code);
58
blob = blob.getBlob("text/javascript");
59
}
60
workerUrl = URL.createObjectURL(blob);
61
}
62
var worker = new Worker(workerUrl);
63
worker.onmessage = function (event) {
64
var Bi = event.data[0], Bslice = event.data[1];
65
worksDone++;
66
67
if (i < p) {
68
worker.postMessage([N, r, p, B, i++]);
69
}
70
71
var length = Bslice.length, destPos = Bi * 128 * r, srcPos = 0;
72
while (length--) {
73
B[destPos++] = Bslice[srcPos++];
74
}
75
76
if (worksDone == p) {
77
callback(Crypto.PBKDF2(passwd, B, dkLen, PBKDF2_opts));
78
}
79
};
80
return worker;
81
};
82
var workers = [makeWorker(), makeWorker()];
83
workers[0].postMessage([N, r, p, B, i++]);
84
if (p > 1) {
85
workers[1].postMessage([N, r, p, B, i++]);
86
}
87
} catch (e) {
88
window.setTimeout(function () {
89
scryptCore();
90
callback(Crypto.PBKDF2(passwd, B, dkLen, PBKDF2_opts));
91
}, 0);
92
}
93
94
// using this function to enclose everything needed to create a worker (but also invokable directly for synchronous use)
95
function scryptCore() {
96
var XY = [], V = [];
97
98
if (typeof B === 'undefined') {
99
onmessage = function (event) {
100
var data = event.data;
101
var N = data[0], r = data[1], p = data[2], B = data[3], i = data[4];
102
103
var Bslice = [];
104
arraycopy32(B, i * 128 * r, Bslice, 0, 128 * r);
105
smix(Bslice, 0, r, N, V, XY);
106
107
postMessage([i, Bslice]);
108
};
109
} else {
110
for (var i = 0; i < p; i++) {
111
smix(B, i * 128 * r, r, N, V, XY);
112
}
113
}
114
115
function smix(B, Bi, r, N, V, XY) {
116
var Xi = 0;
117
var Yi = 128 * r;
118
var i;
119
120
arraycopy32(B, Bi, XY, Xi, Yi);
121
122
for (i = 0; i < N; i++) {
123
arraycopy32(XY, Xi, V, i * Yi, Yi);
124
blockmix_salsa8(XY, Xi, Yi, r);
125
}
126
127
for (i = 0; i < N; i++) {
128
var j = integerify(XY, Xi, r) & (N - 1);
129
blockxor(V, j * Yi, XY, Xi, Yi);
130
blockmix_salsa8(XY, Xi, Yi, r);
131
}
132
133
arraycopy32(XY, Xi, B, Bi, Yi);
134
}
135
136
function blockmix_salsa8(BY, Bi, Yi, r) {
137
var X = [];
138
var i;
139
140
arraycopy32(BY, Bi + (2 * r - 1) * 64, X, 0, 64);
141
142
for (i = 0; i < 2 * r; i++) {
143
blockxor(BY, i * 64, X, 0, 64);
144
salsa20_8(X);
145
arraycopy32(X, 0, BY, Yi + (i * 64), 64);
146
}
147
148
for (i = 0; i < r; i++) {
149
arraycopy32(BY, Yi + (i * 2) * 64, BY, Bi + (i * 64), 64);
150
}
151
152
for (i = 0; i < r; i++) {
153
arraycopy32(BY, Yi + (i * 2 + 1) * 64, BY, Bi + (i + r) * 64, 64);
154
}
155
}
156
157
function R(a, b) {
158
return (a << b) | (a >>> (32 - b));
159
}
160
161
function salsa20_8(B) {
162
var B32 = new Array(32);
163
var x = new Array(32);
164
var i;
165
166
for (i = 0; i < 16; i++) {
167
B32[i] = (B[i * 4 + 0] & 0xff) << 0;
168
B32[i] |= (B[i * 4 + 1] & 0xff) << 8;
169
B32[i] |= (B[i * 4 + 2] & 0xff) << 16;
170
B32[i] |= (B[i * 4 + 3] & 0xff) << 24;
171
}
172
173
arraycopy(B32, 0, x, 0, 16);
174
175
for (i = 8; i > 0; i -= 2) {
176
x[4] ^= R(x[0] + x[12], 7); x[8] ^= R(x[4] + x[0], 9);
177
x[12] ^= R(x[8] + x[4], 13); x[0] ^= R(x[12] + x[8], 18);
178
x[9] ^= R(x[5] + x[1], 7); x[13] ^= R(x[9] + x[5], 9);
179
x[1] ^= R(x[13] + x[9], 13); x[5] ^= R(x[1] + x[13], 18);
180
x[14] ^= R(x[10] + x[6], 7); x[2] ^= R(x[14] + x[10], 9);
181
x[6] ^= R(x[2] + x[14], 13); x[10] ^= R(x[6] + x[2], 18);
182
x[3] ^= R(x[15] + x[11], 7); x[7] ^= R(x[3] + x[15], 9);
183
x[11] ^= R(x[7] + x[3], 13); x[15] ^= R(x[11] + x[7], 18);
184
x[1] ^= R(x[0] + x[3], 7); x[2] ^= R(x[1] + x[0], 9);
185
x[3] ^= R(x[2] + x[1], 13); x[0] ^= R(x[3] + x[2], 18);
186
x[6] ^= R(x[5] + x[4], 7); x[7] ^= R(x[6] + x[5], 9);
187
x[4] ^= R(x[7] + x[6], 13); x[5] ^= R(x[4] + x[7], 18);
188
x[11] ^= R(x[10] + x[9], 7); x[8] ^= R(x[11] + x[10], 9);
189
x[9] ^= R(x[8] + x[11], 13); x[10] ^= R(x[9] + x[8], 18);
190
x[12] ^= R(x[15] + x[14], 7); x[13] ^= R(x[12] + x[15], 9);
191
x[14] ^= R(x[13] + x[12], 13); x[15] ^= R(x[14] + x[13], 18);
192
}
193
194
for (i = 0; i < 16; ++i) B32[i] = x[i] + B32[i];
195
196
for (i = 0; i < 16; i++) {
197
var bi = i * 4;
198
B[bi + 0] = (B32[i] >> 0 & 0xff);
199
B[bi + 1] = (B32[i] >> 8 & 0xff);
200
B[bi + 2] = (B32[i] >> 16 & 0xff);
201
B[bi + 3] = (B32[i] >> 24 & 0xff);
202
}
203
}
204
205
function blockxor(S, Si, D, Di, len) {
206
var i = len >> 6;
207
while (i--) {
208
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
209
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
210
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
211
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
212
213
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
214
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
215
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
216
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
217
218
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
219
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
220
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
221
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
222
223
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
224
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
225
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
226
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
227
228
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
229
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
230
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
231
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
232
233
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
234
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
235
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
236
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
237
238
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
239
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
240
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
241
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
242
243
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
244
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
245
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
246
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
247
}
248
}
249
250
function integerify(B, bi, r) {
251
var n;
252
253
bi += (2 * r - 1) * 64;
254
255
n = (B[bi + 0] & 0xff) << 0;
256
n |= (B[bi + 1] & 0xff) << 8;
257
n |= (B[bi + 2] & 0xff) << 16;
258
n |= (B[bi + 3] & 0xff) << 24;
259
260
return n;
261
}
262
263
function arraycopy(src, srcPos, dest, destPos, length) {
264
while (length--) {
265
dest[destPos++] = src[srcPos++];
266
}
267
}
268
269
function arraycopy32(src, srcPos, dest, destPos, length) {
270
var i = length >> 5;
271
while (i--) {
272
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
273
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
274
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
275
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
276
277
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
278
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
279
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
280
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
281
282
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
283
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
284
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
285
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
286
287
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
288
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
289
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
290
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
291
}
292
}
293
} // scryptCore
294
}; // window.Crypto_scrypt
295
})();
296