基于openssl SHA256WithRSA签名和验签过程

1、我是小蜜蜂搬运每一天。公钥加密、私钥解密、私钥签名、公钥验签。加密是为了保证数据的私密性,签名是为了保证数据的完整性。下面是签名验签过程。

sha256.h

#ifndef __SHA256_H__
#define __SHA256_H__

#include <openssl/rsa.h>

//生成公钥和私钥
void GenerateKeyExx();
//从文件中读取私钥
RSA* GetPrivateKeyExx(const char* szPath);
//从文件中读取公钥
RSA* GetPublicKeyExx(const char* szPath);
//签名
bool RSASign( RSA* rsa, const unsigned char* Msg, size_t MsgLen,
    unsigned char** EncMsg, size_t* MsgLenEnc);
//验签
bool RSAVerifySignature( RSA* rsa, unsigned char* MsgHash, size_t MsgHashLen,
    const char* Msg, size_t MsgLen, bool* Authentic);
//base64编码
void Base64Encode( const unsigned char* buffer, size_t length, char** base64Text);
//base64解码
void Base64Decode(const char* b64message, unsigned char** buffer, size_t* length);
//计算base64解码后数据长度
size_t calcDecodeLength(const char* b64input);
char* signMessage(std::string privateKey, std::string plainText);
bool verifySignature(std::string publicKey, std::string plainText, char* signatureBase64);
int test();

#endif

sha256.cpp

#include <iostream>
#include <assert.h>
#include <string.h>
#include <cstring>
#include "sha256.h"
#include <openssl/objects.h>
#include <openssl/aes.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <unistd.h>

std::string privateKey = "-----BEGIN RSA PRIVATE KEY-----\n"\
"MIIEogIBAAKCAQEAjdKXiqYHzi++YmEb9X6qvqFWLCz1VEfxom2JhinPSJxxcuZW\n"\
"Bejk2I5yCL5pDnUaG2xpQlMTkV/7S7JfGGvYJumKO4R5zg0QSA7qdxiEhcwf/ekf\n"\
"SvzM2EDnLHDCKAQwEWsnJy78uxZTLzu/65VZ7EgEcWUTvCs/GZJLI9s6XmKY2SMm\n"\
"v9+vfqBqkJNXE0ZB6OfSbyeE325P94iMn+B/yJ4vZwXvXGFqNDJyqG+ww7f77HYu\n"\
"bQPJjLQPedy2qTcgmSAwkUEJVBjYA6mPf/BeZlL1YJHHM7CIBnb3/bzED0n944wo\n"\
"io+4+rnMZdfhcCVpm74DZomlEf9KuJtq5u/JRQIDAQABAoIBAG2AzvWE4L346z02\n"\
"0cmptdhe5hRR2lLrAc1yWh83JQ9hi881vfHuMtRql+3cZ218SV4nRNarIo6612NJ\n"\
"JFfM3SaeZ9cwoIPSXmHk8nBmg9xzEbiRSVIzA09uPZB4t9EB+sNYQvDkPMuPn0b3\n"\
"EWaq+LWRnayYaLZ/hccOx+m1mcnJnIs27+EPnufrUKVniCguburQoU3VEXSFCzBk\n"\
"23rhSu20vUOikLuuU4gcvWfnfUoOwdhb2iBhjgMbsjTTmg3+GQuPtblCSTKjk11F\n"\
"YX2MJHEDFfwVzSurmbqAZC9rjr7PbflC8GMmPfa1LCb7IG5s9AIM4v9Fea0SyZP+\n"\
"/pM9mzkCgYEAyjLPU7ieqly9+mgeb2fmWh7pYgO49KuFIqqHnP+LaXXYK/TvCJ8X\n"\
"zJ3PxBgwVMOT94nXSDNjzNLzp0hl8OWWBH0tN0fiq1OEyySM3Mlji6o8KpGcU1k4\n"\
"jFkXMK1rVQcW8ckLmzMrQF3SphQi4UiEpLX1Zba4YQ4fNHK8NHHHaEMCgYEAs48m\n"\
"Oe4iEZcVDnag+Mp0Zjgu4mYJeeeGtVUZFCJOeyLDsQVmnt5mJIgGwrxg4o3qljut\n"\
"aAUXzf8aYZ0fURAsLcwnQg03THFKeIt94Rw/72n2UWT+AZTU3GQtuwf+osZHUfS3\n"\
"XTLaQE+A1JBC4XLJ99j/95sxt6xZy5YyfhfY09cCgYAbqyhDxJexqE823NiNViJn\n"\
"YqN9DhVZJb9qJvu3uCBTphSWr0WmYF7ZWR79LnIupzSwQuR6tM2LUbKVyYpplIEa\n"\
"zCZL0kJqP1uEkNPVwpkkm37wNEy3+xWJ3wcVWiW91OKG44P7EN1ySWRx5X+AZHQC\n"\
"NgQGjyJb5ZrPioPGiWtIEQKBgE/0B/N3o9ftTET6cccWbootDkNlaAbOH1+TGu2q\n"\
"MQQHgNfMLdvD7/uITmpb81AuHSz0Ocy9p9HkK90XV6CC8QkbhMeWlu8E60It6slY\n"\
"COgUaMfpjmkp2nagbPSBJNNaMtu9egCX6jMEs7ry2bUFpgUkrSWWB1df+UP8B1O6\n"\
"TqRVAoGAVQoCUPVm6C6h6V5dgPvsJMxJ8EjOCgwkXNucAHWcpBV3/LlxLiCGRuEL\n"\
"B+epYxqwKLpSQBhldasKmmKB0M6MFTwxXwxCmCi80+DBdP5A7GIK52ZGth63i22t\n"\
"FI8MeDIzA5HqAI24P7ltozoEYAB7GIdJQXq9oT/DRagTwQUzQ8E=\n"\
"-----END RSA PRIVATE KEY-----\n";

