步骤
1.全套证书已经生成。OK
2.找国芯要ECC加密解密签名验签代码。给的逻辑说明没有示例代码很难的上。
3.集成到工具 与SP联调。
1.用openssl全套证书生成及验证
注意:这里CA 签发 KLD 证书用的是SHA256。因为芯片只支持SHA256算法,不支持SHA512。改成统一。
bash
echo 如果有提示,需要把openssl的cnf下的文件复制到提示的目录下
@echo off
setlocal enabledelayedexpansion
:: 设置密码
set PASSWORD=YourPassword
:: 证书信息
set CA_CERT_SUBJ="/C=CN/ST=Beijing/L=Beijing/O=FT/OU=FT/CN=FT_KLD_CA/[email protected]"
set KLD_CERT_SUBJ="/C=CN/ST=Beijing/L=Beijing/O=FT/OU=FT/CN=FT_KLD/[email protected]"
:: 生成 CA 私钥(P-521)并加密
openssl ecparam -name secp521r1 -genkey -out CA_key.pem
openssl pkcs8 -topk8 -inform PEM -outform PEM -in CA_key.pem -out CA_key_enc.pem -passout pass:%PASSWORD%
::del CA_key.pem
echo [INFO] Encrypted CA Private Key generated: CA_key_enc.pem
:: 生成 CA 自签名证书(有效期 10 年)
openssl req -x509 -new -key CA_key_enc.pem -sha512 -days 3650 -subj %CA_CERT_SUBJ% -passin pass:%PASSWORD% -out CA_cert.crt
openssl req -x509 -new -key CA_key_enc.pem -sha512 -days 3650 -subj %CA_CERT_SUBJ% -passin pass:%PASSWORD% -out CA_cert.pem
echo [INFO] CA Certificate generated: CA_cert.pem
:: 生成 KLD 私钥(P-521)并加密
openssl ecparam -name secp521r1 -genkey -out KLD_key.pem
openssl pkcs8 -topk8 -inform PEM -outform PEM -in KLD_key.pem -out KLD_key_enc.pem -passout pass:%PASSWORD%
del KLD_key.pem
echo [INFO] Encrypted KLD Private Key generated: KLD_key_enc.pem
:: 生成 KLD 证书请求(CSR)
openssl req -new -key KLD_key_enc.pem -sha512 -subj %KLD_CERT_SUBJ% -passin pass:%PASSWORD% -out KLD_csr.pem
echo [INFO] KLD Certificate Signing Request generated: KLD_csr.pem
:: 使用 CA 签发 KLD 证书(有效期 10 年),输出为 .crt 格式
openssl x509 -req -in KLD_csr.pem -CA CA_cert.pem -CAkey CA_key_enc.pem -CAcreateserial -sha256 -days 3650 -passin pass:%PASSWORD% -out KLD_cert.crt
echo [INFO] KLD Certificate signed by CA: KLD_cert.crt
:: 清理临时文件
::del CA_cert.srl
::del KLD_csr.pem
echo [SUCCESS] All certificates generated successfully!
echo "查看密钥是否有效"
pause
openssl ec -in CA_key_enc.pem -check -passin pass:%PASSWORD%
openssl ec -in KLD_key_enc.pem -check -passin pass:%PASSWORD%
echo "查看证书信息,确认 "Issuer" 是 CA 证书。"
openssl x509 -in KLD_cert.crt -text -noout
endlocal
pause
导出KLD公私钥
bash
echo # 从加密私钥提取明文私钥
openssl ec -in KLD_key_enc.pem -passin pass:YourPassword -out KLD_key.pem
echo # 从私钥提取公钥
openssl ec -in KLD_key.pem -pubout -out KLD_pub.pem
把证书里的私钥、公钥提取为c语言数组。
python
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import serialization
def format_c_array(name, data, length=68):
"""格式化为 C 语言 uint8_t 数组"""
hex_values = ', '.join(f"0x{b:02X}" for b in data)
return f" uint8_t {name}[{length}] = {{\n {hex_values}\n }};\n"
# 读取私钥
with open("KLD_key.pem", "rb") as f:
private_key = serialization.load_pem_private_key(f.read(), password=None)
# 读取公钥
with open("KLD_pub.pem", "rb") as f:
public_key = serialization.load_pem_public_key(f.read())
# 获取私钥数值
priv_number = private_key.private_numbers().private_value
priv_bytes = priv_number.to_bytes(68, 'big') # 转换成 68 字节大端存储
# 获取公钥数值
pub_numbers = public_key.public_numbers()
x_bytes = pub_numbers.x.to_bytes(68, 'big') # 转换成 68 字节
y_bytes = pub_numbers.y.to_bytes(68, 'big') # 转换成 68 字节
# 格式化为 C 语言数组
print(format_c_array("priv_key", priv_bytes))
print(format_c_array("pub_key_x", x_bytes))
print(format_c_array("pub_key_y", y_bytes))
KLD_cert.crt去头尾,中间做base64解码16进制数组
需要发放KLD_cert.crt到SP验证。
ECC算法工具
有这个工具可以验证:ECC加密解密签名验签。
使芯片算法与PC算法保持一致。
私钥长度 公钥X长度 公钥Y长度 都是68

cpp
#ifndef ECC2_H
#define ECC2_H
#include <openssl/ec.h>
#ifdef __cplusplus
extern "C"
{
#endif
extern uint8_t priv_key_data[68];
extern uint8_t pub_key_x_data[68];
extern uint8_t pub_key_y_data[68];
int KLD_ECC_Privatekey_Decrypt(BYTE* pEncdata, WORD wEncDataLen, BYTE* pExpressData, INT* pwExpressDataLen);
int ECCPublicDecrypt(BYTE* public_key_B, BYTE* pbSignature, BYTE* bHashdata);
int ECCPublicEncrypt(BYTE* pEncdata, WORD wEncDataLen, BYTE* pExpressData, INT* pwExpressDataLen);
int KLD_ECC_Privatekey_Encrypt(BYTE* pEncdata, WORD wEncDataLen, BYTE* pExpressData);
int ECC_ENC(const EC_GROUP* group, const EC_POINT* pub_key, const uint8_t* plain, size_t plain_len, uint8_t* cipher, size_t* cipher_len, BN_CTX* bn_ctx);
int ECC_DEC(const EC_GROUP* group, const BIGNUM* priv_key, const uint8_t* cipher, size_t cipher_len, uint8_t* plain, size_t* plain_len, BN_CTX* bn_ctx);
int ECC_main();
#ifdef __cplusplus
}
#endif
#endif
bash
c++用openssl 3.4.1实现ecc算法的加解密与签名验签示例 代码写在一个文件里
Ecc Curve为P-521,从文件读CA_cert.pem和CA_key_enc.pem,
如果需要 就加上#define OPENSSL_API_COMPAT 10100 // 保持与 1.1.0 兼容
"ECC_Encrypt 算法
输入:明文 M,公钥 P(Px,Py),ECC曲线参数curve(p,a,b,G,n)
输出:密文 C 或 invalid
算法流程:
1. 生成随机数 k ∈ [1, n-1]
2. 计算椭圆曲线点 R(Rx, Ry) = kG
3. 计算椭圆曲线点 Q(Qx, Qy) = kP
4. 按照大端序将明文M转换成整数 m. 如果m==0或m>=n,则输出invalid
5. 计算 c = m * Qx mod n
6. 将点(Rx,Ry)转换成字节串C1,将整数c转换成字节串C2
7. 输出密文 C = C1 || C2
ECC_Decrypt 算法
输入:密文 C = C1 || C2,私钥 d,ECC曲线参数curve(p,a,b,G,n)
输出:明文 M 或 invalid
算法流程:
1. 将字节串C1转换成点R(Rx, Ry), 检查R是否在曲线上,如果不在则输出invalid
2. 计算椭圆曲线点 Q(Qx, Qy) = dR
3. 将字节串C2转换成整数c,计算 m = c * Qx^(-1) mod n
4. 将整数m转换成明文M"
结合芯片提供的接口信息
/*******************************************************************************
* Function Name : ECC_Encrypt
* Description : ECC加密
* Input : -mes :明文数据
* -klen :数据长度
-pstuPubKey :公钥
-pstuEccPrams :椭圆曲线参数
* Output : -cipher :密文数据
* Return : 执行结果
******************************************************************************/
extern UINT8 ECC_Encrypt(unsigned char *mes, unsigned short klen, SM2_STU_PUBKEY *pstuPubKey, SM2_STU_PRAMS *pstuEccPrams, unsigned char *cipher);
/*******************************************************************************
* Function Name : ECC_Encrypt
* Description : ECC加密
* Input : -cipher :密文数据
* -klen :数据长度
-stuPrivKey :私钥
-pstuEccPrams :椭圆曲线参数
* Output : -plain :明文数据
* Return : 执行结果
******************************************************************************/
extern UINT8 ECC_Decrypt(unsigned char *cipher, unsigned short klen, ECC_STU_BIGINT32 *stuPrivKey, SM2_STU_PRAMS *pstuEccPrams, unsigned char *plain);

C++工程加入openssl
C++工程加入openssl 使用的是Win32OpenSSL-3_0_16.exe 好像Win32OpenSSL-3_4_1.exe也行。
C:\Program Files (x86)\OpenSSL-Win32\include;
C:\Program Files (x86)\OpenSSL-Win32\lib\VC\x86\MTd;
libcrypto.lib;libssl.lib;
ECC加解密流程
bash
ECC_Encrypt 算法
输入:明文 M,公钥 P(Px,Py),ECC曲线参数curve(p,a,b,G,n)
输出:密文 C 或 invalid
算法流程:
1. 生成随机数 k ∈ [1, n-1]
2. 计算椭圆曲线点 R(Rx, Ry) = kG
3. 计算椭圆曲线点 Q(Qx, Qy) = kP
4. 按照大端序将明文M转换成整数 m. 如果m==0或m>=n,则输出invalid
5. 计算 c = m * Qx mod n
6. 将点(Rx,Ry)转换成字节串C1,将整数c转换成字节串C2
7. 输出密文 C = C1 || C2
ECC_Decrypt 算法
输入:密文 C = C1 || C2,私钥 d,ECC曲线参数curve(p,a,b,G,n)
输出:明文 M 或 invalid
算法流程:
1. 将字节串C1转换成点R(Rx, Ry), 检查R是否在曲线上,如果不在则输出invalid
2. 计算椭圆曲线点 Q(Qx, Qy) = dR
3. 将字节串C2转换成整数c,计算 m = c * Qx^(-1) mod n
4. 将整数m转换成明文M
ECC加解密算法C代码
bash
在这里插入代码片
500