【问题标题】:SSL Java java.io.IOException: Invalid keystore formatSSL Java java.io.IOException:无效的密钥库格式
【发布时间】:2014-11-22 03:58:16
【问题描述】:

我正在使用 SSLServerSocket 和 java.ssl 包中的其他类在 java 中测试 SSL。当我运行以下代码时,我得到异常 java.io.IOException: Invalid keystore format。我的代码:

package testing;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.security.KeyStore;

import javax.net.ServerSocketFactory;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.TrustManager;

public class SSLServerTest {
    public static void main(String[] args) {
        try {
            int port = 3000;
            SSLContext sc = SSLContext.getInstance("TLSv1.2");
            KeyStore ks = KeyStore.getInstance("JKS");
            InputStream ksIs = new FileInputStream("key.txt");
            try {
                ks.load(ksIs, "Bennett556".toCharArray());
            } finally {
                if (ksIs != null) {
                    ksIs.close();
                }
            }
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(ks, "Bennett556".toCharArray());
            sc.init(kmf.getKeyManagers(), new TrustManager[] {}, null);
            ServerSocketFactory ssocketFactory = sc.getServerSocketFactory();
            SSLServerSocket ssocket = (SSLServerSocket) ssocketFactory
                    .createServerSocket(port);
            ssocket.setEnabledProtocols(new String[] { "SSLv3" });
            Socket socket = ssocket.accept();
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    socket.getInputStream()));
            PrintWriter out = new PrintWriter(socket.getOutputStream());
            out.println("Hello, Securly!");
            out.close();
            in.close();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

文件密钥.txt: 1268312345812304612348712634283427346 我猜我应该在 key.txt 文件中放些别的东西,但我不知道该放什么。可能是一个海化的物体。

编辑:客户代码:

package testing;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;

import javax.net.SocketFactory;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;

public class SSLClientTest {
    public static void main(String[] args) {

        int port = 3000;
        String host = "localhost";

        try {
            SSLContext sc = SSLContext.getInstance("TLSv1.2");
            KeyStore ks = KeyStore.getInstance("JKS");
            InputStream ksIs = new FileInputStream("key.txt");
            try {
                ks.load(ksIs, "Bennett556".toCharArray());
            } finally {
                if (ksIs != null) {
                    ksIs.close();
                }
            }
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(ks, "Bennett556".toCharArray());
            sc.init(kmf.getKeyManagers(), new TrustManager[] {}, null);
            SocketFactory factory = sc.getSocketFactory();
            SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
            socket.startHandshake();
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    socket.getInputStream()));
            String str = "";
            while ((str = in.readLine()) != null)
                System.out.println(str);
            in.close();
            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

【问题讨论】:

  • KeyStore 文件不是文本文件。
  • 实际上密钥不是密钥存储;文本文件不是密钥库;并且密钥不能存储在文本文件中。

标签: java security ssl


【解决方案1】:

您的文件无效。您必须导入 JKS 密钥库文件而不是 txt 文件。您必须使用keytool 创建您的密钥库文件,然后导入此文件。

【讨论】:

  • 这取决于存储密钥的文件类型。可以在here 找到示例。如果您有任何疑问/问题,请随时提出。
  • 我假设您没有将服务器的证书添加到客户端。发送客户端连接代码。
  • 我更改了客户端(和服务器)代码,现在客户端出现以下异常:javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No X509TrustManager implementation availableCaused by: java.security.cert.CertificateException: No X509TrustManager implementation available
  • @JavaIsCool 这是一个新问题,但是您在初始化SSLContext, 时指定了一个空数组TrustManagers,不是吗,所以当然没有TrustManagers 可用。跨度>
  • @VGe0rge 如何使用 keytool 命令制作证书链?
【解决方案2】:

load keystore 使用以下代码时遇到了同样的问题:

KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
Resource resource = new ClassPathResource(file);
trustStore.load(resource.getInputStream(), password.toCharArray());

原来是 JDK 问题,它不适用于 jre1.8.0_25。当我将 JDK 版本升级到最新的jre1.8.0_121 时,它可以工作。

【讨论】:

  • 没有这个问题。你改变了别的东西。当我看到“低版本 JDK”时,我以为你的意思是 1.2.2。 1.8.0_66 几乎不是“低”。
  • 不是1.8.0_66,我弄错了,是我的JDK版本。在我同事的jre1.8.0_25上不行,相对低于66或者最新的,重新安装JDK就可以了,你可以试试。
  • 我遇到了同样的问题,JDK 1.8.0_45 失败,JDK 1.8.0_131 工作正常
  • 是的,我也一样。当使用 ibmjava 的 docker 镜像与 openjdk 镜像时,它也会出现。不知道具体是哪个版本导致的,但是很有可能是JDK版本导致的。
【解决方案3】:

我看到了这个异常:

密钥库格式无效

在 CentOS 6.6 64 位 Linux 上使用 JRE-1.8.0_40 运行 java 应用程序时。

在使用 JRE-1.8.0_172 时,异常消失了。

【讨论】:

    【解决方案4】:

    我遇到了完全相同的问题。实际上,keystore 文件是无效的,并且与 JDK//JRE 版本无关。我的问题是由 Maven 引起的。我在我的 pom 文件中使用了以下选项:

    <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
    

    过滤中的“真”值与密钥文件混淆。因此,当 Spring 运行时,在我的类路径中可用的密钥文件与我在目录“src/main/resources”下的密钥文件不完全相同,这导致了 Invalid Keystore Format 异常。当我使用 keytool 进行测试时,我使用的是“资源”文件夹下的那个,所以这会误导真正的问题。

    解决问题:在您的 pom.xml 文件中,将“filtering”的值更改为“false”。 解决此问题的另一种方法是在 application.properties 文件中明确指定密钥库的位置。所以而不是:

    server.ssl.key-store: classpath:keystore.jks
    

    我用过

    server.ssl.key-store: keystore/keystore.jks
    

    【讨论】:

    • 谢谢!这不是我的确切问题,但它帮助我解决了我的问题。我一遍又一遍地(几天)用我的IDE“热”构建,并且似乎随机地开始发生这个问题。您的回答让我想到了做一个合法的 maven 构建,这允许下一次部署工作:)。
    • 非常感谢!我花了一整天的时间来解决这个问题,试图让 Kafka 在我的 Spring 应用程序中工作。你是救生员。
    【解决方案5】:

    您是如何生成 JKS 文件的?我尝试了所有建议的解决方案,但没有一个对我有用。尝试读取(在我的代码中)使用 OpenJDK Zulu 11 的 keytool 生成的 JKS 文件时,我遇到了同样的错误。

    我通过使用“KeyStore Explorer”工具生成 JKS 文件来解决此问题,我相信该工具在内部使用了 oracle JDK。使用该工具,我基本上创建了一个 JKS 文件并将我的受信任证书添加到其中。

    我希望这会有所帮助。

    【讨论】:

    • 你终于使用 KeyStore Explorer 了吗?
    【解决方案6】:

    就我而言,我使用了不同版本的 keytool 和 java,一旦我切换到相同的 jdk,它们就得到了修复。

    【讨论】:

      猜你喜欢
      • 2023-03-20
      • 2010-11-06
      • 1970-01-01
      • 1970-01-01
      • 2022-12-14
      • 1970-01-01
      • 1970-01-01
      • 2015-04-06
      • 1970-01-01
      相关资源
      最近更新 更多