/*std::string privateKey ="-----BEGIN PRIVATE KEY-----\n"\
"MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCN0peKpgfOL75i\n"\
"YRv1fqq+oVYsLPVUR/GibYmGKc9InHFy5lYF6OTYjnIIvmkOdRobbGlCUxORX/tL\n"\
"sl8Ya9gm6Yo7hHnODRBIDup3GISFzB/96R9K/MzYQOcscMIoBDARaycnLvy7FlMv\n"\
"O7/rlVnsSARxZRO8Kz8Zkksj2zpeYpjZIya/369+oGqQk1cTRkHo59JvJ4Tfbk/3\n"\
"iIyf4H/Ini9nBe9cYWo0MnKob7DDt/vsdi5tA8mMtA953LapNyCZIDCRQQlUGNgD\n"\
"qY9/8F5mUvVgkcczsIgGdvf9vMQPSf3jjCiKj7j6ucxl1+FwJWmbvgNmiaUR/0q4\n"\
"m2rm78lFAgMBAAECggEAbYDO9YTgvfjrPTbRyam12F7mFFHaUusBzXJaHzclD2GL\n"\
"zzW98e4y1GqX7dxnbXxJXidE1qsijrrXY0kkV8zdJp5n1zCgg9JeYeTycGaD3HMR\n"\
"uJFJUjMDT249kHi30QH6w1hC8OQ8y4+fRvcRZqr4tZGdrJhotn+Fxw7H6bWZycmc\n"\
"izbv4Q+e5+tQpWeIKC5u6tChTdURdIULMGTbeuFK7bS9Q6KQu65TiBy9Z+d9Sg7B\n"\
"2FvaIGGOAxuyNNOaDf4ZC4+1uUJJMqOTXUVhfYwkcQMV/BXNK6uZuoBkL2uOvs9t\n"\
"+ULwYyY99rUsJvsgbmz0Agzi/0V5rRLJk/7+kz2bOQKBgQDKMs9TuJ6qXL36aB5v\n"\
"Z+ZaHuliA7j0q4Uiqoec/4tpddgr9O8InxfMnc/EGDBUw5P3iddIM2PM0vOnSGXw\n"\
"5ZYEfS03R+KrU4TLJIzcyWOLqjwqkZxTWTiMWRcwrWtVBxbxyQubMytAXdKmFCLh\n"\
"SISktfVltrhhDh80crw0ccdoQwKBgQCzjyY57iIRlxUOdqD4ynRmOC7iZgl554a1\n"\
"VRkUIk57IsOxBWae3mYkiAbCvGDijeqWO61oBRfN/xphnR9RECwtzCdCDTdMcUp4\n"\
"i33hHD/vafZRZP4BlNTcZC27B/6ixkdR9LddMtpAT4DUkELhcsn32P/3mzG3rFnL\n"\
"ljJ+F9jT1wKBgBurKEPEl7GoTzbc2I1WImdio30OFVklv2om+7e4IFOmFJavRaZg\n"\
"XtlZHv0uci6nNLBC5Hq0zYtRspXJimmUgRrMJkvSQmo/W4SQ09XCmSSbfvA0TLf7\n"\
"FYnfBxVaJb3U4objg/sQ3XJJZHHlf4BkdAI2BAaPIlvlms+Kg8aJa0gRAoGAT/QH\n"\
"83ej1+1MRPpxxxZvKi0OQ2VoBs4fX5Ma7aoxBAeA18wt28Pv+4hOalvzUC4dLPQ5\n"\
"zL2n0eQr3RdXoILxCRuEx5aW7wTrQi3qyVgI6BRox+mOaSnadqBs9IEk01oy2716\n"\
"AJfqMwSzuvLZtQWmBSStJZYHV1/5Q/wHU7pOpFUCgYBVCgJQ9WboLqHpXl2A++wk\n"\
"zEnwSM4KDCRc25wAdZykFXf8uXEuIIZG4QsH56ljGrAoulJAGGV1qwqaYoHQzowV\n"\
"PDFfDEKYKLzT4MF0/kDsYgrnZka2HreLba0Ujwx4MjMDkeoAjbg/uW2jOgRgAHsY\n"\
"h0lBer2hP8NFqBPBBTNDwQ==\n"\
"-----END PRIVATE KEY-----\n";
*/
std::string publicKey ="-----BEGIN PUBLIC KEY-----\n"\
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjdKXiqYHzi++YmEb9X6q\n"\
"vqFWLCz1VEfxom2JhinPSJxxcuZWBejk2I5yCL5pDnUaG2xpQlMTkV/7S7JfGGvY\n"\
"JumKO4R5zg0QSA7qdxiEhcwf/ekfSvzM2EDnLHDCKAQwEWsnJy78uxZTLzu/65VZ\n"\
"7EgEcWUTvCs/GZJLI9s6XmKY2SMmv9+vfqBqkJNXE0ZB6OfSbyeE325P94iMn+B/\n"\
"yJ4vZwXvXGFqNDJyqG+ww7f77HYubQPJjLQPedy2qTcgmSAwkUEJVBjYA6mPf/Be\n"\
"ZlL1YJHHM7CIBnb3/bzED0n944woio+4+rnMZdfhcCVpm74DZomlEf9KuJtq5u/J\n"\
"RQIDAQAB\n"\
"-----END PUBLIC KEY-----\n";

#define PUBLIC_KEY_FILE_EX		"publicEx.pem"		//公钥文件
#define PRIVATE_KEY_FILE_EX		"privateEx.pem"		//私钥文件

//***生成公钥和私钥文件***
void GenerateKeyExx()
{
	/* 生成公钥 */
	RSA* rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL);
	BIO *bp = BIO_new(BIO_s_file());
	BIO_write_filename(bp, (void*)PUBLIC_KEY_FILE_EX);
	PEM_write_bio_RSAPublicKey(bp, rsa);
	BIO_free_all(bp);
 
	/* 生成私钥 */
	bp = BIO_new(BIO_s_file());
	BIO_write_filename(bp, (void*)PRIVATE_KEY_FILE_EX);
	PEM_write_bio_RSAPrivateKey(bp, rsa, NULL, NULL, 0, NULL, NULL);
	CRYPTO_cleanup_all_ex_data();
	BIO_free_all(bp);
	RSA_free(rsa);
}

RSA* createPrivateRSA(std::string key) {
    RSA *rsa = NULL;
    const char* c_string = key.c_str();
    BIO * keybio = BIO_new_mem_buf((void*)c_string, -1);
    if (keybio==NULL) {
        return 0;
    }
    rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL);
    return rsa;
}

RSA* createPublicRSA(std::string key) {
    RSA *rsa = NULL;
    BIO *keybio;
    const char* c_string = key.c_str();
    keybio = BIO_new_mem_buf((void*)c_string, -1);
    if (keybio==NULL) {
        return 0;
    }
    rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa,NULL, NULL);
    return rsa;
}

