Skip to content

Instantly share code, notes, and snippets.

@soxfmr
Created November 25, 2017 10:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save soxfmr/21606281118227abc63ce98f865d511e to your computer and use it in GitHub Desktop.
Save soxfmr/21606281118227abc63ce98f865d511e to your computer and use it in GitHub Desktop.
An example of using PEM encoded RSA private keys with CAPI
/*
* 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>
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);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment