SSLHandshakeException:没有共同的密码套件

时间:2012-03-03 18:45:19

标签: java ssl ssl-certificate authentication

按照说明here重新创建我之前错误创建的证书。有些事情发生了变化,因为我现在在服务器上看到javax.net.ssl.SSLHandshakeException: no cipher suites in common,在客户端看到javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure。而不是错误this question

服务器为ClassFileServer.java,客户端为SSLSocketClientWithClientAuth.java

有关让两端发挥得很好的任何提示,请注意我使用的是localhost所以我认为密码功能是相同的。


更新

以下是我用来生成文件的步骤,我可能会混淆密钥和信任库。:

在服务器上(this指南后面):

$ keytool -genkey -alias serverkey -keyalg RSA -keypass p@ssw0rd -storepass p@ssw0rd -keystore keystore.jks

$ keytool -export -alias serverkey -storepass p@ssw0rd -file server.cer -keystore keystore.jks

$ keytool -import -v -trustcacerts -alias clientkey -file ../client/client.cer -keystore cacerts.jks -keypass p@ssw0rd -storepass p@ssw0rd

在客户端(通过this指南):

$ keytool -genkey -alias clientkey -keyalg RSA -keypass changeit -storepass changeit -keystore keystore.jks

$ keytool -export -alias clientkey -storepass changeit -file client.cer -keystore keystore.jks

$ keytool -import -v -trustcacerts -alias serverkey -file ../server/server.cer -keystore cacerts.jks -keypass changeit -storepass changeit

由于调试超出了本网站的正文限制,因此必须使用其他媒体:

客户端调试错误: http://pastebin.com/mHCmEqAk

服务器调试错误: http://pastebin.com/YZbh7H8f

3 个答案:

答案 0 :(得分:4)

javax.net.ssl.SSLHandshakeException: no cipher suites in common

这有两个原因:

  1. 服务器没有私钥和证书,可能根本没有密钥库。在这种情况下,它只能使用默认禁用的不安全的匿名密码套件,并且应该保持这种状态。因此,没有密码套件可以同意与客户一起使用。

  2. 客户端或服务器或两者对密码套件的限制过多,导致无法达成协议。

  3. 重新安装你的密钥库和信任商店,除了你只需要两个导入步骤外,所有看起来都不错。您无需将服务器的证书导入服务器自己的信任库,或将客户端的证书导入客户端的信任库。你只需要这个:

    服务器:

    $ keytool -import -v -trustcacerts -alias clientkey -file ../client/client.cer -keystore cacerts.jks -keypass p@ssw0rd -storepass p@ssw0rd
    

    客户端:

    $ keytool -import -v -trustcacerts -alias serverkey -file ../server/server.cer -keystore cacerts.jks -keypass changeit -storepass changeit
    

    并且您只需要它,因为您使用的是自签名证书。简单的解决方案:不要。使用CA签名的证书,该证书受Java附带的默认信任库的信任。

答案 1 :(得分:3)

在Cassandra群集上设置SSL时出现此错误。在描述生成密钥时,问题结果出现在version 2.0的文档中:

  

keytool -genkey -alias -keystore .keystore

它省略了RSA的规范作为算法,应该是(see v1.2 docs):

  

keytool -genkey -alias -keyalg RSA -keystore   的.keystore

答案 2 :(得分:0)

作为将trustStores作为JVM参数-Djavax.net.ssl.trustStore=<cacerts_file.jks>传递的一种替代方法,还可以将信任库添加到SSLContext,然后创建SSLSocketFactory作为以下代码段,

SSLContext ctx;
KeyManagerFactory kmf;
TrustManagerFactory tmf;
KeyStore ks;
TrustManager tm;

ctx = SSLContext.getInstance("TLS");

kmf = KeyManagerFactory.getInstance("SunX509");
ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(privateKey), passPhrase.toCharArray());
kmf.init(ks, passphrase);

KeyStore trustKeyStore = KeyStore.getInstance("JKS");
trustKeyStore.load(new FileInputStream(trustStore), trustPassPhrase.toCharArray());

TrustManagerFactory trustMgrFactory = TrustManagerFactory.getInstance("SUNX509");
trustMgrFactory.init(trustKeyStore);

ctx.init(kmf.getKeyManagers(), trustMgrFactory.getTrustManagers(), null);

SSLSocketFactory f = (SSLSocketFactory) ctx.getSocketFactory();

SSLSocket s = (SSLSocket) f.createSocket(serverIp, serverPort);

注意:此客户端套接字同时执行客户端和服务器身份验证。如果要禁用客户端身份验证,请在初始化null时将SSLContext ctx作为第一个参数传递。