Java安全传输实践

传输层安全访问是通过身份验证和加密传输的过程。JDK的JSSE提供了传输层安全访问的实现。本文旨在通过一个完整的TLS通讯实例,辨析一个普遍的误导。


网络上停留在理论的简单实例通常存在一个误导。在双向信任的情况下,双方都需要信任对方的证书。这样的例子很多,普遍拷贝并简述过程。
其 实,在实践中发现,双方都信任一个权威的CA,并持有该CA根证书和该CA签发的证书,即可以信任对方,实现通讯,不需要对方证书。这样做的好处是,连接 方发生变动后,如果新的接入方也是CA签发认证的,即可认为可信。还有一个好处是,减少一个文件的部署(如果该通讯被重用在其他项目,或许这不是小事)。

〇 Scenario
ICM和UCGW是双向信任的两方,通过TLS通讯。CA是内部公信签证机构。

一 Certificate
签证流程:

0.CA自签证书作为其他设备的根证书
1.ICM和UCGW(两方流程一致,以下简称ICM)自签证书
2.向CA发送签发请求
这一步可以是发送一个CSR将公钥信息传递给CA
本例是将证书直接发给CA
3.CA为请求者签发证书
4.CA发送根证 书和 CA签发的证书 给请求者
5.ICM将CA根证书导入信任列表
6.ICM将CA签发的证书替换自己签发的证书

实现代码:

0.CA自签证书作为其他设备的根证书
CertInfo certInfo  =   new  CertInfo();
SelfSign selfs 
=   new  SelfSign();
certInfo.setKeystore(CA_KEYSTORE);
certInfo.setAlias(CA_ALIAS);
certInfo.setCommonName(
" mars_ca " );
selfs.sign(certInfo, CA_CER);

keytool -genkey -dname "CN=mars_ca, OU=rv, O=rcd, L=ZB, ST=bj, C=China" -alias root -keyalg RSA -keystore ca--ca.keystore -keypass 111111 -storepass 111111 -validity 60
keytool -export -alias root -keystore ca--ca.keystore -storepass 111111 -rfc -file ca--ca.cer
Certificate stored in file <ca--ca.cer>

keytool -list -keystore ca--ca.keystore -storepass 111111

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

root, May 24, 2011, PrivateKeyEntry,
Certificate fingerprint (MD5): 24:48:A3:4D:9F:EE:39:DE:8C:E7:51:60:7E:94:7A:76

 

1.ICM和UCGW(两方流程一致,以下简称ICM)自签证书
//  CertInfo certInfo = new CertInfo();
//  SelfSign selfs = new SelfSign();
certInfo.setKeystore(ICM_KEYSTORE);
certInfo.setAlias(ICM_ALIAS);
certInfo.setCommonName(
" mars_icm " );
selfs.sign(certInfo, ICM_CER);

//  SelfSign selfs = new SelfSign();
//  CertInfo certInfo = new CertInfo();
certInfo.setKeystore(UCGW_KEYSTORE);
certInfo.setAlias(UCGW_ALIAS);
certInfo.setCommonName(
" mars_UCGW " );
selfs.sign(certInfo, UCGW_CER);

keytool -genkey -dname "CN=mars_icm, OU=rv, O=rcd, L=ZB, ST=bj, C=China" -alias icm -keyalg RSA -keystore iview.keystore -keypass 111111 -storepass 111111 -validity 60
keytool -export -alias icm -keystore iview.keystore -storepass 111111 -rfc -file icm--icm.cer
Certificate stored in file <icm--icm.cer>

keytool -genkey -dname "CN=mars_UCGW, OU=rv, O=rcd, L=ZB, ST=bj, C=China" -alias ucgw -keyalg RSA -keystore ucgw.keystore -keypass 111111 -storepass 111111 -validity 60
keytool -export -alias ucgw -keystore ucgw.keystore -storepass 111111 -rfc -file ucgw--ucgw.cer
Certificate stored in file <ucgw--ucgw.cer>

