openssl -- 签名和验签函数调用,使用SHA1函数对原数据进行摘要计算 -- 代码

示例代码:

#include <stdio.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/sha.h>
#include <stddef.h>
#include <string.h>

#define OPENSSLKEY "../priv.key"
#define PUBLICKEY "../pub.key"

int my_sign(char *path_key, char *data, unsigned int len_data, char ** p_sign, unsigned int * len_sign);
int my_verify(char *path_key, char *data, unsigned int len_data, char *p_sign, unsigned int len_sign);
void drump_hex(char * data, unsigned int len_data);
int main()
{
printf("first ");
char data[] = "MY name is my";

char * p_sign = NULL;
int len_sign = 0;
int len_data = 0;

char * ptr = data;
while(*(ptr ++))
{
len_data++;
}

printf("Len_data: %d ",len_data);


if(my_sign(OPENSSLKEY, data,len_data, &p_sign, &len_sign))
{
printf("Ha Ha sign succeed!!!! ");
}

#if 1
printf(" The signer is : ");
drump_hex(p_sign, len_sign);
#endif // 1


if(my_verify(PUBLICKEY, data, len_data, p_sign,len_sign))
{
printf("Ha Ha Verify succeed!!!! ");
}

return 0;
}


int my_sign(char *path_key, char *data, unsigned int len_data, char ** p_sign, unsigned int * len_sign)
{
FILE *p_file = NULL;
RSA * p_rsa = NULL;
unsigned char SHA[SHA_DIGEST_LENGTH] = "";


if((p_file = fopen(path_key, "r")) == NULL)
{
perror("the file open fail");
return 0;
}

if((p_rsa = PEM_read_RSAPrivateKey(p_file, NULL, NULL, NULL)) == NULL)
{
//ERR_print_errors_fp(stdout);
printf("RSA 私钥读取失败!");
goto error;
}
fclose(p_file);
/*
原型:
unsigned char * SHA1(const unsigned char * d, size_t n, unsigned char *md);
计算从d开始的n个字节的sha1摘要值,然后存储到md
(md所指像的空间大小时SHA_DIGEST_LENGTH = 20字节)

返回哈希值的指针
*/


if(SHA1(data, len_data, SHA) == NULL)
{
printf("Hash error!! ");
goto error;
}

#if 1
printf(" The First SHA1 data is: ");
drump_hex(SHA, SHA_DIGEST_LENGTH);
#endif // 1


*len_sign = RSA_size(p_rsa);
*p_sign = (char *)malloc((*len_sign) + 1);
memset(*p_sign, 0, (*len_sign) + 1);

/*
原型:
int RSA_sign(int type, unsigned char *m, unsigned int m_len,
unsigned char* sigret, unsigned int *siglen, RSA *rsa);

使用PKCS #1 v2.0中指定的私有密钥rsa对大小m_len的消息摘要m进行签名。
它将签名存储在sigret中,将签名大小存储在siglen中。sigret必须指向内存的RSA_size(rsa)字节。

type表示生成消息m所使用的摘要算法。它通常是NID_sha1,NID_ripemd160和NID_md5.

成功返回1,否则返回0.
*/

if((RSA_sign(NID_sha1, SHA, SHA_DIGEST_LENGTH, *p_sign ,len_sign, p_rsa)) != 1)
{
printf("RSA_sign() error! ");
goto error;
}

return 1;

error:
if(p_file != NULL)
fclose(p_file);
if(p_rsa != NULL)
RSA_free(p_rsa);
if(*p_sign != NULL)
free(*p_sign);

return 0;
}

int my_verify(char *path_key, char *data, unsigned int len_data, char *p_sign, unsigned int len_sign)
{
FILE *p_file;
RSA *p_rsa;
unsigned char SHA[SHA_DIGEST_LENGTH] = "";

if((p_file = fopen(path_key, "r")) == NULL)
{
perror("the file open fail ");
return 0;
}

if((p_rsa = PEM_read_RSA_PUBKEY(p_file, NULL, NULL, NULL)) == NULL)
{
//ERR_print_errors_fp(stdout);
printf("RSA Private key read error! ");
goto error;
}
fclose(p_file);

if(SHA1(data, len_data, SHA) == NULL)
{
printf("Hash error!! ");
goto error;
}

#if 1
printf(" The second SHA1 data is: ");
drump_hex(SHA, SHA_DIGEST_LENGTH);
#endif // 1

/*
int RSA_verify(int type, const unsigned char *m, unsigned int m_len,
unsigned char * sigbuf, unsigned int siglen, RSA *rsa);
RSA_verify()验证大小为siglen的签名sigbuf是否匹配大小为m_len的给定消息摘要m。
type表示用于生成签名的消息摘要算法。rsa是签名者的公钥。

*/
if(RSA_verify(NID_sha1, SHA, SHA_DIGEST_LENGTH, p_sign ,len_sign, p_rsa) != 1)
{
printf("RSA_sign() error! ");
goto error;
}
else
{
return 1;
}
error:
if(p_file != NULL)
fclose(p_file);
if(p_rsa != NULL)
RSA_free(p_rsa);
if(p_file != NULL)
fclose(p_file);

}

void drump_hex(char * data, unsigned int len_data)
{
for(int i = 0; i < len_data; i++)
{
if(i % 8 == 0)
{
printf(" %08d : ", i/8);
}
printf("%02X ", (unsigned char)data[i]);
}
}

//在linux下编译的时候,记得要加链接 -lcrypto。  例如:gcc RSA_sign_verify_my.c -o sign3 -lcrypto

原文地址:https://www.cnblogs.com/ruigelwang/p/12750343.html