7zip 如何为多个文件生成哈希?

7zip 如何为多个文件生成哈希?

我有一个零大小文件。7-zip 会da39a3ee5e6b4b0d3255bfef95601890afd80709为其生成文件。没问题。

但如果我选择 2 个零大小文件,7zip 会b47346ddbdd6961a64aa7edf2bc130205fb10f12为它们生成压缩包。这是怎么回事?

尝试了SHA1(SHA1(file1) + SHA1(file2))算法,但结果却不同:43b1e995dbead10e335145327cf24f8d0ec38f88

答案1

7zip:h(哈希)命令

笔记

7-Zip 显示每个文件的哈希值、哈希值的总和以及包含所有数据哈希值和所有文件名哈希值的总和。

'C:\Program Files\7-Zip\7z.exe' h -scrcsha1 .\new*

7-Zip 19.00 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2019-02-21

Scanning
2 files, 0 bytes

SHA1                                              Size  Name
---------------------------------------- -------------  ------------
DA39A3EE5E6B4B0D3255BFEF95601890AFD80709             0  New Text Document (2).txt
DA39A3EE5E6B4B0D3255BFEF95601890AFD80709             0  New Text Document.txt
---------------------------------------- -------------  ------------
B47346DDBDD6961A64AA7EDF2BC130205FB10F12             0

Files: 2
Size: 0

SHA1   for data:              B47346DDBDD6961A64AA7EDF2BC130205FB10F12
SHA1   for data and names:    AFF4696D47DF1F0699A236DD70D5D51B960DD360

Everything is Ok

两个零字节文件的单个文件数据确实相同,但两个零字节文件连接在一起不一定与一个单字节文件相同。7zip 可能在内部将其表示为末梢血每个文件都有一个字节,没有实际数据。

使用 Python 进行快速测试:

>>> a = 0xDA39A3EE5E6B4B0D3255BFEF95601890AFD80709
>>> b = 0xDA39A3EE5E6B4B0D3255BFEF95601890AFD80709
>>> c = a + b
>>> hex(c)
'0x1b47347dcbcd6961a64ab7fdf2ac031215fb00e12'
>>>

区别在于

0x0b47346ddbdd6961a64aA7df2bC130205FB10F12 0x1b47347dCbCd6961a64ab7Fdf2AC031215FB0012

这意味着它不是简单的加法,还有其他事情发生。

如果你想知道数据是如何处理的,那么 7-zip 的源代码是这里。

答案2

感谢 Mokubai 的回答,我明白了它是如何工作的。

它是哈希数组中相同索引上相应字节的总和。如果总和超过,则255后续总和(如果存在)增加1

以下是 JS 代码:

/** @param {...(Buffer|Uint8Array)} arrays
 *  @return {Uint8Array}  */
function zipByteArrays(...arrays) {
    const result = _zipByteArrays(arrays[0], arrays[1]);
    for (let i = 2; i < arrays.length; i++) {
        _zipByteArrays(result, arrays[i], result);
    }
    return result;
}

function _zipByteArrays(a, b, result = new Uint8Array(a.length)) {
    let extra = 0;
    for (let i = 0; i < a.length; i++) {
        const sum = a[i] + b[i] + extra;
        result[i] = sum % 256;
        if (sum > 255) {
            extra = 1;
        } else {
            extra = 0;
        }
    }
    return result;
}

附加演示代码:

import crypto from "node:crypto";

// Empty file hash
const hash1 = Buffer.from("b47246dcbcd6961a64aa7ede2ac030205eb00e12", "hex");

console.log(hex(zipByteArrays(hash1, hash1))                      === "b47346ddbdd6961a64aa7edf2bc130205fb10f12");
console.log(hex(zipByteArrays(hash1, hash1, hash1))               === "8eade9cb1c42e22796ff3dcfc12149b00e8a171b");
console.log(hex(zipByteArrays(hash1, hash1, hash1, hash1))        === "68e78cba7bad2d35c854fdbe57826140be621f24");
console.log(hex(zipByteArrays(hash1, hash1, hash1, hash1, hash1)) === "422130a9da187942faa9bcaeede279d06d3b272d");

function hex(array) {
    return Buffer.from(array).toString("hex")
}

function sha1(value) {
    const hasher = crypto.createHash("sha1");
    hasher.update(value);
    return hasher.digest();
}

但是,另一个问题是,当 7-zip 创建“数据和名称”哈希时它是如何工作的?

例如,

const f1_name = sha1("file1.txt");
const f2_name = sha1("file2.txt");
console.log(hex(zipByteArrays(hash1, f1_name, hash1, f2_name)));

打印,而 2 个具有和名称447d1e8e010c7344dfa2be63c7ab561b8de1d186的空文件的预期哈希值为file1.txtfile2.txt5d0543836f28cd8c93975c90c61373cd30c9c73f

相关内容