首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java SSL/TLS 安全通訊協議全解析:從原理到 JSSE 實戰

     編輯:Java 相關知識

SSL/TLS 協議定位

位於 TCP/IP 與應用層協議之間,為數據通訊提供加密、認證、完整性保護。
SSL (Secure Sockets Layer) → TLS (Transport Layer Security) 為其標準化後繼版本。

協議分層架構

  1. 記錄協議:建立在可靠傳輸層(TCP)之上,提供數據封裝、壓縮、加密
  2. 握手協議:建立在記錄協議之上,完成身份認證、算法協商、密鑰交換

兩種認證模式

完整握手流程(15 步)

SSL/TLS 握手流程圖

  1. ClientHello:客戶端發送支持的版本、加密套件、壓縮方法
  2. ServerHello:服務器選定參數返回
  3. SendCertificate(可選):服務器發送證書
  4. RequestCertificate(可選,雙向):服務器請求客戶端證書
  5. ServerHelloDone:服務器協商結束
  6. ResponseCertificate(可選,雙向):客戶端發送證書
  7. ClientKeyExchange:客戶端用服務器公鑰加密預主密鑰發送
  8. CertificateVerify(可選,雙向):客戶端簽名驗證持有私鑰
  9. CreateSecretKey:雙方從預主密鑰導出會話密鑰
  10. ChangeCipherSpec (C→S):客戶端切換加密模式
  11. Finished (C→S):客戶端驗證握手完整性
  12. ChangeCipherSpec (S→C):服務器切換加密模式
  13. Finished (S→C):服務器驗證握手完整性
  14. Encrypted Data:雙方用會話密鑰對稱加密通訊
  15. ClosedConnection:任意一方發送 close_notify 結束

核心密碼學概念速查

模式流程關鍵點
單向認證客戶端驗證服務器證書,服務器不驗證客戶端。HTTPS 典型場景。
雙向認證雙方交換證書並互相驗證。金融、企業級應用常用。
概念說明常見算法
對稱加密雙方用同一密鑰,效率高DES, 3DES, RC2, RC4, AES
非對稱加密公鑰加密/私鑰解密,用於密鑰交換RSA, DH, ECC
公鑰證書CA 簽發,綁定身份與公鑰,防偽造X.509, 證書鏈
加密哈希檢測數據篡改MD5, SHA-1/256
HMAC基於密鑰的哈希,防篡改+防偽造HMAC-MD5, HMAC-SHA
數字簽名私鑰加密哈希,不可抵賴RSA-SHA256, ECDSA

JSSE (Java Secure Socket Extension) 核心組件

  • SSLSocket / SSLServerSocket:安全套接字,API 與普通 Socket 一致
  • SSLEngine:非阻塞式 SSL/TLS 引擎,用於 NIO
  • SSLContext:套接字工廠上下文,持有密鑰管理器、信任管理器
  • KeyManager / TrustManager:密鑰管理 / 信任決策
  • KeyStore / TrustStore:密鑰庫 / 信任庫(JKS/PKCS12 格式)

實戰:構建 SSL 客戶端/服務器

服務器端

public class SSLServer {
    private static final String USER = "principal", PWD = "credential";
    private static final String SECRET = "Confidential content from server X";

    public static void main(String[] args) throws Exception {
        SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
        SSLServerSocket serverSocket = (SSLServerSocket) factory.createServerSocket(7070);

        while (true) {
            SSLSocket socket = (SSLSocket) serverSocket.accept();
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));

            String user = in.readLine();
            String pwd = in.readLine();

            if (USER.equals(user) && PWD.equals(pwd)) {
                out.println("Welcome, " + user);
                out.println(SECRET);
            } else {
                out.println("Authentication failed");
            }
            out.flush(); in.close(); out.close(); socket.close();
        }
    }
}

客戶端

public class SSLClient {
    public static void main(String[] args) throws IOException {
        SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
        SSLSocket socket = (SSLSocket) factory.createSocket("localhost", 7070);

        PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
        out.println("principal"); out.println("credential"); out.flush();

        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        System.out.println(in.readLine());
        System.out.println(in.readLine());

        in.close(); out.close(); socket.close();
    }
}

關鍵:密鑰庫配置(否則握手失敗)

默認無配置會報 no cipher suites in common / handshake_failure。需用 keytool 生成雙向信任鏈:

# 1. 生成客戶端密鑰對
keytool -genkey -alias sslclient -keystore sslclientkeys

# 2. 導出客戶端證書
keytool -export -alias sslclient -keystore sslclientkeys -file sslclient.cer

# 3. 生成服務器密鑰對
keytool -genkey -alias sslserver -keystore sslserverkeys
keytool -export -alias sslserver -keystore sslserverkeys -file sslserver.cer

# 4. 交叉導入信任庫
keytool -import -alias sslclient -keystore sslservertrust -file sslclient.cer
keytool -import -alias sslserver -keystore sslclienttrust -file sslserver.cer

啟動命令(指定密鑰庫系統屬性)

# 服務器
java -Djavax.net.ssl.keyStore=sslserverkeys -Djavax.net.ssl.keyStorePassword=123456 \
     -Djavax.net.ssl.trustStore=sslservertrust -Djavax.net.ssl.trustStorePassword=123456 \
     SSLServer

# 客戶端
java -Djavax.net.ssl.keyStore=sslclientkeys -Djavax.net.ssl.keyStorePassword=123456 \
     -Djavax.net.ssl.trustStore=sslclienttrust -Djavax.net.ssl.trustStorePassword=123456 \
     SSLClient

運行結果

Welcome, principal
This is confidential content from server X, for your eye!

生產環境最佳實踐

  • 使用 CA 簽發的正式證書,而非自簽名
  • 啟用強加密套件,禁用 SSLv3、TLS 1.0/1.1
  • 配置 OCSP Stapling、HSTS、Certificate Transparency
  • 定期輪換密鑰,監控證書過期
  • 考慮使用 Netty/Tomcat/Undertow 等成熟服務器組件,而非手寫 SSLSocket

JSSE 讓 Java 開發者以極低成本擁有企業級傳輸層安全能力,掌握其原理與配置,是構建安全系統的必修課。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved