背景:我正在阅读多篇关于使我的golang应用程序符合FIPS要求(换句话说,让我的应用程序使用boringcrypto而不是本地的golang加密)的文章:
- https://kupczynski.info/posts/fips-golang/
- https://developers.redhat.com/articles/2022/05/31/your-go-application-fips-compliant#
# Build a binary and assert that it uses boringcrypto instead of the native golang crypto
RUN GOEXPERIMENT=boringcrypto go build . && \
go tool nm fips-echo-server > tags.txt && \
grep '_Cfunc__goboringcrypto_' tags.txt 1> /dev/null
然后期望得到以下输出:
e70fa0 T _cgo_d3bdb93f8e25_Cfunc__goboringcrypto_AES_cbc_encrypt
e70fc0 T _cgo_d3bdb93f8e25_Cfunc__goboringcrypto_AES_ctr128_encrypt
e70ff0 T _cgo_d3bdb93f8e25_Cfunc__goboringcrypto_AES_decrypt
e71000 T _cgo_d3bdb93f8e25_Cfunc__goboringcrypto_AES_encrypt
e71010 T _cgo_d3bdb93f8e25_Cfunc__goboringcrypto_AES_set_decrypt_key
e71050 T _cgo_d3bdb93f8e25_Cfunc__goboringcrypto_AES_set_encrypt_key
e71200 T _cgo_d3bdb93f8e25_Cfunc__goboringcrypto_BN_bn2le_padded
e71240 T _cgo_d3bdb93f8e25_Cfunc__goboringcrypto_BN_free
e71250 T _cgo_d3bdb93f8e25_Cfunc__goboringcrypto_BN_le2bn
e71300 T _cgo_d3bdb93f8e25_Cfunc__goboringcrypto_BN_new
这段代码将包含_goboringcrypto_
(这意味着该应用程序使用boringcrypto而不是本地的golang加密),或者为空输出(这意味着该应用程序使用本地的golang加密而不是boringcrypto)。
然而,当我在添加GOEXPERIMENT=boringcrypto
时,我的应用程序输出为:
➜ GOEXPERIMENT=boringcrypto CGO_ENABLED=0 go build -o ./bin/app
➜ go tool nm bin/dapp | grep -i boring | cat
11230a0 T crypto/internal/boring.(*PrivateKeyECDH).PublicKey
1123060 T crypto/internal/boring.(*PublicKeyECDH).Bytes
243fba0 D crypto/internal/boring..inittask
243eda0 D crypto/internal/boring/bbig..inittask
1060bc0 T crypto/internal/boring/bcache.registerCache
24efe14 B crypto/internal/boring/fipstls.required
1123040 T crypto/internal/boring/sig.StandardCrypto.abi0
1219c00 T crypto/x509.boringAllowCert
24bfae0 B runtime.boringCaches
➜ go version bin/app
bin/app: go1.20.1 X:boringcrypto
这个与 _goboringcrypto_
没有匹配,但是有 crypto/internal/boring
。
当我打开 crypto/internal/boring
的 文档 时,我可以看到:
包 boring 提供了对 BoringCrypto 实现函数的访问。检查常量 Enabled 可以找出 BoringCrypto 是否可用。如果 BoringCrypto 不可用,则此包中的所有函数都会 panic。
基于此,我有两个快速问题:
- 即使没有与
__goboringcrypto_
完全匹配,我的输出是否在语义上等价?换句话说,它是否确认我的应用程序使用了boringcrypto而不是本机的golang加密库? - 我正在寻找有关FIPS合规性的其他文章,其中一些文章mention使用
CGO_ENABLED=1
(但我正在使用CGO_ENABLED=0
)。当使用golang的1.20.1
版本时,这仍然是一个要求吗?
Go 1.19及更高版本: 从Go 1.19开始,您只需添加 [
BUILD_GOEXPERIMENT=boringcrypto
][18] 和一些相关参数以启用将BoringCrypto集成到标准Go中。
make container \
BUILD_GOEXPERIMENT=boringcrypto \
BUILD_CGO_ENABLED=1 \
BUILD_EXTRA_GO_LDFLAGS="-linkmode=external -extldflags=-static"
话虽如此,本文提到:
自从go 1.19版本以来...在构建时通过GOEXPERIMENT=boringcrypto传递给go工具。就这么简单。
并且根本没有提到CGO_ENABLED
标志。
我只能在go 1.18及更早版本的部分中看到cgo
的提及:
go 1.18及更早版本必须启用cgo。
更新内容:
我找到了另一篇文章,暗示即使对于golang 1.19版本,仍然需要设置
CGO_ENABLED=1
。前一项引用的文章指向
goversion
:
这个 PR 很有趣,它意味着
_Cfunc__goboringcrypto_
等同于 crypto/internal/boring/sig.BoringCrypto
:
还可以查看 goversion/version/read.go
file:
话虽如此,我的输出显示的是 crypto/internal/boring/sig.StandardCrypto
而不是 crypto/internal/boring/sig.BoringCrypto
。
我的结论:
总结起来,看起来如果一个应用程序有任何一个
_Cfunc__goboringcrypto_
crypto/internal/boring/sig.BoringCrypto
go tool nm
命令的输出中,它表示一个应用程序使用了boringcrypto,如果存在的话。
crypto/internal/boring/sig.StandardCrypto
在输出中表示应用程序使用本地的 Golang 加密。