지식

[Security] 암호기술에 대한 최소 이론 8강 — 인터넷 키교환 시스템의 구조: 전달은 비대칭 키로, 데이터는 세션 키로

암호기술에 대한 최소 이론 시리즈 정리 — 8강. 참고: 널널한 개발자 TV, 인터넷 키교환 시스템의 구조 (재생목록)

7강에서 정리한 골격은 이랬다. 통신하려는 두 엔드포인트가 각자 키 쌍(공개키·개인키)을 만들고, 서로 공개키만 교환한 뒤, 받는 사람의 공개키로 암호화하고 받는 사람의 개인키로 복호화한다. 대칭 키가 안고 있던 키 전달 문제가 이걸로 풀린다. 그런데 실제 인터넷은 이 골격을 이대로 쓰지 않는다. 이번에는 왜 그대로 쓰지 않는지, 그래서 실제로는 어떤 구조로 굴러가는지를 정리한다. 이 절차 전체를 부르는 이름이 키 교환, 곧 IKE다.

미리 두 용어만 짚어 둔다. 대칭 키는 암호화와 복호화에 같은 키 하나를 쓰는 방식이고, 비대칭 키는 공개키로 잠그고 짝이 되는 개인키로 여는 방식이다. 이번 이야기는 이 둘을 어떻게 섞어 쓰느냐에 관한 것이다.

첫 번째 이유 — 키 쌍 생성 자체가 비싸다

비대칭 키만으로 통신하려면 통신 주체가 각자 키 쌍을 만들어야 한다. 문제는 키 쌍을 생성하는 연산 자체가 굉장히 비싸다는 데 있다.

알고리즘에 따라 다르지만, i7 코어급을 쓰는 고성능 PC에서도 키 쌍 하나를 만드는 데 1~2초가 걸린다. 그 사이 CPU를 크게 소모한다. 통신 한 번 하겠다고 매번 이 비용을 치르는 것은 부담이다.

여기에 더해 어색한 점이 하나 있다. 그렇게 전산 자원을 크게 써서 만든 키는 수명이 매우 길다. 야외에서 컵라면을 먹을 때 쓰는 나무젓가락은 한 번 쓰고 버려도 아깝지 않다. 그런데 키 쌍은 비싼 쇠젓가락에 가깝다. 큰 비용을 들여 만들어 놓고 통신 한 번에 폐기해 버리면 아깝다. 한두 시간 쓰다 바꾸는 식으로 계속 써도 되기는 하지만, 그렇다면 애초에 통신할 때마다 그 자리에서 만들 이유가 없다.

그래서 미리 만들어 둔다

답은 단순하다. 통신 전에 미리 키 쌍을 생성해 두는 것이다. 이게 핵심이다.

미리 만들어 디스크에 저장해 두고, 실제로 통신할 때가 되면 저장해 둔 키를 꺼내 쓴다. 저장한 개인키가 남에게 읽히지 않는다는 전제는 필요하지만, 그 전제가 지켜지는 한 이 방식이 훨씬 유리하다. 통신을 시작하는 시점에는 키 생성 연산이 아예 없으니 그로 인한 지연도 없다.

  [ 통신 전 ]  키 쌍 생성 (1~2초, CPU 소모) ─▶ 디스크에 저장
                 ├─ 공개키 ── 상대에게 건네는 것
                 └─ 개인키 ── 밖으로 내보내지 않는 것

  [ 통신 시점 ]  저장된 키를 꺼내 쓴다 — 생성 연산 없음

여기까지가 효율에 관한 첫 번째 손질이다. 그리고 효율 이야기를 꺼낸 김에, 대칭 키와 비대칭 키를 효율의 관점에서 비교하면 답이 더 분명해진다.

두 번째 이유 — 효율은 대칭 키가 압도적이다

효율을 기준으로 두 방식을 비교하면 대칭 키가 압도적으로 좋다. CPU를 훨씬 덜 쓴다. 그러면서 보안성도 뒤지지 않는다.

대표 알고리즘만 봐도 감이 온다. 대칭 키 쪽에서 가장 많이 쓰는 것은 AES이고 보통 AES-128을 쓴다. 비대칭 키 쪽에서 가장 많이 쓰는 것은 RSA이고 보통 RSA-2048을 쓴다. 비트 수만 보면 128과 2048로 확연히 차이가 난다. 그러나 비대칭 키는 그 비트를 공개키와 개인키 둘로 쪼개어 쓰는 구조다. 그래서 실제 보안 강도를 비교하면 둘이 엇비슷하거나, 오히려 AES 쪽이 낫다.

이 대응 관계는 표준 기관의 권고에서도 확인된다. NIST가 정리한 등가 강도 기준으로 RSA-2048은 대략 112비트 수준의 보안 강도에 해당하고, AES-128과 같은 128비트 강도를 비대칭 키로 맞추려면 RSA-3072 정도가 필요하다.

