#pragma comment(lib, "crypt32.lib")
#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>
#include <iostream>
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
//this is keylength bit shifted, here we have keylength of 1024bits hence 1024 << 16;
#define KEYLENGTH 0x04000000
using namespace std;
int main()
{
DWORD dwFlags = 0;
HCRYPTPROV m_hProv;
PBYTE pbKeyBlob;
DWORD dwKeyBlobLen;
DWORD m_dwBlockSize;
DWORD dwLen;
DWORD m_dwKeySizeInBits = 50;
HCRYPTKEY hPubKey;
DWORD dwBlockSize = 250;
// Ok this initialises the Crypto stuff, here im using the enhanced provider
if (!CryptAcquireContext(&m_hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, dwFlags))
{
// If cant get default provider the following creates one
DWORD err = GetLastError();
INT iReturn = 0;
LPSTR pszContainerName = NULL;
DWORD cbContainerName = 0;
if(GetLastError() != NTE_BAD_KEYSET)
{
printf("Error opening default key container!\r\n");
}
// Create default key container.
if(!CryptAcquireContext(&m_hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
{
printf("Error creating default key container!\n");
}
// Get size of the name of the default key container name.
if(CryptGetProvParam(m_hProv, PP_CONTAINER, NULL, &cbContainerName, 0))
{
// Allocate buffer to receive default key container name.
pszContainerName = (char *)malloc(cbContainerName);
if(pszContainerName)
{
// Get name of default key container name.
if(!CryptGetProvParam(m_hProv, PP_CONTAINER, (BYTE *)pszContainerName, &cbContainerName, 0))
{
// Error getting default key container name.
pszContainerName[0] = 0;
}
}
}
// printf("Create key container '%s'\n", pszContainerName ? pszContainerName : "");
// Free container name buffer (if created)
if(pszContainerName)
{
free(pszContainerName);
}
}
BOOL bResult = CryptGenKey(m_hProv, CALG_RSA_KEYX, KEYLENGTH | CRYPT_EXPORTABLE, &hPubKey);
if(!CryptExportKey(hPubKey, NULL, PUBLICKEYBLOB, 0, NULL, &dwKeyBlobLen))
{
//deal with errors (wrong types, not set to be exportable etc)
}
if((pbKeyBlob = (unsigned char *) malloc(dwKeyBlobLen)) == NULL)
{
//alloc prob
}
// Export session key into a simple key blob.
if(!CryptExportKey(hPubKey, NULL, PUBLICKEYBLOB, 0, pbKeyBlob, &dwKeyBlobLen))
{
// any probs
}
// Now this bit u would do on your client (after it arrived), you would init the client
if(CryptImportKey(m_hProv,pbKeyBlob,dwKeyBlobLen,0,CRYPT_EXPORTABLE,&hPubKey) )
{
// now we get the block length as we can only encrypt up to that size, per pass
// this can be done as soon as u generate the key u dont need to import/export 2 get it
if(CryptGetKeyParam(hPubKey, KP_BLOCKLEN, (LPBYTE)&m_dwKeySizeInBits, &dwLen,0))
{
m_dwBlockSize = m_dwKeySizeInBits/8;
}
}
// now with RSA enc, it needs 11 bytes of padding at end, so this reduces the length further
DWORD tempLen=m_dwBlockSize-11;
BYTE* tempBuff = (BYTE*)"This is my datarffffffffffffffffffffffffffffffffffffgfhtrfhrthrthrthrthrthtrhrthrthrthrthrh";
cout << *tempBuff << endl;
if(!CryptEncrypt(hPubKey, NULL, FALSE, 0, tempBuff, &tempLen, dwBlockSize))
{
cout << GetLastError() << endl;
}
cout << endl << endl << endl;
cout << "[encrypted buffer]: " << tempBuff;
//now try and decrypt it, again we get length back of orig data
if(!CryptDecrypt(hPubKey, NULL, FALSE, 0, tempBuff, &tempLen))
{
// if anything goes wrong
}
// obviously we need to cleanup nicely
CryptDestroyKey(hPubKey);
CryptReleaseContext(m_hProv,0);
}
if(!CryptEncrypt(hPubKey, NULL, FALSE, 0, tempBuff, &tempLen, dwBlockSize))
is where it fails...