Closed KyleJune closed 3 years ago
Update hashPassword function on the user service to use PBKDF2 for password hashing.
https://github.com/udibo/oauth2_server/blob/main/services/user.ts
I wrote a function for generating salt in the example. It should be moved to the user service so that it's more reusable like the hashPassword function is.
https://github.com/udibo/oauth2_server/blob/main/examples/oak-localstorage/services/user.ts#L4
To be determined, what options should hashPassword have configurable.
Notes:
https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/deriveBits#pbkdf2
import { encode as encodeHex } from "https://deno.land/std@0.114.0/encoding/hex.ts"; function generateSalt(): Uint8Array { return window.crypto.getRandomValues(new Uint8Array(16)); } /* Get some key material to use as input to the deriveBits method. The key material is a password supplied by the user. */ function getKeyMaterial(password: string) { const enc = new TextEncoder(); return window.crypto.subtle.importKey( "raw", enc.encode(password), "PBKDF2", false, ["deriveBits", "deriveKey"], ); } /* Derive some bits from a password supplied by the user. */ async function getDerivedBits( password: string, salt: Uint8Array, ): Promise<[Uint8Array, number]> { const keyMaterial = await getKeyMaterial(password); const derivedBits = await window.crypto.subtle.deriveBits( { "name": "PBKDF2", salt, "iterations": 100000, "hash": "SHA-256", }, keyMaterial, 256, ); const buffer = new Uint8Array(derivedBits, 0, 32); return [buffer, derivedBits.byteLength]; } const salt = generateSalt(); const saltText = (new TextDecoder()).decode(encodeHex(salt)); console.log("salt: ", saltText); const [buffer, length] = await getDerivedBits("hunter2", salt); console.log(buffer); console.log(length); const hashed = (new TextDecoder()).decode(encodeHex(new Uint8Array(buffer))); console.log(hashed); // current SHA-256 hashPassword function async function hashPassword(password: string, salt?: string): Promise<string> { const data = (new TextEncoder()).encode( password + (salt ? `:${salt}` : ""), ); const buffer = await crypto.subtle.digest("SHA-256", data); return (new TextDecoder()).decode(encodeHex(new Uint8Array(buffer))); } console.log(await hashPassword("hunter2", saltText));
Here is an example using deriveKey instead of deriveBits.
https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/deriveKey#pbkdf2_2
Here is an issue on deno tracking supported algorithms.
https://github.com/denoland/deno/issues/11690
Update hashPassword function on the user service to use PBKDF2 for password hashing.
https://github.com/udibo/oauth2_server/blob/main/services/user.ts
I wrote a function for generating salt in the example. It should be moved to the user service so that it's more reusable like the hashPassword function is.
https://github.com/udibo/oauth2_server/blob/main/examples/oak-localstorage/services/user.ts#L4
To be determined, what options should hashPassword have configurable.
Notes:
https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/deriveBits#pbkdf2