NTE_BAD_SIGNATURE在使用Win32 API验证rsa时发生。

huangapple go评论103阅读模式
英文:

NTE_BAD_SIGNATURE while verifying rsa using Win32 API

问题

C++ 代码部分不需要翻译。以下是您提供的信息的中文翻译:

我尝试了一切来让它工作,所以我决定做一个完整的示例。我希望有人能帮助我。

要签名的消息:Hello World

签名示例链接:
https://gchq.github.io/CyberChef/#recipe=RSA_Sign('-----BEGIN%20RSA%20PRIVATE%20KEY-----%5CnMIICWwIBAAKBgQDCLDny1MwbGVFrjtNXH%2BHFxZ/4C5Gz0q2b5exrJLHums5YDSFl%5Cn6c55QLYNZ4MOlVrahVsAOO0ENkqA5QdswTi%2B53nP7zJsxmLnpN5J8QEQJgTlkw%2Bk%5CnIa8%2Bc8j0FWJCRFcZ4vlxcqIymJc/tpBuHfVIXpQpGuPpUTCtyfRmBNuGbQIDAQAB%5CnAoGABH78qoRF45y%2B92Qbvak105wDW7181rKapYD56/MyEYnRHFXVf6QdzU3zyTSr%5Cn4rMPov6ygDtRNadCK2DiPqDsvOiQU%2By7ZSt%2Bt0hdUv8nkQOzR167dM8dLAoVMVtm%5CnKgUYO1MUnERvh%2BpmPKOmYozBAZbJJshOLbmqfGoJH1wUzCECQQDkC1SDsmLbT9uA%5Cn8MR6u4sn%2Bkghli5oxP3dnj/1WRAATt3SrQNGUyJsLCCDc70EOPwx/nIY4aDog/3K%5Cnixut8zVdAkEA2fnp0rCOXXikNV69z5Y2lj4OYpLtJiaJQK6NOYF997zso2oln/xX%5Cnddxle0%2Ba5KufdkP4DGP0QSnZKA%2B6qIf0UQJAf9hOQCrQuwzRDT9tlzTu9bGdoJ62%5CnU%2BwkOotOZfjRPKr6NvLhxBo1URmH/Mn07JoZ4Nk6E/LiJ5hfvp4wHVwczQJAIDxR%5CnVBNAOpqIzkvAjl6MnBN5VSKdZ7LzQVmPER4RXv3VkSU1gz9yP7/kUiQnqAGph3ft%5CnywdNLAXgU4hf9mSEwQJAbLV0c7GWXPCSk3k0gwOOZCjHKaIxDIBjZudv5cvO9sPQx%5CnsqE17eyl5%2BufQq1xOQZL4HL%2BnUjlOcgT/pIdI9430A%3D%3D%5Cn-----END%20RSA%20PRIVATE%20KEY-----','','MD5')To_Hex('0x%20with%20comma',0)&input=SGVsbG8gV29ybGQ

验证示例链接:https://gchq.github.io/CyberChef/#recipe=From_Hex('Auto')RSA_Verify('-----BEGIN%20PUBLIC%20KEY-----%5CnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCLDny1MwbGVFrjtNXH%2BHFxZ/4%5CnC5Gz0q2b5exrJLHums5YDSFl6c55QLYNZ4MOlVrahVsAOO0ENkqA5QdswTi%2B53nP%5Cn7zJsxmLnpN5J8QEQJgTlkw%2BkIa8%2Bc8j0FWJCRFcZ4vlxcqIymJc/tpBuHfVIXpQp%5CnGuPpUTCtyfRmBNuGbQIDAQAB%5Cn-----END%20PUBLIC%20KEY-----','Hello%20World','MD5')&input=YjU5ODE1MzYwNjUyZWU3MWE1OTlhNTljZDQzM2Q4MmMyMzFhY2UzNzdjZWRkZDc3YzBkNTBhMmJkYWZhNDJmMjM0OTVkODVhNDg4Y2RiZmUwNDczNjNkOTI3NGE0MWM0MzgwZTgyNzJjMTEzNTExNDZkYmC8NDE1YTY1Yzc1MDM5ZmEwOTkwNzEzN2U0ZGRkNzFjMTFjZjYyZDYwOWQzNDAxM2E5ZmU1NzM1NDE1ZDhlMDE5Yjk0YTg4Y2RiZmUwNDczNzA5MTkxMGIzNjAxZjQzNDM1NmU3OWUxZDc1MTM3NGY4ZWRmZmRmNzFjMTFmYzllMzQyNGZiZTZmNDliNmViN2M3OGY3NjA0ZWVmYWE1OWUwYTZjYTg

公钥和私钥仅为示例目的生成

执行该代码后,我得到了NTE_BAD_SIGNATURE错误。

我使用了来自https://stackoverflow.com/questions/1231178/load-an-pem-encoded-x-509-certificate-into-windows-cryptoapi/3803333#3803333 的PEM导入。

我真诚地希望有人能帮助我解决这个问题。

英文:

I tried everything to make it working, so i decided to do full example. I hope someone would help me.

Message to sign: Hello World

