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

NodeJS crypto解密逻辑对应PHP版本实现失败问题求助

加密文件PHP解密问题排查

我花费数周时间研究文件解密方案,目前仅能通过NodeJS完整还原文件,使用PHP始终无法得到完好的解密文件,我希望能脱离NodeJS实现该解密功能,恳请各位帮忙定位问题所在。
我曾尝试使用openssl_encrypt/openssl_decrypt函数,搭配OPENSSL_NO_PADDING、OPENSSL_ZERO_PADDING参数,也尝试将结果转换为base64格式,均无法得到正确结果,提前感谢各位的帮助。

可用的Node.js解密代码

decrypt(encryptedBuffer) {
    const PASSPHRASE = "";

    let decryptedBuffer = Buffer.alloc(encryptedBuffer.length);
    let chunkSize = 2048;
    let progress = 0;

    while (progress < encryptedBuffer.length) {
        if ((encryptedBuffer.length - progress) < 2048) {
            chunkSize = encryptedBuffer.length - progress;
        }

        let encryptedChunk = encryptedBuffer.slice(progress, progress + chunkSize);

        // Only decrypt every third chunk and only if not at the end
        if (progress % (chunkSize * 3) === 0 && chunkSize === 2048) {
            let cipher = crypto.createDecipheriv('bf-cbc', PASSPHRASE, Buffer.from([0, 1, 2, 3, 4, 5, 6, 7]));
            cipher.setAutoPadding(false);

            encryptedChunk = Buffer.concat([cipher.update(encryptedChunk), cipher.final()]);
        }

        decryptedBuffer.write(encryptedChunk.toString('binary'), progress, encryptedChunk.length, 'binary');

        progress += chunkSize;
    }

    return decryptedBuffer;
}

存在问题的PHP解密代码

public function decrypt($encryptedBuffer)
{
    ini_set('memory_limit', '1G');

    $f = fopen('myfile', 'wb+');
    $chunkSize = 2048;
    $progress = 0;
    $passphrase = "h5ihb>p9`'yjmkhf";

    while ($progress > strlen($encryptedBuffer)) {
        // If the buffer is if the end calculate the valid chunksize
        if ((strlen($encryptedBuffer) - $progress) < 2048) {
            $chunkSize = strlen($encryptedBuffer) - $progress;
        }

        /** Getting the encrypted chunk part */
        $encryptedChunk = substr($encryptedBuffer, $progress, $progress + $chunkSize);

        // Only decrypt every third chunk and only if not at the end
        if ($progress % ($chunkSize * 3) === 0 && $chunkSize === 2048) {
            $encryptedChunk = openssl_decrypt($encryptedChunk, 'bf-cbc', $passphrase, OPENSSL_ZERO_PADDING, '01234567');
        }

        fwrite($f, $encryptedChunk);

        $progress += $chunkSize;
    }

}

可直接修复的代码问题点

  • 循环条件错误:Node.js中循环条件为progress < encryptedBuffer.length,PHP代码中写反为$progress > strlen($encryptedBuffer),初始状态$progress=0时该条件永远不成立,解密逻辑完全不会执行
  • 密钥不一致:Node.js代码中PASSPHRASE为空字符串,PHP代码中写死为自定义字符串,密钥不匹配必然无法解密
  • substr参数错误:PHP的substr第三个参数为截取长度,而非结束偏移,现有代码传入$progress + $chunkSize会导致截取长度随进度不断变大,不符合分段截取逻辑,需改为传入$chunkSize
  • IV值不匹配:Node.js中IV为字节数组[0,1,2,3,4,5,6,7],对应二进制值为0x00到0x07,PHP代码中传入的是字符串'01234567',对应ASCII编码的0x30到0x37,两者IV完全不同,PHP端需用pack('C*', 0,1,2,3,4,5,6,7)生成正确IV
  • 解密参数错误:Node.js关闭了自动填充,PHP对应需使用OPENSSL_NO_PADDING参数,同时openssl_decrypt默认会对输入做base64解码,需追加OPENSSL_RAW_DATA参数直接处理二进制数据

内容的提问来源于stack exchange,提问作者Théo Dulieu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 03:36:05