Skip to content

Instantly share code, notes, and snippets.

@destan
Last active March 29, 2024 10:43
Show Gist options
  • Save destan/b708d11bd4f403506d6d5bb5fe6a82c5 to your computer and use it in GitHub Desktop.
Save destan/b708d11bd4f403506d6d5bb5fe6a82c5 to your computer and use it in GitHub Desktop.
Parse RSA public and private key pair from string in Java
#!/usr/bin/env bash
openssl genrsa -out private_key.pem 4096
openssl rsa -pubout -in private_key.pem -out public_key.pem
# convert private key to pkcs8 format in order to import it from Java
openssl pkcs8 -topk8 -in private_key.pem -inform pem -out private_key_pkcs8.pem -outform pem -nocrypt
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
/**
* This file is intended to be used on a IDE for testing purposes.
* ClassLoader.getSystemResource won't work in a JAR
*/
public class Main {
public static void main(String[] args) throws InvalidKeySpecException, NoSuchAlgorithmException, IOException, URISyntaxException {
String privateKeyContent = new String(Files.readAllBytes(Paths.get(ClassLoader.getSystemResource("private_key_pkcs8.pem").toURI())));
String publicKeyContent = new String(Files.readAllBytes(Paths.get(ClassLoader.getSystemResource("public_key.pem").toURI())));
privateKeyContent = privateKeyContent.replaceAll("\\n", "").replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "");
publicKeyContent = publicKeyContent.replaceAll("\\n", "").replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "");;
KeyFactory kf = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyContent));
PrivateKey privKey = kf.generatePrivate(keySpecPKCS8);
X509EncodedKeySpec keySpecX509 = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyContent));
RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(keySpecX509);
System.out.println(privKey);
System.out.println(pubKey);
}
}
@hallundbaek
Copy link

hallundbaek commented Jun 25, 2023

Rewrote the java part to a Kotlin function that returns a KeyPair:

import java.nio.file.Files
import java.security.KeyFactory
import java.security.KeyPair
import java.security.spec.PKCS8EncodedKeySpec
import java.security.spec.X509EncodedKeySpec
import java.util.*
import kotlin.io.path.Path

fun readKeyPair(
  publicKeyPath: String,
  privateKeyPath: String,
): KeyPair =
  KeyFactory.getInstance("RSA").let { keyFactory ->
    KeyPair(
      keyFactory.generatePublic(
        X509EncodedKeySpec(
          Base64.getDecoder().decode(
            String(Files.readAllBytes(Path(publicKeyPath)))
                .replace("\n", "")
                .replace("-----BEGIN PUBLIC KEY-----", "")
                .replace("-----END PUBLIC KEY-----", "")
          )
        )
      ),
      keyFactory.generatePrivate(
        PKCS8EncodedKeySpec(
          Base64.getDecoder().decode(
            String(Files.readAllBytes(Path(privateKeyPath)))
                .replace("\n", "")
                .replace("-----BEGIN PRIVATE KEY-----", "")
                .replace("-----END PRIVATE KEY-----", "")
          )
        )
      )
    )
  }

@hungchu0912
Copy link

For anyone using java > 17, if you getting error at line 'Base64.getDecoder().decode(privateKeyContent)'. Replace it with getMimeDecoder() might work.
Base64.getMimeDecoder().decode(privateKeyContent)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment