WP: AesManaged encryption vs. mcrypt_encrypt

Posted by invalidusername on Stack Overflow See other posts from Stack Overflow or by invalidusername
Published on 2011-11-14T00:54:01Z Indexed on 2011/11/14 1:51 UTC
Read the original article Hit count: 381

Filed under:
|
|
|

I'm trying to synchronize my encryption and decryption methods between C# and PHP but something seems to be going wrong.

In the Windows Phone 7 SDK you can use AESManaged to encrypt your data

I use the following method:

    public static string EncryptA(string dataToEncrypt, string password, string salt)
    {
        AesManaged aes = null;
        MemoryStream memoryStream = null;
        CryptoStream cryptoStream = null;

        try
        {
            //Generate a Key based on a Password, Salt and HMACSHA1 pseudo-random number generator 
            Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(salt));

            //Create AES algorithm with 256 bit key and 128-bit block size 
            aes = new AesManaged();
            aes.Key = rfc2898.GetBytes(aes.KeySize / 8);
            aes.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // rfc2898.GetBytes(aes.BlockSize / 8);

            // to check my results against those of PHP
            var blaat1 = Convert.ToBase64String(aes.Key);
            var blaat2 = Convert.ToBase64String(aes.IV);

            //Create Memory and Crypto Streams 
            memoryStream = new MemoryStream();
            cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write);

            //Encrypt Data 
            byte[] data = Encoding.Unicode.GetBytes(dataToEncrypt);
            cryptoStream.Write(data, 0, data.Length);
            cryptoStream.FlushFinalBlock();

            //Return Base 64 String 
            string result = Convert.ToBase64String(memoryStream.ToArray());

            return result;
        }
        finally
        {
            if (cryptoStream != null)
                cryptoStream.Close();

            if (memoryStream != null)
                memoryStream.Close();

            if (aes != null)
                aes.Clear();
        }
    }

I solved the problem of generating the Key. The Key and IV are similar as those on the PHP end. But then the final step in the encryption is going wrong.

here is my PHP code

<?php

function pbkdf2($p, $s, $c, $dk_len, $algo = 'sha1') {

    // experimentally determine h_len for the algorithm in question
     static $lengths;
     if (!isset($lengths[$algo])) { $lengths[$algo] = strlen(hash($algo, null, true)); }
    $h_len = $lengths[$algo];

    if ($dk_len > (pow(2, 32) - 1) * $h_len) {
         return false; // derived key is too long
     } else {
         $l = ceil($dk_len / $h_len); // number of derived key blocks to compute
         $t = null;
         for ($i = 1; $i <= $l; $i++) {
             $f = $u = hash_hmac($algo, $s . pack('N', $i), $p, true); // first iterate
             for ($j = 1; $j < $c; $j++) {
                 $f ^= ($u = hash_hmac($algo, $u, $p, true)); // xor each iterate
             }
             $t .= $f; // concatenate blocks of the derived key
         }
         return substr($t, 0, $dk_len); // return the derived key of correct length
     }

}


$password = 'test';
$salt = 'saltsalt';
$text = "texttoencrypt";

#$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
#echo $iv_size . '<br/>';
#$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
#print_r (mcrypt_list_algorithms());

$iv = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";

$key = pbkdf2($password, $salt, 1000, 32);
echo 'key: ' . base64_encode($key) . '<br/>';
echo 'iv: ' . base64_encode($iv) . '<br/>';

echo '<br/><br/>';

function addpadding($string, $blocksize = 32){
     $len = strlen($string);
     $pad = $blocksize - ($len % $blocksize);
     $string .= str_repeat(chr($pad), $pad);
     return $string;
 }

echo 'text: ' . $text . '<br/>';
echo 'text: ' . addpadding($text) . '<br/>';

// -- works till here

$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC, $iv);

echo '1.' . $crypttext . '<br/>';
$crypttext = base64_encode($crypttext);
echo '2.' . $crypttext . '<br/>';

$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, addpadding($text), MCRYPT_MODE_CBC, $iv);

echo '1.' . $crypttext . '<br/>';
$crypttext = base64_encode($crypttext);
echo '2.' . $crypttext . '<br/>';

?>

So to point out, the Key and IV look similar on both .NET and PHP, but something seems to be going wrong in the final call when executing mcrypt_encrypt(). The end result, the encrypted string, differs from .NET.

Can anybody tell me what i'm doing wrong. As far as i can see everything should be correct.

Thank you!

EDIT:

Additional information on the AESManaged object in .NET

Keysize = 256 Mode = CBC Padding = PKCS7

© Stack Overflow or respective owner

Related posts about php5

Related posts about windows-phone-7