我的C#和PHP解密方法有何不同?

时间:2010-09-17 22:43:18

标签: c# php cryptography mcrypt

我继承了一些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#字符串不匹配的原因。

3 个答案:

答案 0 :(得分:2)

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

从该网站看起来C#的东西应该是UTF-7编码的..不是UTF-8。

答案 1 :(得分:2)

我终于找到了a comment on the Mcrypt page of the PHP manual中的答案:

  

在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字节密钥加密(然后解密),那么一切都很糟糕。

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

答案 2 :(得分:0)

在使用MD5进行哈希处理之前,C#密钥以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编码差异之外,在c#或php端无法保证(来自您提供的样本)str_encrypted是base64编码的。

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