1. 程式人生 > >java SSL加密傳輸

java SSL加密傳輸

網路傳輸是存在風險的,因此對服服務端和客戶端進行安全校驗和傳輸資訊的加密就顯得非常的重要。

上面一句有點拗口,簡單解釋如下文:

  當客戶使用SSL向站點伺服器傳送請求時,伺服器向客戶端傳送一個證書,客戶使用已安裝的證書,驗證伺服器身份,然後檢查IP地址(主機名)與客戶端連線的主機是否匹配。客戶生成可以用來對話的私鑰(稱為會話金鑰),然後用服務者的公鑰對它進行加密並將它傳送到服務者。服務者用自己的私鑰解密,然後用該資訊和客戶端一樣的私有會話金鑰。通常在這個階段使用RSA演算法。 
隨後,客戶端和伺服器端使用私有會話金鑰和私鑰演算法(通常是RC4)進行通訊。使用另一個金鑰的訊息認證碼來確保訊息的完整性。

接下來,就一一介紹下如何進行SSL加密的socket通訊開發

一、建立服務端金鑰

命令列執行

keytool.exe -genkeypair -v -alias sslsocket -keyalg RSA -keystore e:\sslsocket.keystore 

出現提示輸入密碼

複製程式碼
輸入keystore密碼:
        再次輸入新密碼:
        您的名字與姓氏是什麼?
          [Unknown]:  lwx
        您的組織單位名稱是什麼?
          [Unknown]:  newland
        您的組織名稱是什麼?
          [Unknown]:  bomc
        您所在的城市或區域名稱是什麼?
          [Unknown]:  fz
        您所在的州或省份名稱是什麼?
          [Unknown]:  fj
        該單位的兩字母國家程式碼是什麼
          [Unknown]:  zh
        CN
=lwx, OU=newland, O=bomc, L=fz, ST=fj, C=zh 正確嗎? [否]: y
複製程式碼

上述資訊只是為了幫助客戶端校驗服務端證書的資訊,測試的時候只需要注意最後提示是否正確的時候 輸入y 即可。

接著出現下面資訊

正在為以下物件生成 1,024 位 RSA 金鑰對和自簽名證書 (SHA1withRSA)(有效期為 90 天
        ):
                 CN=lwx, OU=newland, O=bomc, L=fz, ST=fj, C=zh
        輸入<sslsocket>的主密碼
                (如果和 keystore 密碼相同,按回車):
        [正在儲存 e:\sslsocket.keystore]

生成金鑰sslsocket.keystore後,可以通過下面的命令來檢視

keytool -list  -v -keystore e:\sslsocket.keystore -storepass 123456    

看到的資訊就是之前我們輸入的內容了 

複製程式碼
Keystore 型別: JKS
        Keystore 提供者: SUN
        
        您的 keystore 包含 1 輸入
        
        別名名稱: sslsocket
        建立日期: 2013-5-8
        項型別: PrivateKeyEntry
        認證鏈長度: 1
        認證 [1]:
        所有者:CN=lwx, OU=newland, O=bomc, L=fz, ST=fj, C=zh
        簽發人:CN=lwx, OU=newland, O=bomc, L=fz, ST=fj, C=zh
        序列號:5189a30d
        有效期: Wed May 08 08:57:49 CST 2013 至Tue Aug 06 08:57:49 CST 2013
        證書指紋:
                 MD5:51:5E:1A:57:1B:B9:18:3A:9B:05:F7:13:E5:06:AB:F0
                 SHA1:11:0E:C8:8B:46:1F:27:FA:12:95:95:4E:1E:29:E7:27:50:2E:E9:48
                 簽名演算法名稱:SHA1withRSA
                 版本: 3
        
複製程式碼

二、生成服務端證書

keytool.exe -exportcert -v -alias sslsocket -file e:\sslsocket.cer -keystore e:\sslsocket.keystore
e:\sslsocket.cer 即我們服務端的證書,到這裡應該就比較熟悉了
檢視證書資訊的命令
keytool.exe -printcert -v -file e:\sslsocket.cer

