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

Commit

Permalink
chore(user_passwords): temporarily disable hashing to work around was…
Browse files Browse the repository at this point in the history
…m bug
  • Loading branch information
NathanFlurry committed Aug 30, 2024
1 parent 5067f78 commit ad4b894
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 134 deletions.
172 changes: 86 additions & 86 deletions modules/user_passwords/utils/argon2.ts
Original file line number Diff line number Diff line change
@@ -1,86 +1,86 @@
import {
hash as hashArgon2,
Argon2Params,
Argon2Version,
Argon2Algorithm,
} from "https://deno.land/x/[email protected]/mod.ts";
import { generateSalt } from "./common.ts";
import { timingSafeEqual } from "https://deno.land/[email protected]/crypto/timing_safe_equal.ts";
import base64 from "https://deno.land/x/[email protected]/src/base64.js";


// OWASP recommended defaults:
// https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#argon2id
const argon2Defaults: Argon2Params = {
algorithm: "Argon2id",
version: 19,
tCost: 2, // 3 iterations
mCost: 19 * 1024, // 19MiB of memory
pCost: 1, // 1 thread

secret: undefined,
outputLength: 32,
};

export function createHash(password: string) {
const salt = generateSalt();
const passwordBuffer = new TextEncoder().encode(password);
const hash = hashArgon2(passwordBuffer, salt, argon2Defaults);
return packDigest(hash, salt, argon2Defaults);
}

export function hashMatches(guess: string, digest: string) {
const { hash, salt, params } = unpackDigest(digest);
const guessBuffer = new TextEncoder().encode(guess);

const hashGuess = hashArgon2(guessBuffer, salt, params);

return timingSafeEqual(hashGuess, hash);
}

function packDigest(hash: ArrayBuffer, salt: ArrayBuffer, params: Argon2Params) {
const headerPart = `$${params.algorithm.toLowerCase()}$v=${params.version}$`;
const paramPart = `m=${params.mCost},t=${params.tCost},p=${params.pCost}`;

const saltBase64 = base64.fromArrayBuffer(salt);
const hashBase64 = base64.fromArrayBuffer(hash);

return `${headerPart}${paramPart}$${saltBase64}$${hashBase64}`;
}

const algorithmMap: Record<string, Argon2Algorithm> = {
"argon2i": "Argon2i",
"argon2d": "Argon2d",
"argon2id": "Argon2id",
};

function unpackDigest(digest: string): { hash: ArrayBuffer, salt: ArrayBuffer, params: Argon2Params } {
const [, algorithmName, versionStr, params, saltStr, hashStr] = digest.split("$");

const algorithm = algorithmMap[algorithmName];
const version = parseInt(versionStr.match(/v=(\d+)/)![1]);

const mCost = parseInt(params.match(/m=(\d+)/)![1]);
const tCost = parseInt(params.match(/t=(\d+)/)![1]);
const pCost = parseInt(params.match(/p=(\d+)/)![1]);

const salt = base64.toArrayBuffer(saltStr);
const hash = base64.toArrayBuffer(hashStr);


if (!algorithm || !version || !mCost || !tCost || !pCost || !salt || !hash) {
throw new Error("Invalid internal hash format");
}

return {
hash,
salt,
params: {
algorithm,
version: version as Argon2Version,
mCost,
tCost,
pCost,
},
};
}
// import {
// hash as hashArgon2,
// Argon2Params,
// Argon2Version,
// Argon2Algorithm,
// } from "https://deno.land/x/[email protected]/mod.ts";
// import { generateSalt } from "./common.ts";
// import { timingSafeEqual } from "https://deno.land/[email protected]/crypto/timing_safe_equal.ts";
// import base64 from "https://deno.land/x/[email protected]/src/base64.js";
//
//
// // OWASP recommended defaults:
// // https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#argon2id
// const argon2Defaults: Argon2Params = {
// algorithm: "Argon2id",
// version: 19,
// tCost: 2, // 3 iterations
// mCost: 19 * 1024, // 19MiB of memory
// pCost: 1, // 1 thread
//
// secret: undefined,
// outputLength: 32,
// };
//
// export function createHash(password: string) {
// const salt = generateSalt();
// const passwordBuffer = new TextEncoder().encode(password);
// const hash = hashArgon2(passwordBuffer, salt, argon2Defaults);
// return packDigest(hash, salt, argon2Defaults);
// }
//
// export function hashMatches(guess: string, digest: string) {
// const { hash, salt, params } = unpackDigest(digest);
// const guessBuffer = new TextEncoder().encode(guess);
//
// const hashGuess = hashArgon2(guessBuffer, salt, params);
//
// return timingSafeEqual(hashGuess, hash);
// }
//
// function packDigest(hash: ArrayBuffer, salt: ArrayBuffer, params: Argon2Params) {
// const headerPart = `$${params.algorithm.toLowerCase()}$v=${params.version}$`;
// const paramPart = `m=${params.mCost},t=${params.tCost},p=${params.pCost}`;
//
// const saltBase64 = base64.fromArrayBuffer(salt);
// const hashBase64 = base64.fromArrayBuffer(hash);
//
// return `${headerPart}${paramPart}$${saltBase64}$${hashBase64}`;
// }
//
// const algorithmMap: Record<string, Argon2Algorithm> = {
// "argon2i": "Argon2i",
// "argon2d": "Argon2d",
// "argon2id": "Argon2id",
// };
//
// function unpackDigest(digest: string): { hash: ArrayBuffer, salt: ArrayBuffer, params: Argon2Params } {
// const [, algorithmName, versionStr, params, saltStr, hashStr] = digest.split("$");
//
// const algorithm = algorithmMap[algorithmName];
// const version = parseInt(versionStr.match(/v=(\d+)/)![1]);
//
// const mCost = parseInt(params.match(/m=(\d+)/)![1]);
// const tCost = parseInt(params.match(/t=(\d+)/)![1]);
// const pCost = parseInt(params.match(/p=(\d+)/)![1]);
//
// const salt = base64.toArrayBuffer(saltStr);
// const hash = base64.toArrayBuffer(hashStr);
//
//
// if (!algorithm || !version || !mCost || !tCost || !pCost || !salt || !hash) {
// throw new Error("Invalid internal hash format");
// }
//
// return {
// hash,
// salt,
// params: {
// algorithm,
// version: version as Argon2Version,
// mCost,
// tCost,
// pCost,
// },
// };
// }
32 changes: 16 additions & 16 deletions modules/user_passwords/utils/bcrypt.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { hash as hashBCrypt, verify, BcryptParams } from "jsr:@blackberry/[email protected]";

