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