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

posted @ 2020-05-29 17:22  独孤剑—宇枫  阅读(3478)  评论(0编辑  收藏  举报