英文:
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_ERROR(BOOL 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;
while(CryptStringToBinaryA(pszString,cchString,dwFlags,pb,&amp;cb,0,0))
{
如果(pb)
{
pdb->pbData = pb,pdb->cbData = cb;
返回 S_OK;
}
如果(!(pb =(PUCHAR)LocalAlloc(LMEM_FIXED,cb)))
{
打破;
}
}
返回 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;
如果(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);
如果(NOERROR == hr)
{
BCRYPT_KEY_HANDLE hKey;
hr = BOOL_TO_ERROR(CryptImportPublicKeyInfoEx2(X509_ASN_ENCODING,publicKeyInfo,0,0,&amp;hKey));
LocalFree(publicKeyInfo);
如果(NOERROR == hr)
{
UCHAR hash[32];
如果(NOERROR ==(hr = BOOL_TO_ERROR(CryptHashCertificate2(pszAlgId,0,0,pbData,cbData,hash,&amp;(cb = sizeof(hash)))))
{
如果(0 <=(hr = StringToBin(&amp;db,CRYPT_STRING_BASE64,szSig)))
{
hr = StringToBin(&amp;db2,CRYPT_STRING_HEXRAW,(PCSTR)db.pbData,db.cbData);
LocalFree(db.pbData);
如果(0 <= hr)
{
BCRYPT_PKCS1_PADDING_INFO pi = { pszAlgId };
如果(0 >(hr = BCryptVerifySignature(hKey,&amp;pi,hash,cb,db2.pbData,db2.cbData,BCRYPT_PAD_PKCS1)))
{
hr |= FACILITY_NT_BIT;
}
LocalFree(db2.pbData);
}
}
}
BCryptDestroyKey(hKey);
}
}
}
返回 HRESULT_FROM_WIN32(hr);
}
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”;
VerifyTest(BCRYPT_MD5_ALGORITHM,szKey,szSig,data,sizeof(data) - 1);
}
----------
用于签名的代码如下:
void PrintStr(PSTR psz,ULONG cch)
{
ULONG len;
做
{
DbgPrint(“%.*s”,len = min(0x100,cch),psz);
} while(psz + = len,cch- = len);
}
NTSTATUS ImportRsaKey(_Out_ BCRYPT_KEY_HANDLE* phKey,_In_ PBYTE pbKey,_In_ ULONG cbKey)
{
如果(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状态;
如果(0 <=(状态= BCryptOpenAlgorithmProvider(&amp;hAlgorithm,BCRYPT_RSA_ALGORITHM,MS_PRIMITIVE_PROVIDER,0)))
{
状态= 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, &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());
}
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(&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, &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(pszAlgId, 0, 0, pbData, cbData, hash, &(cb = sizeof(hash))))))
{
if (0 <= (hr = StringToBin(&db, CRYPT_STRING_BASE64, szSig)))
{
hr = StringToBin(&db2, CRYPT_STRING_HEXRAW, (PCSTR)db.pbData, db.cbData);
LocalFree(db.pbData);
if (0 <= hr)
{
BCRYPT_PKCS1_PADDING_INFO pi = { pszAlgId };
if (0 > (hr = BCryptVerifySignature(hKey, &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[] =
"-----BEGIN PUBLIC KEY-----\n"
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCLDny1MwbGVFrjtNXH+HFxZ/4\n"
"C5Gz0q2b5exrJLHums5YDSFl6c55QLYNZ4MOlVrahVsAOO0ENkqA5QdswTi+53nP\n"
"7zJsxmLnpN5J8QEQJgTlkw+kIa8+c8j0FWJCRFcZ4vlxcqIymJc/tpBuHfVIXpQp\n"
"GuPpUTCtyfRmBNuGbQIDAQAB\n"
"-----END PUBLIC KEY-----";
static const CHAR szSig[] =
"YjU5ODE1MzYwNjUyZWU3MWE1OTlhNTljZDQzM2Q4MmMyMzFhY2UzNzdjZWRkZDc3"
"YzBkNTBhMmJkYWZhNDJmMjM0OTVkODVhNDg4Y2RiZmUwNDczNjNkOTI3NGE0MWM0"
"MzgwZTgyNzJjMTEzNTExNDZkYmM4NDFhNTNkMTVkZGE0NTE2MGEyMzM4YzQxMzcw"
"ZDg2NzFhMTZmYTlkZTExNzQzZjY1N2UzZjMzYzA5MTBmMzYwMWY0MzQzNTZlNzll"
"MWQ3NTEzNzRmOGVkZmZkZmY3MWMxMWZjOWUzNDI0ZmJlNmY0OWI2ZWI3Yzc4Zjc2"
"MDRlZWZhYTU5ZTBhNmNhOA";
static const UCHAR data[] = "Hello World";
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("%.*s", 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, &pbKey, &cbKey))
{
BCRYPT_ALG_HANDLE hAlgorithm;
NTSTATUS status;
if (0 <= (status = BCryptOpenAlgorithmProvider(&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 > 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, &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(&db, CRYPT_STRING_BASE64HEADER, szKey)))
{
BCRYPT_KEY_HANDLE hKey=0;
hr = ImportRsaKey(&hKey, db.pbData, db.cbData);
LocalFree(db.pbData);
if (0 <= hr)
{
UCHAR hash[32];
ULONG cb = sizeof(hash);
if (NOERROR == (hr = BOOL_TO_ERROR(CryptHashCertificate2(pszAlgId, 0, 0, pbData, cbData, hash, &cb))))
{
BCRYPT_PKCS1_PADDING_INFO pi = { pszAlgId };
PUCHAR pbSig = 0;
ULONG cbSig = 0;
while (0 <= (hr = BCryptSignHash(hKey, &pi, hash, cb, pbSig, cbSig, &cbSig, BCRYPT_PAD_PKCS1)))
{
if (pbSig)
{
PSTR psz, psz2;
if (NOERROR == BinToString(&psz, CRYPT_STRING_HEXRAW|CRYPT_STRING_NOCRLF, pbSig, cbSig))
{
if (NOERROR == BinToString(&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[] = "Hello World";
static const CHAR szPrivKey[] =
"-----BEGIN RSA PRIVATE KEY-----"
"MIICWwIBAAKBgQDCLDny1MwbGVFrjtNXH+HFxZ/4C5Gz0q2b5exrJLHums5YDSFl"
"6c55QLYNZ4MOlVrahVsAOO0ENkqA5QdswTi+53nP7zJsxmLnpN5J8QEQJgTlkw+k"
"Ia8+c8j0FWJCRFcZ4vlxcqIymJc/tpBuHfVIXpQpGuPpUTCtyfRmBNuGbQIDAQAB"
"AoGABH78qoRF45y+92Qbvak105wDW7181rKapYD56/MyEYnRHFXVf6QdzU3zyTSr"
"4rMPov6ygDtRNadCK2DiPqDsvOiQU+y7ZSt+t0hdUv8nkQOzR167dM8dLAoVMVtm"
"KgUYO1MUnERvh+pmPKOmYozBAZbJJshOLbmqfGoJH1wUzCECQQDkC1SDsmLbT9uA"
"8MR6u4sn+kghli5oxP3dnj/1WRAATt3SrQNGUyJsLCCDc70EOPwx/nIY4aDog/3K"
"ixut8zVdAkEA2fnp0rCOXXikNV69z5Y2lj4OYpLtJiaJQK6NOYF997zso2oln/xX"
"ddxle0+a5KufdkP4DGP0QSnZKA+6qIf0UQJAf9hOQCrQuwzRDT9tlzTu9bGdoJ62"
"U+wkOotOZfjRPKr6NvLhxBo1URmH/Mn07JoZ4Nk6E/LiJ5hfvp4wHVwczQJAIDxR"
"VBNAOpqIzkvAjl6MnBN5VSKdZ7LzQVmPER4RXv3VkSU1gz9yP7/kUiQnqAGph3ft"
"ywdNLAXgU4hf9mSEwQJAbLV0c7GWXPCSk3k0gwOZCjHKaIxDIBjZudv5cvO9sPQx"
"sqE17eyl5+ufQq1xOQZL4HL+nUjlOcgT/pIdI9430A=="
"-----END RSA PRIVATE KEY-----";
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 <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"
"C5Gz0q2b5exrJLHums5YDSFl6c55QLYNZ4MOlVrahVsAOO0ENkqA5QdswTi+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() {
VerifyTest();
}
I used code in answer on the top
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论