Signing example:
https://gchq.github.io/CyberChef/#recipe=RSA_Sign('-----BEGIN%20RSA%20PRIVATE%20KEY-----%5CnMIICWwIBAAKBgQDCLDny1MwbGVFrjtNXH%2BHFxZ/4C5Gz0q2b5exrJLHums5YDSFl%5Cn6c55QLYNZ4MOlVrahVsAOO0ENkqA5QdswTi%2B53nP7zJsxmLnpN5J8QEQJgTlkw%2Bk%5CnIa8%2Bc8j0FWJCRFcZ4vlxcqIymJc/tpBuHfVIXpQpGuPpUTCtyfRmBNuGbQIDAQAB%5CnAoGABH78qoRF45y%2B92Qbvak105wDW7181rKapYD56/MyEYnRHFXVf6QdzU3zyTSr%5Cn4rMPov6ygDtRNadCK2DiPqDsvOiQU%2By7ZSt%2Bt0hdUv8nkQOzR167dM8dLAoVMVtm%5CnKgUYO1MUnERvh%2BpmPKOmYozBAZbJJshOLbmqfGoJH1wUzCECQQDkC1SDsmLbT9uA%5Cn8MR6u4sn%2Bkghli5oxP3dnj/1WRAATt3SrQNGUyJsLCCDc70EOPwx/nIY4aDog/3K%5Cnixut8zVdAkEA2fnp0rCOXXikNV69z5Y2lj4OYpLtJiaJQK6NOYF997zso2oln/xX%5Cnddxle0%2Ba5KufdkP4DGP0QSnZKA%2B6qIf0UQJAf9hOQCrQuwzRDT9tlzTu9bGdoJ62%5CnU%2BwkOotOZfjRPKr6NvLhxBo1URmH/Mn07JoZ4Nk6E/LiJ5hfvp4wHVwczQJAIDxR%5CnVBNAOpqIzkvAjl6MnBN5VSKdZ7LzQVmPER4RXv3VkSU1gz9yP7/kUiQnqAGph3ft%5CnywdNLAXgU4hf9mSEwQJAbLV0c7GWXPCSk3k0gwOZCjHKaIxDIBjZudv5cvO9sPQx%5CnsqE17eyl5%2BufQq1xOQZL4HL%2BnUjlOcgT/pIdI9430A%3D%3D%5Cn-----END%20RSA%20PRIVATE%20KEY-----','','MD5')To_Hex('0x%20with%20comma',0)&input=SGVsbG8gV29ybGQ

Verification example: https://gchq.github.io/CyberChef/#recipe=From_Hex('Auto')RSA_Verify('-----BEGIN%20PUBLIC%20KEY-----%5CnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCLDny1MwbGVFrjtNXH%2BHFxZ/4%5CnC5Gz0q2b5exrJLHums5YDSFl6c55QLYNZ4MOlVrahVsAOO0ENkqA5QdswTi%2B53nP%5Cn7zJsxmLnpN5J8QEQJgTlkw%2BkIa8%2Bc8j0FWJCRFcZ4vlxcqIymJc/tpBuHfVIXpQp%5CnGuPpUTCtyfRmBNuGbQIDAQAB%5Cn-----END%20PUBLIC%20KEY-----','Hello%20World','MD5')&input=YjU5ODE1MzYwNjUyZWU3MWE1OTlhNTljZDQzM2Q4MmMyMzFhY2UzNzdjZWRkZDc3YzBkNTBhMmJkYWZhNDJmMjM0OTVkODVhNDg4Y2RiZmUwNDczNjNkOTI3NGE0MWM0MzgwZTgyNzJjMTEzNTExNDZkYmM4NDFhNTNkMTVkZGE0NTE2MGEyMzM4YzQxMzcwZDg2NzFhMTZmYTlkZTExNzQzZjY1N2UzZjMzYzA5MTBmMzYwMWY0MzQzNTZlNzllMWQ3NTEzNzRmOGVkZmZkZmY3MWMxMWZjOWUzNDI0ZmJlNmY0OWI2ZWI3Yzc4Zjc2MDRlZWZhYTU5ZTBhNmNhOA

Public and private key are generated only for that example purpose

C++ code:

#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include "windows.h"
#include "wincrypt.h"

using namespace std;

std::string GetLastErrorAsString() {
    //Get the error message ID, if any.
    DWORD errorMessageID = ::GetLastError();
    if (errorMessageID == 0) {
        return std::string(); //No error message has been recorded
    }

    LPSTR messageBuffer = nullptr;

    //Ask Win32 to give us the string version of that message ID.
    //The parameters we pass in, tell Win32 to create the buffer that holds the message for us (because we don't yet know how long the message string will be).
    size_t size = FormatMessageA(
            FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) &messageBuffer, 0, NULL);

    //Copy the error message into a std::string.
    std::string message(messageBuffer, size);

    //Free the Win32's string's buffer.
    LocalFree(messageBuffer);

    return message;
}

