PHP openssl_encrypt加密内容无法用Python pyca/cryptography解密求助
问题分析与解决
核心问题出在PHP的密钥处理环节:你在PHP中使用hash_pbkdf2时将最后一个参数raw_output设为FALSE,这会返回十六进制编码的字符串,但openssl_encrypt需要的是原始二进制格式的密钥。此时PHP实际使用的是十六进制字符串的ASCII字节作为密钥,而非PBKDF2推导的原始二进制密钥,导致和Python端的密钥逻辑不匹配,最终解密失败。
修正后的PHP脚本
将hash_pbkdf2的raw_output参数改为TRUE,直接获取原始二进制密钥:
<?php $pass = "password"; $salt = "salt"; $data = "here is a test message"; $cipher = "aes-256-cbc"; $options = OPENSSL_RAW_DATA; $rnds = 1024; $klen = 32; // AES-256固定需要32字节密钥,无需设为64 // 改为raw_output=TRUE,获取原始二进制密钥 $key = hash_pbkdf2("sha256", $pass, $salt, $rnds, $klen, TRUE); echo("Key hex = '" . bin2hex($key) . "'<br>"); $iv = openssl_random_pseudo_bytes(16); $enc = openssl_encrypt($data, $cipher, $key, $options, $iv); echo("IV = '" . base64_encode($iv) . "'<br>"); echo("Encrypted = '" . base64_encode($enc) . "'<br>"); ?>
补充说明
- AES-256固定需要32字节密钥,因此
$klen直接设为32即可,避免生成不必要的字节。 - 用
bin2hex($key)输出密钥的十六进制形式,方便和Python端的key.hex()结果对比验证。
验证Python脚本
使用修正后的PHP输出的IV和密文,Python脚本无需修改即可正常解密:
import base64 from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC kdf = PBKDF2HMAC( algorithm=hashes.SHA256(), length=32, salt=b'salt', iterations=1024 ) key = kdf.derive(b'password') print(key.hex()) iv = base64.b64decode('修正后的IV') enc = base64.b64decode('修正后的密文') cipher = Cipher(algorithms.AES(key), modes.CBC(iv)) decryptor = cipher.decryptor() plain = decryptor.update(enc) + decryptor.finalize() print(plain.decode('utf-8')) # 输出: here is a test message
内容的提问来源于stack exchange,提问作者barneyAgumble
相关产品推荐
相关产品推荐

