Freigeben über


How to generate key pairs, encrypt and decrypt data with CryptoAPI

Hi, welcome back,

Today I'm posting a sample I did some time ago which shows how to generate key pairs, encrypt and decrypt data with C++ and CryptoAPI. The comments in the code should be self-explanatory.

<SAMPLE>

 // INCLUDES
#include "stdio.h"
#include "conio.h"
#include "windows.h"
#include "wincrypt.h"
#include "tchar.h"

// FUNCTIONS
int Keys(_TCHAR* strPublicKeyFile, _TCHAR* strPrivateKeyFile);
int Encrypt(_TCHAR* strPublicKeyFile, _TCHAR* strPlainFile, _TCHAR* strEncryptedFile);
int Decrypt(_TCHAR* strPrivateKeyFile, _TCHAR* strEncryptedFile, _TCHAR* strPlainFile);

// Main
int _tmain(int argc, _TCHAR* argv[])
{
      int iResult = 0;

      if ((argc == 4) && (_tcscmp(argv[1], _T("k")) == 0))
      {
            // Generate a new key pair
            iResult = Keys(argv[2], argv[3]);
      }
      else if ((argc == 5) && (_tcscmp(argv[1], _T("e")) == 0))
      {
            // Encrypt
            iResult = Encrypt(argv[2], argv[3], argv[4]);
      }
      else if ((argc == 5) && (_tcscmp(argv[1], _T("d"))== 0))
      {
            // Decrypt
            iResult = Decrypt(argv[2], argv[3], argv[4]);
      }
      else 
      {
            // Show usage
            _tprintf(_T("Usage:\n"));
            _tprintf(_T("   - New key pair: EncryptDecrypt k public_key_file private_key_file\n"));
            _tprintf(_T("   - Encrypt:      EncryptDecrypt e public_key_file plain_file encrypted_file\n"));
            _tprintf(_T("   - Decrypt:      EncryptDecrypt d private_key_file encrypted_file plain_file\n"));
            iResult = 1;
      }

      _tprintf(_T("\n<< Press any key to continue >>\n"));
      _getch();
      return iResult;
}
// End of Main

