# HG changeset patch # User Artem Tikhomirov # Date 1294975743 -3600 # Node ID 92c3d0920d589f76e79097b7dbd9c115998b88c6 # Parent 858d1b2458cb8bb56adee24b762de4e33f6f6d51 Real integrity check, with exception. DigestHelper refactored to accomodate new needs diff -r 858d1b2458cb -r 92c3d0920d58 src/com/tmate/hgkit/console/Cat.java --- a/src/com/tmate/hgkit/console/Cat.java Fri Jan 14 04:14:08 2011 +0100 +++ b/src/com/tmate/hgkit/console/Cat.java Fri Jan 14 04:29:03 2011 +0100 @@ -43,7 +43,7 @@ byte[] parent1 = new byte[20]; byte[] parent2 = new byte[20]; fn.parents(i, parentRevisions, parent1, parent2); - System.out.println(dh.sha1(parent1, parent2, content)); + System.out.println(dh.sha1(parent1, parent2, content).asHexString()); } } else { System.out.println(">>>Not found!"); diff -r 858d1b2458cb -r 92c3d0920d58 src/com/tmate/hgkit/ll/DigestHelper.java --- a/src/com/tmate/hgkit/ll/DigestHelper.java Fri Jan 14 04:14:08 2011 +0100 +++ b/src/com/tmate/hgkit/ll/DigestHelper.java Fri Jan 14 04:29:03 2011 +0100 @@ -9,12 +9,18 @@ import java.security.NoSuchAlgorithmException; /** - * TODO sha1_binary to give array for Nodeid.equalsTo - * + *
+ * DigestHelper dh;
+ * dh.sha1(...).asHexString();
+ *  or 
+ * dh = dh.sha1(...);
+ * nodeid.equalsTo(dh.asBinary());
+ * 
* @author artem */ public class DigestHelper { private MessageDigest sha1; + private byte[] digest; public DigestHelper() { } @@ -32,12 +38,12 @@ } - public String sha1(Nodeid nodeid1, Nodeid nodeid2, byte[] data) { + public DigestHelper sha1(Nodeid nodeid1, Nodeid nodeid2, byte[] data) { return sha1(nodeid1.cloneData(), nodeid2.cloneData(), data); } // sha1_digest(min(p1,p2) ++ max(p1,p2) ++ final_text) - public String sha1(byte[] nodeidParent1, byte[] nodeidParent2, byte[] data) { + public DigestHelper sha1(byte[] nodeidParent1, byte[] nodeidParent2, byte[] data) { MessageDigest alg = getSHA1(); if ((nodeidParent1[0] & 0x00FF) < (nodeidParent2[0] & 0x00FF)) { alg.update(nodeidParent1); @@ -46,21 +52,36 @@ alg.update(nodeidParent2); alg.update(nodeidParent1); } - byte[] digest = alg.digest(data); + digest = alg.digest(data); assert digest.length == 20; - return toHexString(digest, 0, 20); + return this; + } + + public String asHexString() { + if (digest == null) { + throw new IllegalStateException("Shall init with sha1() call first"); + } + return toHexString(digest, 0, digest.length); + } + + // by reference, be careful not to modify (or #clone() if needed) + public byte[] asBinary() { + if (digest == null) { + throw new IllegalStateException("Shall init with sha1() call first"); + } + return digest; } // XXX perhaps, digest functions should throw an exception, as it's caller responsibility to deal with eof, etc - public byte[] sha1(InputStream is /*ByteBuffer*/) throws IOException { + public DigestHelper sha1(InputStream is /*ByteBuffer*/) throws IOException { MessageDigest alg = getSHA1(); byte[] buf = new byte[1024]; int c; while ((c = is.read(buf)) != -1) { alg.update(buf, 0, c); } - byte[] digest = alg.digest(); - return digest; + digest = alg.digest(); + return this; } public static String toHexString(byte[] data, final int offset, final int count) { diff -r 858d1b2458cb -r 92c3d0920d58 src/com/tmate/hgkit/ll/HgBundle.java --- a/src/com/tmate/hgkit/ll/HgBundle.java Fri Jan 14 04:14:08 2011 +0100 +++ b/src/com/tmate/hgkit/ll/HgBundle.java Fri Jan 14 04:29:03 2011 +0100 @@ -48,8 +48,10 @@ int resultLen = 10000; // XXX calculate based on baseRevContent.length and ge.patches byte[] csetContent = RevlogStream.apply(baseRevContent, resultLen, ge.patches); // wiki suggests sha1_digest(min(p1,p2) ++ max(p1,p2) ++ final_text), - String digest = dh.sha1(ge.firstParent(), ge.secondParent(), csetContent); // XXX ge may give me access to byte[] content of nodeid directly, perhaps, I don't need DH to be friend of Nodeid? - System.out.println("Node: " + ge.node() + ", digest: " + digest); + dh = dh.sha1(ge.firstParent(), ge.secondParent(), csetContent); // XXX ge may give me access to byte[] content of nodeid directly, perhaps, I don't need DH to be friend of Nodeid? + if (!ge.node().equalsTo(dh.asBinary())) { + throw new IllegalStateException("Integrity check failed on " + bundleFile + ", node:" + ge.node()); + } Changeset cs = Changeset.parse(csetContent, 0, csetContent.length); cs.dump(); baseRevContent = csetContent;