随机密码生成在线之后:12 位小写为何强过 8 位四类

手动想一个复杂密码这件事,从第一步就输了:人不会随机,只会改装。随机密码生成在线服务真正值钱的不是那个「生成」按钮,而是它背后的随机源和你选的长度。

下面是熵的公式、一张能直接对照的破解时间表,以及几条已经被证伪的老规矩。

一、手动想密码为什么会失败

人脑没有随机性。 让人随口报十个「随机」数字,结果会集中在 1 和 2 开头、避开重复与规律。攻击者的字典就是按人的偏好建的。

改装规则是固定的。 首字母大写 + 结尾补 1!,是全人类默认的改装方式。hashcat 的规则文件(best64.ruleOneRuleToRuleThemAll)里写的就是这些变换。

跨站复用。 一个站被拖库,你在其它站的账号同时失守——这是当下最常见的攻击方式,第七节细说。

二、密码强度由什么决定:长度 > 字符空间

强度只有一个公式:

H = log2(N^L) = L × log2(N)

H:信息熵,单位 bit,衡量「攻击者平均要试多少次」
N:字符空间大小(每个位置有多少种可能)
L:长度

关键在于两者位置不对等:L 是乘数,N 要先被取对数。字符空间翻一倍,每字符只多 1 bit;长度翻一倍,总熵直接翻倍。

字符集 N 每字符贡献的熵
纯数字 10 3.32 bit
纯小写 26 4.70 bit
小写 + 大写 52 5.70 bit
大小写 + 数字 62 5.95 bit
再 + 常见符号(共 88 个) 88 6.46 bit

从纯小写堆到四类混合,每字符只从 4.70 涨到 6.46,涨幅不到 40%;而长度从 8 加到 16,什么都不用做,熵已经翻倍。

三、长度 vs 破解时间对照表

表的口径先说清楚:口令库泄露 + 攻击者知道你的生成规则 + 服务端存的是未加盐的快哈希,取离线猜测速度 1e10 次/秒,平均命中需要 2^(H-1) 次尝试。

密码形态 平均尝试次数 破解耗时(1e10 次/秒)
8 位纯数字 26.6 bit 5×10^7 瞬间
8 位小写 37.6 bit 1×10^11 约 10 秒
8 位四类混合 51.7 bit 1.8×10^15 约 2 天
10 位小写 47.0 bit 7×10^13 约 2 小时
12 位小写 56.4 bit 4.8×10^16 约 55 天
12 位四类混合 77.5 bit 1.1×10^23 约 34 万年
16 位四类混合 103.4 bit 6.5×10^30 约 20 万亿年

换成能感知的结论:8 位四类混合在 GPU 面前只有两天寿命——而这正是多数网站注册校验的最低标准。

以上假设服务端用的是 MD5 / SHA 这类快哈希。换成 bcrypt / Argon2,破解成本会抬高几个数量级,但那是服务端的选择,你唯一能做的就是给自己加位数。

四、12 位小写打败 8 位四类,但网站拦的偏偏是前者

const entropy = (L, N) => L * Math.log2(N)

entropy(12, 26)   // 56.4 bit —— 12 位纯小写
entropy(8, 88)    // 51.7 bit —— 8 位含大小写数字符号

12 位纯小写比 8 位四类混合强 26 倍(2^4.7)。

讽刺的是:abcdefghijklmn 会被绝大多数注册表单拒绝(「必须包含大小写字母和数字」),而 Ab3!xy7z 一路放行——后者弱了 26 倍。

这套「必须凑齐三类」的要求源自 2003 年 NIST SP 800-63 附录的一段建议,起草人后来公开表示它已被证明是错的:它恰好鼓励了「首字母大写 + 结尾补符号」这种最易预测的变形。

所以实操只有一句:能选长就优先拉长。本站长度滑杆是 4–64,建议 16 起步;站点限制 12 位以内时,再把四类全勾上补熵。

👉 随机密码生成在线(本地生成不上传,可调长度与字符集)

把「数量」调到 1,结果区会显示这条密码的字符空间、信息熵 bit 数和按 1e10 次/秒 估算的破解耗时——上面表格里的数字可以逐个验证。

五、随机密码生成在线背后的随机源:为什么 Math.random() 不行

这是最容易跳过、也最要命的一节。

// 不推荐:随机源不安全,且存在模偏差
function weakPick(pool, len) {
  let s = ''
  for (let i = 0; i < len; i++) s += pool[Math.floor(Math.random() * pool.length)]
  return s
}

// 推荐:CSPRNG + 拒绝采样
function randInt(max) {
  const arr = new Uint32Array(1)
  const limit = Math.floor(0xffffffff / max) * max  // 去掉尾部的偏斜区间
  let x
  do {
    crypto.getRandomValues(arr)
    x = arr[0]
  } while (x >= limit)
  return x % max
}

两个坑要分开说:

坑一:Math.random() 不是加密安全的随机数。 它是伪随机数发生器(V8 里是 xorshift128+ 一类算法),输出之间存在可推导的数学关系。已有公开研究指出,拿到足够多的连续输出可以反推内部状态,进而预测后续取值。用它生成密码、token、验证码,等于把秘密值拱手让人。

坑二:就算换成 CSPRNG,% pool.length 仍有模偏差。 2^32 通常不是字符池大小的整数倍,靠前的字符更容易被选中。上面的 do...while 是标准的拒绝采样修正,本站的生成器正是这么实现的。

Node 一侧对应 crypto.randomBytes()crypto.randomInt()

六、容易被拖库字典命中的弱密码长什么样

它们的问题不是「短」,而是可被预测生成

