【问题标题】:Why does SSL not work inside a build jar?为什么 SSL 在构建 jar 中不起作用?
【发布时间】:2020-09-28 23:01:48
【问题描述】:

我有一个小项目,我想在其中使用 TLS 1.3。

作为主要示例,我使用了这个响应:https://github.com/williamswhy/SSLSocket

这是我的服务器:

Server() {
    SSLServerSocket serverSocket = null;
    SSLSocket socket = null;

    try {
        SSLServerSocketFactory sslServerSocketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
        serverSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(3122);
        MariaDB mariaDB = new MariaDB();
        new Thread(mariaDB).start();
        while (true) {
            socket = (SSLSocket) serverSocket.accept();
            new Thread(new ClientConnection(socket,mariaDB)).start();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public static void main(String[] args) {
    //System.setProperty("javax.net.debug", "all");
    System.setProperty("javax.net.ssl.keyStore", "sslserverkeys");
    System.setProperty("javax.net.ssl.keyStorePassword", "password");
    new Server();
}

我的客户使用以下类:

try {
    System.setProperty("javax.net.ssl.trustStore", "sslclienttrust");
    System.setProperty("javax.net.ssl.trustStorePassword", "password");

    //DO NOT CHANGE THIS
    SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
    sslContext.init(null, null, new SecureRandom());
    SSLSocketFactory socketFactory = sslContext.getSocketFactory();
    socket = (SSLSocket) socketFactory.createSocket("localhost", 3122);
    System.out.println("Successfully initialized connection");

    try {
        this.out = new ObjectOutputStream(this.socket.getOutputStream());
        System.out.println("Successfully opened ObjectOutputStream");
    } catch (IOException var4) {
        var4.printStackTrace();
        try {
            this.out.close();
        } catch (IOException var3) {
            var3.printStackTrace();
        }
    }
} catch (NoSuchAlgorithmException | KeyManagementException | IOException e) {
    e.printStackTrace();
}

我在客户端的根文件夹中有一个 sslclienttrust 文件,在我的服务器的根文件夹中有一个 sslserverkeys。我正在使用 Maven 在 IntelliJ Ultimate 中进行编码,并且这种连接就像一种魅力。 但是当我构建一个 .jar(使用 maven-shade-plugin)时,我得到了一个异常。

服务器抛出以下异常:

javax.net.ssl.SSLException: readHandshakeRecord
    at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1392)
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:441)
    at java.base/sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:889)
    at java.base/sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:1251)
    at java.base/java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1893)
    at java.base/java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1802)
    at java.base/java.io.ObjectOutputStream.<init>(ObjectOutputStream.java:252)
    at ClientConnection.<init>(ClientConnection.java:21)
    at Server.<init>(Server.java:20)
    at Server.main(Server.java:36)
    Suppressed: java.net.SocketException: An established connection was aborted by the software in your host machine
        at java.base/sun.nio.ch.NioSocketImpl.implWrite(NioSocketImpl.java:420)
        at java.base/sun.nio.ch.NioSocketImpl.write(NioSocketImpl.java:440)
        at java.base/sun.nio.ch.NioSocketImpl$2.write(NioSocketImpl.java:826)
        at java.base/java.net.Socket$SocketOutputStream.write(Socket.java:1052)
        at java.base/sun.security.ssl.SSLSocketOutputRecord.encodeAlert(SSLSocketOutputRecord.java:82)
        at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:356)
        at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:268)
        at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:451)
        ... 8 more
Caused by: java.net.SocketException: An established connection was aborted by the software in your host machine
    at java.base/sun.nio.ch.NioSocketImpl.implWrite(NioSocketImpl.java:420)
    at java.base/sun.nio.ch.NioSocketImpl.write(NioSocketImpl.java:440)
    at java.base/sun.nio.ch.NioSocketImpl$2.write(NioSocketImpl.java:826)
    at java.base/java.net.Socket$SocketOutputStream.write(Socket.java:1052)
    at java.base/sun.security.ssl.SSLSocketOutputRecord.flush(SSLSocketOutputRecord.java:268)
    at java.base/sun.security.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:89)
    at java.base/sun.security.ssl.Finished$T13FinishedProducer.onProduceFinished(Finished.java:783)
    at java.base/sun.security.ssl.Finished$T13FinishedProducer.produce(Finished.java:671)
    at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:440)
    at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.goServerHello(ClientHello.java:1252)
    at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.consume(ClientHello.java:1188)
    at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.onClientHello(ClientHello.java:851)
    at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.consume(ClientHello.java:812)
    at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:445)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:423)
    at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:182)
    at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:171)
    at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1475)
    at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1381)
    ... 9 more

