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

PHP与OpenSSL命令行实现大文件互加解密的兼容问题

PHP大文件分块加密与OpenSSL命令行兼容方案

问题背景

需要实现PHP与OpenSSL命令行的互加解密:PHP加密的文件能通过OpenSSL命令解密,反之亦然。小文件加密方案可正常通过以下命令解密:

openssl enc -p -d -aes-256-cbc -in php-encrypted.bin -out decrypted.txt -pass file:my.key

但针对大文件修改为分块加密后,生成的文件无法被上述命令解密,需调整分块逻辑,兼顾内存占用与兼容性。

问题根源

原分块加密代码存在两个关键问题:

  • CBC模式下,每一块加密的IV应该是上一块加密后的密文(初始IV由EVP_BytesToKey生成),但原代码每次都使用初始IV,破坏了CBC的链式加密逻辑。
  • 未正确处理分块加密时的状态延续,导致密文格式与OpenSSL命令行生成的不兼容。

修正后的大文件分块加密代码

1. 实现OpenSSL兼容的EVP_BytesToKey函数

PHP没有内置该函数,需手动实现:

function EVP_BytesToKey(string $salt, string $password): string
{
    $keyIv = '';
    $data = '';
    while (strlen($keyIv) < 32 + 16) { // AES-256需要32位key + 16位IV
        $data = hash('md5', $data . $password . $salt, true);
        $keyIv .= $data;
    }
    return $keyIv;
}

2. 修正后的分块加密逻辑

$salt = random_bytes(8);
$saltPrefix = "Salted__" . $salt;
$password = file_get_contents('my.key');
$keyIv = EVP_BytesToKey($salt, $password);
$key = substr($keyIv, 0, 32);
$iv = substr($keyIv, 32, 16); // 初始IV

$FILE_ENCRYPTION_BLOCKS = 64; // 每块处理64*16=1024字节
$blockSize = 16; // AES块大小

if ($fpOut = fopen('php-encrypted.bin', 'w')) {
    fwrite($fpOut, $saltPrefix);
    if ($fpIn = fopen('confidential.txt', 'rb')) {
        while (!feof($fpIn)) {
            $plaintext = fread($fpIn, $blockSize * $FILE_ENCRYPTION_BLOCKS);
            
            // 加密:OPENSSL_RAW_DATA会自动添加PKCS#7填充
            $encrypted = openssl_encrypt(
                $plaintext,
                'AES-256-CBC',
                $key,
                OPENSSL_RAW_DATA,
                $iv
            );
            
            fwrite($fpOut, $encrypted);
            
            // 更新IV:CBC模式下,下一块的IV是当前块的密文最后16字节
            $iv = substr($encrypted, -$blockSize);
        }
        fclose($fpIn);
    }
    fclose($fpOut);
}

验证方法

用上述代码加密大文件后,执行原OpenSSL解密命令即可正常解密:

openssl enc -p -d -aes-256-cbc -in php-encrypted.bin -out decrypted.txt -pass file:my.key

额外说明

  • 确保my.key文件的编码和权限正确(命令行读取时不会出现问题)。
  • 分块大小可根据内存情况调整,建议保持为AES块大小(16字节)的整数倍。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 11:01:01