我正在学习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()的数据范围,那么整个计算的校验和很可能看起来不同。
有什么想法吗?
答案 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
可以是 blob
、commit
、tree
或 tag
。
一些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
命令返回的值相同。