微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么SSL无法在构建jar中工作?

如何解决为什么SSL无法在构建jar中工作?

我有一个小项目,我想在其中使用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的线程根本不起作用,但不是这样。

解决方法

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

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

要从任何随机源加载信任库,例如与类文件所在位置相同的“资源”文件;在jar文件中查找(如果需要),请选中this tutorial

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。