我有一个受密码保护的 zip 文件,其中每个文件的路径和文件名都使用 PKWARE 加密进行加密。
密码是已知且正确的,加密算法也是如此。
我还有示例明文和一个可以正确解密文件的应用程序(32 位闭源、优化、无调试符号)。
以下是由闭源程序生成的完全解密文件的示例。
如您所见,对于大多数文件,文件名都可以正确解密。然而,对于一小部分,我得到了部分解码的文件名,其余的都是 mojibake。
所以我的问题是,为什么会发生这种情况,我应该怎么做才能纠正它?我很困惑,因为如果我的解密实现是错误的,我期待 100% 的垃圾。部分正确的输出并不是我所期望的。
注意每个文件名都是独立解密的,也就是说下一个文件的解密不依赖于前一个文件的解密。
解密实现或多或少与此处描述的相同:
static uint32_t keys[3];
// CRC32_table is from zlib
uint32_t compute_crc32(uint32_t crc, char c) {
return CRC32_table[(crc ^ c) & 0xff] ^ (crc >> 8);
}
void init_keys(const std::string& password) {
keys = { 0x12345678, 0x23456789, 0x34567890 };
for (size_t i = 0; i < password.size(); ++i)
key_update(keys, password[i]);
}
void update_keys(char c) {
keys[0] = compute_crc32(keys[0], c);
keys[1] = keys[1] + (keys[0] & 0xff);
keys[1] = (keys[1] * 0x8088405) + 1;
keys[2] = compute_crc32(keys[2], keys[1] >> 24);
}
char decrypt_byte() {
uint16_t temp = (keys[2] & 0xffff) | 2;
return char(((temp * (temp ^ 1))>> 8) & 0xff);
}
std::string decrypt(const std::string& password,
const std::string& input) {
init_keys(password);
auto ret = std::string(input.size(), '\0');
for (int i = 0; i < input.size(); ++i) {
char c = input[i] ^ decrypt_byte();
update_keys(c);
ret[i] = c;
}
return ret;
}
请注意,文件仍能正确解密和解压缩,只是文件名被打乱了。

