使用OpenSSL Dynamic Engine调用CloudHSM加密机内的密钥完成签名和证书签发

本文介绍如何在 Ubuntu 22.04 上使用 AWS CloudHSM OpenSSL Dynamic Engine 完成密钥管理和证书操作。内容涵盖 Dynamic Engine 与OpenSSL Provider 的对比选型、引擎安装配置、RSA 和 ECC(P-256)密钥对的创建与导出、使用 SHA256withRSA 和 SHA256withECDSA进行签名与验签,以及基于 CloudHSM 私钥生成自签名证书和签发下级证书的完整流程。所有签名操作均在 HSM内完成,私钥始终不离开硬件安全模块。

本文介绍如何使用OpenSSL的Dynamic Engine,实现在OpenSSL命令行下调用CloudHSM加密机内的密钥完成签名和证书签发操作。

一、OpenSSL Dynamic Engine 与 OpenSSL Provider 的区别

AWS CloudHSM 提供了两种与 OpenSSL 集成的方式:Dynamic EngineProvider 。在开始操作之前,需要先了解二者的区别和各自的限制。

1、功能对比

对比项 Dynamic Engine Provider
OpenSSL 版本要求 OpenSSL 1.0.2+ OpenSSL 3.2+
OpenSSL CLI 命令行支持 ✅ 支持(-engine cloudhsm 明确不支持
支持的 Web 服务器 NGINX / Apache NGINX / HAProxy
RSA 签名 ✅ PKCS#1 v1.5 ✅ PKCS#1 v1.5 + PSS 填充
ECDSA 签名 ✅ P-256, P-384, secp256k1 ✅ P-256, P-384, P-521
验签 本地 OpenSSL 软件完成 本地 OpenSSL 软件完成

关于 OpenSSL Provider 的重要警告: 官方文档明确声明 “Integration with OpenSSL CLI is not currently supported by AWS CloudHSM OpenSSL Provider”,即 Provider 完全不支持 OpenSSL 命令行集成,Provider这种集成方式只能用于在NGINX上的Offload场景。

2、各自适用场景

OpenSSL Dynamic Engine 适用于:

  • 需要通过 OpenSSL 命令行进行签名操作(如 openssl dgst -engine cloudhsm
  • 需要通过 OpenSSL 命令行生成 CSR 和自签名证书
  • 使用 NGINX 或 Apache 做 SSL/TLS 卸载
  • 运行在 OpenSSL 3.2 以下版本的系统上

OpenSSL Provider 适用于:

  • 使用 OpenSSL 3.2+ 的新部署环境
  • 使用 NGINX 或 HAProxy 做 SSL/TLS 卸载
  • 需要 RSA-PSS 签名填充或 P-521 曲线支持
  • 仅通过 Web 服务器编程方式调用,不需要命令行操作

3、总结

  • 如果你需要 OpenSSL 命令行 操作 CloudHSM → 只能用 Dynamic Engine
  • 如果你只需要 Web 服务器 TLS 卸载 且系统是 OpenSSL 3.2+ → 推荐用 Provider
  • 如果你需要通用的 加密/解密 能力 → 两个方案都不行,请使用 JCE ProviderPKCS#11

4、参考文档


二、Ubuntu 22.04 系统上 OpenSSL Dynamic Engine 库安装

1、概述

本章节介绍如何使用 OpenSSL Dynamic Engine 通过命令行完成 RSA 和 ECC 密钥创建、签名和验签操作:

操作 是否在 CloudHSM 内执行
RSA / ECC 密钥创建 ✅ 是
RSA / ECDSA 签名 ✅ 是
RSA / ECDSA 验签 ❌ 否(在本地 OpenSSL 软件完成)

2、前提条件

  • 已激活的 CloudHSM 集群,至少2个节点
  • 已安装 CloudHSM Client SDK 5
  • 已创建非 Admin 权限的普通加密用户 Crypto User (CU)

3、安装 OpenSSL 动态引擎安装包(区分操作系统)

以Ubuntu 22.04 (x86_64) 系统为例,从官网链接下载对应的操作系统安装包:

wget https://s3.amazonaws.com/cloudhsmv2-software/CloudHsmClient/Jammy/cloudhsm-dyn_latest_u22.04_amd64.deb
sudo apt install ./cloudhsm-dyn_latest_u22.04_amd64.deb

安装完成后,动态引擎库位于 /opt/cloudhsm/lib/libcloudhsm_openssl_engine.so

4、配置 CloudHSM IP 地址

安装完成后,需要将配置文件中的占位符替换为实际的 CloudHSM ENI IP 地址,否则引擎初始化会报错:

Failed to initialize OpenSSL engine, Internal Error: Config key hostname has invalid value %%HSM_IP_ADDRESS%%

1)获取 CloudHSM 的 ENI IP 地址:

aws cloudhsmv2 describe-clusters --query 'Clusters[].Hsms[].EniIp' --output text

2)编辑配置文件,将 %%HSM_IP_ADDRESS%% 替换为实际 IP:

