Skip to content
This repository was archived by the owner on Sep 17, 2024. It is now read-only.

Commit 083974e

Browse files
committed
chore(user_passwords): temporarily disable hashing to work around wasm bug
1 parent 7b1fdce commit 083974e

File tree

4 files changed

+140
-134
lines changed

4 files changed

+140
-134
lines changed

Diff for: modules/user_passwords/utils/argon2.ts

+86-86
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,86 @@
1-
import {
2-
hash as hashArgon2,
3-
Argon2Params,
4-
Argon2Version,
5-
Argon2Algorithm,
6-
} from "https://deno.land/x/[email protected]/mod.ts";
7-
import { generateSalt } from "./common.ts";
8-
import { timingSafeEqual } from "https://deno.land/[email protected]/crypto/timing_safe_equal.ts";
9-
import base64 from "https://deno.land/x/[email protected]/src/base64.js";
10-
11-
12-
// OWASP recommended defaults:
13-
// https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#argon2id
14-
const argon2Defaults: Argon2Params = {
15-
algorithm: "Argon2id",
16-
version: 19,
17-
tCost: 2, // 3 iterations
18-
mCost: 19 * 1024, // 19MiB of memory
19-
pCost: 1, // 1 thread
20-
21-
secret: undefined,
22-
outputLength: 32,
23-
};
24-
25-
export function createHash(password: string) {
26-
const salt = generateSalt();
27-
const passwordBuffer = new TextEncoder().encode(password);
28-
const hash = hashArgon2(passwordBuffer, salt, argon2Defaults);
29-
return packDigest(hash, salt, argon2Defaults);
30-
}
31-
32-
export function hashMatches(guess: string, digest: string) {
33-
const { hash, salt, params } = unpackDigest(digest);
34-
const guessBuffer = new TextEncoder().encode(guess);
35-
36-
const hashGuess = hashArgon2(guessBuffer, salt, params);
37-
38-
return timingSafeEqual(hashGuess, hash);
39-
}
40-
41-
function packDigest(hash: ArrayBuffer, salt: ArrayBuffer, params: Argon2Params) {
42-
const headerPart = `$${params.algorithm.toLowerCase()}$v=${params.version}$`;
43-
const paramPart = `m=${params.mCost},t=${params.tCost},p=${params.pCost}`;
44-
45-
const saltBase64 = base64.fromArrayBuffer(salt);
46-
const hashBase64 = base64.fromArrayBuffer(hash);
47-
48-
return `${headerPart}${paramPart}$${saltBase64}$${hashBase64}`;
49-
}
50-
51-
const algorithmMap: Record<string, Argon2Algorithm> = {
52-
"argon2i": "Argon2i",
53-
"argon2d": "Argon2d",
54-
"argon2id": "Argon2id",
55-
};
56-
57-
function unpackDigest(digest: string): { hash: ArrayBuffer, salt: ArrayBuffer, params: Argon2Params } {
58-
const [, algorithmName, versionStr, params, saltStr, hashStr] = digest.split("$");
59-
60-
const algorithm = algorithmMap[algorithmName];
61-
const version = parseInt(versionStr.match(/v=(\d+)/)![1]);
62-
63-
const mCost = parseInt(params.match(/m=(\d+)/)![1]);
64-
const tCost = parseInt(params.match(/t=(\d+)/)![1]);
65-
const pCost = parseInt(params.match(/p=(\d+)/)![1]);
66-
67-
const salt = base64.toArrayBuffer(saltStr);
68-
const hash = base64.toArrayBuffer(hashStr);
69-
70-
71-
if (!algorithm || !version || !mCost || !tCost || !pCost || !salt || !hash) {
72-
throw new Error("Invalid internal hash format");
73-
}
74-
75-
return {
76-
hash,
77-
salt,
78-
params: {
79-
algorithm,
80-
version: version as Argon2Version,
81-
mCost,
82-
tCost,
83-
pCost,
84-
},
85-
};
86-
}
1+
// import {
2+
// hash as hashArgon2,
3+
// Argon2Params,
4+
// Argon2Version,
5+
// Argon2Algorithm,
6+
// } from "https://deno.land/x/[email protected]/mod.ts";
7+
// import { generateSalt } from "./common.ts";
8+
// import { timingSafeEqual } from "https://deno.land/[email protected]/crypto/timing_safe_equal.ts";
9+
// import base64 from "https://deno.land/x/[email protected]/src/base64.js";
10+
//
11+
//
12+
// // OWASP recommended defaults:
13+
// // https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#argon2id
14+
// const argon2Defaults: Argon2Params = {
15+
// algorithm: "Argon2id",
16+
// version: 19,
17+
// tCost: 2, // 3 iterations
18+
// mCost: 19 * 1024, // 19MiB of memory
19+
// pCost: 1, // 1 thread
20+
//
21+
// secret: undefined,
22+
// outputLength: 32,
23+
// };
24+
//
25+
// export function createHash(password: string) {
26+
// const salt = generateSalt();
27+
// const passwordBuffer = new TextEncoder().encode(password);
28+
// const hash = hashArgon2(passwordBuffer, salt, argon2Defaults);
29+
// return packDigest(hash, salt, argon2Defaults);
30+
// }
31+
//
32+
// export function hashMatches(guess: string, digest: string) {
33+
// const { hash, salt, params } = unpackDigest(digest);
34+
// const guessBuffer = new TextEncoder().encode(guess);
35+
//
36+
// const hashGuess = hashArgon2(guessBuffer, salt, params);
37+
//
38+
// return timingSafeEqual(hashGuess, hash);
39+
// }
40+
//
41+
// function packDigest(hash: ArrayBuffer, salt: ArrayBuffer, params: Argon2Params) {
42+
// const headerPart = `$${params.algorithm.toLowerCase()}$v=${params.version}$`;
43+
// const paramPart = `m=${params.mCost},t=${params.tCost},p=${params.pCost}`;
44+
//
45+
// const saltBase64 = base64.fromArrayBuffer(salt);
46+
// const hashBase64 = base64.fromArrayBuffer(hash);
47+
//
48+
// return `${headerPart}${paramPart}$${saltBase64}$${hashBase64}`;
49+
// }
50+
//
51+
// const algorithmMap: Record<string, Argon2Algorithm> = {
52+
// "argon2i": "Argon2i",
53+
// "argon2d": "Argon2d",
54+
// "argon2id": "Argon2id",
55+
// };
56+
//
57+
// function unpackDigest(digest: string): { hash: ArrayBuffer, salt: ArrayBuffer, params: Argon2Params } {
58+
// const [, algorithmName, versionStr, params, saltStr, hashStr] = digest.split("$");
59+
//
60+
// const algorithm = algorithmMap[algorithmName];
61+
// const version = parseInt(versionStr.match(/v=(\d+)/)![1]);
62+
//
63+
// const mCost = parseInt(params.match(/m=(\d+)/)![1]);
64+
// const tCost = parseInt(params.match(/t=(\d+)/)![1]);
65+
// const pCost = parseInt(params.match(/p=(\d+)/)![1]);
66+
//
67+
// const salt = base64.toArrayBuffer(saltStr);
68+
// const hash = base64.toArrayBuffer(hashStr);
69+
//
70+
//
71+
// if (!algorithm || !version || !mCost || !tCost || !pCost || !salt || !hash) {
72+
// throw new Error("Invalid internal hash format");
73+
// }
74+
//
75+
// return {
76+
// hash,
77+
// salt,
78+
// params: {
79+
// algorithm,
80+
// version: version as Argon2Version,
81+
// mCost,
82+
// tCost,
83+
// pCost,
84+
// },
85+
// };
86+
// }

