Download src/password.ts from ghuser1/pl: direct link, hf CLI and curl.
- Browser
- Download file 1.08 kB
-
https://huggingface.co/spaces/ghuser1/pl/resolve/main/src/password.ts
- Command line
-
hf download hf://spaces/ghuser1/pl/src/password.ts
-
curl -L -o password.ts https://huggingface.co/spaces/ghuser1/pl/resolve/main/src/password.ts
1.08 kB
| import { timingSafeEqual, randomBytes, scryptSync } from 'node:crypto'; | |
| const PREFIX = 'scrypt'; | |
| const KEY_LENGTH = 64; | |
| function hashWithSalt(password: string, salt: string): string { | |
| return scryptSync(password, salt, KEY_LENGTH).toString('base64'); | |
| } | |
| export function isPasswordHash(value: string): boolean { | |
| return value.startsWith(`${PREFIX}$`); | |
| } | |
| export function hashPassword(password: string): string { | |
| const salt = randomBytes(16).toString('base64'); | |
| const hash = hashWithSalt(password, salt); | |
| return `${PREFIX}$${salt}$${hash}`; | |
| } | |
| export function verifyPassword(password: string, stored: string): boolean { | |
| if (!stored) return true; | |
| if (!isPasswordHash(stored)) return password === stored; | |
| const [, salt, expected] = stored.split('$'); | |
| if (!salt || !expected) return false; | |
| const actual = hashWithSalt(password, salt); | |
| const expectedBytes = Buffer.from(expected, 'base64'); | |
| const actualBytes = Buffer.from(actual, 'base64'); | |
| if (expectedBytes.length !== actualBytes.length) return false; | |
| return timingSafeEqual(expectedBytes, actualBytes); | |
| } | |