sudo vi /opt/cloudhsm/etc/cloudhsm-dyn.cfg

替换前:

"hostname": "%%HSM_IP_ADDRESS%%"

替换后(示例):

"hostname": "172.31.36.75"

注意: 如果集群中有多个 CloudHSM 节点,可以在 servers 数组中添加多个条目,每个条目对应一个 CloudHSM 的 ENI IP。

5、验证安装

openssl engine -t cloudhsm

预期输出如下表示正常:

(cloudhsm) CloudHSM OpenSSL Engine
     [ available ]

6、设置 OpenSSL Dynamic Engine访问 CloudHSM 的凭证

在执行任何 OpenSSL 引擎操作前,必须设置环境变量:

export CLOUDHSM_PIN=<CU用户名>:<CU密码>

示例:

export CLOUDHSM_PIN=myuser:mypassword

注意: 如果密码中包含 shell 特殊字符(如 !$& 等),需要进行转义。


三、使用 RSA 签名

注意:请确认您的CloudHSM集群内有两个节点,否则OpenSSL CLI调用Dynamic Engine功能可能不正常。

使用 CloudHSM CLI 在 CloudHSM 内生成 RSA 密钥对,支持的算法包括:

  • SHA1withRSA
  • SHA224withRSA
  • SHA256withRSA
  • SHA384withRSA
  • SHA512withRSA

1、使用 CloudHSM CLI 在 CloudHSM 内生成 RSA 2048 密钥对

/opt/cloudhsm/bin/cloudhsm-cli interactive

执行login --username user01 --role crypto-user命令以普通用户身份登陆,输入user01用户的密钥即可完成登陆。

key generate-asymmetric-pair rsa \
    --modulus-size-bits 2048 \
    --public-exponent 65537 \
    --public-label my_rsa_pub \
    --private-label my_rsa_private \
    --private-attributes sign=true

生成成功后会返回 key-reference 等信息。

2、导出 Fake PEM 私钥文件和公钥 PEM 文件

Fake PEM 文件不包含真实私钥数据,仅包含对 CloudHSM 上私钥的引用,供 OpenSSL 引擎识别使用。

key generate-file \
    --encoding reference-pem \
    --path /tmp/my_rsa_private.key \
    --filter attr.label="my_rsa_private"

导出公钥PEM文件。

key generate-file \
    --encoding pem \
    --path /tmp/my_rsa_pub.pem \
    --filter attr.label="my_rsa_pub"

执行quit命令,退出CloudHSM CLI。

3、使用 OpenSSL 引擎进行签名(CloudHSM内执行)

签名操作通过 -engine cloudhsm 参数将签名运算卸载到 CloudHSM,私钥始终保留在 CloudHSM 内部。

首先准备待签名文件:

echo "Hello CloudHSM OpenSSL Engine" > /tmp/message.txt

然后使用 SHA256withRSA 签名。

openssl dgst -engine cloudhsm -sha256 \
    -sign /tmp/my_rsa_private.key \
    -out /tmp/message.sig \
    /tmp/message.txt

返回Engine "cloudhsm" set.表示成功

参数说明:

  • -engine cloudhsm:指定使用 CloudHSM 动态引擎
  • -sha256:使用 SHA-256 哈希算法(数据哈希在本地完成,签名在 CloudHSM 内完成)
  • -sign /tmp/my_rsa_private.key:使用 Fake PEM 私钥文件(引用 CloudHSM 上的真实私钥)
  • -out /tmp/message.sig:输出签名文件
  • /tmp/message.txt:待签名的原始文件

支持的哈希算法:-sha1-sha224-sha256-sha384-sha512

4、使用 OpenSSL 进行验签(本地执行)

验签操作在本地 OpenSSL 软件中完成,不经过 CloudHSM。因此可以不指定 -engine cloudhsm,直接使用公钥验签。