出現的結果如下

複製程式碼
    所有者:CN=lwx, OU=newland, O=bomc, L=fz, ST=fj, C=zh
        簽發人:CN=lwx, OU=newland, O=bomc, L=fz, ST=fj, C=zh
        序列號:5189a30d
        有效期: Wed May 08 08:57:49 CST 2013 至Tue Aug 06 08:57:49 CST 2013
        證書指紋:
                 MD5:51:5E:1A:57:1B:B9:18:3A:9B:05:F7:13:E5:06:AB:F0
                 SHA1:11:0E:C8:8B:46:1F:27:FA:12:95:95:4E:1E:29:E7:27:50:2E:E9:48
                 簽名演算法名稱:SHA1withRSA
                 版本: 3
複製程式碼

三、生成客戶端金鑰

有了服務端證書之後,自然就是通過密碼來生成客戶端的金鑰了,命令如下

keytool.exe -importcert -v -alias sslsocketcer -file e:\sslsocket.cer -keystore e:\sslclient.keystore
e:\sslclient.keystore 就是客戶端的金鑰了。

關於keytool的更多資訊可以參考這裡:http://blog.chinaunix.net/uid-17102734-id-2830223.html

四、開發程式

為了測試 我將服務端和客戶端的證書放到工程目錄下

服務端程式碼

複製程式碼
  1 /**
  2  * @author  [email protected]
  3  * @TODO    java執行緒開發之四 SSL加密
  4  * 開發步驟
  5  * 1.生成服務端金鑰
  6  * 2.匯出服務端證書
  7  * 3.生成客戶端金鑰
  8  * 4.程式開發測試
  9  * 關於證書的生成請參考readme.txt
 10  * 參考資料:http://chrui.iteye.com/blog/1018778
 11  * @version 1.0
 12  * @date 2013-5-7 23:22:45    
 13  * @update 2013-5-8 10:22:45    
 14  * @blgos http://www.cnblogs.com/draem0507
 15  */
 16 
 17 public class ServerTest {
 18     private ServerSocket serverSocket;
 19     private final static char[] password="123456".toCharArray();
 20     private SSLContext context;
 21     URL url = Thread.currentThread().getContextClassLoader().getResource("sslsocket.keystore");
 22     String path = url.toString();
 23     private InputStream inputStream;
 24     
 25 
 26     public ServerTest() {
 27         inputStream=this.getClass().getResourceAsStream("/sslsocket.keystore");
 28         initContext();
 29         try {
 30             //直接執行會報 javax.net.ssl.SSLException:
 31             //ServerSocketFactory factory=     SSLServerSocketFactory.getDefault();
 32             ServerSocketFactory factory=     context.getServerSocketFactory();
 33 //            serverSocket = new ServerSocket(10000);
 34             serverSocket=factory.createServerSocket(10000);
 35             while (true) {
 36                 Socket socket = serverSocket.accept();
 37                 new ReceiveSocket(socket).start();
 38             }
 39         } catch (IOException e) {
 40             // TODO Auto-generated catch block
 41             e.printStackTrace();
 42         }
 43 
 44     }
 45     
 46     //ssl 上下文物件的初始化
 47     private void initContext() {
 48         try {
 49             KeyStore store=KeyStore.getInstance("JKS");
 50             store.load(inputStream, password);
 51             KeyManagerFactory factory=KeyManagerFactory.getInstance("SunX509");
 52             factory.init(store,password);
 53             KeyManager []keyManagers=factory.getKeyManagers();
 54             context=SSLContext.getInstance("SSL");
 55             context.init(keyManagers, null    , null);
 56         } catch (KeyStoreException e) {
 57             // TODO Auto-generated catch block
 58             e.printStackTrace();
 59         } catch (NoSuchAlgorithmException e) {
 60             // TODO Auto-generated catch block
 61             e.printStackTrace();
 62         } catch (CertificateException e) {
 63             // TODO Auto-generated catch block
 64             e.printStackTrace();
 65         } catch (FileNotFoundException e) {
 66             // TODO Auto-generated catch block
 67             e.printStackTrace();
 68         } catch (IOException e) {
 69             // TODO Auto-generated catch block
 70             e.printStackTrace();
 71         } catch (UnrecoverableKeyException e) {
 72             // TODO Auto-generated catch block
 73             e.printStackTrace();
 74         } catch (KeyManagementException e) {
 75             // TODO Auto-generated catch block
 76             e.printStackTrace();
 77         }
 78         
 79     }
 80 
 81     public static void main(String[] args) {
 82         new ServerTest();
 83 
 84     }
 85 
 86     private class ReceiveSocket extends Thread {
 87         private Socket socket;
 88 
 89         public ReceiveSocket(Socket socket) {
 90             this.socket = socket;
 91         }
 92 
 93         private ObjectInputStream reader;
 94         private ObjectOutputStream writer;
 95 
 96         @Override
 97         public void run() {
 98 
 99             try {
100                 reader=new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
101                 //writer=new ObjectOutputStream(socket.getOutputStream());
102                 // 開啟無限迴圈 監控訊息
103                 
104                     //java.io.EOFException
105                 Object obj=    reader.readObject();
106                     if(obj!=null)
107                     {
108                         User user =(User)obj;
109                         System.out.println("id=="+user.getId()+"\tname=="+user.getName());
110                     }
111                 //    while (true) {}
112 
113             } catch (IOException e) {
114                 // TODO Auto-generated catch block
115                 e.printStackTrace();
116             } catch (ClassNotFoundException e) {
117                 // TODO Auto-generated catch block
118                 e.printStackTrace();
119             } finally {
120                 if (null != reader) {
121                     try {
122                         reader.close();
123                     } catch (IOException e) {
124                         // TODO Auto-generated catch block
125                         e.printStackTrace();
126                     }
127                 }
128                 if (null != writer) {
129                     try {
130                         reader.close();
131                     } catch (IOException e) {
132                         // TODO Auto-generated catch block
133                         e.printStackTrace();
134                     }
135                 }
136                 try {
137                     socket.close();
138                 } catch (IOException e) {
139                     // TODO Auto-generated catch block
140                     e.printStackTrace();
141                 }
142             }
143 
144         }
145 
146     }
147 
148 }
複製程式碼

