Search code examples
javafilejsse

FileNotFound with .jar and JSSE


I am using JSSE and have the following code:

private static void setupServerKeystore() throws GeneralSecurityException, IOException {
        mServerKeyStore = KeyStore.getInstance( "JKS" );
        mServerKeyStore.load(new FileInputStream(iComputer.class.getClassLoader().getResource("res/server.public").getPath()), 
                            "pswd".toCharArray());
}


private static void setupClientKeyStore() throws GeneralSecurityException, IOException {
            mClientKeyStore = KeyStore.getInstance( "JKS" );
            mClientKeyStore.load(new FileInputStream(iComputer.class.getClassLoader().getResource("res/client.private").getPath()),
                                   mPassphrase.toCharArray());
}

Here is my folder structure:

- iComputer
   - src
        - com
            - ...
        - res
            - server.public
            - client.private

Both of the URLs work within Eclipse and the client executes the handshake successfully. However, when I export this as a .jar file, I get a FileNotFoundException:

> java.io.FileNotFoundException:
> file:/Users/Zack/Downloads/iComputer.jar!/res/server.public (No
> such file or directory)

I have been trying to figure this out for hours with no luck. Any help would be much appreciated.


Solution

  • Alright, so here's what I did to fix the issue (thanks to peeskillet for coming up with the solution). I considered the option of using getResourceAsStream(). This worked fine in Eclipse, but the problem was that I was getting an error when exporting and running the jar file, "error error: sun.security.validator.ValidatorException: No trusted certificate found". It seems as though I was giving it the wrong path.

    JSSE's KeyStore.load() method will accept any type of InputStream as shown in the documentation. It doesn't necessarily have to be a FileInputStream.

    So, here is my file structure:

    - iComputer
       - src
            - com
                - ...
            - res
                - server.public
                - client.private
    

    Based off of this file structure, the path that works correctly is "res/server.public" for both Eclipse and the JAR file. So, here are my revisions to the code from my OP:

    private static void setupServerKeystore() throws GeneralSecurityException, IOException {
            mServerKeyStore = KeyStore.getInstance( "JKS" );
            mServerKeyStore.load(iComputer.class.getClassLoader().getResourceAsStream("res/server.public"), 
                                "pswd".toCharArray());
        }
    
    private static void setupClientKeyStore() throws GeneralSecurityException, IOException {
            mClientKeyStore = KeyStore.getInstance( "JKS" );
            mClientKeyStore.load(iComputer.class.getClassLoader().getResourceAsStream("res/client.private"),
                                   mPassphrase.toCharArray());
    }
    

    Do yourself a favor, use this as a reference point for where you are putting your key file(s). This will save you countless hours trying to figure out why you are getting a NullPointerException or FileNotFoundException.