Convert certificate string to byte array

Leem.fin picture Leem.fin · Nov 5, 2016 · Viewed 8.7k times · Source

I got a string represents PEM certificate:

-----BEGIN CERTIFICATE-----
MIICUTCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADBXMQswCQYDVQQGEwJDTjEL
MAkGA1UECBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMC
VU4xFDASBgNVBAMTC0hlcm9uZyBZYW5nMB4XDTA1MDcxNTIxMTk0N1oXDTA1MDgx
NDIxMTk0N1owVzELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAlBOMQswCQYDVQQHEwJD
TjELMAkGA1UEChMCT04xCzAJBgNVBAsTAlVOMRQwEgYDVQQDEwtIZXJvbmcgWWFu
ZzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCp5hnG7ogBhtlynpOS21cBewKE/B7j
V14qeyslnr26xZUsSVko36ZnhiaO/zbMOoRcKK9vEcgMtcLFuQTWDl3RAgMBAAGj
gbEwga4wHQYDVR0OBBYEFFXI70krXeQDxZgbaCQoR4jUDncEMH8GA1UdIwR4MHaA
FFXI70krXeQDxZgbaCQoR4jUDncEoVukWTBXMQswCQYDVQQGEwJDTjELMAkGA1UE
CBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMCVU4xFDAS
BgNVBAMTC0hlcm9uZyBZYW5nggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEE
BQADQQA/ugzBrjjK9jcWnDVfGHlk3icNRq0oV7Ri32z/+HQX67aRfgZu7KWdI+Ju
Wm7DCfrPNGVwFWUQOmsPue9rZBgO
-----END CERTIFICATE-----

I assigned the above string to String variable String myCertStr.

What is the proper way to convert myCertStr to DER encoded byte[]?

(I am using Java 7, and I am not interested to use 3rd party library for this, I am seeking for a JDK7 way of doing it.)

Answer

zeppelin picture zeppelin · Nov 5, 2016

IMPORTANT

As @dave_thompson_085 has pointed out in the comments, SunJCE CertificateFactory is indeed capable of parsing PEM files.

So you can just use that to get the Certificate object as detailed at How to load public certificate from pem file..? (which is an earlier answer by @dave on the same topic, so please upvote it, instead of this one, if you find this useful !), and then access its encoded (DER) form.

However, if your PEM file is a raw "RSA PUBLIC KEY" (like the one that was attached to this question), or some other entity which SunJCE implementation can not parse directly, you can still parse and decode it manually, as detailed below.


Technically what you have here is not a certificate, but just a public key.

You can decode it to DER bytes as simple as that:

byte[] derBytes = Base64.getDecoder().decode(
    pemText.replaceAll("-----(BEGIN|END) RSA PUBLIC KEY-----", "").replaceAll("\n", "")
);

Note, that what you will get will be a raw RSA (PKCS#1) key:

RSAPublicKey ::= SEQUENCE {
    modulus           INTEGER,  -- n
    publicExponent    INTEGER   -- e
}

You can use the same technique to decode X.509 certificates or private keys.

E.g. the code to decode the X.509 certificate:

byte[] certificateBytes = Base64.getDecoder().decode(
    pemText.replaceAll("-----(BEGIN|END) CERTIFICATE-----", "").replaceAll("\n", "").getBytes("UTF-8")
);

CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
    X509Certificate certificate = (X509Certificate)(certificateFactory.generateCertificate(
        new ByteArrayInputStream(certificateBytes)
    )
);

UPDATE

The code above uses Java 8 Base64 decoder. As question has been updated asking for a Java 7 solution, here is a link to an excellent thread, discussing various options available: Base64 Java encode and decode a string.

E.g. java.xml.bind method described there does not require any extra libraries on Java 7 (which seems to match what OP wants)