使用 PHP 解密使用 Rijndael (C#) 加密的数据
Decrypt data using PHP that was encrypted with Rijndael (C#)
我的任务是使用 Php 解密用 C# 加密的数据。我尝试使用 phpseclib 库。所以这是 C# 中用于加密的现有代码:
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
无法更改此代码。所以这是我使用 phpseclib 尝试过的:
$key = "xxxxxxxxxxxxxxx";
$salt = "Ivan Medvedev";
$cipher = new Rijndael();
$cipher->setPassword($cle, 'pbkdf1', 'sha1', $salt);
$cipher->decrypt(base64_decode("someCryptedText"));
此时,代码中断并在 setPassword()
调用时引发异常 "Derived key too long"。
我尝试了很多东西,例如更改 blockLength
和 KeyLenghth
以及不使用 setPassword()
$cipher->setKeyLength(256);
$cipher->setBlockLength(128);
没有显着变化。
我在解密和密码方面没有什么经验,所以我挖掘了一些关于使用的 C# 代码的信息。在此处查看 Rijndael class https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.rijndael?view=netframework-4.8。我尝试了几件事,但对我应该看什么没有太多想法。我什至不知道是否可以使用 Phpseclib 来解密此 C# 代码生成的数据。
感谢所有能给我一些指导的人。
看起来 https://github.com/phpseclib/phpseclib/issues/1447#issuecomment-580594929 可能会回答您的问题。引用它:
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"));
我的任务是使用 Php 解密用 C# 加密的数据。我尝试使用 phpseclib 库。所以这是 C# 中用于加密的现有代码:
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
无法更改此代码。所以这是我使用 phpseclib 尝试过的:
$key = "xxxxxxxxxxxxxxx";
$salt = "Ivan Medvedev";
$cipher = new Rijndael();
$cipher->setPassword($cle, 'pbkdf1', 'sha1', $salt);
$cipher->decrypt(base64_decode("someCryptedText"));
此时,代码中断并在 setPassword()
调用时引发异常 "Derived key too long"。
我尝试了很多东西,例如更改 blockLength
和 KeyLenghth
以及不使用 setPassword()
$cipher->setKeyLength(256);
$cipher->setBlockLength(128);
没有显着变化。
我在解密和密码方面没有什么经验,所以我挖掘了一些关于使用的 C# 代码的信息。在此处查看 Rijndael class https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.rijndael?view=netframework-4.8。我尝试了几件事,但对我应该看什么没有太多想法。我什至不知道是否可以使用 Phpseclib 来解密此 C# 代码生成的数据。
感谢所有能给我一些指导的人。
看起来 https://github.com/phpseclib/phpseclib/issues/1447#issuecomment-580594929 可能会回答您的问题。引用它:
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"));