int test4(const vector<unsigned char> &signature, const vector<unsigned char> &data_to_verify) {
    string rsaKey = "-----BEGIN PUBLIC KEY-----\n"
                           "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCLDny1MwbGVFrjtNXH+HFxZ/4\n"
                           "C5Gz0q2b5exrJLHums5YDSFl6c55QLYNZ4MOlVrahVsAOO0ENkqA5QdswTi+53nP\n"
                           "7zJsxmLnpN5J8QEQJgTlkw+kIa8+c8j0FWJCRFcZ4vlxcqIymJc/tpBuHfVIXpQp\n"
                           "GuPpUTCtyfRmBNuGbQIDAQAB\n"
                           "-----END PUBLIC KEY-----";
    char derPubKey[2048];
    size_t derPubKeyLen = 2048;
    CERT_PUBLIC_KEY_INFO *publicKeyInfo;
    int publicKeyInfoLen;
    HCRYPTPROV hProv = 0;
    HCRYPTKEY hKey = 0;

    /*
     * Convert from PEM format to DER format - removes header and footer and decodes from base64
     */
    if (!CryptStringToBinaryA(rsaKey.data(), 0, CRYPT_STRING_BASE64HEADER, reinterpret_cast<BYTE *>(derPubKey),
                              reinterpret_cast<DWORD *>(&derPubKeyLen), NULL, NULL)) {
        fprintf(stderr, "CryptStringToBinary failed. Err: %d\n", GetLastError());
    }

    /*
     * Decode from DER format to CERT_PUBLIC_KEY_INFO
     */
    if (!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, reinterpret_cast<const BYTE *>(derPubKey),
                             derPubKeyLen,
                             CRYPT_ENCODE_ALLOC_FLAG, NULL, &publicKeyInfo,
                             reinterpret_cast<DWORD *>(&publicKeyInfoLen))) {
        fprintf(stderr, "CryptDecodeObjectEx 1 failed. Err: %p\n", GetLastError());
        return -1;
    }

    /*
     * Acquire context
     */
    if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
        {
            printf("CryptAcquireContext failed - err=0x%x.\n", GetLastError());
            return -1;
        }
    }

    /*
     * Import the public key using the context
     */
    if (!CryptImportPublicKeyInfo(hProv, X509_ASN_ENCODING, publicKeyInfo, &hKey)) {
        fprintf(stderr, "CryptImportPublicKeyInfo failed. error: %d\n", GetLastError());

        return -1;
    }
    LocalFree(publicKeyInfo);

    /*
     * Now use hKey to encrypt whatever you need.
     */

    // Hash the data_to_verify
    HCRYPTHASH hHash = 0;
    if (!CryptCreateHash(hProv, CALG_MD5, NULL, 0, &hHash)) {
        printf("CryptCreateHash failed with error 0x%.8lX\n", GetLastError());
        return -1;
    }

    if (!CryptHashData(hHash, data_to_verify.data(), data_to_verify.size(), 0)) {
        printf("CryptHashData failed with error 0x%.8lX\n", GetLastError());
        return -1;
    }

    // Sign the hash using our imported key
    if (!CryptVerifySignature(hHash, signature.data(), signature.size(), hKey, nullptr, 0)) {
        printf("Signature verification failed with error");
        cout << GetLastErrorAsString() << endl;
        return false;
    } else {
        printf("Signature verification succeeded.\n");
        return true;
    }

    return 0;
}

//vector<unsigned char> to hex
std::string to_hex(const std::vector<unsigned char> &v) {
    std::string result;
    char hex[] = "0123456789abcdef";
    for (unsigned char c : v) {
        result += hex[c >> 4];
        result += hex[c & 15];
    }
    return result;
}

int main() {
    vector<unsigned char> signature = {0xb5, 0x98, 0x15, 0x36, 0x06, 0x52, 0xee, 0x71, 0xa5, 0x99, 0xa5, 0x9c, 0xd4,
                                       0x33, 0xd8, 0x2c, 0x23, 0x1a, 0xce, 0x37, 0x7c, 0xed, 0xdd, 0x77, 0xc0, 0xd5,
                                       0x0a, 0x2b, 0xda, 0xfa, 0x42, 0xf2, 0x34, 0x95, 0xd8, 0x5a, 0x48, 0x8c, 0xdb,
                                       0xfe, 0x04, 0x73, 0x63, 0xd9, 0x27, 0x4a, 0x41, 0xc4, 0x38, 0x0e, 0x82, 0x72,
                                       0xc1, 0x13, 0x51, 0x14, 0x6d, 0xbc, 0x84, 0x1a, 0x53, 0xd1, 0x5d, 0xda, 0x45,
                                       0x16, 0x0a, 0x23, 0x38, 0xc4, 0x13, 0x70, 0xd8, 0x67, 0x1a, 0x16, 0xfa, 0x9d,
                                       0xe1, 0x17, 0x43, 0xf6, 0x57, 0xe3, 0xf3, 0x3c, 0x09, 0x10, 0xf3, 0x60, 0x1f,
                                       0x43, 0x43, 0x56, 0xe7, 0x9e, 0x1d, 0x75, 0x13, 0x74, 0xf8, 0xed, 0xff, 0xdf,
                                       0xf7, 0x1c, 0x11, 0xfc, 0x9e, 0x34, 0x24, 0xfb, 0xe6, 0xf4, 0x9b, 0x6e, 0xb7,
                                       0xc7, 0x8f, 0x76, 0x04, 0xee, 0xfa, 0xa5, 0x9e, 0x0a, 0x6c, 0xa8};
    string message = "Hello World";
    vector<unsigned char> data = vector<unsigned char>(message.begin(), message.end());

    cout << "Signature: " << to_hex(signature) << endl;
    cout << "Message: " << message << endl;

    test4(signature, data);
}

After executing that code, i'm getting NTE_BAD_SIGNATURE error

I used PEM import from https://stackoverflow.com/questions/1231178/load-an-pem-encoded-x-509-certificate-into-windows-cryptoapi/3803333#3803333

I really hope someone would help me resolving that issue

答案1

得分: 1

使用CNG API更好(如果不需要支持XP),并且始终需要释放分配的内存和其他资源,这是你没有做的。此代码正常工作。

内联ULONG BOOL_TO_ERRORBOOL f
{
    返回 f ? NOERROR : GetLastError();
}

HRESULT StringToBin_Out_ PDATA_BLOB pdb_In_ ULONG dwFlags_In_ PCSTR pszString_In_ ULONG cchString = 0
{
    PUCHAR pb = 0;
    ULONG cb = 0;

    whileCryptStringToBinaryApszStringcchStringdwFlagspb,&cb00))
    {
        如果(pb
        {
            pdb->pbData = pbpdb->cbData = cb;
            返回 S_OK;
        }

        如果(!(pb =PUCHARLocalAllocLMEM_FIXEDcb)))
        {
            打破;
        }
    }

    返回 HRESULT_FROM_WIN32GetLastError());
}

