PKCS10CertificationRequestBuilder generates invalid PKCS10CertificationRequest in org.bouncycastle.pkcs

I am trying to use Spongy Castle (v1.47) to create a PKCS10 certification request. Spongy Castle behaves exactly like Bouncy Castle, but more suitable for porting to Android.

The old (stripped) way described at the beginning of cryptography with Java by David Hook in Chapter 6 works very well:

package chapter6;

import java.io.OutputStreamWriter;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Security;
import java.util.Vector;
import javax.security.auth.x500.X500Principal;
import org.spongycastle.asn1.DEROctetString;
import org.spongycastle.asn1.DERSet;
import org.spongycastle.asn1.pkcs.Attribute;
import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.spongycastle.asn1.x509.GeneralName;
import org.spongycastle.asn1.x509.GeneralNames;
import org.spongycastle.asn1.x509.X509Extension;
import org.spongycastle.asn1.x509.X509Extensions;
import org.spongycastle.jce.PKCS10CertificationRequest;
import org.spongycastle.openssl.PEMWriter;
import org.spongycastle.jce.provider.BouncyCastleProvider;

/**
 * Generation of a basic PKCS #10 request with an extension.
 */
public class PKCS10ExtensionExample {
  static {
    BouncyCastleProvider prov = new org.spongycastle.jce.provider.BouncyCastleProvider();
    Security.addProvider(prov);
  }

  public static PKCS10CertificationRequest generateRequest( KeyPair pair) throws Exception {
    // create a SubjectAlternativeName extension value
    GeneralNames subjectAltName = new GeneralNames(new GeneralName(GeneralName.rfc822Name, "test@test.test"));

    // create the extensions object and add it as an attribute
    Vector oids = new Vector();
    Vector values = new Vector();
    oids.add(X509Extensions.SubjectAlternativeName);
    values.add(new X509Extension(false, new DEROctetString(subjectAltName)));
    X509Extensions extensions = new X509Extensions(oids, values);
    Attribute attribute = new Attribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, new DERSet(extensions));

    return new PKCS10CertificationRequest(
           "SHA256withRSA",
           new X500Principal("CN=Requested Test Certificate"),
           pair.getPublic(),
           new DERSet(attribute),
           pair.getPrivate());
  }

  public static void main(String[] args) throws Exception {
    // create the keys
    KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "SC");
    kpGen.initialize(1024, Utils.createFixedRandom());
    KeyPair pair = kpGen.generateKeyPair();
    PKCS10CertificationRequest request = generateRequest(pair);
    PEMWriter pemWrt = new PEMWriter(new OutputStreamWriter(System.out));
    pemWrt.writeObject(request);
    pemWrt.close();
  }
}

      

A small Java program produces the following:

-----BEGIN CERTIFICATE REQUEST-----
MIIBkDCB+gIBADAlMSMwIQYDVQQDExpSZXF1ZXN0ZWQgVGVzdCBDZXJ0aWZpY2F0
ZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAm38mHcNo+YDhe1/XHRa1Cifj
EUwH6SQfqKQcY0sO4gGTVL/U5kBx/y0gIptrnGgUYgfwqptWoKHIqd4PGAuzHfwI
QrTfnYtLnN3dBdnOx/1mZuJ/fCD48H45sTVCcXbypxdwns2PZwgh1rt+jb7TJQii
5TteCLvzzb7FVb/Oc6MCAwEAAaAsMCoGCSqGSIb3DQEJDjEdMBswGQYDVR0RBBIw
EIEOdGVzdEB0ZXN0LnRlc3QwDQYJKoZIhvcNAQELBQADgYEAJexpAYF6RvbYGiNS
kyaF1H8TpDOHaAuIvS4G2Kqw9xXJHYEDiNsQxMc4gWdx6ZNDzc1JYqFBaEV+c/zt
pRPLTRxTi841tLBUAzX7eFQ5EtLwJrKLlHCMXxg3DwcrPjRwidcE87Nl/sOyeT4K
btCXzqpLtklJi/giBl/4L+lQunU=
-----END CERTIFICATE REQUEST-----

      

The problem is that at the same time (book from 2005) most of these classes are marked as deprived. A new way to create certificate signing requests is to use Factory Patterns:

package chapter6;

import java.io.OutputStreamWriter;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Security;
import java.util.Vector;

