SSL 的 java 实现
?
轉載自: http://blog.csdn.net/chw1989/article/details/7584995
實現(xiàn)技術:
JSSE(Java Security Socket Extension)
是Sun為了解決在Internet上的實現(xiàn)安全信息傳輸?shù)慕鉀Q方案。它實現(xiàn)了SSL和 TSL(傳輸層安全)協(xié)議。在JSSE中包含了數(shù)據(jù)加密,服務器驗證,消息完整性和客戶端驗證等技術。通過使用JSSE,可以在Client和 Server之間通過TCP/IP協(xié)議安全地傳輸數(shù)據(jù)。
?
為了實現(xiàn)消息認證。
Server需要:
1)KeyStore: 其中保存服務端的私鑰
2)Trust KeyStore:其中保存客戶端的授權證書
Client需要:
1)KeyStore:其中保存客戶端的私鑰
2)Trust KeyStore:其中保存服務端的授權證書
?
使用Java自帶的keytool命令,去生成這樣信息文件:
1)生成服務端私鑰,并且導入到服務端KeyStore文件中
生成一個CA證書,在命令行下執(zhí)行:
keytool -genkey -alias serverkey -keystore kserver.keystore?
???
???? 第一個參數(shù)是要生成的證書的名字;第二個參數(shù)是證書的別名。rsa指明了我們使用的加密方法。
系統(tǒng)會要求輸入證書發(fā)放者的信息,逐項輸入即可。
???? 系統(tǒng)生成的文件名將會和證書名相同。證書可以提交給權威CA認證組織審核,如果通過審核,組織會提供信任擔保,向客戶擔保你的連接是安全的。當然這不是必須的。在我們的例子中會把證書直接打包到客戶端程序中,保證客戶端是授權用戶,避免偽造客戶,所以不需要提交審核。
生成后的結果:
keytool -genkey -keystore SSLKey -keyalg rsa -alias SSL 指定了使用RSA 加解密的方式
?
2)根據(jù)私鑰,導出服務端證書,生成server .crt 文件。keytool -export -alias serverkey -keystore kserver.keystore -file server.crt
注意: -alias 和 -keystore 要相同,
crt 文件是公鑰,用來解密,用來解密的要導入對方的trust 賬戶中。
?
3)將服務端證書,導入到客戶端的Trust KeyStore中
keytool -import -alias serverkey -file server.crt -keystore tclient.keystore
采用同樣的方法,生成客戶端的私鑰,客戶端的證書,并且導入到服務端的Trust KeyStore中
1)keytool -genkey -alias clientkey -keystore kclient.keystore?
2)keytool -export -alias clientkey -keystore kclient.keystore -file client.crt
--生成客戶端的證書
3)keytool -import -alias clientkey -file client.crt -keystore tserver.keystore
--導入到服務端的Trust KeyStore中
?
Server端代碼:
package ssl; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.security.KeyStore; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.TrustManagerFactory; /** * * @author Leo */ public class Server implements Runnable{ private static final int DEFAULT_PORT = 7777; private static final String SERVER_KEY_STORE_PASSWORD = "123456"; private static final String SERVER_TRUST_KEY_STORE_PASSWORD = "123456"; private SSLServerSocket serverSocket; /** * 啟動程序 * * @param args */ public static void main(String[] args) { Server server = new Server(); server.init(); Thread thread = new Thread(server); thread.start(); } public synchronized void start() { if (serverSocket == null) { System.out.println("ERROR"); return; } while (true) { try { Socket s = serverSocket.accept(); InputStream input = s.getInputStream(); OutputStream output = s.getOutputStream(); BufferedInputStream bis = new BufferedInputStream(input); BufferedOutputStream bos = new BufferedOutputStream(output); byte[] buffer = new byte[20]; bis.read(buffer); System.out.println("------receive:--------"+new String(buffer).toString()); bos.write("yes".getBytes()); bos.flush(); s.close(); } catch (Exception e) { System.out.println(e); } } } public void init() { try { SSLContext ctx = SSLContext.getInstance("SSL"); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); KeyStore ks = KeyStore.getInstance("JKS"); KeyStore tks = KeyStore.getInstance("JKS"); //keystore 與 trust key store ks.load(new FileInputStream("src/ssl/kserver.keystore"), SERVER_KEY_STORE_PASSWORD.toCharArray()); tks.load(new FileInputStream("src/ssl/tserver.keystore"), SERVER_TRUST_KEY_STORE_PASSWORD.toCharArray()); kmf.init(ks, SERVER_KEY_STORE_PASSWORD.toCharArray()); tmf.init(tks); ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); serverSocket = (SSLServerSocket) ctx.getServerSocketFactory().createServerSocket(DEFAULT_PORT); serverSocket.setNeedClientAuth(true); } catch (Exception e) { System.out.println(e); } } public void run() { // TODO Auto-generated method stub start(); } }?Client
package ssl; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.KeyStore; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.TrustManagerFactory; /** * SSL Client * * @author Leo */ public class Client { private static final String DEFAULT_HOST = "127.0.0.1"; private static final int DEFAULT_PORT = 7777; private static final String CLIENT_KEY_STORE_PASSWORD = "123456"; private static final String CLIENT_TRUST_KEY_STORE_PASSWORD = "123456"; private SSLSocket sslSocket; /** * 啟動客戶端程序 * * @param args */ public static void main(String[] args) { Client client = new Client(); client.init(); client.process(); } public void process() { if (sslSocket == null) { System.out.println("ERROR"); return; } try { InputStream input = sslSocket.getInputStream(); OutputStream output = sslSocket.getOutputStream(); BufferedInputStream bis = new BufferedInputStream(input); BufferedOutputStream bos = new BufferedOutputStream(output); bos.write("1234567890".getBytes()); bos.flush(); byte[] buffer = new byte[20]; bis.read(buffer); System.out.println(new String(buffer)); sslSocket.close(); } catch (IOException e) { System.out.println(e); } } public void init() { try { SSLContext ctx = SSLContext.getInstance("SSL"); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); KeyStore ks = KeyStore.getInstance("JKS"); KeyStore tks = KeyStore.getInstance("JKS"); //key store 與 trust key store ks.load(new FileInputStream("src/ssl/kclient.keystore"), CLIENT_KEY_STORE_PASSWORD.toCharArray()); tks.load(new FileInputStream("src/ssl/tclient.keystore"), CLIENT_TRUST_KEY_STORE_PASSWORD.toCharArray()); kmf.init(ks, CLIENT_KEY_STORE_PASSWORD.toCharArray()); tmf.init(tks); ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); sslSocket = (SSLSocket) ctx.getSocketFactory().createSocket(DEFAULT_HOST, DEFAULT_PORT); } catch (Exception e) { System.out.println(e); } } }?如此,就完成了服務端和客戶端之間的基于身份認證的交互。
client采用kclient.keystore中的clientkey私鑰進行數(shù)據(jù)加密,發(fā)送給server。
server采用tserver.keystore中的client.crt證書(包含了clientkey的公鑰)對數(shù)據(jù)解密,如果解密成功,證明消息來自client,進行邏輯處理。
server采用kserver.keystore中的serverkey私鑰進行數(shù)據(jù)加密,發(fā)送給client。
client采用tclient.keystore中的server.crt證書(包含了serverkey的公鑰)對數(shù)據(jù)解密,如果解密成功,證明消息來自server,進行邏輯處理。
如果過程中,解密失敗,那么證明消息來源錯誤。不進行邏輯處理。這樣就完成了雙向的身份認證。
?
總結
以上是生活随笔為你收集整理的SSL 的 java 实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Dojo query 库
- 下一篇: java线程安全问题之静态变量、实例变量