Skip to main content
 首页 » 编程设计

php之将 Php 中的 openssl AES 转换为 Python AES

2024年10月01日32虾米哥

我有一个 php 文件,如下所示:

$encryption_encoded_key = 'c7e1wJFz+PBwQix80D1MbIwwOmOceZOzFGoidzDkF5g='; 
 
function my_encrypt($data, $key) { 
    $encryption_key = base64_decode($key); 
    $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cfb')); 
 
    $encrypted = openssl_encrypt($data, 'aes-256-cfb', $encryption_key, 1, $iv); 
 
    // The $iv is just as important as the key for decrypting, so save it with encrypted data using a unique separator (::) 
    return base64_encode($encrypted . '::' . $iv); 
} 
 
function my_decrypt($data, $key) { 
    // Remove the base64 encoding from key 
    $encryption_key = base64_decode($key); 
 
    // To decrypt, split the encrypted data from IV - unique separator used was "::" 
    list($encrypted_data, $iv) = explode('::', base64_decode($data), 2); 
 
    return openssl_decrypt($encrypted_data, 'aes-256-cfb', $encryption_key, 1, $iv); 
} 
 
$data = 'USER_ID||NAME||EMAIL||MOBILE'; 
$data_encrypted = my_encrypt($data, $encryption_encoded_key); 
echo $data_encrypted; 
$data_decrypted = my_decrypt($data_encrypted, $encryption_encoded_key); 
echo "Decrypted string: ". $data_decrypted; 

这工作正常,并且能够使用加密 key 加密/解密,现在我还有一个 python 文件:

import hashlib 
import base64 
from Crypto.Cipher import AES 
from Crypto import Random 
 
encryption_encoded_key = 'c7e1wJFz+PBwQix80D1MbIwwOmOceZOzFGoidzDkF5g=' 
 
def my_encrypt(data, key): 
    #Remove the base64 encoding from key 
    encryption_key = base64.b64decode(key) 
    #Generate an initialization vector 
    bs = AES.block_size 
    iv = Random.new().read(bs) 
 
    cipher = AES.new(encryption_key, AES.MODE_CFB, iv) 
    #Encrypt the data using AES 256 encryption in CBC mode using our encryption key and initialization vector. 
    encrypted = cipher.encrypt(data) 
 
    #The iv is just as important as the key for decrypting, so save it with encrypted data using a unique separator (::) 
    return base64.b64encode(encrypted + '::' + iv) 
 
 
def my_decrypt(data, key): 
    #Remove the base64 encoding from key 
    encryption_key = base64.b64decode(key) 
 
    #To decrypt, split the encrypted data from IV - unique separator used was "::" 
    encrypted_data, iv = base64.b64decode(data).split('::') 
 
    cipher = AES.new(encryption_key, AES.MODE_CFB, iv) 
 
    return cipher.decrypt(encrypted_data) 
 
data = 'USER_ID||NAME||EMAIL||MOBILE' 
 
print "Actual string: %s" %(data) 
data_encrypted = my_encrypt(data, encryption_encoded_key) 
print data_encrypted 
 
data_decrypted = my_decrypt(data_encrypted, encryption_encoded_key) 
print "Decrypted string: %s" %(data_decrypted) 

当我尝试从 python 中使用它时,它也能正常工作,它能够加密/解密输入字符串, 我想使用 php 文件加密并在 python 中解密输出,两者都应该使用 CFB 模式的 AES 256 加密,我做错了什么?

请您参考如下方法:

使用CFB mode您需要为其指定段大小。 OpenSSL 有 aes-256-cfb(即 128 位)、aes-256-cfb1(即 1 位)和 aes-256-cfb8(8 位)(以及 AES-128 和 192 的类似模式)。所以你在你的 php 代码中使用了 128 位 cfb。

Python 库接受 AES.new 的 segment_size 参数,但默认值为 8,因此您在两个版本。

要获取 Python 代码来解密 PHP 代码的输出,请将长度为 128 的段添加到密码对象:

cipher = AES.new(encryption_key, AES.MODE_CFB, iv, segment_size=128) 

(注意,这是使用更新的 PyCryptodome fork 的 PyCrypto。PyCrypto 在这里有一个错误,不会工作。)

或者,您可以通过设置密码让 PHP 代码使用 CFB-8(显然不要同时更改两者):

$encrypted = openssl_encrypt($data, 'aes-256-cfb8', $encryption_key, 1, $iv);