Code:
#include <iostream>
#include <windows.h>
#include <wincrypt.h>
#include <fstream>
#include <conio.h>
#include <string>
#include <cassert>
using namespace std;
void crypto();
int main()
{
crypto();
return 0;
}
void crypto()
{
HCRYPTPROV CSPhandle;
HCRYPTPROV CSPhandlePass;
HCRYPTKEY keyHandle;
HCRYPTKEY keyExpHandle;
HCRYPTKEY keyPassHandle;
HCRYPTHASH hashPassHandle;
// CHAR szContainerName;
LPCSTR ContainerName = "keyContainer";
CHAR ssPassword[512] = "password";
DWORD dwLength=strlen(ssPassword);
DWORD* blobSize;
BYTE* expData;
ofstream outfile;
string filename = "keys.dat";
int returnCode = 0;
DWORD errorCode = 0;
//creating a container for the public/private key pair:
if (returnCode = CryptAcquireContext(
&CSPhandle,
ContainerName,
NULL,
PROV_RSA_FULL,
0))
{
errorCode = GetLastError();
cout<<"An existing key container has been opened. " <<returnCode <<" " <<errorCode <<endl;
}
else
{
returnCode = CryptAcquireContext(
&CSPhandle,
ContainerName,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET);
errorCode = GetLastError();
cout<<"A new key container has been created. " <<returnCode <<" " <<errorCode <<endl;
}
//generating the public/private key pair:
returnCode = CryptGenKey(
CSPhandle,
AT_SIGNATURE,
(1024U<<16) | CRYPT_EXPORTABLE,
&keyHandle);
errorCode = GetLastError();
cout<<"Created a signature key pair. " <<returnCode <<" " <<errorCode <<endl;
//creating a container for the password key:
if (returnCode = CryptAcquireContext(
&CSPhandlePass,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET))
{
errorCode = GetLastError();
cout<<"A new key container has been created for the password hash. " <<returnCode <<" " <<errorCode <<endl;
}
else
{
returnCode = CryptAcquireContext(
&CSPhandlePass,
NULL,
NULL,
PROV_RSA_FULL,
0);
errorCode = GetLastError();
cout<<"An existing container has been opened for the password hash. " <<returnCode <<" " <<errorCode <<endl;
}
//creating hash object for hashing the password:
returnCode = CryptCreateHash(
CSPhandlePass,
CALG_MD5,
0,
0,
&hashPassHandle);
errorCode = GetLastError();
cout<<"An empty hash object has been created. " <<returnCode <<" " <<errorCode <<endl;
//hashing the password string:
returnCode = CryptHashData(
hashPassHandle,
(BYTE *)ssPassword,
dwLength,
0);
errorCode = GetLastError();
cout<<"Password hashed. " <<returnCode <<" " <<errorCode <<endl;
//creating a key based on the password:
returnCode = CryptDeriveKey(
CSPhandlePass,
CALG_RC2,
hashPassHandle,
0,
&keyPassHandle);
errorCode = GetLastError();
cout<<"Password key created. " <<returnCode <<" " <<errorCode <<endl;
//setting the export key to the key derived from password:
keyExpHandle = keyPassHandle;
//exporting the encrypted public/private key pair:
//getting the size of the data:
blobSize = new DWORD;
*blobSize = 0;
returnCode = CryptExportKey(
keyHandle,
0,
PRIVATEKEYBLOB,
0,
NULL,
blobSize);
errorCode = GetLastError();
cout<<"Return code / error code for sizing CEK call: " <<returnCode <<" " <<errorCode <<endl;
/* cout<<"Error codes:\n";
cout<<ERROR_INVALID_HANDLE <<endl;
cout<<ERROR_INVALID_PARAMETER <<endl;
cout<<ERROR_MORE_DATA <<endl;
cout<<(unsigned int)NTE_BAD_FLAGS <<endl;
cout<<(unsigned int)NTE_BAD_KEY <<endl;
cout<<(unsigned int)NTE_BAD_KEY_STATE <<endl;
cout<<(unsigned int)NTE_BAD_PUBLIC_KEY <<endl;
cout<<(unsigned int)NTE_BAD_TYPE <<endl;
cout<<(unsigned int)NTE_BAD_UID <<endl;
cout<<(unsigned int)NTE_NO_KEY <<endl;
*/
expData = new BYTE[*blobSize];
//exporting the data:
returnCode = CryptExportKey(
keyHandle,
0,
PRIVATEKEYBLOB,
NULL,
expData,
blobSize);
errorCode = GetLastError();
cout<<"Keys exported to expData. " <<returnCode <<" " <<errorCode <<endl;
//writing encrypted keys to file:
outfile.open(filename.c_str());
assert(outfile);
outfile<<expData;
cout<<expData <<endl;
outfile.close();
//cleaning up handles, etc.
delete blobSize;
delete expData;
CryptDestroyKey(keyHandle);
CryptDestroyKey(keyExpHandle);
CryptDestroyKey(keyPassHandle);
CryptDestroyHash(hashPassHandle);
CryptReleaseContext(CSPhandle, 0);
CryptReleaseContext(CSPhandlePass, 0);
}