Skip to content

Commit ca98810

Browse files
committed
perf: another tiny improvement in scrypt
1 parent 59fda2c commit ca98810

File tree

1 file changed

+12
-7
lines changed

1 file changed

+12
-7
lines changed

src/scrypt.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ function scryptInit(password: KDFInput, salt: KDFInput, _opts?: ScryptOpts) {
146146
const B32 = u32(B);
147147
// Re-used between parallel iterations. Array(iterations) of B
148148
const V = u32(new Uint8Array(blockSize * N));
149+
const V0 = new Uint32Array(V.buffer, V.byteOffset, blockSize32);
149150
const tmp = u32(new Uint8Array(blockSize));
150151
let blockMixCb = () => {};
151152
if (onProgress) {
@@ -160,7 +161,7 @@ function scryptInit(password: KDFInput, salt: KDFInput, _opts?: ScryptOpts) {
160161
onProgress(blockMixCnt / totalBlockMix);
161162
};
162163
}
163-
return { N, r, p, dkLen, blockSize32, V, B32, B, tmp, blockMixCb, asyncTick };
164+
return { N, r, p, dkLen, blockSize32, V, V0, B32, B, tmp, blockMixCb, asyncTick };
164165
}
165166

166167
function scryptOutput(
@@ -181,15 +182,16 @@ function scryptOutput(
181182
* scrypt('password', 'salt', { N: 2**18, r: 8, p: 1, dkLen: 32 });
182183
*/
183184
export function scrypt(password: KDFInput, salt: KDFInput, opts: ScryptOpts): Uint8Array {
184-
const { N, r, p, dkLen, blockSize32, V, B32, B, tmp, blockMixCb } = scryptInit(
185+
const { N, r, p, dkLen, blockSize32, V, V0, B32, B, tmp, blockMixCb } = scryptInit(
185186
password,
186187
salt,
187188
opts
188189
);
189190
swap32IfBE(B32);
190191
for (let pi = 0; pi < p; pi++) {
191192
const Pi = blockSize32 * pi;
192-
for (let i = 0; i < blockSize32; i++) V[i] = B32[Pi + i]; // V[0] = B[i]
193+
const B32pi = new Uint32Array(B.buffer, B.byteOffset + Pi * 4, blockSize32);
194+
V0.set(B32pi); // V[0] = B[i]
193195
for (let i = 0, pos = 0; i < N - 1; i++) {
194196
BlockMix(V, pos, V, (pos += blockSize32), r); // V[i] = BlockMix(V[i-1]);
195197
blockMixCb();
@@ -200,7 +202,8 @@ export function scrypt(password: KDFInput, salt: KDFInput, opts: ScryptOpts): Ui
200202
// First u32 of the last 64-byte block (u32 is LE)
201203
// & (N - 1) is % N as N is a power of 2, N & (N - 1) = 0 is checked above; >>> 0 for unsigned, input fits in u32
202204
const j = (B32[Pi + blockSize32 - 16] & (N - 1)) >>> 0; // j = Integrify(X) % iterations
203-
for (let k = 0; k < blockSize32; k++) tmp[k] = B32[Pi + k] ^ V[j * blockSize32 + k]; // tmp = B ^ V[j]
205+
tmp.set(B32pi); // tmp = B
206+
for (let k = 0; k < blockSize32; k ++) tmp[k] ^= V[j * blockSize32 + k]; // tmp = B ^ V[j]
204207
BlockMix(tmp, 0, B32, Pi, r); // B = BlockMix(B ^ V[j])
205208
blockMixCb();
206209
}
@@ -219,15 +222,16 @@ export async function scryptAsync(
219222
salt: KDFInput,
220223
opts: ScryptOpts
221224
): Promise<Uint8Array> {
222-
const { N, r, p, dkLen, blockSize32, V, B32, B, tmp, blockMixCb, asyncTick } = scryptInit(
225+
const { N, r, p, dkLen, blockSize32, V, V0, B32, B, tmp, blockMixCb, asyncTick } = scryptInit(
223226
password,
224227
salt,
225228
opts
226229
);
227230
swap32IfBE(B32);
228231
for (let pi = 0; pi < p; pi++) {
229232
const Pi = blockSize32 * pi;
230-
for (let i = 0; i < blockSize32; i++) V[i] = B32[Pi + i]; // V[0] = B[i]
233+
const B32pi = new Uint32Array(B.buffer, B.byteOffset + Pi * 4, blockSize32);
234+
V0.set(B32pi); // V[0] = B[i]
231235
let pos = 0;
232236
await asyncLoop(N - 1, asyncTick, () => {
233237
BlockMix(V, pos, V, (pos += blockSize32), r); // V[i] = BlockMix(V[i-1]);
@@ -239,7 +243,8 @@ export async function scryptAsync(
239243
// First u32 of the last 64-byte block (u32 is LE)
240244
// & (N - 1) is % N as N is a power of 2, N & (N - 1) = 0 is checked above; >>> 0 for unsigned, input fits in u32
241245
const j = (B32[Pi + blockSize32 - 16] & (N - 1)) >>> 0; // j = Integrify(X) % iterations
242-
for (let k = 0; k < blockSize32; k++) tmp[k] = B32[Pi + k] ^ V[j * blockSize32 + k]; // tmp = B ^ V[j]
246+
tmp.set(B32pi); // tmp = B
247+
for (let k = 0; k < blockSize32; k ++) tmp[k] ^= V[j * blockSize32 + k]; // tmp = B ^ V[j]
243248
BlockMix(tmp, 0, B32, Pi, r); // B = BlockMix(B ^ V[j])
244249
blockMixCb();
245250
});

0 commit comments

Comments
 (0)