Add trustStore for client authentication [duplicat

2019-03-16 21:23发布

This question already has an answer here:

A server and respective client support client authentication but as noted here: SSLHandshakeException: no cipher suites in common, do not have trustStore reference, i.e. they use the default trustStore. How can the trustStore be specified?

ClassFileServer:

private static ServerSocketFactory getServerSocketFactory(String type) {
    if (type.equals("TLS")) {
        SSLServerSocketFactory ssf = null;

        Properties systemProps = System.getProperties();
        systemProps.put( "javax.net.ssl.trustStore", "cacerts.jks");
        systemProps.put( "javax.net.ssl.trustStorePassword", "p@ssw0rd");
        System.setProperties(systemProps);

        try {
            // set up key manager to do server authentication
            SSLContext ctx;
            KeyManagerFactory kmf;
            KeyStore ks;
            char[] passphrase = "p@ssw0rd".toCharArray();

            ctx = SSLContext.getInstance("TLS");
            kmf = KeyManagerFactory.getInstance("SunX509");
            ks = KeyStore.getInstance("JKS");
            ks.load(new FileInputStream("keystore.jks"), passphrase);
            kmf.init(ks, passphrase);
            ctx.init(kmf.getKeyManagers(), null, null);

            ssf = ctx.getServerSocketFactory();
            return ssf;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

SSLSocketClientWithClientAuth:

    try {

        /*
         * Set up a key manager for client authentication
         * if asked by the server.  Use the implementation's
         * default TrustStore and secureRandom routines.
         */
        Properties systemProps = System.getProperties();
        systemProps.put( "javax.net.ssl.trustStore", "cacerts.jks");
        systemProps.put( "javax.net.ssl.trustStorePassword", "changeit");
        System.setProperties(systemProps);

        SSLSocketFactory factory = null;
        try {
            SSLContext ctx;
            KeyManagerFactory kmf;
            KeyStore ks;
            char[] passphrase = "changeit".toCharArray();

            ctx = SSLContext.getInstance("TLS");
            kmf = KeyManagerFactory.getInstance("SunX509");
            ks = KeyStore.getInstance("JKS");

            ks.load(new FileInputStream("keystore.jks"), passphrase);

            kmf.init(ks, passphrase);
            ctx.init(kmf.getKeyManagers(), null, null);

            factory = ctx.getSocketFactory();
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }

        SSLSocket socket = (SSLSocket)factory.createSocket(host, port);

2条回答
成全新的幸福
2楼-- · 2019-03-16 21:38

'No cipher suites in common' is not caused by using the default truststore. It is caused by not having a keystore, or not having a private key and certificate in it, or else by overspecifying cipher suites at one peer or the other such that there can be no agreement.

If the server doesn't have a private key, it can't use any cipher suites except the insecure anonymous ones, which are disabled by default, and should stay that way. Hence the alert.

Using the default truststore will cause a different problem if and only if you are using self-signed certificates. Simple solution: don't. More complex solution: export the respective certificates from the respective keystores and import them into the other party's truststore.

See the JSSE Reference Guide.

查看更多
看我几分像从前
3楼-- · 2019-03-16 21:40

Specify the trustStore by setting the system properties:

System.setProperty("javax.net.ssl.trustStore", "cacerts.jks");

or via command line invocation:

-Djavax.net.ssl.keyStore=path/to/keystore.jks

查看更多
登录 后发表回答