4

I have a document that is digitally signed using CAdES. I use BouncyCastle APIs to get the X509Certificate[] instances of the signers, but let's assume the list contains one and one only element.

I need to verify whether this certificate is trusted or not at today's date, and I don't want to use the system's standard trust store which is normally used to trust SSL certificates. No, I want to build my own trust list with a list of .cer files in my classpath. At the moment, a single CA is trusted but obviously in the future a few more certificates may be added.

So far I have read this and tried to implement in my code. I need no SSLContext, I need to check the validity of a digitally signed document. I am now confused.

X509TrustManager APIs do however provide only methods for validating client/server certificates, but mine only have digital signature/non-repudiation usage flags.

The questions can be formulated in two ways that lead to the same:

  1. How does one in Java check the validity of an X509Certificate instance against a custom root CA list that can be loaded in memory?
  2. How does one check that a digitally-signed document is signed with a certificate deriving from a known CA of a custom list?
Community
  • 1
  • 1
usr-local-ΕΨΗΕΛΩΝ
  • 26,101
  • 30
  • 154
  • 305

1 Answers1

3

Extract from the CAdES signature for each signer the signer's certificate and also the intermediate certificates as a X509Certificate list. Build also a set with all root CA certificates

Then you can use this (slightly adapted) example code to verify and build the certification chain using Java and BouncyCastle. It will return the certification chain if verification is successful

public PKIXCertPathBuilderResult verifyCertificateChain(
     X509Certificate cert, 
     Set<X509Certificate> trustedRootCerts,
     Set<X509Certificate> intermediateCerts) throws GeneralSecurityException {

    // Create the selector that specifies the starting certificate
    X509CertSelector selector = new X509CertSelector(); 
    selector.setCertificate(cert);

    // Create the trust anchors (set of root CA certificates)
    Set<TrustAnchor> trustAnchors = new HashSet<TrustAnchor>();
    for (X509Certificate trustedRootCert : trustedRootCerts) {
        trustAnchors.add(new TrustAnchor(trustedRootCert, null));
    }

    // Configure the PKIX certificate builder algorithm parameters
    PKIXBuilderParameters pkixParams = 
        new PKIXBuilderParameters(trustAnchors, selector);

    // Disable CRL checks (this is done manually as additional step)
    pkixParams.setRevocationEnabled(false);

    // Specify a list of intermediate certificates
    // certificate itself has to be added to the list 
    intermediateCerts.add(cert); 
    CertStore intermediateCertStore = CertStore.getInstance("Collection",
        new CollectionCertStoreParameters(intermediateCerts), "BC");
    pkixParams.addCertStore(intermediateCertStore);

    // Build and verify the certification chain
    CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", "BC");
    PKIXCertPathBuilderResult result = 
        (PKIXCertPathBuilderResult) builder.build(pkixParams);
    return result;
}

If you do not want to deal with CAdES complexity, I suggest to use SD-DSS open-source project

pedrofb
  • 37,271
  • 5
  • 94
  • 142
  • Luckily, BouncyCastle helped me a lot to deal with CAdES complexity by extracting the signer certificate and document hash code – usr-local-ΕΨΗΕΛΩΝ Mar 01 '17 at 09:39
  • Hmmm... no matter what, I always get an exception that "No certificate found matching targetConstraints". I tried to load the trustedRootCerts also from system trust store, which contains the target root CA (debugging, I found the correct certificate in the in-memory store) – usr-local-ΕΨΗΕΛΩΝ Mar 01 '17 at 10:29
  • The certificate itself has to be added to the intermediate list `intermediateCerts.add(cert);` The code i've linked is not correct. I have updated the link with the original source – pedrofb Mar 01 '17 at 11:10
  • Could you check the modified answer? – pedrofb Mar 02 '17 at 10:52
  • Will do in the following days. For the moment I have workarounded the whole thing by the luck of assuming that the path length IS always 1 (user cert is not signed by intermediate CA). I am behind schedule as the majority of developers :-( – usr-local-ΕΨΗΕΛΩΝ Mar 02 '17 at 14:29