[Infra] SSL, CRS 인증 관련 정리(대칭키, 공개키, 개인키)

업데이트:

SSL, CRS 인증 관련 정리(대칭키, 공개키, 개인키)

참고: 링크1, 링크2

참고링크

SSL와 인증서(Certificate)의 정의

SSL(Secure Socket Layer) 프로토콜은 Certificate Authority(CA)라 불리는 인증기관(서드파티)으로부터 서버와 클라이언트의 인증을 하는데 사용됩니다. 여기서 서드 파티란 서버와 클라이언트가 아닌 제 3의 무엇인가를 의미합니다. 흔히 인증서버라고 부르죠. 여기서 인증(Authentication)은 통신의 상대방이 맞는지 확인하는 절차를 의미합니다. 우리 일상에서도 휴대폰인증이나 신분증, 지문 등을 이용해 본인이 맞는지 인증하고 있죠.

OpenSSL

OpenSSL은 정해진 규격의 네트워크 보안 프로토콜을 범용 라이브러리로 구현하기 위한 목적으로 만들어졌습니다. OpenSSL을 이용하면 SSL이나 TLS를 이용한 암호화를 구현할 수 있는데요. 보안이 중요한 대형 포털, 이메일, 금융권 등에서 데이터 통신시 OpenSSL을 사용합니다.

SSL 작동 과정

다음은 SSL 작동 과정입니다.

  1. (웹브라우저) SSL로 암호화된 페이지를 요청하게 된다. (일반적으로 https://가 사용됨)

  2. (웹서버) Public Key를 인증서와 함께 전송한다.

  3. (웹브라우저) 인증서가 자신이 신용있다고 판단한 CA(일반적으로 trusted root CA라고 불림)로부터 서명된 것인지 확인한다. 또한 날짜가 유효한지, 그리고 인증서가 접속하려는 사이트와 관련되어 있는지 확인한다.

  4. (웹브라우저) Public Key를 사용해서 랜덤 대칭 암호화키(Random symmetric encryption key)를 비롯한 URL, http 데이터들을 암호화해서 전송한다.

  5. (웹서버) Private Key를 이용해서 랜덤 대칭 암호화키와 URL, http 데이터를 복호화한다.

  6. (웹서버) 요청받은 URL에 대한 응답을 웹브라우저로부터 받은 랜덤 대칭 암호화키를 이용하여 암호화해서 브라우저로 전송한다.

  7. (웹브라우저) 대칭 키를 이용해서 http 데이터와 html문서를 복호화하고, 화면에 정보를 뿌려준다.

개인키(Private Key)/공개키(Public Key), 또는 비대칭키

Private key/Public Key를 이용한 암호화는 하나의 키로 암호화하고 나머지 다른 하나로 복호화할 수 있도록 되어있습니다. 무슨 말이냐면 암호화한 키로만 암호화를 할 수 있는 것이 아니라 반대 방향으로 복호화한 키로도 암호화할 수도 있는데요. 즉, 암호화한 키가 이번엔 복호화하는 키가 되는 것 입니다. 이러한 키쌍은 소수(prime number)로부터 생성되며, 그 길이(Bit 단위)는 암호화의 강도를 나타냅니다.

Private Key/Public Key는 이러한 키쌍을 관리하는 방법입니다. 한개의 키는 안전한 장소에 자기만 알 수 있도록 보관하고(Private Key) 다른 하나는 모든 사람에게 퍼뜨리는 것(Public Key)입니다. 그렇게 하면 공개키(Public Key)를 가진 사람들이 당신에게 메일을 보낼 때 암호화해서 보낼 수 있으며, 당신만이 그 암호를 풀 수 있습니다. 반대로 개인키(Private Key)를 가진 당신이 다른 사람에게 메일을 보낼 일이 있으면 Private Key를 이용해 암호화 할 수 있습니다. 그러면 메일을 받은 사람들은 공개키(Public Key)를 이용해 복호화해서 볼 수 있습니다. 그러나 이 방법은 모든 사람이 공개키(Public Key)를 가지고 있어야 하므로 그리 안전한 방법은 아닙니다.

정리하면 송신자는 외부에 공개된 키(Public Key)로 암호화하여 송신하고, 수신자는 개인키(Private Key)로 복호화합니다. 이 때, 송신자와 수신자가 사용하는 키가 다르므로 비대칭키라고 합니다.

인증서(Certificate)

여러분이 접속한 웹 사이트가 믿을 수 있는지 어떻게 판단할 수 있을까요? 그 웹사이트 관리자는 여러분에게 이 사이트가 믿을만하다고 열심히 설명합니다. 당신이 그 사이트의 인증서를 설치해 주기를 바라면서 말이죠. 만약 이 과정을 한두번도 아니고 웹사이트 접속할때마다 해야한다면 귀찮지 않을까요? 인증서는 여러 부분으로 이루어져있습니다. 아래는 인증서 속에 들어있는 정보의 종류를 나타낸 것입니다.

  1. 인증서 소유자의 e-mail 주소

  2. 소유자의 이름

  3. 인증서의 용도

  4. 인증서 유효기간

  5. 발행 장소

  6. Distinguished Name (DN)

  • Common Name (CN)

  • 인증서 정보에 대해 서명한 사람의 디지털 ID

  1. Public Key

  2. 해쉬(Hash)

SSL의 기본 구조는 여러분이 인증서에 서명한 사람을 신뢰한다면, 서명된 인증서도 신뢰할 수 있다는 것입니다. 이것은 마치 트리(Tree)와 같은 구조를 이루면서 인증서끼리 서명하게 됩니다. 그러면 최상위 인증서는? 최상위 인증서를 발행한 기관을 Root Certification Authority(줄여서 Root CA)라고 부르며, 유명한 인증 기관(역주:Verisign, Thawte, Entrust, etc)의 Root CA 인증서는 웹브라우저에 기본적으로 설치되어 있습니다. 이러한 인증 기관은 자신들이 서명한 인증서들을 관리할 뿐만 아니라 철회 인증서(Revoked Certificate)들도 관리하고 있습니다. 그러면 Root CA의 인증서는 누가 서명을 했을까요? 모든 Root CA 인증서는 자체 서명(Self Signed)되어 있습니다.

대칭키(The Symmetric key)

Private Key/Public Key 알고리즘은 비실용적이라는 단점이 있습니다. 비대칭(Asymmetric)이란 하나의 키로 암호화를 하면 다른 키가 있어야 복호화를 할 수 있는 것을 뜻합니다. 즉, 하나의 키로 암호화/복호화를 할 수 없다는 말이다. 대칭키(Symmetric Key)는 하나의 키로 암호화/복호화를 하게 되는데요. 대칭키를 사용하면 비대칭키보다 훨씬 빠르게 암호화/복호화를 할 수 있습니다. 하지만 단점도 존재하는데요. 만약 해커가 여러분의 키를 입수해 버리면 여태까지 암호화된 정보가 모두 털리게 됩니다. 대칭키의 예로 우리집 현관문을 생각해봅시다. 하나의 열쇠로 문을 열고 닫는 것과 같으며 열쇠를 외부인에게 주면 안됩니다. 따라서 대칭키를 상대방에게 전송할때 인터넷으로 전송하는 것은 위험하기 때문에 직접 손으로 전달해야만 합니다. 이런 귀찮은 상황을 피하려면 대칭키를 비대칭키로 암호화시켜서 전송하면 됩니다. 자신의 Private Key만 안전하게 관리하면 Public Key로 암호화되어 안전하게 전송할 수 있습니다. 또한 대칭키는 매번 랜덤으로 정해지는데, 이렇게되면 만약 대칭키가 누출되어도 다음번에는 다른 키가 사용되기 때문에 안전합니다.

서명(Signing)

서명은 특정 메시지를 내가 작성했다는 것을 인증하는 역할을 합니다. Text가 될 수도 있고, 인증서 등등이 될 수 있습니다. 아래는 메시지에 서명하는 순서입니다.

  1. 해쉬 생성

  2. Private Key로 해쉬 암호화

  3. 암호화된 해쉬와 서명된 인증서를 메시지에 추가

  4. 받는 사람은 따로 해쉬를 생성

  5. 받은 메시지에 포함된 해쉬를 Public Key를 이용해서 복호화

  6. 4, 5번 과정에서 생성된 해쉬를 비교

CSR(Certificate Signing Request)란?

SSL 서버를 운영하는 회사의 정보를 암호화하여 인증기관으로 보내 인증서를 발급받게 하는 일종의 신청서입니다. CSR은 ASCII 텍스트 화일로 생성됩니다. CSR을 생성할 때 서버의 식별명을 입력하게 됩니다. 식별명은 각 서버를 공유하게 나타내는 이름으로 다음과 같은 정보를 포함합니다.

  • Country Name (ISO형식의 국가코드): KR
  • State or Province Name (지역) : Seoul
  • Locality Name (시/군/구): Seocho
  • Organization Name (회사명): XXX corp
  • Organizational Unit Name (부서명): YYY Team
  • Common Name (서비스도메인명): www.abcd.com
  • Email Address: myid@XXX.com

CSR 입력시 주의 사항

  • Common Name 에는 인증서를 설치할 사이트의 도메인의 이름을 정확하게 입력하셔야 합니다.
  • Common Name 에는 IP 주소, 포트번호, 경로명, http:// 나 https:// 등은 포함할 수 없습니다.
  • CSR 항목에는 < > ~ ! @ # $ % ^ * / \ ( ) ? 등의 특수 68 문자를 넣을 수 없습니다.
  • CSR 생성후 서버에 개인키 (Private Key) 가 생성됩니다. 개인키를 삭제하거나 분실할 경우 인증서를 발급받아도 설치가 불가합니다. 따라서 꼭 개인키를 백업받아 두셔야 합니다.
  • 정보입력과정 마지막에 나오는 A challenge password 와 An optional company name 두 항목은 입력하지 마시고 Enter 만 누르고 넘어가야 합니다. 두 정보가 입력될 경우 잘못된 CSR 생성될 수 있습니다.

SSL 인증서 적용 방법

httpd-ssl.conf 수정

아파치서버 설치 경로의 conf 폴더를 보면 httpd-ssl.conf라는 파일이 있습니다. 해당 파일을 읽으면 아래와 같은 코드를 확인할 수 있는데요.

SSLEngine on
SSLCertificateFile "/usr/local/apache/conf/cert.pem"
SSLCertificateKeyFile "/usr/local/apache/conf/key.pem"
SSLCACertificateFile "/usr/local/apache/conf/chain.pem"

위 코드를 한줄 한줄 알아봅시다.

SSLEngine

SSLEngine on 

위 코드는 SSL을 구동하는 ModSSL의 명령입니다.

SSLCertificateFile

SSLCertificateFile "/usr/local/apache/conf/cert.pem"

SSLCertificateFile은 서버 인증서 위치와 그 이름을 아파치에게 알려줍니다. 서버 인증서 파일 내용은 아래와 같습니다.

-----BEGIN CERTIFICATE-----
bla bla~
-----END CERTIFICATE-----

SSLCertificateKeyFile

SSLCertificateKeyFile "/usr/local/apache/conf/key.pem"

SSLCertificateKeyFile은 비밀키 이름과 그 위치를 아파치에게 알려주는데, 여기서 정의된 디렉토리는 단지 루트에게만 읽기/쓰기 허가권이 주어져야하며 다른 누구도 이 디렉토리에 액세스하지 못해야 합니다. 비밀키 파일 내용은 아래와 같습니다.

-----BEGIN RSA PRIVATE KEY-----
bla bla ~
-----END RSA PRIVATE KEY-----

비밀키의 경우 서버를 재구동시킬때 패스프레이즈를 입력하라고 뜨는데, 이게 매번 서버 구동시킬때마다 입력해야하면 귀찮을 수 있습니다. 그래서 비번입력 안하는 버전으로 바꿀 수 있는데요. 아래와 같은 명령어를 입력해서 비번 없는 파일로 하나 만들어줍니다.

//$ openssl rsa -in [encrypted.key] -out [decrypted.key]
$ openssl rsa -in 기존파일.key -out 비번없는새로운파일.key

SSLCACertificateFile

SSLCACertificateFile "/usr/local/apache/conf/chain.pem"

SSLCACertificateFile는 Intermediate(root) 인증서 위치를 아파치에게 말해주는데 사용하는 인증서에 따라 필요할 수도 있고 아닐 수도 있습니다. 이 인증서는 반드시 신뢰 고리(ring of trust)입니다.

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

웹서버 재구동하기

현재 돌아가고 있는 웹서버 확인

$ ps -ef | grep apache
root     16025     1  0 Jul25 ?        00:02:41 /usr/local/apache/bin/httpd -k start
irteam   16032     1  0 Jul25 ?        03:40:00 LLAWP /usr/local/apache/conf/WebAgent.conf -APACHE22
irteam   27901 16025  0 08:51 ?        00:00:00 /usr/local/apache/bin/httpd -k start
irteam   28210 16025  0 09:16 ?        00:00:00 /usr/local/apache/bin/httpd -k start
irteam   28294 16025  0 09:26 ?        00:00:00 /usr/local/apache/bin/httpd -k start
irteam   28629 16025  0 10:08 ?        00:00:00 /usr/local/apache/bin/httpd -k start
irteam   28630 16025  0 10:08 ?        00:00:00 /usr/local/apache/bin/httpd -k start
irteam   28631 16025  0 10:08 ?        00:00:00 /usr/local/apache/bin/httpd -k start
irteam   29496 16025  0 11:01 ?        00:00:00 /usr/local/apache/bin/httpd -k start
irteam   29497 16025  0 11:01 ?        00:00:00 /usr/local/apache/bin/httpd -k start
irteam   29498 16025  0 11:01 ?        00:00:00 /usr/local/apache/bin/httpd -k start
irteamsu 31315 29024  0 14:44 pts/0    00:00:00 grep --color=auto apache

재구동 스크립트 위치

  • httpd 스크립트인 경우: /usr/local/sbin, /usr/bin
  • apachectl 스크립트인 경우: /usr/local/apache/bin

명령은 다음과 같습니다.

$ httpd stop
$ httpd startssl
$ httpd restart

또는(저 같은 경우 아래쪽이 작동 되었습니다, 위쪽 명령으로 하면 안되더라구요.)

$ apachectl stop
$ apachectl startssl
$ apachectl restart

실제 내가 입력한 명령어

$ sudo ./apachectl stop
$ sudo ./apachectl start
// 프로세스 확인
$ ps -ef | grep httpd
irteam   15296 16025  0 09:40 ?        00:00:00 /usr/local/apache/bin/httpd -k start
irteam   15297 16025  0 09:40 ?        00:00:00 /usr/local/apache/bin/httpd -k start
irteam   15332 16025  0 09:44 ?        00:00:00 /usr/local/apache/bin/httpd -k start
irteam   15340 16025  0 09:44 ?        00:00:00 /usr/local/apache/bin/httpd -k start
irteam   15341 16025  0 09:44 ?        00:00:00 /usr/local/apache/bin/httpd -k start
irteam   15918 16025  0 09:59 ?        00:00:00 /usr/local/apache/bin/httpd -k start
irteam   15919 16025  0 09:59 ?        00:00:00 /usr/local/apache/bin/httpd -k start
irteam   15920 16025  0 09:59 ?        00:00:00 /usr/local/apache/bin/httpd -k start