SM2公私钥的格式转换

基于OpenSSL, 实现算法的 Engine专栏

本专栏订阅后可查看以下文章

1、基于OpenSSL,实现RSA使用的hash的ASN1编码转换

2、基于OpenSSL,实现RSA公钥的ASN1编码转换

3、SM2公私钥的格式转换

4、基于OpenSSL,实现SM2签名数据的ASN1编码转换

5、基于OpenSSL,实现SM2密文数据的ASN1编码转换

 

在硬件密码库中使用的API接口和在OpenSSL中使用的接口,很有可能是两种格式数据的表现形式,因此,本文提供以下方式对SM2公私钥数据格式的转换。

SM2的公私钥格式转换非ASN1编码。

以下是经过整理后的SM2密钥对的格式转换,没有使用OpenSSL的函数库。

/****************************************************************
 * FileName:    SM2_key.c
 * Author:      labixiaoxin1849
 * Date:        2022-08-27
 * Description: SM2 key format conversion 
 ****************************************************************/

#include <stdio.h>
#include <string.h>

// 前缀04用于区分未压缩的公钥,一般使用不压缩的公钥
// 前缀02或03开头的压缩公钥
#define POINT_CONVERSION_UNCOMPRESSED     0x04


// 512是ECC椭圆曲线,256的密钥模长是ECC中的特殊曲线
// 如果想实现SM2密钥的格式转换,可根据实际情况,将密钥的长度判断删除,有效的x、y、d的长度为32
// 在GMT-0018中有定义
#define ECCref_MAX_BITS    512 
#define ECCref_MAX_LEN     ((ECCref_MAX_BITS+7) / 8)

int ECCrefPublicKey_Struct_to_oct(unsigned char *x, unsigned char *y, unsigned int bits, unsigned char *pboct, unsigned int *uioctlen)
{
    unsigned int klen = bits / 8;
    if (klen != ECCref_MAX_LEN) {
        return -1;
    }

    // flag
    *pboct = POINT_CONVERSION_UNCOMPRESSED;
    ++pboct;

    memcpy(pboct, x, klen);
    pboct += klen;

    memcpy(pboct, y, klen);

    *uioctlen = klen * 2 + 1;

    return 0;
}


int ECCrefPublicKey_oct_to_Struct(const unsigned char *pboct, unsigned int uioctlen, unsigned char *x, unsigned char *y, unsigned int *bits)
{
    if (uioctlen != 2 * ECCref_MAX_LEN + 1 || *pboct != POINT_CONVERSION_UNCOMPRESSED) {
        return -1;
    }
    
    *bits = ECCref_MAX_BITS;
    memcpy(x, pboct + 1, ECCref_MAX_LEN);
    memcpy(y, pboct + 1 + ECCref_MAX_LEN, ECCref_MAX_LEN);

    return 0;
}

int ECCrefPrivateKey_Struct_to_oct(const unsigned char *d, unsigned int bits, unsigned char *pboct, unsigned int *uioctlen)
{
    unsigned int klen = bits / 8;
    if (klen != ECCref_MAX_LEN) {
        return -1;
    }

    memcpy(pboct, d, klen);
    *uioctlen = klen;

    return 0;
}

int ECCrefPrivateKey_oct_to_Struct(const unsigned char *pboct, unsigned int uioctlen, unsigned char *d, unsigned int *bits)
{
    if (uioctlen != ECCref_MAX_LEN) {
        return -1;
    }

    *bits = ECCref_MAX_BITS;
    memcpy(d, pboct, uioctlen);

    return 0;
}

int main(int argc, char *argv[]) {
	
	unsigned char pubkey_x[] = {
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x8A, 0xCD, 0x02, 0x70, 0x93, 0x0B, 0x04, 0x9C, 0xDF, 0xAD, 0x5A, 0x5A, 0x1D, 0xFB, 0x4D, 0x28,
		0x69, 0x75, 0x2D, 0x39, 0x4A, 0x94, 0x9C, 0x04, 0x2C, 0xCA, 0x51, 0x7F, 0x6E, 0xAB, 0x9C, 0xD4
	};
	unsigned char pubkey_y[] = {
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x36, 0x1C, 0x79, 0xA5, 0x06, 0x77, 0x5C, 0x51, 0x60, 0x99, 0xE7, 0x6C, 0x69, 0x9A, 0xA4, 0xBC,
		0xFE, 0x34, 0x7B, 0x58, 0x0A, 0x3C, 0x16, 0x01, 0x95, 0xC5, 0xC8, 0xF6, 0x27, 0x8C, 0xA0, 0xE6
	};
	unsigned char prikey_d[] = {
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0xA3, 0xDA, 0x7F, 0xDA, 0xF9, 0x4C, 0x93, 0x09, 0xB9, 0xC8, 0x28, 0x2A, 0x5D, 0x6A, 0xB4, 0xBD,
		0x1C, 0xE4, 0x86, 0x87, 0xF3, 0xE8, 0x4C, 0xF8, 0xAA, 0xF0, 0xC1, 0xA2, 0x1E, 0x59, 0x69, 0xFF
	};
	unsigned char der[256] = {0};
	unsigned int derlen = 0;
	unsigned char pubkey_x2[ECCref_MAX_LEN] = {0};
	unsigned char pubkey_y2[ECCref_MAX_LEN] = {0};
	unsigned char prikey_d2[ECCref_MAX_LEN] = {0};
	unsigned int bits = ECCref_MAX_BITS;
	
	int rv = ECCrefPublicKey_Struct_to_oct(pubkey_x, pubkey_y, bits, der, &derlen);
	if (rv != 0){
		return rv;
	}
	rv = ECCrefPublicKey_oct_to_Struct(der, derlen, pubkey_x2, pubkey_y2, &bits);
	if (rv != 0){
		return rv;
	}
	if(memcmp(pubkey_x, pubkey_x2, ECCref_MAX_LEN) != 0 || memcmp(pubkey_y, pubkey_y2, ECCref_MAX_LEN) != 0) {
		return -1;
	}
	printf("SM2 public key exchange success!!!\n");
	
	memset(der, 0x00, sizeof(der));
	derlen = 0;
	rv = ECCrefPrivateKey_Struct_to_oct(prikey_d, bits, der, &derlen);
	if (rv != 0){
		return rv;
	}
	rv = ECCrefPrivateKey_oct_to_Struct(der, derlen, prikey_d2, &bits);
	if (rv != 0){
		return rv;
	}
	if(memcmp(prikey_d, prikey_d2, ECCref_MAX_LEN) != 0 ) {
		return -1;
	}
	printf("SM2 private key exchange success!!!\n");
	return 0;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蜡笔小新1849

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值