2011-12-07 47 views
1

我在C#的Rijndael/AES解密C#到PHP轉換

string s = "hellowld"; 
byte[] bytes = new UnicodeEncoding().GetBytes(s); 
FileStream stream = new FileStream(inputFile, FileMode.Open); 
RijndaelManaged managed = new RijndaelManaged(); 
CryptoStream stream2 = new CryptoStream(stream, managed.CreateDecryptor(bytes, bytes), CryptoStreamMode.Read); 
FileStream stream3 = new FileStream(outputFile, FileMode.Create); 
try 
{ 
    int num; 
    while ((num = stream2.ReadByte()) != -1) 
    { 
     stream3.WriteByte((byte) num); 
    } 
[....] 

此代碼段解密某個文件,並輸出解密版本下面的代碼。在從IM RijndaelManaged的用所述密碼作爲密鑰對CreateDecryptor的方法,並且還作爲IV。

我發現了一些代碼在這裏計算器上的PHP但如果我嘗試給鑰匙,像在C#什麼也沒有發生字節的IV相同的數組。

$Pass = "hellowld"; 
$Clear = file_get_contents('./file.dat', FILE_USE_INCLUDE_PATH); 

$bytePass=array(); 
$i = 0; 
foreach (str_split($Pass) as $value) { 
    $bytePass[$i]=ord($value); 
    $i++; 
} 

echo decryptAES($Clear,$bytePass,$bytePass); 

function decryptAES($content,$iv, $key,$aes) { 

// Setzt den Algorithmus 
switch ($aes) { 
    case 128: 
     $rijndael = 'rijndael-128'; 
     break; 
    case 192: 
     $rijndael = 'rijndael-192'; 
     break; 
    default: 
     $rijndael = 'rijndael-256'; 
} 

// Setzt den Verschlüsselungsalgorithmus 
// und setzt den Output Feedback (OFB) Modus 
$cp = mcrypt_module_open($rijndael, '', 'ofb', ''); 

// Ermittelt die Anzahl der Bits, welche die Schlüssellänge des Keys festlegen 
$ks = mcrypt_enc_get_key_size($cp); 

// Erstellt den Schlüssel, der für die Verschlüsselung genutzt wird 
$key = substr(md5($key), 0, $ks); 

// Initialisiert die Verschlüsselung 
mcrypt_generic_init($cp, $key, $iv); 

// Entschlüsselt die Daten 
$decrypted = mdecrypt_generic($cp, $content); 

// Beendet die Verschlüsselung 
mcrypt_generic_deinit($cp); 

// Schließt das Modul 
mcrypt_module_close($cp); 

return trim($decrypted); 

} 

我真的需要一些幫助,如何在PHP中正確創建代碼。沒有必要使用PHP輸出文件,字符串就足夠了。

UPDATE: 默認的C#RijndaelManaged密碼方法是AES-128-CBC。我改變了我的PHP代碼到的mcrypt模塊(default C# cipher method

更新2: 我還是設法創建一個Java解密這導致我的另一件事。 PHP必須使用PKCS7填充。

+0

如果它有助於繼承人的文件。 http://php.net/manual/en/function.mcrypt-module-open.php – Matt

回答

1

你的C#代碼並沒有真正看起來安全的,所以如果你可以改變它,請參閱下面的一些技巧。 下面是修改後的樣子可能是相當於給定的C#代碼你給PHP代碼。

function decryptAES128CBC($content,$iv, $key) { 

    // AES is Rijndael-128 
    $rijndael = 'rijndael-128'; 

    // key size is 128 bit = 16 bytes 
    $ks = 16; 

    // CBC mode, not OFB 
    $cp = mcrypt_module_open($rijndael, '', 'cbc', ''); 

    // pad key and IV by zeros (this is not a good idea) 
    $key = str_pad($key, $ks, "\0"); 
    $iv = str_pad($key, $iv, "\0"); 

    // initialize the decryptor with key and IV 
    mcrypt_generic_init($cp, $key, $iv); 

    // the actual work 
    $decrypted = mdecrypt_generic($cp, $content); 

    // clean up 
    mcrypt_generic_deinit($cp); 
    mcrypt_module_close($cp); 

    // remove padding, see below 
    return unpad($decrypted); 
} 

最後unpad是有以除去可能是由加密函數追加到放大消息大小爲完整數量的塊的填充。通過使用RijndaelManaged的默認填充是PKCS7-填充,其附加一字節數(16個1之間),其中的每一個等於添加的字節數。在真正的實現中,你會在解密之後檢查填充是否有效(即所有這些字節都具有相同的值),但對於「快速和骯髒」,你可以簡單地使用檢查最後一個字節並刪除那麼多字節的東西。示例請參見comments to mcrypt_decrypt

如果你可以改變你的C#代碼:

  • 注意,一般是不使用(每個鍵)的固定值作爲初始化向量是一個好主意,並使用該密鑰本身初始化矢量也不好,要麼。使用隨機初始化向量(與消息一起發送)或查看下一個點。另外,您通常不希望直接使用(相當短的)密碼作爲密鑰,而是使用更長的密碼短語,並將其與鹽(包含在消息中)進行哈希以得到密鑰。如果你這樣做,你也可以從相同的兩片的數據(但在某種程度上,他們將不同,使用密鑰導出函數)獲得初始化向量。 爲避免暴力破解加密文件中的密碼,請在此處使用慢哈希函數(PBKDF-2或bcrypt)。

+0

非常感謝你的詳細解答。我無法更改C#代碼,但是php代碼的信息足以解決我的問題。它確實有幫助。 – Taylantz