RSA私钥公钥加密解密与签名、SHA256相关代码
RSA私钥公钥加密解密与签名、SHA256
头文件:HashSignature.h
#ifndef _HASH_SIGNATURE_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/rand.h>
#include <stddef.h>
#include <iostream>
using namespace std;
#define PUBLIC_KEY_FILE "/home/xzj/Code/C++Code/RSA/rsaPublicKey.pem"
#define PRIVATE_KEY_FILE "/home/xzj/Code/C++Code/RSA/rsaPrivateKey.pem"
#define SIGNATURE_FILE "/home/xzj/Code/C++Code/RSA/sha256.sign"
#define DATA_FILE "/home/xzj/Code/C++Code/RSA/myfile.txt"
#define RSA_KEY_LENGTH 1024 // 密钥长度
#define RSA_PRIKEY_PSW "123"
class HashSignature {
public:
HashSignature();
virtual ~HashSignature();
bool generateRSAKey(const char* public_key_path_and_file_name,
const char* private_key_path_and_file_name,
const unsigned char* passwd, int passwd_len); // 函数方法生成密钥对
bool generateRSAKey(const char* public_key_path_and_file_name,
const char* private_key_path_and_file_name,
std::string strKey[2]); // 生成公钥私钥对写入到文件里并且返回公钥私钥字符串数据
bool generateRSAKey(const char* public_key_path_and_file_name,
const char* private_key_path_and_file_name); // 生成公钥私钥对写入到文件里
string RSAPrivateKeyEncypt(int clearText_length, const char* clearText, const char* private_key_path_and_file_name); // 私钥加密
string RSAPrivateKeyDecypt(int cipherText_length, const char* cipherText, const char* private_key_path_and_file_name); // 私钥解密
string RSAPublicKeyEncypt(int clearText_length, const char* clearText, const char* public_key_path_and_file_name); // 公钥加密
string RSAPublicKeyDecypt(int cipherText_length, const char* cipherText, const char* public_key_path_and_file_name); // 公钥解密
string create_hash_by_SHA256(const string data); // 生成hash值
string create_signature(int hash_length, string hash, const char* private_key_path_and_file_name); // 生成签名
string get_hash_from_signature(int signature_length, string signature, const char* public_key_path_and_file_name); // 解签
bool writeStringData_Into_File(const char* filepath, const char *data); //写数据到文件里
string readStringData_From_File(const char* filepath); // 从文件读取数据
bool verify_signature(const char* dataFile ,const char* public_key_path_and_file_name, const char* signatureFile); // 签证签名
};
#endif // _HASH_SIGNATURE_H_
源文件:HashSignature.cpp
#ifndef _HASH_SIGNATURE_H_
# include "HashSignature.h"
#endif
HashSignature::HashSignature() {
}
HashSignature::~HashSignature() {
}
/*
*@author xzj
*@copyright
*@description 生成RSA公钥私钥对(带有salt的)
*[建议新手如果参考这个的带salt的密钥对时一定要弄清楚:
*PEM_write_bio_RSAPrivateKey/PEM_write_bio_RSAPublicKey 在生成私钥和公钥带salt时,
*在PEM_read_bio_RSAPrivateKey/PEM_read_bio_RSAPublicKey时也需要带salt,salt是你自己定义的一个字符串]
*@param public_key_path_and_file_name : 公钥路径+文件名
*@param private_key_path_and_file_name : 私钥路径+文件名
*@param passwd : 自己定义的salt
*@param passwd_len : salt长度
*@return bool true is ok; false is error
*/
bool HashSignature::generateRSAKey(const char* public_key_path_and_file_name,
const char* private_key_path_and_file_name,
const unsigned char* passwd, int passwd_len) {
// 生成密钥对
RSA *keypair = NULL;
// keypair = RSA_generate_key(RSA_KEY_LENGTH, RSA_F4, NULL, NULL);
keypair = RSA_generate_key(RSA_KEY_LENGTH, RSA_3, NULL, NULL);
if (NULL == keypair) {
printf("RSA_generate_key error!\n");
return false;
}
//生成公钥文件
BIO* bio_public = NULL;
bio_public= BIO_new(BIO_s_file());
if (NULL == bio_public)
{
printf("generate_key bio file new error with bio_public!\n");
return false;
}
if (BIO_write_filename(bio_public, (void *)public_key_path_and_file_name) <= 0)
{
printf("BIO_write_filename error!\n");
return false;
}
if (PEM_write_bio_RSAPublicKey(bio_public, keypair) != 1)
{
printf("PEM_write_bio_RSAPublicKey error!\n");
return false;
}
printf("Create public key successful!\n");
BIO_free_all(bio_public); // 内存释放
// 生成私钥文件
BIO* bio_private = NULL;
bio_private = BIO_new_file(private_key_path_and_file_name, "w+");
if (NULL == bio_private)
{
printf("generate_key bio file new error with bio_private!\n");
return false;
}
// if (PEM_write_bio_RSAPrivateKey(bio_private, keypair, EVP_des_ede3_ofb(), (unsigned char *)passwd, passwd_len, NULL, NULL) != 1)
if (PEM_write_bio_RSAPrivateKey(bio_private, keypair, NULL, NULL, 0, NULL, NULL) != 1)
{
printf("PEM_write_bio_RSAPrivateKey error!\n");
return false;
}
printf("Create private key successful!\n");
BIO_free_all(bio_private); // 内存释放
RSA_free(keypair); // 内存释放
return true;
}
/*
*@author xzj
*@copyright
*@description 生成公钥私钥对写入到文件里并且返回公钥私钥字符串数据
*@param public_key_path_and_file_name : 公钥路径+文件名
*@param private_key_path_and_file_name : 私钥路径+文件名
*@param strKey : strKey[0]公钥字符串 strKey[0] 私钥字符串
*@return bool true is ok; false is error
*/
bool HashSignature::generateRSAKey(const char* public_key_path_and_file_name,
const char* private_key_path_and_file_name,
std::string strKey[2]) {
// 密钥对
size_t bio_private_length;
size_t bio_public_length;
char *private_key = NULL;
char *public_key = NULL;
// 生成密钥对
RSA *keypair = NULL;
keypair = RSA_generate_key(RSA_KEY_LENGTH, RSA_3, NULL, NULL);
if (NULL == keypair) {
printf("RSA_generate_key error!\n");
return false;
}
BIO* bio_public = NULL;
bio_public= BIO_new(BIO_s_mem());
if (NULL == bio_public)
{
printf("BIO_new has an error with bio_public!\n");
return false;
}
BIO* bio_private = NULL;
bio_private = BIO_new(BIO_s_mem());
if (NULL == bio_private)
{
printf("BIO_new has an error with bio_private!\n");
return false;
}
if (PEM_write_bio_RSAPrivateKey(bio_private, keypair, NULL, NULL, 0, NULL, NULL) != 1)
{
printf("PEM_write_bio_RSAPublicKey error!\n");
return false;
}
if (PEM_write_bio_RSAPublicKey(bio_public, keypair) != 1)
{
printf("PEM_write_bio_RSAPublicKey error!\n");
return false;
}
// 获取长度
bio_private_length = BIO_pending(bio_private);
bio_public_length = BIO_pending(bio_public);
// 分配长度
private_key = new char[bio_private_length + 1];
public_key = new char[bio_public_length + 1];
// 秘钥对读取到字符串
BIO_read(bio_private, private_key, bio_private_length);
BIO_read(bio_public, public_key, bio_public_length);
private_key[bio_private_length] = '\0';
public_key[bio_public_length] = '\0';
strKey[0] = public_key;
strKey[1] = private_key;
// 把公钥和私钥存储到磁盘文件当中(这种方式存储的是begin rsa public key/ begin rsa private key开头的)
FILE *private_file = fopen(private_key_path_and_file_name, "w");
if (NULL == private_file) {
printf("fopen failed\n");
return false;
}
fputs(private_key, private_file);
fclose(private_file);
FILE *public_file = fopen(public_key_path_and_file_name, "w");
if (NULL == public_file) {
printf("fopen failed\n");
return false;
}
fputs(public_key, public_file); // 向指定的文件写入一个字符串
fclose(public_file);
// 内存释放
RSA_free(keypair);
BIO_free(bio_private);
BIO_free(bio_public);
delete []private_key;
delete []public_key;
return true;
}
/*
*@author xzj
*@copyright
*@description 生成公钥私钥对写入到文件里
*@param public_key_path_and_file_name : 公钥路径+文件名
*@param private_key_path_and_file_name : 私钥路径+文件名
*@return bool true is ok; false is error
*/
bool HashSignature::generateRSAKey(const char* public_key_path_and_file_name,
const char* private_key_path_and_file_name) {
// 密钥对
size_t bio_private_length;
size_t bio_public_length;
char *private_key = NULL;
char *public_key = NULL;
// 生成密钥对
RSA *keypair = NULL;
keypair = RSA_generate_key(RSA_KEY_LENGTH, RSA_3, NULL, NULL);
if (NULL == keypair) {
printf("RSA_generate_key error!\n");
return false;
}
BIO* bio_public = NULL;
bio_public= BIO_new(BIO_s_mem());
if (NULL == bio_public)
{
printf("BIO_new has an error with bio_public!\n");
return false;
}
BIO* bio_private = NULL;
bio_private = BIO_new(BIO_s_mem());
if (NULL == bio_private)
{
printf("BIO_new has an error with bio_private!\n");
return false;
}
// 把私钥从密钥对里写到bio_private里
if (PEM_write_bio_RSAPrivateKey(bio_private, keypair, NULL, NULL, 0, NULL, NULL) != 1)
{
printf("PEM_write_bio_RSAPublicKey error!\n");
return false;
}
// 把公钥从密钥对里写到bio_public里
if (PEM_write_bio_RSAPublicKey(bio_public, keypair) != 1)
{
printf("PEM_write_bio_RSAPublicKey error!\n");
return false;
}
// 获取长度
bio_private_length = BIO_pending(bio_private);
bio_public_length = BIO_pending(bio_public);
// 分配长度
private_key = new char[bio_private_length + 1];
public_key = new char[bio_public_length + 1];
// 秘钥对分别读取到字符串
BIO_read(bio_private, private_key, bio_private_length);
BIO_read(bio_public, public_key, bio_public_length);
private_key[bio_private_length] = '\0';
public_key[bio_public_length] = '\0';
// 把公钥和私钥存储到磁盘文件当中(这种方式存储的是begin rsa public key/ begin rsa private key开头的)
FILE *private_file = fopen(private_key_path_and_file_name, "w");
if (NULL == private_file) {
printf("fopen failed\n");
return false;
}
fputs(private_key, private_file);
fclose(private_file);
FILE *public_file = fopen(public_key_path_and_file_name, "w");
if (NULL == public_file) {
printf("fopen failed\n");
return false;
}
fputs(public_key, public_file);
fclose(public_file);
// 内存释放
RSA_free(keypair);
BIO_free(bio_private);
BIO_free(bio_public);
delete []private_key;
delete []public_key;
return true;
}
// 工具生成公钥私钥(openssl)
//openssl genrsa -out myprivate.pem 4096
//openssl rsa -in myprivate.pem -pubout -out mypublic.pem
/*
*@author xzj
*@copyright
*@description 把数据data生成相应的hash值
*@param data : 数据
*@return string : hash值
*/
string HashSignature::create_hash_by_SHA256(const string data) {
char buf[2];
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, data.c_str(), data.size());
SHA256_Final(hash, &sha256);
std::string NewString = "";
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
sprintf(buf, "%02x", hash[i]);
NewString = NewString +buf;
}
return NewString;
}
/*
*@author xzj
*@copyright
*@description 通过摘要生成签名(私钥加签)
*@param hash_length : hash数据长度
*@param data : hash数据
*@param private_key_path_and_file_name : 私钥路径+文件名
*@return string : 签名数据
*/
string HashSignature::create_signature(int hash_length, string hash, const char* private_key_path_and_file_name) {
// int RSA_private_encrypt(int flen, unsigned char *from,unsigned char *to, RSA *rsa,int padding);
string encryptedText = "";
RSA *rsa = NULL;
BIO* bio_private = NULL;
bio_private = BIO_new(BIO_s_file());
// bio_private = BIO_new_file(private_key_path_and_file_name, "rb");
BIO_read_filename(bio_private, private_key_path_and_file_name); // 类似与fopen()
if (NULL == bio_private) {
printf("open_private_key bio file new error!\n");
return "";
}
// 此处有三种方法
// 1, 读取内存里生成的密钥对,再从内存生成rsa
// 2, 读取磁盘里生成的密钥对文本文件,在从内存生成rsa
// 3,直接从读取文件指针生成rsa
rsa = PEM_read_bio_RSAPrivateKey(bio_private, &rsa, NULL, NULL); // 类似read()
if (rsa == NULL) {
printf("open_private_key failed to PEM_read_bio_RSAPrivateKey!\n");
BIO_free(bio_private);
RSA_free(rsa);
return "";
}
int len = RSA_size(rsa);
printf("private key RSA is [%d]\n", len);
char *out = new char[len + 1];
memset(out, 0, len + 1);
int result = RSA_private_encrypt(hash_length, (unsigned char *)hash.c_str(), (unsigned char *)out, rsa, RSA_PKCS1_PADDING);
if (-1 == result) {
printf("RSA_private_encrypt is failed\n");
BIO_free(bio_private);
RSA_free(rsa);
delete []out;
return "";
} else {
printf("RSA_private_encrypt is successful\n");
encryptedText = string(out, result);
BIO_free(bio_private);
RSA_free(rsa);
delete []out;
return encryptedText;
}
}
/*
*@author xzj
*@copyright
*@description 公钥解签生成摘要
*@param hash_length : 签名数据长度
*@param data : 签名数据
*@param public_key_path_and_file_name : 公钥路径+文件名
*@return string : 摘要数据
*/
string HashSignature::get_hash_from_signature(int signature_length, string signature, const char* public_key_path_and_file_name) {
// int RSA_public_decrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa,int padding);
string clearText;
RSA *rsa = NULL;
BIO* bio_public = NULL;
bio_public = BIO_new(BIO_s_file());
BIO_read_filename(bio_public, public_key_path_and_file_name); // 类似与fopen()
if (NULL == bio_public) {
printf("open_public_key bio file new error!\n");
return "";
}
// 此处有三种方法
// 1, 读取内存里生成的密钥对,再从内存生成rsa
// 2, 读取磁盘里生成的密钥对文本文件,在从内存生成rsa
// 3,直接从读取文件指针生成rsa
rsa = PEM_read_bio_RSAPublicKey(bio_public, &rsa, NULL, NULL); // 类似与read()
if (NULL == rsa) {
printf("open_public_key failed to PEM_read_bio_RSAPublicKey!\n");
BIO_free(bio_public);
RSA_free(rsa);
return "";
}
int len = RSA_size(rsa);
printf("public key RSA is [%d]\n", len);
char *out = new char[len + 1];
memset(out, 0, len + 1);
int result = RSA_public_decrypt(signature_length, (unsigned char *)signature.c_str(), (unsigned char *)out, rsa, RSA_PKCS1_PADDING);
if (-1 == result) {
printf("RSA_public_decrypt is failed\n");
BIO_free(bio_public);
RSA_free(rsa);
delete []out;
return "";
} else {
printf("RSA_public_decrypt is successful\n");
clearText = string(out, result);
BIO_free(bio_public);
RSA_free(rsa);
delete []out;
return clearText;
}
}
/*
*@author xzj
*@copyright
*@description 写字符数据到文件中
*@param filepath : 文件的绝对路径
*@param data : 数据
*@return bool true is ok;false is failed
*/
bool HashSignature::writeStringData_Into_File(const char* filepath, const char *data){
bool result = false;
FILE *file = NULL;
file = fopen(filepath, "w");
do {
if(NULL == file) {
printf("文件打开失败\n");
break;
}
if (EOF == fwrite(data, strlen(data), 1, file)) {
printf("写文件失败\n");
break;
}
result = true;
} while (0);
fclose(file);
return result;
}
/*
*@author xzj
*@copyright
*@description 从文件中读取字符数据
*@param filepath : 文件的绝对路径
*@return string 字符串数据
*/
string HashSignature::readStringData_From_File(const char* filepath){
string data = "";
FILE *file = NULL;
file = fopen(filepath,"rb");
if(NULL == file) {
printf("文件打开失败\n");
return "";
}
unsigned char buf = {0};
while (fread(&buf, sizeof(unsigned char), 1, file)){ // 每次读一个字符,一直读
data += buf;
}
fclose(file);
return data;
}
/*
*@author xzj
*@copyright
*@description 给数据验签
*1、dataFile--->摘要----->私钥加密生成签名--->写入签名文件里(这一步已经完成,并且密钥对也已经生成)
*@param dataFile : 数据文件
*@param public_key_path_and_file_name : 公钥路径+文件名
*@param signatureFile : 签名文件的绝对路径
*@return bool true is ok;false is failed
*/
bool HashSignature::verify_signature(const char* dataFile ,const char* public_key_path_and_file_name, const char* signatureFile) {
bool result = false;
do {
// 从文件读取数据
string data = readStringData_From_File(dataFile);
//生成hash值
std::string dataHash = "";
dataHash = create_hash_by_SHA256(data);
printf("数据生成的hash值为[%s]\n", dataHash.c_str());
// 从文件读取签名
string readSignature = readStringData_From_File(signatureFile);
//签名公钥解密生成摘要
string hash = get_hash_from_signature(readSignature.length(), readSignature, public_key_path_and_file_name);
printf("摘要解签的hash值为[%s]\n", hash.c_str());
int compareResult = dataHash.compare(hash);
if (0 == compareResult) {
printf("签名验证成功\n");
result = true;
} else {
printf("签名验证失败\n");
}
} while (0);
return result;
}
/*
*@author xzj
*@copyright
*@description 私钥加密
*@param clearText_length : 明文数据长度
*@param clearText : 明文数据
*@param private_key_path_and_file_name : 私钥路径+文件名
*@return string cipherText 密文数据
*/
string HashSignature::RSAPrivateKeyEncypt(int clearText_length, const char* clearText, const char* private_key_path_and_file_name) {
// int RSA_private_encrypt(int flen, unsigned char *from,unsigned char *to, RSA *rsa,int padding);
string cipherText = "";
RSA *rsa = NULL;
BIO* bio_private = NULL;
bio_private = BIO_new(BIO_s_file());
// bio_private = BIO_new_file(private_key_path_and_file_name, "rb");
BIO_read_filename(bio_private, private_key_path_and_file_name); // 类似与fopen()
if (NULL == bio_private) {
printf("open_private_key bio file new error!\n");
return cipherText;
}
// 此处有三种方法
// 1, 读取内存里生成的密钥对,再从内存生成rsa
// 2, 读取磁盘里生成的密钥对文本文件,在从内存生成rsa
// 3,直接从读取文件指针生成rsa
rsa = PEM_read_bio_RSAPrivateKey(bio_private, &rsa, NULL, NULL); // 类似read()
if (rsa == NULL) {
printf("open_private_key failed to PEM_read_bio_RSAPrivateKey!\n");
BIO_free(bio_private);
RSA_free(rsa);
return cipherText;
}
int len = RSA_size(rsa);
printf("private key RSA is [%d]\n", len);
char *out = new char[len + 1];
memset(out, 0, len + 1);
int result = RSA_private_encrypt(clearText_length, (unsigned char *)clearText, (unsigned char *)out, rsa, RSA_PKCS1_PADDING);
if (-1 == result) {
printf("RSA_private_encrypt is failed\n");
BIO_free(bio_private);
RSA_free(rsa);
delete []out;
return cipherText;
} else {
printf("RSA_private_encrypt is successful\n");
cipherText = string(out, result);
BIO_free(bio_private);
RSA_free(rsa);
delete []out;
return cipherText;
}
}
/*
*@author xzj
*@copyright
*@description 私钥解密
*@param cipherText_length : 密文数据长度
*@param cipherText : 密文数据
*@param private_key_path_and_file_name : 私钥路径+文件名
*@return string cipherText 明文数据
*/
string HashSignature::RSAPrivateKeyDecypt(int cipherText_length, const char* cipherText, const char* private_key_path_and_file_name) {
// int RSA_private_decrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa,int padding);
string clearText = "";
RSA *rsa = NULL;
BIO* bio_private = NULL;
bio_private = BIO_new(BIO_s_file());
BIO_read_filename(bio_private, private_key_path_and_file_name); // 类似与fopen()
if (NULL == bio_private) {
printf("open_private_key bio file new error!\n");
return clearText;
}
// 此处有三种方法
// 1, 读取内存里生成的密钥对,再从内存生成rsa
// 2, 读取磁盘里生成的密钥对文本文件,在从内存生成rsa
// 3,直接从读取文件指针生成rsa
rsa = PEM_read_bio_RSAPrivateKey(bio_private, &rsa, NULL, NULL); // 类似与read()
if (NULL == rsa) {
printf("open_private_key failed to PEM_read_bio_RSAPrivateKey!\n");
BIO_free(bio_private);
RSA_free(rsa);
return clearText;
}
int len = RSA_size(rsa);
printf("private key RSA is [%d]\n", len);
char *out = new char[len + 1];
memset(out, 0, len + 1);
int result = RSA_private_decrypt(cipherText_length, (unsigned char *)cipherText, (unsigned char *)out, rsa, RSA_PKCS1_PADDING);
if (-1 == result) {
printf("RSA_private_decrypt is failed\n");
BIO_free(bio_private);
RSA_free(rsa);
delete []out;
return clearText;
} else {
printf("RSA_private_decrypt is successful\n");
clearText = string(out, result);
BIO_free(bio_private);
RSA_free(rsa);
delete []out;
return clearText;
}
}
/*
*@author xzj
*@copyright
*@description 公钥加密
*@param clearText_length : 明文数据长度
*@param clearText : 明文数据
*@param private_key_path_and_file_name : 公钥路径+文件名
*@return string cipherText 密文数据
*/
string HashSignature::RSAPublicKeyEncypt(int clearText_length, const char* clearText, const char* public_key_path_and_file_name) {
// int RSA_public_encrypt(int flen, unsigned char *from,unsigned char *to, RSA *rsa,int padding);
string cipherText = "";
RSA *rsa = NULL;
BIO* bio_public = NULL;
bio_public = BIO_new(BIO_s_file());
// bio_public = BIO_new_file(public_key_path_and_file_name, "rb");
BIO_read_filename(bio_public, public_key_path_and_file_name); // 类似与fopen()
if (NULL == bio_public) {
printf("open_public_key bio file new error!\n");
return cipherText;
}
// 此处有三种方法
// 1, 读取内存里生成的密钥对,再从内存生成rsa
// 2, 读取磁盘里生成的密钥对文本文件,在从内存生成rsa
// 3,直接从读取文件指针生成rsa
rsa = PEM_read_bio_RSAPublicKey(bio_public, &rsa, NULL, NULL); // 类似read()
if (rsa == NULL) {
printf("open_public_key failed to PEM_read_bio_RSAPublicKey!\n");
BIO_free(bio_public);
RSA_free(rsa);
return cipherText;
}
int len = RSA_size(rsa);
printf("public key RSA is [%d]\n", len);
char *out = new char[len + 1];
memset(out, 0, len + 1);
int result = RSA_public_encrypt(clearText_length, (unsigned char *)clearText, (unsigned char *)out, rsa, RSA_PKCS1_PADDING);
if (-1 == result) {
printf("RSA_public_encrypt is failed\n");
BIO_free(bio_public);
RSA_free(rsa);
delete []out;
return cipherText;
} else {
printf("RSA_public_encrypt is successful\n");
cipherText = string(out, result);
BIO_free(bio_public);
RSA_free(rsa);
delete []out;
return cipherText;
}
}
/*
*@author xzj
*@copyright
*@description 公钥解密
*@param cipherText_length : 密文数据长度
*@param cipherText : 密文数据
*@param public_key_path_and_file_name : 公钥路径+文件名
*@return string cipherText 明文数据
*/
string HashSignature::RSAPublicKeyDecypt(int cipherText_length, const char* cipherText, const char* public_key_path_and_file_name) {
// int RSA_public_decrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa,int padding);
string clearText = "";
RSA *rsa = NULL;
BIO* bio_public = NULL;
bio_public = BIO_new(BIO_s_file());
BIO_read_filename(bio_public, public_key_path_and_file_name); // 类似与fopen()
if (NULL == bio_public) {
printf("open_public_key bio file new error!\n");
return clearText;
}
// 此处有三种方法
// 1, 读取内存里生成的密钥对,再从内存生成rsa
// 2, 读取磁盘里生成的密钥对文本文件,在从内存生成rsa
// 3,直接从读取文件指针生成rsa
rsa = PEM_read_bio_RSAPublicKey(bio_public, &rsa, NULL, NULL); // 类似与read()
if (NULL == rsa) {
printf("open_public_key failed to PEM_read_bio_RSAPublicKey!\n");
BIO_free(bio_public);
RSA_free(rsa);
return clearText;
}
int len = RSA_size(rsa);
printf("public key RSA is [%d]\n", len);
char *out = new char[len + 1];
memset(out, 0, len + 1);
int result = RSA_public_decrypt(cipherText_length, (unsigned char *)cipherText, (unsigned char *)out, rsa, RSA_PKCS1_PADDING);
if (-1 == result) {
printf("RSA_public_decrypt is failed\n");
BIO_free(bio_public);
RSA_free(rsa);
delete []out;
return clearText;
} else {
printf("RSA_public_decrypt is successful\n");
clearText = string(out, result);
BIO_free(bio_public);
RSA_free(rsa);
delete []out;
return clearText;
}
}
测试入口文件:main.cpp
#ifndef _HASH_SIGNATURE_H_
# include "HashSignature.h"
#endif
#define NAME_SIZE 34
struct persion
{
int age;
unsigned char name [NAME_SIZE];
};
int main() {
// test the function generateRSAKey
HashSignature mHashSignature;
/******************************* 测试生成公钥私自并写入到文件中 ********************************/
// test 1
// bool res = mHashSignature.generateRSAKey(PUBLIC_KEY_FILE, PRIVATE_KEY_FILE,
// (const unsigned char *)RSA_PRIKEY_PSW,
// strlen(RSA_PRIKEY_PSW));
// if (res == false) {
// printf("test 1 RSA create key is failed\n");
// } else {
// printf("test 1 RSA create key is successful\n");
// }
// test 2
// bool res = mHashSignature.generateRSAKey(PUBLIC_KEY_FILE, PRIVATE_KEY_FILE);
// if (res == false) {
// printf("test 2 RSA create key is failed\n");
// } else {
// printf("test 2 RSA create key is successful\n");
// }
/******************************* 测试生成公钥私自并写入到文件中 ********************************/
/********************************** 测试对数据进行验签 ***********************************/
// printf("start1........\n");
// // 生成hash值
// std::string data = "hello world xzj!!!!!";
// std::string dataHash = "";
// dataHash = mHashSignature.create_hash_by_SHA256(data);
// printf("数据生成的hash值为[%s]\n", dataHash.c_str());
// //摘要私钥加密生成签名
// string Signature = mHashSignature.create_signature(dataHash.length(), dataHash, PRIVATE_KEY_FILE);
// printf("摘要生成的签名为[%s]\n", Signature.c_str());
// //签名公钥解密生成摘要
// string hash = mHashSignature.get_hash_from_signature(Signature.length(), Signature, PUBLIC_KEY_FILE);
// printf("摘要解签的hash值为[%s]\n", hash.c_str());
// int compareResult = dataHash.compare(hash);
// if (0 == compareResult) {
// printf("签名验证成功\n");
// } else {
// printf("签名验证失败\n");
// }
/********************************** 测试对数据进行验签 ***********************************/
/********************************** 测试对文件数据进行验签1 ***********************************/
// printf("start2........\n");
// // 从文件读取数据
// string data = mHashSignature.readStringData_From_File(DATA_FILE);
// //生成hash值
// std::string dataHash = "";
// dataHash = mHashSignature.create_hash_by_SHA256(data);
// printf("数据生成的hash值为[%s]\n", dataHash.c_str());
// //摘要私钥加密生成签名
// string Signature = mHashSignature.create_signature(dataHash.length(), dataHash, PRIVATE_KEY_FILE);
// printf("摘要生成的签名为[%s]\n", Signature.c_str());
// // 把签名写入到文件里
// if (true == mHashSignature.writeStringData_Into_File(SIGNATURE_FILE, Signature.c_str())) {
// printf("签名写入到文件 successful!!\n");
// }
// // 从文件读取签名
// string readSignature = mHashSignature.readStringData_From_File(SIGNATURE_FILE);
// //签名公钥解密生成摘要
// string hash = mHashSignature.get_hash_from_signature(readSignature.length(), readSignature, PUBLIC_KEY_FILE);
// printf("摘要解签的hash值为[%s]\n", hash.c_str());
// int compareResult = dataHash.compare(hash);
// if (0 == compareResult) {
// printf("签名验证成功\n");
// } else {
// printf("签名验证失败\n");
// }
/********************************** 测试对文件数据进行验签1 ***********************************/
/********************************** 测试对文件数据进行验签2 ***********************************/
// printf("start3........\n");
// mHashSignature.verify_signature(DATA_FILE, PUBLIC_KEY_FILE, SIGNATURE_FILE);
/********************************** 测试对文件数据进行验签2 ***********************************/
/********************************** 私钥加密公钥解密 ***********************************/
// printf("start4.1........\n");
// persion m_persion = {28,"xzj8023tp"};
// char * clearText1 = new char[sizeof(persion)];
// string cipherText = "";
// memcpy(clearText1, &m_persion, sizeof(persion));
// cipherText = mHashSignature.RSAPrivateKeyEncypt(sizeof(persion), clearText1, PRIVATE_KEY_FILE);
// string clearText2 = "";
// clearText2 = mHashSignature.RSAPublicKeyDecypt(cipherText.length(), cipherText.c_str(), PUBLIC_KEY_FILE);
// persion showData;
// memcpy(&showData, (clearText2.c_str()), sizeof(persion));
// printf("my name is [%s] and I am [%d] years old\n", showData.name, showData.age);
// printf("私钥加密公钥解密successful\n");
// printf("start4.2........\n");
// string clearText1 = "xzjjglajgojagojhaogjagjhajhgdahgkahgoihagoihrwqai";
// string cipherText = "";
// printf("A\n");
// cipherText = mHashSignature.RSAPrivateKeyEncypt(clearText1.length(), clearText1.c_str(), PRIVATE_KEY_FILE);
// string clearText2 = "";
// printf("B\n");
// clearText2 = mHashSignature.RSAPublicKeyDecypt(cipherText.length(), cipherText.c_str(), PUBLIC_KEY_FILE);
// printf("my name is [%s]\n", clearText2.c_str());
/********************************** 私钥加密公钥解密 ***********************************/
/********************************** RSA公钥加密私钥解密 ***********************************/
printf("start5.1........\n");
persion m_persion = {28,"xzj8023tp"};
char * clearText1 = new char[sizeof(persion)];
string cipherText = "";
memcpy(clearText1, &m_persion, sizeof(persion));
cipherText = mHashSignature.RSAPublicKeyEncypt(sizeof(persion), clearText1, PUBLIC_KEY_FILE);
string clearText2 = "";
clearText2 = mHashSignature.RSAPrivateKeyDecypt(cipherText.length(), cipherText.c_str(), PRIVATE_KEY_FILE);
persion showData;
memcpy(&showData, (clearText2.c_str()), sizeof(persion));
printf("my name is [%s] and I am [%d] years old\n", showData.name, showData.age);
printf("RSA公钥加密私钥解密successful\n");
/********************************** RSA公钥加密私钥解密 ***********************************/
return 0;
}
Linux中的编译执行:
g++ HashSignature.cpp main.cpp -o main.run -lssl -lcrypto
运行截图:
test 1:
xzj@xzj-virtual-machine:~/Code/C++Code/RSA$ g++ HashSignature.cpp main.cpp -o main.run -lssl -lcrypto
xzj@xzj-virtual-machine:~/Code/C++Code/RSA$ ./main.run
Create public key successful!
Create private key successful!
test 1 RSA create key is successful
test2
xzj@xzj-virtual-machine:~/Code/C++Code/RSA$ g++ HashSignature.cpp main.cpp -o main.run -lssl -lcrypto
xzj@xzj-virtual-machine:~/Code/C++Code/RSA$ ./main.run
test 2 RSA create key is successful
start1
xzj@xzj-virtual-machine:~/Code/C++Code/RSA$ g++ HashSignature.cpp main.cpp -o main.run -lssl -lcrypto
xzj@xzj-virtual-machine:~/Code/C++Code/RSA$ ./main.run
start1........
数据生成的hash值为[81bbd261553e8aa21b1e36c693bf352c9a43b9453bba5e5059cd47093681ddac]
private key RSA is [128]
RSA_private_encrypt is successful
摘要生成的签名为[��w4��=��߈�#~��p�[m�]
public key RSA is [128]
RSA_public_decrypt is successful
摘要解签的hash值为[81bbd261553e8aa21b1e36c693bf352c9a43b9453bba5e5059cd47093681ddac]
签名验证成功
start2
xzj@xzj-virtual-machine:~/Code/C++Code/RSA$ g++ HashSignature.cpp main.cpp -o main.run -lssl -lcrypto
xzj@xzj-virtual-machine:~/Code/C++Code/RSA$ ./main.run
start2........
数据生成的hash值为[c691fdbd30e610ea7559db3689f4b28554a27ba30f0ab3db1092c294e0f32e41]
private key RSA is [128]
RSA_private_encrypt is successful
摘要生成的签名为[
3ze��:�NRЏ�Cv��}.���ot�#�m��T�9be!D��r"֠i����R��HAh�;�#�P
] ���y Ǟ��͔��t����#)W�
签名写入到文件 successful!!
public key RSA is [128]
RSA_public_decrypt is successful
摘要解签的hash值为[c691fdbd30e610ea7559db3689f4b28554a27ba30f0ab3db1092c294e0f32e41]
签名验证成功
start3
xzj@xzj-virtual-machine:~/Code/C++Code/RSA$ g++ HashSignature.cpp main.cpp -o main.run -lssl -lcrypto
xzj@xzj-virtual-machine:~/Code/C++Code/RSA$ ./main.run
start3........
数据生成的hash值为[c691fdbd30e610ea7559db3689f4b28554a27ba30f0ab3db1092c294e0f32e41]
public key RSA is [128]
RSA_public_decrypt is successful
摘要解签的hash值为[c691fdbd30e610ea7559db3689f4b28554a27ba30f0ab3db1092c294e0f32e41]
签名验证成功
start4.1
xzj@xzj-virtual-machine:~/Code/C++Code/RSA$ g++ HashSignature.cpp main.cpp -o main.run -lssl -lcrypto
xzj@xzj-virtual-machine:~/Code/C++Code/RSA$ ./main.run
start4.1........
private key RSA is [128]
RSA_private_encrypt is successful
public key RSA is [128]
RSA_public_decrypt is successful
my name is [xzj8023tp] and I am [28] years old
私钥加密公钥解密successful
start4.2
xzj@xzj-virtual-machine:~/Code/C++Code/RSA$ g++ HashSignature.cpp main.cpp -o main.run -lssl -lcrypto
xzj@xzj-virtual-machine:~/Code/C++Code/RSA$ ./main.run
start4.2........
A
private key RSA is [128]
RSA_private_encrypt is successful
B
public key RSA is [128]
RSA_public_decrypt is successful
my name is [xzjjglajgojagojhaogjagjhajhgdahgkahgoihagoihrwqai]
start5.1
xzj@xzj-virtual-machine:~/Code/C++Code/RSA$ g++ HashSignature.cpp main.cpp -o main.run -lssl -lcrypto
xzj@xzj-virtual-machine:~/Code/C++Code/RSA$ ./main.run
start5.1........
public key RSA is [128]
RSA_public_encrypt is successful
private key RSA is [128]
RSA_private_decrypt is successful
my name is [xzj8023tp] and I am [28] years old
RSA公钥加密私钥解密successful
参考代码:https://blog.csdn.net/xunmeng2002/article/details/82385004
#include <openssl/rsa.h>
#include <string.h>
#include <openssl/pem.h>
#include <openssl/rand.h>
#include <iostream>
#define PUBLIC_KEY_FILE "rsapub.key"
#define PRIVATE_KEY_FILE "rsapriv.key"
#define RSA_KEY_LENGTH 1024
#define RSA_PRIKEY_PSW "123"
int rsa_test(const unsigned char* data, size_t& len, char* encrypt_data, size_t& encrypt_data_len, char* decrypt_data, size_t& decrypt_data_len)
{
generate_key_files(PUBLIC_KEY_FILE, PRIVATE_KEY_FILE,(const unsigned char *)RSA_PRIKEY_PSW, strlen(RSA_PRIKEY_PSW));
EVP_PKEY *pub_key = open_public_key(PUBLIC_KEY_FILE);
EVP_PKEY *pri_key = open_private_key(PRIVATE_KEY_FILE, (const unsigned char *)RSA_PRIKEY_PSW);
int ret = rsa_key_encrypt(pub_key, data, len, (unsigned char *)encrypt_data, encrypt_data_len);
if (ret != 0)
{
printf("rsa encrypt failed!\n");
return ret;
}
else
{
printf("rsa encrypt success!\n");
}
ret = rsa_key_decrypt(pri_key, (const unsigned char *)encrypt_data, encrypt_data_len, (unsigned char *)decrypt_data, decrypt_data_len);
if (ret != 0)
{
printf("rsa decrypt failed!\n");
}
else
{
printf("rsa decrypt success!\n");
printf("encrypt data:%s\n", encrypt_data);
printf("decrypt data:%s\n", decrypt_data);
}
return ret;
}
int generate_key_files(const char* pub_key_file, const char* priv_key_file, const unsigned char* passwd, int passwd_len)
{
RSA *rsa = NULL;
rsa = RSA_generate_key(RSA_KEY_LENGTH, RSA_F4, NULL, NULL);
if (rsa == NULL)
{
printf("RSA_generate_key error!\n");
return -1;
}
//生成公钥文件
BIO* bio_pub = BIO_new(BIO_s_file());
if (NULL == bio_pub)
{
printf("generate_key bio file new error!\n");
return -1;
}
if (BIO_write_filename(bio_pub, (void *)pub_key_file) <= 0)
{
printf("BIO_write_filename error!\n");
return -1;
}
if (PEM_write_bio_RSAPublicKey(bio_pub, rsa) != 1)
{
printf("PEM_write_bio_RSAPublicKey error!\n");
return -1;
}
printf("Create public key ok!\n");
BIO_free_all(bio_pub);
// 生成私钥文件
BIO* bio_priv = BIO_new_file(priv_key_file, "w+");
if (NULL == bio_priv)
{
printf("generate_key bio file new error2!\n");
return -1;
}
if (PEM_write_bio_RSAPrivateKey(bio_priv, rsa, EVP_des_ede3_ofb(), (unsigned char *)passwd, passwd_len, NULL, NULL) != 1)
{
printf("PEM_write_bio_RSAPublicKey error!\n");
return -1;
}
printf("Create private key ok!\n");
BIO_free_all(bio_priv);
RSA_free(rsa);
return 0;
}
EVP_PKEY* open_public_key(const char* pub_key_file)
{
EVP_PKEY* key = NULL;
RSA *rsa = NULL;
OpenSSL_add_all_algorithms();
BIO *bio_pub = BIO_new(BIO_s_file());
BIO_read_filename(bio_pub, pub_key_file);
if (NULL == bio_pub)
{
printf("open_public_key bio file new error!\n");
return NULL;
}
rsa = PEM_read_bio_RSAPublicKey(bio_pub, NULL, NULL, NULL);
if (rsa == NULL)
{
printf("open_public_key failed to PEM_read_bio_RSAPublicKey!\n");
BIO_free(bio_pub);
RSA_free(rsa);
return NULL;
}
printf("open_public_key success to PEM_read_bio_RSAPublicKey!\n");
key = EVP_PKEY_new();
if (NULL == key)
{
printf("open_public_key EVP_PKEY_new failed\n");
RSA_free(rsa);
return NULL;
}
EVP_PKEY_assign_RSA(key, rsa);
return key;
}
EVP_PKEY* open_private_key(const char* priv_key_file, const unsigned char *passwd)
{
EVP_PKEY* key = NULL;
RSA *rsa = RSA_new();
OpenSSL_add_all_algorithms(); /* 载入Openssl所支持的算法 */
BIO* bio_priv = NULL;
bio_priv = BIO_new_file(priv_key_file, "rb");
if (NULL == bio_priv)
{
printf("open_private_key bio file new error!\n");
return NULL;
}
rsa = PEM_read_bio_RSAPrivateKey(bio_priv, &rsa, NULL, (void *)passwd);
if (rsa == NULL)
{
printf("open_private_key failed to PEM_read_bio_RSAPrivateKey!\n");
BIO_free(bio_priv);
RSA_free(rsa);
return NULL;
}
printf("open_private_key success to PEM_read_bio_RSAPrivateKey!\n");
key = EVP_PKEY_new();
if (NULL == key)
{
printf("open_private_key EVP_PKEY_new failed\n");
RSA_free(rsa);
return NULL;
}
EVP_PKEY_assign_RSA(key, rsa);
return key;
}
int rsa_key_encrypt(EVP_PKEY *key, const unsigned char* data, size_t len, unsigned char *encrypt_data, size_t &encrypt_data_len)
{
EVP_PKEY_CTX *ctx = NULL;
OpenSSL_add_all_ciphers();
ctx = EVP_PKEY_CTX_new(key, NULL);
if (NULL == ctx)
{
printf("ras_pubkey_encryptfailed to open ctx.\n");
EVP_PKEY_free(key);
return -1;
}
if (EVP_PKEY_encrypt_init(ctx) <= 0)
{
printf("ras_pubkey_encryptfailed to EVP_PKEY_encrypt_init.\n");
EVP_PKEY_free(key);
return -1;
}
if (EVP_PKEY_encrypt(ctx, encrypt_data, &encrypt_data_len, data, len) <= 0)
{
printf("ras_pubkey_encryptfailed to EVP_PKEY_encrypt.\n");
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(key);
return -1;
}
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(key);
return 0;
}
int rsa_key_decrypt(EVP_PKEY *key, const unsigned char *encrypt_data, size_t encrypt_data_len, unsigned char *decrypt_data, size_t &decrypt_data_len)
{
EVP_PKEY_CTX *ctx = NULL;
OpenSSL_add_all_ciphers();
ctx = EVP_PKEY_CTX_new(key, NULL);
if (NULL == ctx)
{
printf("ras_prikey_decryptfailed to open ctx.\n");
EVP_PKEY_free(key);
return -1;
}
if (EVP_PKEY_decrypt_init(ctx) <= 0)
{
printf("ras_prikey_decryptfailed to EVP_PKEY_decrypt_init.\n");
EVP_PKEY_free(key);
return -1;
}
if (EVP_PKEY_decrypt(ctx, decrypt_data, &decrypt_data_len, encrypt_data, encrypt_data_len) <= 0)
{
printf("ras_prikey_decryptfailed to EVP_PKEY_decrypt.\n");
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(key);
return -1;
}
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(key);
return 0;
}
openssl命令版本的加签验签
数据文件:myfile.txt
私钥:myprivate.pem
公钥:mypublic.pem
签名文件:sha256.sign
公钥和私钥都可以用cat查看
以"-----BEGIN..."开头, "-----END..."结尾,内容经过BASE64编码
查看PEM格式证书的信息:$openssl x509 -in certificate.pem -text -noout
1、生成私钥myprivate.pem
openssl genrsa -out myprivate.pem 4096
2、通过私钥生成公钥mypublic.pem
openssl rsa -in myprivate.pem -pubout -out mypublic.pem
3、生成签名
openssl dgst -sha256 -sign myprivate.pem -out sha256.sign myfile.txt
sha256.sign 就是文件 myfile.txt 的签名文件
4、使用公钥来验证签名:
openssl dgst -sha256 -verify mypublic.pem -signature sha256.sign myfile.txt
理论上也可以用私钥来验证签名,只是实际上不会使用,也许发送方可能会通过私钥验证来证明计算的正确:
openssl dgst -sha256 -prverify myprivate.pem -signature sha256.sign myfile.txt