本专栏订阅后可查看以下文章
1、基于OpenSSL,实现RSA签名使用的hash的ASN1编码转换
4、基于OpenSSL,实现SM2签名数据的ASN1编码转换
5、基于OpenSSL,实现SM2密文数据的ASN1编码转换
在非对称密钥算法运算中,因为公私钥的特殊使用,会产生签名的场景,在做签名时,只是为了证明身份,而非保护数据,所以在签名时,是对数据的哈希进行签名。
在实际应用场景中会遇到ASN1数据的编码转换,如,在硬件密码库中使用的API接口和在OpenSSL中使用的接口,很有可能是两种格式数据的表现形式,因此,本文提供以下方式进行数据格式的转换。
二进制转为ASN1编码
// hash[in] : 源数据
// hashlen[in] : 源数据长度
// der[out] : 编码后的数据,传入NULL时,可以获得编码后的数据长度
// derlen[out] : 编码后的数据长度
// type[in] : 声明哈希的算法ID,NID_sha256
int RSA_sig_to_der(const unsigned char *hash, unsigned int hashlen, unsigned char *der, unsigned int *derlen, int type) {
int ret = -1;
X509_SIG *xsig;
X509_ALGOR *algor;
ASN1_OCTET_STRING *pdigest;
do{
// 不同于SM2算法的签名转换,此定义已在OpenSSL中声明
// SM2的签名数据需要自己做声明
xsig = X509_SIG_new();
if (!xsig){
break;
}
// 获得algor和pdigest在xsig中的地址,从而设置xsig的值
X509_SIG_getm(xsig, &algor, &pdigest);
if (!X509_ALGOR_set0(algor, OBJ_nid2obj(type), V_ASN1_NULL, NULL)){
break;
}
if (!ASN1_OCTET_STRING_set(pdigest, hash, hashlen)) {
break;
}
if (der) {
*derlen = i2d_X509_SIG(xsig, &der);
}
else {
*derlen = i2d_X509_SIG(xsig, NULL);
}
ret = 0;
} while (0);
if (xsig) {
X509_SIG_free(xsig);
}
return ret;
}
ASN1编码转为二进制
// pbDer[in] : ASN1编码数据
// uiDerLen[in] : ASN1编码数据长度
// hash[out] : 哈希数据
// hashlen[out] : 哈希数据长度
int RSA_sig_to_hash(const unsigned char *pbDer, unsigned int uiDerLen, unsigned char *hash, unsigned int *hashlen) {
int ret = -1;
X509_SIG *xsig = NULL;
const ASN1_OCTET_STRING *doct = NULL;
const unsigned char *data = NULL;
int datalen = 0;
do{
xsig = d2i_X509_SIG(NULL, &pbDer, uiDerLen);
if (!xsig) {
break;
}
// 这里没有对哈希算法进行解析,如需解析,把NULL变为变量再解析
X509_SIG_get0(xsig, NULL, &doct);
datalen = ASN1_STRING_length(doct);
if (datalen <= 0) {
break;
}
data = ASN1_STRING_get0_data(doct);
if (!data) {
break;
}
memcpy(hash, data, datalen);
*hashlen = datalen;
ret = 0;
} while (0);
if (xsig) {
X509_SIG_free(xsig);
}
return ret;
}
具体调用如下:
int main(int argc, char *argv[]) {
//unsigned char derB64[] = "MDEwDQYJYIZIAWUDBAIBBQAEILVRJqOfmxFwoy5vYeSmlMRSNeWsEcBezW/2OV3moRGH";
unsigned char der[] = {
0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
0x00, 0x04, 0x20, 0xB5, 0x51, 0x26, 0xA3, 0x9F, 0x9B, 0x11, 0x70, 0xA3, 0x2E, 0x6F, 0x61, 0xE4,
0xA6, 0x94, 0xC4, 0x52, 0x35, 0xE5, 0xAC, 0x11, 0xC0, 0x5E, 0xCD, 0x6F, 0xF6, 0x39, 0x5D, 0xE6,
0xA1, 0x11, 0x87
};
unsigned int derlen = sizeof(der);
unsigned char hash[64] = { 0 };
unsigned int hashlen = 0;
unsigned char out[128] = { 0 };
unsigned int outlen = 0;
int ret = RSA_sig_to_hash(der, derlen, hash, &hashlen);
if (ret != 0){
return -1;
}
ret = RSA_sig_to_der(hash, hashlen, out, &outlen, 672); // NID_sha256
if (ret != 0){
return -1;
}
if(derlen != outlen || memcmp(der, out, outlen) != 0) {
return -1;
}
printf("exchange success!!!\n");
return 0;
}