my task is to decrypt data encrypted in C# using Php. I try to use the phpseclib library. So here is the existing code that is used in C# to encrypt :
public static String EncryptMyText(string clearText, string Password) { if (clearText.Length == 0) return ""; byte[] clearBytes = System.Text.Encoding.UTF8.GetBytes(clearText); // second parameter is "Ivan Medvedev" in string PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }); byte[] encryptedData = Encrypt(clearBytes, pdb.GetBytes(32), pdb.GetBytes(16)); return Convert.ToBase64String(encryptedData); } public static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV) { try { MemoryStream ms = new MemoryStream(); Rijndael alg = Rijndael.Create(); alg.Key = Key; alg.IV = IV; CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write); cs.Write(clearData, 0, clearData.Length); cs.Close(); byte[] encryptedData = ms.ToArray(); return encryptedData; } catch (Exception ex) { string message = ex.Message; } return null; } EncryptMyText("sometext", "xxxxxxxxxxxxxxx"); // password have 15 characters length
It is not possible to change this code. So here is what I’ve tried using phpseclib :
$key = "xxxxxxxxxxxxxxx"; $salt = "Ivan Medvedev"; $cipher = new Rijndael(); $cipher->setPassword($cle, 'pbkdf1', 'sha1', $salt); $cipher->decrypt(base64_decode("someCryptedText"));
At this point, the code breaks with an Exception “Derived key too long” raised on setPassword()
call.
I tried many things such as changing blockLength
and KeyLenghth
and not using setPassword()
$cipher->setKeyLength(256); $cipher->setBlockLength(128);
with no notable changes.
I have little experience in decrypting and ciphers, so I digged some info on the C# code used. Looking at the Rijndael class here https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.rijndael?view=netframework-4.8. I tried several things with not much ideas on what I should look. I don’t even know if there is possible to use Phpseclib to decrypt data made by this C# code.
Thanks to every people who could give me some guidance.
Advertisement
Answer
It looks like https://github.com/phpseclib/phpseclib/issues/1447#issuecomment-580594929 might answer your question. Quoting it:
According to https://crypto.stackexchange.com/q/22271/4520
PasswordDeriveBytes
implements a customized version of PBKDF1.Try this:
function pbkdf1ms(&$cipher, $password, $hash, $salt, $rounds) { $keyLength = $cipher->getKeyLength() >> 3; $blockLength = $cipher->getBlockLength() >> 3; $dkLen = $keyLength + $blockLength; $hashObj = new Hash(); $hashObj->setHash($hash); if ($dkLen > 100 * $hashObj->getLength()) { user_error('Derived key too long'); return false; } $t = $password . $salt; for ($i = 0; $i < $rounds; ++$i) { $old = $t; $t = $hashObj->hash($t); } $ctr = 1; while ($dkLen > strlen($t)) { $t.= $hashObj->hash($ctr++ . $old); } $key = substr($t, 0, $dkLen); $cipher->setKey(substr($key, 0, $keyLength)); //$cipher->setKey(substr($key, $keyLength)); $remainingBytes = $hashObj->getLength() - $keyLength % $hashObj->getLength(); $cipher->setIV( substr($key, $remainingBytes, $blockLength - $remainingBytes) . substr($key, $keyLength + $remainingBytes) ); } $c = new Rijndael; $c->setKeyLength(256); pbkdf1ms($c, 'xxxxxxxxxxxxxxx', 'sha1', 'Ivan Medvedev', 100); $c->decrypt(base64_decode("s@omeCryptedText"));