Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Encrypt and Windows Decrypt

I 'm stuck. It seems that AES encryption done by PHP cannot be decrypted in windows.

PHP code:

$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128,"12345678", "test", MCRYPT_MODE_CBC));

Windows Code: "s" has the string which is created by the above response after converting back from base64.

bool Decrypt(char* s,char* key,char* dest)
{
// Create the crypto provider context.
HCRYPTPROV hProvider = NULL;
if (!CryptAcquireContext(&hProvider,
    NULL,  // pszContainer = no named container
    MS_ENH_RSA_AES_PROV,  // pszProvider = default provider
    PROV_RSA_AES,
    0)) 
        return false;


// Construct the blob necessary for the key generation.
aes128keyBlob aes_blob128;

aes_blob128.header.bType = PLAINTEXTKEYBLOB;
aes_blob128.header.bVersion = CUR_BLOB_VERSION;
aes_blob128.header.reserved = 0;
aes_blob128.header.aiKeyAlg = CALG_AES_128;
aes_blob128.keySize = 16;
memcpy(aes_blob128.bytes, key, 16);

HCRYPTKEY hKey = NULL;
if (!CryptImportKey(hProvider,
    (BYTE*)(&aes_blob128),
    sizeof(aes_blob128),
    NULL,  // 
    0,     // 
    &hKey)) {

        ...
    }


// Set Mode
DWORD dwMode = CRYPT_MODE_CBC;
CryptSetKeyParam( hKey, KP_MODE, (BYTE*)&dwMode, 0 );


DWORD length = 16;
BOOL X = CryptDecrypt(hKey,
    NULL,  // hHash = no hash
    TRUE,  // Final
    0,
    (BYTE*)s,
    &length);
//int le = GetLastError();
memcpy(dest,s,16);

CryptDestroyKey(hKey);
CryptReleaseContext(hProvider, 0);
}

What could be wrong?

like image 520
Michael Chourdakis Avatar asked Sep 28 '12 17:09

Michael Chourdakis


1 Answers

The information you provided is not enough to say for certain but I think that your problem is the key length.

In PHP code you pass "12345678" as a key. And AES128 has a key length of 128bit or 16 bytes. PHP pads the remaining with zero bytes, as stated in the documentation on mcrypt_encrypt.

In the C++ code you pass only the pointer to your key buffer to Decrypt function. But then you copy 16 bytes from it to the key BLOB:

aes_blob128.keySize = 16;
memcpy(aes_blob128.bytes, key, 16);

Then if you call your function like:

char dest[16];
bool result = Decrypt(string_from_php,"12345678",dest);

than the 8 bytes that happen to reside in memory after the "12345678" constant will be copied to the key blob and passed to CryptImportKey as an actual key. Thus the key in C and in PHP code would be actually different and the decryption will fail due to padding error.

like image 104
Rostislav Kondratenko Avatar answered Oct 03 '22 09:10

Rostislav Kondratenko