在 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有比较详细的格式总结
在程序中使用 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有比较详细的格式总结