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] = '';
    public_key[bio_public_length] = '';

    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 failedn");
        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 failedn");
        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] = '';
    public_key[bio_public_length] = '';

    // 把公钥和私钥存储到磁盘文件当中(这种方式存储的是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 failedn");
        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 failedn");
        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 failedn");
        BIO_free(bio_private);
        RSA_free(rsa);
        delete []out;
        return "";
    } else {
        printf("RSA_private_encrypt is successfuln");
        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 failedn");
        BIO_free(bio_public);
        RSA_free(rsa);
        delete []out;
        return "";
    } else {
        printf("RSA_public_decrypt is successfuln");
        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 failedn");
        BIO_free(bio_private);
        RSA_free(rsa);
        delete []out;
        return cipherText;
    } else {
        printf("RSA_private_encrypt is successfuln");
        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 failedn");
        BIO_free(bio_private);
        RSA_free(rsa);
        delete []out;
        return clearText;
    } else {
        printf("RSA_private_decrypt is successfuln");
        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 failedn");
        BIO_free(bio_public);
        RSA_free(rsa);
        delete []out;
        return cipherText;
    } else {
        printf("RSA_public_encrypt is successfuln");
        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 failedn");
        BIO_free(bio_public);
        RSA_free(rsa);
        delete []out;
        return clearText;
    } else {
        printf("RSA_public_decrypt is successfuln");
        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 failedn");
    // } else {
    //     printf("test 1 RSA create key is successfuln");
    // }
    // test 2
    // bool res = mHashSignature.generateRSAKey(PUBLIC_KEY_FILE, PRIVATE_KEY_FILE);
    // if (res == false) {
    //     printf("test 2 RSA create key is failedn");
    // } else {
    //     printf("test 2 RSA create key is successfuln");
    // }
/******************************* 测试生成公钥私自并写入到文件中 ********************************/

/********************************** 测试对数据进行验签 ***********************************/
    // 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 oldn", showData.name, showData.age);
    // printf("私钥加密公钥解密successfuln");

    // printf("start4.2........n");
    // string clearText1 = "xzjjglajgojagojhaogjagjhajhgdahgkahgoihagoihrwqai";
    // string cipherText = "";
    // printf("An");
    // cipherText = mHashSignature.RSAPrivateKeyEncypt(clearText1.length(), clearText1.c_str(), PRIVATE_KEY_FILE);
    // string clearText2 = "";
    // printf("Bn");
    // 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 oldn", showData.name, showData.age);
    printf("RSA公钥加密私钥解密successfuln");

/********************************** 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:%sn", encrypt_data);
        printf("decrypt data:%sn", 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 failedn");
        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 failedn");
        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

RSA私钥公钥加密解密与签名、SHA256相关代码

2、通过私钥生成公钥mypublic.pem

openssl rsa -in myprivate.pem -pubout -out mypublic.pem

RSA私钥公钥加密解密与签名、SHA256相关代码

3、生成签名
openssl dgst -sha256 -sign myprivate.pem -out sha256.sign myfile.txt

sha256.sign 就是文件 myfile.txt 的签名文件

RSA私钥公钥加密解密与签名、SHA256相关代码

4、使用公钥来验证签名:

openssl dgst -sha256 -verify mypublic.pem -signature sha256.sign myfile.txt

RSA私钥公钥加密解密与签名、SHA256相关代码

理论上也可以用私钥来验证签名,只是实际上不会使用,也许发送方可能会通过私钥验证来证明计算的正确:

openssl dgst -sha256 -prverify myprivate.pem -signature sha256.sign myfile.txt

原文链接: https://www.cnblogs.com/xzj8023tp/p/12988616.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    RSA私钥公钥加密解密与签名、SHA256相关代码

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/351603

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午6:58
下一篇 2023年3月2日 上午6:58

相关推荐