(password: string)
| 132 | const PASSWORD_HASH = "SHA-256"; |
| 133 | |
| 134 | export async function hashPassword(password: string): Promise<string> { |
| 135 | if (!password) { |
| 136 | throw new Error("Cannot hash empty or null password"); |
| 137 | } |
| 138 | |
| 139 | const salt = crypto.getRandomValues(new Uint8Array(SALT_LENGTH)); |
| 140 | const keyMaterial = await crypto.subtle.importKey( |
| 141 | "raw", |
| 142 | new TextEncoder().encode(password), |
| 143 | "PBKDF2", |
| 144 | false, |
| 145 | ["deriveBits"], |
| 146 | ); |
| 147 | |
| 148 | const derived = await crypto.subtle.deriveBits( |
| 149 | { |
| 150 | name: "PBKDF2", |
| 151 | salt, |
| 152 | iterations: PASSWORD_ITERATIONS, |
| 153 | hash: PASSWORD_HASH, |
| 154 | }, |
| 155 | keyMaterial, |
| 156 | PASSWORD_KEY_LENGTH * 8, |
| 157 | ); |
| 158 | |
| 159 | const result = Buffer.concat([Buffer.from(salt), Buffer.from(derived)]); |
| 160 | |
| 161 | return result.toString("base64"); |
| 162 | } |
| 163 | |
| 164 | export async function verifyPassword( |
| 165 | stored: string, |
no outgoing calls
no test coverage detected