位於 TCP/IP 與應用層協議之間,為數據通訊提供加密、認證、完整性保護。
SSL (Secure Sockets Layer) → TLS (Transport Layer Security) 為其標準化後繼版本。
| 模式 | 流程關鍵點 | |
|---|---|---|
| 單向認證 | 客戶端驗證服務器證書,服務器不驗證客戶端。HTTPS 典型場景。 | |
| 雙向認證 | 雙方交換證書並互相驗證。金融、企業級應用常用。 |
| 概念 | 說明 | 常見算法 |
|---|---|---|
| 對稱加密 | 雙方用同一密鑰,效率高 | DES, 3DES, RC2, RC4, AES |
| 非對稱加密 | 公鑰加密/私鑰解密,用於密鑰交換 | RSA, DH, ECC |
| 公鑰證書 | CA 簽發,綁定身份與公鑰,防偽造 | X.509, 證書鏈 |
| 加密哈希 | 檢測數據篡改 | MD5, SHA-1/256 |
| HMAC | 基於密鑰的哈希,防篡改+防偽造 | HMAC-MD5, HMAC-SHA |
| 數字簽名 | 私鑰加密哈希,不可抵賴 | RSA-SHA256, ECDSA |
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!
JSSE 讓 Java 開發者以極低成本擁有企業級傳輸層安全能力,掌握其原理與配置,是構建安全系統的必修課。