赞
踩
本专栏订阅后可查看以下文章
1、基于OpenSSL,实现RSA使用的hash的ASN1编码转换
4、基于OpenSSL,实现SM2签名数据的ASN1编码转换
5、基于OpenSSL,实现SM2密文数据的ASN1编码转换
在实际应用场景中会遇到ASN1数据的编码转换,如,在硬件密码库中使用的API接口和在OpenSSL中使用的接口,很有可能是两种格式数据的表现形式,因此,本文提供以下方式进行数据格式的转换。
由于SM2密文格式分为C1C3C2和C1C2C3两种格式,所以在OpenSSL中并没有提供定义的ASN1编码结构和相关函数的定义,因为,需要用户自己定义ASN1编码的结构体。具体如下:
- /****************************************************************
- * FileName: SM2_cipher.c
- * Author: labixiaoxin1849
- * Date: 2022-08-27
- * Description: call of OpenSSL,RSA key format conversion
- ****************************************************************/
-
-
- #include <string.h>
- #include <openssl/ec.h>
- #include <openssl/asn1.h>
- #include <openssl/asn1t.h>
-
- // 自定义ASN1编码结构
- typedef struct SM2_Ciphertext_st SM2_Ciphertext;
- DECLARE_ASN1_FUNCTIONS(SM2_Ciphertext)
- struct SM2_Ciphertext_st {
- BIGNUM *C1x;
- BIGNUM *C1y;
- ASN1_OCTET_STRING *C3;
- ASN1_OCTET_STRING *C2;
- };
-
- // SM2密文转ASN1编码(ASN1编码格式由上述SM2_Ciphertext_st定义)
- // cipher_x[in] : 密文C1的x分量,长度为32,不是公钥的x坐标
- // cipher_y[in] : 密文C1的y分量,长度为32,不是公钥的y坐标
- // cipher_m[in] : 密文C3,长度为32,原文的哈希值
- // cipher_c[in] : 密文C2
- // cipher_l[in] : 密文C2的长度
- // pbDer[out] : ASN1编码的SM2密文
- // uiDerLen[out] : ASN1编码的SM2密文长度
- int SM2_Cipher_Struct_to_Der(unsigned char *cipher_x, unsigned char *cipher_y, unsigned char *cipher_m, unsigned char *cipher_c, unsigned int cipher_l, unsigned char *pbDer, unsigned int *uiDerLen)
- {
- SM2_Ciphertext *xcipher;
- BIGNUM *x, *y;
- int ret = 1;
-
- do {
- x = y = NULL;
- xcipher = SM2_Ciphertext_new();
- x = BN_bin2bn(cipher_x, 32, NULL);
- y = BN_bin2bn(cipher_y, 32, NULL);
- if (!xcipher || !x || !y) {
- break;
- }
-
- if (xcipher->C1x) {
- BN_free(xcipher->C1x);
- }
- xcipher->C1x = x;
-
- if (xcipher->C1y) {
- BN_free(xcipher->C1y);
- }
- xcipher->C1y = y;
-
- x = y = NULL;
-
- if (!ASN1_OCTET_STRING_set(xcipher->C3, cipher_m, 32)) {
- break;
- }
-
- if (!ASN1_OCTET_STRING_set(xcipher->C2, cipher_c, cipher_l)) {
- break;
- }
- if (pbDer) {
- *uiDerLen = i2d_SM2_Ciphertext(xcipher, &pbDer);
- }
- else {
- *uiDerLen = i2d_SM2_Ciphertext(xcipher, NULL);
- }
- if ((int)*uiDerLen < 1) {
- break;
- }
-
- ret = 0;
- } while (0);
-
- if (xcipher) {
- SM2_Ciphertext_free(xcipher);
- }
- if (x) {
- BN_free(y);
- }
- if (x) {
- BN_free(y);
- }
-
- return ret;
- }
-
- // SM2密文ASN1编码转结构(ASN1编码格式由上述SM2_Ciphertext_st定义)
- // pbDer[in] : ASN1编码的SM2密文
- // uiDerLen[in] : ASN1编码的SM2密文长度
- // cipher_x[out] : 密文C1的x分量,长度为32,不是公钥的x坐标
- // cipher_y[out] : 密文C1的y分量,长度为32,不是公钥的y坐标
- // cipher_m[out] : 密文C3,长度为32,原文的哈希值
- // cipher_c[out] : 密文C2
- // cipher_l[out] : 密文C2的长度
- int SM2_Cipher_Der_to_Struct(const unsigned char *pbDer, unsigned int uiDerLen, unsigned char *cipher_x, unsigned char *cipher_y, unsigned char *cipher_m, unsigned char *cipher_c, unsigned int *cipher_l)
- {
- unsigned char pbTmp[8192] = { 0 };
- const unsigned char *data;
- int len;
- SM2_Ciphertext *xcipher;
- int ret = 1;
-
- do {
- xcipher = d2i_SM2_Ciphertext(NULL, &pbDer, uiDerLen);
- if (!xcipher) {
- break;
- }
-
- len = BN_bn2bin(xcipher->C1x, pbTmp);
- if (len > 32) {
- break;
- }
- memcpy(cipher_x, pbTmp, len);
-
- memset(pbTmp, 0, sizeof(pbTmp));
- len = BN_bn2bin(xcipher->C1y, pbTmp);
- if (len > 32) {
- break;
- }
- memcpy(cipher_y, pbTmp, len);
-
- len = ASN1_STRING_length(xcipher->C3);
- if (len > 32) {
- break;
- }
- data = ASN1_STRING_get0_data(xcipher->C3);
- if (!data) {
- break;
- }
- memcpy(cipher_m, data, len);
-
- *cipher_l = ASN1_STRING_length(xcipher->C2);
- if (*cipher_l > 512) {
- break;
- }
- data = ASN1_STRING_get0_data(xcipher->C2);
- if (!data) {
- break;
- }
- memcpy(cipher_c, data, *cipher_l);
-
- ret = 0;
- } while (0);
-
- SM2_Ciphertext_free(xcipher);
-
- return ret;
- }
-
- ASN1_SEQUENCE(SM2_Ciphertext) = {
- ASN1_SIMPLE(SM2_Ciphertext, C1x, BIGNUM),
- ASN1_SIMPLE(SM2_Ciphertext, C1y, BIGNUM),
- ASN1_SIMPLE(SM2_Ciphertext, C3, ASN1_OCTET_STRING),
- ASN1_SIMPLE(SM2_Ciphertext, C2, ASN1_OCTET_STRING),
- } ASN1_SEQUENCE_END(SM2_Ciphertext)
-
- // 由OpenSSL提供的宏,实现自定义的ASN1编码
- // 调用此宏,便定义了函数: SM2_Ciphertext_new、SM2_Ciphertext_free、d2i_SM2_Ciphertext、i2d_SM2_Ciphertext
- IMPLEMENT_ASN1_FUNCTIONS(SM2_Ciphertext)
-
-
- int main(int argc, char *argv[]){
-
- unsigned char c1x[] = {
- 0x57, 0xE9, 0x62, 0x22, 0xAB, 0x0A, 0x75, 0x43, 0x81, 0xA8, 0x43, 0x6A, 0xD9, 0x5F, 0xCC, 0xDD,
- 0x6B, 0x0D, 0xD4, 0xF6, 0x24, 0x1D, 0x13, 0xA0, 0x80, 0x2D, 0xE5, 0xD7, 0x09, 0x82, 0xF0, 0xF0
- };
- unsigned char c1y[] = {
- 0x97, 0xD3, 0x79, 0x5C, 0x79, 0x50, 0xF2, 0x78, 0x63, 0x50, 0x03, 0xA7, 0x08, 0xD5, 0x6C, 0x4F,
- 0xCB, 0x42, 0x44, 0xE4, 0xE2, 0x8C, 0xAA, 0x4F, 0x74, 0x4E, 0xF9, 0xE7, 0xA6, 0x82, 0x62, 0xE4
- };
- unsigned char c3[] = {
- 0xE7, 0x1B, 0x12, 0x51, 0x61, 0x40, 0xD3, 0xAC, 0x0C, 0x74, 0x84, 0x91, 0xBF, 0xE3, 0xEC, 0x0E,
- 0x60, 0x58, 0x24, 0xAA, 0xD5, 0x66, 0xC4, 0x48, 0x84, 0x10, 0xF4, 0x3C, 0x69, 0x29, 0xD0, 0x6C
- };
- unsigned char c2[] = {
- 0xB5, 0x92, 0xBF, 0x02, 0xD0, 0x53, 0xC2, 0x1A, 0x8A, 0x4A, 0xF1, 0x56, 0x21, 0x2E, 0xBD, 0x37
- };
-
- unsigned char der[256] = {0};
- unsigned int derlen = 0;
-
- unsigned char c1x2[32] = {0};
- unsigned char c1y2[32] = {0};
- unsigned char c32[32] = {0};
- unsigned char c22[32] = {0};
- unsigned int c22len = 0;
-
- // der 设置为NULL可以获得结构长度
- int rv = SM2_Cipher_Struct_to_Der(c1x, c1y, c3, c2, sizeof(c2), der, &derlen);
- if (rv != 0){
- return rv;
- }
- rv = SM2_Cipher_Der_to_Struct(der, derlen, c1x2, c1y2, c32, c22, &c22len);
- if (rv != 0){
- return rv;
- }
- if(memcmp(c1x, c1x2, 32) != 0 || memcmp(c1y, c1y2, 32) != 0 || memcmp(c3, c32, 32) != 0 ||
- sizeof(c2) != c22len || memcmp(c2, c22, c22len) != 0) {
- return -1;
- }
- printf("SM2 cipher exchange success!!!\n");
- return 0;
- }
-
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。