在 Win32 和 Linux-64 位之间使用 zlib 压缩的结果不一致

Inconsistent results in compressing with zlib between Win32 and Linux-64 bit

在程序中使用 zlib 并注意到 "foo" 在 Windows 1F8B080000000000000A4BCBCF07002165738C03000000 和 Linux 1F8B08000000000000034BCBCF07002165738C03000000 上的压缩方式略有不同。两者都解压回 "foo"

我决定检查我们的代码之外,看看实现是否正确,并使用 zlib 存储库中的测试程序来仔细检查。我得到了相同的结果:

Linux: echo -n foo| ./minigzip64 > text.txt'

Windows: echo|set /p="foo" | minigzip > text.txt

造成这种差异的原因是什么?有问题吗?

1F8B 0800 0000 0000 000 *3/A* 4BCB CF07 0021 6573 8C03 0000 00

首先,如果它解压缩到压缩后的内容,那么这不是问题。不同的压缩器,或不同设置的同一压缩器,甚至具有相同设置但不同版本的同一压缩器,都可以从相同的输入产生不同的压缩输出。

其次,本例中的压缩数据是相同的。只有最后一个字节 压缩数据之前的 gzip header 不同。该字节标识原始操作系统。因此它在 Linux 和 Windows 之间正确变化。

即使在同一个操作系统上,header 也可能不同,因为它带有修改日期和时间。但是,在您的这两种情况下,修改日期和时间都被遗漏了(设置为零)。

只是为了添加到此处接受的答案。我很好奇并亲自尝试,保存原始数据并使用 7zip 打开:

Windows:

Linux:

您可以立即注意到唯一不同的字段是 Host OS.

数据的含义

Header                 Data         Footer
1F8B080000000000000A | 4BCBCF0700 | 2165738C03000000

让我们分解一下。

Header

首先,从 this answer 我意识到它实际上是 gzip 而不是 zlib header:

Level   ZLIB    GZIP 
  1   | 78 01 | 1F 8B 
  9   | 78 DA | 1F 8B 

进一步搜索使我在取证 wiki 上找到了一篇关于 Gzip 的文章。 本例中的值为:

Offset   Size   Value   Description
0      | 2    | 1f8b | Signature (or identification byte 1 and 2)
2      | 1    | 08   | Compression Method (deflate)
3      | 1    |      | Flags
4      | 4    |      | Last modification time
8      | 1    |      | Compression flags (or extra flags)
9      | 1    | 0A   | Operating system (TOPS-20)

页脚

Offset   Size   Value    Description
0      | 4    | 2165738C | Checksum (CRC-32) (Little endian)
4      | 4    | 03       | Uncompressed data size Value in bytes.

这里要注意的一个有趣的事情是,即使最后修改时间 与header中的操作系统不同,会压缩成相同的数据 在页脚中使用相同的校验和。

IETF RFC有比较详细的格式总结