#include "../CryptoHelper.h"
|
// The RSA public-key key exchange algorithm
|
#define ENCRYPT_ALGORITHM CALG_RSA_SIGN
|
// The high order WORD 0x0200 (decimal 512)
|
// determines the key length in bits.
|
#define KEYLENGTH 0x02000000
|
//--------------------------------------------------------------------
|
// The constructor initializes the member variables
|
// to NULL.
|
//--------------------------------------------------------------------
|
CryptoHelper::CryptoHelper()
|
{
|
m_hCryptProv = NULL;
|
m_hCryptKey = NULL;
|
}
|
//--------------------------------------------------------------------
|
// The destructor releases the handles acquired
|
// when an object goes out of scope.
|
//--------------------------------------------------------------------
|
CryptoHelper::~CryptoHelper()
|
{
|
if (m_hCryptProv)
|
{
|
CryptReleaseContext(m_hCryptProv,0);
|
m_hCryptProv = NULL;
|
}
|
if (m_hCryptKey)
|
m_hCryptKey = NULL;
|
}
|
|
//--------------------------------------------------------------------
|
// This method calls the CryptAcquireContext function
|
// to get a handle to a key container owned by the the
|
// Microsoft Enhanced Cryptographic Provider.
|
//--------------------------------------------------------------------
|
HRESULT CryptoHelper::AcquireContext(LPCTSTR wszContainerName)
|
{
|
HRESULT hr = S_OK;
|
DWORD dwErrCode;
|
// Release a previously acquired handle to the key container.
|
if (m_hCryptProv != NULL)
|
{
|
CryptReleaseContext(m_hCryptProv,0);
|
m_hCryptProv = NULL;
|
}
|
// Release a previously acquired handle to key-pair.
|
if (m_hCryptKey != NULL)
|
m_hCryptKey = NULL;
|
// Attempt to acquire a context and a key container.
|
// The context will use Microsoft Enhanced Cryptographic
|
// Provider for the RSA_FULL provider type.
|
if(!CryptAcquireContext(&m_hCryptProv,
|
wszContainerName,
|
MS_ENHANCED_PROV,
|
PROV_RSA_FULL,
|
0))
|
{
|
// An error occurred in acquiring the context. This could mean
|
// that the key container requested does not exist. In this case,
|
// the function can be called again to attempt to create a new key
|
// container.
|
if (GetLastError() == NTE_BAD_KEYSET)
|
{
|
if(!CryptAcquireContext(&m_hCryptProv,
|
wszContainerName,
|
MS_ENHANCED_PROV, PROV_RSA_FULL,
|
CRYPT_NEWKEYSET))
|
{
|
dwErrCode = GetLastError();
|
return HRESULT_FROM_WIN32(dwErrCode);
|
}
|
}
|
else
|
{
|
dwErrCode = GetLastError();
|
return HRESULT_FROM_WIN32(dwErrCode);
|
}
|
}
|
return hr;
|
}
|
//--------------------------------------------------------------------
|
|
// This method calls the CryptGenKey function to get a handle to an
|
|
// exportable key-pair. The key-pair is generated with the RSA public-key
|
// key exchange algorithm using Microsoft Enhanced Cryptographic Provider.
|
//--------------------------------------------------------------------
|
HRESULT CryptoHelper::GenerateKeyPair()
|
{
|
HRESULT hr = S_OK;
|
DWORD dwErrCode;
|
// If the handle to key container is NULL, fail.
|
if (m_hCryptProv == NULL)
|
return E_FAIL;
|
// Release a previously acquired handle to key-pair.
|
if (m_hCryptKey)
|
m_hCryptKey = NULL;
|
// Call the CryptGenKey method to get a handle
|
// to a new exportable key-pair.
|
if(!CryptGenKey(m_hCryptProv,
|
ENCRYPT_ALGORITHM,
|
KEYLENGTH | CRYPT_EXPORTABLE,
|
&m_hCryptKey))
|
{
|
dwErrCode = GetLastError();
|
return HRESULT_FROM_WIN32(dwErrCode);
|
}
|
return hr;
|
}
|
//--------------------------------------------------------------------
|
// This method calls the CryptExportKey function to get the Public key
|
// in a byte array. The byte array is allocated on the heap and the size
|
// of this is returned to the caller. The caller is responsible for releasing // this memory using a delete call.
|
//--------------------------------------------------------------------
|
HRESULT CryptoHelper::ExportPublicKey(BYTE **ppPublicKey, DWORD &cbKeySize)
|
{
|
HRESULT hr = S_OK;
|
DWORD dwErrCode;
|
DWORD dwBlobLen;
|
BYTE *pbKeyBlob = NULL;
|
// If the handle to key container is NULL, fail.
|
if (m_hCryptKey == NULL)
|
return E_FAIL;
|
// This call here determines the length of the key
|
// blob.
|
if(!CryptExportKey(
|
m_hCryptKey,
|
NULL,
|
PUBLICKEYBLOB,
|
0,
|
NULL,
|
&dwBlobLen))
|
{
|
dwErrCode = GetLastError();
|
return HRESULT_FROM_WIN32(dwErrCode);
|
}
|
// Allocate memory for the pbKeyBlob.
|
if((pbKeyBlob = new BYTE[dwBlobLen]) == NULL)
|
{
|
return E_OUTOFMEMORY;
|
}
|
// Do the actual exporting into the key BLOB.
|
if(!CryptExportKey(
|
m_hCryptKey,
|
NULL,
|
PUBLICKEYBLOB,
|
0,
|
pbKeyBlob,
|
&dwBlobLen))
|
{
|
delete pbKeyBlob;
|
dwErrCode = GetLastError();
|
return HRESULT_FROM_WIN32(dwErrCode);
|
}
|
else
|
{
|
*ppPublicKey = pbKeyBlob;
|
cbKeySize = dwBlobLen;
|
}
|
return hr;
|
}
|
//--------------------------------------------------------------------
|
// This method calls the CryptExportKey function to get the Private key
|
// in a byte array. The byte array is allocated on the heap and the size
|
// of this is returned to the caller. The caller is responsible for releasing // this memory using a delete call.
|
//--------------------------------------------------------------------
|
HRESULT CryptoHelper::ExportPrivateKey(BYTE **ppPrivateKey, DWORD &cbKeySize)
|
{
|
HRESULT hr = S_OK;
|
DWORD dwErrCode;
|
DWORD dwBlobLen;
|
BYTE *pbKeyBlob;
|
// If the handle to key container is NULL, fail.
|
if (m_hCryptKey == NULL)
|
return E_FAIL;
|
// This call here determines the length of the key
|
// blob.
|
if(!CryptExportKey(
|
m_hCryptKey,
|
NULL,
|
PRIVATEKEYBLOB,
|
0,
|
NULL,
|
&dwBlobLen))
|
{
|
dwErrCode = GetLastError();
|
return HRESULT_FROM_WIN32(dwErrCode);
|
}
|
// Allocate memory for the pbKeyBlob.
|
if((pbKeyBlob = new BYTE[dwBlobLen]) == NULL)
|
{
|
return E_OUTOFMEMORY;
|
}
|
|
// Do the actual exporting into the key BLOB.
|
if(!CryptExportKey(
|
m_hCryptKey,
|
NULL,
|
PRIVATEKEYBLOB,
|
0,
|
pbKeyBlob,
|
&dwBlobLen))
|
{
|
delete pbKeyBlob;
|
dwErrCode = GetLastError();
|
return HRESULT_FROM_WIN32(dwErrCode);
|
}
|
else
|
{
|
*ppPrivateKey = pbKeyBlob;
|
cbKeySize = dwBlobLen;
|
}
|
return hr;
|
}
|