赞
踩
本专栏订阅后可查看以下文章
1、基于OpenSSL,实现RSA使用的hash的ASN1编码转换
4、基于OpenSSL,实现SM2签名数据的ASN1编码转换
5、基于OpenSSL,实现SM2密文数据的ASN1编码转换
在实际应用场景中会遇到ASN1数据的编码转换,如,在硬件密码库中使用的API接口和在OpenSSL中使用的接口,很有可能是两种格式数据的表现形式,因此,本文提供以下方式进行数据格式的转换。
-
- /****************************************************************
- * FileName: SM2_sig.c
- * Author: labixiaoxin1849
- * Date: 2022-08-27
- * Description: call of OpenSSL,SM2 key format conversion
- ****************************************************************/
-
- #include <string.h>
- #include <openssl/ec.h>
-
- // SM2算法,而非ECC
-
- // SM2签名数据结构转为ASN1编码
- // sig_r[in] : 签名的r部分
- // sig_s[in] : 签名的s部分
- // pbDer[out] : 转换后的ASN1编码数据
- // uiDerLen[out] : 转换后的ASN1编码数据长度
- int SM2_Signature_Struct_to_Der(const unsigned char *sig_r, const unsigned char *sig_s, unsigned char *pbDer, unsigned int *uiDerLen)
- {
- ECDSA_SIG *xsig;
- BIGNUM *r, *s;
- int ret = -1;
- do {
- r = s = NULL;
- xsig = ECDSA_SIG_new();
-
- r = BN_bin2bn(sig_r, 32, NULL);
- s = BN_bin2bn(sig_s, 32, NULL);
- if (!xsig || !r || !s) {
- break;
- }
-
- if (!ECDSA_SIG_set0(xsig, r, s)) {
- break;
- }
-
- r = s = NULL;
-
- if (pbDer) {
- *uiDerLen = i2d_ECDSA_SIG(xsig, &pbDer);
- } else {
- *uiDerLen = i2d_ECDSA_SIG(xsig, NULL);
- }
-
- if ((int)*uiDerLen < 1) {
- break;
- }
-
- ret = 0;
- } while (0);
-
- if (xsig) {
- ECDSA_SIG_free(xsig);
- }
- if (r) {
- BN_free(r);
- }
- if (s) {
- BN_free(s);
- }
-
- return ret;
- }
-
- // SM2签名数据的ASN1编码转结构
- // pbDer[in] : 转换后的ASN1编码数据
- // uiDerLen[in] : 转换后的ASN1编码数据长度
- // sig_r[out] : 签名的r部分
- // sig_s[out] : 签名的s部分
- int SM2_Signature_Der_to_Struct(const unsigned char *pbDer, unsigned int uiDerLen, unsigned char *sig_r, unsigned char *sig_s)
- {
- unsigned char pbTmp[64] = { 0 };
- int len;
- ECDSA_SIG *xsig;
- int ret = -1;
-
- do {
- xsig = d2i_ECDSA_SIG(NULL, &pbDer, uiDerLen);
- if (!xsig) {
- break;
- }
-
- memset(pbTmp, 0x00, sizeof(pbTmp));
- len = BN_bn2bin(ECDSA_SIG_get0_r(xsig), pbTmp);
- if (len > 32) {
- break;
- }
- memcpy(&sig_r[32 - len], pbTmp, len);
-
- memset(pbTmp, 0x00, sizeof(pbTmp));
- len = BN_bn2bin(ECDSA_SIG_get0_s(xsig), pbTmp);
- if (len > 32) {
- break;
- }
- memcpy(&sig_s[32 - len], pbTmp, len);
- ret = 0;
- } while (0);
-
- if (xsig) {
- ECDSA_SIG_free(xsig);
- }
-
- return ret;
- }
-
- int main(int argc, char *argv[]){
- unsigned char r[32] = {
- 0x37, 0x1B, 0xAE, 0xC3, 0xC2, 0x32, 0x20, 0xEC, 0xF7, 0x91, 0xE3, 0x6B, 0x47, 0x26, 0x04, 0x64,
- 0x5A, 0x69, 0xE1, 0x86, 0x9E, 0x6D, 0x51, 0xC9, 0x85, 0x4E, 0xA1, 0xDD, 0x07, 0xD3, 0x57, 0x9F
- };
- unsigned char s[32] = {
- 0xDF, 0xAE, 0xE5, 0x73, 0xE6, 0x3E, 0x9C, 0xB3, 0xA4, 0x64, 0xDA, 0xB2, 0xEA, 0x83, 0x4F, 0xEB,
- 0x00, 0xF5, 0xD2, 0x64, 0xE1, 0xD6, 0x3F, 0xF0, 0x70, 0x60, 0xC0, 0x61, 0xF4, 0xDE, 0x2E, 0x30
- };
- // 经过编码后的长度大于64
- unsigned char der[128] = {0};
- unsigned int derlen = 0;
-
- unsigned char r2[32] = {0};
- unsigned char s2[32] = {0};
-
- // der_out 设置为NULL可以获得结构长度
- int rv = SM2_Signature_Struct_to_Der(r, s, der, &derlen);
- if(rv != 0){
- return rv;
- }
-
- rv = SM2_Signature_Der_to_Struct(der, derlen, r2, s2);
- if(rv != 0){
- return rv;
- }
-
- if(memcmp(r, r2, 32) != 0 || memcmp(s, s2, 32) != 0) {
- return -1;
- }
- printf("SM2 signature exchange success!!!\n");
- return 0;
- }
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。