how to calculate leaf hash

288 views
Skip to first unread message

Erdinc Yavas

unread,
Nov 27, 2015, 7:55:48 AM11/27/15
to certificate-transparency
Hi all,

I am trying to implement "get-proof-by-hash" in java.

I have created a test ssl preCertificate and send preCertificate chain to test log server (http://ct.googleapis.com/testtube/ct/v1/) and get sct successfully.

I have implemented "get-proof-by-hash" but when try to invoke it get this error:
error_message=Hash is unknown : generic::failed_precondition: Leafhash (a938e6e3773519720d3018d3f92d10c3666c241d069b2db1890ef6b2406d9fe4) not in index (from fiddler web debugger)
Error making POST request to http://ct.googleapis.com/testtube/ct/v1/get-proof-by-hash: Bad Request (from Eclipse)

Probably the leaf hash parameter which I give is wrong. 
I have calculated leaf hash as described in RFC 6962 Section 3.4. My hash calculation code is like below:

// PreCert
PreCert.Builder preCertBuilder = PreCert.newBuilder();
preCertBuilder.setIssuerKeyHash(ByteString.copyFrom(Util.getSHA256Hash(issuerPublicKey)));
preCertBuilder.setTbsCertificate(ByteString.copyFrom(Util.getSHA256Hash(tbsCertificate))); // tbsCertificate from preCerificate without poison extension

//SignedEntry
SignedEntry.Builder signedEntryBuilder = SignedEntry.newBuilder();
signedEntryBuilder.setPrecert(preCertBuilder.build());

// TimestampedEntry
TimestampedEntry.Builder timestampedEntryBuilder = TimestampedEntry.newBuilder();
timestampedEntryBuilder.setTimestamp(sct.getTimestamp());
timestampedEntryBuilder.setEntryType(LogEntryType.PRECERT_ENTRY);
timestampedEntryBuilder.setExtensions(sct.getExtensions());
timestampedEntryBuilder.setSignedEntry(signedEntryBuilder.build());

// MerkleTreeLeaf
MerkleTreeLeaf.Builder merkleTreeLeafBuilder  = MerkleTreeLeaf.newBuilder();
merkleTreeLeafBuilder.setVersion(sct.getVersion());
merkleTreeLeafBuilder.setType(MerkleLeafType.TIMESTAMPED_ENTRY);
merkleTreeLeafBuilder.setTimestampedEntry(timestampedEntryBuilder.build());

// leafHash
byte[] leafHash = Util.getSHA256Hash(merkleTreeLeafBuilder.build().toByteArray());



Also, I have tried to get tbsCertificate from preCerificate with poison extension, but get the "Leafhash (.....) not in index" error again.

I there anybody know how to calculate the leaf hash?

Thanks.

Erdinc Yavas.









Adam Eijdenberg

unread,
Nov 30, 2015, 12:27:22 PM11/30/15
to certificate-transparency
Hi Erdinc,

I'm not familiar with the Java classes referenced, however once "gotcha" that has hit a number of us when invoking "get-proof-by-hash" is that the MerkleTreeLeaf should be prepended by 0x00 before being hashed.  This is mentioned in section 2.1 of RFC6962 and we've tried to make this clearer in the standards track version (see here).

It could be that the Java classes do this for you, but just in case they don't, try changing:

byte[] leafHash = Util.getSHA256Hash(merkleTreeLeafBuilder.build().toByteArray());

to the following (you will probably need to change a little to actually compile, I suspect the following isn't quite valid Java):

byte[] leafHash = Util.getSHA256Hash("\0" + merkleTreeLeafBuilder.build().toByteArray());

Hope that helps!

Cheers, Adam


--
You received this message because you are subscribed to the Google Groups "certificate-transparency" group.
To unsubscribe from this group and stop receiving emails from it, send an email to certificate-transp...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Erdinc Yavas

unread,
Dec 4, 2015, 10:37:41 AM12/4/15
to certificate-transparency
Thank you Adam,

I have calculated the leaf hash successfully, my code is like below:

Asn1DerEncodeBuffer encBuf = new Asn1DerEncodeBuffer();
etbsCertificate.getObject().encode(encBuf);

byte[] prefix = {0x00};
byte[] version = {0x00}; //V1
byte[] leafType = {0x00}; //TIMESTAMPED_ENTRY_VALUE
byte[] timestamp = Longs.toByteArray(sctTimestamp);
byte[] entryType = {0x00, 0x01}; //PRECERT_ENTRY_VALUE
byte[] issuerPublicKeyHash = Util.getSHA256Hash(subRootCertificate.getSubjectPublicKeyInfo().getEncoded());
byte[] tbsCertificate = encBuf.getMsgCopy();
byte[] tbsCertificateLength = {Util.intToBytes(tbsCertificate.length)[1], Util.intToBytes(tbsCertificate.length)[2], Util.intToBytes(tbsCertificate.length)[3]};
byte[] extensions = {0x00, 0x00};

List<byte[]> byteList = new ArrayList<byte[]>();
byteList.add(prefix);
byteList.add(version);
byteList.add(leafType);
byteList.add(timestamp);
byteList.add(entryType);
byteList.add(issuerPublicKeyHash);
byteList.add(tbsCertificateLength);
byteList.add(tbsCertificate);
byteList.add(extensions);
byte[] leafHash = Util.getSHA256Hash(Util.concat(byteList));

Erdinc.
To unsubscribe from this group and stop receiving emails from it, send an email to certificate-transparency+unsub...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages