PCI认证 密钥注入 ECC算法工具 NID_secp521r1 国密算法 openssl 全套证书生成,从证书提取公私钥数组 x,y等

步骤

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

相关推荐
南川琼语12 分钟前
算法——希尔排序
数据结构·算法·排序算法
xiongmaodaxia_z725 分钟前
python数据类型处理题,输出素数题
数据结构·算法
ゞ 正在缓冲99%…2 小时前
leetcode14.最长公共前缀
java·算法·leetcode
2501_915106322 小时前
iOS 设备应用管理实践分享
websocket·网络协议·tcp/ip·http·网络安全·https·udp
神经星星2 小时前
覆盖40+主流模型及数据集,上海交大团队发布一站式蛋白质工程设计平台VenusFactory,一键部署教程已上线
数据库·人工智能·算法
LuckyLay3 小时前
LeetCode算法题(Go语言实现)_49
算法·leetcode·golang
2501_915106323 小时前
flutter 真机调试 ios
websocket·网络协议·tcp/ip·http·网络安全·https·udp
ElseWhereR3 小时前
二进制求和 - 简单
c++·算法·leetcode