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

PHP+OpenSSL解密报错error:1c800064的技术求助

问题分析与解决方案

问题概述

使用OpenSSL加密gzip文件后,解密时触发错误:error:1c800064:provider routines::bad decrypt。已排查点包括:PHP布尔变量验证密钥/IV一致、尝试二进制模式打开文件(原IV不一致问题已修正)、调整IV存储方式,但错误仍存在。环境配置:Ubuntu 22.04.3 LTS、PHP 8.1.22(cli)、OpenSSL 3.0.2。

核心排查方向与解决方案

1. 加密/解密参数严格对齐

bad decrypt最常见原因是加密、解密两端的算法配置不统一,需强制核对以下参数:

  • 算法与模式:确保加密和解密使用完全相同的算法(如AES-256-CBC),模式(CBC/ECB/GCM等)必须一致
  • 填充方式:PHP的openssl_encrypt默认使用PKCS7填充,解密时若手动指定填充需保持一致;若禁用填充(OPENSSL_ZERO_PADDING),需确保加密时也做相同设置并自行处理数据补位
  • 输出格式:加密时用OPENSSL_RAW_DATA输出二进制,解密时必须同样使用该参数,避免base64编码/解码环节出错

2. 密钥/IV的编码与存储验证

虽然已通过布尔值验证一致性,但需进一步确认二进制层面的匹配:

  • 打印密钥和IV的十六进制值对比(比布尔判断更精准):
    echo bin2hex($key) . PHP_EOL;
    echo bin2hex($iv) . PHP_EOL;
    
  • 确保密钥/IV是二进制数据:若从字符串生成,需通过hex2bin()或base64_decode()转换,避免直接用明文字符串作为密钥(除非通过KDF如hash_pbkdf2生成合法二进制密钥)

3. 文件操作强制二进制模式

全程使用二进制模式读写文件,防止系统自动转换换行符导致数据损坏:

  • 读取文件:file_get_contents($path, FILE_BINARY) 或 fopen($path, 'rb')
  • 写入文件:file_put_contents($path, $data, FILE_BINARY) 或 fopen($path, 'wb')

4. OpenSSL 3.0兼容性适配

OpenSSL 3.0对算法提供者的处理有变更,可尝试指定兼容提供者:

// 加密/解密时添加provider参数
$encrypted = openssl_encrypt($plaintext, $cipher, $key, $options, $iv, '', ['provider' => 'legacy']);
$decrypted = openssl_decrypt($ciphertext, $cipher, $key, $options, $iv, '', ['provider' => 'legacy']);

代码示例参考

加密流程

$inputFile = 'source.gz';
$outputFile = 'encrypted.bin';
$cipher = 'AES-256-CBC';
$key = hex2bin('your-32-byte-key-in-hex'); // 256位密钥需32字节二进制
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher));

// 读取二进制gzip内容
$plaintext = file_get_contents($inputFile, FILE_BINARY);
// 加密(输出二进制)
$encrypted = openssl_encrypt($plaintext, $cipher, $key, OPENSSL_RAW_DATA, $iv);
// 将IV前缀到加密数据前存储(或单独存储IV)
file_put_contents($outputFile, $iv . $encrypted, FILE_BINARY);

解密流程

$inputFile = 'encrypted.bin';
$outputFile = 'decrypted.gz';
$cipher = 'AES-256-CBC';
$key = hex2bin('your-32-byte-key-in-hex');

// 读取加密数据
$encryptedData = file_get_contents($inputFile, FILE_BINARY);
// 提取IV(AES块大小为16字节)
$ivLength = openssl_cipher_iv_length($cipher);
$iv = substr($encryptedData, 0, $ivLength);
$ciphertext = substr($encryptedData, $ivLength);
// 解密
$decrypted = openssl_decrypt($ciphertext, $cipher, $key, OPENSSL_RAW_DATA, $iv);
// 写入解密后的gzip文件
file_put_contents($outputFile, $decrypted, FILE_BINARY);

调试技巧

  • 对比加密前后gzip文件的MD5值:解密后文件的MD5应与原文件完全一致
  • 检查加密后数据长度:AES加密后的数据长度需为块大小的整数倍(含填充)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 15:53:44