简体   繁体   中英

Java HTTPS Server “Unsupported Protocol Error” in Chrome

I'm making a custom HTTP/1.1 server implementation in Java. It's working fine in HTTP mode, but I also want to support HTTPS. I haven't generated a certificate for the server yet, but it should at least be trying to connect. I set the protocol and cipher suite to the same settings as google.com (TLS 1.2, ECDHE_RSA, AES_128_GCM), so I know Chrome supports them.

But when I try to connect to https://localhost in Chrome, it gives ERR_SSL_VERSION_OR_CIPHER_MISMATCH (localhost uses an unsupported protocol) error. On the Java side, I get "no cipher suites in common" error.

Java Code:

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 ... */

}

EDIT: I generated a certificate using keytool -genkey -keyalg RSA -alias selfsigned -keystore cert.jks -storepass password -validity 360 -keysize 2048 , but now Java throws Keystore was tampered with, or password was incorrect error.

Like I said in the comments, using "password" in keyStore.load solved the issue.

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM