利用 JCE (Java Cryptography Extension) 將對稱加密(AES/DES)透明套用在 Socket 流上。核心類 SecretSocket 封裝 CipherInputStream/CipherOutputStream,對上層應用完全隱藏加解密細節。
Application
│
▼
SecretSocket (extends Socket)
├─ getInputStream() → CipherInputStream → DECrypt → 原始 Socket InputStream
└─ getOutputStream() → CipherOutputStream → ENcrypt → 原始 Socket OutputStream
public class SecretSocket extends Socket {
private final Cipher encryptCipher;
private final Cipher decryptCipher;
public SecretSocket(Socket socket, SecretKey key, String algorithm) throws Exception {
super(); // 不自動連線,手動初始化
this.impl = socket.impl; // 共用底層 SocketImpl (需反射或繼承策略)
// 簡化示範:實際建議用組合而非繼承
encryptCipher = Cipher.getInstance(algorithm);
encryptCipher.init(Cipher.ENCRYPT_MODE, key);
decryptCipher = Cipher.getInstance(algorithm);
decryptCipher.init(Cipher.DECRYPT_MODE, key);
}
@Override
public InputStream getInputStream() throws IOException {
return new CipherInputStream(super.getInputStream(), decryptCipher);
}
@Override
public OutputStream getOutputStream() throws IOException {
return new CipherOutputStream(super.getOutputStream(), encryptCipher);
}
}
// Server
public class SecureServer {
public static void main(String[] args) throws Exception {
SecretKey key = KeyGenerator.getInstance("AES").generateKey(); // 實際應安全分發
try (ServerSocket server = new ServerSocket(8888)) {
while (true) {
Socket client = server.accept();
SecretSocket sec = new SecretSocket(client, key, "AES");
new Thread(() -> handle(sec)).start();
}
}
}
static void handle(SecretSocket s) {
try (BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8"));
PrintWriter out = new PrintWriter(new OutputStreamWriter(s.getOutputStream(), "UTF-8"), true)) {
String msg;
while ((msg = in.readLine()) != null) {
System.out.println("收到解密: " + msg);
out.println("Server Echo: " + msg);
}
} catch (IOException e) { e.printStackTrace(); }
}
}
// Client
public class SecureClient {
public static void main(String[] args) throws Exception {
SecretKey key = ...; // 與 Server 共享同一把鑰
try (SecretSocket s = new SecretSocket(new Socket("localhost", 8888), key, "AES");
PrintWriter out = new PrintWriter(new OutputStreamWriter(s.getOutputStream(), "UTF-8"), true);
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8"))) {
out.println("Hello Secure World");
System.out.println("Server 回應: " + in.readLine());
}
}
}
CipherInputStream/OutputStream 是 JDK 提供的「裝飾者模式」加密流,幾行代碼即可為任意 InputStream/OutputStream 增加透明加密。但自行實作安全協議極易踩坑,正式專案優先使用成熟的 TLS (JSSE/Netty SSL) 或成熟框架(Spring Security、Apache MINA/Netty SSL),僅在特殊嵌入式/舊系統無法使用 TLS 時才考慮自行封裝。