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

如何用Python解密Android端基于Bouncy Castle的AES加密Zip文件?

如何用Python解密Android端基于Bouncy Castle的AES加密Zip文件?

我仔细看了你的Kotlin加密代码和Python解密代码,问题主要出在几个细节上,我帮你梳理清楚并给出修正方案:

先说说Kotlin代码里的潜在问题

你的readFile方法有冗余且容易出错的逻辑:file.readBytes()已经完整读取了整个文件的字节内容,后面再用BufferedInputStream重复读取完全是多余的,甚至可能因为流操作覆盖正确的数据。可以直接简化成:

fun readFile(filePath: String): ByteArray {
    return File(filePath).readBytes()
}

另外,你在创建Cipher时只写了"AES",没有明确指定加密模式和填充方式。在Bouncy Castle中,默认的AES转换规则是AES/ECB/PKCS5Padding,但你又传入了IV参数(IvParameterSpec),这在ECB模式下是不合法的——能运行说明你的Android环境可能默认用了CBC模式,但为了避免歧义,建议明确指定模式和填充,把Cipher初始化改成:

val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC")

这样能和Python的实现完全对齐,减少兼容性问题。

再修正你的Python代码

你的Python逻辑大体方向是对的,但手动处理填充容易出错,而且可以优化一些细节,下面是修正后的代码:

from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import base64

def get_secret_key():
    # 替换为你从Android端拿到的Base64编码密钥(注意是NO_WRAP格式,无换行)
    secret_key_encoded = "这里替换为你的AES密钥Base64字符串"
    decoded_key = base64.b64decode(secret_key_encoded)
    # 256位AES密钥必须是32字节,加个断言确保正确性
    assert len(decoded_key) == 32, "AES密钥必须是256位(32字节)"
    return decoded_key

def decrypt_file(input_file_path, output_file_path=None):
    try:
        # 自动处理输出路径
        if output_file_path is None:
            if input_file_path.endswith('.encrypted'):
                output_file_path = input_file_path[:-len('.encrypted')]
            else:
                # 拆分文件名和后缀,添加_decrypted标识
                name_parts = input_file_path.rsplit('.', 1)
                if len(name_parts) == 2:
                    output_file_path = f"{name_parts[0]}_decrypted.{name_parts[1]}"
                else:
                    output_file_path = f"{input_file_path}_decrypted"

        # 读取加密文件的全部内容
        with open(input_file_path, 'rb') as f:
            encrypted_data = f.read()

        # 获取密钥和初始化IV(和Kotlin一致,用全0的16字节数组)
        key = get_secret_key()
        iv = bytes(16)

        # 初始化CBC模式的AES解密器
        cipher = AES.new(key, AES.MODE_CBC, iv=iv)
        # 用pycryptodome自带的工具解PKCS7填充(和PKCS5对AES是等价的)
        decrypted_data = unpad(cipher.decrypt(encrypted_data), AES.block_size)

        # 保存解密后的文件
        with open(output_file_path, 'wb') as f:
            f.write(decrypted_data)

        print(f"文件解密成功,已保存到: {output_file_path}")
        return True

    except Exception as e:
        print(f"解密出错了: {str(e)}")
        return False

# 示例调用
if __name__ == "__main__":
    encrypted_zip_path = "com.android.settings_1736318346774.zip"
    decrypt_file(encrypted_zip_path)

几个需要确认的关键点

  1. 确保你从Android端拿到的Base64密钥是无换行的(Kotlin用了Base64.NO_WRAP,所以Python解码时不用处理换行符);
  2. 检查你的pycryptodome库是不是最新版本,旧版本可能有兼容性问题:
    pip install --upgrade pycryptodome
    
  3. 如果解密后的文件还是无法解压,建议对比原Zip文件和解密后的文件的字节差异,或者检查Kotlin端的加密流程是否真的用了全0IV和CBC模式。

备注:内容来源于stack exchange,提问作者Rahim T.S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 13:35:32