EldoS | Feel safer!

Software components for data protection, secure storage and transfer

Decrypting AES that was created in PHP script

Also by EldoS: BizCrypto
Components for BizTalk® and SQL Server® Integration Services that let you securely store and transfer information in your business automation solutions.
#19354
Posted: 03/08/2012 08:43:10
by mstaszew (Basic support level)
Joined: 03/06/2012
Posts: 3

Hi there. I am trying to decrypt a string that was encrypted using PHP and the mcrypt library. This script was created by another developer here so I'll just relay what I know and will need to follow up on any questions as PHP/mcrypt is not something I have used before.

He's using AES, 256-bit, CBC mode, 128-bit block size, PKCS5 padding. By default mcrypt uses PKCS7, but he is using some code he found online to use PKCS5 instead. We are using the same key and initialization vector.

Code
                                function encrypt_something($input)
                                {
                                                $size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, 'cbc');
                                                $input = pkcs5_pad($input, $size);
                                                
                                                $key = '12345678901234561234567890123456';
                                                $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', 'cbc', '');
                                                
                                                $iv = '1234567890123456';
                                                mcrypt_generic_init($td, $key, $iv);
                                                $data = mcrypt_generic($td, $input);
                                                mcrypt_generic_deinit($td);
                                                mcrypt_module_close($td);
                                                $data = base64_encode($data);
                                                return $data;
                                }

                                function pkcs5_pad ($text, $blocksize)
                                {
                                                $pad = $blocksize - (strlen($text) % $blocksize);
                                                return $text . str_repeat(chr($pad), $pad);
                                }

                                function pkcs5_unpad($text)
                                {
                                                $pad = ord($text{strlen($text)-1});
                                                if ($pad > strlen($text)) return false;
                                                if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;
                                                return substr($text, 0, -1 * $pad);
                                }


My decryption code is as follows. Note that the PHP string was UTF-8 encoded so I'm treating it as UTF-8 after decrypting it.

Code
function GenerateKeyMaterial(const Key, IV: string; Algorithm: Integer): TElSymmetricKeyMaterial;
var
  Hash: TElHashFunction;
  PassBytes: ByteArray;
  Digest: BufferType;
begin
  Hash := TElHashFunction.Create(Algorithm);
  try
    PassBytes := SBUtils.BytesOfS tring(Key);
    Hash.Upd ate(@PassBytes[0], Length(PassBytes));
    Digest := Hash.Finish;
  finally
    Hash.Free;
  end;

  Result := TElSymmetricKeyMaterial.Create;
  Result.Key := SBUtils.BytesOfS tring(Digest);
  Result.IV := SBUtils.BytesOfS tring(IV);
end;

function Decrypt(const S, Key, IV: string; Encoding: TEncoding; Algorithm: Integer; Mode: TSBSymmetricCryptoMode; Padding: TSBSymmetricCipherPadding): string;
var
  Factory: TElSymmetricCryptoFactory;
  Crypto: TELSymmetricCrypto;
  Bytes: TBytes;
  InBuf, OutBuf: ByteArray;
  OutSize: Integer;
begin
  Factory := TElSymmetricCryptoFactory.Create;
  try
    Crypto := Factory.CreateInstance(Algorithm, Mode);
    Crypto.Padding := Padding;
    Crypto.KeyMaterial := GenerateKeyMaterial(Key, IV, SB_ALGORITHM_DGST_SHA256);

    { Decode base64 encoded encrypted string into ByteArray }
    InBuf := SBEncoding.Base64DecodeArray(S);

    { Decrypt }
    OutSize := 0;
    Crypto.Decrypt(@InBuf[0], Length(InBuf), nil, OutSize);
    SetLength(OutBuf, OutSize);
    Crypto.Decrypt(@InBuf[0], Length(InBuf), @OutBuf[0], OutSize);

    { Covert into TBytes }
    Se tLength(Bytes, OutSize);
    Move(OutBuf[0], Bytes[0], OutSize);

    { Return the decrypted string }
    Result := Encoding.GetS tring(Bytes);
  finally
    Factory.Free;
  end;
end;


And I'm calling the above routine like this.

Code
const
  CryptKey = '12345678901234561234567890123456';
  CryptIV = '1234567890123456';

...

mDecrypted.Lines.Text := Decrypt(Trim(mEncrypted.Lines.Text), CryptKey, CryptIV, DefaultEncoding,
    SB_ALGORITHM_CNT_AES256, cmCBC, cpPKCS5);


When I do this I receive an EElSymmetricCryptoError with message "Invalid symmetric cipher padding." If anyone can spot why I am unable to decrypt this data I'd really appreciate it. This stuff is out of my comfort zone.

When I encrypt/decrypt data using SBB alone I have no issues. I've been using different encodings as well to make sure that I can properly handle any encoding and it's all working well except when getting the data from this PHP script.

Thanks,
Michael
#19355
Posted: 03/08/2012 08:45:02
by mstaszew (Basic support level)
Joined: 03/06/2012
Posts: 3

In my call to Decrypt I'm passing "DefaultEncoding" but that is a function that simply returns TEncoding.UTF8. I forgot to include that in my original message.
#19356
Posted: 03/08/2012 08:48:49
by Mykola Olshevsky (Basic support level)
Joined: 07/07/2005
Posts: 450

Hi. What is the size of your encrypted data? Try to decrypt it without padding (setting .Padding to None), and see what tail bytes were appended.
Also, PHP code seems to use AES-128, not 256.
#19359
Posted: 03/08/2012 09:08:06
by Eugene Mayevski (EldoS Corp.)

