들어가며

이 포스팅의 내용은 <<HTTP 완벽 가이드>> 14장 https 의 내용을 정리한 것이다. RSA 암호화는 책에 자세히 나와 있지 않아 따로 포스팅을 참조하여 정리하였다.

웹의 보안

사용자는 웹을 중요한 일을 처리할 때 사용한다. 웹으로 물건을 사고, 자신의 신용카드 정보와 개인정보를 전송한다. 웹에서 전송되는 모든 데이터는 패킷으로 전송되기 때문에, 서버와 클라이언트 사이에서 누군가가 정보를 빼 가려고 할 수 있다.

웹에서 클라이언트 - 서버만 데이터를 확인할 수 있게 하려면 어떻게 해야 할까? 데이터를 전송할 때 암호화하고, 서버는 암호화를 해제하면 될 것이다.

HTTPS

이럴 때 사용하는 것이 HTTPS이다. HTTPS는 HTTP를 안전하게 만드는 기술 중 가장 널리 사용되는 기술이다. 브라우저가 http가 아니라 https로 접근하는 경우, URL이 http:// 대신 https:// 로 시작하는 것을 보고 이 사실을 알아챌 수 있다.

https를 사용할 때, 모든 http요청과 응답 데이터는 네트워크로 보내지기 전에 암호화된다. https는 http 하부에 전송 레벨 암호 보안 계층을 제공함으로써 동작하는데, 이는 SSL(Secure Sockets Layer)혹은 전송 계층 보안을 이용하여 구현화된다. 이 포스팅에서는 이를 SSL이라고 부르도록 하겠다.

OSI 7 레이어를 기 준으로 보았을 때는, 프리젠테이션 레이어에서 이를 담당한다. 사실 세션 - 프리젠테이션 - 애플리케이션 레이어는 엄밀하게 구분하기는 쉽지 않으니, 그냥 트렌스포트 레이어 윗단에서 담당한다고 생각해도 될 것 같다.

암호화

예전 시절의 암호화를 생각해 보자.

밥과 딜런이 서로 암호를 전송한다고 가정해 보자. 밥이 ‘I know you’ 라는 글을 암호화해서 보낸다고 가정하자. 키는 다음 알파벳으로 몇 글자 이동할지 정하는 숫자이다. 예를 들어 키 k=3이라고 하면, ‘L nqrz brx’ 로 변할 것이다.

즉, 암호화를 할 때 키를 어떤 걸 사용하냐에 따라 결과값은 키의 개수만큼 나오는 것이다. 그렇기 때문에 이 암호화를 풀려면 키와 암호화 된 텍스트를 동시에 넘겨 주어야 한다.

이제 디지털 계산이 도래했다. 두 가지 주요한 발전이 있었다.

  • 속도 및 기능에 대한 기계 장치의 한계에서 벗어남으로써, 복잡한 인코딩 / 디코딩 알고리즘이 가능해졌다.
  • 매우 큰 키를 지원하는 것이 가능해져서, 단일 암호 알고리즘으로 키의 값마다 다른 수조 개의 가상 암호 알고리즘을 만들어 낼 수 있게 되었다.

평문 메시지 P, 인코딩 함수 E, 디지털 인코딩 키 e가 주어지면 부호화 된 암호문 C를 생성할 수 있게 되었다.

C = E(P, e)

반대로 C를 디코더 함수 D, 디코딩 키 d를 이용하여 원래의 평문 P로 바꿀 수 있다.

P = D(C, d)

대칭키 암호

암호화의 기본 개념은 수천 년 전, 카이사르 때부터 현대까지 크게 변하지 않았다. 대부분의 암호 키는 대칭키 암호이다. 즉, 인코딩을 할 때 사용하는 키와 디코딩을 할 때 사용하는 키가 같기 때문이다 (e = d) 이 키를 그냥 k라고 부르도록 하자.

대칭키 암호에서, 발송자와 수신자 모두 통신을 위해 키 k를 똑같이 공유할 필요가 있다. 발송자는 공유된 비밀 키를 메시지를 암호화하고, 그 결과인 암호문을 수신자에게 발송하기 위해 사용된다.

