ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 보안 소켓
    프로그래밍/Java 2021. 4. 4. 22:49
    반응형

    보안 통신

    와이파이를 사용하게되면 단말기와 무선 공유기 사이에 패킷이 전송된다. 해커가 설치한 와이파이 혹은 보안에 취약한 와이파이를 사용하게 되면 해당 공유기를 통해 통신하는 모든 데이터가 해커에게 노출된다. 

    • 스누핑(snooping) - 네트워크상에서 남의 정보를 염탐하여 불법으로 가로채는 행위. 소프트웨어 프로그램(스누퍼)을 이용하여 원격으로 다른 컴퓨터의 정보를 엿볼 수 있어, 개인적인 메신저 내용, 로그인 정보, 전자 우편 등의 정보를 몰래 획득한다. 반면, 네트워크 트래픽을 분석하기 위해 사용되기도 한다.
      • 사례
        • AT&T는 자사 비밀룸에 설치된 데이터 마이닝 장비로 패킷을 복사하여 자사 고객의 모든 인터넷 트래픽에 대한 접근을 미국 국가안보국에 제공했다. 
        • 영국 정보통신본부는 세계의 전화 및 인터넷 트래픽의 대부분이 지나가는 광섬유 케이블을 도청한다.

    이러한 인터넷 연결에 대한 더 근본적인 보안을 강화하기 위해 소켓을 암호화할 수 있다. 암호화는 수학적 알고리즘 뿐만아니라 암호화된 데이터를 주고 받기 위한 프로토콜에 대한 자세한 이해가 필요하다.

    하지만 이에 대해 비전문가이더라도 전문가들이 만든 소프트웨어를 이용하여 통신을 보안할 수 있다. 온라인 상점에서 무언가를 주문할 때마다 내부적으로 알고리즘과 프로토콜을 사용하여 트랜잭션을 암호화하고 인증하지만, 이 사실을 알 필요가 없다.

    자바 보안 소켓 확장(JSSE, Java Secure Sockets Extension)보안 소켓 계층(SSL, Secure Sockets Layer) 버전 3전송 계층 보안(TLS, Transport Layer Security) 프로토콜과 관련된 암호화 알고리즘을 사용하여 네트워크 통신을 보안한다. ,

     

    암호화 주요 용어

    • 평문(plaintext): 원본 메시지
    • 암호문(ciphertext): 코드화(암호화)된 메시지
    • 암호화(encryption): 평문을 암호문으로 변환
    • 복호화(decryption): 암호문을 평문으로 변환
    • 키(key): 암호화, 복호화 시 사용하는 가장 중요한 열쇠

     

    치환암호. 컴퓨터의 등장으로 너무 빨리 복호화됨

     

    암호화 알고리즘만으로는 현대 컴퓨터의 성능으로 너무나 빨리 복호화되어 현대 시대에서는 암호화 알고리즘에 키를 추가한 형태로 메시지를 암호화하고 있다. 

     

    일반적인 암호 요건

    • 암호 알고리즘 + 키(key)
      • 키 : 무작위 난수 
      • 제 3자가 암호 알고리즘을 알더라도 키(key)를 모르면 암호를 풀 수 없음

     

    데이터를 암호화하는 방식

    • 대칭키 암호화(Symmetric-key Cryptography)
    • 공개키 암호화(Public-key cryptography, 비대칭 암호화)

     

    대칭키 암호화

    • 메시지를 암호화/복화하하는데 같은 키를 사용한다.
    • 수신자-송신자 사이에서 같은키 사용한다.
    • 메시지 수신자에게 암호키를 먼저 보낸다. -> 키를 암호화할 순 없음 
    • 도청하고 있는 해커에게 동일한 키가 전달된다. -> 모든 대화를 읽게 됨
    • 공개키 암호화와 비교해 속도가 빠르다.
    • DES(Data Encryption Standard), AES(Advanced Encryption Standard)


    공개키 암호화 (비대칭키 암호화)

    • 메시지를 암호화/복화하하는데 다른 키를 사용한다.
    • 공개키(public key) : 데이터를 암호화하는데 사용하고 누구나 이 키에 접근할 수 있다.
    • 비밀키(private key) : 데이터를 복호화하는데 사용하고 권한을 가진 사람만 접근할 수 있다.
    • 메시지 수신자에게 공개키를 먼저 보낸다. 
    • 도청하고 있는 해커에게도 공개키가 전달된다. 
    • 메시지 송신자는 공개키로 메시지를 암호화하여 보낸다.
    • 메시지 수신자는 본인의 비밀키로만 메시지를 복화하할 수 있다. 
    • 해커는 메시지를 복호화하기 위해 개인키가 필요하기 때문에 해독하기 어렵다. 
    • ex) c = a*b로 키를 생성함.
      • 공개키 : 24, 비공개키 : 2*12 혹은 3*8 이 될 수 있음. 해커는 이 비공개키를 알아야 메시지를 해독할 수 있다. 
    • RSA(Rivest, Shamir and Adleman)

     


    SSL(Secure Socket Layer), TLS(Transport Layer Security

    • TLS 1.0의 조상은 SSL 3.0이다. 하지만 TLS라는 이름보다 SSL이라는 이름이 훨씬 많이 사용되고 있다.
    • 네스케이프에 의해서 SSL이 발명되었고, 이것이 점차 폭넓게 사용되다가 표준화 기구인 IETF의 관리로 변경되면서 TLS라는 이름으로 바뀌었다. 
    • SSL/TLS는 클라이언트가 서버에게 민감한 정보를 전달할 때 HTTPS를 이용해 안전하게 전달되도록 해준다. HTTPS는 암호화된 TLS를 이용하는 HTTP라고 보면 된다. 
    • SSL/TLS는 데이터를 암호화/복호화하여 Transport Layer로 전달한다. 

     

    SSL/TLS 동작 방법 

    1. 클라이언트에서 https:// 로 접속한다. 
    2. 서버는 CA(Certificate Authority)에서 검증받은 서버의 인증서와 공개키를 클라이언트에 전달한다. 
    3. 클라이언트는 인증서가 믿을만 한지, 해당 사이트의 인증서인지 등을 확인한다. 
    4. 클라이언트는 서버의 공개키를 이용해 메시지를 암호화한다.
    5. 서버는 개인키를 이용해 메시지를 복호화한다. 

     

    JSSE(Java Secure Sockets Extension)

    좋은 암호화 알고리즘과 프로토콜을 설계하는 일은 쉬운 일이 아니며 어떤 알고리즘과 프로토콜이 좋은지 항상 상황에 따라 다르다. 다행히도 JSSE를 사용할 경우 알고리즘 협상 방법, 키 교환 방법, 인증 방법, 데이터를 암호화를 포함한 낮은 수준의 세부 사항에 대해서 신경쓰지 않아도 된다. JSSE를 이용하여 보안 통신을 위한 통신 협상과 필요한 암호화를 투명하게 처리하는 소켓과 서버 소켓을 만들 수 있다. 

    • javax.net.ssl 보안 네트워크 통신을 위한 자바 API를 정의하는 추상 클래스이다.
    • javax.net 보안 소켓을 생성하기 위해 생성자 대신 사용되는 추상 소켓 팩토리 클래스다.
    • java.security.cert SSL에 필요한 공개키 인증서를 다루는 클래스다.

     

    보안 클라이언트 소켓 만들기

    java.net.Socket 객체를 생성하는 대신 javax.net.ssl.SSLSocketFactory로부터 createSocket() 메소드를 사용하여 소켓 객체를 얻을 수 있다. 

    SoecketFactory factory = SSLScoketFactory.getDefault();
    Socket socket =  factory.createSocket("login.ibiblio.org", 7000);

    createSocket()이 반환하는 클래스 객체는 javax.net.ssl.SSLSocket 클래스 객체이며 java.net.Socket 클래스의 서브클래스다. 보안 소켓이 생성된 다음에는 다른 소켓들처럼 getInputStream(), getOutputStream() 등의 메소드를 통해 다른 소켓들처럼 사용할 수 있다. 

    주문을 받는 서버가 login.ibiblio.org의 7000번 포트에서 대기하고 있다고 가정해 보자. 각 주문은 단일 TCP 연결을 사용하여 아스키 문자로 보내진다. 서버는 주문을 받고 연결을 종료한다. 클라이언트가 보낸 주문은 다음과 같다.

    Name: Jogn Smith
    Product-ID: 67X-89
    Address: 1280 Deniston Blvd, NY NY 10003
    Card number: 4000-1234-5678-9017
    Expires: 08/05

    이 메시지에는 나쁜 목적으로 사용하기에 충분한 정보가 들어있다. 따라서 서버에 이 주문은 보내기 전에 암호화해야한다. 가장 간단한 방법은 보안 소켓을 사용하는 것이다.

    SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
    Socket socket = factory.createSocket("login.ibiblio.org", 7000);
    
    Writer out = new OutputStreamWriter(socket.getOutputStream(), "US-ASCII");
    out.write("Name: Jogn Smith\r\n"); 
    out.write("Product-ID: 67X-89\r\n");
    out.write("Address: 1280 Deniston Blvd, NY NY 10003\r\n");
    out.write("Card number: 4000-1234-5678-9017\r\n");
    out.write("Expires: 08/05\r\n");
    out.flush();

    SSLSocketFactory를 이용하는 것만 다르고 기존은 일반적인 Socket 통신과 같은 방법이다.

     

    아래 예제는 보안 HTTP 서버에 연결하고 GET 요청을 보내고 응답을 출력하는 간단한 프로그램이다.

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.io.Writer;
    
    import javax.net.ssl.SSLSocket;
    import javax.net.ssl.SSLSocketFactory;
    
    
    public class HTTPSClient {
    
        public static void main(String[] args) {
            if (args.length == 0) {
                System.out.println("Usage: java HTTPSClient2 host");
                return;
            }
    
            int port = 443; // https 기본 포트 번호
            String host = args[0];
    
            SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
            SSLSocket socket = null;
    
            try {
                socket = (SSLSocket) factory.createSocket(host, port);
    
                // 모든 암호화 조합을 사용하도록 설정
                String[] supported = socket.getSupportedCipherSuites();
                socket.setEnabledCipherSuites(supported);
    
                Writer out = new OutputStreamWriter(socket.getOutputStream(), "UTF-8");
                // https는 GET 요청 시 전체 URL을 사용해야 한다.
                out.write("GET http://" + host + "/ HTTP/1.1\r\n");
                out.write("Host: " + host + "\r\n");
                out.write("\r\n");
                out.flush();
    
                // 응답 읽기
                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    
                // 헤더 읽기
                String s;
                while (!(s = in.readLine()).equals("")) {
                    System.out.println(s);
                }
                System.out.println();
    
                // 길이 읽기
                String contentLength = in.readLine();
                int length = Integer.MAX_VALUE;
                try {
                    length = Integer.parseInt(contentLength.trim(), 16);
                } catch (NumberFormatException ex) {
                    // 서버가 응답 본문의 첫째 줄에 content-length를 보내지 않은 경우
                }
                System.out.println(contentLength);
    
                int c;
                int i = 0;
                while ((c = in.read()) != -1 && i++ < length) {
                    System.out.write(c);
                }
    
                System.out.println();
            } catch (IOException ex) {
                System.err.println(ex);
            } finally {
                try {
                    if (socket != null) socket.close();
                } catch (IOException e) {
                }
            }
        }
    }
    

     

    미국 우편 서비스웹에 접속해보면 다음과 같다. 

    $ javac ./HTTPSClient.java
    $ java HTTPSClient "www.usps.com"
    HTTP/1.1 200 OK
    Accept-Ranges: bytes
    Access-Control-Allow-Origin: https://www.usps.com
    Age: 1686
    Content-Security-Policy: default-src 'self' https:;                                              connect-src 'self' https:;                                              font-src 'self' https: data:;                                              frame-src 'self' https:;                                              img-src 'self' https: data:; media-src 'self' https:;                                              object-src 'self' https:;                                              script-src 'self' 'unsafe-inline' 'unsafe-eval' https:;                                              style-src 'self' 'unsafe-inline' https:; 
    Content-Type: text/html
    Date: Sun, 11 Apr 2021 09:43:53 GMT
    Last-Modified: Sun, 11 Apr 2021 09:15:47 GMT
    Server: ECAcc (lab/4F86)
    Strict-Transport-Security: max-age=31536000 ; includeSubDomains
    Vary: Accept-Encoding
    X-Cache: HIT
    X-Content-Type-Options: nosniff
    x-ec-custom-error: 1
    X-Frame-Options: SAMEORIGIN
    X-Ruleset-Version: 2.2
    Content-Length: 138793
    
    <!DOCTYPE html>
    <html lang="en">
    ...

     

    이 프로그램을 실행해보면 예상보다 응답이 느리다는 사실을 알 수 있다. 공개키를 생성하고 교환하는 데 소요되는 CPU와 네트워크 오버헤드가 눈에 띌 정도이다. 결과적으로 모든 콘텐츠를 HTTPS로 제공하기보다는 보안이 필요하거나 지연에 민감하지 않는 콘텐츠에 한해서 HTTPS로 제공하고 싶을 것이다. 

     

    암호화 조합 선택하기

    JSSE 구현들마다 서로 다른 인증과 알고리즘의 암호화 조합을 제공한다. 예를 들면 JDK와 함께 제공되는 JSSE(Java Secure Socket Extension)에는 실제로 강력한 256비트 암호화가 포함되어 있지만 법률상의 이유로 JCE Unlimited Strength Jurisdiction Policy Files 를 설치하기  전에는 사용할 수 없다.

    SSLSocketFactory 클래스의 getSupportedCipherSuites() 메소드는 해당 소켓이 이용 가능한 알고리즘의 조합을 알려준다.

    public abstract String[] getSupportedCipherSuites()

    그러나 이 목록에서 반환된 암호화 조합이 항상 사용할 수 있는건 아니다. SSLSocketFactory 클래스의 getEnabledCipherSuites() 메소드는 해당 소켓에서 실제 사용할 수 있는 암호화 조합을 알려준다.

    public abstract String[] getEnabledCipherSuites()

    사용되는 실제 조합은 연결 시에 클라이언트와 서버 사이에 협상으로 결정된다. 클라이언트와 서버가 어떤 조합에도 동의하지 않는 상황도 발생할 수 있다. 어느 한쪽 또는 양쪽 다 필요한 키와 인증서가 없는 경우가 있을 수도 있다. 이 경우에는 createSocket() 메소드는 SSLException을 발생시킨다. Socket 객체 생성 뒤에 setEnabledCipherSuites() 메소드를 통해 클라이언트가 사용하고자 하는 조합을 변경할 수 있다.

    public abstract void setEnabledCipherSuites(String[] suites)

    getSupportedCipherSuites()로 반환된 목록에서 선택되어야한다. 

    반환될 목록의 이름은 각각 프로토콜, 키 교환 알고리즘, 암호화 알고리즘, 체크섬을 의미한다. 예를 들면,

    • SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA의 이름은
      • 프로토콜 : SSL 
      • 키 교환 알고리즘 : DH(DiffieHellman) 키 협정 메소드 / 인증없음
      • 암호화 알고리즘 : 40비트 키의 DES 암호화 / 암호화 블록 체이닝(CBC, Cipher Block Chaning)
      • 체크섬 : 해시 알고리즘(SHA, Secure Hash Algorithm) 체크섬
    더보기

    JDK1.7 암호화 조합 반환 목록

    TLS_ECDHE_ECDSA_WITH_AES_128CBC_SHA256
    TLS_ECDHE_RSA_WITH_AES_128CBC_SHA256
    TLS_RSA_WITH_AES_128CBC_SHA256
    TLS_ECDH_ECDSA_WITH_AES_128CBC_SHA256
    SSL_RSA_WITH_RC4_128_SHA
    ...

     

    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 조합 정도면 보통 알려진 대부분에 공격에 대해 안전하며, AES 128보다는 256(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA256)으로 설정할 경우 좀 더 안전하다. 일반적으로 TLS_ECDHE로 시작하고 SHA256또는 SHA384로 끝나는 조합은 오늘날 널리 사용되는 가장 강력한 암호화 조합을 나타낸다. 

    String[] stringSuites = {"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"};
    socket.setEnabledCipherSuites(stringSuites);

    이런식으로 설정해놓을 수 있다. 이 때, 연결의 반대측에서 이 암호화 프로토콜을 지원하지 않는 경우, 읽거나 쓰려고 할 때 취약한 채널을 통해 뜻하지 않게 기밀데이터가 노출되는 상황을 방지하기 위해 소켓은 예외를 발생시킨다. 

     

    클라이언트 모드

    일반적으로 대부분은 서버가 적절한 인증서로 자신을 스스로 인증한다. 클라이언트는 대부분 그럴 필요 없다. 즉, 유저가 아마존 서버에서 책을 구매할 때, 브라우저에게 해커의 서버가 아닌 진짜 아마존의 서버임을 증명해야한다.

    클라이언트 쪽에서는 대부분 증명할 필요가 없지만 높은 보안이 요구되는 애플리케이션에 한해서는 서버에서 클라이언트에게 증명을 요구하도록 설계할 수 있다. 

    서버쪽 보안 소켓(SSLServerSocket)은 서버로 연결하는 모든 클라이언트에게 스스로 인증을 요청하기 위해 setNeedClientAuth() 메소드를 사용할 수 있다. true로 메소드 호출 시, 클라이언트가 스스로 인증할 수 있는 연결만 허용한다. 

    public abstract void setNeedClientAuth(boolean needsAuthentication)

    클라이언트측에서는 setUseClientMode() 를 이용해 첫 핸드세이크 시에 인증이 필요한지 여부를 결정할 수 있다. 보통은 클라이언트 측에서 인증을 시도하지 않기 때문에 인자를 true로 설정하면 인증을 시도하지 않는다. 인자를 false로 전달해야 스스로 인증을 시도한다. 

    public abstract void setUseClientMode(boolean mode)

    getNeedClientAuth() 메소드는 클라이언트 측에 인증을 요구할 경우 true를 반환하고 그렇지 않은 경우 false를 반환한다.

    public abstract boolean getNeedClientAuth()

     

    보안 서버 소켓 만들기

    서버 소켓은 javax.net.SSLServerSocket 클래스를 사용한다. 

    public abstract class SSLServerSocket extends ServerSocket

    SSLSocket과 마찬가지로 인스턴스는 추상 팩토리 클래스인 javax.net.SSLServerSocketFactory에 의해서 생성된다. 또한 SSLServerSocketFactory의 인스턴스는 getDefault() 메소드로 받아온다. 

    public abstract class SSLServerSocketFactory extends ServerSocketFactory
    public static ServerSocketFactory getDefault()

    다만, SSLServerSocketFacoty.getDefault()가 반환하는 팩토리는 일반적으로 서버 인증만 지원하며 암호화는 지원하지 않는다. 암호화를 지원하기 위해서는 많은 초기화 설정이 필요하다. 썬 마이크로시스템즈에서 만든 참조 구현을 이용해보자.

    1. keytool을 이용하여 공개키와 인증서를 생성한다.
    2. Comodo와 같은 신뢰할 수 있는 서드파티기관에 돈을 지불하고 인증서를 인증 받는다.
    3. 사용할 알고리즘에 대한 SSLContext를 생성한다.
    4. 사용할 인증서 데이터 소스에 대한 TrustManagerFactory를 생성한다.
    5. 사용할 키 데이터 타입에 대한 keyManagerFactoy를 생성한다.
    6. 키와 인증서 데이터베이스를 위한 KeyStore를 생성한다.
    7. 키와 인증서로 KeyStore 객체를 채운다. 예를 들어, 암호화 시에 사용된 암호(passphrase)를 사용하여 파일 시스템에서 읽는다.
    8. KeyManagerFactory를 KeyStore와 KeyStore의 암호(passphrase)로 초기화한다.
    9. KeymanagerFactory에서 키 매니저, TrustMnagerFactory에서 신뢰 매니저, 그리고 난수 소스를 초기화한다. [기본값을 사용하고자할 경우 마지막 두 개는 null일수도 있다]

    ServerSSLSoket 예제

    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.Socket;
    import java.security.KeyManagementException;
    import java.security.KeyStore;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.security.UnrecoverableKeyException;
    import java.security.cert.CertificateException;
    import java.util.Arrays;
    
    import javax.net.ssl.KeyManagerFactory;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLServerSocket;
    import javax.net.ssl.SSLServerSocketFactory;
    
    
    public class ServerSSLSocket {
    
    
        public final static int PORT = 7000;
        public final static String algorithm = "SSL";
    
        public static void main(String[] args) {
            try {
                SSLContext context = SSLContext.getInstance(algorithm);
    
                // 이 예제에서는 X.509만 지원한다. (많이 사용되는 인증서 종류 중 하나)
                KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
    
                // 오라클의 기본 키스토어 유형
                KeyStore ks = KeyStore.getInstance("JKS");
    
                // 보안 문제로, 모든 키스토어는 디스크에서 읽어 오기 전에
                // 패스(passphrase)로 암호화되어야 한다.
                // 패스는 char[] 배열에 저장되어 있으며 가비지 컬렉터를
                // 기다리지 않고 재빨리 메모리에서 지워야 한다.
                char[] password = System.console().readPassword();
                ks.load(new FileInputStream("jnp4e.keys"), password);
                kmf.init(ks, password);
                context.init(kmf.getKeyManagers(), null, null);
    
                // 패스워드 제거
                Arrays.fill(password, '0');
    
                SSLServerSocketFactory factory = context.getServerSocketFactory();
                SSLServerSocket server = (SSLServerSocket) factory.createServerSocket(PORT);
                
                // 현재 JDK 구현에서 이용가능한 암호화 알고리즘 조합을 가져온다.
                String[] supported = server.getSupportedCipherSuites();
                String[] anonCipherSuitesSupport = new String[supported.length];
                int numAnonCipherSuitesSupported = 0;
    
                // 익명(인증되지 않음) 암호화 조합 추가
                // 이 예제에서는 테스트용으로 키를 인증받지 않았기 때문에 인증을 요구하지 않은 암호화 조합을 이용한다.
                // ex. SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
                for (int i = 0; i < supported.length; i++) {
                    if (supported[i].indexOf("_anon_") > 0) {
                        anonCipherSuitesSupport[numAnonCipherSuitesSupported++] = supported[i];
                    }
                }
    
                // 기본 값으로 선언되어 있는 암호화 조합 목록을 가져온다. 
                String[] oldEnabled = server.getEnabledCipherSuites();
                String[] newEnabled = new String[oldEnabled.length + numAnonCipherSuitesSupported];
                System.arraycopy(oldEnabled, 0, newEnabled, 0, oldEnabled.length);
                System.arraycopy(anonCipherSuitesSupport, 0, newEnabled, oldEnabled.length, numAnonCipherSuitesSupported);
    
                // newEnabled 목록으로 소켓의 암호화 목록을 수정한다.
                // 클라이언트 측에서 이 암호화 목록을 지원하지 않는 경우 
                // 읽거나 쓰려고 할 때 예외가 발생될 것이다.
                server.setEnabledCipherSuites(newEnabled);
    
                // 모든 설정이 끝나고 이제 실제 통신에 초점을 맞춘다.
                while (true) {
                    // 이 소켓은 보안이 적용된 소켓이지만 소켓 사용 방법에 별 차이가 없다.
                    try (Socket theConnection = server.accept()) {
                        InputStream in = theConnection.getInputStream();
                        int c;
                        while ((c = in.read()) != -1) {
                            System.out.write(c);
                        }
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
    
            } catch (IOException | KeyManagementException | KeyStoreException
                    | NoSuchAlgorithmException | CertificateException
                    | UnrecoverableKeyException ex) {
                ex.printStackTrace();
            }
        }
    }
    

     

    현재 작업 경로에 있는 jnp4e.keys라는 파일로부터 필요한 키와 인증서를 읽는다. 파일은 비밀번호 "2andnotafnord" 보호되어 있다. 예제에서는 파일을 생성하는 방법을 보여주진 않지만 JDK 함께 번들로 제공되는 keytool프로그램을 이용하여 키를 생성할 있다.

    $ keytool -genkey -alias ourstore -keystore jnp4e.keys
    Enter keystore password:  
    Re-enter new password: 
    They don't match. Try again
    Enter keystore password:  
    Re-enter new password: 
    What is your first and last name?
      [Unknown]:  Elliotte Harold
    What is the name of your organizational unit?
      [Unknown]:  Me, Myself, and I
    What is the name of your organization?
      [Unknown]:  Cafe au Lait
    What is the name of your City or Locality?
      [Unknown]:  Brooklyn
    What is the name of your State or Province?
      [Unknown]:  New York
    What is the two-letter country code for this unit?
      [Unknown]:  NY
    Is CN=Elliotte Harold, OU="Me, Myself, and I", O=Cafe au Lait, L=Brooklyn, ST=New York, C=NY correct?
      [no]:  y

     

    이 과정이 끝나면 jnp4e.keys 파일이 생성되며 이 파일에는 공개키가 포함되어 있다. 그러나 이렇게 생성된 키를 GeoTrust나 GoDaddy와 같은 신뢰할 수 있는 업체로부터 인증 받지 않는다면 아무도 믿지 않을 것이다. 

     

    TLS - protonmail.com/blog/tls-ssl-certificate/

    wiki.gurubee.net/display/SWDEV/SSL+%28TLS%29

    SSL 만화 - wiki.gurubee.net/display/SWDEV/SSL+%28TLS%29

    스누핑 - terms.naver.com/entry.naver?docId=2455057&cid=42346&categoryId=42346

    암호화 주요 용어/요건 - atoz-develop.tistory.com/

    대칭키/공개키 사진 - juneyr.dev/2019-10-08/ssl

    치환암호 - www.pentasecurity.co.kr/encryption/

    공개키 사진 - raonctf.com/essential/study/web/asymmetric_keyliveyourit.tistory.com/183

    체크섬 - wiki.kldp.org/HOWTO/html/SSL-Certificates-HOWTO/x70.html

    반응형

    '프로그래밍 > Java' 카테고리의 다른 글

    URL과 URI  (1) 2021.02.15
    가비지 컬렉션 (Garbage collection)  (0) 2020.10.19
    함수형 프로그래밍 설계 -1  (0) 2017.06.29
    Java Collection  (0) 2015.03.21
    오버로딩(method overloading) vs 오버라이딩(overriding)  (0) 2014.07.30
Designed by Tistory.