使用公钥验签:

openssl dgst -sha256 \
    -verify /tmp/my_rsa_pub.pem \
    -signature /tmp/message.sig \
    /tmp/message.txt

验签成功输出:

Verified OK

验签失败输出:

Verification Failure

5、生成自签名证书

基于 CloudHSM 上的私钥生成证书:

生成 CSR:

openssl req -engine cloudhsm -new \
    -key /tmp/my_rsa_private.key \
    -out /tmp/my_server.csr

按提示填写证书信息(国家、组织、域名等)。在遇到A challenge password时候可以直接回车不设置。在An optional company name参数也可以直接回车不设置。

使用 CloudHSM 内的私钥签名

openssl x509 -engine cloudhsm -req -days 365 \
    -in /tmp/my_server.csr \
    -signkey /tmp/my_rsa_private.key \
    -out /tmp/my_server.crt

签名成功返回:

Certificate request self-signature ok
subject=C = CN, ST = BEIJING, L = BJ, O = BITIPCMAN, OU = rsa_ops, CN = rsa-ops.bitipcman.com, emailAddress = rsa_ops@bitipcman.com

由此获得/tmp/my_server.crt


四、使用 ECC 密钥进行签名和证书签发

注意:请确认您的CloudHSM集群内有两个节点,否则OpenSSL CLI调用Dynamic Engine功能可能不正常。

除 RSA 外,Dynamic Engine 也支持 ECC(ECDSA)签名。以下演示使用 P-256 曲线完成密钥创建、签名、验签和证书签发的完整流程。OpenSSL 会根据你传入的密钥类型自动选择:

  • ECC 密钥 → ECDSA 签名
  • RSA 密钥 → RSASSA-PKCS1-v1_5 签名

Dynamic Engine 支持的 ECC 曲线: P-256(secp256r1/prime256v1)、P-384(secp384r1)、secp256k1。如需 P-521 支持,请使用 OpenSSL Provider。

1、在 CloudHSM 上创建 ECC 密钥对

/opt/cloudhsm/bin/cloudhsm-cli interactive

执行如下命令以user01身份登陆:

login --username <CU用户名> --role crypto-user

执行如下命令创建证书。

key generate-asymmetric-pair ec \
    --curve secp256r1 \
    --public-label my_ec_pub \
    --private-label my_ec_private \
    --public-attributes verify=true \
    --private-attributes sign=true

由此获得公钥和私钥,都保存在CloudHSM内,并未下载到本地。

2、导出 Fake PEM 私钥和公钥

Fake PEM 文件不包含真实私钥数据,仅包含对 CloudHSM 上私钥的引用,供 OpenSSL 引擎识别使用。

key generate-file \
    --encoding reference-pem \
    --path /home/ubuntu/environment/cloudhsm/test-key-2/my_ec_private.key \
    --filter attr.label="my_ec_private"

导出公钥PEM文件。

key generate-file \
    --encoding pem \
    --path /home/ubuntu/environment/cloudhsm/test-key-2/my_ec_pub.pem \
    --filter attr.label="my_ec_pub"

操作成功的话返回如下:

{
  "error_code": 0,
  "data": {
    "message": "Successfully generated key file"
  }
}

由此在指定目录下获得my_ec_private.keymy_ec_pub.pem两个文件。

执行quit命令,退出CloudHSM CLI。

3、使用 ECDSA 签名(CloudHSM 内执行)

签名操作通过 -engine cloudhsm 参数将签名运算卸载到 CloudHSM,私钥始终保留在 CloudHSM 内部。

首先准备待签名文件:

echo "Hello CloudHSM OpenSSL Engine" > message.txt

针对低于SHA256的算法,需要额外打开例外选项。(以下命令是SHA256,因此不用执行此命令)

sudo /opt/cloudhsm/bin/configure-dyn --enable-ecdsa-with-weak-hash-function
openssl dgst -engine cloudhsm -sha256 \
    -sign /home/ubuntu/environment/cloudhsm/test-key-2/my_ec_private.key \
    -out /home/ubuntu/environment/cloudhsm/test-key-2/ecc_message.sig \
    /home/ubuntu/environment/cloudhsm/test-key-2/ecc_message.txt

返回Engine "cloudhsm" set.表示成功。

OpenSSL 会自动识别密钥类型为 EC,使用 ECDSA 算法进行签名。参数 sha256 指定的是哈希算法部分,组合起来就是:

  • SHA256 + ECDSA = SHA256withECDSA
  • SHA384 + ECDSA = SHA384withECDSA

