开发者工具 · UUID 生成器
为什么 crypto.randomUUID() 在 HTTP 页面上失败:安全上下文解释
· 工作原理
uuid 密码学 浏览器 API
crypto.randomUUID 在本地主机和 HTTPS 上工作,然后在纯 HTTP 临时主机上消失。这篇文章解释了该行为背后的安全上下文规则,以及如何在适用的地方安全地生成 UUID 。
登台时出现 TypeError,其他地方都很好 — 症状和导致它的环境差异
开发人员在本地主机上检查他们的工作:3000 并且 UUID 生成器工作正常。他们部署到 http://staging. 内部暂存。例子。 com(公司 LAN 上的纯 HTTP)并且代码抛出 TypeError: crypto.randomUUID is not a function。生产中的相同代码在 https://example. com 上运行良好。这种不一致令人困惑,直到他们阅读 MDN 文档:crypto.randomUUID 仅限于安全上下文。安全上下文是 HTTPS 或 localhost;根据浏览器规则,LAN 上的纯 HTTP 源并不安全,即使网络是私有的。修复方法是使用 crypto.getRandomValues 进行手动位操作,或者将临时服务器升级到 HTTPS。引入安全上下文规则是为了防止敏感 API 泄漏到未加密的连接。
什么是安全上下文 — 为 HTTPS 源和本地主机保留某些 API 的浏览器规则
通过纯 HTTP 的页面可能会被网络攻击者拦截;将加密 API 暴露给此类页面将使攻击者能够使用受损的 API 生成标识符。 HTTPS 对页面和所有 API 通信进行加密,以便网络上的攻击者无法拦截或修改代码。本地主机被视为本质上安全的,因为它仅存在于本地计算机上并且不能通过网络被拦截。根据定义,任何其他 HTTP 来源(LAN 地址、没有 HTTPS 的公共域、转发到 HTTP 的反向代理)都是不安全的。 Web Crypto API 分为两个函数:crypto.randomUUID(仅限于安全上下文)和 crypto.getRandomValues(在安全和非安全上下文中均可用)。两者都使用相同的操作系统 CSPRNG。
Web Crypto 的哪些部分是门控的 - crypto.randomUUID 和 crypto.subtle 需要安全上下文,而 crypto.getRandomValues 不需要
的区别在于 getRandomValues 不会隐藏您正在使用密码学的事实;使用它的页面必须明确请求随机字节。 randomUUID 函数很方便,还可以强制执行安全上下文。如果您的应用程序需要在非安全页面上生成 UUID,则必须使用 getRandomValues 并手动设置版本和变体位。 RFC 9562 指定位操作:将字节 6 设置为 (byte6 & 0x0f) |版本 4 为 0x40,字节 8 为 (byte8 & 0x3f) | RFC 变体为 0x80。 ToolAcre 库正是这样做的,作为 randomUUID 不可用时的后备方案。重现失败:从不被视为潜在可信的普通 HTTP 源提供一个简单页面。检查 randomUUID 是否公开,然后比较 getRandomValues,Web Crypto 参考在不安全的上下文中允许这样做。
从 getRandomValues 构建 v4 UUID — 当 randomUUID 丢失时,屏蔽和格式化回退让您保持在 CSPRNG 上
通过 HTTPS 提供的文件中的相同代码可以公开 randomUUID。如果生产报告“randomUUID 不是函数”,请首先检查源是否是安全上下文,然后验证浏览器支持以及另一个脚本是否替换了加密对象。补救措施可能是 HTTPS 或显式设置 UUID 位的 getRandomValues 实现。 Math.random polyfill 并不是一个等效的后备:它在删除加密源合约的同时重现形状。仅断言破折号和版本数字的测试将错过该替换,因此请检查源路径以及结果字符串。
工作示例 — 在 http:// 源上重现故障并确认修复
但标识符现在是可预测的。从您的系统捕获一些 UUID 的攻击者可以预测下一个。如果应用程序错误地将此类标识符视为持有者凭证,则可预测性将成为授权失败而不是外观缺陷。正确的策略是将服务器升级到 HTTPS(对于任何具有身份验证或敏感数据的页面来说始终是正确的举措)或使用具有显式位操作的 getRandomValues(这需要更多代码,但在加密方面是合理的)。安全上下文由浏览器强制执行;您无法通过配置或环境变量来解决它。 ToolAcre 生成器通过 HTTPS 部署,因此 crypto.randomUUID 可用。当您在工具中生成 UUID 时,它会使用 randomUUID(如果安全上下文检查通过)或带有位操作的 getRandomValues(如果您使用纯 HTTP,尽管这种情况很少见)。
为什么你不应该使用 Math.random 进行填充——诱人的捷径及其带来的安全成本
两条路径都不会退回到 Math.random。如果您正在构建自己的 UUID 生成器并针对非安全来源,请使用 getRandomValues 并自行执行位操作。在 HTTPS 和 localhost 上进行测试以确认 randomUUID 有效,然后在 http:// 源上进行测试以确认 getRandomValues 后备正确。了解安全上下文限制有助于您设计部署策略。如果您的应用程序必须在没有 HTTPS 的私有 LAN(遗留基础设施、嵌入式系统)上运行,那么 getRandomValues 后备方案就是您的前进道路。如果可以选择,请在所有地方升级到 HTTPS; Let's Encrypt 是免费的,而且投资在整个应用程序的安全性上得到回报。本地主机上的开发没有限制,因此在部署到生产环境之前,请在本地主机和 HTTPS 暂存上测试您的 UUID 生成器。生产应始终采用 HTTPS。
这不包括服务器运行时,例如 Node.js 和 Deno,它们在没有安全上下文规则的情况下公开 API
该限制不是错误或麻烦;而是错误。它是一种安全功能,可以防止意外发生并迫使您考虑加密。更广泛的模式是 Web 加密 API 由安全上下文控制。 crypto.getRandomValues,加密。微妙的。加密,加密。微妙的。 generateKey,以及所有其他敏感操作都需要 HTTPS 或 localhost。没有例外,没有覆盖,没有办法禁用检查。单个不安全的页面会破坏用户的安全保证。即使您小心地仅在某些页面上使用加密 API,错误(或包含 UUID 生成器的依赖项)也可能会将随机生成泄漏到未加密的页面。 ToolAcre 生成器在代码级别强制执行此操作:如果 randomUUID 不可用(非安全上下文),它会使用 getRandomValues,该方法可用,但会提醒任何代码审阅者正在发生异常情况。
要点:修复源头,而不是生成器 — ToolAcre 通过 HTTPS 提供服务,因此其生成器设计为在安全上下文中运行
更好的是,如果安全上下文确实不可用(在 getRandomValues 也不可用的环境中,这种情况很少见,但在较旧的或嵌入式系统中是可能的),它会拒绝生成标识符。将现有系统迁移到 HTTPS 以支持安全加密 API 是一个常见的项目。从生成 UUID 的源(您的身份验证服务器、API 后端或关键应用程序服务)开始。获取 TLS 证书(Let's Encrypt 免费提供)。将您的 Web 服务器配置为默认提供 HTTPS 服务,并将 HTTP 请求重定向到 HTTPS。使用多个浏览器和 API 客户端进行测试,以确保一切正常。然后审核您的代码以查找可能在未加密页面上调用的任何剩余加密 API 并修复它们。 ToolAcre 生成器采用 HTTPS;如果您正在使用它,那么您已经成功了。