|
1 | | -import JSSHA from 'jssha/dist/sha1'; |
2 | 1 | import { pwnedPasswordRange } from './pwned-password-range.js'; |
3 | 2 |
|
4 | 3 | /** |
@@ -56,13 +55,25 @@ export async function pwnedPassword( |
56 | 55 | userAgent?: string; |
57 | 56 | } = {}, |
58 | 57 | ): Promise<number> { |
59 | | - // @ts-expect-error: JSSHA types are busted |
60 | | - const sha1 = new JSSHA('SHA-1', 'TEXT'); |
61 | | - sha1.update(password); |
62 | | - const hash = sha1.getHash('HEX', { outputUpper: true }); |
63 | | - const prefix = hash.slice(0, 5); |
64 | | - const suffix = hash.slice(5); |
65 | | - |
| 58 | + const [prefix, suffix] = await getPasswordHashParts(password); |
66 | 59 | const range = await pwnedPasswordRange(prefix, options); |
67 | 60 | return range[suffix] || 0; |
68 | 61 | } |
| 62 | + |
| 63 | +async function getPasswordHashParts(password: string) { |
| 64 | + if (typeof crypto === 'object' && crypto.subtle) { |
| 65 | + const msgUint8 = new TextEncoder().encode(password); |
| 66 | + const hashBuffer = await crypto.subtle.digest('SHA-1', msgUint8); |
| 67 | + const hashArray = Array.from(new Uint8Array(hashBuffer)); |
| 68 | + const hashHex = hashArray |
| 69 | + .map((byte) => byte.toString(16).padStart(2, '0')) |
| 70 | + .join('') |
| 71 | + .toUpperCase(); |
| 72 | + |
| 73 | + return [hashHex.slice(0, 5), hashHex.slice(5)] as const; |
| 74 | + /* c8 ignore start */ |
| 75 | + } |
| 76 | + |
| 77 | + throw new Error('The Web Crypto API is not available in this environment.'); |
| 78 | +} |
| 79 | +/* c8 ignore end */ |
0 commit comments