Go 博客
FIPS 140-3 Go 加密模块
FIPS 140 是密码学实现的标准,尽管它不一定能提高安全性,但在某些日益采用 Go 的受监管环境中,FIPS 140 合规性是强制要求。到目前为止,FIPS 140 合规性一直是 Go 用户面临的一个重大摩擦点,需要使用不受支持的解决方案,这些解决方案存在安全性、开发者体验、功能性、发布速度和合规性问题。
Go 正在通过内置于标准库和 go
命令中的原生 FIPS 140 支持来满足这一日益增长的需求,使 Go 成为遵守 FIPS 140 最简单、最安全的方式。经验证的 FIPS 140-3 Go 加密模块现在构成了 Go 内置加密库的基础,从去年 2 月发布的 Go 1.24 中包含的 Go 加密模块 v1.0.0 开始。
v1.0.0 模块已获得 密码算法验证程序 (CAVP) 证书 A6650,并已提交给密码模块验证程序 (CMVP),并于 5 月进入 正在处理的模块列表 (Modules In Process List)。MIP 列表中的模块正在等待 NIST 审查,并且已经可以在某些受监管环境中部署。
Geomys 与 Go 安全团队合作领导了实现工作,并正在为 Go 社区的利益寻求广泛适用的 FIPS 140-3 验证。Google 和其他行业利益相关者与 Geomys 签订了合同关系,以在证书中包含特定的操作环境。
有关模块的更多详细信息可在文档中找到。
一些 Go 用户目前依赖 Go+BoringCrypto GOEXPERIMENT 或其分支之一作为其 FIPS 140 合规策略的一部分。与 FIPS 140-3 Go 加密模块不同,Go+BoringCrypto 从未得到官方支持,并且存在严重的开发者体验问题,因为它完全是为 Google 的内部需求而生产的。一旦 Google 迁移到原生模块,它将在未来的版本中删除。
原生开发者体验
该模块完全透明地集成到 Go 应用程序中。事实上,每个使用 Go 1.24 构建的 Go 程序都已将其用于所有 FIPS 140-3 批准的算法!该模块只是标准库 crypto/internal/fips140/...
包的另一个名称,这些包提供了 crypto/ecdsa
和 crypto/rand
等包所公开操作的实现。
这些包不涉及 cgo,这意味着它们像任何其他 Go 程序一样进行交叉编译,它们不产生 FFI 性能开销,并且它们不像 Go+BoringCrypto 及其分支那样遭受 内存管理安全问题。
启动 Go 二进制文件时,可以使用 fips140=on
GODEBUG 选项将模块置于 FIPS 140-3 模式,该选项可以设置为环境变量或通过 go.mod
文件设置。如果启用了 FIPS 140-3 模式,模块将使用 NIST DRBG 进行随机性生成,crypto/tls
将自动仅协商 FIPS 140-3 批准的 TLS 版本和算法,并且它将在初始化和密钥生成期间执行强制性自检。就是这样;没有其他行为差异。
还有一个实验性的更严格模式,fips140=only
,它会导致所有未经批准的算法返回错误或触发 panic。我们理解这对于大多数部署来说可能过于不灵活,并且正在寻求反馈,以了解策略执行框架可能是什么样子。
最后,应用程序可以使用 GOFIPS140
环境变量来针对较旧的、经过验证的 crypto/internal/fips140/...
包版本进行构建。GOFIPS140
的工作方式类似于 GOOS
和 GOARCH
,如果设置为 GOFIPS140=v1.0.0
,程序将针对这些包提交给 CMVP 进行验证时的 v1.0.0 快照进行构建。此快照随 Go 标准库的其余部分一起提供,作为 lib/fips140/v1.0.0.zip
。
使用 GOFIPS140
时,fips140
GODEBUG 默认为 on
,因此综上所述,所有针对 FIPS 140-3 模块构建并在 FIPS 140-3 模式下运行所需的一切就是 GOFIPS140=v1.0.0 go build
。就是这样。
如果工具链是使用设置了 GOFIPS140
构建的,则它生成的所有构建都将默认为该值。
用于构建二进制文件的 GOFIPS140
版本可以使用 go version -m
进行验证。
Go 的未来版本将继续与 Go 加密模块的 v1.0.0 一起发布和工作,直到下一个版本由 Geomys 完全认证,但在针对旧模块构建时,某些新的加密功能可能不可用。从 Go 1.24.3 开始,您可以使用 GOFIPS140=inprocess
动态选择 Geomys 验证已达到“正在处理”阶段的最新模块。Geomys 计划每年至少验证一次新的模块版本,以避免 FIPS 140 构建落后太多,并且每当模块中的漏洞无法在调用标准库代码中得到缓解时,也会进行验证。
不妥协的安全性
我们开发模块的首要任务是匹配或超越现有 Go 标准库密码包的安全性。这可能令人惊讶,但有时实现和证明符合 FIPS 140 安全要求最简单的方法并不是超越它们。我们拒绝接受这一点。
例如,crypto/ecdsa
始终生成对冲签名。对冲签名通过结合私钥、消息和随机字节生成 nonce。与确定性 ECDSA 一样,它们可以防止随机数生成器故障,否则会导致私钥泄露 (!)。与确定性 ECDSA 不同,它们还能够抵抗 API 问题和故障攻击,并且不会泄露消息等价性。FIPS 186-5 引入了对 RFC 6979 确定性 ECDSA 的支持,但不支持对冲 ECDSA。
我们没有在 FIPS 140-3 模式下(或者更糟糕的是,在不同模式下)降级到常规随机或确定性 ECDSA 签名,而是切换了对冲算法,并连接了半打文档中的点,以证明新算法是 DRBG 和传统 ECDSA 的合规组合。在此过程中,我们还添加了确定性签名的可选支持。
另一个例子是随机数生成。FIPS 140-3 对加密随机数的生成方式有严格规定,这实质上强制使用用户空间 CSPRNG。相反,我们认为内核最适合生成安全的随机字节,因为它最适合从系统中收集熵,并检测进程甚至虚拟机何时被克隆(这可能导致假定的随机字节被重复使用)。因此,crypto/rand 将每个读取操作路由到内核。
为了解决这个问题,在 FIPS 140-3 模式下,我们维护一个基于 AES-256-CTR 的合规用户空间 NIST DRBG,然后在每个读取操作中注入从内核获取的 128 位数据。为了 FIPS 140-3 的目的,这种额外的熵被认为是“未计入”的附加数据,但实际上,它使其与直接从内核读取一样强大——即使速度较慢。
最后,Go 加密模块 v1.0.0 的所有内容都在 Trail of Bits 最近的安全审计范围内,并且未受唯一非信息性发现的影响。
结合 Go 编译器和运行时提供的内存安全保证,我们相信这实现了我们的目标,即让 Go 成为 FIPS 140 合规性最简单、最安全的解决方案之一。
广泛的平台支持
FIPS 140-3 模块只有在经过测试或“供应商确认”的操作环境中运行才符合要求,这实际上是操作系统和硬件平台的组合。为了尽可能多地启用 Go 用例,Geomys 验证在业内最全面的操作环境集合之一上进行了测试。
Geomys 的实验室在 x86-64(AMD 和 Intel)、ARMv8/9(Ampere Altra、Apple M、AWS Graviton 和 Qualcomm Snapdragon)、ARMv7、MIPS、z/ Architecture 和 POWER 的混合平台上测试了各种 Linux 版本(Podman 上的 Alpine Linux、Amazon Linux、Google Prodimage、Oracle Linux、Red Hat Enterprise Linux 和 SUSE Linux Enterprise Server)、macOS、Windows 和 FreeBSD,总共有 23 个测试环境。
其中一些由利益相关者付费,另一些由 Geomys 为 Go 社区的利益提供资金。
此外,Geomys 验证列出了广泛的通用平台作为供应商确认的操作环境
- x86-64 和 ARMv7/8/9 上的 Linux 3.10+,
- Apple M 处理器上的 macOS 11–15,
- x86-64 上的 FreeBSD 12–14,
- x86-64 上的 Windows 10 和 Windows Server 2016–2022,以及
- x86-64 和 ARMv8/9 上的 Windows 11 和 Windows Server 2025。
全面的算法覆盖
这可能令人惊讶,但即使在受支持的操作环境上使用由 FIPS 140-3 模块实现的 FIPS 140-3 批准的算法,也不一定足以符合要求;该算法必须在验证过程中经过专门测试。因此,为了尽可能轻松地在 Go 中构建符合 FIPS 140 的应用程序,标准库中所有 FIPS 140-3 批准的算法都由 Go 加密模块实现,并作为验证的一部分进行了测试,从数字签名到 TLS 密钥调度。
Go 1.24 中引入的后量子 ML-KEM 密钥交换(FIPS 203)也经过验证,这意味着 crypto/tls
可以通过 X25519MLKEM768 建立符合 FIPS 140-3 的后量子安全连接。
在某些情况下,我们在多个不同的 NIST 命名下验证了相同的算法,以便它们可以完全合规地用于不同的目的。例如,HKDF 在四个名称下进行了测试和验证:SP 800-108 Feedback KDF、SP 800-56C two-step KDF、Implementation Guidance D.P OneStepNoCounter KDF 和 SP 800-133 Section 6.3 KDF。
最后,我们验证了一些内部算法,例如 CMAC Counter KDF,以便能够公开未来的功能,例如 XAES-256-GCM。
总的来说,原生 FIPS 140-3 模块提供了比 Go+BoringCrypto 更好的合规性配置文件,同时为 FIPS 140-3 受限应用程序提供了更多算法。
我们期待新的原生 Go 加密模块能够让 Go 开发者更容易、更安全地运行符合 FIPS 140 的工作负载。
下一篇文章:Go 1.25 发布
上一篇文章:泛型接口
博客索引