import org.spongycastle.asn1.DERPrintableString;
import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.spongycastle.asn1.x500.X500Name;
import org.spongycastle.asn1.x509.ExtendedKeyUsage;
import org.spongycastle.asn1.x509.KeyPurposeId;
import org.spongycastle.asn1.x509.KeyUsage;
import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
import org.spongycastle.asn1.x509.X509Extension;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.spongycastle.openssl.PEMWriter;
import org.spongycastle.operator.ContentSigner;
import org.spongycastle.operator.ContentVerifierProvider;
import org.spongycastle.operator.jcajce.JcaContentSignerBuilder;
import org.spongycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
import org.spongycastle.pkcs.PKCS10CertificationRequest;
import org.spongycastle.pkcs.PKCS10CertificationRequestBuilder;

/**
 * Generation of a basic PKCS #10 request with an extension.
 */
public class PKCS10ExtensionExampleNew {
  static {
    BouncyCastleProvider prov = new org.spongycastle.jce.provider.BouncyCastleProvider();
    Security.addProvider(prov);
  }

  public static PKCS10CertificationRequest generateRequest(KeyPair pair) throws Exception {
    SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(pair.getPublic().getEncoded());
    X500Name subject = new X500Name("CN=Requested Test Certificate");
    PKCS10CertificationRequestBuilder certificationRequestBuilder = new PKCS10CertificationRequestBuilder(subject, publicKeyInfo);

    certificationRequestBuilder.addAttribute(X509Extension.keyUsage, 
        new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment | KeyUsage.dataEncipherment | KeyUsage.keyAgreement));

    Vector<KeyPurposeId> ekUsages = new Vector<KeyPurposeId>();
    ekUsages.add(KeyPurposeId.id_kp_clientAuth);
    ekUsages.add(KeyPurposeId.id_kp_serverAuth);
    certificationRequestBuilder.addAttribute(X509Extension.extendedKeyUsage, new ExtendedKeyUsage(ekUsages));

    JcaContentSignerBuilder contentSignerBuilder = new JcaContentSignerBuilder("SHA1WithRSAEncryption");
    contentSignerBuilder.setProvider("SC");
    ContentSigner contentSigner = contentSignerBuilder.build(pair.getPrivate());

    DERPrintableString password = new DERPrintableString("secret123");
    certificationRequestBuilder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_challengePassword, password);

    PKCS10CertificationRequest certificationRequest = certificationRequestBuilder.build(contentSigner);

    JcaContentVerifierProviderBuilder contentVerifierProviderBuilder = new JcaContentVerifierProviderBuilder();
    ContentVerifierProvider contentVerifierProvider = contentVerifierProviderBuilder.build(pair.getPublic());
    System.out.println("isSignatureValid? " + certificationRequest.isSignatureValid(contentVerifierProvider));
    System.out.println(certificationRequest.getSubject());
    return certificationRequest;
  }

  public static void main(String[] args) throws Exception {
    // create the keys
    KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "SC");
    kpGen.initialize(1024, Utils.createFixedRandom());
    KeyPair pair = kpGen.generateKeyPair();
    PKCS10CertificationRequest request = generateRequest(pair);
    PEMWriter pemWrt = new PEMWriter(new OutputStreamWriter(System.out));
    pemWrt.writeObject(request);
    pemWrt.close();
  }
}

      

Certificate request is not generated as expected as it does not work in PEM Generation:

isSignatureValid? true
CN=Requested Test Certificate
Exception in thread "main" org.spongycastle.util.io.pem.PemGenerationException: unknown object passed - can't encode.
  at org.spongycastle.openssl.MiscPEMGenerator.createPemObject(MiscPEMGenerator.java:208)
  at org.spongycastle.openssl.MiscPEMGenerator.generate(MiscPEMGenerator.java:333)
  at org.spongycastle.util.io.pem.PemWriter.writeObject(PemWriter.java:76)
  at org.spongycastle.openssl.PEMWriter.writeObject(PEMWriter.java:45)
  at be.boeboe.spongycastle.chapter6.PKCS10ExtensionExampleNew.main(PKCS10ExtensionExampleNew.java:71)

      

Does anyone know why the second attempt to create the request failed? I created X509V3Certificate in both the old and the new way and I had no problems there, but adding these differences alongside the ones shown here did not make me any wiser.

Any help is kindly appreciated.

Boeboe

+3


source to share





All Articles