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

将Python文件解密逻辑转PHP遇归档损坏及解密错误问题排查

PHP实现三星.enc4文件解密遇损坏归档问题

背景

基于samloader项目的解密逻辑,在PHP中实现三星固件.enc4文件解密时,得到损坏的归档文件,但控制台用openssl命令可以正常解密,需要排查问题并修复。

核心疑问

Python代码中hashlib.md5(deckey.encode()).digest()转成PHP的$key = hash('md5', $deckey, true);是否正确?

现有代码问题

初始版本代码

<?php
$source = 'file.zip.enc4';
$dest = 'file.zip';

$source = fopen($source, 'r');
$dest = fopen($dest, 'w');
$chunkSize = 4096;
while (!feof($source)) {
    $chunk = fread($source, $chunkSize + 1);
    if (!$chunk) {
        break;
    }
    $encryptedChunk = openssl_decrypt($chunk, 'aes-128-ecb', $key, OPENSSL_RAW_DATA);
    fwrite($dest, $encryptedChunk);
}
fclose($source);
fclose($dest);
?>
  • 问题:解密后的归档文件损坏

添加OPENSSL_ZERO_PADDING后的错误

修改代码添加该参数后,出现以下错误:

string(58) "error:1C80006B:Provider routines::wrong final block length"

问题排查与解决方案

1. MD5密钥转换验证

hash('md5', $deckey, true)是正确的:

  • PHP中hash函数第三个参数设为true时,返回原始二进制数据,和Python的digest()行为完全一致;如果设为false(默认)则返回十六进制字符串,对应Python的hexdigest()。

2. 修正分块解密逻辑

AES-128-ECB要求输入数据长度必须是16字节(块大小)的整数倍,初始代码的分块逻辑存在问题:

  • $chunkSize +1会导致读取的块长度不规整,破坏ECB模式的块对齐要求
  • 三星.enc4加密使用PKCS#7填充(openssl默认填充方式),不需要手动添加OPENSSL_ZERO_PADDING

修正后的代码:

<?php
$sourcePath = 'file.zip.enc4';
$destPath = 'file.zip';
$deckey = '你的解密密钥';
$key = hash('md5', $deckey, true); // 确保密钥为二进制格式

// 以二进制模式读写,避免Windows下换行符转换
$source = fopen($sourcePath, 'rb');
$dest = fopen($destPath, 'wb');
$blockSize = 16; // AES-128的块大小
$chunkSize = 4096; // 必须是blockSize的整数倍,4096=16*256,符合要求

while (!feof($source)) {
    $chunk = fread($source, $chunkSize);
    $chunkLen = strlen($chunk);
    if ($chunkLen === 0) break;
    
    $decryptedChunk = openssl_decrypt($chunk, 'aes-128-ecb', $key, OPENSSL_RAW_DATA);
    if ($decryptedChunk === false) {
        die("解密失败: " . openssl_error_string());
    }
    fwrite($dest, $decryptedChunk);
}

fclose($source);
fclose($dest);
?>

3. 备用方案:调用系统openssl命令

如果PHP openssl扩展存在兼容性问题,可以直接调用系统openssl命令(需确保服务器允许exec函数,且openssl路径正确):

<?php
$sourcePath = 'file.zip.enc4';
$destPath = 'file.zip';
$deckey = '你的解密密钥';
$keyHex = hash('md5', $deckey); // openssl命令需要十六进制格式的密钥

// 复制你控制台能正常解密的命令结构,调整参数
$command = sprintf(
    'openssl enc -d -aes-128-ecb -in "%s" -out "%s" -K %s',
    escapeshellarg($sourcePath),
    escapeshellarg($destPath),
    $keyHex
);

exec($command, $output, $returnCode);
if ($returnCode !== 0) {
    die("命令执行失败: " . implode("\n", $output));
}
?>
  • 提示:如果你的控制台解密命令需要-nopad参数,就把它加到命令里;不需要则去掉,以实际能正常运行的命令为准。

关键注意事项

  • 确保$deckey和samloader中使用的密钥完全一致,注意编码(比如UTF-8)不要出错
  • 必须用二进制模式(rb/wb)读写文件,避免Windows环境下的换行符自动转换破坏二进制数据
  • AES-128-ECB模式不需要初始化向量(IV),因此无需额外设置IV参数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 14:34:57