C++使用OpenSSL实现Rsa验证签名、验签----自测OK
摘自:https://wenku.csdn.net/answer/7c7f06c9f8bb466fb48f47bae5aaf99d
摘自:https://www.dandelioncloud.cn/article/details/1498198300963708930
//RsaUtil.h #ifndef __RSA_UTIL_H__ #define __RSA_UTIL_H__ #ifdef __cplusplus //告诉编译器,这部分代码按C语言的格式进行编译,而不是C++的 extern "C"{ #endif string UTIL_rsa_sign_sha512(string path_private_key, const unsigned char *data, unsigned int data_len); int UTIL_rsa_verify_sha512(string path_public_key, const unsigned char *data, unsigned int data_len, string signature_base64); #ifdef __cplusplus //告诉编译器,这部分代码按C语言的格式进行编译,而不是C++的 } #endif #endif /* __RSA_UTIL_H__ */
//RsaUtil.cpp
#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 "xxxx_platform_common.h" #include "liblicense_log.h" #include "Base64Util.h" #include "RsaUtil.h" #define DEBUG_RSAUTIL (1) #define print_ln(log_level, fmt, ...) do {printf("(%s|%d)" fmt "\r\n", __func__, __LINE__, ##__VA_ARGS__); fflush(stdout);} while(0)
/***************************************************************** 加载公钥 参数 : path_public_key, 公钥文件路径 return : 非NULL, 成功, 返回公钥对象指针 NULL, 失败 *****************************************************************/ static RSA *load_public_key(string path_public_key) { FILE *fp = fopen(path_public_key.c_str(), "r"); if (NULL == fp) { xxxx_print_ln(xxxx_ERROR, "Failed to load public key"); return NULL; } RSA *rsa_pub = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL); // 千万不要调用 PEM_read_RSA_PUBKEY() 接口, 必现: 会导致RSA_verify() 函数内部 coredump fclose(fp); return rsa_pub; } /***************************************************************** 加载私钥 参数 : path_private_key, 私钥文件路径 return : 非NULL, 成功, 返回私钥对象指针 NULL, 失败 *****************************************************************/ static RSA *load_private_key(string path_private_key) { FILE *fp = NULL; RSA *rsa_priv = NULL; fp = fopen(path_private_key.c_str(), "r"); if (NULL == fp) { xxxx_print_ln(xxxx_ERROR, "Failed to load private key"); return NULL; } rsa_priv = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); fclose(fp); return rsa_priv; } /***************************************************************** 私钥签名(sha512) 参数 : private_key, 私钥对象指针 data, 输入参数, 待签名数据 data_len, 输入参数, 待签名数据字节个数 return : 长度>0, 成功, 返回签名的 base64 字符串 长度=0, 失败 *****************************************************************/ static string __rsa_sign_sha512(RSA *private_key, const unsigned char *data, unsigned int data_len) { unsigned char *signature = NULL; unsigned int signature_length = 0; string signature_base64 = ""; unsigned char data_digest[SHA512_DIGEST_LENGTH] = {'\0'}; if (NULL == private_key || NULL == data || 0 >= data_len) { xxxx_print_ln(xxxx_ERROR, "wrong parameter."); return ""; } #if DEBUG_RSAUTIL xxxx_print_ln(xxxx_DEBUG, "========================================================="); xxxx_print_ln(xxxx_DEBUG, "__rsa_sign data=%s, len=%u", data, data_len); #endif // 1. 分配空间 signature_length = RSA_size(private_key); #if DEBUG_RSAUTIL xxxx_print_ln(xxxx_DEBUG, "__rsa_sign signature_length=%u", signature_length); #endif if (0 >= signature_length) { xxxx_print_ln(xxxx_ERROR, "wrong private_key"); return ""; } signature = (unsigned char *)calloc(1, signature_length); if (NULL == signature) { xxxx_print_ln(xxxx_ERROR, "malloc Failed(size=%u).", signature_length); return ""; } // 2. 计算摘要 SHA512(data, data_len, data_digest); // 3. 计算签名 if (1 != RSA_sign(NID_sha512, data_digest, SHA512_DIGEST_LENGTH, signature, &signature_length, private_key)) { xxxx_print_ln(xxxx_ERROR, "Failed to generate RSA signature."); xxxx_free(signature); return ""; } #if DEBUG_RSAUTIL xxxx_print_ln(xxxx_DEBUG, "__rsa_sign signature_length=%u|\n%s", signature_length, hex_2_string(signature, signature_length).c_str()); #endif // 4. 计算签名的base64 signature_base64 = UTIL_base64_encode(signature, signature_length); xxxx_free(signature); #if DEBUG_RSAUTIL xxxx_print_ln(xxxx_DEBUG, "out_signature=%s", signature_base64.c_str()); xxxx_print_ln(xxxx_DEBUG, "========================================================="); #endif return signature_base64; } /***************************************************************** 公钥验签(sha512) 参数 : public_key, 公钥对象指针 data, 输入参数, 待签名数据 data_len, 输入参数, 待签名数据字节个数 signature_base64, 签名的 base64 字符串 return : 0, 成功 -1, 失败 *****************************************************************/ static int __rsa_verify_sha512(RSA *public_key, const unsigned char *data, unsigned int data_len, string signature_base64) { unsigned char *signature = NULL; unsigned int signature_length = 0; int ret = 0; unsigned char data_digest[SHA512_DIGEST_LENGTH] = {'\0'}; if (NULL == public_key || NULL == data || 0 >= data_len || 0 >= signature_base64.length()) { xxxx_print_ln(xxxx_ERROR, "wrong parameter."); return -1; } #if DEBUG_RSAUTIL xxxx_print_ln(xxxx_DEBUG, "========================================================="); xxxx_print_ln(xxxx_DEBUG, "__rsa_verify data=%s, len=%u", data, data_len); #endif #if DEBUG_RSAUTIL signature_length = (unsigned int)RSA_size(public_key); xxxx_print_ln(xxxx_DEBUG, "rsa_verify() signature_length=%u|%lu", signature_length, signature_base64.length()); #endif // 1. 对签名进行 base64 解码 ret = UTIL_base64_decode(signature_base64, &signature, &signature_length); if (0 != ret) { xxxx_print_ln(xxxx_ERROR, "base64_decode() failed."); return -1; } #if DEBUG_RSAUTIL xxxx_print_ln(xxxx_DEBUG, "rsa_verify() signature_length=%d|%lu|\n%s", signature_length, signature_base64.length(), hex_2_string(signature, signature_length).c_str()); #endif // 2. 计算摘要 SHA512(data, data_len, data_digest); // 3. 验证签名 if (1 != RSA_verify(NID_sha512, data_digest, SHA512_DIGEST_LENGTH, signature, signature_length, public_key)) { xxxx_print_ln(xxxx_ERROR, "RSA_verify Failed."); return -1; } xxxx_free(signature); #if DEBUG_RSAUTIL xxxx_print_ln(xxxx_DEBUG, "RSA signature verification succeeded."); xxxx_print_ln(xxxx_DEBUG, "========================================================="); #endif return 0; } /***************************************************************** 私钥签名(sha512) 参数 : path_private_key, 私钥文件路径 data, 输入参数, 待签名数据 data_len, 输入参数, 待签名数据字节个数 return : 长度>0, 成功, 返回签名的 base64 字符串 长度=0, 失败 *****************************************************************/ string UTIL_rsa_sign_sha512(string path_private_key, const unsigned char *data, unsigned int data_len) { RSA *private_key = NULL; string signature_base64 = ""; if (0 >= path_private_key.length() || NULL == data || 0 >= data_len) { xxxx_print_ln(xxxx_ERROR, "wrong parameter."); return ""; } private_key = load_private_key(path_private_key); if (NULL == private_key) { goto __clean; } signature_base64 = __rsa_sign_sha512(private_key, data, data_len); __clean: if (NULL != private_key) { RSA_free(private_key); } return signature_base64; } /***************************************************************** 公钥验签(sha512) 参数 : path_public_key, 公钥文件路径 data, 输入参数, 待签名数据 data_len, 输入参数, 待签名数据字节个数 signature_base64, 签名的 base64 字符串 return : 0, 成功 -1, 失败 *****************************************************************/ int UTIL_rsa_verify_sha512(string path_public_key, const unsigned char *data, unsigned int data_len, string signature_base64) { int ret = 0; RSA *public_key = NULL; if (0 >= path_public_key.length() || NULL == data || 0 >= data_len || 0 >= signature_base64.length() ) { xxxx_print_ln(xxxx_ERROR, "wrong parameter."); return -1; } public_key = load_public_key(path_public_key); if (NULL == public_key) { ret = -1; goto __clean; } ret = __rsa_verify_sha512(public_key, data, data_len, signature_base64); __clean: if (NULL != public_key) { RSA_free(public_key); } return ret; } #if DEBUG_RSAUTIL int test0(void) { string data = "This is a test message."; string signature_base64 = ""; int ret = 0; #define KEY_LENGTH (2048) #define PUB_EXP (65537) RSA *rsa = RSA_generate_key(KEY_LENGTH, PUB_EXP, NULL, NULL); if (NULL == rsa) { ret = -1; goto __clean; } signature_base64 = __rsa_sign_sha512(rsa, (const unsigned char*)data.c_str(), data.length()); if (signature_base64.length() <= 0) { xxxx_print_ln(xxxx_ERROR, "RSA_sign Failed."); ret = -1; goto __clean; } ret = __rsa_verify_sha512(rsa, (const unsigned char*)data.c_str(), data.length(), signature_base64); if (0 != ret) { xxxx_print_ln(xxxx_ERROR, "rsa_verify Failed."); ret = -1; goto __clean; } xxxx_print_ln(xxxx_DEBUG, "test0 rsa_verify Success."); __clean: if (NULL != rsa) { RSA_free(rsa); } return ret; } int test1(void) { string signature_base64 = ""; string path_public_key = "/root/test/81/license_public.pem"; string path_private_key = "/root/test/81/license_private.pem"; string data = "This is a test message."; int ret = 0; RSA *public_key = load_public_key(path_public_key); RSA *private_key = load_private_key(path_private_key); if (NULL == public_key || NULL == private_key) { goto __clean; } signature_base64 = __rsa_sign_sha512(private_key, (const unsigned char*)data.c_str(), data.length()); if (signature_base64.length() <= 0) { xxxx_print_ln(xxxx_ERROR, "RSA_sign Failed."); goto __clean; } xxxx_print_ln(xxxx_DEBUG, "signature_base64=%s", signature_base64.c_str()); ret = __rsa_verify_sha512(public_key, (const unsigned char*)data.c_str(), data.length(), signature_base64); if (0 != ret) { xxxx_print_ln(xxxx_ERROR, "rsa_verify Failed."); goto __clean; } xxxx_print_ln(xxxx_DEBUG, "test1 rsa_verify Success."); __clean: if (NULL != public_key) { RSA_free(public_key); } if (NULL != private_key) { RSA_free(private_key); } return 0; } int test2(void) { string signature_base64 = ""; string path_public_key = "/root/test/81/license_public.pem"; string path_private_key = "/root/test/81/license_private.pem"; string data = "This is a test message."; int ret = 0; signature_base64 = UTIL_rsa_sign_sha512(path_private_key, (const unsigned char *)data.c_str(), data.length()); if (signature_base64.length() <= 0) { xxxx_print_ln(xxxx_ERROR, "RSA_sign Failed."); return -1; } xxxx_print_ln(xxxx_DEBUG, "signature_base64=%s", signature_base64.c_str()); ret = UTIL_rsa_verify_sha512(path_public_key, (const unsigned char *)data.c_str(), data.length(), signature_base64); if (0 != ret) { xxxx_print_ln(xxxx_ERROR, "rsa_verify Failed."); return -1; } xxxx_print_ln(xxxx_DEBUG, "test2 rsa_verify Success."); return 0; } int main(int argc, char *argv[]) { //test0(); //test1(); test2(); return 0; } #endif
g++ Base64Util.c RsaUtil.c -lcrypto -g -Wall ; ./a.out