跳到主要内容

API 密钥怎么生成才安全:随机长度、字符集与前缀约定全解

讲清楚 API Key 该用多长、配什么字符集、前缀有什么用,以及怎么本地生成、安全存储和无停机轮换,附一个真实的密钥格式例子。

发布于 作者 李雷
#api密钥 #api key #安全 #开发者工具 #令牌

API 密钥怎么生成才安全:随机长度、字符集与前缀约定全解

接一个第三方服务,十有八九第一步就是签发一把 API 密钥。它看着只是一串字符,可它的全部价值就在于别人猜不到。生成方式稍微随便一点,这串字符就从凭证退化成摆设。下面把生成、存储、轮换这几件事一次讲透。

随机段的熵才是安全的全部来源

一把密钥的安全性,只看随机段有多少位熵,跟它长得花不花没关系。常用的经验值是:随机段至少 128 位熵,要守护贵重东西就上到 160 到 256 位。

字符集决定每个字符值多少位。base62(大小写字母加数字)每个字符约值 5.95 位,所以长度 22 约到 131 位,长度 27 约到 160 位,长度 32 约到 190 位。换成十六进制,每个字符只有 4 位,要 32 个字符才凑够 128 位。同样一串长度,base62 的熵比 hex 高一截,这就是为什么大多数密钥默认用 base62。

如果 token 要塞进 URL 的 query string 或路径段,标准 base64 里的加号和斜杠会触发百分号转义,这时换成 base64url,它用 - 和 _ 代替,长度 43 给你 256 位,而且整串可以安全复制粘贴。

前缀是路由标签,不是秘密

sk_live_ 这种前缀由 Stripe 带火:sk 表示 secret key,pk 表示 publishable key,live 和 test 标记环境。它的作用是,当一把密钥泄进日志或公开提交,自动扫描器能凭前缀立刻判断,该轮换的是真实资金路径还是无害的沙箱密钥。

关键认知:前缀可预测,贡献的熵为零。一个长前缀后面只跟 4 个随机字符,照样能被轻松暴力破解。所以算安全度时只数随机段长度,别把那个标签算进去。

一把生成出来的密钥长这样:

sk_live_4f9Kp2QzR8nM7vXa1bC3dE6gH0jL5sT9

前面的 sk_live_ 是给人和扫描器看的,后面 32 个 base62 字符才是真正不可预测的那部分,约 190 位熵。

一定要用密码学随机源,别碰 Math.random()

我自己早年图省事,在一个小脚本里用 Math.random() 拼过密钥,后来才知道这是个坑。Math.random() 是非密码学伪随机数,内部状态能从几个输出里还原出来,看到一把密钥的攻击者就能预测下一把。从那以后我只用 crypto.getRandomValues,也就是 Web Crypto API 暴露的那个源,由操作系统播种,和服务端会用的随机性同一档次。要自己写生成器,字节来源必须是它或服务端的 CSPRNG。

API 密钥生成器 全程只用 crypto.getRandomValues,密钥在你浏览器内存里生成,不发往任何地方,也不写进可分享的 URL,从根上避开了把敏感值粘进陌生网站的风险。

静态存储:存哈希,别存明文

把 API 密钥当密码看待。数据库里只存加盐哈希或 HMAC,每次请求比对哈希。创建时把完整密钥给用户看一次,之后只留哈希和一段前缀用于展示。

道理很直接:如果数据库泄露而你存的是明文密钥,每一把都能立刻被人拿去用;存的是哈希,泄露的就只是一堆没法逆推的摘要。这一步是事后补不回来的,生成那一刻就得定好。

无停机轮换:相同前缀和长度并存切换

密钥泄进公开仓库是常见事故,轮换的标准做法是先并存再吊销。用相同的前缀和长度生成一把替换,让它能套进你现有的校验正则,先和旧密钥并存、部署上线,等流量切过去后再吊销旧的。

随机段长度保持一致很重要,这样你的列宽、限流键、日志脱敏规则全都照常工作,不用改 schema。批量开通多个租户时,把数量设成租户数一次生成一批,再整批下载成 .txt 灌进密钥库。

选对工具:密钥、唯一 id 与短码各有所长

不是所有场景都要密钥。UUID 是 128 位标识符,格式固定还带版本位,目标是唯一而非保密,放进 URL 和日志都没问题,用它命名一行数据正合适,见 UUID 生成器。要短一点的唯一 id,NanoID 生成器ULID 生成器 更顺手。而需要给人用的高强度口令,则交给 密码生成器。判断标准只有一句:要保密、要难猜的才用 API key,要唯一、可公开的用 id。

把这几条做齐,一把密钥从生成到吊销的整个生命周期就都站得住:足够的随机段熵、可读的前缀约定、密码学随机源、只存哈希、相同形状轮换。剩下的,交给本地生成就好。


Made by Toolora · Updated 2026-06-13