HRESULT VerifyTest_In_ PCWSTR pszAlgId
                   _In_ PCSTR szKey
                   _In_ PCSTR szSig
                   _In_ const UCHAR *pbData
                   _In_ ULONG cbData
{

    DATA_BLOB dbdb2;
    HRESULT hr;

    如果(NOERROR ==hr = StringToBin(&dbCRYPT_STRING_BASE64HEADERszKey)))
    {
        ULONG cb;
        CERT_PUBLIC_KEY_INFO *publicKeyInfo;

        hr = BOOL_TO_ERRORCryptDecodeObjectExX509_ASN_ENCODINGX509_PUBLIC_KEY_INFO
            db.pbDatadb.cbDataCRYPT_DECODE_ALLOC_FLAG0,&publicKeyInfo,&cb));

        LocalFreedb.pbData;

        如果(NOERROR == hr
        {
            BCRYPT_KEY_HANDLE hKey;

            hr = BOOL_TO_ERRORCryptImportPublicKeyInfoEx2X509_ASN_ENCODINGpublicKeyInfo00,&hKey));

            LocalFreepublicKeyInfo;

            如果(NOERROR == hr
            {
                UCHAR hash[32];

                如果(NOERROR ==hr = BOOL_TO_ERRORCryptHashCertificate2pszAlgId00pbDatacbDatahash,&cb = sizeofhash)))))
                {
                    如果(0 <=hr = StringToBin(&dbCRYPT_STRING_BASE64szSig)))
                    {
                        hr = StringToBin(&db2CRYPT_STRING_HEXRAW,(PCSTRdb.pbDatadb.cbData;

                        LocalFreedb.pbData;

                        如果(0 <= hr
                        {
                            BCRYPT_PKCS1_PADDING_INFO pi = { pszAlgId };

                            如果(0 >hr = BCryptVerifySignaturehKey,&pihashcbdb2.pbDatadb2.cbDataBCRYPT_PAD_PKCS1)))
                            {
                                hr |= FACILITY_NT_BIT;
                            }

                            LocalFreedb2.pbData;
                        }
                    }
                }

                BCryptDestroyKeyhKey;
            }
        }
    }

    返回 HRESULT_FROM_WIN32hr;
}

void VerifyTest()
{
    静态const CHAR szKey[] =
        -----BEGIN PUBLIC KEY-----\n
        MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCLDny1MwbGVFrjtNXH+HFxZ/4\n
        C5Gz0q2b5exrJLHums5YDSFl6c55QLYNZ4MOlVrahVsAOO0ENkqA5QdswTi+53nP\n
        7zJsxmLnpN5J8QEQJgTlkw+kIa8+c8j0FWJCRFcZ4vlxcqIymJc/tpBuHfVIXpQp\n
        GuPpUTCtyfRmBNuGbQIDAQAB\n
        -----END PUBLIC KEY-----;

    静态const CHAR szSig[] =
        YjU5ODE1MzYwNjUyZWU3MWE1OTlhNTljZDQzM2Q4MmMyMzFhY2UzNzdjZWRkZDc3
        YzBkNTBhM2JkYWZhNDJmMjM0OTVkODVhNDg4Y2RiZmUwNDczNjNkOTI3NGE0MWM0
        MzgwZTgyNzJjMTEzNTExNDZkYmM4NDFhNTNkMTVkZGE0NTE2MGEyMzM4YzQxMzcw
        ZDg2NzFhMTZmYTlkZTExNzQzZjY1N2UzZjMzYzA5MTBmMzYwMWY0MzQzNTZlNzll
        MWQ3NTEzNzRmOGVkZmZkZmY3MWMxMWZjOWUzNDI0ZmJlNmY0OWI2ZWI3Yzc4Zjc2
        MDRlZWZhYTU5ZTBhNmNhOA;

    静态const UCHAR data[] = Hello World;

    VerifyTestBCRYPT_MD5_ALGORITHMszKeyszSigdatasizeofdata - 1;
}

----------

用于签名的代码如下:

void PrintStrPSTR pszULONG cch
{
    ULONG len;
    
    {
        DbgPrint(“%.*s”,len = min0x100cch),psz;
    } whilepsz + = lencch- = len;
}

