Class MerkleTreeCertificateValidator
- java.lang.Object
-
- org.bouncycastle.cert.plants.MerkleTreeCertificateValidator
-
public class MerkleTreeCertificateValidator extends java.lang.ObjectValidates a Merkle Tree Certificate (MTC) per Section 7.2 of draft-ietf-plants-merkle-tree-certs.The validator stands in for the per-certificate signature verification step of RFC 5280 path validation (Section 6.1.3 step (a)(1)) when the issuer is a Merkle Tree CA.
validateCertificate(org.bouncycastle.cert.X509CertificateHolder, org.bouncycastle.cert.plants.MerkleTreeCertificateValidator.ValidationParams)decodes theMTCProofcarried in the certificate'ssignatureValue, recomputes the entry hash from the TBSCertificate, evaluates the inclusion proof against the suppliedMerkleTreeHash, and then either matches the resulting subtree hash against aValidationParams.TrustedSubtreeor counts valid cosignatures against the relying party'sMTCCosignerVerifierProvideruntilminCosignaturesis met.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static classMerkleTreeCertificateValidator.RevokedRangeA half-open range[start, end)of revoked certificate serial numbers, per Section 7.5 of the draft.static classMerkleTreeCertificateValidator.TrustedSubtreeRepresents a trusted subtree (typically a landmark subtree predistributed to the relying party).static classMerkleTreeCertificateValidator.ValidationParamsParameters supplied by the relying party for certificate validation.
-
Field Summary
Fields Modifier and Type Field Description static java.lang.StringID_ALG_MTC_PROOFDotted-decimal form ofMTCObjectIdentifiers.id_alg_mtcProof, the signatureAlgorithm of an MTC certificate.
-
Constructor Summary
Constructors Constructor Description MerkleTreeCertificateValidator()
-
Method Summary
All Methods Static Methods Concrete Methods Modifier and Type Method Description static byte[]computeEntryHash(byte[] tbsCertDer, byte[] extensionsWire, MerkleTreeHash hashFunc)Raw-DER variant ofcomputeEntryHash(TBSCertificate, byte[], MerkleTreeHash)— skips the parse + re-encode round trip when the TBSCertificate is already in hand as DER bytes.static byte[]computeEntryHash(byte[] tbsCertDer, MerkleTreeHash hashFunc)Convenience overload ofcomputeEntryHash(byte[], byte[], MerkleTreeHash)with an empty extensions list.static byte[]computeEntryHash(org.bouncycastle.asn1.x509.TBSCertificate tbsCert, byte[] extensionsWire, MerkleTreeHash hashFunc)TBSCertificate variant ofcomputeEntryHash(X509CertificateHolder, byte[], MerkleTreeHash).static byte[]computeEntryHash(org.bouncycastle.asn1.x509.TBSCertificate tbsCert, MerkleTreeHash hashFunc)Convenience overload ofcomputeEntryHash(TBSCertificate, byte[], MerkleTreeHash)with an empty extensions list.static byte[]computeEntryHash(X509CertificateHolder certHolder, byte[] extensionsWire, MerkleTreeHash hashFunc)Computes the entry hash for a certificate by transforming its TBSCertificate into the equivalentMerkleTreeCertEntryof typetbs_cert_entryand hashing per Section 5.2.1 / Section 7.2.static byte[]computeEntryHash(X509CertificateHolder certHolder, MerkleTreeHash hashFunc)Convenience overload ofcomputeEntryHash(X509CertificateHolder, byte[], MerkleTreeHash)with an empty extensions list (the wire form is two zero bytes, the uint16 length prefix).static byte[]computeSubtreeHash(byte[] tbsCertDer, byte[] inclusionProof, MerkleTreeHash hashFunc)Combined "leaf hash + climb one level" for the simple case of a size-two subtree[0, 2)where the EE has exactly one sibling leaf.static byte[]extractCaIdFromIssuer(org.bouncycastle.asn1.x500.X500Name issuer)Extracts the binary CA trust anchor ID from the issuer field of a Merkle Tree certificate.static booleanvalidateCertificate(X509CertificateHolder certHolder, MerkleTreeCertificateValidator.ValidationParams params)Validates a Merkle Tree certificate per Section 7.2.static voidwriteEntryHashInput(byte[] tbsCertDer, byte[] extensionsWire, MerkleTreeHash hashFunc, java.io.OutputStream out)Raw-DER variant ofwriteEntryHashInput(TBSCertificate, byte[], MerkleTreeHash, OutputStream)— skips the parse + re-encode round trip when the TBSCertificate is already in hand as DER bytes (e.g. captured from a streamingContentSigner).static voidwriteEntryHashInput(org.bouncycastle.asn1.x509.TBSCertificate tbsCert, byte[] extensionsWire, MerkleTreeHash hashFunc, java.io.OutputStream out)TBSCertificate variant ofwriteEntryHashInput(X509CertificateHolder, byte[], MerkleTreeHash, OutputStream).static voidwriteEntryHashInput(X509CertificateHolder certHolder, byte[] extensionsWire, MerkleTreeHash hashFunc, java.io.OutputStream out)Streams the byte sequence thatcomputeEntryHash(org.bouncycastle.cert.X509CertificateHolder, org.bouncycastle.cert.plants.MerkleTreeHash)hashes into the suppliedOutputStream.
-
-
-
Method Detail
-
validateCertificate
public static boolean validateCertificate(X509CertificateHolder certHolder, MerkleTreeCertificateValidator.ValidationParams params) throws java.io.IOException
Validates a Merkle Tree certificate per Section 7.2. Always returnstrueon success; any validation failure is signalled as aSecurityException.- Parameters:
certHolder- the certificate to validateparams- validation parameters- Throws:
java.lang.SecurityException- if the certificate is rejectedjava.lang.IllegalArgumentException- if the certificate is not a Merkle Tree certificatejava.io.IOException- if the certificate cannot be parsed
-
computeEntryHash
public static byte[] computeEntryHash(X509CertificateHolder certHolder, MerkleTreeHash hashFunc) throws java.io.IOException
Convenience overload ofcomputeEntryHash(X509CertificateHolder, byte[], MerkleTreeHash)with an empty extensions list (the wire form is two zero bytes, the uint16 length prefix). Use this when the certificate has no log-entry extensions.- Throws:
java.io.IOException
-
computeEntryHash
public static byte[] computeEntryHash(org.bouncycastle.asn1.x509.TBSCertificate tbsCert, MerkleTreeHash hashFunc) throws java.io.IOExceptionConvenience overload ofcomputeEntryHash(TBSCertificate, byte[], MerkleTreeHash)with an empty extensions list. Useful when the caller has aTBSCertificatein hand (for instance during issuance, before the signature is computed) and doesn't want to build a placeholderX509CertificateHoldersolely to satisfy the holder-based overload.- Throws:
java.io.IOException
-
computeEntryHash
public static byte[] computeEntryHash(byte[] tbsCertDer, MerkleTreeHash hashFunc) throws java.io.IOExceptionConvenience overload ofcomputeEntryHash(byte[], byte[], MerkleTreeHash)with an empty extensions list. Use this when the DER encoding of the TBSCertificate is already in hand (e.g. captured from a streamingContentSigner) to avoid the parse + re-encode round trip viaTBSCertificate.- Throws:
java.io.IOException
-
computeSubtreeHash
public static byte[] computeSubtreeHash(byte[] tbsCertDer, byte[] inclusionProof, MerkleTreeHash hashFunc) throws java.io.IOExceptionCombined "leaf hash + climb one level" for the simple case of a size-two subtree[0, 2)where the EE has exactly one sibling leaf. Equivalent tohashFunc.hashNode(computeEntryHash(tbsCertDer, hashFunc), inclusionProof). The extensions list is empty.- Throws:
java.io.IOException
-
computeEntryHash
public static byte[] computeEntryHash(X509CertificateHolder certHolder, byte[] extensionsWire, MerkleTreeHash hashFunc) throws java.io.IOException
Computes the entry hash for a certificate by transforming its TBSCertificate into the equivalentMerkleTreeCertEntryof typetbs_cert_entryand hashing per Section 5.2.1 / Section 7.2.The single-pass procedure (Section 7.2):
- Write the
extensionsfield from the MTCProof (the on-wire bytes including the 2-byte length prefix) to the hash. - Write the big-endian, two-byte
tbs_cert_entryvalue (0x0001). - Write the TBSCertificate contents octets up to
subjectPublicKeyInfo. - Write the
subjectPublicKeyInfo's algorithm field. - Write
0x04 L Hwhere L is the hash length and H is HASH(SPKI). - Write the remaining TBSCertificate contents octets.
- Finalize.
- Parameters:
extensionsWire- theextensions<0..2^16-1>field exactly as it appears at the start of the corresponding MTCProof (useMTCProof.getExtensionsWire())- Throws:
java.io.IOException
- Write the
-
computeEntryHash
public static byte[] computeEntryHash(org.bouncycastle.asn1.x509.TBSCertificate tbsCert, byte[] extensionsWire, MerkleTreeHash hashFunc) throws java.io.IOExceptionTBSCertificate variant ofcomputeEntryHash(X509CertificateHolder, byte[], MerkleTreeHash). The hash depends only on the to-be-signed structure, so callers that haven't yet wrapped the TBSCertificate in a signedX509CertificateHoldercan compute the entry hash directly.- Throws:
java.io.IOException
-
computeEntryHash
public static byte[] computeEntryHash(byte[] tbsCertDer, byte[] extensionsWire, MerkleTreeHash hashFunc) throws java.io.IOExceptionRaw-DER variant ofcomputeEntryHash(TBSCertificate, byte[], MerkleTreeHash)— skips the parse + re-encode round trip when the TBSCertificate is already in hand as DER bytes.- Throws:
java.io.IOException
-
writeEntryHashInput
public static void writeEntryHashInput(X509CertificateHolder certHolder, byte[] extensionsWire, MerkleTreeHash hashFunc, java.io.OutputStream out) throws java.io.IOException
Streams the byte sequence thatcomputeEntryHash(org.bouncycastle.cert.X509CertificateHolder, org.bouncycastle.cert.plants.MerkleTreeHash)hashes into the suppliedOutputStream. Equivalent in output to building aByteArrayOutputStreamand finishing withhashFunc.hashLeaf(baos.toByteArray()), but lets callers pipe the bytes directly into a streaming digest (e.g.org.bouncycastle.crypto.io.DigestOutputStreamorjava.security.DigestOutputStream) so theMerkleTreeCertEntrynever lives fully in memory.hashFuncis still required because Section 7.2's single-pass procedure (step 8) hashes the SubjectPublicKeyInfo separately viaMerkleTreeHash.hashRaw(byte[])and writes only its hash into the entry stream.- Parameters:
certHolder- the X.509 certificateextensionsWire- theMTCProof.getExtensionsWire()bytes (or{0, 0}for an empty extensions list)hashFunc- hash function used for the SPKI hash; the caller computes the leaf hash separately (typically by feeding the leaf-tag byte0x00into a digest first, then pipingoutinto the same digest)out- destination for the streamed entry bytes- Throws:
java.io.IOException
-
writeEntryHashInput
public static void writeEntryHashInput(org.bouncycastle.asn1.x509.TBSCertificate tbsCert, byte[] extensionsWire, MerkleTreeHash hashFunc, java.io.OutputStream out) throws java.io.IOExceptionTBSCertificate variant ofwriteEntryHashInput(X509CertificateHolder, byte[], MerkleTreeHash, OutputStream).- Throws:
java.io.IOException
-
writeEntryHashInput
public static void writeEntryHashInput(byte[] tbsCertDer, byte[] extensionsWire, MerkleTreeHash hashFunc, java.io.OutputStream out) throws java.io.IOExceptionRaw-DER variant ofwriteEntryHashInput(TBSCertificate, byte[], MerkleTreeHash, OutputStream)— skips the parse + re-encode round trip when the TBSCertificate is already in hand as DER bytes (e.g. captured from a streamingContentSigner).- Throws:
java.io.IOException
-
extractCaIdFromIssuer
public static byte[] extractCaIdFromIssuer(org.bouncycastle.asn1.x500.X500Name issuer) throws java.io.IOExceptionExtracts the binary CA trust anchor ID from the issuer field of a Merkle Tree certificate. Per Section 5.1 of the draft the issuer name has a single RDN with a single attribute. For initial experimentation the attribute type isid_rdna_trustAnchorID(1.3.6.1.4.1.44363.47.1) with a UTF8String value of the dotted-decimal trust anchor ID; for the production encoding the value is a RELATIVE-OID. Both are accepted; the return value is the binary trust anchor ID per Section 3 of draft-ietf-tls-trust-anchor-ids.- Throws:
java.io.IOException
-
-