本专栏订阅后可查看以下文章
1、基于OpenSSL,实现RSA使用的hash的ASN1编码转换
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;
}