구분 대칭 키 비대칭 키
연산 비용 낮다 — CPU를 훨씬 덜 쓴다 높다 — 키 쌍 생성만 해도 고성능 PC에서 1~2초
키 길이 예 AES-128 (128비트) RSA-2048 (2048비트)
실제 보안 강도 128비트 약 112비트 — 키를 둘로 쪼개 쓰므로 비트 수만큼이 아니다
키 전달 문제 있다 — 같은 키를 상대도 가져야 한다 없다 — 공개키는 노출을 전제로 주고받는다
섞어 쓰는 구조에서의 역할 데이터 암호화 전량 대칭 키를 건네는 한 번

결론은 하나다. 쓸 수만 있다면 대칭 키를 쓰는 게 낫다. 대칭 키의 유일한 문제는 그 키를 상대에게 안전하게 전달할 방법이 없다는 것이었다. 그렇다면 그 한 가지 문제만 비대칭 키로 해결하면 된다.

실제 구조 — 둘을 섞어 쓴다

실제 인터넷은 대칭 키만 쓰지도, 비대칭 키만 쓰지도 않는다. 둘을 섞어서 쓴다. 순서는 이렇다.

① 서버 : (통신 전) 키 쌍 생성 — 서버 공개키 + 서버 개인키를 저장
② PC   : (접속 시) 대칭 키 생성 — PC 대칭 키

③ PC ◀──────────── 서버 공개키 ──────────── 서버

④ PC ──── PC 대칭 키를 서버 공개키로 암호화 ────▶ 서버

⑤ 서버 : 서버 개인키로 복호화 → PC 대칭 키 획득

⑥ PC ◀═══ 이후 데이터는 PC 대칭 키로 암호화·복호화 (양방향) ═══▶ 서버

단계별로 보면 이렇다.

① 서버의 사전 키 쌍 생성. 서버는 통신이 시작되기 전에 자기 공개키와 개인키를 만들어 둔다. 공개키는 암호화에만, 개인키는 복호화에만 쓴다.

② PC의 대칭 키 생성. PC는 서버에 접속하려는 시점에 대칭 키(symmetric key) 를 하나 만든다. 비대칭 키 쌍이 아니라 대칭 키다. 이 키 하나로 암호화도 복호화도 다 된다. 단점은 앞서 말한 그 하나, 안전하게 전달하기 어렵다는 것뿐이다.

③ 공개키 전달. 서버가 자신의 공개키를 PC에 보낸다. 이 공개키는 노출돼도 무방하다. 암호화에만 쓰이는 물건이기 때문이다.

④ 대칭 키를 공개키로 암호화해 전달. 여기가 핵심이다. PC는 자기가 만든 대칭 키를 그냥 보내지 않는다. 받은 서버의 공개키로 그 대칭 키 자체를 암호화해서 보낸다. 퍼블릭 구간을 지나는 것은 암호문이므로 중간에서 가로채도 대칭 키를 알 수 없다.

⑤ 개인키로 복호화. 서버는 도착한 암호문을 자기 개인키로 푼다. 그러면 안에서 PC의 대칭 키가 나온다. 개인키는 서버 밖으로 나간 적이 없으니 이 복호화는 서버만 할 수 있다.

⑥ 대칭 키로 데이터 통신. 이제 양쪽이 같은 대칭 키를 갖고 있다. PC는 평문 데이터를 그 대칭 키로 암호화해서 보내고, 서버는 그 대칭 키로 복호화해 평문을 되찾는다. 반대 방향도 같은 키로 처리한다.

명령으로 옮기면 각 단계가 어떤 연산인지 더 분명해진다.

# ① 서버: 통신 전에 미리 키 쌍을 만들어 저장해 둔다
openssl genrsa -out server-private.pem 2048
openssl rsa -in server-private.pem -pubout -out server-public.pem

# ② PC: 접속 시점에 대칭 키(AES-128용 16바이트)를 생성한다
openssl rand -out session.key 16

# ④ PC: 그 대칭 키를 서버의 공개키로 암호화해서 보낸다
openssl pkeyutl -encrypt -pubin -inkey server-public.pem \
  -in session.key -out session.key.enc

# ⑤ 서버: 자기 개인키로 복호화해 대칭 키를 얻는다
openssl pkeyutl -decrypt -inkey server-private.pem \
  -in session.key.enc -out session.key

비대칭 연산이 걸리는 곳은 ④와 ⑤ 딱 한 번뿐이고, 그 대상도 16바이트짜리 키 하나다. 그 뒤로 오가는 데이터는 전부 대칭 키가 처리한다.

  키 교환 = 비대칭 키의 일   (대칭 키를 한 번 안전하게 건넨다)
  데이터  = 대칭 키의 일     (효율 좋게 전량을 암호화한다)

섞어 쓰면 무엇이 좋아지나

