我试图在Go中计算gzip压缩文件的sha256总和,但我的输出与gzip命令的输出不匹配.
我有一个函数Compress,io.Reader在我的情况下gzip 一个文件的内容.
func Compress(r io.Reader) (io.Reader, error) {
var buf bytes.Buffer
zw := gzip.NewWriter(&buf)
if _, err := io.Copy(zw, r); err != nil {
return nil, err
}
if err := zw.Close(); err != nil {
return nil, err
}
return &buf, nil
}
Run Code Online (Sandbox Code Playgroud)
然后我有一个函数Sum256来计算读者的sha256和.
func Sum256(r io.Reader) (sum []byte, err error) {
h := sha256.New()
if _, err := io.Copy(h, r); err != nil {
return nil, err
}
return h.Sum(nil), nil
}
Run Code Online (Sandbox Code Playgroud)
我的main函数打开一个文件,gzip,然后计算压缩内容的sha256总和.问题是输出与gzip命令的输出不匹配.输入文件hello.txt包含hello一行,其末尾没有换行符.
func main() {
uncompressed, err := os.Open("hello.txt")
if err != nil {
log.Fatal(err)
}
defer uncompressed.Close()
sum, err := Sum256(uncompressed)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%x %s\n", sum, uncompressed.Name())
uncompressed.Seek(0, 0)
compressed, err := Compress(uncompressed)
if err != nil {
log.Fatal(err)
}
sum, err = Sum256(compressed)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%x %s.gz\n", sum, uncompressed.Name())
}
Run Code Online (Sandbox Code Playgroud)
gzip 结果:
$ sha256sum hello.txt
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 hello.txt
$ gzip -c hello.txt | sha256sum
809d7f11e97291d06189e82ca09a1a0a4a66a3c85a24ac7ff389ae6fbe02bcce -
$ gzip -nc hello.txt | sha256sum
f901eda57fd86d4239806fd4b76f64036c1c20711267a7bc776ab2aa45069b2a -
Run Code Online (Sandbox Code Playgroud)
我的计划结果:
$ go run main.go
# match
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 hello.txt
# mismatch
3429ae8bc6346f1e4fb67b7d788f85f4637e726a725cf4b66c521903d0ab3b07 hello.txt.gz
Run Code Online (Sandbox Code Playgroud)
知道为什么输出不匹配或如何解决这个问题?我已经使用尝试io.Pipe,ioutil.TempFile文件,以及其他方法具有相同的问题.
特别要注意的是,如果运行命令:
gzip -c hello.txt
Run Code Online (Sandbox Code Playgroud)
输出将包含文件名hello.txt.你可以用hexdump看到这个:
$ touch hello.txt; gzip -c hello.txt | hexdump -C 00000000 1f 8b 08 08 ad 1b 14 5c 00 03 68 65 6c 6c 6f 2e |.......\..hello.| 00000010 74 78 74 00 03 00 00 00 00 00 00 00 00 00 |txt...........| 0000001e
如果您只是将数据复制到程序中的Gzip流中,则文件名将不存在.所以你必须得到不同的结果,SHA-256总和应该是不同的.
但是,即使你修复了这个特殊的缺陷......你仍然不能保证通过在同一个文件上运行Gzip来获得相同的结果.
如果要使校验和相同,请在解压缩数据上运行校验和.