如何修复python和php解密错误

问题描述 投票:0回答:1

这是我的 php 函数

<?function encrypt_decrypt($action, $string) {
    $output = false;
    $encrypt_method = "AES-256-CBC";
    $secret_key = '3752395n39572395m82219vc5b13';
    $secret_iv = '67b349vm13408vm2035983v6n2390';
    $key = hash('sha256', $secret_key);
    $iv = substr(hash('sha256', $secret_iv), 0, 16);
    if ($action == 'encrypt') {
        $output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
        $output = base64_encode($output);
    } else if ($action == 'decrypt') {
        $output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
    }
    return $output;
}

这是我的Python函数

def decrypt(encrypted_string, secret_key, secret_iv):
    # Hash key and IV
    key = hashlib.sha256(secret_key.encode()).digest()  # Create binary key
    iv = hashlib.sha256(secret_iv.encode()).digest()[:16]  # First 16 bytes for IV
    # Decode the Base64 encoded string
    decoded_data = base64.b64decode(encrypted_string)
    # Create a cipher object for decryption
    cipher = AES.new(key, AES.MODE_CBC, iv)
    # Decrypt the output
    decrypted_padded = cipher.decrypt(decoded_data)
    # Unpad the output (PKCS7 padding)
    decrypted = unpad(decrypted_padded, AES.block_size)
    return decrypted.decode('utf-8')

当我使用 php 加密字符串时,无法使用 python 解密,出现此错误

Decryption failed: Data must be padded to 16 byte boundary in CBC mode
我该如何解决此问题?我想使用 php 加密并使用 python 解密。

python php encryption pycrypto
1个回答
0
投票

您遇到的错误消息

Decryption failed: Data must be padded to 16 byte boundary in CBC mode
表明 PHP 和 Python 之间处理加密数据的方式存在问题。这通常发生在加密/解密过程中,例如密钥或 IV 处理使用不当、填充不正确或数据编码不匹配。

你可以做的是这样的:


<?php 
function encrypt_decrypt($action,$string) {
   $output = false;
   $encrypted_method = "AES-256-CBC";
   $secret_key = 'your-secret-key';
   $secret_iv = 'your-secret-iv';

   $key = hash('sha256', $secret_key, true);
   $iv = substr(hash('sha256', $secret_iv,true),0,16);

   if($action = 'encrypt') {
       $encrypted = openssl_encrypt($string,$encrypt_method, $key,OPENSSL_RAW_DATA, $iv);
       $output = base64_encode($encrypted);
    } else if ($action = 'decrypt') {
       $decoded = base64_decode($string);
       $output = openssl_decrypt($decoded, $encrypt_method, $key, OPENSSL_RAW_DATA, $iv);
    }
    return $output;
}

// Example use:
$string = 'foo-bar-string';
$encrypted = encrypt_decrypt('encrypt',$string);
// encrypted holds the encrypted string 

解密:

$decrypted = encrypt_decrypt('decrypt', $string);
// decrypted holds the decrypted string which can be then converted to json or array.

Python:

import hashlib, base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad

def decrypt(encrypted_string, secret_key, secret_iv):
    key = hashlib.sha256(secret_key.encode()).digest()  # 32 bytes
    iv = hashlib.sha256(secret_iv.encode()).digest()[:16]  # 16 bytes
    
    try:
        decoded_data = base64.b64decode(encrypted_string)
    except Exception as e:
        raise ValueError(f"Base64 decoding failed: {e}")    
    cipher = AES.new(key, AES.MODE_CBC, iv)
    
    decrypted_padded = cipher.decrypt(decoded_data)
    
    try:
        decrypted = unpad(decrypted_padded, AES.block_size)
    except ValueError as e:
        raise ValueError(f"Unpadding failed: {e}")
    
    return decrypted.decode('utf-8')

# Example usage
if __name__ == "__main__":
    encrypted = "VtA3Q8O4M+wq3kQ1MH2L0w=="  # Replace with your actual encrypted string from PHP
    secret_key = 'your-secret-key-here' // ensure both php and python have same values
    secret_iv = 'your-secret-iv-here' // ensure both php and python have same values

    try:
        decrypted = decrypt(encrypted, secret_key, secret_iv)
        print("Decrypted:", decrypted)
    except Exception as e:
        print("Decryption error:", e)

对于 javascript,我想创建一个 aes.js 文件来加密或解密:

  doEncrypt(plainText) {
    const encrypted = CryptoJS.AES.encrypt(
      plainText,
      this.times, {
      iv: CryptoJS.enc.Latin1.parse(this.iv),
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7
    })
    return encrypted.ciphertext.toString(CryptoJS.enc.Base64)
  }

  doDecrypt(cipherText) {
    // this.generateKey(this.salt, this.passPhrase)
    const decrypted = CryptoJS.AES.decrypt(
      cipherText,
      this.times, {
      iv: CryptoJS.enc.Latin1.parse(this.iv),
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7
    })
    return decrypted.toString(CryptoJS.enc.Utf8)
  }

** 请注意** 每个人都有自己的加密标准,因此您可以根据自己的要求调整代码。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.