Dynamic Engine 支持的 ECDSA 曲线是 P-256、P-384 和 secp256k1。

4、使用公钥验签(本地执行)

openssl dgst -sha256 \
    -verify /home/ubuntu/environment/cloudhsm/test-key-2/my_ec_pub.pem \
    -signature /home/ubuntu/environment/cloudhsm/test-key-2/ecc_message.sig \
    /home/ubuntu/environment/cloudhsm/test-key-2/ecc_message.txt

验签成功输出 Verified OK

5、使用 ECC 密钥生成自签名证书

openssl req -engine cloudhsm -new \
    -key /home/ubuntu/environment/cloudhsm/test-key-2/my_ec_private.key \
    -out /home/ubuntu/environment/cloudhsm/test-key-2/my_ec_server.csr

按提示填写证书信息(国家、组织、域名等)。在遇到A challenge password时候可以直接回车不设置。在An optional company name参数也可以直接回车不设置。

由此在对应目录下生成my_ec_server.csr文件。

openssl x509 -engine cloudhsm -req -days 365 \
    -in /home/ubuntu/environment/cloudhsm/test-key-2/my_ec_server.csr \
    -signkey /home/ubuntu/environment/cloudhsm/test-key-2/my_ec_private.key \
    -out /home/ubuntu/environment/cloudhsm/test-key-2/my_ec_server.crt

执行成功返回:

Engine "cloudhsm" set.
Certificate request self-signature ok
subject=C = CN, ST = BEIJING, L = BJ, O = BITIPCMAN, OU = ec-dev, CN = ec-dev.bitipcman.com, emailAddress = ec-dev@bitipcman.com

由此获得my_ec_server.crt文件。

6、使用 ECC CA 密钥签发证书

如果将 ECC 密钥作为 CA 密钥,可以用它签发其他证书:

openssl x509 -engine cloudhsm -req -days 365 \
    -in /home/ubuntu/environment/cloudhsm/test-key-2/my_ec_server.csr \
    -CA /home/ubuntu/environment/cloudhsm/test-key-2/my_ec_server.crt \
    -CAkey /home/ubuntu/environment/cloudhsm/test-key-2/my_ec_private.key \
    -CAcreateserial \
    -out /home/ubuntu/environment/cloudhsm/test-key-2/client-01.crt

签发成功返回:

Engine "cloudhsm" set.
Certificate request self-signature ok
subject=C = CN, ST = BEIJING, L = BJ, O = BITIPCMAN, OU = ec-dev, CN = ec-dev.bitipcman.com, emailAddress = ec-dev@bitipcman.com

由此获得client-01.crt文件。


五、小结

本文主要流程如下:

┌─────────────────────────────────────────────────────────┐
│  1. 安装 OpenSSL 动态引擎                                 │
│  2. export CLOUDHSM_PIN=user:password                    │
│  3. CloudHSM CLI 生成 RSA 或 ECC 密钥对                   │
│  4. 导出 Fake PEM 私钥 + 公钥 PEM                         │
│  5. openssl dgst -engine cloudhsm -sign ... (签名)        │
│  6. openssl dgst -verify ... (验签,本地完成)              │
│  7. openssl req/x509 -engine cloudhsm ... (生成证书,可选) │
└─────────────────────────────────────────────────────────┘

备注:Cloudhsm官方文档说法:

Only RSA offload to the HSM is supported by default:
- Impact: To maximize performance, the SDK is not configured to offload additional functions such as random number generation or EC-DH operations.
- Workaround: Please contact us through a support case if you need to offload additional operations.
- Resolution status: We are adding support to the SDK to configure offload options through a configuration file. The update will be announced on the version history page once available.

这条 known issue 说的是 EC-DH(椭圆曲线 Diffie-Hellman 密钥协商),不是 ECDSA(签名)。两者是不同的操作:

  • EC-DH — 密钥交换/协商协议,用于 TLS 握手中的密钥协商
  • ECDSA — 数字签名算法,用于签名和验签

Dynamic Engine 的 supported mechanisms 页面 (https://docs.aws.amazon.com/cloudhsm/latest/userguide/openssl-mechanisms.html) 明确列出了 SHA256withECDSA 是支持的。这条 known issue 不影响 ECDSA 签名场景。

六、参考链接


最后修改于 2026-03-31