为了账号安全,请及时绑定邮箱和手机立即绑定

KeyStore.load() 因“无效的密钥库格式”而失败

KeyStore.load() 因“无效的密钥库格式”而失败

慕码人2483693 2023-06-08 19:20:46
在执行 keystore.load() 方法时,下面的代码每次都会出现“无效的密钥库格式”的 IOException。该文件已成功从 .jar 文件加载。在 Windows 10 专业版上使用 Java 1.8。Maven 用于编译和组装 jar 文件,然后一起 war 并作为 war 文件部署到 JBOSS 服务器。我试过 .getInstance 和 getDefault() 也有同样的错误。InputStream stream;stream = Thread.currentThread().getContextClassLoader()    .getResourceAsStream("cacerts.jks");if (stream == null) {    stream = CustomTrustManager.class.getClassLoader()        .getResourceAsStream("cacerts.jks");}if(stream == null) {    Log.error("Unable to load cacerts.jks. This is needed to make HTTPS connections to internal servers.");    throw new NotFoundException();}KeyStore myTrustStore = KeyStore.getInstance("JKS");myTrustStore.load(stream, "xxxxx".toCharArray());“cacerts.jks”文件是使用以下命令从自签名服务器证书“server1.crt”文件生成的:keytool -v -import -alias devserver -file server1.crt -keystore cacerts.jks这成功完成并命令:keytool -list -keystore cacerts.jksKeystore type: JKSKeystore provider: SUNYour keystore contains 1 entrydevserver, Aug 15, 2019, trustedCertEntry,Certificate fingerprint (SHA1): F6:7F:C9:95:0E:B8:59:07:24:23:67:93:43:B2:C9:AA:CD:5B:AF:68显示密钥库文件没有问题。我浏览了许多 StackOverflow 文章,但没有一篇指出问题的解决方案。在调试模式下,资源加载后 InputStream 具有以下格式。我假设从 .jar 文件加载 ZipFile 类型是正常的。感谢任何有关如何成功加载密钥库文件的见解。谢谢
查看完整描述

4 回答

?
偶然的你

TA贡献1841条经验 获得超3个赞

二进制 JKS 文件可能被 Maven 资源插件过滤,导致文件损坏,这是一个很常见的问题:

Maven 在构建期间复制到 Java 资源目录时损坏 WAV 文件

Maven 在构建 jar 时损坏 source/main/resources 中的二进制文件

移动到资源文件夹时生成的证书停止工作

二进制文件基本上被视为文本文件,因此 jar 中的文件以 UTF-8 字符 ( 0xEFBFBDEFBFBD) 而不是 JKS 的幻数 ( 0xFEEDFEED) 开头。

资源插件文档包含一个明确的警告:

不要过滤带有图像等二进制内容的文件!这很可能会导致损坏的输出。

可能的解决方案是:

  • 将资源文件夹拆分为一个已过滤的文件夹和一个未过滤的文件夹

  • 全局禁用对扩展名为 .jks 的文件的过滤


查看完整回答
反对 回复 2023-06-08
?
jeck猫

TA贡献1909条经验 获得超7个赞

确保避免过滤您的密钥库文件 jks


喜欢


<resources>

            <resource>

                <directory>src/main/resources</directory>

                <filtering>true</filtering>

                <excludes>

                    <exclude>**/*.jks</exclude>

                </excludes>

            </resource>

            <resource>

                <directory>src/main/resources</directory>

                <filtering>false</filtering>

                <includes>

                    <include>**/*.jks</include>

                </includes>

            </resource>

        </resources>


查看完整回答
反对 回复 2023-06-08
?
波斯汪

TA贡献1811条经验 获得超4个赞

二进制文件基本上被视为文本文件,因此 jar 中的文件以 UTF-8 字符 (0xEFBFBDEFBFBD) 开头,而不是 JKS 的幻数 (0xFEEDFEED)。

我在 pom.xml 文件的属性部分添加了这两行

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

它完成了工作


查看完整回答
反对 回复 2023-06-08
?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

免责声明:这还不是一个完整的答案,但我需要一个与 OP 讨论的工具。如果这没有导致解决方案,我将再次删除答案。


我在这样的 POJO 中复制了你的情况:


$ openssl req -new -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out MyCertificate.crt -keyout MyKey.key

(answer all questions with RETURN = accept defaults)


$ keytool -v -import -alias devserver -file MyCertificate.crt -keystore src/main/resources/cacerts.jks -storetype JKS

Enter keystore password:  testtest

Re-enter new password: testtest

(...)

Trust this certificate? [no]:  yes

Certificate was added to keystore

[Storing src/main/resources/cacerts.jks]


$ keytool -list -keystore src/main/resources/cacerts.jks

Enter keystore password:  testtest

Keystore type: JKS

Keystore provider: SUN


Your keystore contains 1 entry


devserver, 24.08.2019, trustedCertEntry,

Certificate fingerprint (SHA-256): A2:E1:49:FB:9C:26:6B:8A:21:45:A4:AA:F4:86:A0:A7:82:B8:08:BE:75:A6:BF:E8:F5:13:9E:31:23:8E:B0:71

现在在 Maven JAR 模块中创建一个类似于 OP 所示代码的类:


package de.scrum_master.stackoverflow;


import java.io.IOException;

import java.io.InputStream;

import java.security.KeyStore;

import java.security.KeyStoreException;

import java.security.NoSuchAlgorithmException;

import java.security.cert.CertificateException;


public class CustomTrustManager {

  public static void main(String[] args) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {

    InputStream stream;

    stream = Thread.currentThread().getContextClassLoader().getResourceAsStream("cacerts.jks");

    System.out.println(stream);

    if (stream == null) {

      stream = CustomTrustManager.class.getClassLoader().getResourceAsStream("cacerts.jks");

    }

    if(stream == null) {

      System.out.println("Unable to load cacerts.jks. This is needed to make HTTPS connections to internal servers.");

      throw new RuntimeException("Keystore not found");

    }


    KeyStore myTrustStore = KeyStore.getInstance("JKS");

    myTrustStore.load(stream, "testtest".toCharArray());

    System.out.println("Keystore loaded");

  }

}

现在构建项目并mvn clean package运行它:


$ java -cp target/my-sample-1.0-SNAPSHOT.jar de.scrum_master.stackoverflow.CustomTrustManager

sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream@3d4eac69

Keystore loaded

所以基本上你的方法应该有效。如果没有,它可以连接到

  • 类加载(但我不这么认为,因为密钥存储似乎很好),

  • 我在你的调用堆栈中看到的 AspectJ(或者更确切地说只是 Spring AOP)的东西(也不太可能),

  • 您自己的自定义信任管理器或您的“riskmeter”类所做的任何事情。

请检查你在你的应用程序中使用的完全相同的密钥库是否像我的例子一样从一个简单的 JAR 中工作,没有容器或其他花哨的东西。如果是这样,您就知道问题不是您的密钥库。

那么请在这里提供一些反馈。


查看完整回答
反对 回复 2023-06-08
  • 4 回答
  • 0 关注
  • 468 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信