1.单向ssl和双向ssl
网上有些例子可以参考:
http://www.yeeach.com/digg/story/11964
http://www.bluedash.net/spaces/SSL介绍与Java实例
第一步: 客户端发送ClientHello消息,发起SSL连接请求,告诉服务器自己支持的SSL选项(加密方式等)。
单向SSL:
1 *** ClientHello, TLSv1
第二步: 服务器响应请求,回复ServerHello消息,和客户端确认SSL加密方式:
1 *** ServerHello, TLSv1
第三步: 服务端向客户端发布自己的公钥。
第四步: 客户端与服务端的协通沟通完毕,服务端发送ServerHelloDone消息:
1 *** ServerHelloDone
第五步: 客户端使用服务端给予的公钥,创建会话用密钥(SSL证书认证完成后,为了提高性能,所有的信息交互就可能会使用对称加密算法),并通过ClientKeyExchange消息发给服务器:
1 *** ClientKeyExchange, RSA PreMasterSecret, TLSv1
第六步: 客户端通知服务器改变加密算法,通过ChangeCipherSpec消息发给服务端:
1 main, WRITE: TLSv1 Change Cipher Spec, length = 1
第七步: 客户端发送Finished消息,告知服务器请检查加密算法的变更请求:
1 *** Finished
第八步:服务端确认算法变更,返回ChangeCipherSpec消息
1 main, READ: TLSv1 Change Cipher Spec, length = 1
第九步:服务端发送Finished消息,加密算法生效:
1 *** Finished
那么如何让服务端也认证客户端的身份,即双向握手呢?其实很简单,在服务端代码中,把这一行:
1 ((SSLServerSocket) _socket).setNeedClientAuth(false);
改成:
1 ((SSLServerSocket) _socket).setNeedClientAuth(true);
就可以了。但是,同样的道理,现在服务端并没有信任客户端的证书,因为客户端的证书也是自己生成的。所以,对于服务端,需要做同样的工作:把客户端的证书导出来,并导入到服务端的证书仓库。
双向SSL
在 *** ServerHelloDone 之前,服务端向客户端发起了需要证书的请求 *** CertificateRequest 。
在客户端向服务端发出 Change Cipher Spec 请求之前,多了一步客户端证书认证的过程
*** CertificateVerify 。
编码注意:
System.setProperty("javax.net.ssl.trustStore", SERVER_TRUST_STORE);//在双向SSL才需要,用于对方的证书
System.setProperty("javax.net.debug", "ssl,handshake");//打开SSL握手的日志
((SSLServerSocket) _socket).setNeedClientAuth(true);//是否启用双向SSL认证
context.init(kf.getKeyManagers(), tms, null); //tms参数为TrustManager[],可以自定义,也可以从keystore构造
自定义的例子:
package org.young.ssl; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import javax.net.ssl.X509TrustManager; public class TestX509TrustManager implements X509TrustManager { private static String SERVER_KEY_STORE_PASSWORD = "654321"; @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { System.out.println("checkClientTrusted"); System.out.println(authType); System.out.println(chain); } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { // TODO Auto-generated method stub System.out.println("checkServerTrusted"); } @Override public X509Certificate[] getAcceptedIssuers() { X509Certificate[] chain = null; try { // TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); // KeyStore tks = KeyStore.getInstance("JKS"); // tks.load(new FileInputStream("D:/work/j2eeproject/ssl-demo/store/server/tserver.keystore"), // SERVER_KEY_STORE_PASSWORD.toCharArray()); // tmf.init(tks); // chain = ((X509TrustManager) tmf.getTrustManagers()[0]).getAcceptedIssuers(); //or FileInputStream fis = new FileInputStream("D:/work/j2eeproject/ssl-demo/store/server/tserver.keystore"); BufferedInputStream bis = new BufferedInputStream(fis); CertificateFactory cf = CertificateFactory.getInstance("X.509"); List<X509Certificate> list = new ArrayList<X509Certificate>(); while (bis.available() > 0) { X509Certificate c = (X509Certificate) cf.generateCertificate(bis); list.add(c); } chain = list.toArray(chain); list = null; // for(X509Certificate c: chain) { // System.out.println(c.gets); // } } catch (Exception e) { throw new RuntimeException(e); } return chain; } }
2.签名的例子
http://www.herongyang.com/JDK/jca_signature_2.html
网上有些例子可以参考:
http://www.yeeach.com/digg/story/11964
http://www.bluedash.net/spaces/SSL介绍与Java实例
第一步: 客户端发送ClientHello消息,发起SSL连接请求,告诉服务器自己支持的SSL选项(加密方式等)。
单向SSL:
1 *** ClientHello, TLSv1
第二步: 服务器响应请求,回复ServerHello消息,和客户端确认SSL加密方式:
1 *** ServerHello, TLSv1
第三步: 服务端向客户端发布自己的公钥。
第四步: 客户端与服务端的协通沟通完毕,服务端发送ServerHelloDone消息:
1 *** ServerHelloDone
第五步: 客户端使用服务端给予的公钥,创建会话用密钥(SSL证书认证完成后,为了提高性能,所有的信息交互就可能会使用对称加密算法),并通过ClientKeyExchange消息发给服务器:
1 *** ClientKeyExchange, RSA PreMasterSecret, TLSv1
第六步: 客户端通知服务器改变加密算法,通过ChangeCipherSpec消息发给服务端:
1 main, WRITE: TLSv1 Change Cipher Spec, length = 1
第七步: 客户端发送Finished消息,告知服务器请检查加密算法的变更请求:
1 *** Finished
第八步:服务端确认算法变更,返回ChangeCipherSpec消息
1 main, READ: TLSv1 Change Cipher Spec, length = 1
第九步:服务端发送Finished消息,加密算法生效:
1 *** Finished
那么如何让服务端也认证客户端的身份,即双向握手呢?其实很简单,在服务端代码中,把这一行:
1 ((SSLServerSocket) _socket).setNeedClientAuth(false);
改成:
1 ((SSLServerSocket) _socket).setNeedClientAuth(true);
就可以了。但是,同样的道理,现在服务端并没有信任客户端的证书,因为客户端的证书也是自己生成的。所以,对于服务端,需要做同样的工作:把客户端的证书导出来,并导入到服务端的证书仓库。
双向SSL
在 *** ServerHelloDone 之前,服务端向客户端发起了需要证书的请求 *** CertificateRequest 。
在客户端向服务端发出 Change Cipher Spec 请求之前,多了一步客户端证书认证的过程
*** CertificateVerify 。
编码注意:
System.setProperty("javax.net.ssl.trustStore", SERVER_TRUST_STORE);//在双向SSL才需要,用于对方的证书
System.setProperty("javax.net.debug", "ssl,handshake");//打开SSL握手的日志
((SSLServerSocket) _socket).setNeedClientAuth(true);//是否启用双向SSL认证
context.init(kf.getKeyManagers(), tms, null); //tms参数为TrustManager[],可以自定义,也可以从keystore构造
自定义的例子:
package org.young.ssl; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import javax.net.ssl.X509TrustManager; public class TestX509TrustManager implements X509TrustManager { private static String SERVER_KEY_STORE_PASSWORD = "654321"; @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { System.out.println("checkClientTrusted"); System.out.println(authType); System.out.println(chain); } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { // TODO Auto-generated method stub System.out.println("checkServerTrusted"); } @Override public X509Certificate[] getAcceptedIssuers() { X509Certificate[] chain = null; try { // TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); // KeyStore tks = KeyStore.getInstance("JKS"); // tks.load(new FileInputStream("D:/work/j2eeproject/ssl-demo/store/server/tserver.keystore"), // SERVER_KEY_STORE_PASSWORD.toCharArray()); // tmf.init(tks); // chain = ((X509TrustManager) tmf.getTrustManagers()[0]).getAcceptedIssuers(); //or FileInputStream fis = new FileInputStream("D:/work/j2eeproject/ssl-demo/store/server/tserver.keystore"); BufferedInputStream bis = new BufferedInputStream(fis); CertificateFactory cf = CertificateFactory.getInstance("X.509"); List<X509Certificate> list = new ArrayList<X509Certificate>(); while (bis.available() > 0) { X509Certificate c = (X509Certificate) cf.generateCertificate(bis); list.add(c); } chain = list.toArray(chain); list = null; // for(X509Certificate c: chain) { // System.out.println(c.gets); // } } catch (Exception e) { throw new RuntimeException(e); } return chain; } }
2.签名的例子
http://www.herongyang.com/JDK/jca_signature_2.html