前言:
由於國密標準規定,設備的SM2私鑰文件外部無法訪問,導致研發人員無法使用【密鑰文件.pem】生成【證書請求文件.csr】
花費了半天時間寫了基於SKF標準的生成【證書請求文件.csr】API接口,現在給大家進行參考,減少時間浪費。
準備工具:
LInux上安裝最新的openssl工具箱,用於驗證證書請求文件格式準確。
源碼:
#define SIGN_SEQUENCE (0x30)
#define SIGN_OBJECT (0x06)
#define SIGN_SET (0x31)
#define SIGN_UTF8STRING (0x0c)
#define SIGN_BIT_STRING (0x03)
#define SIGN_ATTRIBUTES (0xa0)
#define SIGN_VERSION (0x02)
#define SIGN_ONEBIT (0x81)
#define SIGN_TWOBIT (0x82)
#define SIGN_PRIVATE (0x02)
#define SIGN_SIGNATURE (0x03)
typedef struct{
char CommonName[64]; /* 通用名稱CN */
char OrganizationUnit[64]; /* 組織單位OU */
char OrganizationName[64]; /* 組織部門O */
char LocalityName[64]; /* 本地名稱L */
char StateOrProvince[64]; /* 州/省 TH*/
char Country[64]; /* 國家 C*/
}QCard_DN;
void QCard_SetASN1Data(unsigned char sign, unsigned char *in, unsigned long inLen,
unsigned char **out, unsigned long *outLen)
{
int i = 0, iNum = 0;
unsigned char *data = 0;
int u8len = sizeof(unsigned long);
iNum = (inLen % 0xff) ? inLen /0xff + 1 : inLen /0xff ;
*outLen = iNum ? 1 + iNum + inLen : 1 + 1 + inLen;
data = (unsigned char *)QCARD_MALLOC(*outLen);
data[0] = sign;
switch(iNum)
{
case 1:
data[1] = ((u8*)(&inLen))[0];
break;
case 2:
data[1] = ((u8*)(&inLen))[1];
data[2] = ((u8*)(&inLen))[0];
break;
}
memcpy( data + 1 + iNum, in, inLen);
//LOG_DATA(data, *outLen);
*out = data;
}
void QCard_AddASN1Data(unsigned char *d1, unsigned long d1Len,
unsigned char *d2, unsigned long d2Len,
unsigned char **d3, unsigned long *d3Len)
{
*d3Len = d1Len + d2Len;
*d3 = (unsigned char *)QCARD_MALLOC(*d3Len);
memcpy(*d3, d1, d1Len);
memcpy((*d3)+d1Len, d2, d2Len);
return;
}
void QCard_AddASN1Data2(unsigned char **d1, unsigned long *d1Len,
unsigned char *d2, unsigned long d2Len)
{
unsigned char *d3 =0;
unsigned long d3Len = 0;
QCard_AddASN1Data(*d1, *d1Len, d2, d2Len, &d3, &d3Len);
QCARD_FREE(*d1);
*d1 = d3;
*d1Len = d3Len;
}
void QCard_GetANS1DnData(char *data, unsigned char *type, unsigned long typeLen, QCARD_ANS1DATA **out)
{
unsigned char *d1 = 0, *d2 = 0, *d3 = 0, *d4 =0, *d5 = 0;
unsigned long d1Len = 0, d2Len = 0, d3Len = 0, d4Len = 0, d5Len = 0;
QCARD_ANS1DATA *ans1 = 0;
QCard_SetASN1Data(SIGN_UTF8STRING, (unsigned char *)data, strlen(data), &d1, &d1Len);
QCard_SetASN1Data(SIGN_OBJECT, type, typeLen, &d2, &d2Len);
QCard_AddASN1Data(d2, d2Len, d1, d1Len, &d3, &d3Len);
QCard_SetASN1Data(SIGN_SEQUENCE, d3, d3Len, &d4, &d4Len);
QCard_SetASN1Data(SIGN_SET, d4, d4Len, &d5, &d5Len);
ans1 = (QCARD_ANS1DATA *)QCARD_MALLOC(sizeof(QCARD_ANS1DATA));
ans1->data = d5;
ans1->len = d5Len;
*out = ans1;
QCARD_FREE(d1);
QCARD_FREE(d2);
QCARD_FREE(d3);
QCARD_FREE(d4);
return;
}
void QCard_SetANS1Dn(QCARD_ANS1DATA *SEQUENCE_C, QCARD_ANS1DATA *SEQUENCE_ST, QCARD_ANS1DATA *SEQUENCE_L,
QCARD_ANS1DATA *SEQUENCE_O, QCARD_ANS1DATA *SEQUENCE_OU ,QCARD_ANS1DATA *SEQUENCE_CN,
QCARD_ANS1DATA **SEQUENCE_DN)
{
unsigned char *data = 0;
unsigned long dataLen = 0;
QCard_AddASN1Data2(&data, &dataLen, SEQUENCE_C->data, SEQUENCE_C->len);
//LOG_DATA(data, dataLen);
QCard_AddASN1Data2(&data, &dataLen, SEQUENCE_ST->data, SEQUENCE_ST->len);
// LOG_DATA(data, dataLen);
QCard_AddASN1Data2(&data, &dataLen, SEQUENCE_L->data, SEQUENCE_L->len);
// LOG_DATA(data, dataLen);
QCard_AddASN1Data2(&data, &dataLen, SEQUENCE_O->data, SEQUENCE_O->len);
// LOG_DATA(data, dataLen);
QCard_AddASN1Data2(&data, &dataLen, SEQUENCE_OU->data, SEQUENCE_OU->len);
// LOG_DATA(data, dataLen);
QCard_AddASN1Data2(&data, &dataLen, SEQUENCE_CN->data, SEQUENCE_CN->len);
// LOG_DATA(data, dataLen);
*SEQUENCE_DN = (QCARD_ANS1DATA *)QCARD_MALLOC(sizeof(QCARD_ANS1DATA));
QCard_SetASN1Data(SIGN_SEQUENCE, data, dataLen, &((*SEQUENCE_DN)->data), &((*SEQUENCE_DN)->len));
QCARD_FREE(data);
}
void QCard_SetANS1Id(unsigned char *id_OID, unsigned long id_OIDLen,
unsigned char *id_CURVE, unsigned long id_CURVELen,
QCARD_ANS1DATA **out)
{
unsigned char *d1 = 0, *d2 = 0, *d3 = 0, *d4 =0;
unsigned long d1Len = 0, d2Len = 0, d3Len = 0, d4Len = 0;
QCARD_ANS1DATA *ans1 = 0;
QCard_SetASN1Data(SIGN_OBJECT, id_OID, id_OIDLen, &d1, &d1Len);
QCard_SetASN1Data(SIGN_OBJECT, id_CURVE, id_CURVELen, &d2, &d2Len);
QCard_AddASN1Data(d1, d1Len, d2, d2Len, &d3, &d3Len);
QCard_SetASN1Data(SIGN_SEQUENCE, d3, d3Len, &d4, &d4Len);
ans1 = (QCARD_ANS1DATA *)QCARD_MALLOC(sizeof(QCARD_ANS1DATA));
ans1->data = d4;
ans1->len = d4Len;
*out = ans1;
QCARD_FREE(d1);
QCARD_FREE(d2);
QCARD_FREE(d3);
return;
}
void QCard_SetANS1PublicKey(unsigned char *pucPublicKey, unsigned long ululPublicKeyLen,
QCARD_ANS1DATA **out)
{
unsigned char *d1 = 0;
unsigned long d1Len = 0;
QCARD_ANS1DATA *ans1 = 0;
QCard_SetASN1Data(SIGN_BIT_STRING, pucPublicKey, ululPublicKeyLen, &d1, &d1Len);
ans1 = (QCARD_ANS1DATA *)QCARD_MALLOC(sizeof(QCARD_ANS1DATA));
ans1->data = d1;
ans1->len = d1Len;
*out = ans1;
return;
}
void QCard_SetANS1Simpleness(unsigned char type, unsigned char *in, unsigned long inLen,
QCARD_ANS1DATA **out)
{
unsigned char *d1 = 0;
unsigned long d1Len = 0;
QCARD_ANS1DATA *ans1 = 0;
QCard_SetASN1Data(type, in, inLen, &d1, &d1Len);
ans1 = (QCARD_ANS1DATA *)QCARD_MALLOC(sizeof(QCARD_ANS1DATA));
ans1->data = d1;
ans1->len = d1Len;
*out = ans1;
return;
}
void QCard_SetANS1ALG(unsigned char *in, unsigned long inLen,
QCARD_ANS1DATA **out)
{
unsigned char *d1 = 0, *d2 = 0;
unsigned long d1Len = 0, d2Len = 0;
QCARD_ANS1DATA *ans1 = 0;
QCard_SetASN1Data(SIGN_OBJECT, in, inLen, &d1, &d1Len);
QCard_SetASN1Data(SIGN_SEQUENCE, d1, d1Len, &d2, &d2Len);
ans1 = (QCARD_ANS1DATA *)QCARD_MALLOC(sizeof(QCARD_ANS1DATA));
ans1->data = d2;
ans1->len = d2Len;
*out = ans1;
QCARD_FREE(d1);
return;
}
void QCard_SetANS1Pub(QCARD_ANS1DATA *SEQUENCE_PUBLICKEY, QCARD_ANS1DATA *SEQUENCE_ID,
QCARD_ANS1DATA **out)
{
unsigned char *d1 = 0, *d2 = 0;
unsigned long d1Len = 0, d2Len = 0;
QCARD_ANS1DATA *ans1 = 0;
QCard_AddASN1Data(SEQUENCE_ID->data, SEQUENCE_ID->len,
SEQUENCE_PUBLICKEY->data, SEQUENCE_PUBLICKEY->len, &d1, &d1Len);
QCard_SetASN1Data(SIGN_SEQUENCE, d1, d1Len, &d2, &d2Len);
ans1 = (QCARD_ANS1DATA *)QCARD_MALLOC(sizeof(QCARD_ANS1DATA));
ans1->data = d2;
ans1->len = d2Len;
*out = ans1;
QCARD_FREE(d1);
return;
}
void QCard_SetANS1CSR(QCARD_ANS1DATA *SEQUENCE_CSRDATA, QCARD_ANS1DATA *SEQUENCE_ALG, QCARD_ANS1DATA *SEQUENCE_SIGN,
QCARD_ANS1DATA **out)
{
unsigned char *d1 = 0, *d2 = 0, *d3 = 0;
unsigned long d1Len = 0, d2Len = 0, d3Len = 0;
QCARD_ANS1DATA *ans1 = 0;
unsigned char bit[] = {SIGN_SEQUENCE};
QCard_AddASN1Data2(&d1, &d1Len, SEQUENCE_CSRDATA->data, SEQUENCE_CSRDATA->len);
QCard_AddASN1Data2(&d1, &d1Len, SEQUENCE_ALG->data, SEQUENCE_ALG->len);
QCard_AddASN1Data2(&d1, &d1Len, SEQUENCE_SIGN->data, SEQUENCE_SIGN->len);
QCard_SetASN1Data(SIGN_TWOBIT, d1, d1Len, &d2, &d2Len);
QCard_AddASN1Data2(&d3, &d3Len, bit, sizeof(bit));
QCard_AddASN1Data2(&d3, &d3Len, d2, d2Len);
ans1 = (QCARD_ANS1DATA *)QCARD_MALLOC(sizeof(QCARD_ANS1DATA));
ans1->data = d3;
ans1->len = d3Len;
*out = ans1;
QCARD_FREE(d1);
QCARD_FREE(d2);
return;
}
void QCard_SetANS1CsrData(QCARD_ANS1DATA *SEQUENCE_VERSION, QCARD_ANS1DATA *SEQUENCE_DN,
QCARD_ANS1DATA *SEQUENCE_PUBLIC, QCARD_ANS1DATA *SEQUENCE_ATTRIBUTES,
QCARD_ANS1DATA **SEQUENCE_CSRDATA)
{
unsigned char *data = 0, *d2 = 0;
unsigned long dataLen = 0, d2Len = 0;
unsigned char sign[] = {SIGN_SEQUENCE};
QCard_AddASN1Data2(&data, &dataLen, SEQUENCE_VERSION->data, SEQUENCE_VERSION->len);
//LOG_DATA(data, dataLen);
QCard_AddASN1Data2(&data, &dataLen, SEQUENCE_DN->data, SEQUENCE_DN->len);
// LOG_DATA(data, dataLen);
QCard_AddASN1Data2(&data, &dataLen, SEQUENCE_PUBLIC->data, SEQUENCE_PUBLIC->len);
// LOG_DATA(data, dataLen);
QCard_AddASN1Data2(&data, &dataLen, SEQUENCE_ATTRIBUTES->data, SEQUENCE_ATTRIBUTES->len);
*SEQUENCE_CSRDATA = (QCARD_ANS1DATA *)QCARD_MALLOC(sizeof(QCARD_ANS1DATA));
QCard_SetASN1Data(SIGN_ONEBIT, data, dataLen, &d2, &d2Len);
QCard_AddASN1Data(sign, sizeof(sign), d2, d2Len, &((*SEQUENCE_CSRDATA)->data), &((*SEQUENCE_CSRDATA)->len));
QCARD_FREE(data);
QCARD_FREE(d2);
}
void QCard_FreeQCARD_ANS1DATA(QCARD_ANS1DATA **in)
{
if(*in)
{
QCARD_FREE((*in)->data);
QCARD_FREE(*in);
}
}
int QCard_Sm2SignWithSm3(HCONTAINER hContainer, unsigned char *data, unsigned long dataLen,
QCARD_ANS1DATA **out)
{
u32 ret = 0;
unsigned char *d1 = 0 , *d2 = 0, *d3 = 0, *d4 = 0, *d5 = 0, *d6 = 0;
unsigned long d1Len = 0, d2Len = 0, d3Len = 0, d4Len = 0, d5Len = 0, d6Len = 0;
unsigned char digest[SM3_DIGEST_LENGTH] = {0};
unsigned char bit[] = {0x00};
ECCSIGNATUREBLOB Signature;
QCARD_ANS1DATA *ans1 = 0;
memset(&Signature, 0, sizeof(ECCSIGNATUREBLOB));
sm3(data, dataLen, digest);
//LOG_DATA(digest, SM3_DIGEST_LENGTH);
ret = SKF_ECCSignData (hContainer, digest, SM3_DIGEST_LENGTH, &Signature);
if(ret)
{
return ret;
}
//LOG_DATA(Signature.r, ECC_MAX_XCOORDINATE_BITS_LEN/8);
//LOG_DATA(Signature.s, ECC_MAX_XCOORDINATE_BITS_LEN/8);
QCard_SetASN1Data(SIGN_PRIVATE, &(Signature.r[31]), 33, &d1, &d1Len);
// LOG_DATA(d1, d1Len);
QCard_SetASN1Data(SIGN_PRIVATE, &(Signature.s[31]), 33, &d2, &d2Len);
// LOG_DATA(d2, d2Len);
QCard_AddASN1Data(d1, d1Len, d2, d2Len, &d3, &d3Len);
QCard_SetASN1Data(SIGN_SEQUENCE, d3, d3Len, &d4, &d4Len);
QCard_AddASN1Data(bit, sizeof(bit), d4, d4Len, &d5, &d5Len);
QCard_SetASN1Data(SIGN_SIGNATURE, d5, d5Len, &d6, &d6Len);
// LOG_DATA(d6, d6Len);
ans1 = (QCARD_ANS1DATA *)QCARD_MALLOC(sizeof(QCARD_ANS1DATA));
ans1->data = d6;
ans1->len = d6Len;
*out = ans1;
QCARD_FREE(d1);
QCARD_FREE(d2);
QCARD_FREE(d3);
QCARD_FREE(d4);
QCARD_FREE(d5);
return 0;
}
int QCard_GenECCReq(HCONTAINER hContainer, QCard_DN DN, unsigned char *pucPublicKey, unsigned long ululPublicKeyLen,
unsigned char **pucReq, unsigned long *pulReqLen)
{
QCARD_ANS1DATA *SEQUENCE_VERSION= 0;
QCARD_ANS1DATA *SEQUENCE_C = 0, *SEQUENCE_ST = 0, *SEQUENCE_L = 0, *SEQUENCE_O = 0, *SEQUENCE_OU = 0, *SEQUENCE_CN = 0;
QCARD_ANS1DATA *SEQUENCE_DN= 0;
QCARD_ANS1DATA *SEQUENCE_ID = 0;
QCARD_ANS1DATA *SEQUENCE_PUBLICKEY = 0;
QCARD_ANS1DATA *SEQUENCE_PUBLIC = 0;
QCARD_ANS1DATA *SEQUENCE_ATTRIBUTES= 0;
QCARD_ANS1DATA *SEQUENCE_CSRDATA= 0;
QCARD_ANS1DATA *SEQUENCE_ALG= 0;
QCARD_ANS1DATA *SEQUENCE_SIGN= 0;
QCARD_ANS1DATA *SEQUENCE_CSR= 0;
unsigned char type_C[] = {0x55, 0x04, 0x06};
unsigned char type_ST[] = {0x55, 0x04, 0x08};
unsigned char type_L[] = {0x55, 0x04, 0x07};
unsigned char type_O[] = {0x55, 0x04, 0x0a};
unsigned char type_OU[] = {0x55, 0x04, 0x0b};
unsigned char type_CN[] = {0x55, 0x04, 0x03};
unsigned char id_OID[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01};
unsigned char id_CURVE[] = {0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, 0x82, 0x2D};
unsigned char id_ALG[] = {0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, 0x83, 0x75};
unsigned char version[] = {0x00};
int ret = 0;
QCard_SetANS1Simpleness(SIGN_VERSION, version, sizeof(version), &SEQUENCE_VERSION);
//LOG_DATA(SEQUENCE_VERSION->data, SEQUENCE_VERSION->len);
QCard_GetANS1DnData(DN.Country, type_C, sizeof(type_C), &SEQUENCE_C);
QCard_GetANS1DnData(DN.StateOrProvince, type_ST, sizeof(type_ST), &SEQUENCE_ST);
QCard_GetANS1DnData(DN.LocalityName, type_L, sizeof(type_L), &SEQUENCE_L);
QCard_GetANS1DnData(DN.OrganizationName, type_O, sizeof(type_O), &SEQUENCE_O);
QCard_GetANS1DnData(DN.OrganizationUnit, type_OU, sizeof(type_OU), &SEQUENCE_OU);
QCard_GetANS1DnData(DN.CommonName, type_CN, sizeof(type_CN), &SEQUENCE_CN);
QCard_SetANS1Dn(SEQUENCE_C, SEQUENCE_ST, SEQUENCE_L, SEQUENCE_O, SEQUENCE_OU, SEQUENCE_CN, &SEQUENCE_DN );
QCard_FreeQCARD_ANS1DATA(&SEQUENCE_C);
QCard_FreeQCARD_ANS1DATA(&SEQUENCE_ST);
QCard_FreeQCARD_ANS1DATA(&SEQUENCE_L);
QCard_FreeQCARD_ANS1DATA(&SEQUENCE_O);
QCard_FreeQCARD_ANS1DATA(&SEQUENCE_OU);
//LOG_DATA(SEQUENCE_DN->data, SEQUENCE_DN->len);
QCard_SetANS1Id(id_OID, sizeof(id_OID), id_CURVE, sizeof(id_CURVE), &SEQUENCE_ID);
QCard_SetANS1PublicKey(pucPublicKey, ululPublicKeyLen, &SEQUENCE_PUBLICKEY);
QCard_SetANS1Pub(SEQUENCE_PUBLICKEY, SEQUENCE_ID, &SEQUENCE_PUBLIC);
QCard_FreeQCARD_ANS1DATA(&SEQUENCE_PUBLICKEY);
QCard_FreeQCARD_ANS1DATA(&SEQUENCE_ID);
//LOG_DATA(SEQUENCE_PUBLIC->data, SEQUENCE_PUBLIC->len);
QCard_SetANS1Simpleness(SIGN_ATTRIBUTES, 0, 0, &SEQUENCE_ATTRIBUTES);
//LOG_DATA(SEQUENCE_ATTRIBUTES->data, SEQUENCE_ATTRIBUTES->len);
QCard_SetANS1CsrData(SEQUENCE_VERSION, SEQUENCE_DN, SEQUENCE_PUBLIC,SEQUENCE_ATTRIBUTES,
&SEQUENCE_CSRDATA);
QCard_FreeQCARD_ANS1DATA(&SEQUENCE_VERSION);
QCard_FreeQCARD_ANS1DATA(&SEQUENCE_DN);
QCard_FreeQCARD_ANS1DATA(&SEQUENCE_PUBLIC);
QCard_FreeQCARD_ANS1DATA(&SEQUENCE_ATTRIBUTES);
// LOG_DATA(SEQUENCE_CSRDATA->data, SEQUENCE_CSRDATA->len);
QCard_SetANS1ALG(id_ALG, sizeof(id_ALG), &SEQUENCE_ALG);
//LOG_DATA(SEQUENCE_ALG->data, SEQUENCE_ALG->len);
//QCard_SetANS1Simpleness(SIGN_ATTRIBUTES, 0, 0, &SEQUENCE_ATTRIBUTES);
ret = QCard_Sm2SignWithSm3(hContainer, SEQUENCE_CSRDATA->data, SEQUENCE_CSRDATA->len,
&SEQUENCE_SIGN);
if(ret)
{
QCard_FreeQCARD_ANS1DATA(&SEQUENCE_CSRDATA);
return ret;
}
//LOG_DATA(SEQUENCE_SIGN->data, SEQUENCE_SIGN->len);
QCard_SetANS1CSR(SEQUENCE_CSRDATA, SEQUENCE_ALG, SEQUENCE_SIGN,&SEQUENCE_CSR);
QCard_FreeQCARD_ANS1DATA(&SEQUENCE_CSRDATA);
QCard_FreeQCARD_ANS1DATA(&SEQUENCE_SIGN);
QCard_FreeQCARD_ANS1DATA(&SEQUENCE_ALG);
//LOG_DATA(SEQUENCE_CSR->data, SEQUENCE_CSR->len);
*pucReq = SEQUENCE_CSR->data;
*pulReqLen = SEQUENCE_CSR->len;
QCARD_FREE(SEQUENCE_CSR);
return 0;
}
校驗結果:
命令【openssl req -in dev.csr -noout -text】
Certificate Request:
Data:
Version: 1 (0x0)
Subject: C = 00, ST = Some-State, L = 11, O = 22, OU = 33, CN = 44
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:b4:a1:13:44:b7:4a:8e:7e:40:26:4f:39:14:c4:
62:72:37:8d:78:ca:ba:9c:6f:e3:52:33:88:b3:c6:
0f:cf:79:6f:e3:83:bd:8d:6f:c1:9b:dd:f5:03:36:
0b:e3:4d:ce:de:fc:22:66:86:bd:75:58:9f:bd:b5:
af:e1:fc:31:f7
ASN1 OID: sm2p256v1
NIST CURVE: SM2
Attributes:
a0:00
Signature Algorithm: sm2sign-with-sm3
30:46:02:21:00:90:d3:b3:92:fe:56:59:30:e2:e1:fc:d6:9d:
17:f3:82:43:49:ca:1e:51:a0:f4:8f:6e:bc:ee:b5:3f:e3:b8:
81:02:21:00:91:88:8c:80:81:11:03:a8:cb:58:9f:e5:14:4e:
b8:aa:59:b1:1f:ed:d6:d4:07:90:86:37:e5:96:2d:cc:35:09