잘 알려진 대칭키 암호 알고리즘으로는 DES, RC2, RC4 등이 있다

열거 공격

당연한 이야기지만, 비밀 키가 누설되면 안 된다. 좋은 암호 알고리즘은 공격자가 코드를 크래킹하려면, 우주에 존재하는 모든 키 값을 시도해 보는 거 이외에는 방법이 없게 한다. 가능한 키 값의 개수는 키가 몇 비트이며 얼마나 많은 키가 유효한지에 대해 달려 있다.

8비트 키라면 256가지, 40비트는 약 1조개 정도이다. 현재는 128비트 DES키는, 브루트포스한 방식으로는 깰 수 없다고 알려져 있다.

128비트로 암호화하여, 대칭키 방식으로 키를 공유하였다고 가정하자. 키를 모르면 상대방은 무차별 대입으로는 암호를 해제할 수 없다. 결국, 암호가 뚫리는 경우는 한 가지이다 : 키를 중간에서 채갔을 경우.

또한 대칭키 암호 방식으로는 세션 하나마다 하나의 키를 유지해야 한다. 즉, A B C D가 하나의 서버에 요청을 했을 때, A 대상으로 키 하나, B대상으로 하나…이런식으로 서버는 총 세션 개수만큼의 키를 보관하고 있어야 한다. 이는 서버 입장에서는 굉장히 어렵고 난감한 일이다.

이 두 가지 방식을 해결해야 한다. 여기서 공개키 암호법이 등장한다.

공개키 암호

한 쌍의 호스트가 인코딩/디코딩 키를 같은 걸 사용하는 대신, 공개키 암호 방식은 두 개의 비대칭 키를 사용한다. 하나는 호스트의 메시지를 인코딩하기 위한 것이고, 하나는 호스트의 메시지를 디코딩하기 위한 것이다.

인코딩 키는 모두를 위해 공개되어 있다(이래서 공개키 암호 방식이다). 하지만 호스트만이 개인 디코딩 키를 알고 있다.

공개키는 인터넷 어딘가에 공개적으로 배포되어 있다.(보통은 디지털 인증서 안에 있다) 이제 메시지를 보내고자 하는 클라이언트는 누구나 똑같고 잘 알려진 공개키를 이용하여 메시지를 보낼 수 있다. 각 호스트마다 누구나 사용할 수 있는 인코딩키가 할당되어 있기 때문에, 대칭 키의 쌍이 N^2으로 폭발적으로 증가하는 것을 피할 수 있다.

모든 사람이 서버에 보내는 메시지를 같은 키로 인코딩 할 수 있지만, 누구도 그 메시지를 디코딩 할 수는 없다. 왜냐면 서버만이 디코딩 개인 키를 가지고 있기 때문이다.

가장 유명한 공개키 알고리즘은 RSA이다.

디지털 서명

암호 체계는 메시지를 해독하고 암호화하는 것 뿐만 아니라, 누가 메시지를 썼는지 알려주고 그 메시지가 위조되지 않았음을 증명하기 위해 메시지에 서명을 하는 데 이용할 수 있다. 디지털 서명이라 불리는 다음의 기법은 인터넷 보안 인증서에게 중요하다.

서명은 암호 체크섬이다

서명은 다음과 같은 기능을 한다.

  • 메시지를 작성한 저자가 누군지 알려준다.
  • 메시지 위조를 방지한다.

디지털 서명은 보통 비대칭 공개키에 의해 생성된다. 개인키는 오직 소유자만이 알고 있기 때문에, 저자의 개인 키는 일종의 지문처럼 사용된다. 노드 A가 B에게 메시지를 보내고, 서명하는 프로세스는 다음과 같다.

  1. A는 가변 길이 메시지를 정제하여 고정된 길이의 요약으로 만든다.
  2. A는 그 요약에, 사용자의 개인 키를 매개변수로 하는 서명 함수를 적용한다.
  3. 한번 서명이 계산되면, A는 이를 메시지의 끝에 덧붙이고 메시지와 서명을 B에게 전송한다.
  4. B가 메시지를 보낸 사람을 확인하기 위하여 서명을 검사할 수 있다. 개인키로 알아보기 어렵게 변형된 서명에 공개키를 적용한 역함수를 적용한다.