特征 典型样本
季节 + 年份 + 感叹号 Spring2026!Summer@2026
键盘走位 qwerty1qaz2wsxqazwsx
公司 / 产品名 + 数字 Company123Admin@123
拼音 + 生日 zhangsan1998
序列 / 重复 12345678aaaa1111

Spring2026! 12 位且四类字符齐全,按熵公式算看着不低——但熵公式只对真正随机生成的密码成立。攻击方拿着公开泄露字典加变形规则,几秒就能覆盖到这种模式。

记住:熵衡量的是随机性,不是复杂度。 人想出来的密码,熵永远接近 0。

七、撞库、彩虹表、加盐分别在说什么

  • 拖库:站点数据库被拿走,账号密码对流入黑市,是所有后续攻击的起点
  • 撞库(credential stuffing):拿 A 站泄露的账号密码批量登录 B 站。它不破解任何东西,只利用你的复用行为
  • 彩虹表:预先算好的「明文 → 哈希」对照表,本质是空间换时间
  • 加盐(salt):给每个用户一段随机值,存 hash(salt + password),让通用彩虹表作废,攻击者必须逐人重算

要补一句防误解:加盐只挡批量攻击,挡不住针对单人的定向爆破。 真正让离线爆破变贵的是慢哈希:

// Node 里存密码的正确姿势(示意)
import bcrypt from 'bcryptjs'

const stored = await bcrypt.hash(password, 12)  // cost 每 +1,算力成本翻倍
await bcrypt.compare(input, stored)             // 永远比对,绝不解密

用 bcrypt / scrypt / Argon2 / PBKDF2 加随机盐存储,选哪个不重要,不要用裸 MD5 / SHA-256 直接存

想直观看看「同明文必然同摘要」这个问题(也就是加盐要解决的),可以拿哈希工具算同一个字符串,再改一个字符看结果如何雪崩:

👉 哈希摘要计算(MD5 / SHA-1 / SHA-256 / SHA-384 / SHA-512,支持文件)

八、「定期强制改密码」这条规矩已经被推翻

NIST SP 800-63B 从 2017 年那一版起就把「周期性更换密码」从建议里删除了,明确要求验证方不得在没有泄露证据的情况下强制用户改密码。

理由很朴素:强制到期会逼出 P@ssw0rd1 → P@ssw0rd2 → P@ssw0rd3 这种可递推序列,也会让人把密码写在便签上。攻破一次等于攻破全部。

NIST 现在推荐的做法是:

  1. 长度优先,最短 8 位,且至少允许 64 位(现实中不少站点反而卡 16 位上限)
  2. 不强制字符种类组合
  3. 注册与改密码时比对公开泄露库,命中就拒绝
  4. 废弃「你母亲的名字」这类知识型安全问题
  5. 提供两步验证,并允许用户粘贴(密码管理器要能用)

所以入职培训里那句「90 天必须改一次」是过期策略。真正有效的组合只有一句:每个站点一个随机长密码 + 开启两步验证

九、网站存明文就是流氓,怎么自查

判断方法很简单:点「找回密码」,看它发的是一次性重置链接,还是把你的原密码原样显示在邮件里。能读出来就是明文或可逆加密存储,立刻改密码并停用该站。

其它信号:注册表单把长度卡在 6–16 位、禁止粘贴、禁止空格,基本可以推断是老旧系统加弱存储。

密码是否已经进了泄露库,唯一靠谱的自查渠道是 Have I Been Pwned 的口令查询。它用 k-匿名模型:本地算 SHA-1,只上传前 5 位,服务端返回这一批后缀后在本机比对,完整密码与完整哈希都不出本机。

要说透一点:没有任何在线工具能查看别人数据库里的明文密码,声称能查的一律是诈骗。

十、生成工具是配角,密码管理器才是正解

生成器的价值有限:它只解决「这一瞬间给我一个足够随机的串」,但人记不住 30 个随机串。让系统真正跑起来的是密码管理器——它同时解决记忆、每站唯一、自动填充和泄露提醒。

分工是这样:

  • 主密码:唯一需要记住的一个,用随机词短语而不是符号串。骰子词表每词约 12.9 bit(log2(7776)),4 个词 51.7 bit,5 个词 64.6 bit,好记又好输入
  • 其余站点:交给管理器生成,长度给到对方允许的上限
  • 在线生成:用于临时场景——测试账号、一次性口令、共享口令

把生成结果复制进记事本是不算数的,那只是换了个地方明文躺着。

十一、密码卫生清单

  1. 主密码改成 4–5 个随机词组成的短语,不搞符号堆砌
  2. 装一个密码管理器,每个站点一个随机串,长度给到该站允许的上限(不低于 16)
  3. 在 HIBP 上把已有邮箱全查一遍,命中的站点立刻改
  4. 找回密码能读出原密码的站点,标记为不可信,换专用密码或停用
  5. 邮箱、支付、网盘这三类账号必须开两步验证(优先 TOTP 或硬件密钥,短信次之)
  6. 复用密码的站点优先整改,尤其是同一密码改后缀用在多处的
  7. 不再设「90 天改一次」的闹钟,改成「收到泄露通知才改」
  8. 开发侧:密码用 bcrypt / Argon2 加随机盐存储;随机源一律用 crypto.randomInt(),任何时候都不要碰 Math.random()

相关工具:随机密码生成器(可调长度与字符集)哈希摘要计算UUID 生成

全部纯前端实现,输入的内容不上传服务器。

还有 53 个免费在线工具

纯前端实现,不用注册,数据不上传服务器。

浏览全部工具