6

我继承了一些 C# 代码,需要将其移植到 PHP。这里是:

string key = "some key";
string strEncrypted = "some encrypted string";

byte[] hashedKey = new MD5CryptoServiceProvider().ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
byte[] strToDecrypt = Convert.FromBase64String(strEncrypted);

TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider();
tripleDES.Key = hashedKey;
tripleDES.Mode = CipherMode.ECB;

string strDecrypted = UTF8Encoding.UTF8.GetString(tripleDES.CreateDecryptor().TransformFinalBlock(strToDecrypt, 0, strToDecrypt.Length));

我的 PHP 代码如下所示:

$key = 'some key';
$str_encrypted = 'some encrypted string';

$hashed_key = md5($key, TRUE);
$str_to_decrypt = base64_decode($str_encrypted);

// The IV isn't used for ECB, but it prevents a warning.
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_TRIPLEDES, MCRYPT_MODE_ECB), MCRYPT_RAND); 

$str_decrypted = mcrypt_decrypt(MCRYPT_TRIPLEDES, $hashed_key, $str_to_decrypt, MCRYPT_MODE_ECB, $iv);

但是两个解密后的值不一样,我不知道为什么。我在这里和其他地方读过很多类似的问题,但似乎没有一个能解释我遇到的问题。

我真的很感激任何帮助弄清楚为什么解密的 PHP 字符串与解密的 C# 字符串不匹配。

4

3 回答 3

2

您可能想查看此论坛:http ://forums.asp.net/t/1498290.aspx 显然去年有人遇到了完全相同的问题。

从那个站点看,C# 的东西应该是 UTF-7 编码的。不是 UTF-8。

于 2010-09-17T22:47:43.313 回答
2

我终于设法在 PHP 手册的 Mcrypt 页面的评论中找到了答案:

在 PHP 和 C# 之间使用 3DES 时,需要注意的是,如果不严格遵守这些细微差别,将导致令人讨厌的问题加密/解密数据。

1),当使用 16 字节的密钥时,php 和 c# 生成完全不同的结果字符串。似乎 php 和 c# 需要一个 24 字节的密钥才能正常工作。

2),php没有“填充”选项,而c#有3(?)。我的解决方法是在源字符串的末尾添加空值,即 chr(0),使其大小为 8 倍,而在 c# 中,需要 PaddingMode.Zeros。

3) 密钥大小必须是 8 的倍数,在 php 中,才能使其适用于 c#。

这里的关键点是#1。由于使用的密钥是 md5 散列的结果,因此它将是 16 个字节。相反,如果我使用一个 24 字节的密钥来加密(然后解密)一切都是 hunky-dory。

到目前为止,我还没有找到解释为什么16 字节密钥会产生不同的结果(或者是否有解决方法)。如果你有这方面的信息,请分享!

于 2010-09-23T20:33:08.350 回答
0

C# 密钥在使用 MD5 散列之前以 UTF8 编码。PHP等效可能不是?

C# 输出也再次进行了 UTF8 编码。

我对 PHP 不太熟悉,但显然你想要的功能是utf8_encode,所以尝试将你的 PHP 端更新为:

$key = 'some key';
$str_encrypted = 'some encrypted string';

$hashed_key = md5(utf8_encode($key), TRUE);
$str_to_decrypt = base64_decode($str_encrypted);

// The IV isn't used for ECB, but it prevents a warning.
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_TRIPLEDES, MCRYPT_MODE_ECB), MCRYPT_RAND); 

$str_decrypted = utf8_encode(mcrypt_decrypt(MCRYPT_TRIPLEDES, $hashed_key, $str_to_decrypt, MCRYPT_MODE_ECB, $iv))

除了 UTF8 编码差异之外,它不能保证(从您提供的示例中)str_encrypted在 c# 或 php 端是 base64 编码的。

您最好接受 colithium 的建议并回显输入,以确保您的所有输入数据在字节级别匹配。

于 2010-09-17T22:45:31.597 回答