Go 博客
Go 密码学安全审计
Go 的标准库中包含一套完整的密码学软件包,可帮助开发人员构建安全的应用程序。Google 最近委托独立的安保公司 Trail of Bits 对核心软件包集进行审计,这些软件包集也作为 新的原生 FIPS 140-3 模块 的一部分进行了验证。审计发现了一个低严重性问题,出现在传统且不受支持的 Go+BoringCrypto 集成 中,以及一些信息性发现。审计报告全文可在此处找到:此处。
审计范围包括我们实现的密钥交换(ECDH 和后量子 ML-KEM)、数字签名(ECDSA、RSA 和 Ed25519)、加密(AES-GCM、AES-CBC 和 AES-CTR)、哈希(SHA-1、SHA-2 和 SHA-3)、密钥派生(HKDF 和 PBKDF2)和认证(HMAC),以及加密随机数生成器。低级别的超大整数和椭圆曲线实现,以及其精密的汇编核心,都包含在内。TLS 和 X.509 等更高级别的协议不在此次审计范围之内。三名 Trail of Bits 工程师参与了为期一个月的审计。
我们为 Go 密码学软件包的安全记录以及此次审计结果感到自豪,这只是我们确保软件包正确性的众多方式之一。首先,我们遵循 密码学原则,积极限制其复杂性,例如优先考虑安全性而非性能。此外,我们采用多种不同技术 对其进行全面测试。我们甚至对内部软件包也力求利用安全的 API,当然,我们还可以依靠 Go 语言特性来避免内存管理问题。最后,我们注重可读性,以使维护更容易,代码审查和审计更有效。
一个低严重性发现
唯一可能被利用的问题 TOB-GOCL-3 具有“低严重性”,这意味着它影响较小且难以触发。此问题已在 Go 1.24 中修复。
至关重要的是,TOB-GOCL-3(下文将进一步讨论)涉及 旧版 Go+BoringCrypto GOEXPERIMENT 中的内存管理,该实验默认未启用,且不支持在 Google 之外使用。
五个信息性发现
其余发现均为“信息性”,这意味着它们不构成即时风险,但与安全最佳实践相关。我们已在当前的 Go 1.25 开发树中解决了这些问题。
发现 TOB-GOCL-1、TOB-GOCL-2 和 TOB-GOCL-6 涉及各种加密操作中可能的时序侧信道。在这三个发现中,只有 TOB-GOCL-2 影响了由于操作秘密值而预期为恒定时间的操作,但它仅影响 Power ISA 目标 (GOARCH ppc64 和 ppc64le)。TOB-GOCL-4 强调了内部 API 中的误用风险,如果将其重新用于当前用例之外的用途。TOB-GOCL-5 指出了一个实际上无法达到的限制的缺失检查。
时序侧信道
发现 TOB-GOCL-1、TOB-GOCL-2 和 TOB-GOCL-6 涉及轻微的时序侧信道。TOB-GOCL-1 和 TOB-GOCL-6 与我们不用于敏感值但将来可能用于此类值的函数有关,而 TOB-GOCL-2 与 Power ISA 上 P-256 ECDSA 的汇编实现有关。
crypto/ecdh,crypto/ecdsa
:字节到字段元素的转换不是恒定时间 (TOB-GOCL-1)
NIST 椭圆曲线的内部实现提供了一种在内部和外部表示之间转换字段元素的方法,该方法以可变时间操作。
该方法的所有使用都对不被视为秘密的公共输入(公共 ECDH 值和 ECDSA 公钥)进行操作,因此我们认为这不是一个安全问题。尽管如此,我们还是决定 将该方法设为恒定时间,以防止将来意外地将此方法与秘密值一起使用,并且我们不必考虑它是否是一个问题。
crypto/ecdsa
:P-256 条件取反在 Power ISA 汇编中不是恒定时间 (TOB-GOCL-2, CVE-2025-22866)
除了 一流 Go 平台 之外,Go 还支持许多其他平台,包括一些不常见的架构。在审查我们各种底层密码原语的汇编实现时,Trail of Bits 团队发现了一个影响 ppc64 和 ppc64le 架构上 ECDSA 实现的问题。
由于在 P-256 点条件取反的实现中使用了条件分支指令,该函数以可变时间而非预期的恒定时间操作。此问题的修复相对简单,用我们已经在其他地方使用的模式替换了条件分支指令,以恒定时间有条件地选择正确的结果。我们将此问题指定为 CVE-2025-22866。
为了优先处理覆盖大多数用户的代码,并且由于针对特定 ISA 需要专业知识,我们通常依靠社区贡献来维护非一流平台的汇编。我们感谢 IBM 的合作伙伴为我们的修复提供审查帮助。
crypto/ed25519
:Scalar.SetCanonicalBytes 不是恒定时间 (TOB-GOCL-6)
内部 edwards25519 包提供了一种在标量的内部和外部表示之间转换的方法,该方法以可变时间操作。
此方法仅用于 ed25519.Verify 的签名输入,这些输入不被视为秘密,因此我们认为这不是一个安全问题。尽管如此,与 TOB-GOCL-1 发现类似,我们还是决定 将该方法设为恒定时间,以防止将来意外地将此方法与秘密值一起使用,并且因为我们知道人们会在标准库之外分叉此代码,并可能将其与秘密值一起使用。
Cgo 内存管理
发现 TOB-GOCL-3 涉及 Go+BoringCrypto 集成中的内存管理问题。
crypto/ecdh
:自定义终结器可能会在使用该内存的 C 函数调用开始时释放内存 (TOB-GOCL-3)
在审查期间,关于我们基于 cgo 的 Go+BoringCrypto 集成有许多问题,该集成提供了 FIPS 140-2 兼容的加密模式,供 Google 内部使用。Go 团队不支持在 Google 之外使用 Go+BoringCrypto 代码,但它对 Google 内部使用 Go 至关重要。
Trail of Bits 团队发现了一个漏洞和一个 非安全相关错误,两者都是与 C 库交互所需的手动内存管理的结果。由于 Go 团队不支持在 Google 之外使用此代码,因此我们选择不为此问题发布 CVE 或 Go 漏洞数据库条目,但我们已在 Go 1.24 中修复了它。
这种陷阱是我们决定放弃 Go+BoringCrypto 集成的众多原因之一。我们一直在开发 原生 FIPS 140-3 模式,该模式使用常规的纯 Go 密码学软件包,使我们能够避免复杂的 cgo 语义,转而采用传统的 Go 内存模型。
实现完整性
发现 TOB-GOCL-4 和 TOB-GOCL-5 涉及两个规范的有限实现,NIST SP 800-90A 和 RFC 8018。
crypto/internal/fips140/drbg
:CTR_DRBG API 存在多种误用风险 (TOB-GOCL-4)
作为我们正在引入的 原生 FIPS 140-3 模式 的一部分,我们需要 NIST CTR_DRBG(基于 AES-CTR 的确定性随机比特生成器)的实现来提供合规的随机性。
由于我们只需要 NIST SP 800-90A Rev. 1 CTR_DRBG 功能的一小部分,因此我们没有实现完整规范,特别是省略了派生函数和个性化字符串。这些功能对于在通用上下文中安全使用 DRBG 至关重要。
由于我们的实现严格限定于我们所需的特定用例,并且由于该实现未公开导出,因此我们认为这是可以接受的,并且值得降低实现的复杂性。我们不期望此实现将来会在内部用于其他目的,并且已在 文档中添加了警告,详细说明了这些限制。
crypto/pbkdf2
:PBKDF2 不强制执行输出长度限制 (TOB-GOCL-5)
在 Go 1.24 中,我们开始了将软件包从 golang.org/x/crypto 移入标准库的过程,结束了一个令人困惑的模式,即第一方、高质量、稳定的 Go 密码学软件包无故保留在标准库之外。
作为此过程的一部分,我们将 golang.org/x/crypto/pbkdf2 软件包移入标准库,作为 crypto/pbkdf2。在审查此软件包时,Trail of Bits 团队注意到我们没有强制执行 RFC 8018 中定义的派生密钥大小限制。
限制为 (2^32 - 1) * <哈希长度>
,超出此限制密钥将循环。使用 SHA-256 时,超出限制将需要超过 137GB 的密钥。我们不期望有人曾使用 PBKDF2 生成如此大的密钥,特别是由于 PBKDF2 在每个块上运行迭代,但为了正确性,我们 现在强制执行标准定义的限制。
下一步是什么
此次审计的结果验证了 Go 团队在开发高质量、易于使用的密码学库方面所做的努力,并应为依赖它们构建安全软件的用户提供信心。
然而,我们并没有止步不前:Go 贡献者仍在继续开发和改进我们为用户提供的密码学库。
Go 1.24 现在包含用纯 Go 编写的 FIPS 140-3 模式,目前正在进行 CMVP 测试。这将为 Go 的所有用户提供受支持的 FIPS 140-3 兼容模式,取代目前不受支持的 Go+BoringCrypto 集成。
我们还在努力实现现代后量子密码学,在 Go 1.24 中在 crypto/mlkem 软件包 中引入 ML-KEM-768 和 ML-KEM-1024 实现,并向 crypto/tls 软件包添加对混合 X25519MLKEM768 密钥交换的支持。
最后,我们计划引入新的更易于使用的高级密码学 API,旨在降低选择和使用高质量算法进行基本用例的门槛。我们计划从提供一个简单的密码哈希 API 开始,该 API 消除了用户决定应该依赖哪种众多可能算法的需要,并提供了自动迁移到最新算法的机制,以适应技术发展。
下一篇文章:[ 关于 | 无 ] 错误处理的语法支持
上一篇文章:使用 testing.B.Loop 实现更可预测的基准测试
博客索引