0

I need to encrypt strings under AES-128 for my C/C++ app making use of WinCrypt.

Just for understanding how the whole thing works, I have written a program to encrypt a 16 byte string with a 16 byte AES key (128 bits) but it is not working as expected (and the MSDN examples are not helping).

My main problem is with the call to CryptEncrypt, I may not have clear how to use the parameters:

  • *pbData
  • *pdwDataLen
  • dwBufLen

Here is my code:

#include <windows.h> 
#include <stdio.h>
#include <wincrypt.h>
#define ENCRYPT_ALGORITHM CALG_AES_128

int main()
{

  HCRYPTPROV hCryptProv;
  HCRYPTKEY hKey;

//---------------------------------------------------------------
// Get the handle to the provider.
if(CryptAcquireContext(
    &hCryptProv, 
    NULL, 
    NULL, //MS_ENH_RSA_AES_PROV
    PROV_RSA_AES, 
    0))
{
    printf("A cryptographic provider has been acquired. \n");
}
else
{
    printf("Error during CryptAcquireContext!\n");
    exit(1);
}


//---------------------------------------------------------------
//  Create a random session key. 

 if(CryptGenKey(
          hCryptProv, 
          ENCRYPT_ALGORITHM, 
          CRYPT_EXPORTABLE, //KEYLENGTH | CRYPT_EXPORTABLE, 
          &hKey))
 {
         printf("A session key has been created.\n");
 } 
 else
 {
          printf("Error during CryptGenKey.\n"); 
          exit(1);
 }
}

char text_test [] = "abcdabcdabcdabcd";
   DWORD text_len = strlen(text_test);

   printf("PlainText: %s\n",text_test);
   printf("Buf Len: %d\n",text_len);

   if (!CryptEncrypt(hKey,
                    NULL,  // hHash = no hash
                    1,  // Final
                    0,     // dwFlags
                    &text_test, //*pbData
                    &text_len,  //*pdwDataLen
                    32)) {      //dwBufLen
     printf("Encryption failed\n");
   }

   printf("CipherText: %s\n",text_test);
   printf("Len: %d\n",text_len);

   if (!CryptDecrypt(hKey,
                    NULL,  // hHash = no hash
                    1,  // Final
                    0,     // dwFlags
                    &text_test,
                    &text_len)) {
     printf("Decryption failed\n");
   }

   printf("PlainText: %s\n",text_test);
   printf("Len: %d\n",text_len);
.
.
.
CryptDestroyKey(hKey)
.
.
CryptReleaseContext(hCryptProv, 0)
.

The output in the cmd is:

enter image description here

Can anyone explain me why the decrypted string is longer and which is the correct use of that three parameters of CryptEncrypt? I set the last value to 32 because after some trial and error that was the only value which made this stuff work. Help please and thank you in advance!

Captain Nemo
  • 262
  • 1
  • 7
  • 22

2 Answers2

2

I am new to crytography too, but this code from here might have your solution:

  // This acts as both the length of bytes to be encoded (on input) and the
  // number of bytes used in the resulting encrypted data (on output).
  DWORD length = kAesBytes128;
  if (!CryptEncrypt(hKey,
                    NULL,  // hHash = no hash
                    true,  // Final
                    0,     // dwFlags
                    reinterpret_cast<BYTE*>(encrypted->data()),
                    &length,
                    encrypted->length())) {
    throw std::runtime_error("Encryption failed");
  }

  // See comment above.
  encrypted->chop(length - kAesBytes128);

Or i might have some working from a similar project code using Crypto++

Community
  • 1
  • 1
meta
  • 153
  • 12
  • Thank you but I saw this post before posting my question. In this example I do not understand the parameters *pbData nor dwBufLen. I do not know how to use them in my code. – Captain Nemo Apr 27 '17 at 13:13
  • https://msdn.microsoft.com/en-us/library/windows/desktop/aa379924(v=vs.85).aspx is the API doc `pbData - A pointer to a buffer that contains the plaintext to be encrypted. The plaintext in this buffer is overwritten with the ciphertext created by this function.` `dwBufLen - Specifies the total size, in bytes, of the input pbData buffer.` Seems straightforward to me. – PatrickB Jun 28 '17 at 23:39
  • Also, AES is a block cypher, so this restriction applies: `When a block cipher is used, this data length must be a multiple of the block size unless this is the final section of data to be encrypted and the Final parameter is TRUE.` – PatrickB Jun 28 '17 at 23:43
0

It's padding. By default, you'll get an equal amount of padding inserted as the bytes you encrypt. Ignore the last 16 bytes. The first 16 bytes are what you want.