I have used the same plain text, same public key, but get different result in Wincrypt and openssl. My enviroment is win7 64bit and VS 2010 and openssl 1.1.1S.
here is the code:
/*
* An example of using PEM encoded RSA private keys with CAPI
* - Modified on March 29th 2014 to show how to use PEM encoded RSA public key
*
* Copyright (c) 2012 Mounir IDRASSI <mounir.idrassi@idrix.fr>. All rights reserved.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
*/
//
//#ifndef _WIN32_WINNT
//#define _WIN32_WINNT 0x0501
//#endif
//
//#include <windows.h>
//#include <wincrypt.h>
//#include <stdio.h>
//
//#pragma comment(lib, "Crypt32.lib")
//
//const char* szPemPrivKey =
// "-----BEGIN RSA PRIVATE KEY-----"
// "MIICXAIBAAKBgQCf6YAJOSBYPve1jpYDzq+w++8YVoATI/YCi/RKZaQk+l2ZfoUQ"
// "g0qrYrfkzeoOa/qd5VLjTTvHEgwXnlDXMfo+vSgxosUxDOZXMTBqJGOViv5K2QBv"
// "k8A1wi4k8tuo/7OWya29HvcfavUk3YXaV2YFe8V6ssaZjNcVWmDdjqNkXwIDAQAB"
// "AoGALrd+ijNAOcebglT3ioE1XpUbUpbir7TPyAqvAZUUESF7er41jY9tnwgmBRgL"
// "Cs+M1dgLERCdKBkjozrDDzswifFQmq6PrmYrBkFFqCoLJwepSYdWnK1gbZ/d43rR"
// "2sXzSGZngscx0CxO7KZ7xUkwENGd3+lKXV7J6/vgzJ4XnkECQQDTP6zWKT7YDckk"
// "We04hbhHyBuNOW068NgUUvoZdBewerR74MJx6nz28Tp+DeNvc0EveiQxsEnbV8u+"
// "NRkX5y0xAkEAwcnEAGBn5kJd6SpU0ALA9XEpUv7tHTAGQYgCRbfTT59hhOq6I22A"
// "ivjOCNG9c6E7EB2kcPVGuCpYUhy7XBIGjwJAK5lavKCqncDKoLwGn8HJdNcyCIWv"
// "q5iFoDw37gTt1ricg2yx9PzmabkDz3xiUmBBNeFJkw/FToXiQRGIakyGIQJAJIem"
// "PPPvYgZssYFbT4LVYO8d/Rk1FWVyKHQ9CWtnmADRXz7oK7l+m7PfEuaGsf9YpOcR"
// "koGJ/TluQLxNzUNQnQJBAImwr/yYFenIx3HQ6UX/fCt6qpGDv0VfOLyR64MNeegx"
// "o7DhNxHbFkIGzk4lKhMKcHKDrawZbdJtS9ie2geSwVQ="
// "-----END RSA PRIVATE KEY-----";
//
//const char* szPemPubKey =
// "-----BEGIN RSA PUBLIC KEY-----"
// "MIGJAoGBAJ/pgAk5IFg+97WOlgPOr7D77xhWgBMj9gKL9EplpCT6XZl+hRCDSqti"
// "t+TN6g5r+p3lUuNNO8cSDBeeUNcx+j69KDGixTEM5lcxMGokY5WK/krZAG+TwDXC"
// "LiTy26j/s5bJrb0e9x9q9STdhdpXZgV7xXqyxpmM1xVaYN2Oo2RfAgMBAAE="
// "-----END RSA PUBLIC KEY-----";
//
//const char* szDataToSign = "Data to be signed by the private key";
//
//
//
//
//
//int main(int argc, char* argv[])
//{
// DWORD dwBufferLen = 0, cbKeyBlob = 0, cbSignature = 0,i;
// LPBYTE pbBuffer = NULL, pbKeyBlob = NULL, pbSignature = NULL;
// HCRYPTPROV hProv = NULL;
// HCRYPTKEY hKey = NULL;
// HCRYPTHASH hHash = NULL;
//
// if (!CryptStringToBinaryA(szPemPrivKey, 0, CRYPT_STRING_BASE64HEADER, NULL, &dwBufferLen, NULL, NULL))
// {
// printf("Failed to convert BASE64 private key. Error 0x%.8X\n", GetLastError());
// goto main_exit;
// }
//
// pbBuffer = (LPBYTE) LocalAlloc(0, dwBufferLen);
// if (!CryptStringToBinaryA(szPemPrivKey, 0, CRYPT_STRING_BASE64HEADER, pbBuffer, &dwBufferLen, NULL, NULL))
// {
// printf("Failed to convert BASE64 private key. Error 0x%.8X\n", GetLastError());
// goto main_exit;
// }
//
// if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbBuffer, dwBufferLen, 0, NULL, NULL, &cbKeyBlob))
// {
// printf("Failed to parse private key. Error 0x%.8X\n", GetLastError());
// goto main_exit;
// }
//
// pbKeyBlob = (LPBYTE) LocalAlloc(0, cbKeyBlob);
// if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbBuffer, dwBufferLen, 0, NULL, pbKeyBlob, &cbKeyBlob))
// {
// printf("Failed to parse private key. Error 0x%.8X\n", GetLastError());
// goto main_exit;
// }
//
// // Create a temporary and volatile CSP context in order to import
// // the key and use for signing
// if (!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
// {
// printf("CryptAcquireContext failed with error 0x%.8X\n", GetLastError());
// goto main_exit;
// }
//
// if (!CryptImportKey(hProv, pbKeyBlob, cbKeyBlob, NULL, 0, &hKey))
// {
// printf("CryptImportKey for private key failed with error 0x%.8X\n", GetLastError());
// goto main_exit;
// }
//
// // Hash the data
// if (!CryptCreateHash(hProv, CALG_SHA1, NULL, 0, &hHash))
// {
// printf("CryptCreateHash failed with error 0x%.8X\n", GetLastError());
// goto main_exit;
// }
//
// if (!CryptHashData(hHash, (LPCBYTE) szDataToSign, strlen(szDataToSign), 0))
// {
// printf("CryptHashData failed with error 0x%.8X\n", GetLastError());
// goto main_exit;
// }
//
// // Sign the hash using our imported key
// if (!CryptSignHash(hHash, AT_KEYEXCHANGE, NULL, 0, NULL, &cbSignature))
// {
// printf("CryptSignHash failed with error 0x%.8X\n", GetLastError());
// goto main_exit;
// }
//
// pbSignature = (LPBYTE) LocalAlloc(0, cbSignature);
// if (!CryptSignHash(hHash, AT_KEYEXCHANGE, NULL, 0, pbSignature, &cbSignature))
// {
// printf("CryptSignHash failed with error 0x%.8X\n", GetLastError());
// goto main_exit;
// }
//
// printf("Signature = ");
// for (i = 0; i < cbSignature; i++)
// {
// printf("%.2X", pbSignature[i]);
// }
// printf("\n\n");
//
// /***************************************************
// * Import the public key and verify the signature
// ***************************************************/
//
// if (!CryptStringToBinaryA(szPemPubKey, 0, CRYPT_STRING_BASE64HEADER, NULL, &dwBufferLen, NULL, NULL))
// {
// printf("Failed to convert BASE64 public key. Error 0x%.8X\n", GetLastError());
// goto main_exit;
// }
//
// LocalFree(pbBuffer);
// pbBuffer = (LPBYTE) LocalAlloc(0, dwBufferLen);
// if (!CryptStringToBinaryA(szPemPubKey, 0, CRYPT_STRING_BASE64HEADER, pbBuffer, &dwBufferLen, NULL, NULL))
// {
// printf("Failed to convert BASE64 public key. Error 0x%.8X\n", GetLastError());
// goto main_exit;
// }
//
// if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, pbBuffer, dwBufferLen, 0, NULL, NULL, &cbKeyBlob))
// {
// printf("Failed to parse public key. Error 0x%.8X\n", GetLastError());
// goto main_exit;
// }
//
// LocalFree(pbKeyBlob);
// pbKeyBlob = (LPBYTE) LocalAlloc(0, cbKeyBlob);
// if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, pbBuffer, dwBufferLen, 0, NULL, pbKeyBlob, &cbKeyBlob))
// {
// printf("Failed to parse public key. Error 0x%.8X\n", GetLastError());
// goto main_exit;
// }
//
// CryptDestroyHash(hHash);
// CryptDestroyKey(hKey);
// CryptReleaseContext(hProv, 0);
//
// if (!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
// {
// printf("CryptAcquireContext failed with error 0x%.8X\n", GetLastError());
// goto main_exit;
// }
//
// if (!CryptImportKey(hProv, pbKeyBlob, cbKeyBlob, NULL, 0, &hKey))
// {
// printf("CryptImportKey for public key failed with error 0x%.8X\n", GetLastError());
// goto main_exit;
// }
//
// // Hash the data
// if (!CryptCreateHash(hProv, CALG_SHA1, NULL, 0, &hHash))
// {
// printf("CryptCreateHash failed with error 0x%.8X\n", GetLastError());
// goto main_exit;
// }
//
// if (!CryptHashData(hHash, (LPCBYTE) szDataToSign, strlen(szDataToSign), 0))
// {
// printf("CryptHashData failed with error 0x%.8X\n", GetLastError());
// goto main_exit;
// }
//
// // Sign the hash using our imported key
// if (!CryptVerifySignature(hHash, pbSignature, cbSignature, hKey, NULL, 0))
// {
// printf("Signature verification failed with error 0x%.8X\n", GetLastError());
// goto main_exit;
// }
//
// printf("Signature verified successfully!\n\n");
//
//main_exit:
// if (pbBuffer) LocalFree(pbBuffer);
// if (pbKeyBlob) LocalFree(pbKeyBlob);
// if (pbSignature) LocalFree(pbSignature);
// if (hHash) CryptDestroyHash(hHash);
// if (hKey) CryptDestroyKey(hKey);
// if (hProv) CryptReleaseContext(hProv, 0);
//
// system("pause");
// return 0;
//}
#include <stdio.h>
#include <string>
//openssl
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/sha.h>
#include <openssl/crypto.h>
#pragma comment(lib, "libcrypto.lib")
#pragma comment(lib, "libssl.lib")
#pragma comment(lib, "ws2_32.lib")
int main()
{
FILE *fp = NULL;
RSA *pubRsa = NULL;
unsigned char buf[128] = { 0 };
int nOutLen = sizeof(buf);
char * p_KeyPath = "D:/PublicKey.pem";
printf("PublicKeyPath[%s]\n", p_KeyPath);
/* 打开密钥文件 */
if (NULL == (fp = fopen(p_KeyPath, "r")))
{
printf("fopen[%s] \n", p_KeyPath);
return NULL;
}
/* 获取公钥 */
if (NULL == (pubRsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL)))
{
printf("PEM_read_RSA_PUBKEY error\n");
fclose(fp);
return NULL;
}
fclose(fp);
char * message = "BFEBFBFF000906E9:L1HF73P055S";
unsigned char md[SHA256_DIGEST_LENGTH];
SHA256((unsigned char *)message, strlen(message), md);
int nRet = RSA_verify(NID_sha256, md, SHA256_DIGEST_LENGTH, buf, nOutLen, pubRsa);
if (nRet != 1)
{
printf("RSA_verify err !!! \n");
}
printf("RSA_verify Success !!! \n");
system("pause");
return 0;
}
The wincrypt method is commented. and the openssl method is presented. you can toggle the comment to reproduce both results. PS: I don't have the public pem directly. I converted the xml file to pem by BouncyCastle.Crypto API in C#. The original xml public key is
<RSAKeyValue><Modulus>wz1A5Neh5XiRPa+FDdqpVxQGpNSoz4GWj4D4iYC1w4Lf8quQ73iz8iHz9x+U/Ep+EJtdQyBCOveT0999uQuvH6/GDIAX9QXr5+uE7Koxbh680hCMqDE7DP3VR2UVzluVLVVqfdSQZIFad5+xKAnpgVHBWFxPgRjijHSDHnHnEVU=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>