디지털 인증서

디지털 인증서(흔히 certs라 불리는)는 신뢰할 수 있는 기관으로부터 보증 받은 사용자나 회사에 대한 정보를 담고 있다.

인증서의 내부

디지털 인증서에는 또한 공식적으로 ‘인증 기관’에 의해 디지털 서명된 정보의 집합이 담겨 있다. 기본적인 디지털 인증서는 보통 다음과 같이 인쇄된 ID에도 흔히 들어가게 되는 기본적인 것들을 담고 있다.

  • 대상의 이름(사람, 서버, 조직 등)
  • 유효 기간
  • 인증서 발급자(인증서를 보증하는 사람)
  • 인증서 발급자의 디지털 서명

인증서 사용하기

사용자가 HTTPS를 통해 안전한 웹 트랜잭션을 시작할 때, 최신 브라우저는 자동으로 접속한 서버에서 디지털 인증서를 가져온다. 만약 서버가 인증서를 가지고 있지 않다면, 보안 커넥션은 실패한다.

서버 인증서는 다음을 포함한 많은 필드를 가지고 있다.

  • 웹 사이트의 이름과 호스트명
  • 웹 사이트의 공개키
  • 서명 기관의 이름
  • 서명 기관의 서명

브라우저가 인증서를 받으면, 서명 기관을 검사한다. 만약 그 기관이 공공이 신뢰할만한 서명 기관이라면, 브라우저는 그것의 공개키를 미리 알고 있을 것이며, 서명을 검증할 수 있다.

브라우저 암호화 동작 방식

실제로 브라우저는 다음과 같은 방식을 통해 데이터를 주고받는다.

  1. 클라이언트가 서버에 접속한다. 서버에 접속하면서 다음과 같은 데이터를 전송한다.
  • 클라이언트 측에서 생성한 랜덤 데이터
  • 클라이언트가 지원하는 암호화 방식들
  • 세션 아이디
  1. 서버는 응답을 전송한다.
  • 서버 측에서 생성한 랜덤 데이터
  • 서버가 선택한 클라이언트의 암호화 방식 : 클라이언트가 전송한 암호화 방식 중 하나를 택한다.
  • 인증서
  1. 클라이언트는 인증서(certs) 가 정확한 것인지 확인하기 위해 클라이언트에 내장된 CA 리스트를 확인한다. CA 리스트에 인증서가 없다면 사용자에게 경고 메시지를 출력한다. 인증서가 CA 에게서 온 것인지 확인하기 위해, 클라이언트의 공개키로 인증서를 복호화한다. 인증서가 복호화된다는 것은, CA 의 비공개키로 암호화되었다는 의미이므로 이 인증서는 정확한 것임을 알 수 있다.
  2. 클라이언트는 클라이언트 측에서 생성한 랜덤 데이터서버 측에서 생성한 랜덤 데이터 를 조합하여 pre master secret 을 생성한다. pre master secret 대칭키이다. 즉 pre master secret 키로 데이터를 클라이언트에서 암호화하고 서버에서 복호화하게 된다. 그렇기 때문에 이 키는 절대로 노출되지 않고 서버로 전송되어야 한다.
  3. pre master secret 를 인증서에 동봉된 공개키로 암호화한다.
  4. 키를 서버로 전송한다. 서버는 자신의 비공개키로 pre master secret 를 복호화한다.
  5. pre master secret 키로 암호화 한 정보를 전송한다.

정리하면 다음과 같다.

  • 데이터는 대칭키 방식으로 주고받는다.
  • 대칭키는 공개키로 암호화하여 공유한다.

이렇게 하는 이유는, 공개키 방식의 암호화가 매우 많은 컴퓨터 자원을 소비하기 때문이다. 그렇기 때문에 키 교환에만 공개키를 사용하고, 실제 암호화에는 대칭키를 사용한다.