2016-12-07 125 views
2

下面的代碼是一個簡單的.NET代碼片段,其輸入爲test,它返回p+cTm2VODfvQnreAl02wUQ==作爲輸出。將.net aes256加密代碼轉換爲php

Dim aesEncryptObj As New System.Security.Cryptography.RijndaelManaged() 
Dim encoder As System.Text.ASCIIEncoding = New System.Text.ASCIIEncoding() 

Dim tempKey As Byte() = encoder.GetBytes("00000011111111111111111111111111") 
aesEncryptObj.Key = tempKey 
aesEncryptObj.BlockSize = 128 
aesEncryptObj.Mode = System.Security.Cryptography.CipherMode.ECB 
aesEncryptObj.Padding = System.Security.Cryptography.PaddingMode.PKCS7 
aesEncryptObj.GenerateIV() 

Dim EncryptedBytes As Byte() 
Dim encryptor As System.Security.Cryptography.ICryptoTransform = aesEncryptObj.CreateEncryptor(aesEncryptObj.Key, aesEncryptObj.IV) 

Using msEncrypt As New System.IO.MemoryStream() 
    Using csEncrypt As New System.Security.Cryptography.CryptoStream(msEncrypt, encryptor, System.Security.Cryptography.CryptoStreamMode.Write) 
     Using swEncrypt As New System.IO.StreamWriter(csEncrypt) 
      swEncrypt.Write(txtInput.Text) 
     End Using 
     EncryptedBytes = msEncrypt.ToArray() 
    End Using 
End Using 

txtOutput.Text = Convert.ToBase64String(EncryptedBytes) 

現在,這裏是PHP代碼:

const ENCRYPT_METHOD = 'aes-256-ecb'; 

$aesKey = pack('H*', '00000011111111111111111111111111'); 
$ivSize = openssl_cipher_iv_length(ENCRYPT_METHOD); 

$plainText = "test"; 

$iv = openssl_random_pseudo_bytes($ivSize); 

$cipherText = openssl_encrypt(
    $plainText, 
    ENCRYPT_METHOD, 
    $aesKey, 
    OPENSSL_RAW_DATA, 
    $iv 
); 

$encryptedText = $iv . $cipherText; 

echo base64_encode($encryptedText); 

它返回1W3UvYVNKWEoFrpPZPd+Qw==從.NET一個不同。我已經嘗試了aes-256-ecb和aes-128-ecb,結果總是與.NET不同。

據我所知,openssl_encrypt默認做PKCS7填充,是嗎?你能看到PHP給出不同結果的原因嗎?

回答

5

您的代碼不工作,因爲:

  • 在.NET GetBytes將返回該字符串的字節值。也就是說,你將得到長度爲32(AES-256)的字節數組。然而,pack在PHP中與H*解碼一個十六進制字符串,它將給你一個長度爲16(AES-128)的密鑰。這整個時間你一直用兩個不同的密鑰加密,但兩個不同的密鑰大小

解決上述問題將會使您的代碼正常工作,但它會是,遠離實際安全且不應使用。如果您想讓代碼安全,您需要:

  • 停止使用ECB模式。如果可以,請使用GCM模式,否則使用CBC。你很可能最終會使用CBC。如果這樣做,則需要在密文前面加上IV,這樣解密方可以檢索並在解密時使用它。 IVs不需要保密,它們只需要是隨機的,所以使用OpenSSL隨機字節和GenerateIV方法是很好的。
  • 由於您很可能要使用CBC模式,因此您需要應用HMAC以確保完整性。否則,任何人都可以修改你的密文,你不會知道。當應用HMAC時,始終使用encrypt-then-mac。請記住在應用HMAC之前在之前包含您的IV
  • 最後,我不認爲你真的打算這樣做,但從不使用字符串的ASCII值作爲關鍵。如果您想從密碼創建密鑰,則應該應用KDF。 PBKDF2可能是最適合的,並且在PHP和.NET中都有實現。
+0

謝謝您對該問題的完整分析。我將進一步調查並在當天晚些時候接受答案。 –

+0

你釘了它!我知道ECB模式並不安全,但是我正在使用一個封閉源設備向我發送加密數據。這將是接下來要做的事 - 當通信協議驗證完全實施時,要求改變模式。再次感謝你,你保存了我的一天,因爲我幾乎沒有.NET知識,是的,我們很可能會使用CBC。 –

+0

@StanimirStoyanov樂於幫助。對你來說很好,因爲它迫使密切的開源開發者實施更安全的方法! –