목공책 하나 들이셔요~

2014년 6월 27일 금요일

[TLS] SSL에 대해 알아보아요~

이 글은 Oracle에서 제공하는 Java CAPS Documentation 중에서 "Secure Sockets Layer (SSL) Overview"라는 글을 번역하고 내용을 보강하였습니다. 최근에 TLS Client Authentication 코드를 개발하던 와중에 보안과 관련된 내용을 공부하게 되었는데 그 중에 짧지만 큰 도움을 줬던 문서라서 소개 드립니다. 원문은 아래 링크를 확인하세요

http://docs.oracle.com/cd/E21454_01/html/821-2544/cnfg_ssl-overview_c.html


인터넷을 통해 클라이언트와 서버가 통신할 때 통신 내용을 안전하게 보호하는 방법으로 SSL(Secure Sockets Layer)을 사용할 수 있습니다. SSL은 서버 인증(Server Authentication), 클라이언트 인증(Client Authentication) 그리고 데이타 암호화(Data Encryption) 기능을 제공합니다.

인증(Authentication)은 통신의 상대방이 맞는지 확인하는 절차를 의미합니다. 암호화는 데이타가 누출되더라도 외부에서 이 내용을 해독할 수 없게 하는 걸 의미합니다.

SSL을 사용하는 URL은 https 라는 스킴(scheme)을 사용하여 구분합니다. 예를 들어서 이렇습니다.

https://www.onlinebooks.com/creditcardinfo.html

최근 버전의 SSL은 이제 TLS(Transport Layer Security)라고 이름이 바뀌었습니다. 현재 IETF(Internet Engineering Task Force)가 TLS 표준을 유지 관리하고 있습니다. 




공개키, 비밀키 그리고 인증서 (Public Keys, Private Keys and Certificates)

인증을 수행할 때 SSL은 공개키 암호화(public-key cryptography)라는 기술을 사용합니다. 공개키 암호화는 공개키(public key)와 비밀키(private key) 이 둘의 조합에 근거한 알고리즘입니다. 공개키로 암호화된 데이타는 그 공개키와 짝이 되는 비밀키에 의해서만 해독이 가능합니다. 반대로 비밀키로 암호화된 데이타 역시 짝이 되는 공개키로 해독할 수도 있습니다. 


이 키 쌍을 가지고 있는 소유자는 이 중에서 공개키를 아무에게나 공개할 수 있습니다. 하지만 비밀키는 비밀스럽게 보관해야 합니다. 인증서(Certificate)는 소유자의 공개키가 맞는지를 검증하는 도구입니다. X.509 표준을 준수하는 인증서는 다음과 같은 데이타와 서명(signature) 영역을 가지고 있습니다. 
  • 공개키를 소유하고 있는 자의 구별 가능한 이름 
  • 공개키를 발급(issue)한 자의 구별 가능한 이름 
  • 이 인증서가 언제까지 유효한지를 나타내는 유효기간 
  • 공개키 그 자체
당신은 VeriSign과 같은 인증 기관 (CA, Certificate Authority)을 통해 인증서를 발급 받을 수 있습니다. 혹은 당신이 스스로 자기 서명 인증서(self-signed cerficate)를 만들 수도 있습니다. 이 경우 소유자와 발급자가 같겠죠. 인증서를 발급하는 인증 기관은 서로간에 어떤 계층(hierarchy) 관계가 있습니다. 루트 CA는 자기-서명 인증서를 가지고 있겠지요. 하지만 그 하부 CA들은 자기 직속 상관이 발급한 인증서를 가지고 있습니다. 그래서 특정 CA는 이런 인증서들의 묶음을 가지게 되는데 이를 인증서 체인(certificate chain)이라고 합니다. 인증서 체인은 자기 직속 상위 CA가 발급한 인증서를 가지고 있고, 그 상위 CA는 또 그 위의 상위 CA가 발급한 인증서를 가지고 있는 식입니다.



Keytool 프로그램

