2

我正在学习 Git 包文件,目前正在尝试重现(在 Java 中)我认为是整个包文件的 SHA1 20 字节校验和。我将字节数组从“PACK”4 字节标头中提取到最后一个打包对象的压缩数据的末尾。我读过的所有内容都表明接下来的 20 个字节是整个包文件的 SHA1 校验和。

作为从 Git 接收的字节数组的一部分的 20 字节校验和是:B910248BF9B63AC53595E3835CA57BDAF08DA830

我使用以下来计算我自己的 SHA1 校验和:
crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(testData);
byte [] result = crypt.digest();

我的结果是:B910248BF9B63AC53595E3835CA57BDAF08DA813

我对我的结果的最后一个字节如何与 Git 的不同(如果我使用字节流的正确部分)感到困惑。如果唯一的问题是传递给 digest() 的数据范围,那么整个计算的校验和很可能看起来不同。

有任何想法吗?

4

2 回答 2

0

使用 JGit:

byte[] data = new byte[] { ... };
ObjectInserter.Formatter f = new ObjectInserter.Formatter();
ObjectId id = f.idFor(OBJ_BLOB, data);
String hash = id.getName();
于 2012-07-09T09:16:30.253 回答
0

git object-id 是这样计算的(伪代码):

sha1(obj_type | 0x20 | ascii(data_length) | 0x00 | data);

哪里obj_type可以是blob, commit,treetag.

一些Java代码:

byte[] getObjectId(String type, byte[] input) throws NoSuchAlgorithmException {
    MessageDigest md = MessageDigest.getInstance("SHA1");  
    md.update(String.format("%s %d\u0000", type, input.length).getBytes()); 
    md.update(input);
    return md.digest(); 
}

getObjectId("blob", "helloworld".getBytes())返回 620ffd0fd9579a46e46ef4505b198ee0a01a57f2git hash-object这与命令返回的值相同。

于 2021-06-05T15:35:09.993 回答