SSL套接字连接

20

如何创建SSL Socket连接?

我是否真的需要创建一个密钥库?这个密钥库需要与所有客户端应用程序共享吗?

我已经使用以下代码创建了服务器:

SSLServerSocketFactory sslserversocketfactory = (SSLServerSocketFactory) SSLServerSocketFactory
                    .getDefault();
SSLServerSocket sslserversocket = (SSLServerSocket) sslserversocketfactory
                    .createServerSocket(ServerProperties.getInstance()
                            .getVSSPAuthenticationPort());

我已经用以下代码在安卓上创建了一个客户端:

SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory
                .getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(
                host, authPort);

sslsocket.startHandshake();

BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
                sslsocket.getOutputStream()));
BufferedReader reader = new BufferedReader(new InputStreamReader(
                sslsocket.getInputStream()));

但是当我尝试连接时,会抛出以下错误:

javax.net.ssl.SSLHandshakeException: no cipher suites in common
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1886)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:276)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:266)
    at sun.security.ssl.ServerHandshaker.chooseCipherSuite(ServerHandshaker.java:894)
    at sun.security.ssl.ServerHandshaker.clientHello(ServerHandshaker.java:622)
    at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:167)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:804)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1016)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323)
1个回答

35

建立SSL连接需要证书,您可以将证书加载到密钥库中,也可以直接加载证书本身。我将展示一些选项的示例。

您的代码需要一些参数才能运行:

java -Djavax.net.ssl.keyStore=keyStoreFile -Djavax.net.ssl.keyStorePassword=keystorePassword Server

您也可以使用Java代码加载密钥库,最简单的方法是设置系统属性:

System.setProperty("javax.net.ssl.keyStore", 'keystoreFile');
System.setProperty("javax.net.ssl.keyStorePassword", 'keystorePassword ');

您也可以用不同的方式加载keystore,这样更复杂,但您可以做更复杂的事情:

KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("keystoreFile"), "keystorePassword".toCharArray());

KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
kmf.init(ks, "keystorePassword".toCharArray());

TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509"); 
tmf.init(ks);

SSLContext sc = SSLContext.getInstance("TLS"); 
TrustManager[] trustManagers = tmf.getTrustManagers(); 
sc.init(kmf.getKeyManagers(), trustManagers, null); 

SSLServerSocketFactory ssf = sc.getServerSocketFactory(); 
SSLServerSocket s = (SSLServerSocket) ssf.createServerSocket(serverport);
SSLSocket c = (SSLSocket) s.accept();

对于客户端代码,最后几行需要进行一些更改:将原来的最后3行替换为以下内容:

SSLSocketFactory ssf = sc.getSocketFactory(); 
SSLSocket s = (SSLSocket) ssf.createSocket(serverip, serverport);
s.startHandshake();

如果你想要为安卓加载一个密钥库,那么类型必须是"BKS"而不是"JKS"。你可以很容易地找到创建密钥库的资源。


只有当您连接的服务器需要时,才需要证书来建立SSL连接。同样,密钥库也是如此。 - user207421
你是说证书是可选的吗? - VGe0rge
1
我说过,只有在服务器需要时才需要它。我不会将其描述为“可选的”,而是更依赖于配置。 - user207421
你在谈论用户证书,当然你是对的!而我则误解了这一点 ;) - VGe0rge
这里没有证据表明服务器没有证书。 - user207421
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接