NTSTATUS ImportRsaKey_Out_ BCRYPT_KEY_HANDLE* phKey_In_ PBYTE pbKey_In_ ULONG cbKey
{
    如果(CryptDecodeObjectExX509_ASN_ENCODINGCNG_RSA_PRIVATE_KEY_BLOB
        pbKeycbKeyCRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG0,&pbKey,&cbKey))
    {
        BCRYPT_ALG_HANDLE hAlgorithm;

        NTSTATUS状态;

        如果(0 <=(状态= BCryptOpenAlgorithmProvider(&hAlgorithmBCRYPT_RSA_ALGORITHMMS_PRIMITIVE_PROVIDER0)))
        {
            状态= BCryptImport

<details>
<summary>英文:</summary>

better use CNG api (if not need support xp) and always need free allocated memory and other resources, what you not do. this code work ok

    inline ULONG BOOL_TO_ERROR(BOOL f)
    {
    	return f ? NOERROR : GetLastError();
    }
    
    HRESULT StringToBin(_Out_ PDATA_BLOB pdb, _In_ ULONG dwFlags, _In_ PCSTR pszString, _In_ ULONG cchString = 0)
    {
    	PUCHAR pb = 0;
    	ULONG cb = 0;
    
    	while (CryptStringToBinaryA(pszString, cchString, dwFlags, pb, &amp;cb, 0, 0))
    	{
    		if (pb)
    		{
    			pdb-&gt;pbData = pb, pdb-&gt;cbData = cb;
    			return S_OK;
    		}
    
    		if (!(pb = (PUCHAR)LocalAlloc(LMEM_FIXED, cb)))
    		{
    			break;
    		}
    	}
    
    	return HRESULT_FROM_WIN32(GetLastError());
    }
    
    HRESULT VerifyTest(_In_ PCWSTR pszAlgId, 
    				   _In_ PCSTR szKey, 
    				   _In_ PCSTR szSig, 
    				   _In_ const UCHAR *pbData,
    				   _In_ ULONG cbData)
    {
    
    	DATA_BLOB db, db2;
    	HRESULT hr;
    
    	if (NOERROR == (hr = StringToBin(&amp;db, CRYPT_STRING_BASE64HEADER, szKey)))
    	{
    		ULONG cb;
    		CERT_PUBLIC_KEY_INFO *publicKeyInfo;
    
    		hr = BOOL_TO_ERROR(CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, 
    			db.pbData, db.cbData, CRYPT_DECODE_ALLOC_FLAG, 0, &amp;publicKeyInfo, &amp;cb));
    
    		LocalFree(db.pbData);
    
    		if (NOERROR == hr)
    		{
    			BCRYPT_KEY_HANDLE hKey;
    
    			hr = BOOL_TO_ERROR(CryptImportPublicKeyInfoEx2(X509_ASN_ENCODING, publicKeyInfo, 0, 0, &amp;hKey));
    
    			LocalFree(publicKeyInfo);
    
    			if (NOERROR == hr)
    			{
    				UCHAR hash[32];
    
    				if (NOERROR == (hr = BOOL_TO_ERROR(CryptHashCertificate2(pszAlgId, 0, 0, pbData, cbData, hash, &amp;(cb = sizeof(hash))))))
    				{
    					if (0 &lt;= (hr = StringToBin(&amp;db, CRYPT_STRING_BASE64, szSig)))
    					{
    						hr = StringToBin(&amp;db2, CRYPT_STRING_HEXRAW, (PCSTR)db.pbData, db.cbData);
    
    						LocalFree(db.pbData);
    
    						if (0 &lt;= hr)
    						{
    							BCRYPT_PKCS1_PADDING_INFO pi = { pszAlgId };
    							
    							if (0 &gt; (hr = BCryptVerifySignature(hKey, &amp;pi, hash, cb, db2.pbData, db2.cbData, BCRYPT_PAD_PKCS1)))
    							{
    								hr |= FACILITY_NT_BIT;
    							}
    
    							LocalFree(db2.pbData);
    						}
    					}
    				}
    
    				BCryptDestroyKey(hKey);
    			}
    		}
    	}
    
    	return HRESULT_FROM_WIN32(hr);
    }
    
    void VerifyTest()
    {
    	static const CHAR szKey[] = 
    		&quot;-----BEGIN PUBLIC KEY-----\n&quot;
    		&quot;MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCLDny1MwbGVFrjtNXH+HFxZ/4\n&quot;
    		&quot;C5Gz0q2b5exrJLHums5YDSFl6c55QLYNZ4MOlVrahVsAOO0ENkqA5QdswTi+53nP\n&quot;
    		&quot;7zJsxmLnpN5J8QEQJgTlkw+kIa8+c8j0FWJCRFcZ4vlxcqIymJc/tpBuHfVIXpQp\n&quot;
    		&quot;GuPpUTCtyfRmBNuGbQIDAQAB\n&quot;
    		&quot;-----END PUBLIC KEY-----&quot;;
    
    	static const CHAR szSig[] = 
    		&quot;YjU5ODE1MzYwNjUyZWU3MWE1OTlhNTljZDQzM2Q4MmMyMzFhY2UzNzdjZWRkZDc3&quot;
    		&quot;YzBkNTBhMmJkYWZhNDJmMjM0OTVkODVhNDg4Y2RiZmUwNDczNjNkOTI3NGE0MWM0&quot;
    		&quot;MzgwZTgyNzJjMTEzNTExNDZkYmM4NDFhNTNkMTVkZGE0NTE2MGEyMzM4YzQxMzcw&quot;
    		&quot;ZDg2NzFhMTZmYTlkZTExNzQzZjY1N2UzZjMzYzA5MTBmMzYwMWY0MzQzNTZlNzll&quot;
    		&quot;MWQ3NTEzNzRmOGVkZmZkZmY3MWMxMWZjOWUzNDI0ZmJlNmY0OWI2ZWI3Yzc4Zjc2&quot;
    		&quot;MDRlZWZhYTU5ZTBhNmNhOA&quot;;
    
    	static const UCHAR data[] = &quot;Hello World&quot;;
    
    	VerifyTest(BCRYPT_MD5_ALGORITHM, szKey, szSig, data, sizeof(data) - 1);
    }


----------
for sign can be used next code:

    void PrintStr(PSTR psz, ULONG cch)
    {
    	ULONG len;
    	do 
    	{
    		DbgPrint(&quot;%.*s&quot;, len = min(0x100, cch), psz);
    	} while (psz += len, cch -= len);
    }
    
    NTSTATUS ImportRsaKey(_Out_ BCRYPT_KEY_HANDLE* phKey, _In_ PBYTE pbKey, _In_ ULONG cbKey)
    {
    	if (CryptDecodeObjectEx(X509_ASN_ENCODING, CNG_RSA_PRIVATE_KEY_BLOB, 
    		pbKey, cbKey, CRYPT_DECODE_ALLOC_FLAG|CRYPT_DECODE_NOCOPY_FLAG, 0, &amp;pbKey, &amp;cbKey))
    	{
    		BCRYPT_ALG_HANDLE hAlgorithm;
    
    		NTSTATUS status;
    
    		if (0 &lt;= (status = BCryptOpenAlgorithmProvider(&amp;hAlgorithm, BCRYPT_RSA_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0)))
    		{
    			status = BCryptImportKeyPair (hAlgorithm, 0, BCRYPT_PRIVATE_KEY_BLOB, phKey, pbKey, cbKey, 0);
    			BCryptCloseAlgorithmProvider(hAlgorithm, 0);
    		}
    
    		LocalFree(pbKey);
    
    		return 0 &gt; status ? HRESULT_FROM_NT(status) : S_OK;
    	}
    
    	return HRESULT_FROM_WIN32(GetLastError());
    }
    
    HRESULT BinToString(_Out_ PSTR *ppszString, _In_ ULONG dwFlags, _In_ const UCHAR* pb, _In_ ULONG cb)
    {
    	PSTR pszString = 0;
    	ULONG cch = 0;
    
    	while (CryptBinaryToStringA(pb, cb, dwFlags, pszString, &amp;cch))
    	{
    		if (pszString)
    		{
    			*ppszString = pszString;
    			return S_OK;
    		}
    
    		if (!(pszString = (PSTR)LocalAlloc(LMEM_FIXED, cch)))
    		{
    			break;
    		}
    	}
    
    	return HRESULT_FROM_WIN32(GetLastError());
    }
    
    
    HRESULT SignTest(_In_ PCWSTR pszAlgId, 
    				 _In_ PCSTR szKey, 
    				 _In_ const UCHAR *pbData,
    				 _In_ ULONG cbData)
    {
    	DATA_BLOB db;
    	HRESULT hr;
    
    	if (NOERROR == (hr = StringToBin(&amp;db, CRYPT_STRING_BASE64HEADER, szKey)))
    	{
    		BCRYPT_KEY_HANDLE hKey=0;
    
    		hr = ImportRsaKey(&amp;hKey, db.pbData, db.cbData);
    
    		LocalFree(db.pbData);
    
    		if (0 &lt;= hr)
    		{
    			UCHAR hash[32];
    			ULONG cb = sizeof(hash);
    
    			if (NOERROR == (hr = BOOL_TO_ERROR(CryptHashCertificate2(pszAlgId, 0, 0, pbData, cbData, hash, &amp;cb))))
    			{
    				BCRYPT_PKCS1_PADDING_INFO pi = { pszAlgId };
    
    				PUCHAR pbSig = 0;
    				ULONG cbSig = 0;
    
    				while (0 &lt;= (hr = BCryptSignHash(hKey, &amp;pi, hash, cb, pbSig, cbSig, &amp;cbSig, BCRYPT_PAD_PKCS1)))
    				{
    					if (pbSig)
    					{
    						PSTR psz, psz2;
    						if (NOERROR == BinToString(&amp;psz, CRYPT_STRING_HEXRAW|CRYPT_STRING_NOCRLF, pbSig, cbSig))
    						{
    							if (NOERROR == BinToString(&amp;psz2, CRYPT_STRING_BASE64, (PUCHAR)psz, (ULONG)strlen(psz)))
    							{
    								PrintStr(psz2, (ULONG)strlen(psz2));
    								LocalFree(psz2);
    							}
    							LocalFree(psz);
    						}
    						break;
    					}
    
    					pbSig = (PUCHAR)alloca(cbSig);
    				}
    			}
    
    			BCryptDestroyKey(hKey);
    		}
    	}
    
    	return HRESULT_FROM_WIN32(hr);
    }
    
    void sign()
    {
    	static const UCHAR data[] = &quot;Hello World&quot;;
    
    	static const CHAR szPrivKey[] = 
    		&quot;-----BEGIN RSA PRIVATE KEY-----&quot;
    		&quot;MIICWwIBAAKBgQDCLDny1MwbGVFrjtNXH+HFxZ/4C5Gz0q2b5exrJLHums5YDSFl&quot;
    		&quot;6c55QLYNZ4MOlVrahVsAOO0ENkqA5QdswTi+53nP7zJsxmLnpN5J8QEQJgTlkw+k&quot;
    		&quot;Ia8+c8j0FWJCRFcZ4vlxcqIymJc/tpBuHfVIXpQpGuPpUTCtyfRmBNuGbQIDAQAB&quot;
    		&quot;AoGABH78qoRF45y+92Qbvak105wDW7181rKapYD56/MyEYnRHFXVf6QdzU3zyTSr&quot;
    		&quot;4rMPov6ygDtRNadCK2DiPqDsvOiQU+y7ZSt+t0hdUv8nkQOzR167dM8dLAoVMVtm&quot;
    		&quot;KgUYO1MUnERvh+pmPKOmYozBAZbJJshOLbmqfGoJH1wUzCECQQDkC1SDsmLbT9uA&quot;
    		&quot;8MR6u4sn+kghli5oxP3dnj/1WRAATt3SrQNGUyJsLCCDc70EOPwx/nIY4aDog/3K&quot;
    		&quot;ixut8zVdAkEA2fnp0rCOXXikNV69z5Y2lj4OYpLtJiaJQK6NOYF997zso2oln/xX&quot;
    		&quot;ddxle0+a5KufdkP4DGP0QSnZKA+6qIf0UQJAf9hOQCrQuwzRDT9tlzTu9bGdoJ62&quot;
    		&quot;U+wkOotOZfjRPKr6NvLhxBo1URmH/Mn07JoZ4Nk6E/LiJ5hfvp4wHVwczQJAIDxR&quot;
    		&quot;VBNAOpqIzkvAjl6MnBN5VSKdZ7LzQVmPER4RXv3VkSU1gz9yP7/kUiQnqAGph3ft&quot;
    		&quot;ywdNLAXgU4hf9mSEwQJAbLV0c7GWXPCSk3k0gwOZCjHKaIxDIBjZudv5cvO9sPQx&quot;
    		&quot;sqE17eyl5+ufQq1xOQZL4HL+nUjlOcgT/pIdI9430A==&quot;
    		&quot;-----END RSA PRIVATE KEY-----&quot;;
    
    	SignTest(BCRYPT_MD5_ALGORITHM, szPrivKey, data, sizeof(data) - 1);
    }

</details>



# 答案2
**得分**: 0

以下是编辑后的工作示例:

```c++
#include <iostream>
#include <cstdio>
#include "windows.h"
#include "wincrypt.h"
#include "comdef.h"

using namespace std;

inline ULONG BOOL_TO_ERROR(BOOL f)
{
    return f ? NOERROR : GetLastError();
}

HRESULT StringToBin(_Out_ PDATA_BLOB pdb, _In_ ULONG dwFlags, _In_ PCSTR pszString, _In_ ULONG cchString = 0)
{
    PUCHAR pb = 0;
    ULONG cb = 0;

    while (CryptStringToBinaryA(pszString, cchString, dwFlags, pb, &cb, 0, 0))
    {
        if (pb)
        {
            pdb->pbData = pb, pdb->cbData = cb;
            return S_OK;
        }

        if (!(pb = (PUCHAR)LocalAlloc(LMEM_FIXED, cb)))
        {
            break;
        }
    }

    return HRESULT_FROM_WIN32(GetLastError());
}

#define SIGNATURE_SIZE 128
HRESULT VerifyTest(_In_ PCWSTR algorithm,
                   _In_ PCSTR keyAsPem,
                   _In_ BYTE *signatureBase64,
                   _In_ const UCHAR *dataToCheck,
                   _In_ ULONG dataToCheckSize)
{

    DATA_BLOB db, db2;
    HRESULT hr;

    if (NOERROR == (hr = StringToBin(&db, CRYPT_STRING_BASE64HEADER, keyAsPem)))
    {
        ULONG cb;
        CERT_PUBLIC_KEY_INFO *publicKeyInfo;

        hr = BOOL_TO_ERROR(CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO,
                                               db.pbData, db.cbData, CRYPT_DECODE_ALLOC_FLAG, 0, &publicKeyInfo, &cb));

        LocalFree(db.pbData);

        if (NOERROR == hr)
        {
            BCRYPT_KEY_HANDLE hKey;

            hr = BOOL_TO_ERROR(CryptImportPublicKeyInfoEx2(X509_ASN_ENCODING, publicKeyInfo, 0, 0, &hKey));

            LocalFree(publicKeyInfo);

            if (NOERROR == hr)
            {
                UCHAR hash[32];

                if (NOERROR == (hr = BOOL_TO_ERROR(CryptHashCertificate2(algorithm, 0, 0, dataToCheck, dataToCheckSize, hash, &(cb = sizeof(hash))))))
                {
                    BCRYPT_PKCS1_PADDING_INFO pi = {algorithm};

                    if (0 > (hr = BCryptVerifySignature(hKey, &pi, hash, cb, signatureBase64, SIGNATURE_SIZE, BCRYPT_PAD_PKCS1)))
                    {
                        hr |= FACILITY_NT_BIT;
                    }
                }

                BCryptDestroyKey(hKey);
            }
        }
    }

    return HRESULT_FROM_WIN32(hr);
}

void VerifyTest()
{
    static const CHAR szKey[] =
        "-----BEGIN PUBLIC KEY-----\n"
        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCLDny1MwbGVFrjtNXH+HFxZ/4\n"
        "C5Gz0k2b5exrJLHums5YDSFl6c55QLYNZ4MOlVrahVsAOO0ENkqA5QdswTi+53nP\n"
        "7zJsxmLnpN5J8QEQJgTlkw+kIa8+c8j0FWJCRFcZ4vlxcqIymJc/tpBuHfVIXpQp\n"
        "GuPpUTCtyfRmBNuGbQIDAQAB\n"
        "-----END PUBLIC KEY-----";

    static BYTE dataToVerify[] = {0xb5, 0x98, 0x15, 0x36, 0x06, 0x52, 0xee, 0x71, 0xa5, 0x99, 0xa5, 0x9c, 0xd4,
                                  0x33, 0xd8, 0x2c, 0x23, 0x1a, 0xce, 0x37, 0x7c, 0xed, 0xdd, 0x77, 0xc0, 0xd5,
                                  0x0a, 0x2b, 0xda, 0xfa, 0x42, 0xf2, 0x34, 0x95, 0xd8, 0x5a, 0x48, 0x8c, 0xdb,
                                  0xfe, 0x04, 0x73, 0x63, 0xd9, 0x27, 0x4a, 0x41, 0xc4, 0x38, 0x0e, 0x82, 0x72,
                                  0xc1, 0x13, 0x51, 0x14, 0x6d, 0xbc, 0x84, 0x1a, 0x53, 0xd1, 0x5d, 0xda, 0x45,
                                  0x16, 0x0a, 0x23, 0x38, 0xc4, 0x13, 0x70, 0xd8, 0x67, 0x1a, 0x16, 0xfa, 0x9d,
                                  0xe1, 0x17, 0x43, 0xf6, 0x57, 0xe3, 0xf3, 0x3c, 0x09, 0x10, 0xf3, 0x60, 0x1f,
                                  0x43, 0x43, 0x56, 0xe7, 0x9e, 0x1d, 0x75, 0x13, 0x74, 0xf8, 0xed, 0xff, 0xdf,
                                  0xf7, 0x1c, 0x11, 0xfc, 0x9e, 0x34, 0x24, 0xfb, 0xe6, 0xf4, 0x9b, 0x6e, 0xb7,
                                  0xc7, 0x8f, 0x76, 0x04, 0xee, 0xfa, 0xa5, 0x9e, 0x0a, 0x6c, 0xa8};

    static const UCHAR data[] = "Hello World";

    HRESULT i = VerifyTest(BCRYPT_MD5_ALGORITHM, szKey, dataToVerify, data, sizeof(data) - 1);

    _com_error err(i);
    LPCTSTR errMsg = err.ErrorMessage();
    cout << "Result: " << errMsg << endl;
}

int main()
{
    Verify

<details>
<summary>英文:</summary>

Working example after some edit:

```c++
#include &lt;iostream&gt;
#include &lt;cstdio&gt;
#include &quot;windows.h&quot;
#include &quot;wincrypt.h&quot;
#include &quot;comdef.h&quot;

using namespace std;

inline ULONG BOOL_TO_ERROR(BOOL f)
{
    return f ? NOERROR : GetLastError();
}

HRESULT StringToBin(_Out_ PDATA_BLOB pdb, _In_ ULONG dwFlags, _In_ PCSTR pszString, _In_ ULONG cchString = 0)
{
    PUCHAR pb = 0;
    ULONG cb = 0;

    while (CryptStringToBinaryA(pszString, cchString, dwFlags, pb, &amp;cb, 0, 0))
    {
        if (pb)
        {
            pdb-&gt;pbData = pb, pdb-&gt;cbData = cb;
            return S_OK;
        }

        if (!(pb = (PUCHAR)LocalAlloc(LMEM_FIXED, cb)))
        {
            break;
        }
    }

    return HRESULT_FROM_WIN32(GetLastError());
}

#define SIGNATURE_SIZE 128
HRESULT VerifyTest(_In_ PCWSTR algorithm,
                   _In_ PCSTR keyAsPem,
                   _In_ BYTE *signatureBase64,
                   _In_ const UCHAR *dataToCheck,
                   _In_ ULONG dataToCheckSize)
{

    DATA_BLOB db, db2;
    HRESULT hr;

    if (NOERROR == (hr = StringToBin(&amp;db, CRYPT_STRING_BASE64HEADER, keyAsPem)))
    {
        ULONG cb;
        CERT_PUBLIC_KEY_INFO *publicKeyInfo;

        hr = BOOL_TO_ERROR(CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO,
                                               db.pbData, db.cbData, CRYPT_DECODE_ALLOC_FLAG, 0, &amp;publicKeyInfo, &amp;cb));

        LocalFree(db.pbData);

        if (NOERROR == hr)
        {
            BCRYPT_KEY_HANDLE hKey;

            hr = BOOL_TO_ERROR(CryptImportPublicKeyInfoEx2(X509_ASN_ENCODING, publicKeyInfo, 0, 0, &amp;hKey));

            LocalFree(publicKeyInfo);

            if (NOERROR == hr)
            {
                UCHAR hash[32];

                if (NOERROR == (hr = BOOL_TO_ERROR(CryptHashCertificate2(algorithm, 0, 0, dataToCheck, dataToCheckSize, hash, &amp;(cb = sizeof(hash))))))
                {
                    BCRYPT_PKCS1_PADDING_INFO pi = {algorithm };

                    if (0 &gt; (hr = BCryptVerifySignature(hKey, &amp;pi, hash, cb, signatureBase64, SIGNATURE_SIZE, BCRYPT_PAD_PKCS1)))
                    {
                        hr |= FACILITY_NT_BIT;
                    }
                }

                BCryptDestroyKey(hKey);
            }
        }
    }

    return HRESULT_FROM_WIN32(hr);
}

