Files
TallyNote/server/security.ts
T
Qiufeng 9719429f4a
TallyNote release / linux-x64 (push) Failing after 2m41s
feat: add TallyNote local reimbursement ledger
2026-08-29 01:02:29 +08:00

53 lines
1.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import argon2 from "argon2";
import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
const ARGON_OPTIONS = {
type: argon2.argon2id,
memoryCost: 65_536,
timeCost: 3,
parallelism: 1,
hashLength: 32,
} as const;
export function normalizeUsername(username: string): string {
return username.normalize("NFKC").trim().toLocaleLowerCase("und");
}
export function validateNewPassword(password: string): string | null {
const length = [...password].length;
if (length < 12 || length > 128 || Buffer.byteLength(password, "utf8") > 512) {
return "密码长度需要为 12–128 个字符";
}
return null;
}
export function hashPassword(password: string): Promise<string> {
return argon2.hash(password, ARGON_OPTIONS);
}
export async function verifyPassword(hash: string, password: string): Promise<boolean> {
try {
return await argon2.verify(hash, password);
} catch {
return false;
}
}
export function randomToken(bytes = 32): string {
return randomBytes(bytes).toString("base64url");
}
export function sha256(value: string | Buffer): string {
return createHash("sha256").update(value).digest("hex");
}
export function constantTimeEqual(left: string, right: string): boolean {
const leftBuffer = Buffer.from(left);
const rightBuffer = Buffer.from(right);
return leftBuffer.length === rightBuffer.length && timingSafeEqual(leftBuffer, rightBuffer);
}
export function temporaryPassword(): string {
return `${randomToken(15)}A7!`;
}