Java SSLHandshakeException: no cipher suites in common

The keystore for each authenticated party, always the server and here the client also because you specified NeedClientAuth, must have the PRIVATE KEY AND certificate(s), not merely the certificate(s). There are two ways to do this:

  • convert the OpenSSL generated privatekey plus the related certs to PKCS#12, and then either convert the PKCS#12 to JKS or just use the PKCS#12 in Java (JCE can handle it, and recent versions of Java8 even if you specify JKS! -- see http://www.oracle.com/technetwork/java/javase/8u60-relnotes-2620227.html under Keystore Compatibility Mode). See:

    How to import an existing x509 certificate and private key in Java keystore to use in SSL?
    How can i create keystore from an existing certificate (abc.crt) and abc.key files?
    Importing the private-key/public-certificate pair in the Java KeyStore
    convert certificate from pem into jks (disclosure: mine)
    How to create keystore from cer files (disclosure: mine)

  • generate EE privatekey and CSR in Java, then use OpenSSL (with CA key and cert) to issue the EE cert, and import the certs back into the Java keystore:

    keytool -keystore server.jks -genkeypair -keyalg RSA 
    # before j7 best to add -keysize 2048 see below 
    keytool -keystore server.jks -certreq >server.csr 
    openssl ca -in server.csr ... -out server.crt 
    # or submit the CSR to a real CA and get its response
    
    # then either install the chain all at once:
    cat server.crt ca.crt >temp
    keytool -keystore server.jks -importcert -file temp
    # and confirm (need temp so stdin available for confirm;
    # if using a public CA, can add -trustcacerts and use pipe instead)
    
    # or install the certs separately, top down:
    keytool -keystore server.jks -importcert -file ca.crt -alias ca
    # and confirm, THEN
    keytool -keystore server.jks -importcert -file server.crt 
    
    # (last) response must be 'Certificate reply was installed'
    # NOT merely 'Certificate was added' which means you messed up
    
    # and similarly for client
    

The latter method (separate entries for ca.crt and privatekey+server.crt) has the advantage this same file can be used as both the keystore and truststore, you don't need to use serverkey as clienttrust and vice versa. If these were real systems, this would be a security benefit.

A final note: you should start using RSA 2048-bit keys. 1024-bit has been prohibited by authorities like NIST and CABforum since 2014, and although Java still accepts them, most browsers and many other tools are already warning for them and likely soon will reject them. For similar reasons you should sign the certificates with at least SHA256 -- this can be set in the config file used by ca or you can just use the commandline flag -md sha256.


I have never seen the KeyManagerFactory declared the way you have, I typically see it like this:

KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());

I realize that I missed this second link for you:

http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html#Debug

You will need to walk through SSL debug. However, you need to explicitly enable certain ciphers (if I recall correctly) and would recommend that path.