Diff for: modules/user_passwords/utils/bcrypt.ts

+16-16
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
import { hash as hashBCrypt, verify, BcryptParams } from "jsr:@blackberry/[email protected]";
2-
3-
// OWASP recommended defaults:
4-
// https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#bcrypt
5-
const bcryptParams: BcryptParams = {
6-
cost: 10,
7-
version: "2b", // 2b is the newest version of the OpenBSD bcrypt standard.
8-
};
9-
10-
export function createHash(password: string) {
11-
return hashBCrypt(new TextEncoder().encode(password), undefined, bcryptParams);
12-
}
13-
14-
export function hashMatches(guess: string, hash: string) {
15-
return verify(new TextEncoder().encode(guess), hash);
16-
}
1+
// import { hash as hashBCrypt, verify, BcryptParams } from "jsr:@blackberry/[email protected]";
2+
//
3+
// // OWASP recommended defaults:
4+
// // https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#bcrypt
5+
// const bcryptParams: BcryptParams = {
6+
// cost: 10,
7+
// version: "2b", // 2b is the newest version of the OpenBSD bcrypt standard.
8+
// };
9+
//
10+
// export function createHash(password: string) {
11+
// return hashBCrypt(new TextEncoder().encode(password), undefined, bcryptParams);
12+
// }
13+
//
14+
// export function hashMatches(guess: string, hash: string) {
15+
// return verify(new TextEncoder().encode(guess), hash);
16+
// }

