0

I have two applications, one writen in C#, the other in PHP.

C# application encrypt messages using AES 256 CBC. Key used for encrypt is located in a byte[] property hardcoded in the class. The Initialization vector is also hardcoded and is the same through the time.

C# Application

byte[] key  = {142, 237, ....};
byte[] InitilizationVector  = {132, ...};
var mensajeSinEncriptar = "";

SymmetricAlgorithm algoritmo = SymmetricAlgorithm.Create("Rijndael");
algoritmo.BlockSize = 128;
algoritmo.Mode = CipherMode.CBC;
algoritmo.Padding = PaddingMode.Zeros;
algoritmo.KeySize = 256;
algoritmo.Key = key;
algoritmo.IV = InitilizationVector;

ICryptoTransform encriptador  = algoritmo.CreateEncryptor();
byte[] textoPlano = Encoding.Default.GetBytes(mensajeSinEncriptar);
MemoryStream memoryStream = new MemoryStream();

CryptoStream cryptoStream = new CryptoStream(memoryStream, encriptador, CryptoStreamMode.Write);
cryptoStream.Write(textoPlano, 0, textoPlano.Length);
cryptoStream.FlushFinalBlock();

memoryStream.Close();
cryptoStream.Close();

return Convert.ToBase64String(memoryStream.ToArray());

Then, in my PHP application I want to decrypt the messages generated by c # using OpenSSL. I use the same key and iv used in C#. I convert them to characters because the function does not accept anything other than string.

PHP

    private function decrypt(string $message)
    {
        $stringOf = function ($bytes) {
            return implode('', array_map('chr', $bytes));
        };

        $key = [142, 237, ...];
        $iv  = [132, ... ];

        $result = openssl_decrypt(
            base64_decode($message), 
            'aes-256-cbc', 
            $stringOf($key), 
            1, 
            $stringOf($iv)
        );

        if (is_bool($result) && !$result) {
            return new Error('Error: ' . openssl_error_string());
        }

        return $result;
    }

When I try to decrypt I get this error

Error: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt

I guess it's a mistake of mine when trying to convert the key to a string. Since I also have a function to encrypt which gives me different results using the same key and iv used in C#.

  • I had the [same problem](https://stackoverflow.com/questions/54328768/get-a-c-sharp-byte-array-equal-to-a-php-hex-string/54416378#54416378) but the other way around. Long story short, the array lengths are different in php and C# so the key ends up being different – ikerbera Feb 05 '20 at 12:33
  • 2
    In the C# code Zero-padding is applied, in the PHP code PKCS7 padding (the default). Use a consistent padding in both codes, preferably PKCS7, as it is more reliable. – Topaco Feb 05 '20 at 15:41
  • @Topaco You're right, I was using a different padding mode on each one. I can't change the padding in c # because the app is in production. When decrypting the message in PHP with the OPENSSL_ZERO_PADDING flag, the library returns the decrypted message, but adds bar characters at the end of the text string. For example "mymessage /////". – Alejandro Gutiérrez Feb 06 '20 at 09:14
  • 2
    Since `openssl_...` doesn't support Zero-padding, the only option is to disable PKCS7-padding for decryption. This is done with `OPENSSL_ZERO_PADDING`. Note that the flag doesn't enable Zero-padding (the name isn't well chosen). As a result, the `0`-values of the Zero-padding remain, which must be removed manually (e.g. with `rtrim($decrypted,"\0");`). However, if the unpadded ciphertext already ends with `0`-values, these would be removed as well because the information is missing how many bytes to remove. This is different for PKCS7-padding, that's why it is more reliable than Zero-padding. – Topaco Feb 06 '20 at 09:52

0 Answers0