CloudHSM Java JCE Provider 实现 ECC 签名和证书签发
本文介绍如何使用 Java JCE Provider (SDK 5) 实现与 OpenSSL Dynamic Engine 在CLI下操作等效的 ECC 密钥生成、ECDSA 签名、自签名证书和 CA 签发证书功能。
本文与这篇文章(点这里跳转) 实现相同的操作。区别是这篇文章采用OpenSSL的CLI命令行工具操作,本文使用Java代码调用JCE Provider SDK实现。
一、项目结构
java-ecc-demo/
├── pom.xml
├── .gitignore
└── src/main/java/com/example/cloudhsm/
├── ECCKeyGenAndExport.java → ecc-keygen.jar
├── ECDSAFileSigner.java → ecdsa-sign.jar
├── SelfSignedCertGenerator.java → self-signed-cert.jar
└── CAIssueCert.java → ca-issue-cert.jar
二、Java 文件与 OpenSSL 文档的对应关系
| 序号 | Java 文件 | jar 包 | 对应 OpenSSL 章节四 |
|---|---|---|---|
| 1 | ECCKeyGenAndExport.java |
ecc-keygen.jar |
标题1(创建 ECC P-256 密钥对)+ 标题2(导出 Fake PEM 和公钥 PEM) |
| 2 | ECDSAFileSigner.java |
ecdsa-sign.jar |
标题3(ECDSA 签名 ecc_message.txt) |
| 3 | SelfSignedCertGenerator.java |
self-signed-cert.jar |
标题5(自签名证书,CA 信息使用指定的配置) |
| 4 | CAIssueCert.java |
ca-issue-cert.jar |
标题6(CA 签发新证书) |
三、关键设计说明
- 密钥 label 使用
jce_ec_private/jce_ec_pub,与 OpenSSL 文档中的my_ec_private/my_ec_pub区分开 - 算法与 OpenSSL 保持一致:ECC P-256 (secp256r1) + SHA256withECDSA
- JCE Provider 中私钥不可导出(
getEncoded()返回 null),通过 label 引用等效于 OpenSSL 的 Fake PEM 机制 - 证书生成使用 BouncyCastle 的
JcaX509v3CertificateBuilder,签名通过自定义CloudHsmContentSigner转发到 CloudHSM
四、JCE Provider SDK 初始化
在运行本项目之前,需要先完成 CloudHSM JCE Provider SDK 5 的安装和初始化配置。
1、安装 JCE Provider SDK
以 Ubuntu 22.04 (x86_64) 为例,从官网下载并安装:
wget https://s3.amazonaws.com/cloudhsmv2-software/CloudHsmClient/Jammy/cloudhsm-jce_latest_u22.04_amd64.deb
sudo apt install ./cloudhsm-jce_latest_u22.04_amd64.deb
安装完成后,SDK jar 文件位于 /opt/cloudhsm/java/ 目录下,配置工具位于 /opt/cloudhsm/bin/configure-jce。
2、配置 CloudHSM 集群 IP 地址
使用 configure-jce 工具将 CloudHSM 节点的 ENI IP 写入配置文件:
sudo /opt/cloudhsm/bin/configure-jce -a 172.31.17.81
如果集群中有多个 HSM 节点,可以同时指定多个 IP:
sudo /opt/cloudhsm/bin/configure-jce -a 172.31.17.81 172.31.36.75
执行后会自动更新配置文件 /opt/cloudhsm/etc/cloudhsm-jce.cfg,内容类似:
{
"clusters": [
{
"type": "hsm1",
"cluster": {
"hsm_ca_file": "/opt/cloudhsm/etc/customerCA.crt",
"servers": [
{
"hostname": "172.31.17.81",
"port": 2223,
"enable": true
}
]
}
}
],
"logging": {
"log_type": "file",
"log_file": "/opt/cloudhsm/run/cloudhsm-jce.log",
"log_level": "info",
"log_interval": "daily"
}
}
3、确认 CA 证书
激活 CloudHSM 集群时生成的 CA 证书需要存放在 /opt/cloudhsm/etc/customerCA.crt,SDK 初始化时会使用该证书与 HSM 节点建立 TLS 连接。
4、设置 CU 用户凭证
JCE Provider SDK 5 通过环境变量传递 Crypto User (CU) 的登录凭证:
export HSM_USER=<CU用户名>
export HSM_PASSWORD=<CU密码>
5、Java 代码中加载 Provider
相关代码请参考本文Github网址:https://github.com/aobao32/cloudhsm-openssl-dynamic-engine/java-ecc-demo/
以下为简单讲解:
在 Java 代码中通过以下方式加载 CloudHSM JCE Provider:
import com.amazonaws.cloudhsm.jce.provider.CloudHsmProvider;
import java.security.Security;
// 方式一:添加到 Provider 列表末尾
Security.addProvider(new CloudHsmProvider());
// 方式二:添加到最高优先级(确保所有加密操作优先使用 CloudHSM)
Security.insertProviderAt(new CloudHsmProvider(), 1);
加载 Provider 后,通过指定 CloudHsmProvider.PROVIDER_NAME 即可将密钥生成、签名等操作路由到 CloudHSM:
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", CloudHsmProvider.PROVIDER_NAME);
Signature sig = Signature.getInstance("SHA256withECDSA", CloudHsmProvider.PROVIDER_NAME);
五、构建环境准备
1、安装 CloudHSM JCE SDK 到本地 Maven 仓库
CloudHSM JCE SDK 的 jar 包不在 Maven 中央仓库中,需要手动安装到本地 Maven 仓库后才能作为依赖被 fat-jar 构建引用。
SDK 安装包(deb)安装后,jar 文件位于 /opt/cloudhsm/java/ 目录下。执行以下命令将其注册到本地 Maven 仓库:
mvn install:install-file \
-Dfile=/opt/cloudhsm/java/cloudhsm-jce-5.17.0.jar \
-DgroupId=com.amazonaws \
-DartifactId=cloudhsm-jce \
-Dversion=5.17.0 \
-Dpackaging=jar
安装成功后可在 ~/.m2/repository/com/amazonaws/cloudhsm-jce/5.17.0/ 目录下看到对应文件。
2、构建 fat-jar
进入项目目录,执行 Maven 构建:
cd java-ecc-demo
mvn clean package
构建完成后在 target/ 目录下生成 4 个可独立运行的 fat-jar:
target/
├── ecc-keygen.jar (约 22MB)
├── ecdsa-sign.jar (约 22MB)
├── self-signed-cert.jar (约 22MB)
└── ca-issue-cert.jar (约 22MB)
fat-jar 使用 maven-shade-plugin 将 CloudHSM JCE SDK、BouncyCastle 等所有依赖打包在一起,可直接通过 java -jar 运行。
六、运行代码
1、设置环境变量
export HSM_USER=<CU用户名>
export HSM_PASSWORD=<CU密码>
2、步骤1:生成 ECC 密钥对 + 导出公钥 PEM
java -jar target/ecc-keygen.jar
在 CloudHSM 内生成 ECC P-256 密钥对,密钥 label 为 jce_ec_private / jce_ec_pub,并导出公钥 PEM 文件 jce_ec_pub.pem到当前目录。后续操作中使用 label “jce_ec_private” 引用私钥。
返回结果如下:
使用用户: user01 连接到CloudHSM...
--- 步骤1:在 CloudHSM 内生成 ECC P-256 密钥对 ---
ECC P-256 密钥对生成成功!
私钥 label: jce_ec_private
公钥 label: jce_ec_pub
--- 步骤2:导出 Fake PEM 私钥引用和公钥 PEM ---
公钥 PEM 已保存到: jce_ec_pub.pem
私钥 getEncoded() 返回 null(不可导出,符合预期)
说明:JCE Provider 中私钥始终保留在 CloudHSM 内,
通过 label "jce_ec_private" 在后续签名/证书操作中引用。
这等效于 OpenSSL Dynamic Engine 的 Fake PEM 机制。
✅ 密钥生成和导出完成
后续操作中使用 label "jce_ec_private" 引用私钥
公钥 PEM 文件: jce_ec_pub.pem
3、步骤2:ECDSA 文件签名
echo "Hello CloudHSM OpenSSL Engine" > ecc_message.txt
java -jar target/ecdsa-sign.jar
使用 SHA256withECDSA 对 ecc_message.txt 签名,输出签名文件 ecc_message.sig。
执行成功返回信息如下:
使用用户: user01 连接到CloudHSM...
已找到私钥: jce_ec_private
签名完成!
待签名文件: ecc_message.txt
签名输出: ecc_message.sig (71 bytes)
签名算法: SHA256withECDSA
4、步骤3:生成自签名证书
java -jar target/self-signed-cert.jar
生成自签名证书 jce_ec_server.crt,CA 信息为:
/C=CN/ST=BJ/L=BEIJING/O=BITIPCMAN/OU=DEV/CN=dev.bitipcman.com/emailAddress=dev_admin@bitipcman.com
执行成功返回信息如下:
使用用户: user01 连接到CloudHSM...
已找到密钥对: jce_ec_private / jce_ec_pub
自签名证书生成成功!
证书文件: jce_ec_server.crt
Subject: EMAILADDRESS=dev_admin@bitipcman.com, CN=dev.bitipcman.com, OU=DEV, O=BITIPCMAN, L=BEIJING, ST=BJ, C=CN
Issuer: EMAILADDRESS=dev_admin@bitipcman.com, CN=dev.bitipcman.com, OU=DEV, O=BITIPCMAN, L=BEIJING, ST=BJ, C=CN
有效期: Wed Apr 01 14:44:59 UTC 2026 ~ Thu Apr 01 14:44:59 UTC 2027
签名算法: SHA256withECDSA
由此在当前目录下获得了jce_ec_server。
5、步骤4:CA 签发新证书
java -jar target/ca-issue-cert.jar
使用步骤3生成的自签名证书作为 CA,签发客户端证书 jce_client-01.crt。
返回结果如下:
使用用户: user01 连接到CloudHSM...
已加载 CA 证书: EMAILADDRESS=dev_admin@bitipcman.com, CN=dev.bitipcman.com, OU=DEV, O=BITIPCMAN, L=BEIJING, ST=BJ, C=CN
已找到 CA 私钥: jce_ec_private
--- 为客户端生成新的 ECC P-256 密钥对 ---
客户端密钥对生成成功
✅ CA 签发证书成功!
客户端证书文件: jce_client-01.crt
Subject: EMAILADDRESS=client01@bitipcman.com, CN=client01.bitipcman.com, OU=DEV, O=BITIPCMAN, L=BEIJING, ST=BJ, C=CN
Issuer: C=CN, ST=BJ, L=BEIJING, O=BITIPCMAN, OU=DEV, CN=dev.bitipcman.com, EMAILADDRESS=dev_admin@bitipcman.com
有效期: Wed Apr 01 14:46:32 UTC 2026 ~ Thu Apr 01 14:46:32 UTC 2027
签名算法: SHA256withECDSA
由此在当前目录下获得jce_client-01.crt。
七、参考代码
https://github.com/aobao32/cloudhsm-openssl-dynamic-engine/java-ecc-demo/
最后修改于 2026-04-01