You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python与PHP中AES-256-CBC加密结果不一致,求解决方案

AES-256-CBC加密:Python与PHP输出不一致的解决方法

问题重现

Python代码与输出

from Crypto.Random import get_random_bytes
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import base64

def encrypt_string(input_string, key_base64, str_iv):
    try:
        key = key_base64.encode('utf-8')
    
        if str_iv:
            iv = base64.b64decode(str_iv)
        else:
            iv = get_random_bytes(16)

        cipher = AES.new(key, AES.MODE_CBC, iv)
        padded_data = pad(input_string.encode(), AES.block_size)
        cipher_data = cipher.encrypt(padded_data)
        combined_data = iv + cipher_data
        return base64.b64encode(combined_data).decode()

    except Exception as e:
        print(e)

if __name__ == "__main__":
    key = "1bd393e7a457f9023d9ba95fffb5a2e1"
    iv = "1oTOhV9xGyu1mppmWZWa5w=="
    input_string = "AAAAAAA"
    encrypted_data = encrypt_string(input_string, key, iv)
    print("Encrypted string:", encrypted_data)

输出:

Encrypted string: 1oTOhV9xGyu1mppmWZWa5+kzveiTRzRH+gRVHx+7Ad0=

PHP代码与输出

<?php
function encrypt_string($input_string, $key_base64, $str_iv) {
    try {
        $key = base64_decode($key_base64);

        if ($str_iv) {
            $iv = base64_decode($str_iv);
        } else {
            $iv = openssl_random_pseudo_bytes(16);
        }
        $ciphertext = openssl_encrypt($input_string, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
        $combined_data = $iv . $ciphertext;
        return base64_encode($combined_data);
    } catch (Exception $e) {
        echo $e->getMessage();
    }
}
$key = "1bd393e7a457f9023d9ba95fffb5a2e1";
$iv = "1oTOhV9xGyu1mppmWZWa5w==";
$input_string = "AAAAAAA";
$encrypted_data = encrypt_string($input_string, $key, $iv);
echo "Encrypted string: " . $encrypted_data . "\n";
?>

输出:

Encrypted string: 1oTOhV9xGyu1mppmWZWa53Nc8rxWTultBWLvWitUICQ=

核心差异原因

两段代码的密钥处理逻辑完全不一致:

  • Python直接将传入的key字符串编码为UTF-8字节作为AES密钥(长度32字节,符合AES-256的密钥要求)。
  • PHP对传入的key字符串执行base64_decode操作,得到24字节数据,不符合AES-256的32字节密钥要求,openssl会自动用零填充补全至32字节,最终导致两边使用的密钥完全不同,加密结果自然不一致。

注:两边填充逻辑一致,均默认使用PKCS7填充,无差异。

修正方案

方案1:修改PHP代码(推荐)

将PHP密钥处理逻辑改为与Python一致,直接使用key的UTF-8字节作为密钥:

<?php
function encrypt_string($input_string, $key_base64, $str_iv) {
    try {
        // 替换base64_decode为直接使用字符串(PHP字符串默认是字节串)
        $key = $key_base64;

        if ($str_iv) {
            $iv = base64_decode($str_iv);
        } else {
            $iv = openssl_random_pseudo_bytes(16);
        }
        $ciphertext = openssl_encrypt($input_string, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
        $combined_data = $iv . $ciphertext;
        return base64_encode($combined_data);
    } catch (Exception $e) {
        echo $e->getMessage();
    }
}
$key = "1bd393e7a457f9023d9ba95fffb5a2e1";
$iv = "1oTOhV9xGyu1mppmWZWa5w==";
$input_string = "AAAAAAA";
$encrypted_data = encrypt_string($input_string, $key, $iv);
echo "Encrypted string: " . $encrypted_data . "\n";
?>

修正后输出:

Encrypted string: 1oTOhV9xGyu1mppmWZWa5+kzveiTRzRH+gRVHx+7Ad0=

与Python代码输出完全一致。

方案2:修改Python代码(若需保持PHP原密钥逻辑)

若必须使用base64_decode后的密钥,需手动补全至32字节(模拟openssl的零填充行为):

from Crypto.Random import get_random_bytes
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import base64

def encrypt_string(input_string, key_base64, str_iv):
    try:
        # 模拟PHP的密钥处理:base64解码后补零至32字节
        key = base64.b64decode(key_base64)
        if len(key) < 32:
            key += b'\x00' * (32 - len(key))
    
        if str_iv:
            iv = base64.b64decode(str_iv)
        else:
            iv = get_random_bytes(16)

        cipher = AES.new(key, AES.MODE_CBC, iv)
        padded_data = pad(input_string.encode(), AES.block_size)
        cipher_data = cipher.encrypt(padded_data)
        combined_data = iv + cipher_data
        return base64.b64encode(combined_data).decode()

    except Exception as e:
        print(e)

if __name__ == "__main__":
    key = "1bd393e7a457f9023d9ba95fffb5a2e1"
    iv = "1oTOhV9xGyu1mppmWZWa5w=="
    input_string = "AAAAAAA"
    encrypted_data = encrypt_string(input_string, key, iv)
    print("Encrypted string:", encrypted_data)

修正后输出:

Encrypted string: 1oTOhV9xGyu1mppmWZWa53Nc8rxWTultBWLvWitUICQ=

与原PHP代码输出完全一致。


内容的提问来源于stack exchange,提问作者Dafahan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 02:19:54