feat(sdk): add initial browser and server authentication SDK exports
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
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);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user