Your key in PHP is too large for 128-bit encryption. Docs say

Quote

key

The maximum length of the key should be the one obtained by calling mcrypt_enc_get_key_size() and every value smaller than this is legal.


For 128 bits it's 16 bytes.


Sincerely yours
Eugene Mayevski
#22985
Posted: 12/27/2012 12:46:25
by Bojan Premuš (Basic support level)
Joined: 12/27/2012
Posts: 3

Hello, i am trying to encrypt in PHP a sting that your software will be able to decrypt, however mycrtypt give me different data with all the same parametars, is there a tested example in PHP?
#22986
Posted: 12/27/2012 12:52:35
by Vsevolod Ievgiienko (EldoS Corp.)

Hello.

We don't have such example. Could you post here source code for both PHP and SBB, so we'll be able to find the difference.
#22987
Posted: 12/27/2012 13:47:54
by Bojan Premuš (Basic support level)
Joined: 12/27/2012
Posts: 3

i will have a Delphi code shortly, but i have also recived an example in js that works the same way one in Delphi
Code
key = CryptoJS.enc.Hex.parse('4aa0926253e9ac84032b2e3f5f407efde7076ffa102ae6788e861ddeede9e945');
   iv  = CryptoJS.enc.Hex.parse('03fe2d2ec11c11894459380d4f15da45');
   var encrypted = CryptoJS.AES.encrypt('hello world', key, { iv : iv });


this is the result: 'drFuaHHBsj+dExDHROMUUA=='

and on my PHP side there is a

Code
$input = 'hello world';
$key = '4aa0926253e9ac84032b2e3f5f407efde7076ffa102ae6788e861ddeede9e945';
$iv  = '03fe2d2ec11c11894459380d4f15da45';
$clp = MCRYPT_RIJNDAEL_128;

        function encrypt_something($input,$key,$iv,$clp)
        {
                        $size = mcrypt_get_block_size($clp, 'cbc');
                        $input = pkcs5_pad($input, $size);
                        $td = mcrypt_module_open($clp, '', 'cbc', '');


                        mcrypt_generic_init($td, $key, $iv);
                        $data = mcrypt_generic($td, $input);
                        mcrypt_generic_deinit($td);
                        mcrypt_module_close($td);
                        $data = base64_encode($data);
                        return $data;
        }

        function pkcs5_pad ($text, $blocksize)
        {
                        $pad = $blocksize - (strlen($text) % $blocksize);
                        return $text . str_repeat(chr($pad), $pad);
        }


with a result : 'W3B9oXKYPsodS2YCqLtnZw=='

i have also try and catch some others modes hoping to find one that we can use to crtypt data from php to delphi

// tripledes RHzUcLo8mGC0uwHX8Mt/+Q==
// blowfish rR8Bqgyfn8Nk2321CPskDg==
// cast-128 GGD2oa1A4TfJD0MbYArveg==
// cast-256 PzqiCOCjjNriGAqByE58Hg==
// des WHCfVwHGagK82iujQ3awjQ==
// gost a23jfx+LpTcTDDI89VikXA==
// loki97 sLHibM5wwDLS+Qxmk1j2bg==
// rijndael-128 W3B9oXKYPsodS2YCqLtnZw==
// rijndael-192 B816+41wxip2VqPjdhEUo5R160hQx5Qf
// rijndael-256 Z/xqupGrKwCxACr0EX9vAhIedrSHAqjut8t415vLC3E=
// rc2 vvC6i02II66Rvp79JZfS2A==
// saferplus m+kV45MrqUHkWiuV4UpvmA==
// serpent YC7zR7DiHVS/9tdDUU4jIg==
// tripledes RHzUcLo8mGC0uwHX8Mt/+Q==
// twofish j5n/xFLwXUzhF2RI2kBxag==
// xtea amRGFmtDhq0hQ06D3jvT1A==
#22988
Posted: 12/27/2012 14:03:15
by Vsevolod Ievgiienko (EldoS Corp.)

You PHP code uses AES-128, but JS code uses AES-256 because the key is 256 bits long. Please try to use MCRYPT_RIJNDAEL_256 instead.
#22989
Posted: 12/27/2012 14:13:53
by Bojan Premuš (Basic support level)
Joined: 12/27/2012
Posts: 3

i have tested that also,
// rijndael-256 Z/xqupGrKwCxACr0EX9vAhIedrSHAqjut8t415vLC3E=

but i have read that in PHP AES 256 is AES 128 with 256 key
#22990
Posted: 12/27/2012 15:25:19
by Mykola Olshevsky (Basic support level)
Joined: 07/07/2005
Posts: 450

AES is the 128-bit block cipher with keys 128, 192 or 256 bits in length.
And AES-128 stands for AES (128-bit block) cipher with 128 bit key.

Looks like CryptoJS serializes ciphertext in it's own way (with IV, or whatever else). Please try to compare encrypted.ciphertext with hex-encoded output of PHP encryption.
Also by EldoS: CallbackFilter
A component to monitor and control disk activity, track file and directory operations (create, read, write, rename etc.), alter file data, encrypt files, create virtual files.

Reply

Statistics

Topic viewed 8418 times

Number of guests: 1, registered members: 0, in total hidden: 0




|

Back to top

As of July 15, 2016 EldoS Corporation will operate as a division of /n software inc. For more information, please read the announcement.

Got it!