이 구조의 이점은 세 갈래다.

첫째, 대칭 키의 유일한 한계가 사라진다. 키를 안전하게 전달하지 못하는 것이 대칭 키의 한계였는데, 비대칭 키 체계를 섞으니 그 전달이 가능해진다. 그러면서 데이터 암호화는 효율 좋은 대칭 키가 맡는다. 각자 잘하는 일만 한다.

둘째, 세션마다 키가 달라져 보안성이 올라간다. 대칭 키를 만드는 쪽은 PC, 즉 클라이언트다. 큰 서비스라면 같은 서버에 접속하는 PC가 수백 수천 대다. 그 PC들이 각자 자기 대칭 키를 따로 만든다. 그러니 데이터 암호화에 쓰이는 키가 접속마다 전부 다르다. 하나가 뚫려도 그 하나의 연결에서 끝난다.

셋째, 키 생성 지연이 없다. 비싼 쪽인 서버 키 쌍은 통신 전에 미리 만들어 두었고, 접속 시점에 만드는 것은 대칭 키뿐이다.

항목 비대칭 키만 쓰는 골격 섞어 쓰는 구조
키 쌍 생성 양쪽 다, 통신할 때마다 서버만, 통신 전에 미리
주고받는 것 서로의 공개키 서버 공개키 + 공개키로 암호화한 대칭 키
데이터 암호화 비대칭 키 대칭 키
연산 부담 크다 — 데이터 전량이 비대칭 연산 작다 — 비대칭 연산은 키 전달 1회
접속마다 키 키 쌍 수명이 길어 사실상 고정 접속마다 새 대칭 키
접속 시 키 생성 지연 있다 없다

이렇게 대칭 키와 비대칭 키를 함께 쓰는 방식을 하이브리드 암호화라고 부른다.

세션 키와 IKE

PC와 서버 사이의 연결 하나를 세션이라고 한다. 이 구조에서 PC가 만들어 서버에 건네는 대칭 키는 그 세션 동안만 쓰이는 키다. 그래서 이 대칭 키를 다른 말로 세션 키(session key) 라고도 한다.

그리고 지금까지의 절차 전체 — 서버가 공개키를 보내고, 클라이언트가 세션 키를 그 공개키로 암호화해 보내고, 서버가 자기 개인키로 풀어 세션 키를 공유하게 되는 과정 — 이것이 키 교환(key exchange) 이다. 인터넷에서 이 일을 한다고 해서 약어로 IKE(Internet Key Exchange) 라고 많이 쓴다.

  IKE = Internet Key Exchange

    서버   : 미리 만든 키 쌍 중 공개키를 보낸다
    클라이언트 : 세션 키를 만들어 그 공개키로 암호화해 보낸다
    서버   : 개인키로 풀어 세션 키를 공유한다
    → 이후 통신은 세션 키(대칭 키)로

물론 이것으로 끝은 아니다. 이 구조에도 아직 남은 구멍이 있다.

정리

  • 비대칭 키만으로 통신하지 않는 첫 번째 이유는 키 쌍 생성 연산이 비싸다는 것이다. 고성능 PC에서도 1~2초가 걸리고 CPU를 크게 쓴다. 그렇게 만든 키의 수명은 매우 길다.
  • 그래서 키 쌍은 통신할 때마다 만들지 않고 통신 전에 미리 생성해 디스크에 저장해 둔다. 접속 시점의 키 생성 지연이 사라진다.
  • 두 번째 이유는 효율이다. 대칭 키가 비대칭 키보다 압도적으로 효율이 좋다. CPU를 훨씬 덜 쓰고, 비대칭 키는 키를 둘로 쪼개 쓰므로 비트 수 차이만큼 보안 강도가 앞서지도 않는다(AES-128 대 RSA-2048).
  • 그래서 실제 구조는 둘을 섞어 쓴다 — ① 서버는 미리 키 쌍을 만들어 두고, ② PC는 접속할 때 대칭 키를 만들고, ③ 서버가 공개키를 보내고, ④ PC가 대칭 키를 그 공개키로 암호화해 보내고, ⑤ 서버가 개인키로 풀어 대칭 키를 얻고, ⑥ 이후 데이터는 그 대칭 키로 주고받는다.
  • 이 구조의 이점은 셋이다 — 대칭 키의 키 전달 문제를 비대칭 키가 풀어 주고, 데이터 암호화는 효율 좋은 대칭 키가 맡고, 접속하는 PC마다 다른 키를 만드니 세션마다 키가 달라진다.
  • 이때의 대칭 키를 세션 키(session key) 라고도 한다. 그리고 이 절차 전체가 키 교환, 약어로 IKE(Internet Key Exchange) 다.

다음 편은 이 키 교환 구조를 공격하는 원리, 중간자 공격이다.

조회 1댓글 0

댓글

아직 댓글이 없습니다. 첫 댓글을 남겨보세요.