openssl-私钥签名(SHA256withRSA)、公钥验签(SHA1withRSA)
一、来由-决定思路
1、近期调试的一个客户端,为了防止接口请求被劫持、 篡改, 需通过证书对请求数据进行签名操作, 来确保请求数据的完整性;要用私钥对数据进行RSA签名,用的SHA256withRSA, 然后使用 Base64 封装签名结果,将数据发送到服务器,服务器对数据进行验签。
2、针对服务器返回结果数据, 客户端需要进行验签操作来确保接收到的数据的完整性, 要用公钥验证签名,用的SHA1withRSA。
3、不论是计算签名还是进行数据验签,主要是看计算摘要的接口。
4、使用到的证书格式为pem格式的。
二、以下是核心代码
//私钥签名 SHA256withRSA
/*
* @param [in] filename 证书路径
* @param [in] src 待签名源数据
* @param [in] srclen 待签名源数据
* @param [out] sign 签名
* @param [out] signlen 签名长度
* @return -
*/
static int My_Rsa_PrikeySign(char *filename, unsigned char *src, int srclen, unsigned char *sign, int *signlen)
{
int iRet = 0;
unsigned char uchash[256] = {0};//计算的摘要
if(filename == NULL || src == NULL || sign == NULL)
{
printf("parameter error\r\n");
return -1;
}
RSA *rsa_pri_key = RSA_new();
FILE *fp = NULL;
//打开文件
fp = fopen(filename, "rt");
if ( fp == NULL )
{
RSA_free(rsa_pri_key);
printf("fopen [%s] error\r\n", filename);
return -2;
}
//读取PEM证书文件
if(PEM_read_RSAPrivateKey(fp, &rsa_pri_key, 0, 0) == NULL)
{
RSA_free(rsa_pri_key);
fclose( fp );
printf("PEM_read_RSAPrivateKey error\r\n");
return -3;
}
//关闭句柄
fclose( fp );
//使用的SHA256计算摘要,若是SHA1则替换成对应的函数
SHA256(src, srclen, uchash);
//print_hex("hash", uchash, 32);
//计算签名,前三个参数传入SHA256对应的参数
iRet = RSA_sign(NID_sha256, uchash, 32, sign, signlen, rsa_pri_key);
if(1 != iRet)
{
RSA_free(rsa_pri_key);
printf("RSA_sign error, iRet is:[%d], sign_len is:[%d]\r\n", iRet, signlen);
return -4;
}
printf("RSA_sign ok\n");
RSA_free(rsa_pri_key);
return 0;
}
//公钥签名验证 SHA1withRSA
/*
* @param [in] filename 证书路径
* @param [in] src 待验签源数据
* @param [in] srclen 待验签源数据
* @param [in] sign 签名
* @param [in] signlen 签名长度
* @return - 返回0成功,非0失败
*/
static int My_Rsa_PublicVerify(char *filename, unsigned char *src, int srclen, unsigned char *sign, int signlen)
{
int iRet = 0;
unsigned char uchash[256] = {0};//计算的摘要
if(filename == NULL || src == NULL || sign == NULL)
{
printf("parameter error\r\n");
return -1;
}
RSA *rsa_pub_key = RSA_new();
FILE *fp = NULL;
fp = fopen(filename, "rt");
if( fp == NULL )
{
RSA_free(rsa_pub_key);
printf("fopen [%s] error\r\n", filename);
return -2;
}
if(!PEM_read_RSA_PUBKEY(fp, &rsa_pub_key, 0, 0))
{
RSA_free(rsa_pub_key);
fclose( fp );
printf("PEM_read_RSA_PUBKEY error\r\n");
return -3;
}
fclose( fp );
//使用的SHA1计算摘要,若是其他算法则替换成对应的函数
SHA1(src, srclen, uchash);
//print_hex("hash", uchash, 20);
//计算签名,前三个参数传入SHA1对应的参数
iRet = RSA_verify(NID_sha1, uchash, 20, sign, signlen, rsa_pub_key);
if(1 != iRet)
{
RSA_free(rsa_pub_key);
printf("RSA_verify error, iRet is:[%d], sign_len is:[%d]\r\n", iRet, signlen);
return -4;
}
printf("RSA_verify ok\n");
RSA_free(rsa_pub_key);
return 0;
}