자바에서 SSL/TLS를 사용하는 방법은 무엇인가요?
자바(Java)에서 SSL/TLS를 사용하는 방법에 대해 설명드리겠습니다.
SSL(Secure Sockets Layer)과 TLS(Transport Layer Security)는 네트워크 통신의 보안을 위해 데이터를 암호화하는 프로토콜로, 자바에서는 주로 HTTPS 통신이나 소켓 통신 시 SSL/TLS를 적용하여 보안을 강화합니다.
--- 1. 자바에서 SSL/TLS란? 자바는 기본적으로 `javax.net.ssl` 패키지를 통해 SSL/TLS 기능을 제공합니다.
이를 사용하면 서버와 클라이언트 간에 암호화된 통신을 쉽게 구현할 수 있습니다.
또한, 자바 최신 버전에서는 기본적으로 TLS를 지원하며, SSL은 보안상 취약점이 있어 TLS 사용이 권장됩니다.
--- 2. SSL/TLS 적용 방법 2.1. HTTPS 통신 시 자바에서 HTTPS 프로토콜을 사용하고자 할 때는 보통 `HttpsURLConnection` 클래스를 이용합니다.
HTTPS 연결은 기본적으로 SSL/TLS를 사용합니다.
```java URL url = new URL("https://example.com"); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); conn.setRequestMethod("GET"); int responseCode = conn.getResponseCode(); System.out.println("Response Code : " + responseCode); BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); String inputLine; StringBuffer response = new StringBuffer(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } in.close(); System.out.println(response.toString()); ``` 이때, 자바는 기본 신뢰 저장소(truststore)에 있는 인증서를 사용하여 서버 인증서를 검증합니다.
2.2. 커스텀 신뢰 저장소(truststore) 및 키 저장소(keystore) 사용 - 키 저장소(Keystore): 서버 또는 클라이언트 자신의 개인키와 인증서를 저장 - 신뢰 저장소(Truststore): 상대방의 인증서를 신뢰하는 저장소 (보통 CA 인증서 포함) 예를 들어 자체 서명된 인증서를 사용할 때는 신뢰 저장소를 직접 지정해야 할 수 있습니다.
```java System.setProperty("javax.net.ssl.keyStore", "/path/to/keystore.jks"); System.setProperty("javax.net.ssl.keyStorePassword", "keystorepassword"); System.setProperty("javax.net.ssl.trustStore", "/path/to/truststore.jks"); System.setProperty("javax.net.ssl.trustStorePassword", "truststorepassword"); ``` 2.3. SSLServerSocket과 SSLSocket 사용하기 서버와 클라이언트 모두 SSL/TLS 소켓 통신을 직접 구현할 때는 다음과 같이 `SSLServerSocket`과 `SSLSocket`을 사용합니다.
SSL 서버 예제 ```java import javax.net.ssl.*; import java.io.*; import java.security.KeyStore; public class SSLServer { public static void main(String[] args) throws Exception { // 키 저장소 로드 KeyStore keyStore = KeyStore.getInstance("JKS"); FileInputStream keyStoreIS = new FileInputStream("serverkeystore.jks"); keyStore.load(keyStoreIS, "password".toCharArray()); // 키 매니저 팩토리 초기화 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(keyStore, "password".toCharArray()); // SSL 컨텍스트 초기화 SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(kmf.getKeyManagers(), null, null); // SSL 서버 소켓 팩토리 생성 SSLServerSocketFactory ssf = sslContext.getServerSocketFactory(); SSLServerSocket serverSocket = (SSLServerSocket) ssf.createServerSocket(8443); System.out.println("SSL Server Started and listening on port 8443"); SSLSocket clientSocket = (SSLSocket) serverSocket.accept(); BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); String line; while ((line = in.readLine()) != null) { System.out.println("Received: " + line); out.println("Echo: " + line); } clientSocket.close(); serverSocket.close(); } } ``` SSL 클라이언트 예제 ```java import javax.net.ssl.*; import java.io.*; import java.security.KeyStore; public class SSLClient { public static void main(String[] args) throws Exception { // 신뢰 저장소 로드 (서버 인증서 신뢰) KeyStore trustStore = KeyStore.getInstance("JKS"); FileInputStream trustStoreIS = new FileInputStream("clienttruststore.jks"); trustStore.load(trustStoreIS, "password".toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(trustStore); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, tmf.getTrustManagers(), null); SSLSocketFactory ssf = sslContext.getSocketFactory(); SSLSocket socket = (SSLSocket) ssf.createSocket("localhost", 8443); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out.println("Hello Server!"); System.out.println("Server says: " + in.readLine()); socket.close(); } } ``` --- 3. 키스토어 및 트러스트스토어 생성 및 관리 - `keytool` 유틸리티를 사용하여 키스토어, 트러스트스토어 생성 - 자체 서명된 인증서 생성, CSR 발급 가능 - 예: ```bash keytool -genkeypair -alias serverkey -keyalg RSA -keysize 2048 -keystore serverkeystore.jks -validity 365 keytool -exportcert -alias serverkey -file servercert.cer -keystore serverkeystore.jks keytool -importcert -alias servercert -file servercert.cer -keystore clienttruststore.jks ``` --- 4. 요약 - 자바에서 SSL/TLS는 `javax.net.ssl` 패키지를 활용해 구현 - HTTPS 연결은 기본적으로 SSL/TLS를 사용하며 `HttpsURLConnection`으로 간단하게 사용할 수 있음 - 커스텀 인증서 사용 시 키스토어와 트러스트스토어를 설정해야 함 - 서버/클라이언트 간의 SSL/TLS 소켓 통신은 `SSLServerSocket`과 `SSLSocket`을 통해 구현 가능 - 인증서와 키 관리는 `keytool`을 통해 수행 --- 필요에 따라 추가 라이브러리(예: BouncyCastle)를 활용하거나 더 높은 수준의 HTTP 클라이언트를 (예: Apache HttpClient, OkHttp) SSL 환경에서 쓸 수도 있습니다.
하지만 기본 자바 환경만으로도 SSL/TLS를 충분히 구현하고 활용 가능합니다.