在java中计算git packfile sha1校验和

时间:2011-03-22 02:48:41

标签: git checksum jgit

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

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

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

我的结果最终为: B910248BF9B63AC53595E3835CA57BDAF08DA813

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

有什么想法吗?

2 个答案:

答案 0 :(得分:0)

使用JGit:

byte[] data = new byte[] { ... };
ObjectInserter.Formatter f = new ObjectInserter.Formatter();
ObjectId id = f.idFor(OBJ_BLOB, data);
String hash = id.getName();

答案 1 :(得分:0)

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

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

其中 obj_type 可以是 blobcommittreetag

一些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()) 返回 620ffd0fd9579a46e46ef4505b198ee0a01a57f2。 这与 git hash-object 命令返回的值相同。