Search code examples
javaencryptioncryptographyrsax509

InvalidKeySpecException when trying to Load RSA public key from file- Java


I am creating public and private RSA keys and saving them to separate files using the code below. The file are successfully created without any error:

public static void main(String[] args) throws Exception {
    String path = "D:\\OneDrive\\Desktop\\Keys\\";

    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
    kpg.initialize(2048);
    KeyPair kp = kpg.genKeyPair();

    ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream(path + args[0] + ".pub"));
    System.out.println(kp.getPublic().getFormat());
    objOut.writeObject(kp.getPublic());
    objOut.close();

    objOut = new ObjectOutputStream(new FileOutputStream(path + args[0] + ".prv"));
    System.out.println(kp.getPrivate().getFormat());
    objOut.writeObject(kp.getPrivate());
    objOut.close();
}    

After creating the files I want to read the public key from the file and encrypt some string using that key. To get the key from the file I am using the code below:

private static PublicKey GetRecipientPublicKey(String filename)
        throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {

    Path path = Paths.get(basePath + filename + ".pub");
    byte[] arrByte = Files.readAllBytes(path);

    X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(arrByte);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PublicKey publicKey = keyFactory.generatePublic(publicSpec);
    return publicKey;
}    

As soon as the code PublicKey publicKey = keyFactory.generatePublic(publicSpec); in above code is executed an exception is thrown as follow:

Exception in thread "main" java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: DerInputStream.getLength(): lengthTag=109, too big.
    at java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:241)
    at java.base/java.security.KeyFactory.generatePublic(KeyFactory.java:351)
    at Client.GetRecipientPublicKey(Client.java:89)
    at Client.EncryptMessage(Client.java:66)
    at Client.main(Client.java:57)
    Caused by: java.security.InvalidKeyException: IOException: 
    DerInputStream.getLength(): lengthTag=109, too big.
    at java.base/sun.security.x509.X509Key.decode(X509Key.java:397)
    at java.base/sun.security.x509.X509Key.decode(X509Key.java:402)
    at java.base/sun.security.rsa.RSAPublicKeyImpl.<init>(RSAPublicKeyImpl.java:151)
    at java.base/sun.security.rsa.RSAPublicKeyImpl.newKey(RSAPublicKeyImpl.java:78)
    at java.base/sun.security.rsa.RSAKeyFactory.generatePublic(RSAKeyFactory.java:327)
    at java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:237)
    ... 4 more

Solution

  • Right now you are serializing the Key object, not the encoded form. If you read the documentation for the Key interface in the Java SE documentation; you will find the following:

    An Encoded Form

    This is an external encoded form for the key used when a standard representation of the key is needed outside the Java Virtual Machine, as when transmitting the key to some other party. The key is encoded according to a standard format (such as X.509 SubjectPublicKeyInfo or PKCS#8), and is returned using the getEncoded method.