keytool -export -alias ca_signed -keystore ca--ca_sign.keystore -storepass 111111 -rfc -file ca--icm.signed.cer
Certificate stored in file <ca--icm.signed.cer>

keytool -export -alias ca_signed -keystore ca--ca_sign.keystore -storepass 111111 -rfc -file ca--ucgw.signed.cer
Certificate stored in file <ca--ucgw.signed.cer>

 

keytool  - list  - keystore iview.keystore  - storepass  111111

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 
1  entry

icm , May  24 2011 , PrivateKeyEntry,
Certificate fingerprint (MD5): 
78 :5C:AA:1B: 27 :9D:FB:3E:BE:1A:BD:6E:C5:A5: 25 :BD

keytool 
- list  - keystore ucgw.keystore  - storepass  111111

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 
1  entry

ucgw , May  24 2011 , PrivateKeyEntry,
Certificate fingerprint (MD5): 7B:
88 : 44 : 27 : 88 : 66 :2D:6B: 64 :E3:D5: 34 :4A: 03 :DA:8F

 

2.向CA发送签发请求
3.CA为请求者签发证书
CASign cas  =   new  CASign();
cas.sign(ICM_CER, ICM_SIGN_CER, CASIGN_KEYSTORE);
cas.sign(UCGW_CER, UCGW_SIGN_CER, CASIGN_KEYSTORE);

 

5.ICM将CA根证书导入信任列表
6.ICM将CA签发的证书替换自己签发的证书
CertImport im  =   new  CertImport();
im.importCA(ICM_KEYSTORE);
im.importSign(ICM_ALIAS, ICM_SIGN_CER, ICM_KEYSTORE);

im.importCA(UCGW_KEYSTORE);
im.importSign(UCGW_ALIAS, UCGW_SIGN_CER, UCGW_KEYSTORE);

keytool -importcert -noprompt -alias root -file ca--ca.cer -keystore iview.keystore -storepass 111111
Certificate was added to keystore

keytool -importcert -noprompt -trustcacerts -alias icm -file ca--icm.signed.cer -keystore iview.keystore -storepass 111111 -keypass 111111
Certificate reply was installed in keystore

keytool -importcert -noprompt -alias root -file ca--ca.cer -keystore ucgw.keystore -storepass 111111
Certificate was added to keystore

keytool -importcert -noprompt -trustcacerts -alias ucgw -file ca--ucgw.signed.cer -keystore ucgw.keystore -storepass 111111 -keypass 111111
Certificate reply was installed in keystore

 

keytool  - list  - keystore iview.keystore  - storepass  111111

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 
2  entries

root , May  24 2011 , trustedCertEntry,
Certificate fingerprint (MD5): 
24 : 48 :A3:4D:9F:EE: 39 :DE:8C:E7: 51 : 60 :7E: 94 :7A: 76
icm , May  24 2011 , PrivateKeyEntry, 
Certificate fingerprint (MD5): 
18 :D9: 40 :BD: 65 :6C:4D:B9:F3: 87 :2B: 09 : 63 :CD:F0:7A

keytool 
- list  - keystore ucgw.keystore  - storepass  111111

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 
2  entries

root , May  24 2011 , trustedCertEntry,
Certificate fingerprint (MD5): 
24 : 48 :A3:4D:9F:EE: 39 :DE:8C:E7: 51 : 60 :7E: 94 :7A: 76
ucgw , May  24 2011 , PrivateKeyEntry, 
Certificate fingerprint (MD5): 2A:3D:3F:A6:E3:2F:
36 :B9: 71 :CD:AB:1D:9F: 19 :8A: 49


二 TLS
这里以ICM作为服务器端,UCGW作为客户端。
方式一:加载keystore到环境变量,启用默认工厂SSL-Server-Socket-Factory

