ThalesGroup/crypto11
GitHub: ThalesGroup/crypto11
一个将 Go 标准 crypto 接口桥接到 PKCS#11 HSM 的库,让开发者用熟悉的 API 即可实现硬件级密钥保护。
Stars: 254 | Forks: 90
# Crypto11
[](https://godoc.org/github.com/ThalesIgnite/crypto11)
[](https://travis-ci.com/ThalesIgnite/crypto11)
这是一个使用 [PKCS#11](http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/errata01/os/pkcs11-base-v2.40-errata01-os-complete.html) 作为后端的 Golang 标准 crypto 接口实现。支持的功能包括:
* 生成和检索 RSA、DSA 和 ECDSA 密钥。
* 导入和检索 x509 证书
* PKCS#1 v1.5 签名。
* PKCS#1 PSS 签名。
* PKCS#1 v1.5 解密
* PKCS#1 OAEP 解密
* ECDSA 签名。
* DSA 签名。
* 随机数生成。
* AES 和 DES3 加密及解密。
* HMAC 支持。
签名通过
[crypto.Signer](https://golang.org/pkg/crypto/#Signer) 接口完成,
解密通过
[crypto.Decrypter](https://golang.org/pkg/crypto/#Decrypter) 完成。
要验证签名或加密消息,请检索公钥并在软件中完成。
有关各种限制的详细信息,请参阅 [文档](https://godoc.org/github.com/ThalesIgnite/crypto11),
特别是关于对称加密的部分。
# 安装
从 v1.0.0 版本开始,crypto11 需要 Go v1.11+。通过运行以下命令安装库:
```
go get github.com/ThalesGroup/crypto11
```
crypto11 库需要配置有关 PKCS#11 安装的信息。这可以通过编程方式完成
(参见 [文档](https://godoc.org/github.com/ThalesIgnite/crypto11) 中的 `Config` 结构体)或通过配置
文件完成。配置文件是 `Config` 结构体的 JSON 表示形式。
一个最小配置文件如下所示:
```
{
"Path": "/usr/lib/softhsm/libsofthsm2.so",
"TokenLabel": "token1",
"Pin": "password"
}
```
- `Path` 指向 PKCS#11 供应商提供的库。
- `TokenLabel` 是您希望使用的 token 的 `CKA_LABEL`。
- `Pin` 是 `CKU_USER` 用户的密码。
- `UseGCMIVFromHSM` 从 HSM 生成 GCM 机制的 IV
# 构建
此包使用 CGo 进行加密操作。
在构建 Crypto11 之前启用 CGo:
```
go env -w CGO_ENABLED=1
go build
```
# 测试指南
## 禁用测试
要禁用特定测试,请设置环境变量 `CRYPTO11_SKIP=`,其中 `` 是以下选项的逗号分隔
列表:
* `CERTS` - 禁用与证书相关的测试。AWS CloudHSM 需要此项,因为它不支持证书。
* `OAEP_LABEL` - 禁用使用源数据编码参数(在某些加密库中也称为 'label')的 RSA OAEP 加密测试。AWS CloudHSM 需要此项。
* `DSA` - 禁用 DSA 测试。AWS CloudHSM(以及任何其他不支持 DSA 的 token)需要此项。
## 单个文件的单元测试
```
export DEPENDENCIES="rand.go attributes.go hmac.go crypto11.go common.go keys.go rsa.go certificates.go ecdsa.go blockmode.go sessions.go aead.go dsa.go symmetric.go common_test.go"
go test block_test.go $DEPENDENCIES
```
远程调试:
```
dlv test --headless --listen=:2345 --api-version=2 --accept-multiclient block_test.go $DEPENDENCIES
```
## 使用 AWS CloudHSM 进行测试
CloudHSM 的最小配置文件如下所示:
```
{
"Path": "/opt/cloudhsm/lib/libcloudhsm_pkcs11_standard.so",
"TokenLabel": "cavium",
"Pin": "username:password",
"UseGCMIVFromHSM": true
}
```
要运行测试套件,您必须跳过不支持的测试:
```
CRYPTO11_SKIP=CERTS,OAEP_LABEL,DSA go test -v
```
请务必注意 中描述的支持机制、密钥类型和其他特性。以下是我们在使用 v2.0.4 PKCS#11 库进行测试时注意到的一些事项:
- 尽管 `C_GetMechanismInfo` 显示支持,但似乎不支持 1024 位 RSA 密钥。
- `CKM_RSA_PKCS_OAEP` 机制不支持源数据。即,在构造 `CK_RSA_PKCS_OAEP_PARAMS` 时,
必须将 `pSourceData` 设置为 `NULL`,将 `ulSourceDataLen` 设置为零。
- CloudHSM 将为 GCM 模式生成自己的 IV。这在其文档中进行了描述,请参阅 上的脚注 4。
- 似乎 `CKA_ID` 值必须是唯一的,否则会出现 `CKR_ATTRIBUTE_VALUE_INVALID` 错误。
- 非常快速的会话打开可能会触发以下错误:
C_OpenSession failed with error CKR_ARGUMENTS_BAD : 0x00000007
HSM error 8c: HSM Error: Already maximum number of sessions are issued
## 使用 SoftHSM2 进行测试
设置一个 slot:
```
$ cat softhsm2.conf
directories.tokendir = /home/rjk/go/src/github.com/ThalesIgnite/crypto11/tokens
objectstore.backend = file
log.level = INFO
$ mkdir tokens
$ export SOFTHSM2_CONF=`pwd`/softhsm2.conf
$ softhsm2-util --init-token --slot 0 --label test
=== SO PIN (4-255 characters) ===
Please enter SO PIN: ********
Please reenter SO PIN: ********
=== User PIN (4-255 characters) ===
Please enter user PIN: ********
Please reenter user PIN: ********
The token has been initialized.
```
配置如下所示:
```
$ cat config
{
"Path" : "/usr/lib/softhsm/libsofthsm2.so",
"TokenLabel": "test",
"Pin" : "password"
}
```
(在撰写本文时)OAEP 仅部分支持,HSM 不支持,因此预计会有测试被跳过。
## 使用 nCipher nShield 进行测试
在所有情况下,都值得启用 nShield PKCS#11 日志输出:
```
export CKNFAST_DEBUG=2
```
要使用 1/N 操作员卡集保护密钥:
```
$ cat config
{
"Path" : "/opt/nfast/toolkits/pkcs11/libcknfast.so",
"TokenLabel": "rjk",
"Pin" : "password"
}
```
您也可以通过序列号识别 token,在这种情况下,
这指的是操作员卡集 token 哈希的前 16 位十六进制数字:
```
$ cat config
{
"Path" : "/opt/nfast/toolkits/pkcs11/libcknfast.so",
"TokenSerial": "1d42780caa22efd5",
"Pin" : "password"
}
```
运行 `go test` 时,卡集中的一张卡必须位于 slot 中。
要仅使用模块保护密钥,请使用 'accelerator' token:
```
$ cat config
{
"Path" : "/opt/nfast/toolkits/pkcs11/libcknfast.so",
"TokenLabel": "accelerator",
"Pin" : "password"
}
```
(在撰写本文时)GCM 尚未实现,因此预计会有测试被跳过。
## 使用 TPM 和 PKCS11 进行测试
您必须知道,对于加密操作,tpm2-pkcs11 比其他库(如 softhsm2)受到更多限制。
tpm2-pkcs11 库中缺少 `C_GenerateKey` 函数就是限制的一个例子。
但是,某些测试已经过修改,以支持 tpm2-pkcs11 库的特性。
要使用 TPM 进行测试,您需要:
- 安装虚拟 TPM 或使用机器上的 TPM
- 安装 `libtpm2_pkcs11` 库
- 在 TPM 中创建单元测试所需的所有密钥(因为不支持 C_Generate key)
配置:
```
{
"Path": "/usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1",
"TokenLabel": "mylabel",
"Pin": "mypin"
}
```
微调单元测试以使用您在上一步中创建的密钥。
请注意,否则许多单元测试可能会失败。您必须针对 TPM 使用场景微调用例。
# 限制
* [PKCS1v15DecryptOptions SessionKeyLen](https://golang.org/pkg/crypto/rsa/#PKCS1v15DecryptOptions) 字段
未实现,如果它不为零则返回错误。
原因是 crypto11 无法保证规范中的常量时间行为。
有关进一步讨论,请参阅 [issue #5](https://github.com/ThalesIgnite/crypto11/issues/5)。
* 通过 [cipher.Block](https://golang.org/pkg/crypto/cipher/#Block) 的对称加密支持非常慢。
您可以使用 `BlockModeCloser` API
(在我的计算机上快 400 多倍)
但您必须调用 Close()
接口(在 [cipher.BlockMode](https://golang.org/pkg/crypto/cipher/#BlockMode) 中未找到)。
有关进一步讨论,请参阅 [issue #6](https://github.com/ThalesIgnite/crypto11/issues/6)。
* 单元测试之间可能会相互干扰。您应该微调并选择要运行的 Go 测试文件,一次运行一个。
# 贡献
我们非常感谢收到贡献。在开始进行大规模更改之前,请先开一个 issue
进行讨论。
以下是我们希望涵盖的一些主题:
* 其他 PKCS#11 实现的完整测试说明。
## 漏洞检查
```
$ govulncheck ./... ─╯
Scanning your code and 112 packages across 5 dependent modules for known vulnerabilities...
No vulnerabilities found.
```
标签:AES, crypto.Decrypter, crypto.Signer, CVE, DES3, DNS 反向解析, DSA, ECDSA, EVTX分析, Go, Golang, HMAC, HSM, meg, PKCS#11, RSA, Ruby工具, SamuraiWTF, SoftHSM, Thales, x509证书, 信息安全, 加密, 后端库, 安全编程, 密码学, 手动系统调用, 数字签名, 日志审计, 漏洞扫描器, 硬件安全模块, 解密