簡體   English   中英

在 php 中加密並嘗試在 VB 中解密的密碼

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM