Decode/Read a CSR (Certificate Signing Request) Using Java or BouncyCastle

13,391

Solution 1

Figured it out:

  1. Convert the CSR PEM to a PKCS10CertificationRequest
  2. Get the X500Name instance by accessing the getSubject() method from PKCS10CertificationRequest instance
  3. Iterate over the RDN[] array and get the specific field you want using one of the ASN1ObjectIdentifier's (for example COUNTRY is 2.5.4.6)

Here is the code:

public class EncryptDecrypt {
    private Logger LOG = LoggerFactory.getLogger(EncryptDecrypt.class);
    private final String COUNTRY = "2.5.4.6";
    private final String STATE = "2.5.4.8";
    private final String LOCALE = "2.5.4.7";
    private final String ORGANIZATION = "2.5.4.10";
    private final String ORGANIZATION_UNIT = "2.5.4.11";
    private final String COMMON_NAME = "2.5.4.3";


    @Test
    public void testReadCertificateSigningRequest() {
        String csrPEM = "-----BEGIN CERTIFICATE REQUEST-----\n" +
                "MIICwjCCAaoCAQAwfTELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0Zsb3JpZGExEzAR\n" +
                "BgNVBAcTCkJvY2EgUmF0b24xGzAZBgNVBAoTEkxvb25leSBUb29ucywgSW5jLjEU\n" +
                "MBIGA1UECxMLRGV2ZWxvcG1lbnQxFDASBgNVBAMTC2V4YW1wbGUuY29tMIIBIjAN\n" +
                "BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiJCj31d1Rp+aKz/GTkedaiS/VSCc\n" +
                "PRARYgXukobjgBHx46HjldAcfg/DoANn5lEQaFxaIZJLbZ/AdLUyw/hUbU0CjWXv\n" +
                "pN3Ep3o9XgRTPkIFoI22VOI/O2ZLjBq/E4DWyVmv+vG6BK0LRh7hykzPCw6KIRR9\n" +
                "NCmUMJMQX5d5P/r1lR5H399pnLcLsrHoWDwBSEDgkGWyxnvEB0+/bIz42T3qnlFt\n" +
                "7avarxlHG2p5DoRTf8GJ+6imY88ZeBW/Nk18aDINsAHWLv383JICIAsZ3VuMk8m/\n" +
                "Z/Z5b21zIuZECDJjZjvAAjr/shVLB+Pck5+HJy6tqj79MJOQu+jKIrK8VwIDAQAB\n" +
                "oAAwDQYJKoZIhvcNAQEFBQADggEBAGtuAAHG4OC9jSRjGWSqfMXTDMz9tgekDREA\n" +
                "SYv5QIrOXsMzwbgDw8LxRJZEskl4JJOnjwEvUXWUF1M6XmG2h358nOnrkOlsumHw\n" +
                "Tx5gGSr6S6aJO/HG46erctE8aWpnFZYMfuEkul4ApsIufL7Bxqs3NHZWcrWBlLIP\n" +
                "aVCKx1FPRMC36Tj3EslbuUB/iTRt90Nfq1IxHMIKiwCiSNJSqfRVLANhI8MUbOjB\n" +
                "CBly1wcH68WWNkyvHVvbcF/B9AfYG9AqWjZjygKpyf81VZWctXhDc8UtomqrblXN\n" +
                "mvz4RKpIhZQLuuxlBrdzJkPm2sOdtdZghebCRRVWdjsig4sylgQ=\n" +
                "-----END CERTIFICATE REQUEST-----";

        PKCS10CertificationRequest csr = convertPemToPKCS10CertificationRequest(csrPEM);

        X500Name x500Name = csr.getSubject();
        System.out.println("x500Name is: " + x500Name + "\n");

        // country is 2.5.4.6
        System.out.println("COUNTRY: " + getX500Field(COUNTRY, x500Name));
        // state is 2.5.4.8
        System.out.println("STATE: " + getX500Field(STATE, x500Name));
        // locale is 2.5.4.7
        System.out.println("LOCALE: " + getX500Field(LOCALE, x500Name));


    }

