2016-07-31 34 views
1

我想將用C#編寫的加密代碼移植到PHP。以下代碼使用Rijndael-128加密。 PHP代碼給出的結果與C#代碼略有不同。我受限於不使用Salt和隨機IV而不改變C#代碼。在瀏覽了關於這個問題的stackoverflow上的很多答案之後,仍然對代碼進行了一些更改,但代碼並未產生正確的結果。Rijndael C#到PHP轉換給出不同的結果

C#代碼(一類的成員函數)

public static string Encrypt(string plainText, string passPhrase) 
{ 
    byte[] initVectorBytes = Encoding.UTF8.GetBytes(initVector); 
    byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText); 
    var password = new Rfc2898DeriveBytes(passPhrase, new byte[8], 10000); 
    byte [] keyBytes= password.GetBytes(keysize/8); //256/8 
    var symmetricKey = new RijndaelManaged(); 
    symmetricKey.Mode = CipherMode.CBC; 
    ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes); 
    var memoryStream = new MemoryStream(); 
    var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write); 
    cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length); 
    cryptoStream.FlushFinalBlock(); 
    byte[] cipherTextBytes = memoryStream.ToArray(); 
    memoryStream.Close(); 
    cryptoStream.Close(); 

    return Convert.ToBase64String(cipherTextBytes); 
} 

PHP代碼(一類的成員函數)

public function encrypt(){ 

    $plainText="Same_input_as_above"; 

    $plainText=mb_convert_encoding($plainText,'UTF-8'); 

    $passPhrase=mb_convert_encoding($this->secret,'UTF-8'); 

    $salt=str_pad("",8,"\0"); 

    $key= hash_pbkdf2 ('sha1' , $passPhrase, $salt , 10000 ,self::KEYSIZE/8, true); 

    $initVector=mb_convert_encoding(self::INITVECTOR,'UTF-8'); 

    $tempCipher= mcrypt_encrypt (MCRYPT_RIJNDAEL_128 , $key , $plainText , MCRYPT_MODE_CBC,$initVector); 

    return base64_encode($tempCipher); 
} 

C#輸出

O/Fi4tfdS5APen6YAboRnr%2B2bSrHSG71OHhX7YZbbhJYr8mt3HxfYza4bjkV8gtq 

PHP輸出

O/Fi4tfdS5APen6YAboRnr%2B2bSrHSG71OHhX7YZbbhIpdOLx9oscZnlAdyTMgeGX 

C#的解密函數可以與自己創建的密碼正常工作,但在解碼PHP生成的密碼時出現Padding is invalid and cannot be removed.錯誤。

+0

最好不要使用mcrypt,它是棄用的,多年未更新並且不支持標準PKCS#7(néePKCS#5)填充,只有非標準的null填充甚至不能使用與二進制數據。 mcrypt有很多優秀的[bug](https://sourceforge.net/p/mcrypt/bugs/)可以追溯到2003年。相反,考慮使用[defuse](https://github.com/defuse/php-encryption)或者[RNCryptor](https://github.com/RNCryptor),他們提供了一個完整的解決方案,並且正在維護和正確。 – zaph

+0

@ ArtjomB。謝謝。首先,我認爲這是空的鹽,在填充零填充鹽後出現問題,我忘了取消註釋之後的純文本填充行。 – UDB

回答

1

問題是mcrypt只支持非標準的null填充。 C#庫支持標準PKCS#7(néePKCS#5)填充。見PKCS#7 padding

您可以輕鬆地添加和刪除PKCS#7填充加密之前和解密之後,在PHP中:

添加PKCS#7填充

$padLength = $blockSize - (strlen($clearText) % $blockSize); 
$clearText = $clearText . str_repeat(chr($padLength), $padLength); 

地帶PKCS#7填充

$padLength = ord($cryptText[strlen($cryptText)-1]); 
$cryptText = substr($cryptText, 0, strlen($cryptText) - $padLength); 

更好的解決方案是不要使用mcrypt。選項包括defuseRNCryptor,它們提供完整的解決方案。

+0

感謝您提出更好的解決方案,但解密時不需要刪除填充 – UDB

相關問題