네트워크 보안의 원리 (1) - 암호화의 수학적 기초 - soo:bak
작성일 :
네트워크에서 보안이 필요한 이유
네트워크 통신의 원리 시리즈에서 데이터가 어떻게 전송되는지 살펴보았습니다.
하지만 문제가 있습니다.
네트워크를 지나는 데이터는 노출되기 쉽습니다. 이더넷은 같은 세그먼트의 모든 트래픽이 보이고, Wi-Fi는 공기 중에 방송되며, 인터넷은 수많은 라우터를 거칩니다. 이 중 어디서든 도청이 가능합니다.
네트워크 보안에는 세 가지 목표가 있습니다.
- 기밀성(Confidentiality): 허가되지 않은 자가 내용을 볼 수 없어야 합니다.
- 무결성(Integrity): 데이터가 전송 중 변조되지 않았음을 보장합니다.
- 인증(Authentication): 통신 상대방이 실제로 그 사람인지 확인합니다.
이 세 가지를 달성하는 핵심 도구가 암호화(Cryptography)입니다.
암호화의 기본 개념
암호화는 평문(plaintext)을 암호문(ciphertext)으로 변환하는 것이고, 복호화는 암호문을 다시 평문으로 변환하는 것입니다.
1
2
평문 ──[암호화]──► 암호문 ──[복호화]──► 평문
키 사용 키 사용
여기서 키(Key)가 핵심입니다. 같은 알고리즘을 사용해도 키가 다르면 결과가 다르고, 키를 모르면 복호화할 수 없습니다.
암호화 방식은 크게 두 가지로 나뉩니다.
- 대칭키 암호(Symmetric Key): 암호화와 복호화에 같은 키를 사용합니다.
- 비대칭키 암호(Asymmetric Key): 서로 다른 키를 사용합니다.
대칭키 암호: 빠르고 효율적
대칭키 암호는 암호화와 복호화에 동일한 키를 사용합니다.
연산이 빠르고 계산 비용이 적습니다. 하지만 단점도 있습니다. 키를 어떻게 안전하게 전달할 것인가 하는 키 교환 문제가 있고, 통신 상대마다 별도의 키가 필요합니다. n명이 서로 통신하려면 n(n-1)/2개의 키가 필요합니다.
대표적인 대칭키 알고리즘은 AES(Advanced Encryption Standard)입니다.
AES: 현대 대칭키 암호의 표준
AES는 2001년 미국 국립표준기술연구소(NIST)가 선정한 표준입니다.
AES는 데이터를 16바이트씩 잘라서 암호화합니다. 각 조각을 블록이라고 부릅니다.
암호화 과정은 여러 번 반복되는데, 한 번의 반복을 라운드라고 합니다. 키 길이는 128, 192, 256비트 세 가지 중 선택하며, 각각 10, 12, 14라운드를 수행합니다.
각 라운드에서는 값을 바꾸고(치환), 위치를 섞는(순열) 과정을 거칩니다.
한 라운드는 네 단계로 구성됩니다.
- SubBytes: 각 바이트를 정해진 표에 따라 다른 값으로 바꿉니다.
- ShiftRows: 각 행을 옆으로 밀어서 위치를 바꿉니다.
- MixColumns: 각 열의 바이트들을 서로 섞습니다.
- AddRoundKey: 키와 섞습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
입력 블록 (16바이트)
│
▼
┌─────────────┐
│ SubBytes │ ← 값 치환
└─────────────┘
│
▼
┌─────────────┐
│ ShiftRows │ ← 행 이동
└─────────────┘
│
▼
┌─────────────┐
│ MixColumns │ ← 열 섞기
└─────────────┘
│
▼
┌─────────────┐
│AddRoundKey │ ← 키와 섞음
└─────────────┘
│
▼
(반복)
왜 이렇게 설계했을까요? 두 가지 목표가 있습니다.
혼돈(Confusion): 키와 암호문의 관계를 복잡하게 만듭니다. SubBytes가 이 역할을 합니다.
확산(Diffusion): 평문의 한 비트가 바뀌면 암호문의 많은 비트가 바뀌도록 합니다. ShiftRows와 MixColumns가 이 역할을 합니다.
이 두 성질이 결합되어 통계적 분석을 어렵게 만듭니다.
블록 암호 운용 모드
AES는 16바이트씩 암호화합니다. 긴 데이터는 여러 블록으로 나뉘는데, 이 블록들을 어떻게 처리할까요?
ECB(Electronic Codebook)는 가장 단순한 방식입니다. 각 블록을 독립적으로 암호화합니다.
1
2
3
평문1 ──[암호화]──► 암호문1
평문2 ──[암호화]──► 암호문2
평문3 ──[암호화]──► 암호문3
하지만 문제가 있습니다. “AAAA”를 암호화하면 같은 블록이 반복되어 “XXXX”처럼 됩니다. 암호문만 봐도 “같은 내용이 반복되는구나”를 알 수 있습니다. 이미지를 ECB로 암호화하면 같은 색 영역이 같은 패턴으로 나타나서, 암호화 후에도 원본 모양이 드러납니다.
CBC(Cipher Block Chaining)는 이 문제를 해결합니다. 각 블록을 암호화하기 전에 이전 암호문과 섞습니다. 같은 평문이라도 앞 블록이 다르면 결과가 달라집니다.
1
2
3
평문1 + IV ──[암호화]──► 암호문1
평문2 + 암호문1 ──[암호화]──► 암호문2
평문3 + 암호문2 ──[암호화]──► 암호문3
첫 블록은 이전 암호문이 없으므로 IV(Initialization Vector)라는 무작위 값을 사용합니다. IV가 다르면 같은 데이터도 완전히 다른 암호문이 됩니다.
GCM(Galois/Counter Mode)은 암호화와 무결성 검증을 동시에 제공합니다.
CBC는 패턴을 숨기지만, 암호문이 중간에 변조되었는지는 알 수 없습니다. 공격자가 암호문의 일부를 바꿔도 복호화는 진행됩니다. GCM은 이 문제를 해결합니다.
1
2
3
평문1 + 1 ──[암호화]──► 암호문1 ─┐
평문2 + 2 ──[암호화]──► 암호문2 ─┼──► 인증 태그
평문3 + 3 ──[암호화]──► 암호문3 ─┘
각 블록마다 1, 2, 3처럼 다른 순서 번호를 섞어서 패턴을 숨깁니다. 그리고 모든 암호문을 수학적으로 조합하여 인증 태그(Authentication Tag)를 만듭니다.
수신자는 같은 방식으로 태그를 계산하고, 받은 태그와 비교합니다. 일치하지 않으면 암호문이 변조된 것이므로 복호화를 거부합니다.
GCM은 현대 네트워크 보안에서 가장 널리 사용됩니다.
TLS(Transport Layer Security)는 인터넷에서 데이터를 암호화하여 전송하는 표준 프로토콜입니다. 웹 브라우저에서 https://로 접속할 때 TLS가 사용됩니다. TLS 1.3(최신 버전)에서는 AES-GCM이 필수입니다.
비대칭키 암호: 키 교환 문제의 해결
대칭키 암호는 빠르지만, 키를 어떻게 안전하게 공유할지가 문제입니다. 키를 전달하는 과정에서 도청당하면 암호화의 의미가 없습니다.
비대칭키 암호(Asymmetric Key Cryptography)는 이 문제를 해결합니다. 공개키 암호화(Public Key Cryptography)라고도 부릅니다.
핵심 아이디어는 두 개의 키를 사용하는 것입니다.
- 공개키(Public Key): 누구에게나 공개
- 개인키(Private Key): 본인만 보관
이 두 키로 두 가지 기능을 수행합니다.
암호화와 복호화 (내용을 숨김):
- 송신자는 수신자의 공개키로 암호화합니다
- 수신자는 자신의 개인키로 복호화합니다
- 개인키는 수신자만 가지고 있으므로, 수신자만 읽을 수 있습니다
서명과 검증 (보낸 사람을 증명):
- 송신자는 자신의 개인키로 서명합니다
- 수신자는 송신자의 공개키로 검증합니다
- 개인키는 송신자만 가지고 있으므로, 검증이 성공하면 송신자가 보낸 것입니다
어떻게 이것이 수학적으로 가능할까요?
RSA: 소인수분해의 어려움
RSA는 대표적인 비대칭키 알고리즘입니다. 이름은 발명자 세 명의 이니셜입니다.
핵심 원리는 곱셈은 쉽지만 소인수분해는 어렵다는 것입니다.
- 3 × 5 = 15 (쉬움)
- 15 = ? × ? (작은 수는 쉬움)
- 2048비트 수 = ? × ? (현재 기술로 불가능)
키 생성 과정:
- 두 개의 큰 소수 p와 q를 선택합니다 (예: p=17, q=19)
- 두 수를 곱합니다: N = p × q = 323
- (p-1) × (q-1)을 계산합니다: 16 × 18 = 288
- 288을 이용해 공개키와 개인키를 계산합니다
공개키: N(323)과 암호화용 숫자 개인키: 복호화용 숫자 (288을 알아야 계산 가능)
여기서 핵심은 3번입니다. (p-1) × (q-1)을 계산하려면 p와 q를 따로 알아야 합니다.
- p=17, q=19를 알면 → (17-1) × (19-1) = 288 계산 가능 → 개인키 계산 가능
- N=323만 알면 → p와 q를 모르므로 → 288을 계산할 수 없음 → 개인키 계산 불가능
암호화와 복호화:
1
2
송신자: 평문 → [공개키로 암호화] → 암호문
수신자: 암호문 → [개인키로 복호화] → 평문
왜 안전한가?
공격자는 공개키(N)를 알 수 있습니다. 하지만 개인키를 계산하려면 (p-1)×(q-1)이 필요하고, 이를 위해서는 p와 q를 따로 알아야 합니다.
N에서 p와 q를 알아내는 것이 소인수분해입니다.
1
2
3
4
5
공개키: N = 323 (공개)
↓
323 = ? × ? ← 소인수분해
↓
17 × 19 ← 작은 수는 쉬움
323처럼 작은 수는 쉽게 분해됩니다. 하지만 2048비트(약 600자리) 수는 현재 컴퓨터로 분해할 수 없습니다. 우주의 나이보다 긴 시간이 걸릴 것으로 추정됩니다.
단, 양자 컴퓨터가 실용화되면 달라질 수 있습니다.
Diffie-Hellman: 안전한 키 교환
비대칭키 암호는 안전하지만 계산 비용이 큽니다. 대칭키 암호는 빠르지만 키 공유가 문제입니다.
해결책: 비대칭키 방식으로 대칭키를 안전하게 교환하고, 이후 통신은 대칭키로 암호화합니다.
Diffie-Hellman 키 교환은 도청자가 있는 공개 채널에서도 두 사람이 같은 비밀 값을 만들어내는 방법입니다.
핵심 원리:
RSA가 “곱셈은 쉽고 소인수분해는 어렵다”를 이용했다면, Diffie-Hellman은 “거듭제곱은 쉽고 로그는 어렵다”를 이용합니다.
- 2^10 = 1024 (거듭제곱: 쉬움)
- 2^? = 1024 → ?=10 (로그: 작은 수는 쉬움)
- 큰 수에서 로그를 찾는 것은 현재 기술로 불가능
이것을 이산 로그 문제라고 합니다.
키 교환 과정:
- 송신자와 수신자가 공개 값 g와 p를 정합니다 (도청자도 알 수 있음)
- 송신자는 비밀 값 a를 선택하고, g^a mod p를 계산해서 보냅니다
- 수신자는 비밀 값 b를 선택하고, g^b mod p를 계산해서 보냅니다
- 송신자는 받은 값에 a를 적용: (g^b)^a = g^(ab)
- 수신자는 받은 값에 b를 적용: (g^a)^b = g^(ab)
둘 다 같은 값 g^(ab)를 얻습니다. 이 값을 대칭키로 사용합니다.
왜 안전한가?
도청자는 g, p, g^a, g^b를 모두 볼 수 있습니다. 하지만 g^(ab)를 계산하려면 a나 b를 알아야 합니다.
g^a에서 a를 알아내는 것이 이산 로그 문제입니다. 큰 수에서는 이것이 불가능합니다.
ECDH(Elliptic Curve Diffie-Hellman)
Diffie-Hellman의 변형으로, 타원곡선이라는 수학 구조를 이용합니다.
같은 보안 수준을 더 짧은 키로 달성할 수 있습니다.
| 알고리즘 | 키 크기 | 보안 수준 |
|---|---|---|
| RSA | 2048비트 | 동등 |
| ECDH | 224비트 | 동등 |
키가 짧으면 계산이 빠르고 전송할 데이터도 적습니다. 그래서 모바일 기기나 IoT처럼 자원이 제한된 환경에서 많이 사용됩니다.
전방향 비밀성: 키가 유출되어도 과거는 안전하게
공격자가 암호화된 통신을 몰래 저장해둔다고 가정합니다. 지금은 복호화할 수 없지만, 나중에 서버의 개인키가 유출되면 저장해둔 모든 과거 통신을 복호화할 수 있습니다.
전방향 비밀성(Forward Secrecy)은 이 문제를 해결합니다. 개인키가 유출되어도 과거 통신은 복호화할 수 없도록 합니다.
해결 방법: 임시 키 사용
Diffie-Hellman으로 키를 교환할 때, 매 세션마다 새로운 임시 키를 생성합니다. 세션이 끝나면 임시 키를 폐기합니다.
세션(Session)은 한 번의 연결을 의미합니다. 예를 들어 웹사이트에 접속해서 나갈 때까지가 하나의 세션입니다.
1
2
3
세션 1: 임시 키 생성 → 통신 → 임시 키 폐기
세션 2: 임시 키 생성 → 통신 → 임시 키 폐기
세션 3: 임시 키 생성 → 통신 → 임시 키 폐기
서버의 장기 개인키가 나중에 유출되어도, 각 연결의 임시 키는 이미 폐기되었으므로 과거 통신을 복호화할 수 없습니다.
TLS 1.3은 전방향 비밀성을 필수로 요구합니다. 임시 Diffie-Hellman(DHE) 또는 임시 ECDH(ECDHE)만 허용됩니다.
해시 함수: 데이터의 지문
사람마다 고유한 지문이 있듯이, 데이터에도 고유한 “지문”을 만들 수 있습니다.
해시 함수는 어떤 길이의 데이터든 고정된 길이의 값으로 변환합니다. 이 값을 해시값이라고 합니다.
1
2
1KB 파일 ──[SHA-256]──► 256비트 해시값
1GB 파일 ──[SHA-256]──► 256비트 해시값
입력 크기와 관계없이 항상 같은 크기의 해시값이 나옵니다. 덕분에 대용량 파일도 짧은 해시값만 비교하면 동일 여부를 확인할 수 있습니다.
1
2
"Hello" ──[SHA-256]──► 185f8db32271fe25f561a6fc938b2e26...
"Hello!" ──[SHA-256]──► 33b55d...
느낌표 하나만 추가해도 해시값이 완전히 달라집니다. 덕분에 원본을 조금만 변조해도 해시값이 달라지므로, 데이터 변조 여부를 쉽게 감지할 수 있습니다.
해시 함수의 특징:
- 일방향성: 해시값에서 원본을 역으로 찾을 수 없습니다
- 충돌 저항성: 같은 해시값을 가지는 서로 다른 두 입력을 찾기 어렵습니다
- 눈사태 효과: 입력이 조금만 바뀌어도 해시값이 완전히 달라집니다
주요 해시 함수:
| 이름 | 출력 크기 | 상태 |
|---|---|---|
| MD5 | 128비트 | 취약점 발견, 사용 금지 |
| SHA-1 | 160비트 | 취약점 발견, 사용 금지 |
| SHA-256 | 256비트 | 현재 안전, 널리 사용 |
“취약점 발견”은 같은 해시값을 가지는 서로 다른 입력을 찾아냈다는 의미입니다. 지문이 겹치면 고유성이 깨지므로 더 이상 안전하지 않습니다.
해시의 용도:
1. 무결성 검증
파일을 다운로드할 때, 중간에 변조되었는지 확인할 수 있습니다.
1
2
3
원본 파일 해시값: a1b2c3d4...
다운로드 후 해시값: a1b2c3d4... → 일치하면 변조 없음
다운로드 후 해시값: x9y8z7w6... → 다르면 변조됨
소프트웨어 다운로드 페이지에서 SHA-256 해시값을 함께 제공하는 이유입니다.
2. 비밀번호 저장
서버는 비밀번호 원본을 저장하지 않고 해시값만 저장합니다.
1
2
사용자 입력: "mypassword123"
저장된 값: 해시("mypassword123") = 5f4d...
로그인할 때 입력된 비밀번호의 해시값과 저장된 해시값을 비교합니다. 서버가 해킹되어도 해시값에서 원본 비밀번호를 알아낼 수 없습니다.
3. 디지털 서명
앞서 살펴본 서명은 개인키로 암호화하는 과정입니다. 긴 문서 전체를 암호화하면 시간이 오래 걸립니다.
1
2
3
4
5
6
7
서명 생성:
문서 (10MB) → 해시값 (256비트) → [개인키로 암호화] → 서명
서명 검증:
문서 → 해시값 계산 ─┐
├─ 두 값이 같으면 검증 성공
서명 → [공개키로 복호화] → 해시값 ─┘
문서 전체(10MB) 대신 해시값(256비트)만 암호화하면 빠르게 처리됩니다. 문서가 조금이라도 바뀌면 해시값이 달라지므로, 검증 시 두 해시값이 일치하지 않아 변조를 감지할 수 있습니다.
HMAC: 키가 있는 해시
일반 해시는 누구나 계산할 수 있습니다. 공격자가 메시지를 변조한 후 새로운 해시값을 계산해서 함께 보내면, 수신자는 변조를 감지할 수 없습니다.
1
2
3
4
공격 시나리오:
원본: "100원 송금" + 해시값
공격자: "10000원 송금" + 새 해시값 계산해서 교체
수신자: 해시값 일치 → 변조 감지 실패
HMAC(Hash-based Message Authentication Code)은 해시 계산에 비밀 키를 사용합니다.
1
2
송신자: 메시지 + 비밀키 → HMAC 값 생성
수신자: 메시지 + 같은 비밀키 → HMAC 값 계산 → 비교
공격자는 비밀 키를 모르므로 올바른 HMAC 값을 만들 수 없습니다. 메시지를 변조해도 HMAC 값을 새로 계산할 수 없어서 수신자가 변조를 감지할 수 있습니다.
HMAC-SHA256은 TLS에서 메시지가 변조되지 않았음을 확인하는 데 사용됩니다.
디지털 서명: 부인 방지
HMAC은 송신자와 수신자가 같은 키를 공유합니다. 그래서 문제가 있습니다.
예를 들어, A가 B에게 “100만원을 송금하겠다”는 메시지를 HMAC과 함께 보냈다고 가정합니다. 나중에 A가 “나는 그런 메시지를 보낸 적 없다”고 주장하면 어떻게 될까요?
- B도 같은 키를 알고 있으므로, B가 메시지와 HMAC을 직접 만들었을 수도 있습니다
- 제3자(법원 등)는 A가 보냈는지 B가 만들었는지 구분할 수 없습니다
즉, 송신자가 나중에 “나는 보낸 적 없다”고 부인할 수 있습니다. 이것을 부인(Repudiation)이라고 합니다.
디지털 서명은 비대칭키를 사용하여 이 문제를 해결합니다.
1
2
3
4
5
6
7
서명 생성 (송신자):
메시지 → 해시값 → [개인키로 암호화] → 서명
서명 검증 (수신자 또는 제3자):
메시지 → 해시값 계산 ─┐
├─ 일치하면 검증 성공
서명 → [공개키로 복호화] → 해시값 ─┘
서명은 개인키로만 생성할 수 있고, 개인키는 A만 가지고 있습니다. B는 A의 개인키를 모르므로 서명을 만들 수 없습니다.
따라서 서명이 유효하면 A가 보낸 것이 확실합니다. A는 “보낸 적 없다”고 부인할 수 없습니다. 이것을 부인 방지(Non-repudiation)라고 합니다.
디지털 서명은 세 가지를 보장합니다.
- 인증: 서명이 유효하면 개인키 소유자가 보낸 것입니다
- 무결성: 메시지가 변조되면 해시값이 달라져 서명 검증에 실패합니다
- 부인 방지: 개인키는 본인만 가지고 있으므로 “보낸 적 없다”고 부인할 수 없습니다
암호화 시스템의 조합
지금까지 살펴본 암호화 기법들은 각각 장단점이 있습니다.
| 방식 | 장점 | 단점 |
|---|---|---|
| 대칭키 (AES) | 빠름 | 키 공유가 어려움 |
| 비대칭키 (RSA) | 키 공유 쉬움 | 느림 |
실제 시스템은 두 방식을 조합하여 각각의 장점만 활용합니다. 이것을 하이브리드 암호화라고 합니다.
하이브리드 암호화 과정:
- 이번 연결에서만 사용할 임시 대칭키를 생성합니다
- 이 대칭키를 수신자의 공개키로 암호화하여 전송합니다 (RSA - 작은 데이터)
- 실제 데이터는 대칭키로 암호화하여 전송합니다 (AES - 빠름)
1
2
3
4
5
6
7
송신자:
임시 대칭키 생성 → [공개키로 암호화] → 암호화된 대칭키 전송
데이터 → [대칭키로 암호화] → 암호화된 데이터 전송
수신자:
암호화된 대칭키 → [개인키로 복호화] → 대칭키 획득
암호화된 데이터 → [대칭키로 복호화] → 원본 데이터
비대칭키(RSA)로 대칭키를 안전하게 교환하고, 대칭키(AES)로 대용량 데이터를 빠르게 암호화합니다.
마무리
이 글에서 살펴본 내용을 정리하면:
- 대칭키 암호(AES): 같은 키로 암호화/복호화, 빠르지만 키 공유가 어려움
- 비대칭키 암호(RSA): 공개키/개인키 쌍 사용, 키 공유 문제 해결
- Diffie-Hellman: 공개 채널에서 안전하게 대칭키를 교환하는 방법
- 전방향 비밀성: 임시 키를 사용하여 과거 통신을 보호
- 해시 함수: 데이터의 고유한 지문, 변조 감지에 사용
- HMAC: 비밀 키를 사용한 해시로 메시지 인증
- 디지털 서명: 비대칭키로 송신자를 증명하고 부인 방지
실제 시스템은 이 기법들을 조합하여 사용합니다. 비대칭키로 대칭키를 교환하고, 대칭키로 데이터를 암호화하는 하이브리드 방식이 대표적입니다.
Part 2에서는 이런 암호화 기법들이 TLS에서 어떻게 조합되어 안전한 연결을 만드는지 살펴봅니다.
관련 글