Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't load a jks file from classpath

I've created a JKS file with public and private RSA keys. When I load this file using external path (like c:/file.jks), the program executes like a charm. However, if I try load this same file from classpath, I got this exception:

java.io.IOException: Invalid keystore format

This is the code used to load the jks:

 KeyStore keyStore = KeyStore.getInstance("JKS");
 InputStream stream=this.getClass().getResourceAsStream("/lutum.jks") ;
 keyStore.load(stream,passe);

the only difference is that I use FileInputStream with full path when loading externally. What I'm doing wrong?

like image 286
brevleq Avatar asked Feb 28 '14 19:02

brevleq


People also ask

How do I open a JKS file?

Provided you know a JKS file's password, you can open it and view its contents using KeyStore Explorer, a multiplatform app that allows users to create, import, export, and save various KeyStore files. Note that you must have the Java Runtime Environment installed in order to use KeyStore Explorer.

Is keystore and JKS file same?

The Java KeyStore (JKS) system is provided as part of your Java installation. Private keys and certificates for your server are stored in a keystore file. The JKS system supports both PKCS #12 . p12 files as well as legacy keystore .

What is the difference between JKS and PKCS12?

The biggest difference between JKS and PKCS12 is that JKS is a format specific to Java, while PKCS12 is a standardized and language-neutral way of storing encrypted private keys and certificates.

Is JKS file is private key?

Java Key Store (JKS) Is a repository of security certificates — either authorisation certificates or public key certificates — plus corresponding private keys, used for instance in SSL encryption.


2 Answers

In general your solution should work, provisionally.

What are those provisions? Make sure that your resource folder is in your classpath. If you aren't sure, add it to the -cp flag passed to java when executing your program, or if you are using Eclipse or some other IDE, make sure it is listed as a member of the classpath for that project.

Next, check out this stackoverflow that relates to your question. While the way you are using the class's getResourceAsStream() method is valid (including the / at the start of the filename causes the class resource loader to defer to the ClassLoader's method) it is perhaps less confusing to use the ClassLoader directly. Another good example is found here.

So, first, check that your resources folder is explicitly part of the classpath. Second, prefer the following construction for finding the resource:

InputStream stream= this.class.getClassLoader().getResourceAsStream("lutum.jks");

Note the missing / from the filename. This is because the ClassLoader will automatically start searching at "project root", and the slash will likely just cause issues (if you deploy to JBoss or Tomcat, for instance, that will probably get interpreted by the classloader as an absolute file system path instead of a relative path).

I hope this helps. If not, comment me with more details on your project and I'll alter my answer accordingly.

like image 75
ProgrammerDan Avatar answered Sep 21 '22 20:09

ProgrammerDan


I suspect that the two keystores are in fact not the same, and that the keystore on the classpath are somehow corrupt.

Try comparing the two keystores. Just read the files into a byte array with something like this:

    public static byte[] streamToByteArray(InputStream is) throws IOException {
        ByteArrayOutputStream tmp = new ByteArrayOutputStream();
        int b = is.read();
        while (b > -1) {
            tmp.write(b);
            b = is.read();
        }
        tmp.flush();
        return tmp.toByteArray();
    }

And then compare them like this:

    InputStream cpStream = this.getClass().getResourceAsStream("/lutum.jks");
    InputStream fileStream = new FileInputStream("c:/file.jks");

    byte[] cpBytes = streamToByteArray(cpStream); 
    byte[] fileBytes = streamToByteArray(fileStream);

    if (Arrays.equals(cpBytes, fileBytes)) {
        System.out.println("They are the same.");
    } else {
        System.out.println("They are NOT the same.");
        // print the file content ...
    }
like image 33
Ebbe M. Pedersen Avatar answered Sep 24 '22 20:09

Ebbe M. Pedersen