I needed to be able to encrypt/decrypt in PHP and decrypt in C# using the same key. So I put the key and initialization vector in a XML file and use it in the PHP and C#.
A few quick notes:
- PHP’s MD5 implementation returns the hash in a 32 character string. C#’s MD5 implementation produces a 16 byte binary array. This is why I convert the byte array to a string in C#.
- The code assumes you are storing the encrypted data in a base 64 encoded string.
$td = mcrypt_module_open('rijndael-256', '', 'cbc', '');
if ($td !== FALSE)
{
$expected_key_size = mcrypt_enc_get_key_size($td);
$key = substr(md5($key), 0, $expected_key_size);
$rc = mcrypt_generic_init($td, $key, $iv);
}
So now $td is an object that can encrypt/decrypt, like this:
Encrypt:
base64_encode(mcrypt_generic($td, $plaintext));
Decrypt:
mdecrypt_generic($td, base64_decode($str));
Now for the C#.
Initialization:
byte[] keyBytes = Encoding.ASCII.GetBytes(key.value);
byte[] hash = MD5.Create().ComputeHash(keyBytes);
string ret = "";
foreach (byte a in hash)
{
if (a < 16)
ret += "0" + a.ToString("x");
else
ret += a.ToString("x");
}
byte[] ivBytes = Convert.FromBase64String(key.iv);
r = Rijndael.Create();
r.Padding = PaddingMode.Zeros;
r.BlockSize = 256;
r.Key = Encoding.ASCII.GetBytes(ret);
r.IV = ivBytes;
Encrypt/decrypt:
public string decrypt(string str)
{
byte[] encryptedBytes = Convert.FromBase64String(str);
byte[] decryptedBytes = transformBytes(
r.CreateDecryptor(), encryptedBytes);
string plaintext = Encoding.ASCII.GetString(decryptedBytes);
int idx = plaintext.IndexOf(" ");
if (idx > -1)
plaintext = plaintext.Substring(0, idx);
return plaintext;
}
public string encrypt(string plaintext)
{
byte[] plainBytes = Encoding.ASCII.GetBytes(plaintext);
byte[] encryptedBytes = transformBytes(
r.CreateEncryptor(), plainBytes);
return Convert.ToBase64String(encryptedBytes);
}
private byte[] transformBytes(ICryptoTransform transform,
byte[] plainBytes)
{
MemoryStream memStream = new MemoryStream();
CryptoStream cryptStream =
new CryptoStream(memStream, transform,
CryptoStreamMode.Write);
cryptStream.Write(plainBytes, 0, plainBytes.Length);
cryptStream.Close();
byte[] encryptedBytes = memStream.ToArray();
memStream.Close();
return encryptedBytes;
}