`
sunnylocus
  • 浏览: 869665 次
  • 性别: Icon_minigender_1
  • 来自: 美国图森
社区版块
存档分类
最新评论

用JSSE实现网络安全通信

    博客分类:
  • Java
阅读更多

    在网络上信息由源主机到目标主机要经过很多路由和计算机,通常这些机器不会监听路过的信息。但在使用网络银行进行网上消费时,不加以保护的账号密码很有可能被黑客截获并利用给消费者造成不可估量的损失。

      Java安全套接字扩展(JSSE,Java Secure Socket Extension)为基于SSL和TLS协议的Java网络应用程序提供了Java API及参考实现。JSSE支持数据加密、服务器端身份验证、数据完整性。使用JSSE,能保证采用各种应用层协议(HTTP、Telnet、FTP等)的客户程序与服务器程序安全地交换数据

     要实现用JSSE交换数据,需要用到证书,获取证书有两种方式,一是从权威机构购买证书,二是创建自我签名的证书。我们用JDK现有的工具keytool创建一个自我签名的证书。

 

服务端证书

 

客户端证书

 

jks文件是一个密钥容器,证书都会存储在里面,如果要导出刚刚生成的证书,用下面的命令

keytool -export -alias keyAlias
-storepass changeit
 -file server.cer
 -keystore keystore.jks

JSSE中负责安全通信的核心类是SSLServerSocket类和SSLSocket类,它们分别是ServerSocket与Socket类的子类。SSLSocket对象由SSLSocketFactory创建,不过SSLServerSocket的accept()方法也会创建SSLSocket。SSLServerSocketFactory、SSLSocketFactory对象都由SSLContext对象创建。

 

下面是一个简单的例子,客户端和服务端采用刚才生成的两个证书进行通信,在控制台随便输入信息,服务端都会响应,输入"88"结束本次会话。

 

客户端:

package com.bill99.seashell.domain;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.security.KeyStore;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

public class MySSLClient {
	
	private static final String SSL_TYPE = "SSL";
	private static final String X509 = "SunX509";
	private static final String KS_TYPE = "JKS";
	
	private SSLSocket sslcntSocket;
	
	public MySSLClient(String targetHost,int port) throws Exception {
		SSLContext sslContext = createSSLContext(); //创建SSL上下文
		SSLSocketFactory sslcntFactory =(SSLSocketFactory) sslContext.getSocketFactory();
		sslcntSocket = (SSLSocket) sslcntFactory.createSocket(targetHost, port);
		String[] supported = sslcntSocket.getSupportedCipherSuites();
		sslcntSocket.setEnabledCipherSuites(supported); //设置加密套件
	}
	
	private SSLContext createSSLContext() throws Exception{
		KeyManagerFactory kmf = KeyManagerFactory.getInstance(X509);
		TrustManagerFactory tmf = TrustManagerFactory.getInstance(X509);
		//-----------------------------------------------------------
		String clientKeyStoreFile = "c:\\merchant.jks"; //客户端用于证实自己身份的证书
		String cntPassphrase = "baitour";               //证书密码
		char[] cntPassword = cntPassphrase.toCharArray();
		KeyStore clientKeyStore = KeyStore.getInstance(KS_TYPE);
		clientKeyStore.load(new FileInputStream(clientKeyStoreFile),cntPassword);
		//-----------------------------------------------------------
		String serverKeyStoreFile = "c:\\paygateway.jks"; //服务端证书
		String svrPassphrase = "99bill";                 //证书密码
		char[] svrPassword = svrPassphrase.toCharArray();
		KeyStore serverKeyStore = KeyStore.getInstance(KS_TYPE);
		serverKeyStore.load(new FileInputStream(serverKeyStoreFile), svrPassword);
		
		kmf.init(clientKeyStore, cntPassword); 
		
		tmf.init(serverKeyStore);  //添加信任的证书
		
		SSLContext sslContext  = SSLContext.getInstance(SSL_TYPE);
		sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
		
		return sslContext;
	}
	
	/**
	 * 发送消息至服务器
	 * @param sayMsg 发送给服务器信息
	 * @return String 服务器响应的信息
	 * @throws IOException 发送过程Socket出错时抛出此异常
	 */
	public String sayToSvr(String sayMsg) throws IOException{
		BufferedReader ioReader = new BufferedReader(new InputStreamReader(
				sslcntSocket.getInputStream()));
		PrintWriter ioWriter = new PrintWriter(sslcntSocket.getOutputStream());

		ioWriter.println(sayMsg);
		ioWriter.flush();

		return ioReader.readLine();
	}
	
	public static void main(String[] args) throws Exception {
		MySSLClient mysslCnt = new MySSLClient("127.0.0.1",7612);
		BufferedReader ioReader = new BufferedReader(new InputStreamReader(System.in));
		String sayMsg = "";
		String svrRespMsg= "";
		while( (sayMsg = ioReader.readLine())!= null ) {
			svrRespMsg = mysslCnt.sayToSvr(sayMsg);
			if(svrRespMsg != null && !svrRespMsg.trim().equals("")) {
				System.err.println("服务器响应:"+svrRespMsg);
			}
			if(sayMsg.trim().equals("88")) {
				break ;
			}
		}
	}
}

 服务端

package com.bill99.seashell.domain;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.security.KeyStore;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManagerFactory;

public class MySSLServer {

	private static final String SSL_TYPE = "SSL";
	private static final String KS_TYPE = "JKS";
	private static final String X509 = "SunX509";
	
	private final static int PORT = 7612;  //监听端口
	private final static Object lock = new Object();//对象锁
	
	private static MySSLServer mysslServer;
	
	private SSLServerSocket svrSocket;
	
	/**
	 * 通过单态模式获得MySSLServer对象
	 */
	public static MySSLServer getInstance() throws Exception {
		synchronized (lock) {
			if (mysslServer == null) {
				mysslServer = new MySSLServer();
			}
			return mysslServer;
		}
	}
	
	private MySSLServer() throws Exception{
		//输出跟踪日志
		System.setProperty("javax.net.debug","all");
		//创建SSL上下文
		SSLContext sslContext = createSSLContext();
		
		SSLServerSocketFactory serverFactory = sslContext.getServerSocketFactory();
		svrSocket =(SSLServerSocket) serverFactory.createServerSocket(PORT);
		svrSocket.setNeedClientAuth(true);  //需要验证客户的身份
		
		System.err.println("【SSL服务器启动,监听端口:"+PORT+ "】");
		System.err.println(svrSocket.getNeedClientAuth() ? "【需要验证对方身份】" : "【不需要验证对方的身份】");
		//设置支持加密的套件
		String[] supported = svrSocket.getEnabledCipherSuites();
		svrSocket.setEnabledCipherSuites(supported);
	}
	
	/**
	 * 创建上下文
	 * @return SSLContext
	 * @throws Exception 在创建SSLContext发生错误时抛出此异常
	 */
	private SSLContext createSSLContext() throws Exception{
		//证书管理器
		KeyManagerFactory kmf = KeyManagerFactory.getInstance(X509);
		//信任管理器
		TrustManagerFactory tmf = TrustManagerFactory.getInstance(X509);
		
		//服务器证书加载到证书管理器
		//----------------------------------------------------------
		String serverKeyStoreFile = "c:\\paygateway.jks"; //服务器用于证实自己身份的证书
		String svrPassphrase = "99bill";               //服务器证书密码
		char[] svrPassword = svrPassphrase.toCharArray();
		KeyStore serverKeyStore = KeyStore.getInstance(KS_TYPE);
		serverKeyStore.load(new FileInputStream(serverKeyStoreFile), svrPassword);
		kmf.init(serverKeyStore, svrPassword);
		//客户机证书加载到证书管理器
		//-----------------------------------------------------------
		String clientKeyStoreFile = "c:\\merchant.jks"; //客户端用于证实自己身份的证书
		String cntPassphrase = "baitour";               //证书密码
		char[] cntPassword = cntPassphrase.toCharArray();
		KeyStore clientKeyStore = KeyStore.getInstance(KS_TYPE);
		clientKeyStore.load(new FileInputStream(clientKeyStoreFile),cntPassword);
		tmf.init(clientKeyStore);  //添加信任的证书
		
		SSLContext sslContext  = SSLContext.getInstance(SSL_TYPE);
		sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
		
		return sslContext;
	}
	
	/**
	 * 开始服务
	 */
	public void startService() {
		SSLSocket cntSocket = null;
		BufferedReader ioReader = null;
		PrintWriter ioWriter = null;
		String tmpMsg = null;
		while( true ) {
			try {
				cntSocket =(SSLSocket) svrSocket.accept();
				System.err.println("[有客户机连接,IP:"+cntSocket.getInetAddress()+"]");
				ioReader = new BufferedReader(new InputStreamReader(cntSocket.getInputStream()));
				ioWriter = new PrintWriter(cntSocket.getOutputStream());
				
				while ( (tmpMsg = ioReader.readLine()) != null) {
					System.err.println("[客户机说:"+tmpMsg+"]");
					if("88".equals(tmpMsg)) {
						break;
					}
					tmpMsg = " **** Welcome to our website  **** ";
					ioWriter.println(tmpMsg);
					ioWriter.flush();
					System.err.println("[服务器说:"+tmpMsg+"]");
				}
			} catch(IOException e) {
				e.printStackTrace();
			} finally {
				try {
					if(cntSocket != null) cntSocket.close();
				} catch(Exception ex) {ex.printStackTrace();}
			}
		}//end while
	}//end startService method
	
	public static void main(String[] args) throws Exception {
		MySSLServer mysslSvr = MySSLServer.getInstance();
		mysslSvr.startService();

	}
}
 
3
1
分享到:
评论
2 楼 sunnylocus 2011-03-10  
xuxinyl 写道
你好,为什么我按照你的步骤去操作了,运行服务器端还是报错呢?
错误如下:
***
found key for : www.yljs88.com
chain [0] = [
[
  Version: V3
  Subject: CN=xu xin, OU=xys, O=yljs, L=Shenzhen, ST=Guangdong, C=CN
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5

  Key:  Sun RSA public key, 1024 bits
  modulus: 123607024255248258784439028545372026631058966832992855876875000483173298539930721531819202920732193114521618181081579266576350014370654512557051745354541444935824536358484956714753978411516947333147034447568059605065181763586882032781499880058910142827243197441307414996839234272128064359138425232459725803057
  public exponent: 65537
  Validity: [From: Tue Mar 08 18:07:47 CST 2011,
               To: Mon Jun 06 18:07:47 CST 2011]
  Issuer: CN=xu xin, OU=xys, O=yljs, L=Shenzhen, ST=Guangdong, C=CN
  SerialNumber: [    4d75fff3]

]
  Algorithm: [SHA1withRSA]
  Signature:
0000: 64 6A B8 3C 8F 49 F8 9C   10 92 BF EC BC 1F B0 53  dj.<.I.........S
0010: D1 9C E2 17 1D 8D 4D 22   C3 B0 50 A2 A7 E2 2B 65  ......M"..P...+e
0020: 6E 48 F1 89 2C B1 C9 BC   92 C8 A1 35 32 01 BC EE  nH..,......52...
0030: F1 54 BA BB E7 35 86 6C   F9 1C 82 C2 F6 C8 F5 1E  .T...5.l........
0040: 28 5D CC 98 63 78 EE BA   AA 04 B8 45 11 0A EE EA  (]..cx.....E....
0050: B8 A7 39 9B 48 D0 91 6C   C6 14 03 CE 2B 8F 61 5A  ..9.H..l....+.aZ
0060: 91 1A 32 2D C8 B1 1F 5F   81 16 6E DB 10 E9 AC 01  ..2-..._..n.....
0070: CE 97 3F 0C C9 91 DF 3D   FE 6F EE D0 B2 BA 31 B5  ..?....=.o....1.

]
***
adding as trusted cert:
  Subject: CN=li hua, OU=tianpai, O=tian, L=Shenzhen, ST=Guangdong, C=CN
  Issuer:  CN=li hua, OU=tianpai, O=tian, L=Shenzhen, ST=Guangdong, C=CN
  Algorithm: RSA; Serial number: 0x4d760069
  Valid from Tue Mar 08 18:09:45 CST 2011 until Mon Jun 06 18:09:45 CST 2011

trigger seeding of SecureRandom
done seeding SecureRandom
【SSL服务器启动,监听端口:7612】
【不需要验证对方的身份】
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
matching alias: www.yljs88.com
main, called closeSocket()

期待你的回复,谢谢。

能把你的源代码发过来我看下么,这些信息我还看不出问题所在
1 楼 xuxinyl 2011-03-09  
你好,为什么我按照你的步骤去操作了,运行服务器端还是报错呢?
错误如下:
***
found key for : www.yljs88.com
chain [0] = [
[
  Version: V3
  Subject: CN=xu xin, OU=xys, O=yljs, L=Shenzhen, ST=Guangdong, C=CN
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5

  Key:  Sun RSA public key, 1024 bits
  modulus: 123607024255248258784439028545372026631058966832992855876875000483173298539930721531819202920732193114521618181081579266576350014370654512557051745354541444935824536358484956714753978411516947333147034447568059605065181763586882032781499880058910142827243197441307414996839234272128064359138425232459725803057
  public exponent: 65537
  Validity: [From: Tue Mar 08 18:07:47 CST 2011,
               To: Mon Jun 06 18:07:47 CST 2011]
  Issuer: CN=xu xin, OU=xys, O=yljs, L=Shenzhen, ST=Guangdong, C=CN
  SerialNumber: [    4d75fff3]

]
  Algorithm: [SHA1withRSA]
  Signature:
0000: 64 6A B8 3C 8F 49 F8 9C   10 92 BF EC BC 1F B0 53  dj.<.I.........S
0010: D1 9C E2 17 1D 8D 4D 22   C3 B0 50 A2 A7 E2 2B 65  ......M"..P...+e
0020: 6E 48 F1 89 2C B1 C9 BC   92 C8 A1 35 32 01 BC EE  nH..,......52...
0030: F1 54 BA BB E7 35 86 6C   F9 1C 82 C2 F6 C8 F5 1E  .T...5.l........
0040: 28 5D CC 98 63 78 EE BA   AA 04 B8 45 11 0A EE EA  (]..cx.....E....
0050: B8 A7 39 9B 48 D0 91 6C   C6 14 03 CE 2B 8F 61 5A  ..9.H..l....+.aZ
0060: 91 1A 32 2D C8 B1 1F 5F   81 16 6E DB 10 E9 AC 01  ..2-..._..n.....
0070: CE 97 3F 0C C9 91 DF 3D   FE 6F EE D0 B2 BA 31 B5  ..?....=.o....1.

]
***
adding as trusted cert:
  Subject: CN=li hua, OU=tianpai, O=tian, L=Shenzhen, ST=Guangdong, C=CN
  Issuer:  CN=li hua, OU=tianpai, O=tian, L=Shenzhen, ST=Guangdong, C=CN
  Algorithm: RSA; Serial number: 0x4d760069
  Valid from Tue Mar 08 18:09:45 CST 2011 until Mon Jun 06 18:09:45 CST 2011

trigger seeding of SecureRandom
done seeding SecureRandom
【SSL服务器启动,监听端口:7612】
【不需要验证对方的身份】
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
matching alias: www.yljs88.com
main, called closeSocket()

期待你的回复,谢谢。

相关推荐

    Java网络编程(第三版)中文版.part11.rar

    本书展示了如何使用JSSE编写安全的网络应用程序,解释了如何使用NIO API编写超高性能的服务器。它还涵盖了Java对网络代理、Web cookie和URL缓存的支持。 《Java网络编程》不仅仅是对API的解释:它还展示了如何使用...

    Java网络编程(第三版)中文版.part06.rar

    本书展示了如何使用JSSE编写安全的网络应用程序,解释了如何使用NIO API编写超高性能的服务器。它还涵盖了Java对网络代理、Web cookie和URL缓存的支持。 《Java网络编程》不仅仅是对API的解释:它还展示了如何使用...

    Java网络编程(第三版)中文版.part07.rar

    本书展示了如何使用JSSE编写安全的网络应用程序,解释了如何使用NIO API编写超高性能的服务器。它还涵盖了Java对网络代理、Web cookie和URL缓存的支持。 《Java网络编程》不仅仅是对API的解释:它还展示了如何使用...

    Java网络编程(第三版)中文版.part09.rar

    本书展示了如何使用JSSE编写安全的网络应用程序,解释了如何使用NIO API编写超高性能的服务器。它还涵盖了Java对网络代理、Web cookie和URL缓存的支持。 《Java网络编程》不仅仅是对API的解释:它还展示了如何使用...

    Java网络编程(第三版)高清中文版.part01.rar

    本书展示了如何使用JSSE编写安全的网络应用程序,解释了如何使用NIO API编写超高性能的服务器。它还涵盖了Java对网络代理、Web cookie和URL缓存的支持。 《Java网络编程》不仅仅是对API的解释:它还展示了如何使用...

    Java网络编程(第三版)中文版.part01.rar

    本书展示了如何使用JSSE编写安全的网络应用程序,解释了如何使用NIO API编写超高性能的服务器。它还涵盖了Java对网络代理、Web cookie和URL缓存的支持。 《Java网络编程》不仅仅是对API的解释:它还展示了如何使用...

    Java网络编程(第三版)中文版.part03.rar

    本书展示了如何使用JSSE编写安全的网络应用程序,解释了如何使用NIO API编写超高性能的服务器。它还涵盖了Java对网络代理、Web cookie和URL缓存的支持。 《Java网络编程》不仅仅是对API的解释:它还展示了如何使用...

    Java网络编程(第三版)中文版.part02.rar

    本书展示了如何使用JSSE编写安全的网络应用程序,解释了如何使用NIO API编写超高性能的服务器。它还涵盖了Java对网络代理、Web cookie和URL缓存的支持。 《Java网络编程》不仅仅是对API的解释:它还展示了如何使用...

    Java网络编程(第三版)中文版.part04.rar

    本书展示了如何使用JSSE编写安全的网络应用程序,解释了如何使用NIO API编写超高性能的服务器。它还涵盖了Java对网络代理、Web cookie和URL缓存的支持。 《Java网络编程》不仅仅是对API的解释:它还展示了如何使用...

    Java网络编程(第三版)中文版.part10.rar

    本书展示了如何使用JSSE编写安全的网络应用程序,解释了如何使用NIO API编写超高性能的服务器。它还涵盖了Java对网络代理、Web cookie和URL缓存的支持。 《Java网络编程》不仅仅是对API的解释:它还展示了如何使用...

    Java网络编程(第三版)中文版.part13.rar

    本书展示了如何使用JSSE编写安全的网络应用程序,解释了如何使用NIO API编写超高性能的服务器。它还涵盖了Java对网络代理、Web cookie和URL缓存的支持。 《Java网络编程》不仅仅是对API的解释:它还展示了如何使用...

    Java网络编程(第三版)中文版.part05.rar

    本书展示了如何使用JSSE编写安全的网络应用程序,解释了如何使用NIO API编写超高性能的服务器。它还涵盖了Java对网络代理、Web cookie和URL缓存的支持。 《Java网络编程》不仅仅是对API的解释:它还展示了如何使用...

    Java网络编程(第三版)中文版.part12.rar

    本书展示了如何使用JSSE编写安全的网络应用程序,解释了如何使用NIO API编写超高性能的服务器。它还涵盖了Java对网络代理、Web cookie和URL缓存的支持。 《Java网络编程》不仅仅是对API的解释:它还展示了如何使用...

    Java网络编程(第三版)中文版.part08.rar

    本书展示了如何使用JSSE编写安全的网络应用程序,解释了如何使用NIO API编写超高性能的服务器。它还涵盖了Java对网络代理、Web cookie和URL缓存的支持。 《Java网络编程》不仅仅是对API的解释:它还展示了如何使用...

Global site tag (gtag.js) - Google Analytics