mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-15 19:57:07 +08:00
31 lines
1.1 KiB
TypeScript
31 lines
1.1 KiB
TypeScript
import { randomBytes, scrypt, timingSafeEqual } from 'crypto';
|
|
import { promisify } from 'util';
|
|
|
|
const deriveKey = promisify(scrypt);
|
|
const HASH_PREFIX = 'scrypt$';
|
|
|
|
export async function hashPassword(password: string): Promise<string> {
|
|
const salt = randomBytes(16).toString('hex');
|
|
const key = (await deriveKey(password, salt, 64)) as Buffer;
|
|
return `${HASH_PREFIX}${salt}$${key.toString('hex')}`;
|
|
}
|
|
|
|
export function isPasswordHash(password: string): boolean {
|
|
return /^scrypt\$[a-f0-9]{32}\$[a-f0-9]{128}$/.test(password);
|
|
}
|
|
|
|
export async function verifyPassword(
|
|
password: string,
|
|
stored: string,
|
|
): Promise<boolean> {
|
|
if (!isPasswordHash(stored)) {
|
|
// Existing installations migrate after a successful password check.
|
|
const input = Buffer.from(password);
|
|
const expected = Buffer.from(stored);
|
|
return input.length === expected.length && timingSafeEqual(input, expected);
|
|
}
|
|
const [, salt, hash] = stored.split('$');
|
|
const key = (await deriveKey(password, salt, 64)) as Buffer;
|
|
return timingSafeEqual(key, Buffer.from(hash, 'hex'));
|
|
}
|