암호화는 보안 시스템의 핵심이다. 단순히 데이터를 숨기는 수준을 넘어, 정보의 기밀성·무결성·인증·부인방지를 달성하기 위한 핵심 기술이다. 이 글에서는 실무 개발자가 반드시 이해하고 있어야 할 암호화 개념과 구현 시 고려사항을 체계적으로 정리한다.
1. 암호화의 목적과 보안 속성
암호화를 설계하거나 적용할 때는 “왜 암호화하는가”에 대한 명확한 이해가 필요하다.
보안은 단일 기능이 아니라 여러 속성이 맞물려 작동한다.
속성 설명
기밀성 (Confidentiality) | 권한 없는 사용자가 데이터를 볼 수 없도록 보호한다. |
무결성 (Integrity) | 데이터가 전송·저장 중 변조되지 않았음을 보장한다. |
인증 (Authentication) | 데이터를 보낸 주체가 누구인지 확인할 수 있다. |
부인방지 (Non-repudiation) | 데이터를 보낸 후 송신자가 이를 부인할 수 없다. |
가용성 (Availability) | 암호화가 시스템의 가용성을 저해하지 않도록 설계되어야 한다. |
2. 암호화 방식의 분류
암호화는 단순히 “데이터를 암호문으로 바꾸는 것”이 아니라, 어떤 목적을 달성하기 위한 기술적 조합이다.
이 절에서는 대칭, 비대칭, 해시, MAC, 서명, 키 교환까지 암호화의 모든 축을 체계적으로 정리한다.
2.1 대칭 암호화 (Symmetric Encryption)
하나의 비밀 키로 암호화와 복호화를 모두 수행하는 방식이다.
동일한 키를 양쪽에서 공유해야 하므로 “속도는 빠르지만 키 관리가 어렵다.”
① 작동 원리
- 평문(Plaintext)을 **하나의 키(Key)**로 암호화 → 암호문(Ciphertext) 생성
- 수신자는 같은 키로 암호문을 복호화해 평문 복원
- 대표 알고리즘: AES, 3DES, ChaCha20
② 블록 암호 vs 스트림 암호
처리 단위 | 고정 크기 블록 (예: AES는 128비트) | 연속 비트 단위 |
대표 알고리즘 | AES, 3DES, DES | ChaCha20, RC4 |
암호화 모드 필요 여부 | 필요 (ECB, CBC, CTR, GCM 등) | 불필요 (내부적으로 처리) |
패딩 필요 여부 | 필요 | 불필요 |
③ 암호화 모드 (Cipher Mode)
블록 암호는 “블록 단위 암호화”이므로 모드에 따라 결과와 보안성이 달라진다.
ECB (Electronic Code Book) | 같은 블록은 같은 암호문 | 취약 | 가능 |
CBC (Cipher Block Chaining) | 이전 블록과 XOR 후 암호화 | 안전 | 불가 |
CTR (Counter) | 블록을 카운터 기반으로 암호화 | 안전 | 가능 |
GCM (Galois/Counter Mode) | CTR + 인증 기능(AEAD) | 매우 안전 | 가능 |
GCM은 최근 대부분의 실무에서 표준 선택지이다. (예: TLS 1.3, AWS KMS)
④ IV / Nonce
- CBC, GCM, CTR 등에서는 초기 벡터(IV) 또는 Nonce가 필요
- 암호문을 예측 불가능하게 만드는 “한 번만 사용하는 값”
- 절대 중복 금지, 특히 GCM에서 nonce 중복 시 전체 키가 노출될 수 있음
- 보통 12바이트(96비트) 랜덤값을 권장
⑤ 패딩 (Padding)
- AES는 16바이트 블록 단위로 암호화하므로, 길이가 맞지 않으면 패딩 필요
- 가장 일반적인 방식은 PKCS#7
- 복호화 시 패딩 검증 오류 메시지로 공격(패딩 오라클 공격)이 가능하므로 에러 처리 시 유의
⑥ 실무 적용 포인트
- AES는 AES/GCM/NoPadding을 기본으로 사용
- IV/Nonce는 SecureRandom으로 매번 새로 생성
- 키는 코드에 하드코딩하지 말고 KMS, Vault, HSM에 저장
2.2 비대칭 암호화 (Asymmetric Encryption)
**공개키(public key)**와 개인키(private key) 한 쌍을 이용한다.
- 공개키로 암호화 → 개인키로 복호화
- 개인키로 서명 → 공개키로 검증
① 작동 원리
- 공개키는 자유롭게 배포 가능
- 개인키는 오직 본인만 보유
- “키 교환, 인증서, 서명”의 핵심 기반
② 대표 알고리즘
RSA | 전통적 대표 알고리즘, 키 길이 큼 |
ECC | 짧은 키로 같은 보안 강도, 모바일에 적합 |
DSA / ECDSA | 디지털 서명 전용 |
ElGamal | 암호화 및 키 교환 가능, 상대적으로 느림 |
③ RSA 구조 예시
- 공개키: (e, n)
- 개인키: (d, n)
- 암호화: C = M^e mod n
- 복호화: M = C^d mod n
- 반드시 OAEP 패딩과 함께 사용 (단독 RSA는 안전하지 않음)
④ ECC의 장점
- 같은 보안 수준에서 RSA 2048비트 ≈ ECC 256비트
- 키 교환(ECDH), 서명(ECDSA) 등에 활용
- TLS 1.3, JWT 서명 등에서 사실상 표준
⑤ 실무 적용 포인트
- RSA는 최소 2048비트 이상
- ECC는 secp256r1(P-256) 혹은 ed25519 권장
- 개인키 보호는 HSM 또는 OS KeyStore를 사용
2.3 해시 함수 (Hash Function)
입력을 고정 길이 해시값으로 변환하는 단방향 함수.
복호화 불가능하며, 데이터 무결성 확인에 사용된다.
주요 특징
- 단방향성: 해시 → 원문 복원 불가
- 충돌 저항성: 서로 다른 입력이 같은 해시를 갖기 어려움
- 2차 저항성: 특정 입력과 같은 해시를 만드는 다른 입력 찾기 어려움
대표 알고리즘
MD5, SHA-1 | 취약. 사용 금지 |
SHA-2 (SHA-256, SHA-512) | 표준 |
SHA-3 | 차세대 표준 |
BLAKE2, BLAKE3 | 빠르고 안전 |
활용 예시
- 비밀번호 저장 시 salt + hash
- 파일 무결성 검증 (예: SHA256 체크섬)
- 전자서명 시 메시지 다이제스트 생성
2.4 메시지 인증 코드 (MAC)와 AEAD
단순 해시는 “변조 탐지”는 가능하지만 “누가 만든 데이터인지”는 알 수 없다.
MAC은 비밀 키를 추가해 인증 기능을 더한 해시이다.
대표 방식
HMAC | 해시 기반 MAC (예: HMAC-SHA256) |
CMAC | 블록 암호 기반 MAC |
GMAC | GCM 모드에서 생성되는 인증 태그 |
AEAD (Authenticated Encryption with Associated Data)
- 암호화 + 인증을 한 번에 처리
- 대표: AES-GCM, AES-CCM, ChaCha20-Poly1305
- 암호문 + 인증 태그를 함께 반환
- 실무에서는 AES-GCM 또는 ChaCha20-Poly1305가 기본 선택
2.5 디지털 서명 (Digital Signature)
데이터 위조 방지, 송신자 인증, 부인방지 기능 제공.
작동 과정
- 메시지 해시 생성: H = Hash(M)
- 개인키로 서명: S = Sign(H, private key)
- 공개키로 검증: Verify(S, public key)
대표 알고리즘
- RSA-PSS (권장)
- ECDSA (TLS, JWT 등에서 표준)
- EdDSA (ed25519, 최신)
실무 포인트
- 서명은 암호화보다 검증 기능 중심
- JWT, SAML, 전자계약 등에서 기본 구성요소
2.6 키 교환과 키 유도 함수 (Key Exchange / KDF)
키 교환 (Key Exchange)
네트워크 상에서 공유 키를 안전하게 합의하는 프로토콜.
DH (Diffie–Hellman) | 기본 키 교환 방식 |
ECDH | ECC 기반 DH, 빠르고 안전 |
PAKE | 비밀번호 기반 키 교환 |
키 유도 함수 (KDF)
- 입력된 비밀값(패스워드 등)으로부터 안전한 파생 키 생성
- 반복 연산, salt, 목적 식별자 포함
PBKDF2 | 표준 KDF, 단순하지만 비교적 느림 |
bcrypt | 패스워드 저장용 |
scrypt | 메모리 집약형 |
Argon2 | 최신 KDF, 가장 권장 |
2.7 혼동하기 쉬운 핵심 개념 요약
IV / Nonce | 블록 암호나 스트림 암호의 초기값. 중복 금지 |
Padding | 블록 크기 맞추기 위한 채움. 검증 로직 주의 |
Padding Oracle | 복호화 에러 메시지로 평문 추론하는 공격 |
Nonce 재사용 | 스트림 암호나 GCM에서 절대 금지 |
안전한 난수 | SecureRandom 사용 필수, Random은 금지 |
3. 공격 기법과 보안 고려사항
암호화는 알고리즘 자체보다도 잘못된 사용 방식으로 인한 취약이 많다.
공격자가 어떤 방식으로 취약점을 악용할 수 있는지 이해해야 안전한 설계가 가능하다.
주요 공격 기법
- 중간자 공격 (MITM): 키 교환 과정에서 통신을 가로채는 공격.
- Replay 공격: 암호화된 데이터를 그대로 재전송하여 인증을 우회.
- 패딩 오라클 공격: 복호화 오류 응답을 통해 평문을 유추.
- 충돌 공격: 해시 함수의 충돌을 이용.
- 타이밍/사이드 채널 공격: 연산 시간이나 부수 정보를 이용해 키를 추출.
- nonce 재사용 공격: 스트림 암호나 AEAD에서 nonce 중복 시 암호 무력화.
- 랜덤 생성 취약점: 예측 가능한 난수로 인한 키 노출.
설계 및 구현 시 고려사항
- 충분히 긴 키 길이와 최신 알고리즘을 사용한다.
- 키와 IV/nonce를 안전하게 생성하고 재사용하지 않는다.
- 인증 기능이 없는 암호화는 사용하지 않는다. (MAC 또는 AEAD 필수)
- 예외 메시지나 로그에 민감한 정보를 남기지 않는다.
- 검증되지 않은 직접 구현 대신 표준 라이브러리를 사용한다.
- 키 관리 및 교체 정책을 명확히 설계한다.
4. 실무에서의 구현 주의사항 (Java 예시 포함)
안전한 라이브러리 사용
- 표준 라이브러리(예: Java Cryptography Architecture)나 검증된 서드파티(예: Bouncy Castle)를 사용한다.
- 직접 알고리즘을 구현하지 않는다.
- 암호화 알고리즘과 모드는 명시적으로 지정한다.
안전한 난수 생성
- SecureRandom을 사용한다.
- Random이나 Math.random()은 예측 가능성이 있어 사용 금지.
키 및 IV 관리
- 키와 IV는 코드에 하드코딩하지 않는다.
- 안전한 저장소(KMS, HSM 등)나 안전한 전달 채널을 이용한다.
예시: AES-GCM 암호화
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKey key = KeyGenerator.getInstance("AES").generateKey();
byte[] iv = new byte[12];
SecureRandom rnd = SecureRandom.getInstanceStrong();
rnd.nextBytes(iv);
GCMParameterSpec spec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
byte[] ciphertext = cipher.doFinal(plaintext);
- GCM 모드에서는 96비트(12바이트) nonce를 권장한다.
- 같은 키/nonce 조합은 절대 재사용하지 않는다.
- 인증 태그가 함께 생성되므로 별도 MAC 처리가 필요 없다.
마무리
암호화는 개별 알고리즘만으로는 안전하지 않다.
알고리즘 + 모드 + 키 관리 + 난수 + 인증이 조합되어야 진정한 보안이 만들어진다.
단순히 AES를 쓴다고 안전해지는 게 아니다.
GCM 모드를 사용할 때 nonce를 어떻게 다루는지, 서명은 어떤 알고리즘으로 검증하는지, 해시 함수는 어떤 경우에 적합한지까지 이해해야 한다.
한 번 익혀두면 어떤 시스템에서도 공통적으로 적용할 수 있는 핵심 기술이다.
보안은 “추가 기능”이 아니라 시스템의 기본 설계 요소여야 한다.