I'm trying to recreate the following C# implementation of TripleDES ECB with PKCS7 padding in PHP using openssl_encrypt and openssl_decrypt.
private static string Key = "<some random key with umlauts and special characters length of 24>";
public static string Decrypt(string cypherText)
{
using(var des = CreateDes(Key))
{
var ct = des.CreateDecryptor();
var input = Convert.FromBase64String(cypherText);
var output = ct.TransformFinalBlock(input, 0, input.Length);
return Encoding.UTF8.GetString(output);
}
}
public static string Encrypt(string plainText)
{
using(var des = CreateDes(Key))
{
var ct = des.CreateEncryptor();
var input = Encoding.UTF8.GetBytes(plainText);
var output = ct.TransformFinalBlock(input, 0, input.Length);
return Convert.ToBase64String(output);
}
}
private static TripleDES CreateDes(string key)
{
MD5 md5 = new MD5CryptoServiceProvider();
TripleDES des = new TripleDESCryptoServiceProvider();
var desKey = md5.ComputeHash(Encoding.UTF8.GetBytes(key));
des.Key = desKey;
des.IV = new byte[des.BlockSize / 8];
des.Padding = PaddingMode.PKCS7;
des.Mode = CipherMode.ECB;
return des;
}
So far I've managed to figure out that I had to use the raw_output parameter of the md5-function in PHP to get the exact same key (compared with breakpoint in C# and getByteFromString-function in PHP) and the encryption/decryption basically is working on both sides. Except that values encrypted in C# cannot be decrypted in PHP and vice versa as the encryption results are not the same.
What I've got in PHP so far:
function getByteFromString( $value )
{
$ret = '';
for($i = 0; $i < strlen($value); $i++)
{
$ret .= '[' . $i . '] => ' . ord($value[$i])."<br/>";
}
return $ret;
}
function encrypt( $key, $value )
{
if( function_exists( 'openssl_encrypt' ) )
{
return base64_encode( openssl_encrypt( $value, 'DES-EDE3', $key, OPENSSL_RAW_DATA ) );
}
return 'openssl missing';
}
function decrypt( $key, $value )
{
if( function_exists( 'openssl_decrypt' ) )
{
return openssl_decrypt( base64_decode( $value ), 'DES-EDE3', $key, OPENSSL_RAW_DATA );
}
return 'openssl missing';
}
$sKey = md5("<the same random key with umlauts and special characters length of 24 as in c#>", true);
$number = '1234567890';
$encrypted = encrypt( $sKey, $number );
$decrypted = decrypt( $sKey, $encrypted );
// For key debugging only:
echo 'key:<br>' . getByteFromString($sKey) . '<br>';
echo 'encrypted: ' . var_export($encrypted, true) . '<br>';
echo 'decrypted: ' . var_export($decrypted, true). '<br>';
I know TripleDES should not be used anymore and ECB mode especially not, but I cannot change the C# Code, so the PHP Code has to create the same results as C# and has to be able to decrypt values encrypted in C# aswell as encrypt values so that C# can decrypt them - using TripleDES and ECB. I just can't figure out what I'm missing on PHP side.