摘自:https://www.dandelioncloud.cn/article/details/1498198300963708930
// RsaUtil.c
#include <string>
using namespace std;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/sha.h>
#include "Base64Util.h"
#define KEY_LENGTH 2048
#define PUB_EXP 65537
static string hex_2_string(unsigned char *data, unsigned int data_len)
{
string str = "";
size_t malloc_len = 2 * data_len + 1;
char *tmp_str = (char *)calloc(1, malloc_len);
if (NULL == tmp_str) {
return "";
}
for (unsigned int index = 0; index < data_len; index++) {
snprintf(tmp_str + strlen(tmp_str), malloc_len - strlen(tmp_str) - 1, "%02x", data[index]);
}
str = tmp_str;
free(tmp_str);
return str;
}
// 加载公钥
static RSA *load_publicKey(string path_public_key)
{
FILE *fp = fopen(path_public_key.c_str(), "r");
if (NULL == fp) {
printf("Failed to load public key\n");
return NULL;
}
RSA *rsa_pub = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL); // 千万不要调用PEM_read_RSA_PUBKEY()接口, 必现: 会导致RSA_verify() 函数内部 coredump
fclose(fp);
return rsa_pub;
}
// 加载私钥
static RSA *load_privateKey(string path_private_key)
{
FILE *fp = fopen(path_private_key.c_str(), "r");
if (NULL == fp) {
printf("Failed to load private key\n");
return NULL;
}
RSA *rsa_priv = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
fclose(fp);
printf("RSA_size=%d\r\n", RSA_size(rsa_priv));
return rsa_priv;
}
static string __rsa_sign(RSA *private_key, const unsigned char *data, size_t data_len)
{
unsigned char *signature = NULL;
unsigned int signature_length = 0;
string out_signature = "";
printf("=========================================================\n");
printf("__rsa_sign data=%s, len=%lu\n", data, data_len);
signature_length = RSA_size(private_key);
printf("__rsa_sign signature_length=%d\n", signature_length);
signature = (unsigned char *)malloc(signature_length);
// 计算哈希值
signature_length = RSA_size(private_key);
if (1 != RSA_sign(NID_sha256, data, data_len, signature, &signature_length, private_key)) {
printf("Failed to generate RSA signature.\n");
return "";
}
printf("__rsa_sign signature_length=%d|\n%s\n", signature_length, hex_2_string(signature, signature_length).c_str());
out_signature = base64_encode(signature, signature_length);
free(signature);
printf("=========================================================\n\n\n");
return out_signature;
}
static int __rsa_verify(RSA *public_key, const unsigned char *data, size_t data_len, string signature_base64)
{
unsigned char *signature = NULL;
int signature_length = 0;
int ret = 0;
printf("=========================================================\n");
signature_length = RSA_size(public_key);
printf("rsa_verify() signature_length=%d|%lu\n", signature_length, signature_base64.length());
ret = base64_decode(signature_base64, &signature, &signature_length);
if (0 != ret) {
printf("base64_decode() failed.\n");
return -1;
}
printf("rsa_verify() signature_length=%d|%lu|\n%s\n", signature_length, signature_base64.length(), hex_2_string(signature, signature_length).c_str());
if (1 != RSA_verify(NID_sha256, data, data_len, signature, signature_length, public_key)) {
printf("RSA signature verification failed.\n");
return -1;
}
printf("RSA signature verification succeeded.\n");
free(signature);
printf("=========================================================\n\n\n");
return 0;
}
string rsa_sign(string path_private_key, const unsigned char *data, size_t data_len)
{
RSA *private_key = NULL;
string out_signature = "";
private_key = load_privateKey(path_private_key);
out_signature = __rsa_sign(private_key, data, data_len);
RSA_free(private_key);
return out_signature;
}
int rsa_verify(string path_public_key, const unsigned char *data, size_t data_len, string signature_base64)
{
int ret = 0;
RSA *public_key = NULL;
public_key = load_publicKey(path_public_key);
ret = __rsa_verify(public_key, data, data_len, signature_base64);
RSA_free(public_key);
return ret;
}
#if 1
int main() {
string sig = "";
string path_public_key = "/root/test/81/lanxin_public.pem";
string path_private_key = "/root/test/81/lanxin_private.pem";
string data = "This is a test message.";
int ret = 0;
//RSA *rsa = RSA_generate_key(KEY_LENGTH, PUB_EXP, NULL, NULL);
RSA *private_key = load_privateKey(path_private_key);
RSA *public_key = load_publicKey(path_public_key);
sig = __rsa_sign(private_key, (const unsigned char*)data.c_str(), data.length());
if (sig.length() <= 0) {
printf("RSA_sign Failed.\n");
return -1;
}
printf("sig=%s|\n", sig.c_str());
ret = __rsa_verify(public_key, (const unsigned char*)data.c_str(), data.length(), sig);
if (0 != ret) {
printf("rsa_verify Failed.\n");
return -1;
}
return 0;
}
#endif
// Base64Util.c
#include <string>
using namespace std;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include "Base64Util.h"
/*****************************************************************
Base64编码
参数 : data, 输入参数, 输入数据
data_len, 输入参数, 输入数据长度
return : 长度>0, 成功, 返回 base64 字符串
长度=0, 失败
*****************************************************************/
string base64_encode(const unsigned char *data, int data_len)
{
BIO *bio = NULL;
BIO *b64 = NULL;
char *buffer = NULL;
int buf_len = 0;
if (NULL == data || 0 >= data_len) {
return "";
}
// 创建Base64编码的BIO
b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); // 去掉所有换行符
bio = BIO_new(BIO_s_mem());
bio = BIO_push(b64, bio);
// 写入数据并刷新BIO
BIO_write(bio, data, data_len);
(void)BIO_flush(bio);
// 读取Base64编码后的数据
buf_len = BIO_get_mem_data(bio, &buffer);
if (0 <= buf_len) {
buffer[buf_len] = '\0';
}
string base64_str = (NULL == buffer) ? "" : buffer;
// 清理资源
BIO_free_all(bio); // 内部已经 释放buffer
return base64_str;
}
/*****************************************************************
Base64解码
参数 : base64_str, 输入参数, base64 字符串
output, 输出参数, 输出数据(请调用者自行free)
out_len, 输出参数, 输出数据长度
return : 0, 成功
-1, 失败
*****************************************************************/
int base64_decode(string base64_str, unsigned char **output, int *out_len)
{
BIO *bio = NULL;
BIO *b64 = NULL;
char *buffer = NULL;
int buf_len = 0;
int decoded_len = 0;
if (NULL == output || NULL == out_len) {
return -1;
}
// 创建Base64解码的BIO
b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); // 没有换行符
bio = BIO_new_mem_buf(base64_str.c_str(), base64_str.length());
bio = BIO_push(b64, bio);
// 读取Base64解码后的数据
buf_len = base64_str.length() * 3 / 4;
buffer = (char *)calloc(1, buf_len + 1);
decoded_len = BIO_read(b64, buffer, base64_str.length());
if (0 <= decoded_len) {
buffer[decoded_len] = '\0';
}
*output = (unsigned char *)buffer;
*out_len = decoded_len;
//printf("decoded_len=%d, buf_len=%d, buffer=%s\r\n", decoded_len, buf_len, buffer);
// 清理资源
BIO_free_all(bio);
return 0;
}
#if 0
// 主函数测试Base64编码和解码函数
int main() {
const char *str = "Hello, World!我爱你";
string base64_str = "";
unsigned char *output = NULL;
int out_len = 0;
int ret = 0;
base64_str = base64_encode((const unsigned char *)str, strlen(str));
ret = base64_decode(base64_str, &output, &out_len);
printf("base64=%s\r\n", base64_str.c_str());
printf("ret=%d, out_len=%d, str=%s\r\n", ret, out_len, output);
free(output);
return 0;
}
#endif
g++ Base64Util.c RsaUtil.c -lcrypto -g -Wall ; ./a.out