Abstract
JDK 25 - JEP 470: PEM Encodings of Cryptographic Objects (Preview). The Privacy-Enhanced Mail (PEM) format https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail defined by RFC 7468 https://www.rfc-editor.org/rfc/rfc7468 is a representation of cryptographic objects. This JEP adds encoding and decoding of the PEM format to Java.
Disclaimer
This post is solely informative. Critically think before using any information presented. Learn from it but ultimately make your own decisions at your own risk.
Requirements
I did all of the work for this post using the following major technologies. You may be able to do the same thing with different technologies or versions, but no guarantees.
- openjdk 25-ea 2025–09–16 (build 25-ea+27–3363)
- NetBeans 25
- Maven 3.9.6 (Bundled with NetBeans)
- maven-compiler-plugin-3.14.0
Download
Visit my GitHub page https://github.com/mjremijan to see all of my open source projects. The code for this post is located at https://github.com/mjremijan/thoth-jdk25
Compile and Run
This is a preview API, disabled by default. To use this API in JDK 25, you must enable preview APIs:
- Compile the program with javac --release 25 --enable-preview Main.java and run it with java --enable-preview Main;
- When using the source code launcher, run the program with java --enable-preview Main.java;
- When using jshell, start it with jshell --enable-preview.
Java Generate public/private PEM files
Create a Java KeyPair
and generate the public/private keys in PEM format.
Listing 1 - Java Generate Keys in PEM Format
package org.thoth.jdk25.jep470.main;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PEMEncoder;
import java.security.SecureRandom;
/**
*/
public class MainInMemoryEncoding {
public static void main(String[] args) throws Exception {
System.out.printf("Hello JEP-470 In memory encoding!%n%n");
System.out.printf("Create KeyPairGenerator for RSA%n");
KeyPairGenerator generator
= KeyPairGenerator.getInstance("RSA");
System.out.printf("Initialize KeyPairGenerator with a key size and SecureRandom%n");
generator.initialize(2048, new SecureRandom());
System.out.printf("Generate a KeyPair%n");
KeyPair pair
= generator.generateKeyPair();
System.out.printf("Create PEMEncoder%n");
PEMEncoder pe = PEMEncoder.of();
System.out.printf("Encode private key to the PEM format%n");
String privatePem = pe.encodeToString(pair.getPrivate());
System.out.printf("%s%n", privatePem);
System.out.printf("Encode public key to the PEM format%n");
String publicPem = pe.encodeToString(pair.getPublic());
System.out.printf("%s%n", publicPem);
}
}
OpenSSL Generate public/private PEM files
Use the following Linux commands to generate public/private keys in PEM format saved to files.
Listing 2 - Generate 2048-bit RSA private key PEM file
openssl genrsa -out test-private.pem 2048
Listing 3 - Extract RSA public key PEM file
openssl rsa -in test-private.pem -out test-public.pem -pubout -outform PEM
Java read public OpenSSL PEM file
Read the test-public.pem
file.
Listing 4 - Read test-public.pem
package org.thoth.jdk25.jep470.main;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.DEREncodable;
import java.security.PEMDecoder;
import java.security.PublicKey;
/**
*/
public class MainOpenSSLDecodingPublicFile {
public static void main(String[] args) throws Exception {
System.out.printf("Hello JEP-470! OpenSSL decoding public PEM file%n%n");
System.out.printf("Read the OpenSSL test-public.pem file into a String%n");
InputStream is = MainOpenSSLDecodingPublicFile.class.getClassLoader().getResourceAsStream("test-public.pem");
byte[] bytes = is.readAllBytes();
String publicPem = new String(bytes, StandardCharsets.UTF_8);
System.out.printf("%s%n", publicPem);
System.out.printf("Create PEMDecoder%n");
PEMDecoder pd = PEMDecoder.of();
System.out.printf("Decode the OpenSSL test-public.pem file%n");
DEREncodable derEncodable = pd.decode(publicPem);
switch (derEncodable) {
case PublicKey publicKey -> System.out.printf("Successfully decoded PublicKey!%n");
default -> System.out.printf("What is \"%s\"%n", derEncodable.getClass().getName());
}
}
}
Java read private OpenSSL PEM file
Read the test-private.pem
file.
Listing 5 - Read test-private.pem
package org.thoth.jdk25.jep470.main;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.DEREncodable;
import java.security.PEMDecoder;
import java.security.PrivateKey;
/**
*/
public class MainOpenSSLDecodingPrivateFile {
public static void main(String[] args) throws Exception {
System.out.printf("Hello JEP-470! OpenSSL decoding private PEM file%n%n");
System.out.printf("Read the OpenSSL test-private.pem file into a String%n");
InputStream is = MainOpenSSLDecodingPrivateFile.class.getClassLoader().getResourceAsStream("test-private.pem");
byte[] bytes = is.readAllBytes();
String privatePem = new String(bytes, StandardCharsets.UTF_8);
System.out.printf("%s%n", privatePem);
System.out.printf("Create PEMDecoder%n");
PEMDecoder pd = PEMDecoder.of();
System.out.printf("Decode the OpenSSL test-private.pem file%n");
DEREncodable derEncodable = pd.decode(privatePem);
switch (derEncodable) {
case PrivateKey privateKey -> System.out.printf("Successfully decoded PrivateKey!%n");
default -> System.out.printf("What is \"%s\"%n", derEncodable.getClass().getName());
}
}
}
Summary
JEP 470 add PEM encoding and decoding functionality to Java. In JDK 25, it is a preview feature so look for it to be finalized in a future release.
References
Scarpino, A. (2023, January 23). JEP 470: PEM Encodings of Cryptographic Objects (Preview). https://openjdk.org/jeps/470