令牌生成器
在浏览器中生成密码学强度高的随机令牌、API 密钥、密钥与 nonce。可选择长度、字符集与生成数量。
随机、不可预测的令牌。 所有随机性都来自浏览器的 crypto.getRandomValues,与浏览器生成 TLS 密钥用的是同一来源。数据不会离开你的设备。
在浏览器中生成密码学强度高的随机令牌、API 密钥、密钥与 nonce。可选择长度、字符集与生成数量。
随机、不可预测的令牌。 所有随机性都来自浏览器的 crypto.getRandomValues,与浏览器生成 TLS 密钥用的是同一来源。数据不会离开你的设备。
大多数语言都提供两种截然不同的随机数生成器。Math.random()、rand() 这一类是速度优先的伪随机生成器,种子往往来自时钟这种廉价来源。用它们打乱播放列表没问题,用来生成令牌则是灾难:攻击者只要观察到少量输出,通常就能还原内部状态,进而复现该生成器今后产生的每一个值。
密码学安全的生成器在设计上保证:看到过去的输出无法推断未来的输出。在浏览器中它就是 crypto.getRandomValues(),数据取自操作系统的熵池。本工具只使用它。如果你要在自己的代码里生成令牌,对应的选择是 Python 的 secrets、Go 的 crypto/rand、Java 的 java.security.SecureRandom——绝不要用普通的 random 模块或 Math.random()。
拿到高质量随机字节只完成了一半。最直觉的取字符方式是 bytes[i] % alphabet.length,但只要字母表大小不能整除 256,结果就会悄悄偏斜。以 62 字符的字母表为例,前 8 个字符出现的概率会略高于其余字符——偏差不大,却实实在在削弱了熵,而且完全可以避免。
解决办法是拒绝采样:落在最后那个不完整区间里的字节直接丢弃,重新取一个。本工具正是这么做的,因此所选字母表中的每个字符出现概率完全相等。
熵值等于 log2(字母表大小) × 长度 比特。62 字符的字母表每个字符约 5.95 比特,因此 22 位令牌约携带 131 比特,暴力破解已无从下手。凡是用于保护真实访问权限的场景,128 比特是通行下限;低于约 64 比特时,攻击者只要有一个响应够快的接口,威胁就变得真实。
字母表的选择主要取决于令牌要经过哪些环节。Base64url 和十六进制可以原样穿过 URL、文件名和 HTTP 头。无歧义字母表剔除了 0/O、1/l/I 这类易混字符,凡是需要人念出来或照着屏幕重新输入的场景都值得使用。