Files
sdk/ts_server/classes.password-hasher.ts
T

40 lines
1.3 KiB
TypeScript

import * as plugins from './plugins.js';
const HASH_PREFIX = 'scrypt:v1';
export class PasswordHasher {
public static async hashPassword(passwordArg: string): Promise<string> {
const salt = plugins.crypto.randomBytes(16).toString('base64url');
const key = await this.scrypt(passwordArg, salt);
return `${HASH_PREFIX}:${salt}:${key.toString('base64url')}`;
}
public static async verifyPassword(passwordArg: string, passwordHashArg?: string): Promise<boolean> {
if (!passwordHashArg) {
return false;
}
const [prefix, version, salt, storedKey] = passwordHashArg.split(':');
if (`${prefix}:${version}` !== HASH_PREFIX || !salt || !storedKey) {
return false;
}
const candidate = await this.scrypt(passwordArg, salt);
const stored = Buffer.from(storedKey, 'base64url');
if (candidate.byteLength !== stored.byteLength) {
return false;
}
return plugins.crypto.timingSafeEqual(candidate, stored);
}
private static async scrypt(passwordArg: string, saltArg: string): Promise<Buffer> {
return new Promise((resolve, reject) => {
plugins.crypto.scrypt(passwordArg, saltArg, 64, (error, derivedKey) => {
if (error) {
reject(error);
return;
}
resolve(derivedKey as Buffer);
});
});
}
}