keytool은 Java SDK와 함께 배포되며 bin 디렉토리에 있는 보안 관련 프로그램입니다. keytool은 키스토어(keystore)라는 일종의 데이타베이스를 관리하는 프로그램입니다. 키스토어는 두개의 항목을 가지고 있습니다. 
  • 키 엔트리 (key entry) : 비밀키와 공개키와 관련된 인증서 체인으로 구성됩니다. 
  • 공인 인증서 엔트리 (trusted certificate entry) : 신뢰할 수 있는 기관을 나타내는 공개키 인증서 
키스토어의 각 항목은 유니크한 별명(alias)에 의해 식별됩니다. 키스토어에 새로운 엔티티를 추가할 때는 반드시 이 별명을 부여해야 합니다. 

keytool이 지원하는 커맨드는 다음과 같습니다. 
  • genkey : 공개치/비밀키 쌍을 만듭니다. 지정한 키스토어가 없는 파일이라면 새로 파일을 생성합니다. 
  • certreq : 인증서 서명 요청(CSR, Certificate Signing Request) 파일을 만듭니다. 
  • import : 인증서를 키스토어에 추가합니다. 키스토어가 없는 파일이라면 새로 파일을 만듭니다. 
  • export : 키스토어에서 인증서를 추출하여 파일로 저장합니다. 
  • list : 키스토어 엔트리들을 출력합니다. 
아래는 keytool list 커맨드로 키스토어의 내용을 출력해본 예입니다.


OpenSSL 프로젝트

OpenSSL은 SSL과 TLS 프로토콜과 각종 암호화 라이브러리를 구현한 오픈소스 툴킷입니다. 이 툴킷은 openssl 이라는 커맨드 라인 도구를 제공하는데 이를 이용하여 암호화 라이브러리의 다양한 기능을 사용할 수 있습니다.

openssl에서 사용할 수 있는 커맨드는 다음과 같습니다. 
  • pkcs12 커맨드 : PKCS#12 파일을 파싱하거나 생성합니다. 
  • req 커맨드 : PKCS#10 포맷의 인증서를 생성하거나 처리합니다. 
OpenSSL은 http://www.openssl.org에서 최신 버전을 다운로드 받을 수 있습니다.


SSL과 어댑터

HTTP와 SSL을 같이 사용하면 통신하는 두 주체 사이에 해커가 개입하여 내용을 알아내지 못합니다. 


Java에서는 JSSE (Java Secure Socket Extension)이라는 API 세트로 관련 기능이 제공되고 있습니다. Java 1.4 이후로는 JRE 기본 패키지에 포함되었습니다.

SL을 이용하여 웹서버를 구성할 경우 다음과 같은 선택 사항이 있습니다. 
  • 서버측 인증 : 대부분의 전자 상거래 사이트들은 서버측 인증을 사용하고 있습니다. 클라이언트는 웹서버로 인증서를 요구하고 그 인증서가 신뢰성 있는 것인지 확인해야 안전한 전자 상거래를 할 수 있습니다. 웹서버로 부터 전달되는 인증서의 서명을 확인하기 위해서 CA의 Truststore를 사용합니다. 
  • 상호 인증 : 상호 인증은 서버와 클라이언트 양쪽 모두를 인증하는 것입니다. 서버측 인증은 앞서 설명한 것과 같습니다. 추가로 웹서버는 클라이언트가 신뢰성이 있는지를 마찬가지로 확인하게 됩니다.
(보통 SSL이 쓰이는 것은 서버측 인증입니다. 즉 사용자가 지마켓에 들어가 물건을 구매하려고 하는데, 그것이 정말로 지마켓이 맞는지를 SSL을 통해 인증하는 것이지요. 반면 상호인증은 많이 사용되지 않는데 클라이언트 측의 공개키가 서버로 Out-of-Band로 전달되어야 하기 때문입니다. SSH 자동로그인이 대표적인 예입니다. 보통은 서버인증만 사용하고 클라이언트 인증은 아이디+암호를 입력하는 방식으로 인증합니다)
KeyStore와 TrustStore

