[英]Decrypting string encrypted in C# with RijndaelManaged class using PHP
Here's some C# code (I've modified it slightly to modify some of the hard coded values in it): 这是一些C#代码(我对其进行了一些修改,以修改其中的一些硬编码值):
public static string Decrypt(string InputFile)
{
string outstr = null;
if ((InputFile != null))
{
if (File.Exists(InputFile))
{
FileStream fsIn = null;
CryptoStream cstream = null;
try
{
byte[] _b = { 94, 120, 102, 204, 199, 246, 243, 104, 185, 115, 76, 48, 220, 182, 112, 101 };
fsIn = File.Open(InputFile, FileMode.Open, System.IO.FileAccess.Read);
SymmetricAlgorithm symm = new RijndaelManaged();
PasswordDeriveBytes Key = new PasswordDeriveBytes(System.Environment.MachineName, System.Text.Encoding.Default.GetBytes("G:MFX62rlABW:IUYAX(i"));
ICryptoTransform transform = symm.CreateDecryptor(Key.GetBytes(24), _b);
cstream = new CryptoStream(fsIn, transform, CryptoStreamMode.Read);
StreamReader sr = new StreamReader(cstream);
char[] buff = new char[1000];
sr.Read(buff, 0, 1000);
outstr = new string(buff);
}
finally
{
if (cstream != null)
{
cstream.Close();
}
if (fsIn != null)
{
fsIn.Close();
}
}
}
}
return outstr;
}
I need to come up with a function to do the same in PHP. 我需要拿出一个函数在PHP中执行相同的操作。 Bear in mind, I did not write the C# code and I cannot modify it, so even if it's bad, I'm stuck with it.
请记住,我没有编写C#代码,也无法修改它,因此即使它很糟糕,我也坚持使用它。 I've searched all over and have found bits and pieces around, but nothing that works so far.
我到处搜索,发现周围有些零散,但到目前为止没有任何效果。 All examples I've found use mcrypt, which seems to be frowned upon these days, but I'm probably stuck using it.
我发现的所有示例都使用mcrypt,这些天来似乎对此不满意,但我可能会坚持使用它。 Next, I found the following post which has some useful info: Rewrite Rijndael 256 C# Encryption Code in PHP
接下来,我发现了以下帖子,其中包含一些有用的信息: 用PHP重写Rijndael 256 C#加密代码
So looks like the PasswordDeriveBytes class is the key to this. 因此,看起来PasswordDeriveBytes类是实现此目的的关键。 I created the following PHP code to try to decrypt:
我创建了以下PHP代码以尝试解密:
function PBKDF1($pass,$salt,$count,$dklen) {
$t = $pass.$salt;
//echo 'S||P: '.bin2hex($t).'<br/>';
$t = sha1($t, true);
//echo 'T1:' . bin2hex($t) . '<br/>';
for($i=2; $i <= $count; $i++) {
$t = sha1($t, true);
//echo 'T'.$i.':' . bin2hex($t) . '<br/>';
}
$t = substr($t,0,$dklen);
return $t;
}
$input = 'Ry5WdjGS8rpA9eA+iQ3aPw==';
$key = "win7x64";
$salt = implode(unpack('C*', "G:MFX62rlABW:IUYAX(i"));
$salt = pack("H*", $salt);
$it = 1000;
$keyLen = 16;
$key = PBKDF1($key, $salt, $it, $keyLen);
$key = bin2hex(substr($key, 0, 8));
$iv = bin2hex(substr($key, 8, 8));
echo trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($input), MCRYPT_MODE_CBC, $iv));
You'll note that for what I believe to be System.Environment.MachineName, I put in a fixed value for now which is the computer name of the machine I'm on, so should be equivalent of what the C# code is doing. 您会注意到,对于我认为是System.Environment.MachineName的东西,我现在输入一个固定值,它是我所在机器的计算机名称,因此应等效于C#代码正在执行的操作。 Other than that, I've noticed that using MCRYPT_RIJNDAEL_256 doesn't work, it throws the error "The IV parameter must be as long as the blocksize".
除此之外,我注意到使用MCRYPT_RIJNDAEL_256不起作用,它会引发错误“ IV参数必须与块大小一样长”。 If I use MCRYPT_RIJNDAEL_128, I don't get that error, but decryption still fails.
如果我使用MCRYPT_RIJNDAEL_128,则不会收到该错误,但解密仍然会失败。 I assume I'm missing the piece for the byte array _b that's used by the CreateDecryptor function, I have no idea where that's supposed to fit in. Any help is appreciated.
我以为我缺少CreateDecryptor函数使用的字节数组_b的那一部分,我不知道该放在哪里。任何帮助都将受到赞赏。
UPDATE 更新
This is the solution, which was made possible by the answer marked correct. 这是解决方案,答案是正确的。 Note that the code for the PBKDF1 function is not mine, it was linked to in the answer.
请注意,PBKDF1函数的代码不是我的,而是在答案中链接到的。
function PBKDF1($pass, $salt, $count, $cb) {
static $base;
static $extra;
static $extracount= 0;
static $hashno;
static $state = 0;
if ($state == 0)
{
$hashno = 0;
$state = 1;
$key = $pass . $salt;
$base = sha1($key, true);
for($i = 2; $i < $count; $i++)
{
$base = sha1($base, true);
}
}
$result = "";
if ($extracount > 0)
{
$rlen = strlen($extra) - $extracount;
if ($rlen >= $cb)
{
$result = substr($extra, $extracount, $cb);
if ($rlen > $cb)
{
$extracount += $cb;
}
else
{
$extra = null;
$extracount = 0;
}
return $result;
}
$result = substr($extra, $rlen, $rlen);
}
$current = "";
$clen = 0;
$remain = $cb - strlen($result);
while ($remain > $clen)
{
if ($hashno == 0)
{
$current = sha1($base, true);
}
else if ($hashno < 1000)
{
$n = sprintf("%d", $hashno);
$tmp = $n . $base;
$current .= sha1($tmp, true);
}
$hashno++;
$clen = strlen($current);
}
// $current now holds at least as many bytes as we need
$result .= substr($current, 0, $remain);
// Save any left over bytes for any future requests
if ($clen > $remain)
{
$extra = $current;
$extracount = $remain;
}
return $result;
}
$input = 'base 64 encoded string to decrypt here';
$key = strtoupper(gethostname());
$salt = 'G:MFX62rlABW:IUYAX(i';
$it = 100;
$keyLen = 24;
$key = PBKDF1($key, $salt, $it, $keyLen);
$iv = implode(array_map('chr', [94, 120, 102, 204, 199, 246, 243, 104, 185, 115, 76, 48, 220, 182, 112, 101]));
_b
is a static value that is used as the IV ( CreateDecryptor
takes a key and IV parameter). _b
是用作IV的静态值( CreateDecryptor
带有密钥和IV参数)。 Since it is 16 bytes long, this means that you're using Rijndael-128 or more commonly known AES. 由于它的长度为16个字节,这意味着您正在使用Rijndael-128或更常见的AES。
Key.GetBytes(24)
suggests that a 24 byte key is derived and not a 16 byte key. Key.GetBytes(24)
建议派生一个24字节的密钥,而不是16字节的密钥。
Make sure that 确保
System.Text.Encoding.Default
is equivalent with implode(unpack('C*', ...
, System.Text.Encoding.Default
与implode(unpack('C*', ...
, PasswordDeriveBytes
is 1000, PasswordDeriveBytes
迭代的默认值为1000, PasswordDeriveBytes
is SHA-1 PasswordDeriveBytes
哈希的默认值是SHA-1 bin2hex
). bin2hex
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.