#pkcs11 #openpgp #key-management #pkcs #public-key #module #generate-keys

app openpgp-pkcs11-tools

用于在OpenPGP环境中使用PKCS #11设备的命令行工具

2个版本

0.0.2 2023年6月22日
0.0.1 2023年6月15日

#2130密码学

LGPL-2.0-or-later

105KB
1K SLoC

openpgp-pkcs11-tools

该包实现了opgpkcs11,这是一个探索性命令行工具,它将openpgp-pkcs11-sequoia中的功能暴露出来,以便在OpenPGP环境中使用PKCS #11设备。

该工具可用于将OpenPGP组件密钥上传到PKCS #11设备,并使用这些密钥执行OpenPGP签名和解密操作。

此工具还可用于将基于gnupg-pkcs11-scd的设置迁移到Sequoia PGP。在此用例中,需要OpenPGP公钥(或OpenPGP证书)以及PKCS #11设备(OpenPGP证书是访问HSM上不可用的OpenPGP元数据的必要条件)。

通过PKCS #11进行签名

一旦将签名子密钥加载到HSM中,就可以将其用作OpenPGP密钥进行签名(该工具生成一个分离的签名)。

$ echo "hello world" | cargo run --bin opgpkcs11 -- sign --serial 16019180 --id 2
-----BEGIN PGP MESSAGE-----

wsAdBAATCgBvBYJj9RTACRDgxC4SrzU3rkcUAAAAAAAeACBzYWx0QG5vdGF0aW9u
cy5zZXF1b2lhLXBncC5vcmcbgC3H5TAyHrskkS/Df1YhQm0hOxV2PR//4p0LHA7k
cRYhBNbjGCcsr64WE/F/t+DELhKvNTeuAABosAF/Yd26f75FMeP8uSVFR2+4J593
F+O5+U5kx1Fo1IXX6gNhrLuniEq7fDrbflFStbuCAX47Cd/+D/IlC6YSf//W9etl
sd4uMBq3AWNU3IwYJpm3/Zcx0L/2CTVa3hYa/jWmCm8=
=/R5+
-----END PGP MESSAGE-----

注意:在YubiKey 4/5上,--id 2对应于PIV "数字签名"插槽(PIV 9c)。有关ykcs11密钥映射的更多信息,请参阅此处

