← 中文资源

简体中文版本

基于熵的密码强度评估

从字符池、唯一字符数与常见模式估算密码熵,输出五级强度评分与可读标签。

阅读英文原文

功能说明

estimatePasswordStrength 根据密码使用的字符种类估算搜索空间,结合去重后的有效长度计算熵值,并对常见弱口令、键盘序列和连续重复字符打折。结果包含熵位数、零到四的评分、标签、字符池大小、长度与唯一字符数,适合注册与修改密码表单的即时提示,也可用于后台弱口令巡检。

关键代码

函数依次检测小写字母、大写字母、数字和符号,累加对应字符池大小,再用有效长度乘 log2 得到理论熵。有效长度取唯一字符数与实际长度四分之三中的较大值,降低 aaaaaa 这类重复串的收益。命中 123456、password、qwerty 或三连重复时熵减半,长度不足八位再乘 0.6。评分按二十、四十、六十、八十分档。

使用注意

这是启发式估算,不等同于 zxcvbn 等基于泄露字典的评估,不能替代服务端强度策略。熵高不代表未被泄露,注册流程仍应检查泄露密码库并强制多因素认证。函数在浏览器执行,密码字符串会短暂存在于内存,不要记录到日志或分析事件。评分只用于提示,最终是否允许提交应由明确规则决定。

验证方式

用 password、P@ssw0rd!、随机十六位字符串、纯数字长串和空串验证评分梯度。测试三连重复与键盘序列会降低熵,唯一字符少的重复串得分更低。检查返回值字段完整、熵为整数、评分在零到四之间。再覆盖非字符串输入被转成字符串的行为,并确认空密码返回 very weak 且不抛错。

代码示例

const COMMON_PATTERNS = [/^123456/, /password/i, /qwerty/i, /(.)\1{2,}/];

// Password strength estimation based on character-pool entropy.
export function estimatePasswordStrength(password) {
  const value = String(password);
  const pools = [
    [/[a-z]/, 26],
    [/[A-Z]/, 26],
    [/[0-9]/, 10],
    [/[^A-Za-z0-9]/, 33],
  ];
  const poolSize = pools.reduce((total, [pattern, size]) => {
    return total + (pattern.test(value) ? size : 0);
  }, 0);
  const unique = new Set(value).size;
  const effectiveLength = Math.max(unique, Math.ceil(value.length * 0.75));
  let entropyBits = poolSize > 0 ? effectiveLength * Math.log2(poolSize) : 0;
  for (const pattern of COMMON_PATTERNS) {
    if (pattern.test(value)) entropyBits *= 0.5;
  }
  if (value.length < 8) entropyBits *= 0.6;
  const thresholds = [20, 40, 60, 80];
  let score = thresholds.filter((threshold) => entropyBits >= threshold).length;
  if (value.length === 0) score = 0;
  const labels = ["very weak", "weak", "fair", "strong", "very strong"];
  return {
    entropyBits: Math.round(entropyBits),
    score,
    label: labels[score],
    poolSize,
    length: value.length,
    uniqueCharacters: unique,
  };
}