Java HTTPS服务器"不支持的协议错误"在Chrome中

时间:2017-07-17 03:07:14

标签: java ssl https server tls1.2

我在Java中使用自定义HTTP / 1.1服务器实现。它在HTTP模式下工作正常,但我也想支持HTTPS。我还没有为服务器生成证书,但它至少应该尝试连接。我将协议和密码套件设置为与google.com(TLS 1.2,ECDHE_RSA,AES_128_GCM)相同的设置,因此我知道Chrome支持它们。

但是当我尝试在Chrome中连接到https://localhost时,它会提供ERR_SSL_VERSION_OR_CIPHER_MISMATCH(localhost使用不受支持的协议)错误。在Java方面,我得到了#34;没有共同的密码套件"错误。

Java代码:

public class Server {
    private final String dir;
    private final ServerSocket server;
    private final SSLServerSocket sslServer;

    public static String jarDir() {
        String uri = ClassLoader.getSystemClassLoader().getResource(".").getPath();
        try { return new File(URLDecoder.decode(uri,"UTF-8")).getPath()+File.separator; }
        catch (Exception e) { return null; }
    }

    private static SSLContext createSSLContext(String cert, char[] pass) throws Exception {
        /*//Load KeyStore in JKS format:
        KeyStore keyStore = KeyStore.getInstance("jks");
        keyStore.load(new FileInputStream(cert), pass);

        //Create key manager:
        KeyManagerFactory kmFactory = KeyManagerFactory.getInstance("SunX509");
        kmFactory.init(keyStore, pass); KeyManager[] km = kmFactory.getKeyManagers();

        //Create trust manager:
        TrustManagerFactory tmFactory = TrustManagerFactory.getInstance("SunX509");
        tmFactory.init(keyStore); TrustManager[] tm = tmFactory.getTrustManagers();

        //Create SSLContext with protocol:
        SSLContext ctx = SSLContext.getInstance("TLSv1.2");
        ctx.init(km, tm, null); return ctx;*/

        SSLContext ctx = SSLContext.getInstance("TLSv1.2");
        ctx.init(null, null, null); return ctx;
    }

    Server(String localPath, int port) throws Exception {
        this(localPath, port, 0);
    }

    //Server is being initialized with:
    //new Server("root", 80, 443);

    Server(String localPath, int port, int httpsPort) throws Exception {
        dir = localPath; File fdir = new File(jarDir(), dir);
        if(!fdir.isDirectory()) throw new Exception("No such directory '"+fdir.getAbsolutePath()+"'!");

        //Init Server:
        server = new ServerSocket(port);
        if(httpsPort > 0) {
            SSLContext ctx = createSSLContext("cert.jks", "pass".toCharArray());
            sslServer = (SSLServerSocket)ctx.getServerSocketFactory().createServerSocket(httpsPort);

            //TLS_DH_anon_WITH_AES_128_GCM_SHA256
            sslServer.setEnabledCipherSuites(new String[]{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"});
            sslServer.setEnabledProtocols(new String[]{"TLSv1.2"});

            //Also does not work, same error:
            //sslServer.setEnabledCipherSuites(sslServer.getSupportedCipherSuites());
            //sslServer.setEnabledProtocols(sslServer.getSupportedProtocols());
        } else sslServer = null;

        /*new Thread(() -> { while(true) try {
            new HTTPSocket(server.accept(), this);
        } catch(Exception e) { Main.err("HTTP Server Error",e); }}).start();*/

        if(httpsPort > 0) new Thread(() -> { while(true) try {
            new HTTPSocket(sslServer.accept(), this);
        } catch(Exception e) { Main.err("HTTPS Server Error",e); }}).start();
    }

    /* ... Other Stuff ... */

}

编辑:我使用keytool -genkey -keyalg RSA -alias selfsigned -keystore cert.jks -storepass password -validity 360 -keysize 2048生成了证书,但现在Java抛出密钥库被篡改,或密码错误错误。

1 个答案:

答案 0 :(得分:0)

就像我在评论中所说,在 keyStore.load 中使用“密码”解决了这个问题。

private static SSLContext createSSLContext(String cert, char[] pass) throws Exception {
    //Load KeyStore in JKS format:
    KeyStore keyStore = KeyStore.getInstance("jks");
    keyStore.load(new FileInputStream(cert), "password".toCharArray());

    //Create key manager:
    KeyManagerFactory kmFactory = KeyManagerFactory.getInstance("SunX509");
    kmFactory.init(keyStore, pass); KeyManager[] km = kmFactory.getKeyManagers();

    //Create trust manager:
    TrustManagerFactory tmFactory = TrustManagerFactory.getInstance("SunX509");
    tmFactory.init(keyStore); TrustManager[] tm = tmFactory.getTrustManagers();

    //Create SSLContext with protocol:
    SSLContext ctx = SSLContext.getInstance("TLSv1.2");
    ctx.init(km, tm, null); return ctx;
}