C++ SHA256WithRSA 签名算法

网上大部分 SHA256WithRSA 的示例 C++源码实际是 Sha256 后 RSA,与标准的 SHA256WithRSA 签名结果不符,只好自已写了一个,后来者拿走不谢少入坑。

///<summary>
///SignWithRSA 签名,可用于 SHA256WithRSA,MD5withRSA,XXXwithRSA ...
///<![CDATA[
///基于 openssl 库,需要以下头文件及库文件:
///#include <openssl/rsa.h>
///#include <openssl/pem.h>
///#include <openssl/err.h>
///#include <openssl/sha.h>
///#include <openssl/evp.h>
///#pragma comment(lib, "libssl.lib")
///#pragma comment(lib, "libcrypto.lib")
///]]>
///</summary>
///<param name="sData">待签名字符串</param>
///<param name="signtype">签名类型,SHA256WithRSA 时为 EVP_sha256(), MD5withRSA 时为 EVP_md5() ...,具体查看 openssl 头文件定义</param>
///<param name="rsa">RSA 证书,用 PEM_read_RSAPrivateKey(从文件)/PEM_read_bio_RSAPrivateKey(从内存)等函数加载,用 RSA_free(rsa) 释放</param>
///<returns>签名结果 (base64 编码的字符串)</returns>
string SignWithRSA(const char* sData, const EVP_MD* signtype, RSA* rsa)
{
    string sResult;

    EVP_PKEY*    pEvpPkey    = ::EVP_PKEY_new();
    EVP_MD_CTX* pEvpMdCtx    = ::EVP_MD_CTX_new();

    if (::EVP_PKEY_assign_RSA(pEvpPkey, rsa) == 1)
    {
        ::EVP_SignInit(pEvpMdCtx, signtype);
        ::EVP_SignUpdate(pEvpMdCtx, sData, ::strlen(sData));

        unsigned int nSignLen = (unsigned int)::EVP_PKEY_size(pEvpPkey);

        string sSign(nSignLen, 0);

        if (::EVP_SignFinal(pEvpMdCtx, (unsigned char*)sSign.c_str(), &nSignLen, pEvpPkey) == 1)
        {
            sResult.resize(nSignLen * 2);
            int nOutLen = ::EVP_EncodeBlock((unsigned char*)sResult.c_str(), (unsigned char*)sSign.c_str(), nSignLen);
            sResult.resize(nOutLen);
        }
    }

    ::EVP_MD_CTX_free(pEvpMdCtx);
    ::EVP_PKEY_free(pEvpPkey);

    return sResult;
}

版权声明:本文为bigwasp原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。