July 29, 2025

JDK 25 - JEP 470: PEM Encodings of Cryptographic Objects (Preview)

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