RSA* GetPublicKeyExx(const char* szPath)
{
	RSA *pubkey = RSA_new();
 
	BIO *pubio;
 
	pubio = BIO_new_file(szPath, "rb");
	pubkey = PEM_read_bio_RSAPublicKey(pubio, &pubkey, NULL, NULL);
 
	BIO_free(pubio);
 
	return pubkey;
}
 
RSA* GetPrivateKeyExx(const char* szPath)
{
	RSA *prikey = RSA_new();
 
	BIO *priio;
 
	priio = BIO_new_file(szPath, "rb");
	prikey = PEM_read_bio_RSAPrivateKey(priio, &prikey, NULL, NULL);
 
	BIO_free(priio);
 
	return prikey;
}

bool RSASign( RSA* rsa,
              const unsigned char* Msg,
              size_t MsgLen,
              unsigned char** EncMsg,
              size_t* MsgLenEnc) {
    EVP_MD_CTX* m_RSASignCtx = EVP_MD_CTX_create();
    EVP_PKEY* priKey  = EVP_PKEY_new();
    EVP_PKEY_assign_RSA(priKey, rsa);
    if (EVP_DigestSignInit(m_RSASignCtx,NULL, EVP_sha256(), NULL,priKey)<=0) {
        return false;
    }
    if (EVP_DigestSignUpdate(m_RSASignCtx, Msg, MsgLen) <= 0) {
        return false;
    }
    if (EVP_DigestSignFinal(m_RSASignCtx, NULL, MsgLenEnc) <=0) {
        return false;
    }
    *EncMsg = (unsigned char*)malloc(*MsgLenEnc);
    if (EVP_DigestSignFinal(m_RSASignCtx, *EncMsg, MsgLenEnc) <= 0) {
        return false;
    }
    EVP_MD_CTX_destroy(m_RSASignCtx);
    EVP_PKEY_free(priKey);
    return true;
}

bool RSAVerifySignature( RSA* rsa,
                         unsigned char* MsgHash,
                         size_t MsgHashLen,
                         const char* Msg,
                         size_t MsgLen,
                         bool* Authentic) {
    *Authentic = false;
    EVP_PKEY* pubKey  = EVP_PKEY_new();
    EVP_PKEY_assign_RSA(pubKey, rsa);
    EVP_MD_CTX* m_RSAVerifyCtx = EVP_MD_CTX_create();

    if (EVP_DigestVerifyInit(m_RSAVerifyCtx,NULL, EVP_sha256(),NULL,pubKey)<=0) {
        return false;
    }
    if (EVP_DigestVerifyUpdate(m_RSAVerifyCtx, Msg, MsgLen) <= 0) {
        return false;
    }
    int AuthStatus = EVP_DigestVerifyFinal(m_RSAVerifyCtx, MsgHash, MsgHashLen);
    if (AuthStatus==1) {
        *Authentic = true;
        EVP_MD_CTX_destroy(m_RSAVerifyCtx);
        EVP_PKEY_free(pubKey);
        return true;
    } else if(AuthStatus==0){
        *Authentic = false;
        EVP_MD_CTX_destroy(m_RSAVerifyCtx);
        EVP_PKEY_free(pubKey);
        return true;
    } else{
        *Authentic = false;
        EVP_MD_CTX_destroy(m_RSAVerifyCtx);
        EVP_PKEY_free(pubKey);
        return false;
    }
}

