编译环境
CRsa.h
#pragma once
#include <cassert>
#include <string>
#include <fstream>
#include <iostream>
#include <openssl\pem.h>
#include <openssl\rsa.h>
#include <openssl\bio.h>
#pragma comment(lib, "libcrypto.lib")
#pragma comment(lib, "libssl.lib")
#define DEBUG_TEST
#define KEY_LENGTH 2048
using std::string;
void GenerateRSAKey(string& out_pub_key, string& out_pri_key);
string RsaPriEncrypt(const string& text, const string& pri_key);
string RsaPubDecrypt(const string& data, const string& pub_key);
string RsaPubEncrypt(const string& text, const string& pub_key);
string RsaPriDecrypt(const string& data, const string& pri_key);
string GenerateRsaSignByString(const string& message, const string& pri_key);
bool VerifyRsaSignByString(const string& sign, const string& pubkey, const string& verify_str);
CRsa.cpp
#include "CRsa.h"
const char* pub_key_file = { "./key/pubkey.pem" };
const char* pri_key_file = { "./key/prikey.pem" };
using namespace std;
void GenerateRSAKey(string& out_pub_key, string& out_pri_key)
{
RSA* keypair = RSA_new();
BIGNUM* bne = BN_new();
BN_set_word(bne, (unsigned int)RSA_3);
RSA_generate_key_ex(keypair, KEY_LENGTH, bne, NULL);
BIO* pri = BIO_new(BIO_s_mem());
PEM_write_bio_RSAPrivateKey(pri, keypair, NULL, NULL, 0, NULL, NULL);
size_t pri_len = BIO_pending(pri);
BIO* pub = BIO_new(BIO_s_mem());
PEM_write_bio_RSAPublicKey(pub, keypair);
size_t pub_len = BIO_pending(pub);
char* pri_key = (char*)malloc(pri_len + 1);
char* pub_key = (char*)malloc(pub_len + 1);
#ifdef DEBUG_TEST
assert(pri_key != NULL);
assert(pub_key != NULL);
#endif
BIO_read(pri, pri_key, pri_len);
BIO_read(pub, pub_key, pub_len);
pri_key[pri_len] = '\0';
pub_key[pub_len] = '\0';
out_pub_key = pub_key;
out_pri_key = pri_key;
ofstream pub_file(pub_key_file);
if (!pub_file.is_open())
{
perror("pub key file open fail:");
exit(0);
}
pub_file << pub_key;
pub_file.close();
ofstream pri_file(pri_key_file);
if (!pri_file.is_open())
{
perror("pri key file open fail:");
exit(0);
}
pri_file << pri_key;
pri_file.close();
RSA_free(keypair);
BIO_free_all(pub);
BIO_free_all(pri);
free(pri_key);
free(pub_key);
}
inline RSA* string2rsa(const string& key, decltype(PEM_read_bio_RSAPublicKey)* callback) {
BIO* keybio = BIO_new_mem_buf((unsigned char*)key.c_str(), -1);
RSA* rsa = RSA_new();
rsa = callback(keybio, &rsa, NULL, NULL);
BIO_free(keybio);
return rsa;
}
string RsaPriEncrypt(const string& text, const string& pri_key)
{
RSA* rsa = string2rsa(pri_key, PEM_read_bio_RSAPrivateKey);
if (rsa == nullptr) {
cout << "PEM_read_bio_RSAPrivateKey fail" << endl;
return string();
}
int key_len = RSA_size(rsa);
int block_len = key_len - 11;
string data;
char* sub_data = new char[key_len + 1];
string sub_text;
for (int ret = 0, pos = 0; pos < text.length(); pos += block_len) {
sub_text = text.substr(pos, block_len);
memset(sub_data, 0, key_len + 1);
ret = RSA_private_encrypt(sub_text.length(), (const unsigned char*)sub_text.c_str(), (unsigned char*)sub_data, rsa, RSA_PKCS1_PADDING);
if (ret >= 0) {
data.append(string(sub_data, ret));
}
}
delete[] sub_data;
RSA_free(rsa);
return data;
}
string RsaPubDecrypt(const string& data, const string& pub_key)
{
RSA* rsa = string2rsa(pub_key, PEM_read_bio_RSAPublicKey);
if (rsa == nullptr) {
cout << "PEM_read_bio_RSAPublicKey fail" << endl;
return string();
}
int len = RSA_size(rsa);
char* sub_text = new char[len + 1];
string text;
string sub_data;
for (int ret = 0, pos = 0; pos < data.length(); pos += len) {
sub_data = data.substr(pos, len);
memset(sub_text, 0, len + 1);
ret = RSA_public_decrypt(sub_data.length(), (const unsigned char*)sub_data.c_str(), (unsigned char*)sub_text, rsa, RSA_PKCS1_PADDING);
if (ret >= 0) {
text.append(string(sub_text, ret));
}
}
delete[] sub_text;
RSA_free(rsa);
return text;
}
string RsaPubEncrypt(const string& text, const string& pub_key)
{
RSA* rsa = string2rsa(pub_key, PEM_read_bio_RSAPublicKey);
if (rsa == nullptr) {
cout << "PEM_read_bio_RSAPublicKey fail" << endl;
return string();
}
int key_len = RSA_size(rsa);
int block_len = key_len - 11;
char* sub_data = new char[key_len + 1];
string sub_text;
string data;
for (int ret = 0, pos = 0; pos < text.length(); pos += block_len) {
sub_text = text.substr(pos, block_len);
memset(sub_data, 0, key_len + 1);
ret = RSA_public_encrypt(sub_text.length(), (const unsigned char*)sub_text.c_str(), (unsigned char*)sub_data, rsa, RSA_PKCS1_PADDING);
if (ret >= 0) {
data.append(string(sub_data, ret));
}
}
RSA_free(rsa);
delete[] sub_data;
return data;
}
string RsaPriDecrypt(const string& data, const string& pri_key)
{
RSA* rsa = string2rsa(pri_key, PEM_read_bio_RSAPrivateKey);
if (rsa == nullptr) {
cout << "PEM_read_bio_RSAPrivateKey fail" << endl;
return string();
}
int len = RSA_size(rsa);
char* sub_text = new char[len + 1];
string sub_data;
string text;
for (int ret = 0, pos = 0; pos < data.length(); pos += len) {
sub_data = data.substr(pos, len);
memset(sub_text, 0, len + 1);
ret = RSA_private_decrypt(sub_data.length(), (const unsigned char*)sub_data.c_str(), (unsigned char*)sub_text, rsa, RSA_PKCS1_PADDING);
if (ret >= 0) {
text.append(string(sub_text, ret));
}
}
delete[] sub_text;
RSA_free(rsa);
return text;
}
string GenerateRsaSignByString(const string& message, const string& pri_key) {
OpenSSL_add_all_algorithms();
RSA* rsa = string2rsa(pri_key, PEM_read_bio_RSAPrivateKey);
if (rsa == nullptr) {
cout << "PEM_read_bio_RSAPrivateKey fail" << endl;
return string();
}
unsigned int size = RSA_size(rsa);
string sign;
sign.resize(size);
int ret = RSA_sign(NID_md5, (const unsigned char*)message.c_str(), message.length(), (unsigned char*)sign.data(), &size, rsa);
RSA_free(rsa);
if (ret != 1) {
cout << "RSA_sign failed" << endl;
return string();
}
return sign;
}
bool VerifyRsaSignByString(const string &sign, const string& pub_key, const string& verify_str) {
RSA* rsa = string2rsa(pub_key, PEM_read_bio_RSAPublicKey);
if (rsa == nullptr) {
cout << "PEM_read_bio_RSAPublicKey fail" << endl;
return false;
}
int ret = RSA_verify(NID_md5, (const unsigned char*)verify_str.c_str(), verify_str.size(), (const unsigned char*)sign.c_str(), sign.size(), rsa);
RSA_free(rsa);
if (ret != 1) {
cout << "RSA_verify failed" << endl;
return false;
}
return true;
}
main.cpp
#include <iostream>
#include <openssl\md5.h>
#include <openssl\sha.h>
#include "CRsa.h"
using namespace std;
int main() {
string prikey, pubkey;
GenerateRSAKey(pubkey, prikey);
string cipher1 = RsaPubEncrypt("hello\n", pubkey);
cout << RsaPriDecrypt(cipher1, prikey);
string cipher2 = RsaPriEncrypt("world\n", prikey);
cout << RsaPubDecrypt(cipher2, pubkey);
string sign = GenerateRsaSignByString("jifanlichou", prikey);
string verify("jifanlichou");
if (VerifyRsaSignByString(sign, pubkey, verify))
cout << "verify success" << endl;
unsigned char md5bigest[16], shabigest[20];
char message[] = { "jifanlichou is very cool" };
MD5((const unsigned char*)message, strlen(message), md5bigest);
cout << endl << "md5 : ";
for (unsigned short ch : md5bigest) {
cout <<hex << ch;
}
cout << endl;
SHA1((const unsigned char*)message, strlen(message), shabigest);
cout << "sha1 : ";
for (unsigned short ch : shabigest) {
cout << hex << ch;
}
cout << endl;
}