
linux C语言用openssl进行签名验签
openssl
传输层安全性/安全套接层及其加密库
项目地址:https://gitcode.com/gh_mirrors/ope/openssl
·
1.安装openssl
安装完成之后,会有个lib目录,将lib目录下的 libcrypto 拷贝到/usr/lib64目录下。
2. 生成私钥和公钥
生成私钥:openssl genrsa -out rsa_private_key.pem 2048
生成加密的私钥:openssl genrsa -out rsa_private_key.pem -des3 2048
生成公钥:openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
3.签名
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/sha.h>
#include <openssl/crypto.h>
/*
* 参考https://blog.csdn.net/zjf535214685/article/details/82182241
*/
#define SHA_WHICH NID_sha256
#define WHICH_DIGEST_LENGTH SHA256_DIGEST_LENGTH
char transToHex[2048];
unsigned char BASE64_CODE[]={"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"};
void printHex(unsigned char *md, int len)
{
memset(transToHex, 0x00, sizeof(transToHex));
int i = 0;
for (i = 0; i < len; i++)
{
printf("%02x", md[i]);
sprintf(transToHex+i*2, "%02x", md[i]);
}
printf("\n");
printf("transToHex[%s]\n", transToHex);
}
/*读取私钥*/
RSA* ReadPrivateKey(char* p_KeyPath)
{
FILE *fp = NULL;
RSA *priRsa = NULL;
printf("PrivateKeyPath[%s] \n", p_KeyPath);
/* 打开密钥文件 */
if(NULL == (fp = fopen(p_KeyPath, "r")))
{
printf( "fopen[%s] failed \n", p_KeyPath);
return NULL;
}
/* 获取私钥 */
//priRsa = PEM_read_RSAPrivateKey(fp, NULL, NULL,NULL); /*不加密*/
priRsa = PEM_read_RSAPrivateKey(fp, NULL, NULL,"123456"); /*加密, 密码是123456*/
if(NULL == priRsa)
{
ERR_print_errors_fp(stdout);
printf( "PEM_read_RSAPrivateKey\n");
fclose(fp);
return NULL;
}
fclose(fp);
return priRsa;
}
/*
* ToBase64 (Internal used by EncodeBase64)
* Param: unsigned char psInData[3] -- IN / Pointer to 3 or less chars of Original Data
* unsigned char psOutData[4] -- IN / Pointer to 4 char of Encoded Base64 Data
* int iLen -- IN / Length of the Original Data, should only be 1, 2, or 3
*
* Return: 0 -- On sucess
* -1 -- On any error
*/
int ToBase64(unsigned char psInData[3], unsigned char psOutData[4], int iLen)
{
psOutData[0] = BASE64_CODE[psInData[0] >> 2];
if (iLen == 1)
{
psOutData[1] = BASE64_CODE[psInData[0] << 4 & 0x30];
psOutData[2] = '=';
psOutData[3] = '=';
return 0;
}
psOutData[1] = BASE64_CODE[psInData[0] << 4 & 0x30 | psInData[1] >> 4];
if (iLen == 2)
{
psOutData[2] = BASE64_CODE[psInData[1] << 2 & 0x3C];
psOutData[3] = '=';
return 0;
}
psOutData[2] = BASE64_CODE[psInData[1] << 2 & 0x3C | psInData[2] >> 6];
psOutData[3] = BASE64_CODE[psInData[2] & 0x3F];
return 0;
}
/*
* EncodeBase64
* Param: unsigned char* psInData -- IN / Pointer to Original Data buf
* long lInDataLen -- IN / Length of Original Data
* unsigned char* psOutData -- IN / Pointer to Output Data buf
* long* plOutDataLen -- IN / Length of Output Data buf
* OUT / Length of Base64 Code
*
* Return: 0 -- On Successful
* -1 -- *plOutDataLen too small
*/
int EncodeBase64(unsigned char* psInData, long lInDataLen, unsigned char* psOutData, long* plOutDataLen)
{
int i;
if (*plOutDataLen < lInDataLen/3*4)
{
/*
printf("Base64 Encode overflow! (output buf not enough)\n\n");
*/
return -1;
}
for (i = 0; i < lInDataLen; i += 3)
ToBase64(&psInData[i], &psOutData[i/3*4], lInDataLen-i-3 >= 0 ? 3 : lInDataLen%3);
*plOutDataLen = i/3*4;
return 0;
}
int test_RSA_sign(char *inData, char *outData, char *keyName)
{
RSA *privKey = NULL;
char outdatab64[2000546] = {0}; /*原报文base64加密*/ /*如果定义长度2900546, 编译会报 Segmentation fault*/
char signbase64[2048*8] = {0}; /*签名之后base64加密*/
char buf[2048] = {0}; /*签名之后的数据*/
int nOutLen = sizeof(buf); /*签名之后的长度*/
long int outdatab64_len = sizeof(outdatab64); /*原报文base加密之后的长度*/
long int indata_len = strlen(inData); /*原报文的长度*/
long int signbase64_len = sizeof(signbase64); /*签名之后base64加密之后的长度*/
int nRet = 0;
/*对原报文进行base64加密*/
nRet = EncodeBase64(inData, indata_len, outdatab64, &outdatab64_len);
if (nRet != 0)
{
printf("EncodeBase64() error!!!\n");
return -1;
}
printf("-------------------\n");
printf("FILE[%s]LINE[%d] outdatab64_len[%ld], outdatab64[%s]\n", __FILE__, __LINE__, outdatab64_len, outdatab64);
//对数据进行sha256算法摘要
unsigned char md[WHICH_DIGEST_LENGTH];
SHA256((unsigned char *)inData, strlen(inData), md);
printHex(md, WHICH_DIGEST_LENGTH);
privKey = ReadPrivateKey(keyName);
if (!privKey)
{
ERR_print_errors_fp (stderr);
return -1;
}
/* 签名 */
nRet = RSA_sign(SHA_WHICH, md, WHICH_DIGEST_LENGTH, buf, &nOutLen, privKey);
if(nRet != 1)
{
printf("RSA_sign err !!! \n");
goto quit;
}
printf("RSA_sign len = %d:", nOutLen);
printHex(buf, nOutLen);
nOutLen = strlen(transToHex);
/*签名之后,再进行base64加密*/
// nRet = EncodeBase64(buf, nOutLen, signbase64, &signbase64_len);
nRet = EncodeBase64(transToHex, nOutLen, signbase64, &signbase64_len);
if (nRet != 0)
{
printf("FILE[%s]LINE[%d] EncodeBase64() error!!!\n", __FILE__, __LINE__);
return -1;
}
printf("signbase64_len[%d],signbase64[%s]\n", signbase64_len, signbase64);
sprintf(outData,"<?xml version= \"1.0\"encoding= \"gb2312\"?> <msg><sourceData>%s</sourceData><signData>%s</signData></msg>",outdatab64,signbase64);
// sprintf(outData,"<?xml version= \"1.0\"encoding= \"gb2312\"?> <msg><sourceData>%s</sourceData><signData>",outdatab64);
// outDataHalf_len = strlen(outData);
// memcpy(outData+strlen(outData), buf, nOutLen);
// memcpy(outData+outDataHalf_len+nOutLen, "</sgnData></msg>", 16);
quit:
RSA_free(privKey);
return 0;
}
int main(int argc, char *argv[])
{
int iRet;
// char *idata = "china";
char *idata = "<?xml version = \"1.0\" encoding = \"GB2312\"?><bocb2e version=\"100\" security=\"true\" lang=\"chs\"><head><termid>E127000000001</termid><trnid>20060704001</trnid><custid>12345678</custid><cusopr>BOC</cusopr><trncod>b2e0005</trncod><token>9TTQALYGH1</token></head><trans><trn-b2e0005-rq><b2e0005-rq><account><ibknum>40001</ibknum><actacn>800100053208091001</actacn></account></b2e0005-rq><b2e0005-rq><account><ibknum>40002</ibknum><actacn>800100053108091001</actacn></account></b2e0005-rq></trn-b2e0005-rq></trans></bocb2e>";
char StrNewBuf[2099546*2+1] = {0}; /*报文头+原数据+签名之后 的数据*/
char StrNewBuf_tmp[2099546+1] = {0}; /*需要加签的数据*/
char keyName[] = "./rsa_private_key.pem"; /*key的路径*/
memcpy(StrNewBuf_tmp, idata, strlen(idata));
iRet = test_RSA_sign(StrNewBuf_tmp, StrNewBuf, keyName); /*替换函数SM2RawSign(StrNewBuf_tmp, StrNewBuf, keyName, passWord);*/
if(iRet != 0)
{
printf("test_RSA_sign() error !!!\n");
return -1;
}
printf("---------------------------\n");
printf("FILE[%s]LINE[%d]StrNewBuf[%s]\n\n\n", __FILE__, __LINE__, StrNewBuf);
return 0;
}
运行:gcc rsa_sign.c -lcrypto ; ./a.out

