qnote/web/src/lib/utils.ts
2025-04-18 19:13:37 +03:00

51 lines
1.2 KiB
TypeScript

import {
ENTROPY_CLASSES,
MAX_PASSWORD_LENGTH,
MIN_PASSWORD_ENTROPY,
MIN_PASSWORD_LENGTH
} from "./const"
export const isPasswordValid = (password: string): [boolean, string] => {
if (password.length < MIN_PASSWORD_LENGTH) {
return [false, `Password cannot be shorter than ${MIN_PASSWORD_LENGTH} characters`]
}
if (password.length > MAX_PASSWORD_LENGTH) {
return [false, `Password cannot be longer than ${MAX_PASSWORD_LENGTH} characters`]
}
const entropy = calculateEntropy(password)
console.log(`entropy: ${entropy}`)
if (entropy < MIN_PASSWORD_ENTROPY) {
return [
false,
"Password is not complex enough (add uppercase, lowercase, numbers, and symbols)"
]
}
return [true, ""]
}
const calculateEntropy = (password: string) => {
let poolSize = 0
for (const [eClass, poolPlus] of ENTROPY_CLASSES) {
if (eClass.test(password)) {
poolSize += poolPlus
}
}
// Empty password exception
if (poolSize === 0) {
return 0
}
const uniqueChars = new Set(password.split("")).size
const basicEntropy = password.length * Math.log2(poolSize)
const diversityAdjustedEntropy =
Math.log2(poolSize) + (password.length - 1) * Math.log2(uniqueChars)
return Math.min(basicEntropy, diversityAdjustedEntropy)
}