步驟
1.全套證書已經生成。OK
2.找國芯要ECC加密解密簽名驗簽代碼。給的邏輯說明沒有示例代碼很難的上。
3.集成到工具 與SP聯調。
1.用openssl全套證書生成及驗證
注意:這里CA 簽發 KLD 證書用的是SHA256。因為芯片只支持SHA256算法,不支持SHA512。改成統一。
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/emailAddress=ftkdh@ftsafe.com"
set KLD_CERT_SUBJ="/C=CN/ST=Beijing/L=Beijing/O=FT/OU=FT/CN=FT_KLD/emailAddress=ftkdh@ftsafe.com":: 生成 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.pemecho [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 -nooutendlocal
pause
導出KLD公私鑰
echo # 從加密私鑰提取明文私鑰
openssl ec -in KLD_key_enc.pem -passin pass:YourPassword -out KLD_key.pemecho # 從私鑰提取公鑰
openssl ec -in KLD_key.pem -pubout -out KLD_pub.pem
把證書里的私鑰、公鑰提取為c語言數組。
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import serializationdef 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
#ifndef ECC2_H
#define ECC2_H
#include <openssl/ec.h>
#ifdef __cplusplus
extern "C"
{
#endifextern 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
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 || C2ECC_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加解密流程
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 || C2ECC_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代碼
在這里插入代碼片
500