// Keys
int Keys(_TCHAR* strPublicKeyFile, _TCHAR* strPrivateKeyFile)
{
      // Variables
      HCRYPTPROV hCryptProv = NULL;
      HCRYPTKEY hKey = NULL;
      DWORD dwPublicKeyLen = 0;
      DWORD dwPrivateKeyLen = 0;
      BYTE* pbPublicKey = NULL;
      BYTE* pbPrivateKey = NULL;
      HANDLE hPublicKeyFile = NULL;
      HANDLE hPrivateKeyFile = NULL;
      DWORD lpNumberOfBytesWritten = 0;

      __try 
      {
            // Acquire access to key container
            _tprintf(_T("CryptAcquireContext...\n"));
            if (!CryptAcquireContext(&hCryptProv, _T("AlejaCMa.EncryptDecrypt"), NULL, PROV_RSA_FULL, 0)) 
            {
                  // Error
                  _tprintf(_T("CryptAcquireContext error 0x%x\n"), GetLastError());

                  // Try to create a new key container
                  if (!CryptAcquireContext(&hCryptProv, _T("AlejaCMa.EncryptDecrypt"), NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
                  {
                        // Error
                        _tprintf(_T("CryptAcquireContext error 0x%x\n"), GetLastError());
                        return 1;
                  }
            }

            // Generate new key pair
            _tprintf(_T("CryptGenKey...\n"));
            if (!CryptGenKey(hCryptProv, AT_KEYEXCHANGE,  CRYPT_ARCHIVABLE, &hKey))
            {
                  // Error
                  _tprintf(_T("CryptGenKey error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Get public key size
            _tprintf(_T("CryptExportKey...\n"));
            if (!CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, NULL, &dwPublicKeyLen))
            {
                  // Error
                  _tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Create a buffer for the public key
            _tprintf(_T("malloc...\n"));
            if (!(pbPublicKey = (BYTE *)malloc(dwPublicKeyLen)))
            {
                  // Error
                  _tprintf(_T("malloc error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Get public key
            _tprintf(_T("CryptExportKey...\n"));
            if (!CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, pbPublicKey, &dwPublicKeyLen))
            {
                  // Error
                  _tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Get private key size
            _tprintf(_T("CryptExportKey...\n"));
            if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwPrivateKeyLen))
            {
                  // Error
                  _tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Create a buffer for the private key
            _tprintf(_T("malloc...\n"));
            if (!(pbPrivateKey = (BYTE *)malloc(dwPrivateKeyLen)))
            {
                  // Error
                  _tprintf(_T("malloc error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Get private key
            _tprintf(_T("CryptExportKey...\n"));
            if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, pbPrivateKey, &dwPrivateKeyLen))
            {
                  // Error
                  _tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Create a file to save the public key
            _tprintf(_T("CreateFile...\n"));
            if ((hPublicKeyFile = CreateFile(
            strPublicKeyFile,
            GENERIC_WRITE,
            0,
            NULL,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL,
            NULL
            )) == INVALID_HANDLE_VALUE)
            {
                  // Error
                  _tprintf(_T("CreateFile error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Write the public key to the file
            _tprintf(_T("WriteFile...\n"));
            if (!WriteFile(
                  hPublicKeyFile, 
                  (LPCVOID)pbPublicKey, 
                  dwPublicKeyLen, 
                  &lpNumberOfBytesWritten, 
                  NULL
            )) 
            {
                  // Error
                  _tprintf(_T("WriteFile error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Create a file to save the private key
            _tprintf(_T("CreateFile...\n"));
            if ((hPrivateKeyFile = CreateFile(
            strPrivateKeyFile,
            GENERIC_WRITE,
            0,
            NULL,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL,
            NULL
            )) == INVALID_HANDLE_VALUE)
            {
                  // Error
                  _tprintf(_T("CreateFile error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Write the private key to the file
            _tprintf(_T("WriteFile...\n"));
            if (!WriteFile(
                  hPrivateKeyFile, 
                  (LPCVOID)pbPrivateKey, 
                  dwPrivateKeyLen, 
                  &lpNumberOfBytesWritten, 
                  NULL
            )) 
            {
                  // Error
                  _tprintf(_T("WriteFile error 0x%x\n"), GetLastError());
                  return 1;
            }

            return 0;
      }
      __finally
      {
            // Clean up       
            if (!pbPublicKey) {
                  _tprintf(_T("free...\n"));
                  free(pbPublicKey);
            }           
            if (!pbPrivateKey) {
                  _tprintf(_T("free...\n"));
                  free(pbPrivateKey);
            }           
            if (hPublicKeyFile) {
                  _tprintf(_T("CloseHandle...\n"));
                  CloseHandle(hPublicKeyFile);
            }           
            if (hPrivateKeyFile) {
                  _tprintf(_T("CloseHandle...\n"));
                  CloseHandle(hPrivateKeyFile);
            }
            if (hKey) {
                  _tprintf(_T("CryptDestroyKey...\n"));
                  CryptDestroyKey(hKey);
            }           
            if (hCryptProv) {
                  _tprintf(_T("CryptReleaseContext...\n"));
                  CryptReleaseContext(hCryptProv, 0);
            }
      }
}
// End of Keys

// Encrypt
int Encrypt(_TCHAR* strPublicKeyFile, _TCHAR* strPlainFile, _TCHAR* strEncryptedFile)
{
      // Variables
      HCRYPTPROV hCryptProv = NULL;
      HCRYPTKEY hKey = NULL;
      DWORD dwPublicKeyLen = 0;
      DWORD dwDataLen = 0;
      DWORD dwEncryptedLen = 0;
      BYTE* pbPublicKey = NULL;
      BYTE* pbData = NULL;
      HANDLE hPublicKeyFile = NULL;
      HANDLE hEncryptedFile = NULL;
      HANDLE hPlainFile = NULL;
      DWORD lpNumberOfBytesWritten = 0;

      __try
      {
            // Acquire access to key container
            _tprintf(_T("CryptAcquireContext...\n"));
            if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) 
            {
                  // Error
                  _tprintf(_T("CryptAcquireContext error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Open public key file
            _tprintf(_T("CreateFile...\n"));
            if ((hPublicKeyFile = CreateFile(
            strPublicKeyFile,
            GENERIC_READ,
            FILE_SHARE_READ,
            NULL,
            OPEN_EXISTING,
            FILE_FLAG_SEQUENTIAL_SCAN,
            NULL
            )) == INVALID_HANDLE_VALUE)
            {
                  // Error
                  _tprintf(_T("CreateFile error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Get file size
            _tprintf(_T("GetFileSize...\n"));
            if ((dwPublicKeyLen = GetFileSize(hPublicKeyFile, NULL)) == INVALID_FILE_SIZE)
            {
                  // Error
                  _tprintf(_T("GetFileSize error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Create a buffer for the public key
            _tprintf(_T("malloc...\n"));
            if (!(pbPublicKey = (BYTE *)malloc(dwPublicKeyLen)))
            {
                  // Error
                  _tprintf(_T("malloc error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Read public key
            _tprintf(_T("ReadFile...\n"));
            if (!ReadFile(hPublicKeyFile, pbPublicKey, dwPublicKeyLen, &dwPublicKeyLen, NULL))
            {
                  // Error
                  _tprintf(_T("ReadFile error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Import public key
            _tprintf(_T("CryptImportKey...\n"));
            if (!CryptImportKey(hCryptProv, pbPublicKey, dwPublicKeyLen, 0, 0, &hKey))
            {
                  // Error
                  _tprintf(_T("CryptImportKey error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Open plain text file
            _tprintf(_T("CreateFile...\n"));
            if ((hPlainFile = CreateFile(
            strPlainFile,
            GENERIC_READ,
            FILE_SHARE_READ,
            NULL,
            OPEN_EXISTING,
            FILE_FLAG_SEQUENTIAL_SCAN,
            NULL
            )) == INVALID_HANDLE_VALUE)
            {
                  // Error
                  _tprintf(_T("CreateFile error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Get file size
            _tprintf(_T("GetFileSize...\n"));
            if ((dwDataLen = GetFileSize(hPlainFile, NULL)) == INVALID_FILE_SIZE)
            {
                  // Error
                  _tprintf(_T("GetFileSize error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Create a buffer for the plain text
            _tprintf(_T("malloc...\n"));
            if (!(pbData = (BYTE *)malloc(dwDataLen)))
            {
                  // Error
                  _tprintf(_T("malloc error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Read plain text
            _tprintf(_T("ReadFile...\n"));
            if (!ReadFile(hPlainFile, pbData, dwDataLen, &dwDataLen, NULL))
            {
                  // Error
                  _tprintf(_T("ReadFile error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Get lenght for encrypted data
            if (!CryptEncrypt(hKey, NULL, TRUE, 0, NULL, &dwEncryptedLen, 0))
            {
                  // Error
                  _tprintf(_T("CryptEncrypt error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Create a buffer for encrypted data
            _tprintf(_T("malloc...\n"));
            if (!(pbData = (BYTE *)realloc(pbData, dwEncryptedLen)))
            {
                  // Error
                  _tprintf(_T("malloc error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Encrypt data
            if (!CryptEncrypt(hKey, NULL, TRUE, 0, pbData, &dwDataLen, dwEncryptedLen))
            {
                  // Error
                  _tprintf(_T("CryptEncrypt error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Create a file to save the encrypted data
            _tprintf(_T("CreateFile...\n"));
            if ((hEncryptedFile = CreateFile(
            strEncryptedFile,
            GENERIC_WRITE,
            0,
            NULL,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL,
            NULL
            )) == INVALID_HANDLE_VALUE)
            {
                  // Error
                  _tprintf(_T("CreateFile error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Write the public key to the file
            _tprintf(_T("WriteFile...\n"));
            if (!WriteFile(
                  hEncryptedFile, 
                  (LPCVOID)pbData, 
                  dwDataLen, 
                  &lpNumberOfBytesWritten, 
                  NULL
            )) 
            {
                  // Error
                  _tprintf(_T("WriteFile error 0x%x\n"), GetLastError());
                  return 1;
            }

            return 0;
      }
      __finally
      {
            // Clean up
            if (!pbPublicKey) {
                  _tprintf(_T("free...\n"));
                  free(pbPublicKey);
            }
            if (!pbData) {
                  _tprintf(_T("free...\n"));
                  free(pbData);
            }
            if (hPublicKeyFile) {
                  _tprintf(_T("CloseHandle...\n"));
                  CloseHandle(hPublicKeyFile);
            }
            if (hPlainFile) {
                  _tprintf(_T("CloseHandle...\n"));
                  CloseHandle(hPlainFile);
            }
            if (hEncryptedFile) {
                  _tprintf(_T("CloseHandle...\n"));
                  CloseHandle(hEncryptedFile);
            }
            if (hKey) {
                  _tprintf(_T("CryptDestroyKey...\n"));
                  CryptDestroyKey(hKey);
            }           
            if (hCryptProv) {
                  _tprintf(_T("CryptReleaseContext...\n"));
                  CryptReleaseContext(hCryptProv, 0);
            }
      }
}
// End of Encrypt

// Decrypt
int Decrypt(_TCHAR* strPrivateKeyFile, _TCHAR* strEncryptedFile, _TCHAR* strPlainFile)
{
      // Variables
      HCRYPTPROV hCryptProv = NULL;
      HCRYPTKEY hKey = NULL;
      DWORD dwPrivateKeyLen = 0;
      DWORD dwDataLen = 0;
      BYTE* pbPrivateKey = NULL;
      BYTE* pbData = NULL;
      HANDLE hPrivateKeyFile = NULL;
      HANDLE hEncryptedFile = NULL;
      HANDLE hPlainFile = NULL;
      DWORD lpNumberOfBytesWritten = 0;

      __try 
      {
            // Acquire access to key container
            _tprintf(_T("CryptAcquireContext...\n"));
            if (!CryptAcquireContext(&hCryptProv, _T("AlejaCMa.EncryptDecrypt"), NULL, PROV_RSA_FULL, 0)) 
            {
                  // Error
                  _tprintf(_T("CryptAcquireContext error 0x%x\n"), GetLastError());

                  // Try to create a new key container
                  if (!CryptAcquireContext(&hCryptProv, _T("AlejaCMa.EncryptDecrypt"), NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
                  {
                        // Error
                        _tprintf(_T("CryptAcquireContext error 0x%x\n"), GetLastError());
                        return 1;
                  }
            }

            // Open private key file
            _tprintf(_T("CreateFile...\n"));
            if ((hPrivateKeyFile = CreateFile(
            strPrivateKeyFile,
            GENERIC_READ,
            FILE_SHARE_READ,
            NULL,
            OPEN_EXISTING,
            FILE_FLAG_SEQUENTIAL_SCAN,
            NULL
            )) == INVALID_HANDLE_VALUE)
            {
                  // Error
                  _tprintf(_T("CreateFile error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Get file size
            _tprintf(_T("GetFileSize...\n"));
            if ((dwPrivateKeyLen = GetFileSize(hPrivateKeyFile, NULL)) == INVALID_FILE_SIZE)
            {
                  // Error
                  _tprintf(_T("GetFileSize error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Create a buffer for the private key
            _tprintf(_T("malloc...\n"));
            if (!(pbPrivateKey = (BYTE *)malloc(dwPrivateKeyLen)))
            {
                  // Error
                  _tprintf(_T("malloc error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Read private key
            _tprintf(_T("ReadFile...\n"));
            if (!ReadFile(hPrivateKeyFile, pbPrivateKey, dwPrivateKeyLen, &dwPrivateKeyLen, NULL))
            {
                  // Error
                  _tprintf(_T("ReadFile error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Import private key
            _tprintf(_T("CryptImportKey...\n"));
            if (!CryptImportKey(hCryptProv, pbPrivateKey, dwPrivateKeyLen, 0, 0, &hKey))
            {
                  // Error
                  _tprintf(_T("CryptImportKey error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Open encrypted file
            _tprintf(_T("CreateFile...\n"));
            if ((hEncryptedFile = CreateFile(
            strEncryptedFile,
            GENERIC_READ,
            FILE_SHARE_READ,
            NULL,
            OPEN_EXISTING,
            FILE_FLAG_SEQUENTIAL_SCAN,
            NULL
            )) == INVALID_HANDLE_VALUE)
            {
                  // Error
                  _tprintf(_T("CreateFile error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Get file size
            _tprintf(_T("GetFileSize...\n"));
            if ((dwDataLen = GetFileSize(hEncryptedFile, NULL)) == INVALID_FILE_SIZE)
            {
                  // Error
                  _tprintf(_T("GetFileSize error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Create a buffer for the encrypted data
            _tprintf(_T("malloc...\n"));
            if (!(pbData = (BYTE *)malloc(dwDataLen)))
            {
                  // Error
                  _tprintf(_T("malloc error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Read encrypted data
            _tprintf(_T("ReadFile...\n"));
            if (!ReadFile(hEncryptedFile, pbData, dwDataLen, &dwDataLen, NULL))
            {
                  // Error
                  _tprintf(_T("ReadFile error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Get lenght for plain text
            if (!CryptDecrypt(hKey, NULL, TRUE, 0, pbData, &dwDataLen))
            {
                  // Error
                  _tprintf(_T("CryptDecrypt error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Create a file to save the plain text
            _tprintf(_T("CreateFile...\n"));
            if ((hPlainFile = CreateFile(
            strPlainFile,
            GENERIC_WRITE,
            0,
            NULL,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL,
            NULL
            )) == INVALID_HANDLE_VALUE)
            {
                  // Error
                  _tprintf(_T("CreateFile error 0x%x\n"), GetLastError());
                  return 1;
            }

            // Write the plain text the file
            _tprintf(_T("WriteFile...\n"));
            if (!WriteFile(
                  hPlainFile, 
                  (LPCVOID)pbData, 
                  dwDataLen, 
                  &lpNumberOfBytesWritten, 
                  NULL
            )) 
            {
                  // Error
                  _tprintf(_T("WriteFile error 0x%x\n"), GetLastError());
                  return 1;
            }

            return 0;
      }
      __finally
      {
            // Clean up       
            if (!pbPrivateKey) {
                  _tprintf(_T("free...\n"));
                  free(pbPrivateKey);
            }                       
            if (!pbData) {
                  _tprintf(_T("free...\n"));
                  free(pbData);
            }           
            if (hPrivateKeyFile) {
                  _tprintf(_T("CloseHandle...\n"));
                  CloseHandle(hPrivateKeyFile);
            }
            if (hEncryptedFile) {
                  _tprintf(_T("CloseHandle...\n"));
                  CloseHandle(hEncryptedFile);
            }
            if (hPlainFile) {
                  _tprintf(_T("CloseHandle...\n"));
                  CloseHandle(hPlainFile);
            }
            if (hKey) {
                  _tprintf(_T("CryptDestroyKey...\n"));
                  CryptDestroyKey(hKey);
            }           
            if (hCryptProv) {
                  _tprintf(_T("CryptReleaseContext...\n"));
                  CryptReleaseContext(hCryptProv, 0);
            }
      }
}
// End of Decrypt

</SAMPLE>

 

Take a look to the following article for more info on these APIs: The Cryptography API, or How to Keep a Secret.

 

I hope this helps.

Cheers,

 

Alex (Alejandro Campos Magencio)

Comments

  • Anonymous
    April 22, 2008
    I am working in a concern in chennai,india.i am doing POC on 2-factor authentication.I need to have a client part for encrypting a data with certificate and post the same to server where i am decrypting with C#.net.i completed server part.i am working on client part. need your help.if possible please help me.My Mail ID: lraja@rsi.ramco.com

  • Anonymous
    April 22, 2008
    Hi there,If you want to encrypt data with a certificate using CryptoAPI, you may want to take a look to this other post:How to Encrypt and Decrypt with CryptoAPI and a user Certificate (Windows Mobile)http://blogs.msdn.com/alejacma/archive/2008/04/04/how-to-encrypt-and-decrypt-with-cryptoapi-and-a-user-certificate-windows-mobile.aspxThis article talks about a solution for Windows Mobile, but for standard Windows the idea is the same. Just pay attention to the differences in the APIs as stated in MSDN.I hope this helps. If not, please open a case with MS Technical Support and we will help you.Cheers,Alex

  • Anonymous
    May 11, 2011
    Very interesting article, but won't your encryption fail, if the file is bigger than bytelength of key -11?I'm sure i read about this limitation in MSDN.Thanks in Advance for your answer

  • Anonymous
    August 11, 2015
    Very good article...worked like a charm... Thanks Alex..

  • Anonymous
    October 22, 2015
    I'm not sure what I'm doing wrong.  I create a pub and private key.  I encrypt with the public key.  I can then decrypt using either the public key or the private key.

  • Anonymous
    November 07, 2015
    Rob, i've the same problem on windows 7 x64. Did you find out what's wrong with this code?