Class RelatedCertificateTool
- java.lang.Object
-
- org.bouncycastle.cert.RelatedCertificateTool
-
public class RelatedCertificateTool extends java.lang.ObjectOperator-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
RelatedCertificatecertificate extension carried on an end-entity certificate (OIDX509ObjectIdentifiers.id_pe_relatedCert/Extension.relatedCertificate), and - the
RequesterCertificateCSR attribute value the requester includes in the CSR to prove they hold the private key of the related certificate (attribute OIDPKCSObjectIdentifiers.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
id-aa-relatedCertRequestattribute in the new CSR; the CA verifies the requester controls both private keys, then issues the new certificate carrying aRelatedCertificateextension 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/ContentVerifierfromorg.bouncycastle.operator, so both the lightweight (BC) and JCA bindings of those operator interfaces are equally usable. Wrapping / unwrapping the value as a PKCS#9Attributelives on the value class itself — seeRequesterCertificate#toAttribute()andRequesterCertificate#fromAttribute(org.bouncycastle.asn1.pkcs.Attribute). - the
-
-
Method Summary
All Methods Static Methods Concrete Methods Modifier and Type Method Description static org.bouncycastle.asn1.x509.RelatedCertificatecreateRelatedCertificate(X509CertificateHolder relatedCert, DigestCalculator digestCalculator)Compute theRelatedCertificateextension value identifying the supplied certificate by digest.static org.bouncycastle.asn1.cms.RequesterCertificatecreateRequesterCertificate(org.bouncycastle.asn1.cms.IssuerAndSerialNumber certID, org.bouncycastle.asn1.cms.BinaryTime requestTime, java.lang.String[] locationInfo, ContentSigner signer)Build a fully-signedRequesterCertificatevalue.static org.bouncycastle.asn1.cms.RequesterCertificatefromAttribute(org.bouncycastle.asn1.pkcs.Attribute attribute)Extract aRequesterCertificatevalue from a PKCS#9Attribute.static booleanisRelatedCertificate(org.bouncycastle.asn1.x509.RelatedCertificate extensionValue, X509CertificateHolder relatedCert, DigestCalculatorProvider digestProvider)Recompute the digest specified in aRelatedCertificateextension value over the supplied candidate certificate and report whether it matches the stored hash.static org.bouncycastle.asn1.pkcs.AttributetoAttribute(org.bouncycastle.asn1.cms.RequesterCertificate value)Wrap aRequesterCertificatevalue as a PKCS#9AttributecarryingPKCSObjectIdentifiers.id_aa_relatedCertRequest, ready to drop into aCertificationRequestInfoattributes set.static booleanverifyRequesterCertificate(org.bouncycastle.asn1.cms.RequesterCertificate value, ContentVerifier verifier)Verify the signature carried invalueusing the suppliedContentVerifier.static voidwriteSignatureInput(java.io.OutputStream out, org.bouncycastle.asn1.cms.IssuerAndSerialNumber certID, org.bouncycastle.asn1.cms.BinaryTime requestTime)Write the bytes thesignaturefield must cover straight intoout: the DER encoding ofcertIDfollowed by the DER encoding ofrequestTime, per RFC 9763 sec. 4.1 ("concatenation of DER-encoded IssuerAndSerialNumber and BinaryTime").
-
-
-
Method Detail
-
createRelatedCertificate
public static org.bouncycastle.asn1.x509.RelatedCertificate createRelatedCertificate(X509CertificateHolder relatedCert, DigestCalculator digestCalculator) throws java.io.IOException
Compute theRelatedCertificateextension value identifying the supplied certificate by digest. Per RFC 9763 sec. 3.2 the digest input is the DER encoding of the entireCertificatestructure (i.e. the value returned byX509CertificateHolder.getEncoded()).- Parameters:
relatedCert- the related end-entity certificate to bind.digestCalculator- a calculator configured for the desired digest algorithm; itsAlgorithmIdentifieris copied verbatim into the extension'shashAlgorithmfield.- 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.IOExceptionRecompute the digest specified in aRelatedCertificateextension value over the supplied candidate certificate and report whether it matches the stored hash.- Parameters:
extensionValue- the parsedRelatedCertificateextension value, e.g. viaRelatedCertificate.getInstance(ext.getParsedValue()).relatedCert- the candidate related certificate.digestProvider- a provider able to instantiate aDigestCalculatorfor thehashAlgorithmcarried byextensionValue.- Throws:
OperatorCreationExceptionjava.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.IOExceptionWrite the bytes thesignaturefield must cover straight intoout: the DER encoding ofcertIDfollowed by the DER encoding ofrequestTime, 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 intermediatebyte[]is materialised; pass aContentSigner/ContentVerifieroutput stream (or aByteArrayOutputStreamif 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.IOExceptionBuild a fully-signedRequesterCertificatevalue. The suppliedContentSignermust be configured with the private key of the certificate identified bycertID.- Throws:
java.io.IOException
-
verifyRequesterCertificate
public static boolean verifyRequesterCertificate(org.bouncycastle.asn1.cms.RequesterCertificate value, ContentVerifier verifier) throws java.io.IOExceptionVerify the signature carried invalueusing the suppliedContentVerifier. The verifier must be configured with the public key of the certificate identified byvalue.getCertID()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 aRequesterCertificatevalue as a PKCS#9AttributecarryingPKCSObjectIdentifiers.id_aa_relatedCertRequest, ready to drop into aCertificationRequestInfoattributes set.
-
fromAttribute
public static org.bouncycastle.asn1.cms.RequesterCertificate fromAttribute(org.bouncycastle.asn1.pkcs.Attribute attribute)
Extract aRequesterCertificatevalue from a PKCS#9Attribute.- Throws:
java.lang.IllegalArgumentException- if the attribute is not of typePKCSObjectIdentifiers.id_aa_relatedCertRequestor does not carry exactly one value.
-
-