14

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?

Michael Chourdakis
  • 10,345
  • 3
  • 42
  • 78
  • how are you passing the encrypted string? i.e. cookie, db etc.. – solidau Sep 28 '12 at 17:15
  • Passing it back to the windows program? Via print and it takes it as the output of the browser. – Michael Chourdakis Sep 28 '12 at 17:17
  • 3
    Where are you handling the initialization vector (IV)? If you don't set an IV, PHP uses one with all its bytes set to `'\0'`; but it doesn't look like you are supplying that to your decryption routine. You really should use an IV though, otherwise might as well ditch CBC and use ECB (at the expense of security, of course). – NullUserException Sep 28 '12 at 19:19
  • 5
    Another thing you might want to look at is how padding is handled by both ends. IIRC mcrypt uses zero-padding; it's possible that your C++ end is using PKCS #7 or something else. – NullUserException Sep 28 '12 at 19:29
  • 1
    We don't know what could be wrong as you haven't supplied us with an indication how it goes wrong. Do you get exceptions? Garbled text? Do you have input/output you can share? – Maarten Bodewes Oct 07 '12 at 17:02
  • [Did you try converting the PHP output to little endian - some "windows code" fails at endianness](http://stackoverflow.com/questions/11638089/php-md5-not-matching-c-sharp-md5/11638154#comment15416389_11638154) - Also I assume you're removing the base64 encoding before you try and decrypt, right? – Leigh Oct 09 '12 at 09:12

3 Answers3

9

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.

1

PHP MCRYPT functions are a bit different than the windows decryption functions.

Because the mcrypt function takes the key of any length and converts it to the length required by the algorithm by adding \0 at the end of key string.

Please note to create a key with the specified length required for the encryption by the algorithm on both sides.

use md5 on the key and then convert it to the length required for the algorithm.

Vipin Jain
  • 1,382
  • 1
  • 10
  • 19
0

See below URL

Encrypt in PHP, Decrypt in C# (WP7 / Silverlight) using AES / Rijndael

http://pumka.net/2009/12/16/rsa-encryption-cplusplus-delphi-cryptoapi-php-openssl-2/

http://www.developer.nokia.com/Community/Wiki/Encrypt-Decrypt_contacts_database_entries_using_Symbian_C%2B%2B

Read it

I droped the MD5 crap out of PHP and C#, and they are now working properly.

Just in case you dropped here looking for the same answer, here is a sample code. Don't forget to make your own key and iv (although those bellow will work, is not recommended to use!)

PHP:

function encrypt128($message) {

    $vector = "0000000000000000";
    $key = "00000000000000000000000000000000";

    $block = mcrypt_get_block_size('rijndael_128', 'cbc');
    $pad = $block - (strlen($message) % $block);
    $message .= str_repeat(chr($pad), $pad);

    $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', 'cbc', '');
    mcrypt_generic_init($cipher, $key, $vector);
    $result = mcrypt_generic($cipher, $message);
    mcrypt_generic_deinit($cipher);

    return base64_encode($result);
}

C++

Encrypt-Decrypt contacts database entries using Symbian C++

http://www.developer.nokia.com/Community/Wiki/Encrypt-Decrypt_contacts_database_entries_using_Symbian_C%2B%2B

Headers Required:

#include <cntdb.h> // CContactDatabse, 
#include <cntitem.h> //CContactItem,CContactItemFieldSet

http://www.developer.nokia.com/Community/Wiki/Encrypt-Decrypt_contacts_database_entries_using_Symbian_C%2B%2B

Encrypt Contact Fields

void CEncryptContactContainer::EncryptAll()
{
    CContactDatabase *contactDB = CContactDatabase::OpenL();
    CleanupStack::PushL(contactDB);

    TContactIter iter(*contactDB);
    TContactItemId aContactId;

//Developer can take Heap based descriptor for large/unknown size of contact items.
    TBuf16<70> aValue; 

    const CContactIdArray* contactArray = contactDB->SortedItemsL();

    TInt cnt=contactArray->Count();

    for(TInt i=0;i<cnt;i++)
    {
        CContactItem* contactItem=NULL;

        contactItem= contactDB->OpenContactL((*contactArray)[i]);
        CleanupStack::PushL(contactItem);

        CContactItemFieldSet& fieldSet= contactItem->CardFields();
        TInt fieldCount=fieldSet.Count(); // This will give number of contact fields.

        for(TInt index=0; index < fieldCount; index++)
        {
            CContactItemField& field = fieldSet[index];
            const CContentType& type = field.ContentType();
            if(!(type.ContainsFieldType(KUidContactFieldBirthday)))
            {
                TPtrC name = contactItem->CardFields()[index].TextStorage()->Text();
                aValue.Copy(name);
                Encrypt(aValue); // Call real encyption here
                contactItem->CardFields()[index].TextStorage()->SetTextL(aValue);
            }
        } //Inner for loop ends here
        contactDB->CommitContactL(*contactItem);
        CleanupStack::PopAndDestroy(contactItem);
    } //Outer for loop ends here
    CleanupStack::PopAndDestroy(contactDB);
}

void CEncryptContactContainer:: Encrypt (TDes& aValue)
{
    for(TInt iCount=0; iCount< aValue.Length();iCount++)
    {
        aValue[iCount]+=3;
    }
}

Decrypt Contact Fields

void CEncryptContactContainer::DecryptAll()
{
    CContactDatabase *contactDB = CContactDatabase::OpenL();
    CleanupStack::PushL(contactDB);

    TContactIter iter(*contactDB);
    TContactItemId aContactId;
    TBuf16<70> aValue;

    const CContactIdArray* contactArray = contactDB->SortedItemsL();

    TInt cnt=contactArray->Count();

    for(TInt i=0;i<cnt;i++)
    {
        CContactItem* contactItem=NULL;

        contactItem= contactDB->OpenContactL((*contactArray)[i]);
        CleanupStack::PushL(contactItem);

        CContactItemFieldSet& fieldSet= contactItem->CardFields();
        TInt fieldCount=fieldSet.Count(); // This will give number of contact fields.

        for(TInt index=0; index < fieldCount; index++)
        {
            CContactItemField& field = fieldSet[index];
            const CContentType& type = field.ContentType();
            if(!(type.ContainsFieldType(KUidContactFieldBirthday)))
            {
                TPtrC name = contactItem->CardFields()[index].TextStorage()->Text();
                aValue.Copy(name);
                Decrypt(aValue);
                contactItem->CardFields()[index].TextStorage()->SetTextL(aValue);
            }
        } //Inner for loop ends here
        contactDB->CommitContactL(*contactItem);
        CleanupStack::PopAndDestroy(contactItem);
    } //Outer for loop ends here
    CleanupStack::PopAndDestroy(contactDB);
}

void CEncryptContactContainer:: Decrypt (TDes& aValue)
{
    for(TInt iCount=0; iCount< aValue.Length();iCount++)
    {
        aValue[iCount]-=3;
    }
}

C#:

byte[] cripted = EncryptStringToBytes("Test", System.Text.Encoding.UTF8.GetBytes("00000000000000000000000000000000"), System.Text.Encoding.UTF8.GetBytes("0000000000000000"));
Community
  • 1
  • 1
Abid Hussain
  • 7,724
  • 3
  • 35
  • 53