How to generate PublicKey object from file in Java

I have a file containing the RSA public key (generated using ssh-keygen ). I would like to read the file and generate a PublicKey object.

Before that, I converted the file, because reading the source files seems impossible:

 # http://unix.stackexchange.com/questions/220354/how-to-convert-public-key-from-pem-to-der-format/220356#220356 ssh-keygen -f ~/.ssh/id_rsa.pub -e -m PEM > ~/.ssh/id_rsa.pub.pem openssl rsa -RSAPublicKey_in -in ~/.ssh/id_rsa.pub.pem -inform PEM -outform DER -out ~/.ssh/id_rsa.pub.der -RSAPublicKey_out 

From Java - Encrypting a string with an existing public key file I defined the readFileBytes function:

 public static byte[] readFileBytes(String filename) throws IOException { Path path = Paths.get(System.getProperty("user.home") + filename); return Files.readAllBytes(path); } 

Now I would like to read the file and create a PublicKey object, but I could not find a way to do this; java.security.spec.RSAPublicKeySpec does not provide a substitution constructor and java.security.spec.X509EncodedKeySpec throws an error java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: algid parse error, not a sequence :

 //RSAPublicKeySpec publicSpec = new RSAPublicKeySpec(readFileBytes("/.ssh/id_rsa.pub.der")); // No fitting construktor X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(readFileBytes("/.ssh/id_rsa.pub.der")); // Gives: "algid parse error, not a sequence" 
+6
source share
2 answers

I had a project in which (RSA) encryption was needed, this is how I restored publicKey given the publicKey byte array, which was just read from a file.

 public PublicKey reconstruct_public_key(String algorithm, byte[] pub_key) { PublicKey public_key = null; try { KeyFactory kf = KeyFactory.getInstance(algorithm); EncodedKeySpec pub_key_spec = new X509EncodedKeySpec(pub_key); public_key = kf.generatePublic(pub_key_spec); } catch(NoSuchAlgorithmException e) { System.out.println("Could not reconstruct the public key, the given algorithm oculd not be found."); } catch(InvalidKeySpecException e) { System.out.println("Could not reconstruct the public key"); } return public_key; } 

Then you can call a procedure similar to this call, reconstruct_public_key("RSA", readFileBytes("path/to/your/publicKey/file"));

EDIT: I tried to do it myself (write the public key to a file, read this file and restore the key). It works:

 public static void main(String args[]) { String path = "./pub_key_test.txt"; // Generate a keypair to write to file KeyPair kp = generate_key(); PublicKey pub_key = kp.getPublic(); File file = new File(path); try { // Write to file file.createNewFile(); FileOutputStream out = new FileOutputStream(path); out.write(pub_key.getEncoded()); // Write public key to the file out.close(); // Read from file FileInputStream in = new FileInputStream(path); byte[] pub_key_arr = new byte[in.available()]; in.read(pub_key_arr, 0, in.available()); in.close(); // Reconstruct public key PublicKey reconstructed_pub_key = reconstruct_public_key("RSA", pub_key_arr); } catch(IOException e) { System.out.println("Could not open the file : " + e.getStackTrace()); } } 

And this is the generate_key procedure:

 public KeyPair generate_key() { while(true) { // Else the compiler will complain that this procedure does not always return a "KeyPair" try { final KeyPairGenerator key_generator = KeyPairGenerator.getInstance("RSA"); key_generator.initialize(2048); // Keys of 2048 bits (minimum key length for RSA keys) are safe enough (according to the slides 128bit keys > 16 years to brute force it) final KeyPair keys = key_generator.generateKeyPair(); return keys; } catch(NoSuchAlgorithmException e) { System.out.println("The given encryption algorithm (RSA) does not exist. -- generate_key() - Cryptography."); } } } 

If you check this, you will see that publicKey been successfully restored.

EDIT: I tried to do this myself using the ssh-keygen tool. This is what I did:

  • First I created the RSA private key ( .PEM format)
  • Output part of the public key in .DER format .DER that it can be used by Java.

Here's how I made the conversion, which is slightly different from yours:

 openssl rsa -in private_key_file.pem -pubout -outform DER -out java_readable_file.der 

And I read the file as here , which is not much different from yours. I tested this and Java successfully restored the public key.

+5
source

Create RSA Secret Key

openssl genrsa -out rsaprivkey.pem 1024

Generates a public key in DER format.

openssl rsa -in rsaprivkey.pem -pubout -outform DER -out rsapubkey.der

We use this code that extracts the RSA or DSA public key from an X.509 certificate.

 import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; /** * This class is capable of extracting a public key from a X.509 certficate * and returning the PublicKey representation from a referenced byte array. * */ public class ExtractPublicKey { // Certificate Filename (Including Path Info) private static final String certFilename = "cacert.pem"; // Public Key Filename (Including Path Info) private static final String pubKeyFilename = "rsapublic.key"; public static PublicKey generatePublicKey(byte[] encodedKey) throws NoSuchAlgorithmException, InvalidKeySpecException { X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(encodedKey); boolean isSupportedKey = false; KeyFactory factory; PublicKey retKey = null; //first try the DSA alg try { factory = KeyFactory.getInstance("DSA"); retKey = factory.generatePublic(pubSpec); isSupportedKey = true; } catch (InvalidKeySpecException e) { System.out.println("Could not create DSA Public Key: " + e.toString()); } //if DSA didnt work, then try RSA if (!isSupportedKey) { try { factory = KeyFactory.getInstance("RSA"); retKey = factory.generatePublic(pubSpec); isSupportedKey = true; } catch (InvalidKeySpecException e) { System.out.println("Could not create RSA Public Key: " + e.toString()); } } // if not DSA or RSA if (!isSupportedKey) { throw new InvalidKeySpecException("Unsupported key spec: Not RSA or DSA"); } return retKey; } } 
+4
source

All Articles