import java.nio.charset.StandardCharsets;import java.util.Base64; public final class Pem { private Pem() {} /** The DER bytes inside the PEM block with the given label ("CERTIFICATE", "PRIVATE KEY", ...). */ public static byte[] toDer(String pem, String label) { String begin = "-----BEGIN " + label + "-----"; String end = "-----END " + label + "-----"; int from = pem.indexOf(begin); int to = pem.indexOf(end, from + 1); if (from < 0 || to < 0) throw new IllegalArgumentException("no " + label + " block"); return Base64.getMimeDecoder().decode(pem.substring(from + begin.length(), to)); // skips line breaks } /** DER bytes as a PEM block: base64 in 64-character lines between BEGIN and END. */ public static String fromDer(byte[] der, String label) { String body = Base64.getMimeEncoder(64, "\n".getBytes(StandardCharsets.US_ASCII)).encodeToString(der); return "-----BEGIN " + label + "-----\n" + body + "\n-----END " + label + "-----\n"; }} How it works
toDerfinds the block with the expected label and decodes its body withBase64.getMimeDecoder(), which skips the line breaks: 563 bytes for the certificate, 138 for the PKCS#8 key.fromDerencodes withBase64.getMimeEncoder(64, "\n")— PEM's 64-character lines with LF endings — so the round trip reproduces the original files exactly.- The DER goes straight into the JCA:
CertificateFactory.generateCertificate(whosegetEncoded()returns the same bytes) andKeyFactory.generatePrivate(new PKCS8EncodedKeySpec(der)). - The run checks the certificate's DER with OpenSSL (
openssl x509 -inform DER) too.
Gotchas
Base64.getDecoder()rejects the line breaks inside PEM:Illegal base64 character a(0x0a, the newline). UsegetMimeDecoder().getMimeEncoder()without arguments writes 76-character lines with CRLF (checked in the run) — valid MIME, but not PEM's 64 characters, and not byte-identical to OpenSSL's output.PKCS8EncodedKeySpecneeds PKCS#8 (BEGIN PRIVATE KEY); the same key as SEC1 DER (BEGIN EC PRIVATE KEY) fails withInvalidKeySpecException. Convert it once withopenssl pkcs8 -topk8 -nocrypt.
Related recipes
- How to convert a certificate and a private key between PEM and DER in Kotlin
- How to convert a certificate and a private key between PEM and DER in C# (.NET)
- How to convert a certificate and a private key between PEM and DER with OpenSSL
- How to export a public key as PEM in Java
- How to decode an X.509 certificate in Java