From 16311436477c339ec4762079ec91d228c47ac227 Mon Sep 17 00:00:00 2001 From: Kim Ravn Hansen Date: Mon, 13 Oct 2025 15:56:44 +0200 Subject: [PATCH] Minor tweaks and renames --- utils/security.js | 74 ++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 42 deletions(-) diff --git a/utils/security.js b/utils/security.js index afa0434..eca4506 100644 --- a/utils/security.js +++ b/utils/security.js @@ -2,22 +2,18 @@ import { randomBytes, pbkdf2Sync } from "node:crypto"; import { Config } from "../config.js"; // Settings (tune as needed) -const ITERATIONS = 1000; -const KEYLEN = 32; // 32-bit hash -const DIGEST = "sha256"; -const DEV = process.env.NODE_ENV === "dev"; +const ITERATIONS = 1000; // MAGIC CONSTANT - move to Config +const DIGEST = "sha256"; // MAGIC CONSTANT - move to Config +const KEYLEN = 32; // MAGIC CONSTANT - move to Config /** - * Generate a hash from a plaintext password. - * @param {string} password - * @returns {string} + * Generate a hash from a string + * @param {string} source @returns {string} */ -export function generateHash(password) { - const salt = randomBytes(16).toString("hex"); // 128-bit salt - const hash = pbkdf2Sync(password, salt, ITERATIONS, KEYLEN, DIGEST).toString( - "hex", - ); - return `${ITERATIONS}:${salt}:${hash}`; +export function generateHash(source) { + const salt = randomBytes(16).toString("hex"); // 128-bit salt + const hash = pbkdf2Sync(source, salt, ITERATIONS, KEYLEN, DIGEST).toString("hex"); + return `${ITERATIONS}:${salt}:${hash}`; } /** @@ -28,41 +24,35 @@ export function generateHash(password) { * @returns {boolean} */ export function verifyPassword(password_candidate, stored_password_hash) { - const [iterations, salt, hash] = stored_password_hash.split(":"); - const derived = pbkdf2Sync( - password_candidate, - salt, - Number(iterations), - KEYLEN, - DIGEST, - ).toString("hex"); - const success = hash === derived; - if (Config.dev || true) { - console.debug( - "Verifying password:\n" + - " Input : %s (the password as it was sent to us by the client)\n" + - " Given : %s (the input password hashed by us (not necessary for validation))\n" + - " Stored : %s (the password hash we have on file for the player)\n" + - " Derived : %s (the hashed version of the input password)\n" + - " Verified : %s (was the password valid)", - password_candidate, - generateHash(password_candidate), - stored_password_hash, - derived, - success, - ); - } - return success; + const [iterations, salt, hash] = stored_password_hash.split(":"); + const derived = pbkdf2Sync(password_candidate, salt, Number(iterations), KEYLEN, DIGEST).toString("hex"); + const success = hash === derived; + if (Config.dev) { + console.debug( + "Verifying password:\n" + + " Input : %s (the password as it was sent to us by the client)\n" + + " Given : %s (the input password hashed by us (not necessary for validation))\n" + + " Stored : %s (the password hash we have on file for the player)\n" + + " Derived : %s (the hashed version of the input password)\n" + + " Verified : %s (was the password valid)", + password_candidate, + generateHash(password_candidate), + stored_password_hash, + derived, + success, + ); + } + return success; } /** @param {string} candidate */ export function isUsernameSane(candidate) { - return /^[a-zA-Z0-9_]{4,}$/.test(candidate); + return Config.usernameSanityRegex.test(candidate); } /** @param {string} candidate */ export function isPasswordSane(candidate) { - // We know the password must adhere to one of our client-side-hashed crypto schemes, - // so we can be fairly strict with the allowed passwords - return /^[a-zA-Z0-9_: -]{8,}$/.test(candidate); + // We know the password must adhere to one of our client-side-hashed crypto schemes, + // so we can be fairly strict with the allowed passwords + return Config.passwordSanityRegex.test(candidate); }