void VerifyTest()
{
    static const CHAR szKey[] =
            &quot;-----BEGIN PUBLIC KEY-----\n&quot;
            &quot;MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCLDny1MwbGVFrjtNXH+HFxZ/4\n&quot;
            &quot;C5Gz0q2b5exrJLHums5YDSFl6c55QLYNZ4MOlVrahVsAOO0ENkqA5QdswTi+53nP\n&quot;
            &quot;7zJsxmLnpN5J8QEQJgTlkw+kIa8+c8j0FWJCRFcZ4vlxcqIymJc/tpBuHfVIXpQp\n&quot;
            &quot;GuPpUTCtyfRmBNuGbQIDAQAB\n&quot;
            &quot;-----END PUBLIC KEY-----&quot;;

    static BYTE dataToVerify[] = {0xb5, 0x98, 0x15, 0x36, 0x06, 0x52, 0xee, 0x71, 0xa5, 0x99, 0xa5, 0x9c, 0xd4,
                                        0x33, 0xd8, 0x2c, 0x23, 0x1a, 0xce, 0x37, 0x7c, 0xed, 0xdd, 0x77, 0xc0, 0xd5,
                                        0x0a, 0x2b, 0xda, 0xfa, 0x42, 0xf2, 0x34, 0x95, 0xd8, 0x5a, 0x48, 0x8c, 0xdb,
                                        0xfe, 0x04, 0x73, 0x63, 0xd9, 0x27, 0x4a, 0x41, 0xc4, 0x38, 0x0e, 0x82, 0x72,
                                        0xc1, 0x13, 0x51, 0x14, 0x6d, 0xbc, 0x84, 0x1a, 0x53, 0xd1, 0x5d, 0xda, 0x45,
                                        0x16, 0x0a, 0x23, 0x38, 0xc4, 0x13, 0x70, 0xd8, 0x67, 0x1a, 0x16, 0xfa, 0x9d,
                                        0xe1, 0x17, 0x43, 0xf6, 0x57, 0xe3, 0xf3, 0x3c, 0x09, 0x10, 0xf3, 0x60, 0x1f,
                                        0x43, 0x43, 0x56, 0xe7, 0x9e, 0x1d, 0x75, 0x13, 0x74, 0xf8, 0xed, 0xff, 0xdf,
                                        0xf7, 0x1c, 0x11, 0xfc, 0x9e, 0x34, 0x24, 0xfb, 0xe6, 0xf4, 0x9b, 0x6e, 0xb7,
                                        0xc7, 0x8f, 0x76, 0x04, 0xee, 0xfa, 0xa5, 0x9e, 0x0a, 0x6c, 0xa8};

    static const UCHAR data[] = &quot;Hello World&quot;;

    HRESULT i = VerifyTest(BCRYPT_MD5_ALGORITHM, szKey, dataToVerify, data, sizeof(data) - 1);

    _com_error err(i);
    LPCTSTR errMsg = err.ErrorMessage();
    cout &lt;&lt; &quot;Result: &quot; &lt;&lt; errMsg &lt;&lt; endl;
}

int main() {
    VerifyTest();
}

I used code in answer on the top

huangapple
  • 本文由 发表于 2023年1月8日 23:22:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/75048954.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定