    private String getX500Field(String asn1ObjectIdentifier, X500Name x500Name) {
        RDN[] rdnArray = x500Name.getRDNs(new ASN1ObjectIdentifier(asn1ObjectIdentifier));
        String retVal = null;
        for (RDN item : rdnArray) {
            retVal = item.getFirst().getValue().toString();
        }

        return retVal;
    }

    private PKCS10CertificationRequest convertPemToPKCS10CertificationRequest(String pem) {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        PKCS10CertificationRequest csr = null;
        ByteArrayInputStream pemStream = null;
        try {
            pemStream = new ByteArrayInputStream(pem.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException ex) {
            LOG.error("UnsupportedEncodingException, convertPemToPublicKey", ex);
        }

        Reader pemReader = new BufferedReader(new InputStreamReader(pemStream));
        PEMParser pemParser = new PEMParser(pemReader);

        try {
            Object parsedObj = pemParser.readObject();

            System.out.println("PemParser returned: " + parsedObj);

            if (parsedObj instanceof PKCS10CertificationRequest) {
                csr = (PKCS10CertificationRequest) parsedObj;

            }
        } catch (IOException ex) {
            LOG.error("IOException, convertPemToPublicKey", ex);
        }

        return csr;
    }

    private String toPEM(Object key) {
        StringWriter sw = new StringWriter();
        PEMWriter pem = new PEMWriter(sw);
        try {
            pem.writeObject(key);
            pem.close();
        } catch (IOException e) {
            System.out.printf("IOException: %s%n", e);
        }
        return sw.toString();
    }
}

Solution 2

I propose this "simple" solution to read a csr

You must add dependency with

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcmail-jdk15on</artifactId>
    <version>1.62</version>
</dependency>

Create new object CSRObject

import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x500.RDN;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;

import java.io.*;

public class CSRObject {
    private final X500Name x500Name;

    public CSRObject(final String csr) throws IOException {
        final Reader pemReader = new StringReader(csr);
        final PEMParser pemParser = new PEMParser(pemReader);
        x500Name = ((PKCS10CertificationRequest) pemParser.readObject()).getSubject();
    }


    public String get(final CSRObjectEnum field) {
        RDN[] rdnArray = x500Name.getRDNs(new ASN1ObjectIdentifier(field.code));
        String retVal = null;
        for (RDN item : rdnArray) {
            retVal = item.getFirst().getValue().toString();
        }
        return retVal;
    }

    public enum CSRObjectEnum {
        COUNTRY("2.5.4.6"),
        STATE("2.5.4.8"),
        LOCALE("2.5.4.7"),
        ORGANIZATION("2.5.4.10"),
        ORGANIZATION_UNIT("2.5.4.11"),
        COMMON_NAME("2.5.4.3"),//
        ;
        private final String code;

        CSRObjectEnum(final String sCode) {
            code = sCode;
        }

    }
}

And you can test with this method :

@Test
public void test() throws IOException {
    final CSRObject csr = new CSRObject(TEST_CERTIF);
    for (final CSRObject.CSRObjectEnum field : CSRObject.CSRObjectEnum.values()){
        LOGGER.info("{}:{}", field.name(), csr.get(field));
    }
}

with TEST_CERTIF is String

private static final String TEST_CERTIF = "-----BEGIN CERTIFICATE REQUEST-----\n" +
        "...\n" +
        "-----END CERTIFICATE REQUEST-----\n";
Share:
13,391
David
Author by

David

Updated on June 05, 2022

Comments

  • David
    David almost 2 years

    I am generating a CSR (certificate signing request) using code without an issue with the appropriate information. I need pointers to figure out how to read the CSR content using Java and/or BouncyCastle.

    Any pointers or ideas are appreciated.

  • EpicPandaForce
    EpicPandaForce over 9 years
    It is worth noting that ASN1ObjectIdentifiers are stored in the BCStyle static class as public static final ASN1ObjectIdentifiers, so things like COUNTRY don't need to be recreated from zero. However, it is not an enum.
  • darkknightsds
    darkknightsds about 5 years
    Nice, thanks for sharing. See my updated code for Kotlin/ Android below.