56 行
1.3 KiB
JavaScript
56 行
1.3 KiB
JavaScript
const crypto = require("node:crypto");
|
|
const bcrypt = require("bcryptjs");
|
|
|
|
function sha256Hex(input) {
|
|
return crypto.createHash("sha256").update(input).digest("hex");
|
|
}
|
|
|
|
function generateSixDigitCode() {
|
|
return String(crypto.randomInt(0, 1_000_000)).padStart(6, "0");
|
|
}
|
|
|
|
function hashAuthCode({ employeeId, code, purpose, pepper }) {
|
|
return crypto
|
|
.createHmac("sha256", pepper)
|
|
.update(`${purpose}:${employeeId}:${code}`)
|
|
.digest("hex");
|
|
}
|
|
|
|
function timingSafeEqualHex(left, right) {
|
|
if (
|
|
typeof left !== "string" ||
|
|
typeof right !== "string" ||
|
|
!/^[0-9a-f]+$/i.test(left) ||
|
|
!/^[0-9a-f]+$/i.test(right)
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
const leftBuffer = Buffer.from(left, "hex");
|
|
const rightBuffer = Buffer.from(right, "hex");
|
|
return leftBuffer.length === rightBuffer.length && crypto.timingSafeEqual(leftBuffer, rightBuffer);
|
|
}
|
|
|
|
function randomRefreshToken() {
|
|
return crypto.randomBytes(32).toString("base64url");
|
|
}
|
|
|
|
async function hashPassword(password) {
|
|
const saltRounds = 12;
|
|
return bcrypt.hash(password, saltRounds);
|
|
}
|
|
|
|
async function verifyPassword(password, passwordHash) {
|
|
return bcrypt.compare(password, passwordHash);
|
|
}
|
|
|
|
module.exports = {
|
|
generateSixDigitCode,
|
|
hashPassword,
|
|
hashAuthCode,
|
|
randomRefreshToken,
|
|
sha256Hex,
|
|
timingSafeEqualHex,
|
|
verifyPassword,
|
|
};
|