字符对网址与 shell 都安全的随机 API 密钥,在你的浏览器里生成。不联网,不记录,不上传。
按 空格键 换一个,C 复制。密钥由本机的 crypto.getRandomValues 生成,页面不加载任何外部资源。
API 密钥并不是本站其他生成器所产生的那种密码学密钥 —— 没有东西用它签名或解密。它只是一串你的服务器认得的长随机字符串,因此唯一重要的性质是:没有人猜得到它,也造不出另一把你的服务器会接受的。128 位的随机性就已经在可及范围之外,而大多数服务最后选的是 256。
这些字节取自 crypto.getRandomValues,也就是浏览器的密码学安全随机数生成器,再以 Base64URL 或十六进制写出。这两种字母表穿过网址、HTTP 头、环境变量和 shell 命令时都不需要转义 —— 这也正是这里不提供普通 Base64 的原因,它含有 +、/ 和 =。整条路径上没有时间戳、没有计数器,也没有 Math.random。
全部在你自己的设备上完成。页面加载后不发出任何网络请求,所以这把密钥从未在别处存在过,也不会传到任何地方。刷新一下就消失 —— 这也意味着关掉标签页之前,记得先把它粘进你的密钥存储里。
128 位的随机性 —— 也就是 22 个 Base64URL 字符 —— 就已经超出暴力破解的范围,没有人能穿过你的限流把这样一把密钥猜出来。256 位是常见的默认值,主要是因为它几乎不增加成本,还能让这个问题在代码评审时不必再提。再长完全不会更安全,只会让密钥更难粘贴,也更容易在路上被某行日志或某个数据库字段截断。
可以,但它没有看上去那么可靠。随机的 UUIDv4 带的是 122 位而不是 128,因为其中有六位是固定的版本与变体标记 —— 这仍然够用,但前提是背后接的是密码学安全随机数生成器,而不少实现其实悄悄用了普通的随机数。UUIDv1 和 v7 内嵌时间戳,设计上就有一部分可预测。而且 UUID 一眼就会被认出是标识符,这会诱使下游的每一个环节把它当标识符对待并写进日志。
如果你是签发密钥的一方,要。像 sk_live_ 或 myapp_ 这样的前缀能让泄漏的密钥一眼可辨,更实际的好处是给了 GitHub 和 GitLab 的密钥扫描一个可匹配的模式,于是误提交的密钥会被上报,而不是静静躺在那里。它也让你能在碰数据库之前就按前缀分流或直接拒绝。把它加在本页生成的值前面即可:前缀不是机密,也不提供任何熵,所以它不替换随机部分的任何一个字符。
像存密码那样存哈希 —— 一把能从你的数据库里读出来的密钥,等于一次随时可以被导出的泄漏。但和密码不同的是,这里用普通的 SHA-256 就够,不需要 bcrypt 这类慢哈希:密钥本身已经是 128 位的均匀随机,没有字典可以拿来跑,也没有理由在每个请求上付那份成本。另外把前缀或末四位明文留着,让密钥能在列表里被认出来,而完整的值只在创建当下显示一次。
API 密钥是不透明的:除了签发它的系统之外它不代表任何含义,而那个系统必须查一次才能验证。JWT 正好相反 —— 它把声明和过期时间带在自己身上并附有签名,所以服务不必查询就能验证。OAuth 意义下的 token 更靠近 JWT 那一端:生命周期短、有作用域限制,而且是在另一次认证之后才签发的。机器需要能写进配置文件的长期访问时用密钥;访问本身就该自动过期时用 token。
两者是同一串字节,差别在长度,以及这串字符能在哪些地方不经转义地存活。Base64URL 更短 —— 256 位是 43 个字符,十六进制则要 64 个 —— 而且它的字母表是 A-Z、a-z、0-9、连字符和下划线,全都能原封不动地穿过网址、请求头和 shell。十六进制更长,但更容易念出来、口述和用眼睛比对,也不会在任何大小写处理不当的地方出事。真正该避开的是普通 Base64:+ 和 / 在网址里要转义,而 = 这个补位字符在传输途中经常被剥掉。
尽量别。查询字符串会被写进服务器访问日志、代理日志和浏览器历史记录,还会通过 Referer 头泄漏给页面接下来链接到的任何地方 —— 请求一旦发出,这些都不在你的控制范围内。改用 Authorization 头传送,也就是 Authorization: Bearer 后面接密钥,一般的日志默认不会记录它。这里采用网址安全字母表,是为了偶尔出现的路径片段或 webhook 回调,而不是为了让查询字符串变成一个放机密的好地方。
比密码学密钥轻松得多:轮换 API 密钥不需要重新加密任何东西,成本全部在协调客户端这一件事上。让每个账号能同时持有两把有效密钥,轮换就变成创建、部署、吊销三步,中间没有任何服务中断的空窗。按计划走的话,多数系统一年一到两次就绰绰有余。更重要的是吊销必须即时而且能自助完成,因为真正要紧的那次轮换永远是计划外的那次。
只有在这个页面无法把它送出去的前提下才安全,而这件事你可以核实,不必只是相信。打开开发者工具停在「网络」面板,然后随便生成几次:页面加载之后不发出任何请求。它背后没有服务器可以接收任何东西,也没有统计分析或第三方脚本可以外泄。在你把它粘到别处之前,这把密钥只存在于这一个标签页的内存里,刷新就没了。