#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...

Recommended Answers

All 2 Replies

bump for help

The MSDN is very clear: the data buffer is an in/out parameter, that is

The plaintext in this buffer is overwritten with the ciphertext created by this function.

Your pointer is pointing to a read-only string literal. Besides, keep in mind that a ciphertext may take more space than the plaintext. It is always a good idea to call CryptEncrypt twice, first with a null data pointer to figure out how much space is required, then do an actual encryption with the buffer large enough.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.