c# MCRYPT_RIJNDAEL_256 Encryption Decryption Class in php
c# MCRYPT_RIJNDAEL_256 Encryption Decryption Class in php
I am trying to convert c# application into php but I stuck at a place where C# provides Security class for Encryption and decryption based on RIJNDAEL algo. I am trying to convert into php.
Note: I am Using php 7.2 so mcrypt is deprecated for this version.
C# code
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace pharmarackencryption
class Program
private const string initVector = "aw90rela942f65u2";
// This constant is used to determine the keysize of the encryption algorithm.
private const int keysize = 256;
public static string Encrypt(string plainText, string passPhrase = "testing")
byte initVectorBytes = Encoding.UTF8.GetBytes(initVector);
byte plainTextBytes = Encoding.UTF8.GetBytes(plainText);
PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null);
byte keyBytes = password.GetBytes(keysize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream();
CryptoStream 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);
public static string Decrypt(string cipherText, string passPhrase = "testing")
byte initVectorBytes = Encoding.ASCII.GetBytes(initVector);
byte cipherTextBytes = Convert.FromBase64String(cipherText);
PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null);
byte keyBytes = password.GetBytes(keysize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
static void Main(string args)
Program p = new Program();
string enc_password = Encrypt("437217");
string dec_password = Decrypt("C9xJGa03dRQx9ePm0nLnHg==");
Console.WriteLine(enc_password);
Console.WriteLine(dec_password);
Encryption : C9xJGa03dRQx9ePm0nLnHg==
I found some what similar code in php like
PHP code:
<?php
// key/iv in ASCII binary data, $str base64
function decrypt_stuff($key, $str, $iv)
// $plaintext_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($str), MCRYPT_MODE_CBC, $iv);
$plaintext_dec = openssl_decrypt(base64_decode($str), "aes-256-cbc", $key, OPENSSL_RAW_DATA
// key/iv in ascii binary data, $str ascii
function encrypt_stuff($key, $str, $iv)
// $ciphertext = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $str, MCRYPT_MODE_CBC, $iv));
if (($l = (strlen($str) & 15)) > 0) $str .= str_repeat(chr(0), 16 - $l);
$ciphertext = base64_encode(openssl_encrypt($str, "aes-256-cbc", $key, OPENSSL_RAW_DATA
echo encrypt_stuff("testing","437217","aw90rela942f65u2");
//Result : LTbhEHjFgfa5PDJQXJEdKQ==
Both are going same thing but still result is different
openssl_encrypt is alternative to mcrypt
– Juned Ansari
Sep 5 '18 at 10:06
Thanks i never knew that.
– Waqar Adil
Sep 5 '18 at 10:54
you might want to double-check padding
– sh4dowb
Sep 7 '18 at 10:18
@sh4dowb, I already checked padding but still results are different
– Juned Ansari
Sep 7 '18 at 10:26
4 Answers
4
Your PHP code produces different results because you're not using the same key. In your C# code you're using PasswordDeriveBytes
to create the key, which is Microsoft's implementation of PBKDF1.
PasswordDeriveBytes
PHP doesn't support PBKDF1, but we could write a function that is compatible with C#. The code below is inspired from this great answer by Maarten Bodewes, translated to PHP.
function passwordDeriveBytes($password, $salt, $iterations = 100, $len = 32)
$key = $password . $salt;
for($i = 0; $i < $iterations; $i++)
$key = sha1($key, true);
if (strlen($key) < $len)
$hx = passwordDeriveBytes($password, $salt, $iterations - 1, 20);
$counter = 0;
while (strlen($key) < $len)
$counter += 1;
$key .= sha1($counter . $hx, true);
return substr($key, 0, $len);
Also, you're bese64 encoding and padding your data manually. You're preforming zero byte padding, but in your C# code you're using PKCS7 (the default and preferred) padding. It's best to let openssl
pad and encode your data.
openssl
function encrypt_stuff($key, $str, $iv)
return openssl_encrypt($str, "aes-256-cbc", $key, 0, $iv);
function decrypt_stuff($key, $str, $iv)
return openssl_decrypt($str, "aes-256-cbc", $key, 0, $iv);
Using the key derived from passwordDeriveBytes
, this PHP code produces the same results as your C# code.
passwordDeriveBytes
$key = passwordDeriveBytes("testing", null);
$enc = encrypt_stuff($key,"437217","aw90rela942f65u2");
echo $enc;
//C9xJGa03dRQx9ePm0nLnHg==
However, I don't recommend using this code for the following reasons.
It's best to use PBKDF2 for your key. You can use Rfc2898DeriveBytes
in C#:
Rfc2898DeriveBytes
Rfc2898DeriveBytes kdf = new Rfc2898DeriveBytes(password, salt, iterations);
byte key = kdf.GetBytes(32);
and hash_pbkdf2
in PHP:
hash_pbkdf2
$key = hash_pbkdf2("sha1", $password, $salt, $iterations, 32, true);
The salt should be at least 8 bytes long, and the number of iterations should be at least 10,000.
You're not using a salt. You should use a random salt for each password, it makes your keys stronger.
You're using a static IV. The IV should be unique and unpredictable. You can create a random IV with RNGCryptoServiceProvider
:
RNGCryptoServiceProvider
byte iv = new byte[16];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(iv);
and openssl_random_pseudo_bytes
:
openssl_random_pseudo_bytes
$iv = openssl_random_pseudo_bytes(16);
You could use this code for the salt too.
You're not using authenticated encryption. If you're using PHP 7 you could use GCM, but unfortunately .NET doesn't provide any AEAD algorithms. However, you could use bouncycastle, if you choose to use authenticated encryption.
But your encryption code should produce different results every time you use it, because you should be using a random IV. You can decrypt the ciphertext correctly if you have the IV. The IV doesn't have to be secret; you could store it next to the ciphertext.
If you were using mcrypt
with MCRYPT_RIJNDAEL_256
, you could still make your PHP code compatible with C#, as RijndaelManaged
supports 256 bit block size.
mcrypt
MCRYPT_RIJNDAEL_256
RijndaelManaged
symmetricKey.BlockSize = 256;
However you shouldn't use mcrypt
because it's not maintained, and it's deprecated in PHP 7.
mcrypt
your php script returns "R6CjRlJr+2fXh8ic6JeZBA==" not "C9xJGa03dRQx9ePm0nLnHg==" please check it.
– Juned Ansari
Sep 10 '18 at 9:02
To be honest, I didn't use your padding method. I've updated my answer to produce the required result.
– t.m.adam
Sep 10 '18 at 11:04
I am not familiar with the C# end of this question. However I will point out some information that may be relevant to your problem.
MCRYPT_RIJNDAEL_256
aes-256-cbc
MCRYPT_RIJNDAEL_128
MCRYPT_RIJNDAEL_128
aes-256-cbc
So for these reasons aes-256-cbc
can not be used with MCRYPT_RIJNDAEL_256
. They simply are not the same thing.
aes-256-cbc
MCRYPT_RIJNDAEL_256
This one is redundant. If you are using the aes-256-cbc
you need to make sure that you are using a 256 bit key. Obviously make sure that your are using the same key to encrypt and decrypt. Make sure your IV is the correct IV. I would make them both static for testing. Once you get it working tinker around with adding the IV to the cipher string on encrypt and separating the IV from the cipher text on decrypt
aes-256-cbc
Use openssl_random_pseudo_bytes()
to generate your 256 bit(32 byte)key. You can also use openssl_random_pseudo_bytes()
to generate your IV.
openssl_random_pseudo_bytes()
openssl_random_pseudo_bytes()
On a side note. I would highly recommend using the LibSodium library. It is now native on the latest versions of PHP and has a C# library as well. You can find it on Github easy enough.
Once you get this going I would look at learning how to Authenticate/Verify your encryption. Here is a good starting link for that. Authentication Read
Hope that helps.
It is not recommended to store passwords at the database using an reversible algo, passwords should be stored using expensive hashes. You should consider switching your password storage to a hash like Argon2.
Check this: http://php.net/manual/en/function.password-hash.php
mcrypt has been moved. not removed. you may try installing this
sudo apt-get -y install gcc make autoconf libc-dev pkg-config
sudo apt-get -y install php7.2-dev
sudo apt-get -y install libmcrypt-dev
sudo pecl install mcrypt-1.0.1
PS: not tested
I am using windows
– Juned Ansari
Sep 5 '18 at 9:33
openssl_encrypt is alternative to mcrypt
– Juned Ansari
Sep 5 '18 at 9:36
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
You can move back to version 7.0, there is not a major difference but you will find mcrypt in that version
– Waqar Adil
Sep 5 '18 at 9:30