Diff for: modules/user_passwords/utils/common.ts

+20-14
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import base64 from "https://deno.land/x/[email protected]/src/base64.js";
22

3-
import { createHash as hashSCrypt } from "./scrypt.ts";
4-
import { createHash as hashBCrypt } from "./bcrypt.ts";
3+
// import { createHash as hashSCrypt } from "./scrypt.ts";
4+
// import { createHash as hashBCrypt } from "./bcrypt.ts";
55

6-
import { hashMatches as matchesSCrypt } from "./scrypt.ts";
7-
import { hashMatches as matchesBCrypt } from "./bcrypt.ts";
6+
// import { hashMatches as matchesSCrypt } from "./scrypt.ts";
7+
// import { hashMatches as matchesBCrypt } from "./bcrypt.ts";
88

9-
import { createHash as hashArgon2 } from "./argon2.ts";
10-
import { hashMatches as matchesArgon2 } from "./argon2.ts";
9+
// import { createHash as hashArgon2 } from "./argon2.ts";
10+
// import { hashMatches as matchesArgon2 } from "./argon2.ts";
1111

1212
export function toBase64(buffer: ArrayBufferLike) {
1313
return base64.fromArrayBuffer(new Uint8Array(buffer));
@@ -57,24 +57,30 @@ export type Algorithm = "bcrypt" | "scrypt" | "argon2";
5757
export const ALGORITHM_DEFAULT: Algorithm = "bcrypt";
5858

5959

60-
export function hash(password: string, algorithm: Algorithm = ALGORITHM_DEFAULT) {
60+
export function hash(password: string, algorithm: Algorithm = ALGORITHM_DEFAULT): string {
6161
switch (algorithm) {
6262
case "argon2":
63-
return hashArgon2(password);
63+
// return hashArgon2(password);
64+
throw new Error("Unimplemented");
6465
case "bcrypt":
65-
return hashBCrypt(password);
66+
// return hashBCrypt(password);
67+
throw new Error("Unimplemented");
6668
case "scrypt":
67-
return hashSCrypt(password);
69+
// return hashSCrypt(password);
70+
throw new Error("Unimplemented");
6871
}
6972
}
7073

71-
export function hashMatches(password: string, hash: string, algorithm: Algorithm = ALGORITHM_DEFAULT) {
74+
export function hashMatches(password: string, hash: string, algorithm: Algorithm = ALGORITHM_DEFAULT): boolean {
7275
switch (algorithm) {
7376
case "argon2":
74-
return matchesArgon2(password, hash);
77+
// return matchesArgon2(password, hash);
78+
throw new Error("Unimplemented");
7579
case "bcrypt":
76-
return matchesBCrypt(password, hash);
80+
// return matchesBCrypt(password, hash);
81+
throw new Error("Unimplemented");
7782
case "scrypt":
78-
return matchesSCrypt(password, hash);
83+
// return matchesSCrypt(password, hash);
84+
throw new Error("Unimplemented");
7985
}
8086
}

Diff for: modules/user_passwords/utils/scrypt.ts

+18-18
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
import { hash as hashScrypt, verify } from "https://deno.land/x/[email protected]/mod.ts";
2-
import { ScryptParameters } from "https://deno.land/x/[email protected]/lib/format.ts";
3-
4-
// OWASP recommended defaults (listed option 3):
5-
// https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#scrypt
6-
const scryptParams: Partial<ScryptParameters> = {
7-
logN: 15,
8-
r: 8,
9-
p: 3,
10-
};
11-
12-
export function createHash(password: string) {
13-
return hashScrypt(password, scryptParams);
14-
}
15-
16-
export function hashMatches(guess: string, hash: string) {
17-
return verify(guess, hash);
18-
}
1+
// import { hash as hashScrypt, verify } from "https://deno.land/x/[email protected]/mod.ts";
2+
// import { ScryptParameters } from "https://deno.land/x/[email protected]/lib/format.ts";
3+
//
4+
// // OWASP recommended defaults (listed option 3):
5+
// // https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#scrypt
6+
// const scryptParams: Partial<ScryptParameters> = {
7+
// logN: 15,
8+
// r: 8,
9+
// p: 3,
10+
// };
11+
//
12+
// export function createHash(password: string) {
13+
// return hashScrypt(password, scryptParams);
14+
// }
15+
//
16+
// export function hashMatches(guess: string, hash: string) {
17+
// return verify(guess, hash);
18+
// }

0 commit comments

Comments
 (0)