客戶端程式碼

複製程式碼
 1 public class ClientTest {
 2     private final static char[] password="123456".toCharArray();
 3     private static SSLContext context;
 4     static InputStream inputStream=ClientTest.class.getResourceAsStream("/sslclient.keystore");
 5     
 6     public static void main(String[] args) throws Exception {
 7          
 8         KeyStore ts = KeyStore.getInstance("JKS");  
 9         ts.load(inputStream, password);  
10         TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");  
11         tmf.init(ts);  
12         TrustManager [] tm = tmf.getTrustManagers();  
13         context = SSLContext.getInstance("SSL");  
14         context.init(null, tm, null);  
15         
16         //SocketFactory factory=    SSLSocketFactory.getDefault();
17         //Socket socket =factory.createSocket("localhost", 10000);
18         SocketFactory factory=    context.getSocketFactory();
19         SSLSocket socket=(SSLSocket) factory.createSocket("localhost", 10000);
20         
21         
22         //ObjectInputStream in=new ObjectInputStream(socket.getInputStream());
23         ObjectOutputStream out=new ObjectOutputStream(socket.getOutputStream());
24         
25         
26                 User user =new User();
27                 user.setId(1);
28                 user.setName("lwx_"+1);
29                 out.writeObject(user);
30                 out.flush();
31     
32             
33         socket.close();
34         
35         
36     }
37 }
複製程式碼

如果想要原始碼的話,可以到這裡來下載 http://download.csdn.net/detail/draem0507/5343534