1

I am trying to port an encryption code written in C# to PHP. The code below uses Rijndael-128 encryption. The result given by PHP code is slightly different than the C# code. I am under constraint of not using Salt and Random IV and not altering C# code. After browsing through many of the answers on stackoverflow on this issue and making several changes to the code still the code is not producing correct result.

C# code (member function of a class)

public static string Encrypt(string plainText, string passPhrase)
{
    byte[] initVectorBytes = Encoding.UTF8.GetBytes(initVector);
    byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
    var password = new Rfc2898DeriveBytes(passPhrase, new byte[8], 10000);
    byte [] keyBytes= password.GetBytes(keysize / 8); //256/8
    var symmetricKey = new RijndaelManaged();
    symmetricKey.Mode = CipherMode.CBC;
    ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
    var memoryStream = new MemoryStream();
    var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
    cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
    cryptoStream.FlushFinalBlock();
    byte[] cipherTextBytes = memoryStream.ToArray();
    memoryStream.Close();
    cryptoStream.Close();

    return Convert.ToBase64String(cipherTextBytes);
}

PHP code (member function of a class)

public function encrypt(){

    $plainText="Same_input_as_above";

    $plainText=mb_convert_encoding($plainText,'UTF-8');

    $passPhrase=mb_convert_encoding($this->secret,'UTF-8');

    $salt=str_pad("",8,"\0");

    $key= hash_pbkdf2 ( 'sha1' , $passPhrase, $salt , 10000 ,self::KEYSIZE/8, true);

    $initVector=mb_convert_encoding(self::INITVECTOR,'UTF-8');

    $tempCipher= mcrypt_encrypt (MCRYPT_RIJNDAEL_128 , $key , $plainText , MCRYPT_MODE_CBC,$initVector);

    return base64_encode($tempCipher);
}

C# Output

O/Fi4tfdS5APen6YAboRnr%2B2bSrHSG71OHhX7YZbbhJYr8mt3HxfYza4bjkV8gtq

PHP Output

O/Fi4tfdS5APen6YAboRnr%2B2bSrHSG71OHhX7YZbbhIpdOLx9oscZnlAdyTMgeGX

The decryption function of C# works fine with the cipher created by itself but gives Padding is invalid and cannot be removed. error while decoding PHP generated cipher.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
Udit Bhardwaj
  • 1,761
  • 1
  • 19
  • 29
  • It is best not to use mcrypt, it is abandonware, has not been updated in years and does not support standard PKCS#7 (née PKCS#5) padding, only non-standard null padding that can't even be used with binary data. mcrypt had many outstanding [bugs](https://sourceforge.net/p/mcrypt/bugs/) dating back to 2003. Instead consider using [defuse](https://github.com/defuse/php-encryption) or [RNCryptor](https://github.com/RNCryptor), they provide a complete solution and are being maintained and is correct. – zaph Jul 31 '16 at 16:51
  • @ArtjomB. thanks. First I thought it was the empty salt that was making trouble after applying null padded salt I forgot to uncomment the plain-text padding lines after. – Udit Bhardwaj Jul 31 '16 at 16:57

1 Answers1

1

The problem is that mcrypt only supports non-standard null padding. The C# library supports standard PKCS#7 (née PKCS#5) padding. See PKCS#7 padding.

You can easily add and remove PKCS#7 padding prior to encryption and after decryption, in PHP:

Add PKCS#7 padding

$padLength = $blockSize - (strlen($clearText) % $blockSize);
$clearText = $clearText . str_repeat(chr($padLength), $padLength);

Strip PKCS#7 padding

$padLength = ord($cryptText[strlen($cryptText)-1]);
$cryptText = substr($cryptText, 0, strlen($cryptText) - $padLength);

The better solution is not to use mcrypt. Options include defuse or RNCryptor which provide a complete solution.

zaph
  • 111,848
  • 21
  • 189
  • 228