红色框框里的表示十六进制打印出来的签名。
4.验签
#include <string.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/sha.h>
#include <openssl/crypto.h>
/*
* 参考https://blog.csdn.net/zjf535214685/article/details/82182241
*/
//#define PUBLIC_KEY_PATH ("./public_key.pem")
#define PUBLIC_KEY_PATH ("./rsa_public_key.pem")
#define SHA_WHICH NID_sha256
#define WHICH_DIGEST_LENGTH SHA256_DIGEST_LENGTH
void printHex(unsigned char *md, int len)
{
int i = 0;
for (i = 0; i < len; i++)
{
printf("%02x", md[i]);
}
printf("\n");
}
/*读取公匙*/
RSA* ReadPublicKey(char* p_KeyPath)
{
FILE *fp = NULL;
RSA *pubRsa = NULL;
printf("PublicKeyPath[%s]\n", p_KeyPath);
/* 打开密钥文件 */
if(NULL == (fp = fopen(p_KeyPath, "r")))
{
printf( "fopen[%s] \n", p_KeyPath);
return NULL;
}
/* 获取公钥 */
if(NULL == (pubRsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL,NULL)))
{
printf( "PEM_read_RSAPrivateKey error\n");
fclose(fp);
return NULL;
}
fclose(fp);
return pubRsa;
}
int test_RSA_verify(void)
{
char *data = "<?xml version = \"1.0\" encoding = \"GB2312\"?><bocb2e version=\"100\" security=\"true\" lang=\"chs\"><head><termid>E127000000001</termid><trnid>20060704001</trnid><custid>12345678</custid><cusopr>BOC</cusopr><trncod>b2e0005</trncod><token>9TTQALYGH1</token></head><trans><trn-b2e0005-rq><b2e0005-rq><account><ibknum>40001</ibknum><actacn>800100053208091001</actacn></account></b2e0005-rq><b2e0005-rq><account><ibknum>40002</ibknum><actacn>800100053108091001</actacn></account></b2e0005-rq></trn-b2e0005-rq></trans></bocb2e>";
char buf[256] = {
0x5d,
0xa7,0x17,0x2b,0xe2,0x37,0x00,0xd4,0xe7,
0x71,0xd1,0x41,0x9a,0xe2,0x81,0x46,0x97,
0x69,0xb4,0x39,0x4d,0x84,0x1d,0x7e,0x98,
0x72,0xe3,0x27,0xcf,0x5e,0xaf,0x3d,0xc4,
0x8d,0xcd,0x01,0x63,0x1b,0x71,0x48,0x06,
0xd1,0x96,0x9c,0x23,0x58,0x59,0xfc,0x96,
0x0a,0xd9,0x24,0x6c,0x57,0xf6,0x62,0x17,
0xb9,0xc4,0x6d,0x80,0xa7,0x01,0x08,0x7e,
0x3d,0x91,0x70,0x6e,0xe7,0x09,0x28,0xda,
0xe3,0xe7,0x6d,0xba,0x47,0xa5,0xd3,0x0c,
0x51,0xe0,0x5c,0xcc,0x74,0x65,0x13,0xed,
0x13,0x31,0xc4,0xff,0x22,0x46,0x52,0xb4,
0x17,0x46,0xfe,0x03,0x45,0x96,0x19,0xbc,
0x1f,0xd7,0x93,0x65,0xc6,0x48,0xae,0x4c,
0xd3,0xbd,0x6a,0xa0,0xfc,0xb8,0x20,0x3b,
0xa9,0x5d,0xb5,0x07,0x20,0x3f,0x38,0xaf,
0x95,0xff,0x12,0x45,0xde,0x40,0xc3,0x62,
0x38,0x69,0xec,0xff,0x2b,0x44,0x39,0xca,
0x1d,0xd4,0x3e,0xba,0x1a,0x28,0x57,0x54,
0x09,0x8c,0x3d,0x57,0xb4,0x2f,0x33,0xd9,
0xa4,0xd9,0x45,0x72,0xec,0xbb,0x2a,0x96,
0x34,0x97,0xe1,0x2a,0x78,0xec,0xf2,0x2b,
0xd3,0xcc,0xa6,0xcf,0xbc,0xdf,0xa2,0x8e,
0xab,0x90,0x28,0x18,0x0b,0x73,0x61,0x8f,
0xfb,0xf3,0xfe,0x33,0xc5,0xaa,0x9f,0x1e,
0xac,0x83,0x93,0x72,0x50,0xdf,0xfa,0xb5,
0x80,0xfa,0x17,0xd2,0xe5,0x9a,0x6e,0x7f,
0x3b,0x78,0x60,0x9b,0xb5,0xa0,0xc7,0x47,
0x24,0x4d,0x94,0x6e,0x40,0xcb,0x73,0x86,
0x23,0x18,0x33,0xc9,0xff,0x93,0x21,0xce,
0xcc,0x70,0xb0,0x9f,0x14,0xef,0x72,0x61,
0xe7,0x28,0x85,0xeb,0x51,0x39,0x68,
};
RSA *pubKey = NULL;
int nOutLen = sizeof(buf);
int nRet = 0;
//对数据进行sha256算法摘要
unsigned char md[WHICH_DIGEST_LENGTH];
SHA256((unsigned char *)data, strlen(data), md);
printHex(md, WHICH_DIGEST_LENGTH);
pubKey = ReadPublicKey(PUBLIC_KEY_PATH);
if (!pubKey)
{
printf("Error: can't load public key");
return -1;
}
/* 验签 */
nRet = RSA_verify(SHA_WHICH, md, WHICH_DIGEST_LENGTH, buf, nOutLen, pubKey);
printf("RSA_verify %s(ret=%d).\r\n", (1 == nRet) ? "Success" : "Failed", nRet);
RSA_free(pubKey);
return 0;
}
int main(int argc, char *argv[])
{
test_RSA_verify();
return 0;
}
运行:gcc rsa_verify.c -lcrypto ; ./a.out

传输层安全性/安全套接层及其加密库
最近提交(Master分支:3 个月前 )
b049ce0e
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26359)
6 天前
75416c09
Once lcov is updated to 2.2 version or later, it could be dropped.
Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Tom Cosgrove <tom.cosgrove@arm.com>
(Merged from https://github.com/openssl/openssl/pull/26381)
7 天前
更多推荐



所有评论(0)