9

我创建了一个带有公共和私有 RSA 密钥的 JKS 文件。当我使用外部路径(如 c:/file.jks)加载此文件时,程序的执行就像一个魅力。但是,如果我尝试从类路径加载相同的文件,我得到了这个异常:

java.io.IOException: Invalid keystore format

这是用于加载 jks 的代码:

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

唯一的区别是我在外部加载时使用带有完整路径的 FileInputStream。我做错了什么?

4

2 回答 2

6

一般来说,您的解决方案应该可以暂时起作用。

那些规定是什么?确保您的资源文件夹在您的类路径中。如果您不确定,请将其添加到执行程序时-cp传递给的标志中java,或者如果您使用的是 Eclipse 或其他 IDE,请确保它被列为该项目的类路径的成员。

接下来,查看与您的问题相关的这个 stackoverflow。虽然您使用类的 getResourceAsStream() 方法的方式是有效的(包括/文件名开头的 导致类资源加载器遵循 ClassLoader 的方法),但直接使用 ClassLoader 可能不会那么混乱。另一个很好的例子可以在这里找到

因此,首先,检查您的资源文件夹是否明确包含在类路径中。其次,更喜欢以下构造来查找资源:

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

请注意文件名中的缺失/。这是因为 ClassLoader 将自动从“项目根目录”开始搜索,而斜杠可能只会导致问题(例如,如果您部署到 JBoss 或 Tomcat,则可能会被类加载器解释为绝对文件系统路径的相对路径)。

我希望这有帮助。如果没有,请评论我有关您项目的更多详细信息,我会相应地更改我的答案。

于 2014-03-05T17:43:37.893 回答
4

我怀疑这两个密钥库实际上并不相同,并且类路径上的密钥库在某种程度上已损坏。

尝试比较两个密钥库。只需将文件读入一个字节数组,如下所示:

    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();
    }

然后像这样比较它们:

    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 ...
    }
于 2014-03-07T22:55:51.603 回答