* feature(auth): replace clerk.com with custom auth * minor fixes * remove notification preferences * decrease live events interval fix(api): cookies.. # Conflicts: # .gitignore # apps/api/src/index.ts # apps/dashboard/src/app/providers.tsx # packages/trpc/src/trpc.ts
67 lines
1.7 KiB
TypeScript
67 lines
1.7 KiB
TypeScript
import {
|
|
createHash as cryptoCreateHash,
|
|
randomBytes,
|
|
scrypt,
|
|
timingSafeEqual,
|
|
} from 'node:crypto';
|
|
|
|
export function generateSalt() {
|
|
return randomBytes(16).toString('hex');
|
|
}
|
|
|
|
/**
|
|
* Has a password or a secret with a password hashing algorithm (scrypt)
|
|
* @param {string} password
|
|
* @returns {string} The salt+hash
|
|
*/
|
|
export async function hashPassword(
|
|
password: string,
|
|
keyLength = 32,
|
|
): Promise<string> {
|
|
return new Promise((resolve, reject) => {
|
|
// generate random 16 bytes long salt - recommended by NodeJS Docs
|
|
const salt = generateSalt();
|
|
scrypt(password, salt, keyLength, (err, derivedKey) => {
|
|
if (err) reject(err);
|
|
// derivedKey is of type Buffer
|
|
resolve(`${salt}.${derivedKey.toString('hex')}`);
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Compare a plain text password with a salt+hash password
|
|
* @param {string} password The plain text password
|
|
* @param {string} hash The hash+salt to check against
|
|
* @returns {boolean}
|
|
*/
|
|
export async function verifyPassword(
|
|
password: string,
|
|
hash: string,
|
|
keyLength = 32,
|
|
): Promise<boolean> {
|
|
return new Promise((resolve, reject) => {
|
|
const [salt, hashKey] = hash.split('.');
|
|
// we need to pass buffer values to timingSafeEqual
|
|
const hashKeyBuff = Buffer.from(hashKey!, 'hex');
|
|
scrypt(password, salt!, keyLength, (err, derivedKey) => {
|
|
if (err) {
|
|
reject(err);
|
|
}
|
|
// compare the new supplied password with the hashed password using timeSafeEqual
|
|
resolve(
|
|
timingSafeEqual(
|
|
new Uint8Array(hashKeyBuff),
|
|
new Uint8Array(derivedKey),
|
|
),
|
|
);
|
|
});
|
|
});
|
|
}
|
|
|
|
export function createHash(data: string, len: number) {
|
|
return cryptoCreateHash('shake256', { outputLength: len })
|
|
.update(data)
|
|
.digest('hex');
|
|
}
|