2010-09-17 44 views
6

我已經繼承了一些C#代碼,需要將它移植到PHP。那就是:我的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#字符串任何幫助。

+0

迴應每個版本的MD5哈希,並看到問題出現或晚於。還可以回顯各種字節數組,併發揮差異。 – colithium 2010-09-17 22:51:27

+0

謝謝。我嘗試了第一件事,但由於我對C#不太瞭解,因此我對自己的工作並不十分自信。一切似乎與解密步驟一致,但我想我不是100%確定。但hashedKey和strToDecrypt的長度與它們的PHP等效長度和相同的可打印字符長度相同,因此它們看起來相當確定,它們是相同的。 – matthewwithanm 2010-09-20 14:50:56

回答

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字節密鑰產生不同的結果(或是否有解決方法)。如果您有關於此的任何信息,請分享!

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編碼不同,其不保證(從你提供的樣本)str_encrypted是base64編碼,在c#或php方面。

你最好服用colithium的意見,並呼應了投入,以確保您所有輸入數據以字節級別相匹配。

+0

是的,我試過了,但它不影響輸出。 – matthewwithanm 2010-09-17 23:02:47

+0

它幾乎總是在一側的編碼錯誤。雙方都是str_encrypted base64編碼? – PaulG 2010-09-17 23:18:40

+0

是的,我使用完全相同的字符串,如我的示例代碼所示。相同的輸入。 – matthewwithanm 2010-09-20 14:54:05

2

您可能需要查看這個論壇:http://forums.asp.net/t/1498290.aspx顯然有人去年有什麼似乎是完全相同的問題。

從該網站,它看起來像C#的東西應該是UTF-7編碼..不是UTF-8。

+0

我已經看到了,但似乎utf7的事情是對它如何工作的誤解。 (無論哪種情況,它似乎都不起作用。) – matthewwithanm 2010-09-17 23:07:19

相關問題