개발

ssl 을 이용한 에코 서버 클라이언트 예제

에드몽단테스 2009. 10. 1. 17:04

[서버]
import javax.net.ssl.*;
   import javax.net.*;
   import java.io.*;
   import java.net.*;

   public class EchoServer {
     private static final int PORT_NUM = 6789;
     public static void main(String args[]) {
       ServerSocketFactory serverSocketFactory =
         SSLServerSocketFactory.getDefault();
       ServerSocket serverSocket = null;
       try {
         serverSocket =
           serverSocketFactory.createServerSocket(PORT_NUM);
       } catch (IOException ignored) {
         System.err.println("Unable to create server");
         System.exit(-1);
       }
       while(true) {
         Socket socket = null;
         try {
           socket = serverSocket.accept();
           InputStream is = socket.getInputStream();
           BufferedReader br = new BufferedReader(
             new InputStreamReader(is, "US-ASCII"));
           OutputStream os = socket.getOutputStream();
           Writer writer =
             new OutputStreamWriter(os, "US-ASCII");
           PrintWriter out = new PrintWriter(writer, true);
           String line = null;
           while ((line = br.readLine()) != null) {
             out.println(line);
           }
         } catch (IOException exception) {
           exception.printStackTrace();
         } finally {
           if (socket != null) {
             try {
               socket.close();
             } catch (IOException ignored) {
             }
           }
         }
       }
     }
   }


그러나 이 프로그램을 구동하기 전에 한가지 문제가 있다. 인증서가 없다는 것이다. 특정 인증서 없이 이 프로그램을 구동하면 SSLException을 얻게 된다.

   javax.net.ssl.SSLException: No available certificate corresponds to the SSL cipher suites which are enabled.
      at com.sun.net.ssl.internal.ssl.SSLServerSocketImpl.a(DashoA6275)
      at com.sun.net.ssl.internal.ssl.SSLServerSocketImpl.accept(DashoA6275)
      at EchoServer.main(EchoServer.java:21)


SDK와 함께 제공되는 키툴(keytool) 프로그램으로 인증서를 생성할 수 있다. 키페어(keypair)를 생성하는 -genkey 옵션, 키 스토어 파일(key store file)을 지정하는 -keystore옵션, 암호 알고리즘을 지정하는 -keyalg 옵션이 포함된 keytool 커멘드를 실행하자.

   keytool -genkey -keystore testStore -keyalg RSA


실행
 
    java -Djavax.net.ssl.keyStore=testStore -Djavax.net.ssl.keyStorePassword=tutorial EchoServer




[클라이언트]
 import javax.net.ssl.*;
   import javax.net.*;
   import java.io.*;
   import java.net.*;

   public class EchoClient {
     private static int PORT_NUM = 6789;
     private static String host = "localhost";
     public static void main(String args[])
         throws IOException {
       SocketFactory socketFactory =
         SSLSocketFactory.getDefault();
       Socket socket = socketFactory.createSocket(
         host, PORT_NUM);

       BufferedReader br = new BufferedReader(
         new InputStreamReader(System.in, "US-ASCII"));
       PrintWriter out = new PrintWriter(
         new OutputStreamWriter(
           socket.getOutputStream(), "US-ASCII"), true);

       BufferedReader socketBr = new BufferedReader(
         new InputStreamReader(
           socket.getInputStream(), "US-ASCII"));

       String string = null;
       System.out.print("First line: ");
       while (!(string = br.readLine()).equals("")) {
         out.println(string);
         String line = socketBr.readLine();
         System.out.println("Got Back: " + line);
         System.out.print("Next line: ");
       }
       socket.close();
     }
   }


클라이언트를 컴파일하자. 클라이언트를 구동하기 위해서는 서버를 시작할 때 지정한 것과 같은 인증서를 지정해야한다. 그렇지 않으면 클라이언트가 서버에 연결하기 위해 시도할 때 서버에 SSLHandshakeException이 발생한다.

   javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake

클라이언트를 시작할 때 키 스토어 대신 트러스트 스토어로서 인증서를 참조해보자.

 


실행

   java -Djavax.net.ssl.trustStore=testStore -Djavax.net.ssl.trustStorePassword=tutorial EchoClient


출처 : http://sdnkorea.com

반응형