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
相关产品推荐
相关产品推荐

