JEP 538: PEM Encodings of Cryptographic Objects (Third Preview)
Introduction
Some formats are so ubiquitous that we almost forget they need to be "supported." PEM is one such format, every developer who has ever used a certificate, SSH, or HTTPS has seen it, yet Java's standard library never officially supported reading and writing it. So countless projects each rolled their own. JEP 538 finally fits that missing piece into the standard library.
PEM, the format everyone already uses
If you have ever worked with HTTPS, SSH, or any kind of certificate, then you have already encountered PEM, those text blocks wrapped in -----BEGIN----- and -----END----- lines.
- Its structure is simple: a Base64-encoded payload wrapped in BEGIN/END lines.
- It is the default on-disk format for keys, certificates, and CRLs (certificate revocation lists).
- Virtually every security tool speaks it: OpenSSL, Kubernetes Secrets, every cloud provider's key stores, PEM is the de facto lingua franca of this ecosystem.
- Yet, ironically, the JDK never had a supported API to read or write PEM. For such a pervasive format, the Java standard library always treated it as "someone else's problem."
What developers do without it
Without a standard API, the result is that every project reinvents the wheel, and not necessarily correctly.
The typical hand-rolled approach:
- Strip the BEGIN/END header and footer lines by hand, then Base64-decode the content in between.
- Guess what the decoded DER data actually is, a PKCS#8 private key? An X.509 certificate? Something else?
- Or simply pull in a heavyweight third-party library like Bouncy Castle just to parse a few lines of text.
- And this ad-hoc, cobbled-together code is especially prone to subtle, non-throwing errors, it runs without complaint but behaves quietly wrong, and by the time you notice, it may already have become a security problem.
Scattered across countless codebases, this ad-hoc code is both duplicated effort and a breeding ground for hidden risks.
What the JEP provides
JEP 538 provides a clean pair of APIs in the standard library: PEMEncoder (writes) and PEMDecoder (reads).
PEMEncoderandPEMDecoderare built into the standard library.- You can decode straight to public keys, private keys, certificates, CRLs, or generic PEM objects. You tell the decoder the type you expect, and it hands back the corresponding Java object.
- You can also encode objects implementing
BinaryEncodableback out to PEM text. Text and object round-trip cleanly in both directions. - Encrypted private keys are handled too, by configuring the encoder with
PEMEncoder.of().withEncryption(password).
The whole process is type-safe, concise, and requires no knowledge of ASN.1 internals.
Code example
// Decode a PEM file to a PrivateKey
PEMDecoder decoder = PEMDecoder.of();
PrivateKey key = decoder.decode(
Files.readString(Path.of("key.pem")),
PrivateKey.class);
// Encode a certificate back to PEM
PEMEncoder encoder = PEMEncoder.of();
String pem = encoder.encodeToString(certificate);
Reading a PEM file and getting a PrivateKey object, three lines. Encoding a certificate back to a PEM string, two. Compare that to the old "strip lines + Base64 + guess the algorithm + pull in a dependency" code, and the difference is obvious at a glance.
Before and after
Before:
- Manual string surgery plus Base64 decoding.
- A
KeyFactorycall per key algorithm, chosen by guesswork, guess wrong and it breaks. - An extra third-party dependency for a format the JDK should already understand.
After:
- One decoder call returns the right object.
- Text and object round-trip cleanly.
- No third-party library in the trust boundary.
That last point deserves emphasis: a security-related third-party library is itself a link in your trust boundary. One fewer third-party dependency means one less supply-chain risk. JEP 538 lets you do this with the standard library, removing an external dependency from the core cryptographic path.
Preview status
This is already the third preview, meaning the API is being continuously refined based on community feedback.
- It ships in JDK 27 as a third preview, refined from earlier feedback.
- It requires the
--enable-previewflag. - It is part of a broader modernization of the JDK security APIs, together with a series of other security-related improvements bringing Java's cryptography development experience up to modern expectations.
Conclusion
PEM is a format nearly every deployment uses, yet Java developers have for years dealt with it through ad-hoc workarounds, manual parsing, guessed algorithms, heavyweight dependencies. JEP 538 closes that long-standing gap with a standard-library API that replaces error-prone hand-written code and unnecessary third-party dependencies. A format everyone already uses finally gets official support in Java.