// OWASP recommended defaults:
// https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#bcrypt
const bcryptParams: BcryptParams = {
cost: 10,
version: "2b", // 2b is the newest version of the OpenBSD bcrypt standard.
};

export function createHash(password: string) {
return hashBCrypt(new TextEncoder().encode(password), undefined, bcryptParams);
}

export function hashMatches(guess: string, hash: string) {
return verify(new TextEncoder().encode(guess), hash);
}
// import { hash as hashBCrypt, verify, BcryptParams } from "jsr:@blackberry/[email protected]";
//
// // OWASP recommended defaults:
// // https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#bcrypt
// const bcryptParams: BcryptParams = {
// cost: 10,
// version: "2b", // 2b is the newest version of the OpenBSD bcrypt standard.
// };
//
// export function createHash(password: string) {
// return hashBCrypt(new TextEncoder().encode(password), undefined, bcryptParams);
// }
//
// export function hashMatches(guess: string, hash: string) {
// return verify(new TextEncoder().encode(guess), hash);
// }
34 changes: 20 additions & 14 deletions modules/user_passwords/utils/common.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import base64 from "https://deno.land/x/[email protected]/src/base64.js";

import { createHash as hashSCrypt } from "./scrypt.ts";
import { createHash as hashBCrypt } from "./bcrypt.ts";
// import { createHash as hashSCrypt } from "./scrypt.ts";
// import { createHash as hashBCrypt } from "./bcrypt.ts";

import { hashMatches as matchesSCrypt } from "./scrypt.ts";
import { hashMatches as matchesBCrypt } from "./bcrypt.ts";
// import { hashMatches as matchesSCrypt } from "./scrypt.ts";
// import { hashMatches as matchesBCrypt } from "./bcrypt.ts";

import { createHash as hashArgon2 } from "./argon2.ts";
import { hashMatches as matchesArgon2 } from "./argon2.ts";
// import { createHash as hashArgon2 } from "./argon2.ts";
// import { hashMatches as matchesArgon2 } from "./argon2.ts";

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


export function hash(password: string, algorithm: Algorithm = ALGORITHM_DEFAULT) {
export function hash(password: string, algorithm: Algorithm = ALGORITHM_DEFAULT): string {
switch (algorithm) {
case "argon2":
return hashArgon2(password);
// return hashArgon2(password);
throw new Error("Unimplemented");
case "bcrypt":
return hashBCrypt(password);
// return hashBCrypt(password);
throw new Error("Unimplemented");
case "scrypt":
return hashSCrypt(password);
// return hashSCrypt(password);
throw new Error("Unimplemented");
}
}

export function hashMatches(password: string, hash: string, algorithm: Algorithm = ALGORITHM_DEFAULT) {
export function hashMatches(password: string, hash: string, algorithm: Algorithm = ALGORITHM_DEFAULT): boolean {
switch (algorithm) {
case "argon2":
return matchesArgon2(password, hash);
// return matchesArgon2(password, hash);
throw new Error("Unimplemented");
case "bcrypt":
return matchesBCrypt(password, hash);
// return matchesBCrypt(password, hash);
throw new Error("Unimplemented");
case "scrypt":
return matchesSCrypt(password, hash);
// return matchesSCrypt(password, hash);
throw new Error("Unimplemented");
}
}
36 changes: 18 additions & 18 deletions modules/user_passwords/utils/scrypt.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { hash as hashScrypt, verify } from "https://deno.land/x/[email protected]/mod.ts";
import { ScryptParameters } from "https://deno.land/x/[email protected]/lib/format.ts";

// OWASP recommended defaults (listed option 3):
// https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#scrypt
const scryptParams: Partial<ScryptParameters> = {
logN: 15,
r: 8,
p: 3,
};

export function createHash(password: string) {
return hashScrypt(password, scryptParams);
}

export function hashMatches(guess: string, hash: string) {
return verify(guess, hash);
}
// import { hash as hashScrypt, verify } from "https://deno.land/x/[email protected]/mod.ts";
// import { ScryptParameters } from "https://deno.land/x/[email protected]/lib/format.ts";
//
// // OWASP recommended defaults (listed option 3):
// // https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#scrypt
// const scryptParams: Partial<ScryptParameters> = {
// logN: 15,
// r: 8,
// p: 3,
// };
//
// export function createHash(password: string) {
// return hashScrypt(password, scryptParams);
// }
//
// export function hashMatches(guess: string, hash: string) {
// return verify(guess, hash);
// }

0 comments on commit ad4b894

Please sign in to comment.