51 lines
1.8 KiB
TypeScript
51 lines
1.8 KiB
TypeScript
import crypto from "crypto";
|
|
|
|
const SECRET = process.env.JWT_SECRET || "default_ayristech_super_secure_admin_jwt_secret_key_2026";
|
|
|
|
// ── PASSWORD HASHING ──
|
|
|
|
export function hashPassword(password: string): string {
|
|
const salt = crypto.randomBytes(16).toString("hex");
|
|
const hash = crypto.pbkdf2Sync(password, salt, 1000, 64, "sha512").toString("hex");
|
|
return `${salt}:${hash}`;
|
|
}
|
|
|
|
export function verifyPassword(password: string, storedHash: string): boolean {
|
|
const [salt, hash] = storedHash.split(":");
|
|
if (!salt || !hash) return false;
|
|
const verify = crypto.pbkdf2Sync(password, salt, 1000, 64, "sha512").toString("hex");
|
|
return hash === verify;
|
|
}
|
|
|
|
// ── NATIVE LIGHTWEIGHT JWT SIGN & VERIFY ──
|
|
|
|
export function signToken(payload: any): string {
|
|
const header = Buffer.from(JSON.stringify({ alg: "HS256", typ: "JWT" })).toString("base64url");
|
|
// Expire session in 24 hours
|
|
const body = Buffer.from(JSON.stringify({ ...payload, exp: Date.now() + 24 * 60 * 60 * 1000 })).toString("base64url");
|
|
const hmac = crypto.createHmac("sha256", SECRET);
|
|
hmac.update(`${header}.${body}`);
|
|
const signature = hmac.digest("base64url");
|
|
return `${header}.${body}.${signature}`;
|
|
}
|
|
|
|
export function verifyToken(token: string): any {
|
|
try {
|
|
const [header, body, signature] = token.split(".");
|
|
if (!header || !body || !signature) return null;
|
|
|
|
const hmac = crypto.createHmac("sha256", SECRET);
|
|
hmac.update(`${header}.${body}`);
|
|
const expectedSignature = hmac.digest("base64url");
|
|
|
|
if (signature !== expectedSignature) return null;
|
|
|
|
const payload = JSON.parse(Buffer.from(body, "base64url").toString("utf8"));
|
|
if (payload.exp < Date.now()) return null; // Expired
|
|
|
|
return payload;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|