客户端抛出以下内容:

the last modified time is: Mon Sep 28 00:44:21 CEST 2020
javax.net.ssl|DEBUG|15|Thread-4|2020-09-29 24:55:10.430 CEST|TrustStoreManager.java:334|Reload the trust store
javax.net.ssl|DEBUG|15|Thread-4|2020-09-29 24:55:10.468 CEST|TrustManagerFactoryImpl.java:70|SunX509: skip default keystore (
"throwable" : {
  java.io.IOException: Keystore was tampered with, or password was incorrect
        at java.base/sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:794)
        at java.base/sun.security.util.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:241)
        at java.base/java.security.KeyStore.load(KeyStore.java:1472)
        at java.base/sun.security.ssl.TrustStoreManager$TrustAnchorManager.loadKeyStore(TrustStoreManager.java:390)
        at java.base/sun.security.ssl.TrustStoreManager$TrustAnchorManager.getTrustedCerts(TrustStoreManager.java:336)
        at java.base/sun.security.ssl.TrustStoreManager.getTrustedCerts(TrustStoreManager.java:56)
        at java.base/sun.security.ssl.TrustManagerFactoryImpl.engineInit(TrustManagerFactoryImpl.java:49)
        at java.base/javax.net.ssl.TrustManagerFactory.init(TrustManagerFactory.java:281)
        at java.base/sun.security.ssl.SSLContextImpl.engineInit(SSLContextImpl.java:94)
        at java.base/javax.net.ssl.SSLContext.init(SSLContext.java:313)
        at connection.ServerConnection.connectToServer(ServerConnection.java:204)
        at connection.ServerConnection.run(ServerConnection.java:42)
        at java.base/java.lang.Thread.run(Thread.java:832)
  Caused by: java.security.UnrecoverableKeyException: Password verification failed
        at java.base/sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:792)
        ... 12 more}

起初我认为这与错误的路径有关,所以我尝试了sof上提到的几种方法。但是密码不正确或密钥库被篡改的错误让我感到困惑。密码不能错,因为它在 IDE 中工作。

为什么 SSL 在我的 IDE 中有效,但在 .jar 中无效 我看到一些关于 SSL 的帖子根本不起作用,但不是这样的。

【问题讨论】:

    标签: java ssl javafx jar


    【解决方案1】:

    系统属性javax.net.ssl.trustStore 要求您传入一个文件,并且该文件必须.. 存在。

    jar 中的条目类似于文件,但不是文件,因此您不能使用打包在 jar 文件中的信任库文件。这首先会爆炸罐子的要点,这就是为什么这不是“工作”的原因-您是从工作目录不正确的地方运行罐子的。一般来说,将相对条目(不以/C:\ 或诸如此类的东西开头的东西)传递给javax.net.ssl.trustStore 在最终用户手中永远不会起作用,并且如果您尝试,则需要运营团队仔细编写脚本将其部署在您自己的服务器上。

    从任何随机源加载信任库,例如位于我的类文件所在位置的“资源”文件;如果需要,请查看 jar 文件,检查 this tutorial

    【讨论】:

    • 感谢您的回答。除了更简单的方法来实现我想要实现的目标之外,还有更常见的方法吗?
    • 我链接到它了,不是吗?通常,服务器有一些标准证书,例如来自lets-encrypt(任何网络浏览器都会理解的东西),然后你根本不需要在java客户端上自定义信任库。
    • 是的,效果很好。我的问题是,如果这是对 TLS1.3 进行身份验证的常用方法,还是使用其他方法,也许是使用 Web 服务器?我在设置方面遇到了很多困难,但没有找到太多关于它的文档。
    猜你喜欢
    • 2014-01-15
    • 2015-08-22
    • 1970-01-01
    • 1970-01-01
    • 2016-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-21
    相关资源
    最近更新 更多