示例代码:
#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