Java解密Python加密WAV文件仅兼容部分脚本的问题排查
您好!我仔细对比了您提供的两个Python加密脚本和Java解密代码,找到了几个可能导致Script B加密文件解密失败的关键问题,下面逐一分析说明:
1. Java代码读取加密数据的致命bug
您的Java解密代码中,读取加密数据的逻辑存在严重问题:
byte[] inputBytes = new byte[(int)inputFile.length() - 16]; inputStream.read(inputBytes);
InputStream.read(byte[])方法无法保证一次性读取完所有指定字节,它只会返回本次实际读取的字节数。如果Script B加密的文件体积较大,这行代码会导致读取的加密数据不完整,解密后的文件自然损坏;而Script A加密的文件可能较小,刚好能一次性读取完成,所以能正常解密。
修复方式:循环读取完整的加密数据
把上述代码替换为循环读取的逻辑,确保获取全部加密数据:
byte[] inputBytes = new byte[(int)inputFile.length() - 16]; int totalBytesRead = 0; while (totalBytesRead < inputBytes.length) { int bytesRead = inputStream.read(inputBytes, totalBytesRead, inputBytes.length - totalBytesRead); if (bytesRead == -1) break; // 提前到达文件末尾,可在此处添加异常处理 totalBytesRead += bytesRead; }
2. 密钥处理的一致性问题
首先要明确:AES密钥长度必须是128/192/256位(对应16/24/32字节),而bytes.fromhex('ABC')这种奇数长度的十六进制字符串,在Python中会直接抛出ValueError,说明您实际代码中的密钥肯定是偶数长度的。但需要确认:
- Script A和Script B中使用的密钥完全一致(包括十六进制字符串的长度和内容)
- Java的
hexStringToByteArray方法对奇数长度的密钥会忽略最后一个字符,如果您的密钥字符串是奇数长度,会导致Java端的密钥与Python端不一致,直接引发解密失败
3. 流模式下不必要的PKCS7填充
您的两个Python脚本都使用了AES-CFB模式(流加密模式),但却对明文做了PKCS7填充。流模式完全不需要对明文进行填充,因为它是逐字节处理数据的。这种多余的填充会导致解密后的数据尾部多出填充字节,虽然部分WAV播放器可能忽略尾部噪音,但这是不规范的做法,也可能在某些场景下导致文件解析失败。
优化建议:移除Python脚本中的填充步骤
修改两个Python脚本的加密流程,删除填充相关代码:
# 删掉以下填充代码 # padder = padding.PKCS7(algorithms.AES.block_size).padder() # padded_data = padder.update(data) + padder.finalize() # 直接加密原始文件数据 encrypted_data = encryptor.update(data) + encryptor.finalize()
调整后,Java解密后无需额外处理,直接写入文件即可。
4. 脚本运行环境的差异排查
还要确认Script B的运行环境与Script A完全一致:
- 两者使用的
cryptography库版本相同,避免因库版本差异导致的加密逻辑细微变化 - 运行Script B时的工作目录正确,确保
sys.argv[1]传入的文件路径是正确的(尽量使用绝对路径避免相对路径的坑) - 确认Script B加密的是目标WAV文件,没有因路径错误读取到空文件或其他无关文件
总结
最可能的直接原因是Java代码未循环读取加密数据,导致大文件解密失败;其次要确保密钥在Python和Java端的处理完全一致,同时建议移除流模式下的不必要填充,从根源上避免兼容性问题。
备注:内容来源于stack exchange,提问作者Amjad

