Read RSA private key of format PKCS1 in JAVA
Asked Answered
P

2

19

Is it possible to read the RSA private key of format PKCS1 in JAVA without converting to PKCS8? if yes, sample code is appreciated.

-----BEGIN RSA PRIVATE KEY-----
 BASE64 ENCODED DATA
-----END RSA PRIVATE KEY-----
Parasitism answered 30/1, 2017 at 11:31 Comment(0)
S
32

Java does not come with out-of-the-box support for PKCS1 keys. You can however use Bouncycastle

PEMParser pemParser = new PEMParser(new FileReader(privateKeyFile));
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
Object object = pemParser.readObject();
KeyPair kp = converter.getKeyPair((PEMKeyPair) object);
PrivateKey privateKey = kp.getPrivate();
Sousaphone answered 31/1, 2017 at 8:42 Comment(9)
I got an error: java.security.NoSuchProviderException: no such provider: BCGilkey
I solved it by adding Security.addProvider(new BouncyCastleProvider());Gilkey
@Sousaphone .... I am trying this in android I cannot resolve PEMParser and JcaPEMKeyConverter .... I tried using https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on/1.55 ... but didn't work .... Which Jar I need to use or which grade do I need to use for this ?Perdu
You will need bcpkix and bcprov. Try with compile "org.bouncycastle:bcprov-jdk15on:$bouncycastleVersion" compile "org.bouncycastle:bcpkix-jdk15on:$bouncycastleVersion"Sousaphone
Here is a solution without Bouncycastle: https://mcmap.net/q/417647/-getting-rsa-private-key-from-pem-base64-encoded-private-key-filePrecipitancy
With most Java (at least Oracle and OpenJDK) technically you don't need to set or have configured the BC provider; JcaPEMKeyConverter works fine with the default provider(s). But you do need the bcprov jar because BC's asn1 classes are in it, and given you have the jar you might as well use the provider classes.Flatten
This code throws exception java.lang.ClassCastException: class org.bouncycastle.cert.X509CertificateHolder cannot be cast to class org.bouncycastle.openssl.PEMKeyPair (org.bouncycastle.cert.X509CertificateHolder and org.bouncycastle.openssl.PEMKeyPair are in unnamed module of loader 'app')Agosto
This method doesn't work. I used Java 20.Agosto
@Nambi: you tried to read a file that contains a certificate, not a PKCS1 (actually any OpenSSL-legacy) private key. This question and answer is only for reading a PKCS1/legacy private key, not a certificate, and not anything else that isn't a PKCS1/legacy private key. It does work for a correct file, in any Java version.Flatten
A
1

As hinted here, there is a solution without BouncyCastle.

import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

public class Pkcs1ToPkcs8 {
  private static final String PRIVATE_KEY = """
      -----BEGIN RSA PRIVATE KEY-----
      MIIEogIBAAKCAQEAkiAWsNL5sQqkDi04soEEOGiZQ7LlB91Z3jh1uHFByXXixHVC
      VwuahgAWxJ345G6AZVqgPxLnopPh513kXTPWRMggC6HszU+jQp3fkNo7OnzMhQcP
      ...
      -----END RSA PRIVATE KEY-----
      """;

  public static void main(String[] args) throws Exception {
    var pem = PRIVATE_KEY
        .replaceAll("-----.+KEY-----", "")
        .replaceAll("\\s+", "");

    var bytes = Base64.getDecoder().decode(pem);
    bytes = buildPkcs8KeyFromPkcs1Key(bytes);
    var keyFactory = KeyFactory.getInstance("RSA");
    var keySpec = new PKCS8EncodedKeySpec(bytes);
    var privateKey = (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
    System.out.println(privateKey);
  }

  private static byte[] buildPkcs8KeyFromPkcs1Key(byte[] innerKey) {
    var result = new byte[innerKey.length + 26];
    System.arraycopy(Base64.getDecoder().decode("MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKY="), 0, result, 0, 26);
    System.arraycopy(BigInteger.valueOf(result.length - 4).toByteArray(), 0, result, 2, 2);
    System.arraycopy(BigInteger.valueOf(innerKey.length).toByteArray(), 0, result, 24, 2);
    System.arraycopy(innerKey, 0, result, 26, innerKey.length);
    return result;
  }
}
Affectional answered 1/2 at 11:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.