public   class  SSLServer {
    
public   static   void  main(String args[])  throws  Exception {
        System.setProperty(
" javax.net.ssl.keyStore " , TLSParameter.ICM_KEYSTORE);
        System.setProperty(
" javax.net.ssl.keyStorePassword " , TLSParameter.S_KEY_PASS);
        
        SSLServerSocketFactory ssf 
=  (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
        ServerSocket ss 
=  ssf.createServerSocket(TLSParameter.SSLPORT);
        System.out.println(
" SSL Server is started. " );
        
while  ( true ) {
            Socket s 
=  ss.accept();
            PrintStream out 
=   new  PrintStream(s.getOutputStream());
            out.println(
" ICM say Hello to UCGW! " );
            out.close();
            s.close();
        }
    }
}

 

public   class  SSLClient {

    
public   static   void  main(String args[])  throws  Exception {
        System.setProperty(
" javax.net.ssl.trustStore " , TLSParameter.UCGW_KEYSTORE);
        SSLSocketFactory ssf 
=  (SSLSocketFactory) SSLSocketFactory.getDefault();
        Socket s 
=  ssf.createSocket(TLSParameter.IP, TLSParameter.SSLPORT);
        BufferedReader in 
=   new  BufferedReader( new  InputStreamReader(s.getInputStream()));
        String x 
=  in.readLine();
        System.out.println(x);
        in.close();
    }
}


方式二:设置SSLContext,通过上下文实例启用SSL-Server-Socket-Factory

public   class  SSLServer1 {
    
public   static   void  main(String args[])  throws  Exception {
        SSLContext sslContext 
=  SSLContext.getInstance(PROTOCOL);
        KeyManager[] km 
=  TLSSocket.createKeyManagers(keyStoreType, ICM_KEYSTORE);
        TrustManager[] tm 
=  TLSSocket.createTrustManagers(keyStoreType, ICM_KEYSTORE);
        SecureRandom random 
=  SecureRandom.getInstance(SHA1PRNG);
        sslContext.init(km, tm, random);
        
        SSLServerSocketFactory factory 
=  sslContext.getServerSocketFactory();        
        ServerSocket ss 
=  (SSLServerSocket) factory.createServerSocket(SSLPORT);
        System.out.println(
" SSL Server is started. " );
        
while  ( true ) {
            Socket s 
=  ss.accept();
            PrintStream out 
=   new  PrintStream(s.getOutputStream());
            out.println(
" ICM say Hello to UCGW! " );
            out.close();
            s.close();
        }
    }
}

 

public   class  SSLClient1 {

    
public   static   void  main(String args[])  throws  Exception {
        SSLContext sslContext 
=  SSLContext.getInstance(PROTOCOL);
        KeyManager[] km 
=  TLSSocket.createKeyManagers(keyStoreType, UCGW_KEYSTORE);
        TrustManager[] tm 
=  TLSSocket.createTrustManagers(keyStoreType, UCGW_KEYSTORE);
        SecureRandom random 
=  SecureRandom.getInstance(SHA1PRNG);
        sslContext.init(km, tm, random);
        SSLSocketFactory factory 
=  sslContext.getSocketFactory();

        System.out.println(
" TLS Client, Connecting to server  "   +  IP  +   " "   +  SSLPORT);
        SSLSocket socket 
=  (SSLSocket) factory.createSocket(IP, SSLPORT);
        socket.setUseClientMode(
true );

        BufferedReader in 
=   new  BufferedReader( new  InputStreamReader(socket.getInputStream()));
        String x 
=  in.readLine();
        System.out.println(x);
        in.close();
    }
}


三 Summary
ICM和UCGW共同信任CA,各自持有CA根证书和CA签发的自身证书,通过TLS协议实现传输层的安全通讯。
双向信任的两方无需持有对方证书。

四 EasterEgg
运行结果:
服务器端:

SSL Server is started.
client端:
ICM say Hello to UCGW!


网络包分析(工具:Wireshark)

1.抓取本地通信:route add 192.168.225.166 mask 255.255.255.255 192.168.225.254 metric 1

Connection-specific DNS Suffix  . :
IP Address. . . . . . . . . . . . : 192.168.225.166
Subnet Mask . . . . . . . . . . . : 255.255.255.0
IP Address. . . . . . . . . . . . : fe80::225:64ff:feb3:88dc%4
Default Gateway . . . . . . . . . : 192.168.225.254


2.设置过滤器

Filter:
ip.addr==192.168.225.166

Decode As:
transport = SSL

Filter:
ip.addr==192.168.225.166&&ssl


3.结果和分析


测试完毕 请删除本地IP:(reference: http://hi.baidu.com/btb368/blog/item/098d36acfbc837014b36d6cd.html)

route delete 192.168.225.166

Export File:
No.     Time        Source                Destination           Protocol Info
    
217   12.022322     192.168 . 225.166         192.168 . 225.166        SSLv2    Client Hello
Transmission Control Protocol, 
Src Port: prp ( 2091 ), Dst Port:  9527  ( 9527 ) , Seq:  1 , Ack:  1 , Len:  103
Secure Socket Layer
    SSLv2 Record Layer: Client Hello

No.     Time        Source                Destination           Protocol Info
    
219   12.024335     192.168 . 225.166         192.168 . 225.166        TLSv1    Server Hello, Certificate, Server Hello Done
Transmission Control Protocol, 
Src Port:  9527  ( 9527 ), Dst Port: prp ( 2091 ) , Seq:  1 , Ack:  104 , Len:  1210
Secure Socket Layer
    TLSv1 Record Layer: Handshake Protocol: Multiple Handshake Messages

No.     Time        Source                Destination           Protocol Info
    
221   12.036842     192.168 . 225.166         192.168 . 225.166        TLSv1    Client Key Exchange
Transmission Control Protocol, 
Src Port: prp ( 2091 ), Dst Port:  9527  ( 9527 ) , Seq:  104 , Ack:  1211 , Len:  139
Secure Socket Layer
    TLSv1 Record Layer: Handshake Protocol: Client Key Exchange
 
No.     Time        Source                Destination           Protocol Info
    
225   12.161312     192.168 . 225.166         192.168 . 225.166        TLSv1    Change Cipher Spec, Encrypted Handshake Message
Transmission Control Protocol, 
Src Port: prp ( 2091 ), Dst Port:  9527  ( 9527 ) , Seq:  243 , Ack:  1211 , Len:  43
Secure Socket Layer
    TLSv1 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
    TLSv1 Record Layer: Handshake Protocol: Encrypted Handshake Message

No.     Time        Source                Destination           Protocol Info
    
227   12.165380     192.168 . 225.166         192.168 . 225.166        TLSv1    Change Cipher Spec
Transmission Control Protocol, 
Src Port:  9527  ( 9527 ), Dst Port: prp ( 2091 ) , Seq:  1211 , Ack:  286 , Len:  6
Secure Socket Layer
    TLSv1 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec

No.     Time        Source                Destination           Protocol Info
    
229   12.165965     192.168 . 225.166         192.168 . 225.166        TLSv1    Encrypted Handshake Message, Application Data, Application Data, Encrypted Alert
Transmission Control Protocol, 
Src Port:  9527  ( 9527 ), Dst Port: prp ( 2091 ) , Seq:  1217 , Ack:  286 , Len:  126
Secure Socket Layer
    TLSv1 Record Layer: Handshake Protocol: Encrypted Handshake Message
    TLSv1 Record Layer: Application Data Protocol: Application Data
    TLSv1 Record Layer: Application Data Protocol: Application Data
    TLSv1 Record Layer: Encrypted Alert

No.     Time        Source                Destination           Protocol Info
    
233   12.166930     192.168 . 225.166         192.168 . 225.166        TLSv1    Encrypted Alert
Transmission Control Protocol, 
Src Port: prp ( 2091 ), Dst Port:  9527  ( 9527 ) , Seq:  286 , Ack:  1344 , Len:  23
Secure Socket Layer
    TLSv1 Record Layer: Encrypted Alert

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值