I want to encrypt a text string in C using the WinAPI implementation of AES-256-CBC, and then manually (using terminal) decrypt it in a linux machine using OpenSSL. I use this code: WinAPI - CryptDecrypt() not working properly in AES 256
// handles for csp and key
HCRYPTPROV hProv = NULL;
HCRYPTKEY hKey = NULL;
BYTE szKey[DEFAULT_AES_KEY_SIZE + 1] = { 0 };
BYTE szIV[DEFAULT_IV_SIZE + 1] = { 0 };
// plain bytes
BYTE szPlainText[BUFFER_FOR_PLAINTEXT + 1] = { 0 }, * pBuf = NULL;
AES256KEYBLOB AESBlob;
memset(&AESBlob, 0, sizeof(AESBlob));
// initalize key and plaintext
StrCpyA((LPSTR)szKey, "00112233445566778899001122334455");
StrCpyA((LPSTR)szIV, "4455667788990011");
StrCpyA((LPSTR)szPlainText, "abcdefghijklmnopqrstuvwxyzabcdef");
DWORD dwPlainSize = lstrlenA((LPCSTR)szPlainText), dwBufSize = dwPlainSize, dwBufSize2 = dwPlainSize;
// blob data for CryptImportKey() function (include key and version and so on...)
AESBlob.bhHdr.bType = PLAINTEXTKEYBLOB;
AESBlob.bhHdr.bVersion = CUR_BLOB_VERSION;
AESBlob.bhHdr.reserved = 0;
AESBlob.bhHdr.aiKeyAlg = CALG_AES_256;
AESBlob.dwKeySize = DEFAULT_AES_KEY_SIZE;
StrCpyA((LPSTR)AESBlob.szBytes, (LPCSTR)szKey);
// create a cryptographic service provider (CSP)
if (!CryptAcquireContextA(&hProv, NULL, MS_ENH_RSA_AES_PROV_A, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {goto error;}
if (!CryptImportKey(hProv, (BYTE*)&AESBlob, sizeof(AES256KEYBLOB), NULL, CRYPT_EXPORTABLE, &hKey)) { goto error; }
if (!CryptSetKeyParam(hKey, KP_IV, szIV, 0)) { goto error; }
if (CryptEncrypt(hKey, NULL, TRUE, 0, NULL, &dwBufSize, 0)) {
if ((pBuf = (BYTE*)calloc(dwBufSize, sizeof(BYTE))) == NULL) { goto error; }
StrCpyA((LPSTR)pBuf, (LPCSTR)szPlainText);
}
else { goto error; }
if (CryptEncrypt(hKey, NULL, TRUE, 0, pBuf, &dwBufSize2, dwBufSize)) {
BYTE* reversed = (BYTE*)calloc(dwBufSize, sizeof(BYTE));
ReverseStream(pBuf, reversed, dwBufSize);// reverse ciphertext
DWORD bytesWritten = 0;
if (ResList != INVALID_HANDLE_VALUE)
{
WriteFile(
res,
(char*)reversed,
dwBufSize,
&bytesWritten,
NULL);
}
//if (CryptDecrypt(hKey, NULL, TRUE, 0, pBuf, &dwBufSize)) {
// printf("\nDecrypted data: [%s]\nSize: %d\n", (LPCSTR)pBuf, dwBufSize);
//}else { goto error; }
} else { goto error; }
// return encrypted string
if (pBuf) free(pBuf);
if (hKey) CryptDestroyKey(hKey);
if (hProv) CryptReleaseContext(hProv, 0);
return NULL;
error:
if (pBuf) free(pBuf);
if (hKey) CryptDestroyKey(hKey);
if (hProv) CryptReleaseContext(hProv, 0);
return NULL;
}
This is the ReverseStream function. It's needed to convert ciphertext from Little Endian to Big Endian, for Openssl compatibility.
void ReverseStream(LPBYTE Source, LPBYTE Destination, DWORD Size)
{
int SourceCnt = Size;
int DestCnt = 0;
for (SourceCnt = Size - 1, DestCnt = 0; SourceCnt >= 0; SourceCnt--, DestCnt++)
Destination[DestCnt] = Source[SourceCnt];
}
Using WriteFile I create a file encrypted.txt to be decrypted in linux.
The command I use is:
openssl aes-256-cbc -d -a -nosalt -k "00112233445566778899001122334455" -in encrypted.txt -out secrets.txt
EDIT: a better command is the following (using hex values of the same key/value below), but it returns the same error
openssl aes-256-cbc -d -nosalt -K "3030313132323333343435353636373738383939303031313232333334343535" -iv "34343535363637373838393930303131" -in encrypted.txt -out secrets.txt
the error:
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
bad decrypt
140584380352320:error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length:crypto/evp/evp_enc.c:601:
It seems the last block is not correctly written, anyway the decryption in C (commented in the code) works. Where is the problem?