Skip to content

Instantly share code, notes, and snippets.

@destan
Last active October 28, 2024 07:07
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);
}
}
@raksheetbhat
Copy link

saved my day as well! Thanks.

@amifeanyi
Copy link

amifeanyi commented May 26, 2020

Thanks a lot, saved my day.

@DEVIJAM
Copy link

DEVIJAM commented Jun 8, 2020

Gracias

@ieugen
Copy link

ieugen commented Jun 10, 2020

Thank you. I found this while researching how to load PEM files for TLS termination with LetsEncrypt certificates in Apache James (Java email server).

Do you know if it is possible to multiple PEM files ? One certificate for each email domain? I'm not familiar with all the jargon in the security area.

@rsb007
Copy link

rsb007 commented Jun 18, 2020

Thanks a lot.

@kumarvimals
Copy link

Hi, I am trying to generate java.security.interfaces.RSAPublicKey object using publickey as a String to validate the access token (JWT),But i am getting InvalidKeyException: algid parse error. Please help me on this. Below is my code

String publicKeyB64 = "my publickey ";
byte[] decoded = Base64.getDecoder().decode(publicKeyB64);
X509EncodedKeySpec spec = new X509EncodedKeySpec(decoded);
KeyFactory kf = KeyFactory.getInstance("RSA");
RSAPublicKey generatePublic = (RSAPublicKey) kf.generatePublic(spec);

@KiryhaPikoff
Copy link

Thanks man, i spent 4 hours, before i find it!!

@abhishekprasad870
Copy link

Is there any way to generate a private key without replacing the below lines?
privateKeyContent = privateKeyContent.replaceAll("\n", "").replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "");
publicKeyContent = publicKeyContent.replaceAll("\n", "").replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "");

@abhishekprasad870
Copy link

abhishekprasad870 commented Sep 8, 2020

Generate Private key and Public key in Java using .key file

Got the answer for above query this...... Use bouncycastle jar

// using bouncycastle to generate public key
public static PublicKey getPublicKey() throws InvalidKeySpecException, NoSuchAlgorithmException, IOException {
	KeyFactory factory = KeyFactory.getInstance("RSA");
	File file = new File("../sha1/src/main/resources/cert/publicKey.key");
	try (FileReader keyReader = new FileReader(file); PemReader pemReader = new PemReader(keyReader)) {
		PemObject pemObject = pemReader.readPemObject();
		byte[] content = pemObject.getContent();
		X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(content);
		PublicKey publicKey = factory.generatePublic(pubKeySpec);
		return publicKey;
	}
}

public static PrivateKey getPrivateKey() throws InvalidKeySpecException, NoSuchAlgorithmException, IOException {
	KeyFactory factory = KeyFactory.getInstance("RSA");
	File file = new File("../sha1/src/main/resources/cert/privateKey.key");
	try (FileReader keyReader = new FileReader(file); PemReader pemReader = new PemReader(keyReader)) {
		PemObject pemObject = pemReader.readPemObject();
		byte[] content = pemObject.getContent();
		PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(content);
		PrivateKey privateKey = factory.generatePrivate(privateKeySpec);
		return privateKey;
	}
}

@a-torres
Copy link

a-torres commented Oct 5, 2020

@abhishekprasad870 I'm trying to get Private key from .key file, but I get null when reading pemObject. Is there something I'm missing? I'm using an existing .key file.

public static PrivateKey getPrivateKey() throws InvalidKeySpecException, NoSuchAlgorithmException, IOException { KeyFactory factory = KeyFactory.getInstance("RSA"); File file = new File("../sha1/src/main/resources/cert/privateKey.key"); try (FileReader keyReader = new FileReader(file); PemReader pemReader = new PemReader(keyReader)) { PemObject pemObject = pemReader.readPemObject(); byte[] content = pemObject.getContent(); PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(content); PrivateKey privateKey = factory.generatePrivate(privateKeySpec); return privateKey; }

@alemasettonttdata
Copy link

Thanks!

@TavenYin
Copy link

Thanks!

@Nallani9
Copy link

Nallani9 commented Mar 30, 2021

Getting NullPointerException, I have files in the root directory ??

@samiraghayarov
Copy link

Tesekkurler kardes!

@ytahrijo
Copy link

ytahrijo commented May 6, 2021

I got this error Illegal base64 character d
Do you have an idea ?

@tmuerell
Copy link

Thanks for this! 👍

@turkdogantdx
Copy link

Thanks 😄

@bronejeffries
Copy link

thanks man, saved my day

@supejuice
Copy link

Thanks man, saved my day

@devToroko
Copy link

thanks!!!

@and-petrenko
Copy link

Thanks, it was helpful!

@felixcarpena
Copy link

Thanks!!! ❤️

@ubaid4j
Copy link

ubaid4j commented Dec 20, 2022

Thanks, it worked like a charm.

@KhawanC
Copy link

KhawanC commented Dec 26, 2022

For those who are getting "Illegal base64 character d" error, here is the solution.

There is a regex missing in the public/privateKeyContent. Just add it at the end of the statment --> .replaceAll("\s", "")

@chmonk
Copy link

chmonk commented Jan 31, 2023

thanks a lot! save my day!!

@ssm498
Copy link

ssm498 commented Apr 13, 2023

For @KhawanC comment on 'illegal character d', its .replaceAll("\\s", "") for ALL whitespace characters (two backward slashes)
... ahhh I see the mistake, when we type in two '\' '\' github automatically removes one before posting :)

@thar0x29a
Copy link

Saved many of us. Thank you.

@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)

@bithexe
Copy link

bithexe commented Jul 9, 2024

Thank you! Still helpful in 2024... 😄

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