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

kea*_*ist 5 compression zlib

在程序中使用zlib并注意到"foo"在Windows 1F8B080000000000000A4BCBCF07002165738C03000000和Linux 上压缩的方式有一点差异1F8B08000000000000034BCBCF07002165738C03000000.两者都解压缩回"foo"

我决定在我们的代码外部检查以确定实现是否正确并使用zlib存储库中的测试程序进行双重检查.我得到了相同的结果:

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

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

什么能解释这种差异?这是个问题吗?

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

Mar*_*ler 6

首先,如果它解压缩到压缩的内容,那么这不是问题.不同的压缩机,或不同设置的相同压缩机,或者具有相同设置但不同版本的相同压缩机,可以从相同的输入产生不同的压缩输出.

其次,这种情况下的压缩数据是相同的.只有压缩数据之前的gzip头的最后一个字节是不同的.该字节标识原始操作系统.因此,它在Linux和Windows之间有所不同.

即使在相同的操作系统上,标头也可以变化,因为它带有修改日期和时间.但是,在您的两种情况下,修改日期和时间都被省略(设置为零).


Gee*_*y I 5

只是为了在这里添加已接受的答案。我很好奇,自己尝试了一下,保存原始数据并用 7zip 打开:

视窗:

gzip-win

Linux:

gzip-Linux

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

数据意味着什么

Header                 Data         Footer
1F8B080000000000000A | 4BCBCF0700 | 2165738C03000000
Run Code Online (Sandbox Code Playgroud)

让我们来分解一下。

标头

首先,从这个答案我意识到它实际上是一个gzip而不是zlib标头:

Level   ZLIB    GZIP 
  1   | 78 01 | 1F 8B 
  9   | 78 DA | 1F 8B 
Run Code Online (Sandbox Code Playgroud)

进一步搜索让我在取证 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)
Run Code Online (Sandbox Code Playgroud)

页脚

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

这里需要注意的有趣的事情是,即使标头中的上次修改时间操作系统不同,它也会压缩为相同的数据,并在页脚中具有相同的校验和。

IETF RFC有更详细的格式摘要