Crypto
Crypto
암호 기술(Cryptography)은 데이터를 안전하게 저장하고 전달하기 위해 다음 네 가지 보안 목표를 달성하는 것을 목적으로 함
| 보안 목표 | 의미 | 주요 기술 |
|---|---|---|
| Confidentiality(기밀성) | 허가된 사용자만 데이터의 내용을 볼 수 있음 | 암호화(AES, RSA) |
| Integrity(무결성) | 데이터가 중간에 변경되지 않았음을 보장 | Hash, MAC, 전자서명 |
| Authentication(인증) | 데이터를 보낸 상대가 누구인지 확인 | MAC, 전자서명, 인증서 |
| Non-repudiation(부인방지) | 보낸 사람이 나중에 “보내지 않았다”고 부인할 수 없음 | 전자서명 |
Crypto 기술의 역할
데이터 보안 서비스
| 서비스 | 기술 | 대표 알고리즘 |
|---|---|---|
| 데이터 기밀성 | Encryption | AES(+RSA) |
| 데이터 요약 / 변경 감지 | HASH | SHA-256 |
| 메시지 인증 | MAC | HMAC |
| 부인방지 | Digital Signature | RSA / DSA / ECDSA |
- AES(+RSA) : 실제로는 대용량 데이터를 빠른 대칭키(AES)로 암호화하고, 그 대칭키만 느린 비대칭키(RSA 등)로 암호화해 전달하는 하이브리드 암호화 방식을 주로 사용함
키 기반
| 서비스 | 기술 | 대표 알고리즘 |
|---|---|---|
| 난수 생성 | CSPRNG | DRBG / OS 난수원 |
| 키 쌍 생성 | Key Pair Generation | RSA, EC(P-256) |
| 키 합의 | Key Agreement | DH, ECDH |
| 키 유도 | KDF | HKDF, PBKDF2 |
| Public Key의 소유자 인증 | Certificate | X.509 |
- 데이터 보안 서비스는 결국 키를 기반으로 동작하므로, 키를 안전하게 만들고(생성), 나누고(합의), 파생시키고(유도), 신뢰할 수 있게(인증서) 하는 기술이 함께 필요함
대칭키 & AES
대칭키 암호화
- 암호화와 복호화에 동일한 Secret Key를 사용하는 방식
1
2
3
Secret Key Secret Key
│ │
Plaintext ─▶ [암호화] ─▶ Ciphertext ─▶ [복호화] ─▶ Plaintext
- 장점 : 연산이 빠르고 대용량 데이터 암호화에 적합함
- 단점 : 송신자와 수신자가 같은 키를 미리 안전하게 공유해야 함 (키 분배 문제)
- N명이 서로 1:1로 통신하려면 N(N-1)/2개의 키가 필요해 키 관리가 어려움
- 이 문제를 해결하기 위해 비대칭키, DH/ECDH 같은 키 합의 기술을 함께 사용함
- 종류
- Block Cipher : 데이터를 고정 크기 블록 단위로 암호화 (AES, DES, ARIA, SEED)
- Stream Cipher : 데이터를 비트/바이트 단위로 Key Stream과 XOR해서 암호화 (ChaCha20)
왜 N(N-1)/2개의 키가 필요할까?
- 모든 사람이 같은 키 하나를 쓰면 A가 B에게 보낸 메시지를 C도 복호화할 수 있음
- A와 B 사이의 비밀을 지키려면 A-B만 아는 키가 따로 있어야 함
- 즉, 두 사람마다 서로 다른 키가 하나씩 필요함 → 키 개수 = N명 중 2명을 고르는 경우의 수
- 계산
- 한 사람은 자기를 제외한 N-1명과 각각 키가 필요함
- N명 × (N-1)개로 세면 A-B 키와 B-A 키를 두 번 센 것이므로(같은 키) 2로 나눔
1
N(N-1) / 2 = N명 중 2명을 고르는 조합 nC2
- 예시 (N = 4)
1
2
3
4
5
A
/ | \
B──┼──C 키 : A-B, A-C, A-D, B-C, B-D, C-D
\ | / → 4 × 3 / 2 = 6개
D
| 사용자 수(N) | 대칭키 개수 N(N-1)/2 | 비대칭키 개수 2N |
|---|---|---|
| 4 | 6 | 8 |
| 10 | 45 | 20 |
| 100 | 4,950 | 200 |
| 1,000 | 499,500 | 2,000 |
- 대칭키는 사용자가 늘어날수록 키 개수가 N²에 비례해 증가하므로 키 분배, 보관, 교체 부담이 커짐
- 비대칭키는 각자 공개키 1개 + 개인키 1개만 가지면 됨
- 누구에게 보내든 받는 사람의 공개키로 암호화하면 되므로 전체 키는 2N개
AES(Advanced Encryption Standard)
- 대표적인 대칭키 Block Cipher로, 2001년 NIST가 DES를 대체하는 표준으로 채택함 (원래 이름 : Rijndael)
- Block Size : 128bit(16byte)
- Key Size에 따라 라운드 수가 달라짐
| 구분 | Key Size | Round 수 |
|---|---|---|
| AES-128 | 128bit | 10 |
| AES-192 | 192bit | 12 |
| AES-256 | 256bit | 14 |
- Round
- 암호 알고리즘 내에서 암호화할 데이터 블록을 여러 번 반복적으로 변환하는 과정
- 라운드 수가 많을수록 암호 알고리즘 강도는 높아지며 이를 통해 공격에 대한 저항성이 높아짐
AES 동작 과정
- 16byte 평문 블록을 4x4 바이트 행렬(State)로 배치함
- Key Expansion : 원래의 Key로부터 각 라운드에서 사용할 Round Key들을 생성함
- 초기 라운드 :
AddRoundKey - 반복 라운드 (AES-128 기준 9번) : 아래 4단계를 순서대로 수행
SubBytes: S-Box 테이블을 이용해 각 바이트를 다른 바이트로 치환 (비선형성 → 혼돈, Confusion)ShiftRows: 각 행을 0, 1, 2, 3칸씩 왼쪽으로 회전 이동MixColumns: 각 열을 행렬 곱셈으로 섞음 (ShiftRows와 함께 → 확산, Diffusion)AddRoundKey: State와 Round Key를 XOR
- 마지막 라운드 :
MixColumns를 제외한SubBytes→ShiftRows→AddRoundKey - 최종 State가 Ciphertext가 됨
- 복호화는 각 단계의 역연산(InvSubBytes, InvShiftRows, InvMixColumns)을 역순으로 수행함
혼돈(Confusion) : 키와 암호문의 관계를 복잡하게 만듦 확산(Diffusion) : 평문 1bit의 변화가 암호문 전체에 퍼지도록 만듦
블록 암호 운용 모드(Mode of Operation)
- AES는 한 번에 16byte만 암호화할 수 있으므로, 16byte보다 긴 데이터를 암호화하려면 블록들을 어떻게 연결할지 정해야 함 → 운용 모드
- 평문 길이가 블록 크기의 배수가 아니면 패딩(Padding, 주로 PKCS#7)이 필요한 모드(ECB, CBC)와 필요 없는 모드(CTR, GCM, CCM)가 있음
AES-ECB(Electronic Code Book)
- 각 Plaintext Block을 독립적으로 암호화
1
2
3
4
5
P1 P2 P3
│ │ │
[AES(K)] [AES(K)] [AES(K)]
│ │ │
C1 C2 C3
Ci = E(K, Pi)- 장점 : 구조가 단순하고 블록별 병렬 처리가 가능함
- 단점 : 같은 평문 블록은 항상 같은 암호문 블록이 되어 평문의 패턴이 그대로 드러남
- 이미지를 ECB로 암호화하면 윤곽이 그대로 보이는 “ECB 펭귄” 예시가 유명함
- 보안상 실제 데이터 암호화에는 사용하지 않음
AES-CBC(Cipher Block Chaining)
- 이전 Ciphertext를 다음 Block에 사용
- 첫 블록은 이전 암호문이 없으므로 IV(Initialization Vector)를 사용함
1
2
3
4
5
6
7
P1 P2 P3
│ │ │
IV ───▶(⊕) ┌─────▶(⊕) ┌─────▶(⊕)
│ │ │ │ │
[AES(K)] │ [AES(K)] │ [AES(K)]
│ │ │ │ │
C1 ────┘ C2 ────┘ C3
- 암호화 :
Ci = E(K, Pi ⊕ Ci-1),C0 = IV - 복호화 :
Pi = D(K, Ci) ⊕ Ci-1 - 장점 : 같은 평문 블록이라도 앞 블록이 다르면 다른 암호문이 됨
- 단점
- 암호화는 이전 블록 결과가 필요하므로 병렬 처리 불가 (복호화는 병렬 가능)
- 패딩이 필요하고, 패딩 오류 응답을 이용한 Padding Oracle 공격에 취약할 수 있음
- 무결성을 보장하지 않으므로 별도의 MAC이 필요함
- IV는 매번 예측 불가능한 랜덤 값을 사용해야 함
AES-CTR(Counter)
- Plaintext를 직접 AES에 넣지 않고 Nonce + Counter를 AES로 암호화하여 Key Stream 생성
- 생성한 Key Stream과 Plaintext를 XOR해서 Ciphertext를 만듦 → 블록 암호를 스트림 암호처럼 사용
1
2
3
4
5
6
7
Nonce||Ctr1 Nonce||Ctr2 Nonce||Ctr3
│ │ │
[AES(K)] [AES(K)] [AES(K)]
│ Key Stream │ │
P1─(⊕) P2─(⊕) P3─(⊕)
│ │ │
C1 C2 C3
- 암호화 :
Ci = Pi ⊕ E(K, Nonce || Counter_i) - 복호화 :
Pi = Ci ⊕ E(K, Nonce || Counter_i)→ 암호화와 복호화가 같은 연산 (AES 복호화 함수가 필요 없음) - 장점
- 블록끼리 독립적이어서 암호화/복호화 모두 병렬 처리 가능
- XOR만 하므로 패딩이 필요 없음
- 단점
- 같은 Key에서 Nonce + Counter를 재사용하면 안 됨 : 같은 Key Stream이 나와
C1 ⊕ C2 = P1 ⊕ P2가 되어 평문이 노출됨 - 무결성을 보장하지 않음 (암호문 비트를 뒤집으면 평문의 같은 위치 비트가 뒤집힘)
- 같은 Key에서 Nonce + Counter를 재사용하면 안 됨 : 같은 Key Stream이 나와
AES-GCM(Galois/Counter Mode)
- Encryption과 Authentication을 함께 제공하는 AEAD(Authenticated Encryption with Associated Data) 모드
- CTR 모드로 암호화 + GHASH(Galois Field 곱셈 기반 해시)로 인증 태그 생성
- 입력 : Key, IV(Nonce, 보통 96bit), Plaintext, AAD(Additional Authenticated Data)
- AAD : 암호화하지는 않지만 변조되면 안 되는 데이터 (예: 패킷 헤더)
- 출력 : Ciphertext, Authentication Tag(보통 128bit)
암호화 과정
H = E(K, 0^128): 0 블록을 AES로 암호화해 GHASH용 해시 키를 생성- IV로 초기 카운터 블록
J0를 만듦 J0 + 1부터 시작하는 카운터로 CTR 모드 암호화 수행 → CiphertextGHASH(H, AAD, Ciphertext)를 계산하고, 그 결과를E(K, J0)와 XOR → Tag
- Decryption은 Verification을 함께 수행
- 수신자는 받은 AAD와 Ciphertext로 Tag를 다시 계산해 받은 Tag와 비교함
- Tag가 다르면 복호화 결과를 내보내지 않고 실패 처리함
- 장점 : 빠르고 병렬 처리가 가능함. TLS 1.3, IPSec 등에서 가장 많이 사용됨
- 주의 : CTR과 마찬가지로 같은 Key에서 IV를 재사용하면 기밀성뿐 아니라 인증까지 깨짐
AES-CCM(Counter with CBC-MAC)
- CTR + CBC-MAC 구조의 AEAD 모드
- CBC-MAC으로 인증 태그 생성 + CTR 모드로 암호화
- 입력 : Key, Nonce(7~13byte), Plaintext, AAD
암호화 과정
- Nonce, 메시지 길이 등으로 첫 블록
B0를 만듦 B0 || AAD || Plaintext를 CBC-MAC으로 계산해 TagT를 생성 (IV = 0인 CBC 암호화의 마지막 블록)- Counter 블록
A1, A2, ...로 CTR 모드 암호화해 Ciphertext 생성 - Counter 블록
A0로 만든 Key Stream과T를 XOR해 최종 Tag 생성
- 복호화 시에는 CTR로 평문과 Tag를 복원한 뒤, 평문으로 CBC-MAC을 다시 계산해 Tag를 비교함
- 장점 : AES 암호화 함수 하나만으로 구현 가능해 하드웨어/임베디드 환경에 적합함
- 단점 : CBC-MAC 계산과 CTR 암호화로 데이터를 두 번 처리하고, CBC-MAC은 병렬 처리가 불가능해 GCM보다 느림
- 사용 예 : Wi-Fi(WPA2 CCMP), Bluetooth LE, Zigbee, IEEE 1609.2(V2X)의 AES-128-CCM
운용 모드 비교
| 모드 | 패딩 | 병렬 암호화 | 무결성 | 비고 |
|---|---|---|---|---|
| ECB | 필요 | O | X | 패턴 노출, 사용 금지 |
| CBC | 필요 | X | X | IV 필요 |
| CTR | 불필요 | O | X | Nonce 재사용 금지 |
| GCM | 불필요 | O | O | AEAD, 가장 널리 사용 |
| CCM | 불필요 | X | O | AEAD, 임베디드/V2X |
Hash / SHA-256 / HMAC
HASH
- 임의 길이 입력을 고정 길이 HASH 값(Digest)으로 변환하는 단방향 함수
- 데이터 무결성 확인 시 사용
- 파일 다운로드 후 배포자가 공개한 해시값과 비교해 변조 여부 확인
- 전자서명 시 메시지 전체 대신 해시값에 서명
- 비밀번호 저장 (단, 단순 해시가 아니라 Salt + KDF 사용)
- 암호학적 해시 함수의 조건
| 성질 | 의미 |
|---|---|
| 역상 저항성(Preimage Resistance) | 해시값 h가 주어졌을 때 H(m) = h인 m을 찾기 어려움 |
| 제2 역상 저항성(Second Preimage Resistance) | m1이 주어졌을 때 H(m1) = H(m2)인 다른 m2를 찾기 어려움 |
| 충돌 저항성(Collision Resistance) | H(m1) = H(m2)인 서로 다른 m1, m2 쌍을 찾기 어려움 |
- 눈사태 효과(Avalanche Effect) : 입력이 1bit만 바뀌어도 출력의 약 절반이 바뀜
- MD5, SHA-1은 충돌이 발견되어 보안 용도로 더 이상 사용하지 않음
SHA-256(Secure Hash Algorithm)
- NIST에서 표준화한 SHA-2 계열의 해시 함수
- 입력 길이와 관계없이 출력은 256bit
- 256bit = 32byte
- 16진수 표현 시 64자리
1
2
SHA-256("abc")
= ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
SHA-256 동작 과정 (Merkle–Damgård 구조)
- Padding : 메시지 뒤에
1비트를 붙이고, 전체 길이가 512bit의 배수가 되도록0을 채운 뒤, 마지막 64bit에 원래 메시지 길이를 기록함 - Block 분할 : 패딩된 메시지를 512bit(64byte) 블록으로 나눔
- 초기 해시값 설정 : 32bit 초기값 8개(
H0 ~ H7)를 준비함 - 압축 함수(Compression) : 블록마다 아래 과정을 반복
- 512bit 블록을 32bit 워드 16개로 나누고, 이를 확장해 64개의 워드(Message Schedule)를 만듦
- 8개의 작업 변수(a~h)를 현재 해시값으로 초기화하고, 64라운드 동안 비트 연산(회전, 시프트, XOR, AND, 덧셈)과 라운드 상수를 이용해 섞음
- 결과를 현재 해시값에 더해 다음 블록의 입력으로 사용함
- 마지막 블록까지 처리한 후
H0 ~ H7(32bit x 8 = 256bit)을 이어 붙인 것이 최종 해시값
1
2
3
IV(H0~H7) ─▶ [압축 f] ─▶ [압축 f] ─▶ ... ─▶ [압축 f] ─▶ Hash
▲ ▲ ▲
Block 1 Block 2 Block N
Merkle–Damgård 구조는
H(m)과m의 길이만 알면 비밀값을 몰라도H(m || 추가 데이터)를 계산할 수 있는 Length Extension 공격에 취약함. 그래서H(Key || Message)형태로 MAC을 만들면 안 되고 HMAC을 사용해야 함
HMAC(Hash-based Message Authentication Code)
- Hash 함수와 Secret Key를 사용하여 메시지 인증 코드를 생성하는 방식
- 단순 Hash는 누구나 계산할 수 있어 공격자가 메시지를 바꾸고 해시도 다시 계산할 수 있음
- HMAC은 Secret Key를 아는 사람만 올바른 값을 만들 수 있으므로 무결성 + 메시지 인증을 함께 제공함
HMAC 동작 과정
1
HMAC(K, m) = H( (K' ⊕ opad) || H( (K' ⊕ ipad) || m ) )
- Key를 Hash의 블록 크기(SHA-256은 64byte)에 맞춤 →
K'- Key가 블록 크기보다 길면 해시하고, 짧으면 뒤에 0을 채움
- Inner Hash :
K' ⊕ ipad(0x36 반복)와 메시지를 이어 붙여 해시 - Outer Hash :
K' ⊕ opad(0x5c 반복)와 Inner Hash 결과를 이어 붙여 다시 해시 - 최종 결과가 HMAC 값 (HMAC-SHA256은 32byte)
- 해시를 두 번 감싸는 구조 때문에 Length Extension 공격에 안전함
HMAC 검증 과정
- 송신자 : 메시지와
HMAC(K, m)을 함께 전송 - 수신자 : 같은 Key로 받은 메시지의 HMAC을 다시 계산
- 받은 값과 비교해 같으면 변조되지 않았고, Key를 가진 상대가 보냈다고 판단
- 비교 시 타이밍 공격을 막기 위해 상수 시간 비교(Constant-time Compare)를 사용해야 함
HMAC은 송신자와 수신자가 같은 Key를 공유하므로 수신자도 같은 HMAC을 만들 수 있음. 따라서 제3자에게 “누가 만들었는지” 증명할 수 없어 부인방지는 제공하지 못함 → 부인방지가 필요하면 전자서명을 사용함
비대칭키 / RSA / DSA / ECDSA
비대칭키
- 서로 다른 두 개의 Key 사용
- Public Key(공개키) : 누구에게나 공개
- Private Key(개인키) : 소유자만 보관
- 두 키는 수학적으로 연결되어 있지만, 공개키로부터 개인키를 계산하는 것은 사실상 불가능함
- RSA : 큰 수의 소인수분해 문제
- DSA, DH : 이산 로그 문제
- ECC(ECDSA, ECDH) : 타원 곡선 이산 로그 문제
- 사용 방식은 목적에 따라 두 가지
| 목적 | 송신자 | 수신자 | 제공하는 보안 |
|---|---|---|---|
| 암호화 | 수신자의 공개키로 암호화 | 자신의 개인키로 복호화 | 기밀성 |
| 전자서명 | 자신의 개인키로 서명 | 송신자의 공개키로 검증 | 무결성, 인증, 부인방지 |
- 장점 : 키 분배 문제 해결 (공개키는 공개해도 됨), 전자서명 가능
- 단점 : 대칭키보다 연산이 수백~수천 배 느림 → 데이터 암호화는 대칭키로, 키 교환과 서명은 비대칭키로 하는 하이브리드 방식을 사용함
RSA - Rivest, Shamir, Adleman
- 1977년 세 사람의 이름을 따서 만든 최초의 실용적인 공개키 알고리즘
- 암호화와 전자서명 모두 가능함
- 안전성 : 두 큰 소수의 곱
n을 다시 소인수분해하기 어렵다는 점에 기반
키 생성 과정
- 두 개의 큰 소수
p,q를 선택 n = p × q계산 (n의 비트 수가 키 길이, 예: 2048bit)φ(n) = (p - 1)(q - 1)계산φ(n)과 서로소인 공개 지수e선택 (보통65537)e × d ≡ 1 (mod φ(n))을 만족하는 개인 지수d계산- 공개키 :
(n, e), 개인키 :(n, d)
암호화 / 복호화
- 암호화 :
C = M^e mod n - 복호화 :
M = C^d mod n
작은 수 예시
1
2
3
4
5
6
7
8
9
p = 61, q = 53
n = 61 × 53 = 3233
φ(n) = 60 × 52 = 3120
e = 17
d = 2753 (17 × 2753 = 46801 = 15 × 3120 + 1)
M = 65
암호화 : C = 65^17 mod 3233 = 2790
복호화 : M = 2790^2753 mod 3233 = 65
서명 / 검증
- 서명 :
S = H(M)^d mod n(개인키 사용) 검증 :
S^e mod n을 계산해H(M)과 같은지 비교 (공개키 사용)- 실제로는 위의 수식을 그대로 쓰면(Textbook RSA) 안전하지 않아 패딩을 함께 사용함
- 암호화 : RSA-OAEP
- 서명 : RSA-PSS (또는 PKCS#1 v1.5)
- 키 길이 : 현재 최소 2048bit 이상 권장
Digital Signature
- 본인 증명을 위해 서명하는 수단
- 손으로 하는 서명처럼, 메시지를 개인키를 가진 사람만 만들 수 있는 값으로 서명하고, 누구나 공개키로 확인할 수 있게 함
- 제공하는 보안 : 무결성, 인증, 부인방지
서명 / 검증 과정
1
2
3
4
5
6
7
8
9
[송신자]
Message ─▶ Hash ─▶ Digest ─▶ [서명(개인키)] ─▶ Signature
│
Message + Signature 전송 │
▼
[수신자]
Message ─▶ Hash ─▶ Digest ──────┐
├─▶ 비교 / 검증 ─▶ 성공 or 실패
Signature ─▶ [검증(공개키)] ─────┘
- 송신자는 메시지를 해시해 Digest를 만듦 (메시지 전체가 아닌 고정 길이 값에 서명하므로 빠름)
- Digest를 자신의 개인키로 서명해 Signature를 만들고 메시지와 함께 전송
- 수신자는 받은 메시지를 같은 해시 함수로 해시함
- 송신자의 공개키로 Signature를 검증해 Digest와 일치하는지 확인
- 일치 : 메시지가 변조되지 않았고(무결성), 해당 개인키 소유자가 서명했음(인증, 부인방지)
- 불일치 : 메시지 변조 또는 다른 사람이 서명함
전자서명은 공개키가 정말 그 사람의 것인지 확인할 수 있어야 의미가 있음 → 이를 보장하는 것이 인증서(X.509)
DSA(Digital Signature Algorithm)
- NIST가 전자서명 전용으로 표준화한 알고리즘 (DSS, FIPS 186)
- RSA와 달리 서명만 가능하고 암호화는 불가능함
- 안전성 : 이산 로그 문제 (
g^x mod p에서x를 구하기 어려움)
키 생성
- 공개 파라미터 : 큰 소수
p,p - 1의 소인수q, 생성자g - 개인키 : 랜덤 값
x(0 < x < q) - 공개키 :
y = g^x mod p
서명 과정
- 서명마다 새로운 랜덤 값
k선택 (0 < k < q) r = (g^k mod p) mod qs = k^-1 × (H(m) + x × r) mod q- 서명 값 :
(r, s)
검증 과정
w = s^-1 mod qu1 = H(m) × w mod q,u2 = r × w mod qv = (g^u1 × y^u2 mod p) mod qv == r이면 검증 성공
서명할 때 사용하는
k가 재사용되거나 예측 가능하면 서명 두 개로 개인키x를 계산할 수 있음 (Sony PS3 서명 키 유출 사례). DSA/ECDSA는k를 반드시 안전한 난수로 생성하거나 RFC 6979의 결정적 방식으로 생성해야 함
- 현재는 키와 서명 크기가 더 작은 ECDSA로 대부분 대체되었고, FIPS 186-5(2023)에서는 새로운 서명 생성용으로 DSA를 더 이상 승인하지 않음
ECDSA(Elliptic Curve Digital Signature Algorithm)
- 타원 곡선 암호(ECC)를 이용하는 Digital Signature Algorithm
- DSA를 타원 곡선 위의 연산으로 옮긴 것
타원 곡선 암호(ECC)
- 타원 곡선
y² = x³ + ax + b (mod p)위의 점들로 연산함 - Scalar Multiplication : 점
G를d번 더하는 연산Q = d × Gd와G로Q를 계산하는 것은 쉽지만,Q와G로d를 구하는 것은 매우 어려움 (ECDLP)
- 같은 보안 강도에서 RSA보다 키가 훨씬 짧아 연산이 빠르고 저장 공간이 적음
| 보안 강도 | RSA 키 길이 | ECC 키 길이 |
|---|---|---|
| 128bit | 3072bit | 256bit (P-256) |
| 192bit | 7680bit | 384bit (P-384) |
| 256bit | 15360bit | 521bit (P-521) |
키 생성
- 공개 파라미터 : 곡선, 기준점
G,G의 위수n - 개인키 : 랜덤 정수
d(1 ≤ d ≤ n - 1) - 공개키 : 곡선 위의 점
Q = d × G
서명 과정
z = H(m)(메시지 해시)- 랜덤 값
k선택 (1 ≤ k ≤ n - 1) - 점
(x1, y1) = k × G계산 r = x1 mod n(0이면k를 다시 선택)s = k^-1 × (z + r × d) mod n(0이면k를 다시 선택)- 서명 값 :
(r, s)
검증 과정
z = H(m)w = s^-1 mod nu1 = z × w mod n,u2 = r × w mod n- 점
(x1, y1) = u1 × G + u2 × Q계산 r == x1 mod n이면 검증 성공
- P-256 기준 서명 크기는
r,s각 32byte로 총 64byte - V2X(IEEE 1609.2)에서는 차량이 초당 수많은 메시지를 서명·검증해야 하고 메시지 크기도 작아야 하므로, 서명이 작고 빠른 ECDSA(NIST P-256, brainpoolP256r1 등)를 사용함
Key Generation & Key Establishment
Key Generation
- 암호 알고리즘에 필요한 Secret Key 또는 Public/Private Key Pair를 생성하는 과정
- 키의 안전성은 난수의 품질에 달려 있음
- 일반 난수(
rand()등)는 예측 가능하므로 반드시 CSPRNG(Cryptographically Secure PRNG)를 사용해야 함 - DRBG : NIST SP 800-90A에서 정의한 결정적 난수 생성기 (CTR_DRBG, Hash_DRBG, HMAC_DRBG)
- OS 난수원 :
/dev/urandom,getrandom(), WindowsBCryptGenRandom등
- 일반 난수(
- 알고리즘별 키 생성 방식
| 종류 | 생성 방식 |
|---|---|
| 대칭키(AES) | CSPRNG로 128/256bit 랜덤 값 생성 |
| RSA | 큰 소수 p, q를 랜덤으로 생성 후 n, e, d 계산 |
| EC(P-256) | 랜덤 정수 d 생성 후 Q = d × G 계산 |
- 생성한 개인키는 HSM(Hardware Security Module)이나 보안 칩에 저장해 외부로 노출되지 않도록 관리함
Key Establishment
- 통신하는 두 당사자가 같은 Secret Key를 갖도록 하는 과정
- Key Transport : 한쪽이 키를 만들어 상대 공개키로 암호화해 전달 (예: RSA 키 전송)
- Key Agreement : 양쪽이 값을 교환해 같은 키를 각자 계산 (예: DH, ECDH)
DH(Diffie-Hellman)
- 공개된 통신 채널을 통해 서로의 공개값을 교환하여 동일한 Shared Secret을 계산하는 방식
- Secret Key 자체는 네트워크로 전송되지 않음
동작 과정
- A와 B가 공개 파라미터 소수
p와 생성자g를 공유함 - A는 비밀값
a를 선택하고A = g^a mod p를 B에게 전송 - B는 비밀값
b를 선택하고B = g^b mod p를 A에게 전송 - A는
S = B^a mod p, B는S = A^b mod p를 계산 - 두 값은
g^(ab) mod p로 동일함 → Shared Secret
1
2
3
4
5
6
7
p = 23, g = 5
A : a = 4 → A = 5^4 mod 23 = 4 ──▶ B에게 전송
B : b = 3 → B = 5^3 mod 23 = 10 ──▶ A에게 전송
A : S = 10^4 mod 23 = 18
B : S = 4^3 mod 23 = 18 → Shared Secret = 18
- 공격자는
p,g,A,B를 볼 수 있지만a나b를 알아내려면 이산 로그 문제를 풀어야 함 - 주의 : DH 자체에는 상대방 인증 기능이 없어 중간자 공격(MITM)에 취약함
- 공격자가 중간에서 A, B와 각각 DH를 수행할 수 있음
- 그래서 교환하는 공개값에 전자서명을 하거나 인증서로 상대를 확인함
- 매 세션마다 새로운 비밀값을 사용(Ephemeral DH, DHE)하면 나중에 장기 키가 유출되어도 과거 통신을 복호화할 수 없음 → 전방향 안전성(Forward Secrecy)
ECDH(Elliptic Curve Diffie-Hellman)
- 타원곡선의 Scalar Multiplication을 이용하여 동일한 Shared Secret을 계산하는 Key Agreement 방식
- DH와 원리는 같고, 거듭제곱 대신 타원 곡선의 Scalar Multiplication을 사용함
동작 과정
- A와 B가 같은 곡선과 기준점
G를 사용함 - A : 개인키
dA, 공개키QA = dA × G→ B에게 전송 - B : 개인키
dB, 공개키QB = dB × G→ A에게 전송 - A는
S = dA × QB, B는S = dB × QA를 계산 - 두 값은
dA × dB × G로 동일함 → Shared Secret (보통 점의 x좌표 사용)
- 계산된 Shared Secret을 그대로 키로 쓰지 않고 KDF(HKDF 등)를 거쳐 실제 암호화 키를 만듦
- DH보다 짧은 키로 같은 보안 강도를 제공해 TLS 1.3의 기본 키 교환 방식(ECDHE)으로 사용됨
- V2X(IEEE 1609.2)에서는 ECDH 기반의 ECIES로 AES-CCM 대칭키를 수신자의 공개키로 암호화해 전달함
HKDF(HMAC-based Key Derivation Function)
- 기존의 비밀값으로부터 암호학적으로 사용할 Key를 도출하기 위한 HMAC 기반 KDF (RFC 5869)
- DH/ECDH의 Shared Secret처럼 길이가 맞지 않거나 균일하게 랜덤하지 않은 값을 안전한 키로 바꿔줌
- 하나의 비밀값으로 용도별(암호화 키, MAC 키, IV 등)로 서로 다른 여러 키를 만들 수 있음
동작 과정 (Extract-then-Expand)
- Extract : 입력 비밀값(IKM)을 Salt와 함께 HMAC해 고정 길이의 균일한 키(PRK)를 만듦
PRK = HMAC(Salt, IKM)
- Expand : PRK와
info(용도를 구분하는 문자열)를 이용해 필요한 길이만큼 키(OKM)를 늘림T(1) = HMAC(PRK, info || 0x01)T(2) = HMAC(PRK, T(1) || info || 0x02)- …
OKM = T(1) || T(2) || ...의 앞에서 필요한 길이(L)만큼 사용
info를 다르게 주면 같은 PRK에서 서로 독립적인 키를 만들 수 있음 (예:"client key","server key")- TLS 1.3, Signal 프로토콜 등에서 키 스케줄에 사용함
PBKDF2(Password-Based Key Derivation Function 2)
- Password와 Salt를 입력받아 HMAC 등의 연산을 반복 수행함으로써 암호키를 도출하는 방식 (RFC 8018)
- 비밀번호는 사람이 기억할 수 있는 값이라 엔트로피가 낮음 → 반복 연산으로 계산을 일부러 느리게 만들어 무차별 대입 공격을 어렵게 함
1
DK = PBKDF2(PRF, Password, Salt, Iterations, dkLen)
동작 과정
- 출력 키 길이(
dkLen)만큼 블록T1, T2, ...을 만듦 - 각 블록
Ti는 다음과 같이 계산U1 = HMAC(Password, Salt || INT(i))U2 = HMAC(Password, U1)- …
Uc = HMAC(Password, Uc-1)(c= 반복 횟수)Ti = U1 ⊕ U2 ⊕ ... ⊕ Uc
DK = T1 || T2 || ...의 앞에서dkLen만큼 사용
- Salt : 사용자마다 다른 랜덤 값을 섞어 같은 비밀번호라도 다른 키가 나오게 함 → 레인보우 테이블 공격 방지
- Iterations : 반복 횟수가 클수록 공격 비용이 커짐 (OWASP 권장 : PBKDF2-HMAC-SHA256 기준 600,000회)
- GPU를 이용한 병렬 공격에 상대적으로 약해, 메모리를 많이 쓰는 scrypt, Argon2가 대안으로 사용됨
| 구분 | HKDF | PBKDF2 |
|---|---|---|
| 입력 | 이미 랜덤성이 높은 비밀값 (DH 결과 등) | 엔트로피가 낮은 비밀번호 |
| 목적 | 키 추출 및 확장 | 무차별 대입을 어렵게 만들기 |
| 속도 | 빠름 | 의도적으로 느림 |
X.509
- 공개 키 기반(PKI)의 디지털 인증서 표준 (ITU-T X.509, 인터넷용 프로파일 RFC 5280)
- 인증서는 “이 공개키는 이 주체의 것이다”라는 내용을 신뢰할 수 있는 인증기관(CA)이 전자서명으로 보증한 문서
- 역할
- 공개 키 인증 : 공개키와 해당 키 소유자 간의 관계를 인증
- 디지털 서명 : 개인 키로 디지털 서명을 생성하고, 공개 키로 서명을 확인
- 데이터 암호화 : 공개 키로 데이터를 암호화하고, 개인키로 복호화
- 통신 보안 : SSL/TLS와 같은 프로토콜에서 신원 확인 및 암호화 통신을 가능하게 함
X.509 v3 인증서 구조
| 필드 | 설명 |
|---|---|
| Version | 인증서 버전 (현재 v3) |
| Serial Number | CA가 발급한 인증서 고유 번호 |
| Signature Algorithm | CA가 서명에 사용한 알고리즘 (예: sha256WithRSAEncryption, ecdsa-with-SHA256) |
| Issuer | 인증서를 발급한 CA |
| Validity | 유효 기간 (Not Before ~ Not After) |
| Subject | 인증서 소유자 |
| Subject Public Key Info | 소유자의 공개키와 알고리즘 |
| Extensions | Key Usage, Basic Constraints(CA 여부), SAN(도메인 목록) 등 |
| Signature Value | 위 내용을 해시해 CA 개인키로 서명한 값 |
- ASN.1로 정의되고 DER로 인코딩됨 (텍스트로 저장할 때는 Base64로 변환한 PEM 형식 사용)
- 폐기된 인증서는 CRL(인증서 폐기 목록)이나 OCSP(실시간 상태 조회)로 확인함
V2X에서는 X.509 대신 크기가 더 작고 빠르게 처리할 수 있는 IEEE 1609.2 인증서를 사용하며, OER로 인코딩함
Certificate Chain of Trust
1
2
3
4
5
6
7
Root CA Certificate (Self-Signed, OS/브라우저 Trust Store에 미리 설치)
│ 서명
▼
Intermediate CA Certificate (Root CA의 개인키로 서명)
│ 서명
▼
End-Entity Certificate (Intermediate CA의 개인키로 서명, 서버/기기의 인증서)
- End-Entity Certificate : 실제 서버나 기기의 인증서
- Intermediate CA Certificate : Root CA 대신 실제로 인증서를 발급하는 중간 인증기관의 인증서
- Root CA Certificate : 신뢰의 출발점. 스스로 서명한(Self-Signed) 인증서로, 미리 Trust Store에 설치되어 있음
검증 과정
- 서버가 End-Entity 인증서와 Intermediate CA 인증서를 함께 전달함
- End-Entity 인증서의 서명을 Intermediate CA의 공개키로 검증함
- Intermediate CA 인증서의 서명을 Root CA의 공개키로 검증함
- Root CA가 Trust Store에 있으면 체인 전체를 신뢰함
- 각 인증서의 유효 기간, 폐기 여부, 용도(Key Usage), 도메인(SAN) 등도 함께 확인함
- Intermediate CA를 두는 이유
- Root CA의 개인키가 유출되면 체인 전체를 신뢰할 수 없게 되므로, Root CA는 오프라인으로 안전하게 보관함
- 평소 발급은 Intermediate CA가 담당하고, Intermediate CA가 문제가 생기면 해당 CA만 폐기하면 됨