Using CryptoAPI with KP_IV, but the encryption string is the same?

100 views Asked by At

I am using the CryptoAPI and initializing the hash with CBC and an IV to create a random encrypted string each time the same string is encrypted. I then try and decrypt but only get a partial string. I'm missing something simple here (I hope!). Can someone help me?

Example of [expected] encrypted binary string:
W»½¬{èeüÔÓoE付bnx=s„?äèÍÙÎÛg°fÒéò½üír&¯ñ\œÅö»R

Example of [messed up!] decrypted binary string:
c±O Ê›©qtœ‘þH² mother were hanging up clothes

UPDATE: So what is happening is when I take this code and put it into a DLL, each function Aes*() calls AesInitialization() separately. So an encrypted string will have its own IV.

QUESTION: How do I send the IV with the ciphertext to fix this?

Here is my working sample:

#include <iostream>
#include <windows.h>
#include <wincrypt.h>
using std::string;
const char *key = "yM7TbMuL3TNUmeBs1Mqdw73G2BmMBHHV7cDAF3V5v9FAOqYc0mF133T8WE5foqAG3rJAK8dU1hKc";
HCRYPTPROV hCryptProv = NULL; 
HCRYPTKEY hKey = NULL;
#define AES_BLOCK_SIZE 16

    
BOOL AesInitialization()
{
// Set hCryptProv and hKey
HCRYPTHASH hHash = NULL;
BOOL result = FALSE;
if (CryptAcquireContextW(&hCryptProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT))
    if (CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hHash))
        if (CryptHashData(hHash, (BYTE*)key, strlen(key), 0))
            if (CryptDeriveKey(hCryptProv, CALG_AES_256, hHash, 0, &hKey))
                {
                DWORD dwMode = CRYPT_MODE_CBC;
                result = CryptSetKeyParam(hKey, KP_MODE, (BYTE *)&dwMode, 0);
                }

if (hHash != NULL) 
    CryptDestroyHash(hHash);

return result;
}


BOOL AesEncrypt(string &data)
{
BOOL result = TRUE;
string iv;
iv.resize(AES_BLOCK_SIZE);  // allocate space for random IV

result = CryptGenRandom(hCryptProv, AES_BLOCK_SIZE, (BYTE *)&iv[0]);
if (result) 
    {
    if (CryptSetKeyParam(hKey, KP_IV, (BYTE *) iv.c_str(), 0))            
        {
        data = data + iv;       // Append the random string
        DWORD dwDataLen = data.length();
        data.resize(dwDataLen + AES_BLOCK_SIZE); // give enough space for padding
        result = CryptEncrypt(hKey, NULL, TRUE, 0, (BYTE *)&data[0], &dwDataLen, data.length());
        data.resize(dwDataLen);  // resize to actual ciphertext length
        }
    }

    
return result;
}


BOOL AesDecrypt(string &data)
{
BOOL success = TRUE;

string iv;
iv.resize(AES_BLOCK_SIZE);  // ensure IV has the correct size
iv.assign(key);
if (CryptSetKeyParam(hKey, KP_IV, (BYTE*)iv.c_str(), 0))
    {
    if (CryptSetKeyParam(hKey, KP_IV, (BYTE*)&iv[0], 0))
        {
        DWORD dwDataLen = data.length();
        success = CryptDecrypt(hKey, NULL, TRUE, 0, (BYTE *)&data[0], &dwDataLen);
        data.resize(dwDataLen - AES_BLOCK_SIZE);  // resize to actual ciphertext length
        }
    }


return success;
}


int main()
{
if (!AesInitialization()) 
    return 1;

string message = "my mother & your mother were hanging up clothes";
string iv;

if (!AesEncrypt(message))
    return 1;

if (!AesDecrypt(message)) 
    return 1;

return 0;
}
0

There are 0 answers