JSSE는 KeyStore와 TrustStore라는 두 개의 파일을 사용합니다. KeyStore는 클라이언트 인증을 위해 클라이언트 측에 놓이는 것이고, TrustStore는 서버를 인증하기 위한 것입니다. 
  • KeyStore는 비밀키, 관련된 인증서 혹은 인증서 체인을 가지고 있는 데이타베이스입니다. 인증서 체인은 클라이언트 인증서와 하나 이상의 CA 인증서(공인인증서)로 구성됩니다. 보통 서버 역할을 하는 측에서만 필요하지만, 클라이언트 인증을 요구하는 경우 클라이언트 쪽도 있어야 합니다. 
  • TrustStore는 클라이언트가 신뢰할 수 있는 인증서만을 가지고 있습니다. 이들 인증서는 CA 루트 인증서 즉 자기서명 인증서입니다. 보통 웹서버가 설치되면 cacerts.jks라는 파일명으로 이 TrustStore가 저장됩니다. 
KeyStore와 TrustStore의 파일 형식은 동일합니다. 이 둘다 keytool을 이용하여 만들고 조작할 수 있습니다.


JKS포맷으로 KeyStore 만들기

여기서는 KeyStore를 JKS(Java KeyStore) 포맷으로 만드는 방법을 알아봅니다.

1. 다음 커맨드를 실행합니다. 

keytool -keystore clientkeystore -genkey -alias client

2. CSR(Certificate Signing Request)을 생성하기 위한 입력창이 나옵니다. 아래와 같은 식으로 입력합니다.

Enter keystore password: javacaps
What is your first and last name?
[Unknown]: development.oracle.com
What is the name of your organizational unit?
[Unknown]: Development
what is the name of your organization?
[Unknown]: Oracle
What is the name of your City or Locality?
[Unknown]: Monrovia
What is the name of your State or Province?
[Unknown]: California
What is the two-letter country code for this unit?
[Unknown]: US
Is<CN=development.oracle.com, OU=Development, O=Oracle, L=Monrovia, ST=California, 
C=US> correct?
[no]: yes

Enter key password for <client>
    (RETURN if same as keystore password):

3. Key Password를 물으면 그냥 엔터키를 치세요. (그러면 KeyStore 암호와 같은 암호가 설정됩니다)
위와 같이 하면 clientkeystore라는 파일이 사용자 디렉토리에 생성됩니다. 위에서 first and last name 입력하라는 창에서 풀 도메인 이름을 쓰는 것이 좋습니다. 왜냐하면 VeriSign과 같은 인증기관에서 요구하기 때문입니다.

이 KeyStore는 "client"라는 별명의 엔트리를 가지고 있습니다. 이 엔트리는 생성된 비밀키와 CSR을 만들기 위한 정보들을 가지고 있습니다. 다음과 같은 명령으로 CSR을 만들 수 있습니다.

keytool -keystore clientkeystore -certreq -alias client -keyalg rsa -file client.csr

이렇게 만들어진 CSR파일을 인증기관에 전달하면 됩니다. client.csr 파일은 PEM 포맷입니다.

PEM 포맷과 DER 포맷

PEM(Privacy-enhanced Electronic Mail) 포맷은 인증기관에서 가장 많이 사용하는 포맷입니다. PEM 인증서는 보통 .pem, .crt, .cer, .key 와 같은 확장자를 가집니다. 이 포맷은 Base64로 인코딩된 ASCII 텍스트 파일이고 "------BEGIN CERTIFICATE----"와 "----END CERTIFICATE----"와 같은 시작과 끝을 알리는 문구가 들어 갑니다.

DER(Distinguished Encoding Rules) 포맷은 PEM과 달리 바이너리 포맷입니다. 확장자는 주로 .der이 쓰이지만 종종 .cer로 쓰이는 경우도 있습니다. 그러므로 .cer 확장자를 보면 편집기로 열어 보아야 PEM 포맷인지 DER 포맷인지 알 수 있습니다. DER은 주로 Java 플랫폼에서 쓰입니다.

DER과 PEM은 서로 등가로 변환할 수 있는데 아래 URL을 이용하여 온라인에서 변환할 수 있습니다.

https://www.sslshopper.com/ssl-converter.html

댓글 없음:

댓글 쓰기