void Base64Encode( const unsigned char* buffer,
                   size_t length,
                   char** base64Text) {
    BIO *bio, *b64;
    BUF_MEM *bufferPtr;

    b64 = BIO_new(BIO_f_base64());
    bio = BIO_new(BIO_s_mem());
    bio = BIO_push(b64, bio);

    BIO_write(bio, buffer, length);
    BIO_flush(bio);
    BIO_get_mem_ptr(bio, &bufferPtr);
    BIO_set_close(bio, BIO_CLOSE);

    *base64Text = (char *)calloc((*bufferPtr).length, 1);
    if(!(*base64Text))
        printf("calloc base64Text failed\n");
    memcpy(*base64Text, (*bufferPtr).data, (*bufferPtr).length);

	BIO_free_all(bio);
}

size_t calcDecodeLength(const char* b64input) {
    size_t len = strlen(b64input), padding = 0;

    if (b64input[len-1] == '=' && b64input[len-2] == '=') //last two chars are =
        padding = 2;
    else if (b64input[len-1] == '=') //last char is =
        padding = 1;
    return (len*3)/4 - padding;
}

void Base64Decode(const char* b64message, unsigned char** buffer, size_t* length) {
    BIO *bio, *b64;

    int decodeLen = calcDecodeLength(b64message);
    *buffer = (unsigned char*)malloc(decodeLen + 1);
    (*buffer)[decodeLen] = '\0';

    bio = BIO_new_mem_buf(b64message, -1);
    b64 = BIO_new(BIO_f_base64());
    bio = BIO_push(b64, bio);

    *length = BIO_read(bio, *buffer, strlen(b64message));
    BIO_free_all(bio);
}
unsigned char * strToHex(std::string plainText){
    unsigned char * hexArray;
    hexArray = (unsigned char*)malloc(plainText.length());
    for(int i = 0; i < plainText.size();i++){
        hexArray[i] = std::strtol(&plainText[i],NULL,64);
    }
    return hexArray;
}
char* signMessage(std::string privateKey, std::string plainText) {
//  RSA* privateRSA = createPrivateRSA(privateKey);
    RSA* privateRSA = GetPrivateKeyExx(privateKey.c_str());
    unsigned char* encMessage;
    char* base64Text;
    size_t encMessageLength;

    RSASign(privateRSA, (unsigned char*) plainText.data(), plainText.length(), &encMessage, &encMessageLength);
    Base64Encode(encMessage, encMessageLength, &base64Text);
    free(encMessage);
    return base64Text;
}

bool verifySignature(std::string publicKey, std::string plainText, char* signatureBase64) {
//    RSA* publicRSA = createPublicRSA(publicKey);
    RSA* publicRSA = GetPublicKeyExx(publicKey.c_str());
    unsigned char* encMessage;
    size_t encMessageLength;
    bool authentic;
    Base64Decode(signatureBase64, &encMessage, &encMessageLength);
    bool result = RSAVerifySignature(publicRSA, encMessage, encMessageLength, plainText.c_str(), plainText.length(), &authentic);
    free(encMessage);
    return result & authentic;
}

int test() {
	GenerateKeyExx();
	std::string plainText = "ET8d1voUkzNcqud7M8W0WQcd3l2Ih1ZtiMxStPeubKg=";
	std::string strData = "MIICXwIBAAKBgQDNrGwRjt6l6ABjFcsoMU8MM7GjC4akItMjpD9brnZayudxsns8/h0HDzw0XkpCmGUTPGN+NBGBkitpoIcJnWz0z6eM6K9P7rytUeM0cXC+zCrlIxUN";
	
	char* signature = signMessage(PRIVATE_KEY_FILE_EX, strData);
	bool authentic = verifySignature(PUBLIC_KEY_FILE_EX, strData, signature);
	if ( authentic ) {
	    std::cout << "Authentic" << std::endl;
	    std::cout << signature << std::endl;
	} else {
	    std::cout << "Not Authentic" << std::endl;
	}
	
	free(signature);

}

参考链接:
这个好像有点问题,但是我没找到😀。
https://blog.csdn.net/Best_ZYJ/article/details/101029719

https://stackoverflow.com/questions/59204804/incorrect-signature-with-rsa-and-sha256

验证网站:
http://www.metools.info/code/c82.html