(如果您的系统上PKCS #11模块的默认路径/usr/lib64/libykcs11.so不正确,您需要通过参数--module提供路径。)

将此分离签名存储在/tmp/sig后,我们可以使用sq进行验证

$ echo "hello world" | sq verify --signer-file /tmp/janus.pgp --detached /tmp/sig
Good signature from E0C42E12AF3537AE
1 good signature.

通过PKCS #11进行解密

类似于签名(上面),PKCS #11设备可以用于执行OpenPGP解密操作

让我们创建一条加密消息

$ echo "secret message!" | sq encrypt --recipient-file /tmp/janus.pgp > /tmp/secret.pgp

(如果您的系统上PKCS #11模块的默认路径/usr/lib64/libykcs11.so不正确,您需要通过参数--module提供路径。)

现在我们可以在卡上解密消息

$ cat /tmp/secret.pgp | cargo run --bin opgpkcs11 -- decrypt --serial 16019180 --id 3
secret message!

注意:在YubiKey 4/5上,--id 3对应于PIV "密钥管理"插槽(PIV 9d)。有关ykcs11密钥映射的更多信息,请参阅此处(ID 5-24可用于访问"退役密钥管理"插槽)。

上传到PKCS #11

cargo run --bin opgpkcs11 -- upload --serial 1234 --id 2 --key /tmp/janus.rsa2 --fingerprint E35AE0F1494FBE1098014BD61E71CF45C4A31FEC

注意:由于ykcs11驱动程序的限制,当前通过ykcs11驱动程序将数据上传到YubiKey 4/5不可用(作为替代方案,可以通过PIV接口将这些OpenPGP密钥上传到这些设备,然后通过PKCS #11进行签名和解密)。

支持PKCS #11的硬件设备

有关可以通过PKCS #11访问的一些特定设备的说明。

YubiKey 4/5

https://developers.yubico.com/PIV/

使用YubiKey PIV CLI工具的示例设置

重置卡片上的PIV应用程序

$ykman piv reset

在槽位'9d'("密钥管理")中生成新密钥,并将公钥导出到文件public-9d.pem

$yubico-piv-tool -s9d -agenerate -AECCP256 -opublic-9d.pem

(要检查公钥ECC文件:openssl ec -pubin -in pubkey.pem -text

在槽位'9a'("PIV认证")中生成新密钥,默认使用RSA,并将公钥导出到文件public-9a.pem

$yubico-piv-tool -s9a -agenerate -opublic-9a.pem

PKCS #11访问的动态库

$export MODULE=/usr/lib64/libykcs11.so

检查卡片上的"对象"

$pkcs11-tool --module $MODULE -O

支持的功能和限制

YubiKey PIV小程序(可以通过PKCS #11接口可选访问)支持RSA 2048、NIST P-256和NIST P-384。支持使用这些算法的密钥进行签名和解密操作。

由于ykcs11驱动程序的限制,目前不支持通过PKCS #11接口上传到卡片。然而,可以使用PIV接口将密钥上传到卡片,然后通过PKCS#11进行加密操作。

注意

YubiHSM 2

https://developers.yubico.com/YubiHSM2/Usage_Guides/YubiHSM_quick_start_tutorial.html

USB访问(udev)

需要授权对USB设备的访问,例如使用以下udev规则

/etc/udev/rules.d/10-yubihsm.rules:

SUBSYSTEM=="usb", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0030", OWNER="username"

如有必要,重新加载规则

# udevadm control --reload-rules

注意:在我的系统中,当连接到USB3端口时,YubiHSM2不起作用。如果遇到问题,请尝试不同的USB端口和/或USB集线器。

yubihsm-connector

"Connector,yubihsm-connector,负责YubiHSM 2与应用程序之间的通信"

https://developers.yubico.com/YubiHSM2/Component_Reference/yubihsm-connector/

$ yubihsm-connector -d

一旦连接器运行,可以通过以下方式测试对YubiHSM的访问

$ yubihsm-shell
Using default connector URL: https://127.0.0.1:12345
yubihsm> connect
Session keepalive set up to run every 15 seconds

注意:在正常操作期间,在我的系统中,我在yubihsm-connector输出中看到常规错误:handle_events: error: libusb: interrupted [code -10]

登录

默认情况下,使用yubihsm-shell登录的方式如下

yubihsm> session open 1 password

yubihsm-shell中,使用KDF方案

列出对象

yubihsm> connect
Session keepalive set up to run every 15 seconds
yubihsm> session open 1 password
Created session 0
yubihsm> list objects 0 0 asymmetric-key
Found 12 object(s)
id: 0x02f1, type: asymmetric-key, algo: rsa2048, sequence: 0 label:
[..]
id: 0xf6bc, type: asymmetric-key, algo: rsa2048, sequence: 0 label:

重置YubiHSM

yubihsm> connect
Session keepalive set up to run every 15 seconds
yubihsm> session open 1 password
Created session 0
yubihsm> reset 0
Device successfully reset

通过PKCS #11使用YubiHSM2

https://developers.yubico.com/yubihsm-shell/yubihsm-pkcs11.html

https://github.com/Yubico/yubihsm-shell/blob/master/lib/yubihsm.c#L579

YubiHSM PKCS #11模块的源代码

https://github.com/Yubico/yubihsm-shell/tree/master/pkcs11

测试

yubihsm_pkcs11.so可以使用配置文件。这里我们使用一个最小文件/tmp/ykhsm.conf

connector=http://localhost:12345

设置

$ export MODULE="/usr/lib64/pkcs11/yubihsm_pkcs11.so"
$ export YUBIHSM_PKCS11_CONF=/tmp/ykhsm.conf
$ export SERIAL=`cargo run --bin opgpkcs11 -- --module $MODULE list`

上传解密子密钥

cargo run --bin opgpkcs11 -- --module $MODULE upload --serial $SERIAL --slot dec --pin 0001password --key /tmp/janus.rsa

解密

echo "hello world" | sq encrypt --recipient-file /tmp/janus.rsa  >/tmp/enc
cat /tmp/enc | cargo run --bin opgpkcs11 -- --module $MODULE decrypt --serial $SERIAL --pin 0001password

签名

echo "hello world" | cargo run --bin opgpkcs11 -- --module $MODULE sign --serial $SERIAL --pin 0001password

检查卡片状态

cargo run --bin opgpkcs11 -- --module $MODULE dump --serial $SERIAL --pin 0001password

支持的功能

支持所有操作(密钥上传、签名、解密)对于RSA 2048、RSA 3072、RSA 4096、NIST P-256、NIST P-384和NIST P-521。

PKCS #11的软件实现

SoftHSM2

https://github.com/opendnssec/SoftHSMv2

示例设置/使用

(当前Fedora的路径,在不同发行版上确切路径可能不同)

创建临时存储路径并配置SoftHSM使用它

$export SOFTHSM2_CONF=$(mktemp) && DIR=$(mktemp --目录) && echo "directories.tokendir =$DIR" > $SOFTHSM2_CONF

$export MODULE=/usr/lib64/softhsm/libsofthsm.so

在SoftHSM上初始化'槽0',设置用户PIN为123456,在槽0生成RSA密钥

$ pkcs11-tool --init-token --module $MODULE --slot-index 0 --label TestToken --so-pin 12345678
$ pkcs11-tool --init-pin --login --so-pin 12345678 --pin 123456 --slot-index 0 --module $MODULE
$ pkcs11-tool --module $MODULE --slot-index 0 --login --pin 123456 --keypairgen --key-type rsa:2048 --id 3

检查卡片(需要用户PIN)

$pkcs11-tool --module $MODULE --test --pin 123456

使用SoftHSM测试opgpkcs11

"SoftHSM是通过PKCS #11接口访问的加密存储的实现。"

初始化(Fedora的模块路径,其他系统可能不同)

export SOFTHSM2_CONF=$(mktemp) && DIR=$(mktemp --directory) && echo "directories.tokendir = $DIR" > $SOFTHSM2_CONF
export MODULE=/usr/lib64/softhsm/libsofthsm.so

pkcs11-tool --init-token --module $MODULE --slot-index 0 --label TestToken --so-pin 123456
pkcs11-tool --init-pin --login --so-pin 123456 --pin 123456 --slot-index 0 --module $MODULE

生成用于测试的OpenPGP密钥

cargo run --bin janus_gen rsa2048 >/tmp/janus.rsa

将解密子密钥上传到SoftHSM

您可以使用以下命令将SoftHSM设备的序列号存储在环境变量SERIAL

export SERIAL=`cargo run --bin opgpkcs11 -- --module $MODULE list`
cargo run --bin opgpkcs11 -- --module $MODULE upload --serial $SERIAL --slot dec --key /tmp/janus.rsa

加密到密钥,在卡片上解密

echo "hello world" | sq encrypt --recipient-file /tmp/janus.rsa  >/tmp/enc.janus
cat /tmp/enc.janus | cargo run --bin opgpkcs11 -- --module $MODULE decrypt --serial $SERIAL

支持的功能

在此设备上,所有操作(密钥上传、签名、解密)均支持以下算法:RSA 2048、RSA 3072、RSA 4096、NIST P-256、NIST P-384和NIST P-521。

cli/ci/softhsm下的CI测试测试所有支持算法的全部操作集。

依赖项

~31-42MB
~751K SLoC