Bouncy Castle Cryptography Library 1.85

org.bouncycastle.cert
Class RelatedCertificateTool

java.lang.Object
  extended byorg.bouncycastle.cert.RelatedCertificateTool

public class RelatedCertificateTool
extends java.lang.Object

Operator-style helpers for building and verifying the two wire-format pieces defined by RFC 9763 ("Related Certificates for Use in Multiple Authentications within a Protocol"): the RelatedCertificate certificate extension carried on an end-entity certificate (OID X509ObjectIdentifiers.id_pe_relatedCert / Extension.relatedCertificate), and the RequesterCertificate CSR attribute value the requester includes in the CSR to prove they hold the private key of the related certificate (attribute OID PKCSObjectIdentifiers.id_aa_relatedCertRequest).

The intended use case is post-quantum migration: an end entity that already holds a traditional certificate requests a parallel post-quantum certificate by including a attribute in the new CSR; the CA verifies the requester controls both private keys, then issues the new certificate carrying a extension that pins the traditional certificate by digest. A verifier seeing both certificates can then assert with assurance that they identify the same principal.

This class is JCA-free and lightweight-crypto-free: it consumes DigestCalculator / DigestCalculatorProvider / ContentSigner / ContentVerifier from , so both the lightweight (BC) and JCA bindings of those operator interfaces are equally usable. Wrapping / unwrapping the value as a PKCS#9 Attribute lives on the value class itself — see RequesterCertificate#toAttribute() and RequesterCertificate#fromAttribute(org.bouncycastle.asn1.pkcs.Attribute).


Method Summary
static org.bouncycastle.asn1.x509.RelatedCertificate createRelatedCertificate(X509CertificateHolder relatedCert, DigestCalculator digestCalculator)
          Compute the RelatedCertificate extension value identifying the supplied certificate by digest.
static org.bouncycastle.asn1.cms.RequesterCertificate createRequesterCertificate(org.bouncycastle.asn1.cms.IssuerAndSerialNumber certID, org.bouncycastle.asn1.cms.BinaryTime requestTime, java.lang.String[] locationInfo, ContentSigner signer)
          Build a fully-signed RequesterCertificate value.
static org.bouncycastle.asn1.cms.RequesterCertificate fromAttribute(org.bouncycastle.asn1.pkcs.Attribute attribute)
          Extract a value from a PKCS#9 Attribute.
static boolean isRelatedCertificate(org.bouncycastle.asn1.x509.RelatedCertificate extensionValue, X509CertificateHolder relatedCert, DigestCalculatorProvider digestProvider)
          Recompute the digest specified in a RelatedCertificate extension value over the supplied candidate certificate and report whether it matches the stored hash.
static org.bouncycastle.asn1.pkcs.Attribute toAttribute(org.bouncycastle.asn1.cms.RequesterCertificate value)
          Wrap a value as a PKCS#9 Attribute carrying PKCSObjectIdentifiers.id_aa_relatedCertRequest, ready to drop into a attributes set.
static boolean verifyRequesterCertificate(org.bouncycastle.asn1.cms.RequesterCertificate value, ContentVerifier verifier)
          Verify the signature carried in using the supplied ContentVerifier.
static void writeSignatureInput(java.io.OutputStream out, org.bouncycastle.asn1.cms.IssuerAndSerialNumber certID, org.bouncycastle.asn1.cms.BinaryTime requestTime)
          Write the bytes the signature field must cover straight into : the DER encoding of followed by the DER encoding of , per RFC 9763 sec. 4.1 ("concatenation of DER-encoded IssuerAndSerialNumber and BinaryTime").
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Method Detail

createRelatedCertificate

public static org.bouncycastle.asn1.x509.RelatedCertificate createRelatedCertificate(X509CertificateHolder relatedCert,
                                                                                     DigestCalculator digestCalculator)
                                                                              throws java.io.IOException
Compute the RelatedCertificate extension value identifying the supplied certificate by digest. Per RFC 9763 sec. 3.2 the digest input is the DER encoding of the entire structure (i.e. the value returned by X509CertificateHolder.getEncoded()).

Parameters:
relatedCert - the related end-entity certificate to bind.
digestCalculator - a calculator configured for the desired digest algorithm; its AlgorithmIdentifier is copied verbatim into the extension's field.
Throws:
java.io.IOException - if the related certificate cannot be encoded or the digest calculator's output stream rejects bytes.

isRelatedCertificate

public static boolean isRelatedCertificate(org.bouncycastle.asn1.x509.RelatedCertificate extensionValue,
                                           X509CertificateHolder relatedCert,
                                           DigestCalculatorProvider digestProvider)
                                    throws OperatorCreationException,
                                           java.io.IOException
Recompute the digest specified in a RelatedCertificate extension value over the supplied candidate certificate and report whether it matches the stored hash.

Parameters:
extensionValue - the parsed extension value, e.g. via .
relatedCert - the candidate related certificate.
digestProvider - a provider able to instantiate a DigestCalculator for the carried by .
Throws:
OperatorCreationException
java.io.IOException

writeSignatureInput

public static void writeSignatureInput(java.io.OutputStream out,
                                       org.bouncycastle.asn1.cms.IssuerAndSerialNumber certID,
                                       org.bouncycastle.asn1.cms.BinaryTime requestTime)
                                throws java.io.IOException
Write the bytes the signature field must cover straight into : the DER encoding of followed by the DER encoding of , per RFC 9763 sec. 4.1 ("concatenation of DER-encoded IssuerAndSerialNumber and BinaryTime"). This is NOT wrapped in an outer SEQUENCE — implementations that hash a SEQUENCE will fail to interoperate. The two structures are streamed directly so no intermediate is materialised; pass a ContentSigner / ContentVerifier output stream (or a if you need the bytes).

Throws:
java.io.IOException

createRequesterCertificate

public static org.bouncycastle.asn1.cms.RequesterCertificate createRequesterCertificate(org.bouncycastle.asn1.cms.IssuerAndSerialNumber certID,
                                                                                        org.bouncycastle.asn1.cms.BinaryTime requestTime,
                                                                                        java.lang.String[] locationInfo,
                                                                                        ContentSigner signer)
                                                                                 throws java.io.IOException
Build a fully-signed RequesterCertificate value. The supplied ContentSigner must be configured with the private key of the certificate identified by .

Throws:
java.io.IOException

verifyRequesterCertificate

public static boolean verifyRequesterCertificate(org.bouncycastle.asn1.cms.RequesterCertificate value,
                                                 ContentVerifier verifier)
                                          throws java.io.IOException
Verify the signature carried in using the supplied ContentVerifier. The verifier must be configured with the public key of the certificate identified by and the signature algorithm the CSR signer used (RFC 9763 carries no AlgorithmIdentifier with the signature, so the caller must derive it from the related certificate's SPKI plus any local policy).

Throws:
java.io.IOException

toAttribute

public static org.bouncycastle.asn1.pkcs.Attribute toAttribute(org.bouncycastle.asn1.cms.RequesterCertificate value)
Wrap a value as a PKCS#9 Attribute carrying PKCSObjectIdentifiers.id_aa_relatedCertRequest, ready to drop into a attributes set.


fromAttribute

public static org.bouncycastle.asn1.cms.RequesterCertificate fromAttribute(org.bouncycastle.asn1.pkcs.Attribute attribute)
Extract a value from a PKCS#9 Attribute.

Throws:
java.lang.IllegalArgumentException - if the attribute is not of type PKCSObjectIdentifiers.id_aa_relatedCertRequest or does not carry exactly one value.

Bouncy Castle Cryptography Library 1.85