[英]Password encrypted in php and trying to decrypt in VB
我有一個密碼,我正在使用openssl AES-256-CBC
在 php 中加密,我試圖在VB
中解密。 我在使用openssl_random_pseudo_bytes()
php function 生成的 IV 時遇到問題。如果我只是使用隨機 IV 字符串而不是調用openssl_random_pseudo_bytes()
,它返回 php 中的字節字符串,我的 VB 代碼將返回正確的解密密碼。 任何建議將不勝感激。
我有以下 php function 加密密碼:
function f_infr_encrypt_value($password, $key) {
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('AES-256-CBC'));
return trim(
base64_encode(
openssl_encrypt($value, "AES-256-CBC", $key, 0, $iv) . '::' . $iv));
}
我有以下 VB 代碼試圖解密由上面的 php function 創建的密碼
Private Function DecryptPassword(encryptedPassword As String, key As String) As String
Try
'Decode password from base 64
Dim base64Decoded As String
Dim data() As Byte
data = System.Convert.FromBase64String(encryptedPassword)
base64Decoded = System.Text.ASCIIEncoding.ASCII.GetString(data)
'Separating the password from the IV. Delimeter is "::"
Dim ivct = base64Decoded.Split({"::"}, StringSplitOptions.None)
'baseEncodedPassword is the password that is encrypted using AES-256-CBC
Dim baseEncodedPassword As String
baseEncodedPassword = ivct(0)
Dim iv As String = ivct(1)
Dim sEncryptedString As String = baseEncodedPassword
Dim myRijndael As New RijndaelManaged
myRijndael.Padding = PaddingMode.Zeros
myRijndael.Mode = CipherMode.CBC
myRijndael.KeySize = 256
myRijndael.BlockSize = 128
Dim keyByte() As Byte
Dim IVByte() As Byte
keyByte = System.Text.Encoding.ASCII.GetBytes(key)
IVByte = System.Text.Encoding.ASCII.GetBytes(iv)
Dim decryptor As ICryptoTransform = myRijndael.CreateDecryptor(keyByte, IVByte)
Dim sEncrypted As Byte() = Convert.FromBase64String(sEncryptedString)
Dim fromEncrypt() As Byte = New Byte(sEncrypted.Length) {}
Dim msDecrypt As New MemoryStream(sEncrypted)
Dim csDecrypt As New CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)
csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length)
Dim returnvalue = (System.Text.Encoding.ASCII.GetString(fromEncrypt))
Return returnvalue
Catch ex As Exception
Return ex.Message
End Try
End Function
VB代碼中有幾個問題:
在當前的 PHP 代碼中,密文隱含地由 openssl_encrypt 編碼為openssl_encrypt
,二進制 IV 與分隔符::
連接,順序為ciphertext | 四、 然后將結果再次編碼為 Base64。 在VB代碼中數據經過Base64解碼后轉為字符串。 這會破壞二進制 IV(另請參閱參考資料)。 由於其 Base64 解碼,密文未損壞。 為防止這種情況,不得執行到字符串的轉換。
注意:PHP 代碼中的串聯不必要地復雜。 通常 IV 和密文以沒有分隔符的二進制形式連接(通常按順序IV | ciphertext ),結果編碼為 Base64。 第二種變體是連接兩個部分,每個部分都采用 Base64 編碼形式,使用分隔符(s. Michael Fehr 的評論)。
openssl_encrypt
隱式使用 PKCS7 填充,在 VB 代碼中應用零填充(另請參見)。 這里也必須使用 PKCS7 填充。
在 VB 代碼中,明文存儲在一個Byte
數組中,該數組具有密文的長度。 由於padding導致密文比明文長,數組太大。 當例如使用StreamReader
時,這個問題就解決了。
此外,應Using
語句來釋放可能的系統資源。
一個可能的實現是:
Dim ciphertextSepIv() As Byte ciphertextSepIv = System.Convert.FromBase64String(encryptedPassword) Dim iv(16 - 1) As Byte 'arbitrary binary data, length: 16 bytes Dim ciphertext(ciphertextSepIv.Length - 1 - 2 - 16) As Char 'ASCII data (since Base64 encoded), length: ciphertext.Length - 2 - 16 bytes, 2 considers the delimiter :: Array.Copy(ciphertextSepIv, 0, ciphertext, 0, ciphertext.Length) Array.Copy(ciphertextSepIv, ciphertext.Length + 2, iv, 0, iv.Length) Dim rijndael As New RijndaelManaged rijndael.Padding = PaddingMode.PKCS7 'use PKCS7-Padding rijndael.Mode = CipherMode.CBC rijndael.KeySize = 256 rijndael.BlockSize = 128 Dim keyByte() As Byte keyByte = System.Text.Encoding.ASCII.GetBytes(key) Dim decryptor As ICryptoTransform = rijndael.CreateDecryptor(keyByte, iv) Dim encrypted As Byte() = Convert.FromBase64CharArray(ciphertext, 0, ciphertext.Length) Dim decryptedData As String = Nothing Using msDecrypt As New MemoryStream(encrypted) Using csDecrypt As New CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read) Using srDecrypt As New StreamReader(csDecrypt) 'return only the plain text (without whitespaces etc.) decryptedData = srDecrypt.ReadToEnd() End Using End Using End Using Return decryptedData
使用此 VB 代碼可以解密使用發布的 PHP 代碼加密的密文。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.