0. 블록암호 운용모드 (Modes of Operation)
블록암호에서는 plaintext가 블록 크기 보다 클 때 plaintext를 블록 크기로 분할해서 암호 알고리즘을 적용한다.
블록암호 운용모드라는 것은 이 분할을 처리하는 방법론들이다.
즉, 블록암호를 어떻게 반복하고 연결해서 전체 데이터를 안전하게 암호화할 것인지를 정의하는 것이다.
| 운용모드 | 초기화 벡터 | 병렬처리 | 에러 전파 | 복호화 함수 | 스트림 암호 | 분류 |
| ECB | X | 가능 | X | 필요 | 블록 암호 | 독립적 블록 암호 |
| CBC | O | 암호화 불가 / 복호화 가능 | 해당 블록 + 다음 블록 1개 | 필요 | 블록 암호 | 체인형 블록 암호 |
| CFB | O | 암호화 불가 / 복호화 가능 | 해당 블록 + 다음 블록 1개 | 불필요 | 스트림 암호 | 비동기식 스트림 암호 |
| OFB | O | 불가능 | X | 불필요 | 스트림 암호 | 동기식 스트림 암호 |
| CTR | O | 가능 | X | 불필 | 스트림 암호 | 동기식 스트림 암호 |
| GCM | O | 가능 | X | 불필요 | 스트림 암호 | 동기식 인증 스트림 암호 |
주로 운용모드라고 하면 보통 ECB, CBC, CFB, OFB, CTR 이렇게 5가지를 다룬다. 여기서는 GCM이라고 하는 운용모드까지 더해 총 6가지 블록암호 운용모드를 살펴볼 것이다.
평문이 직접 암호화 대상이면 블록 암호이다. 운용모드에서 말하는 스트림 암호는 블록 암호를 마치 난수 발생기(PRNG) 처럼 써서 키 스트림을 생성하는데 사용하는 방식을 말한다.
CFB, OFB, CTR, GCM이 스트림 암호 방식에 해당한다. (여기서 키 스트림은 일회용 난수열을 말한다.)
블록 암호 방식은 $D_k$가 복호화에 필요하지만 스트림 암호 방식은 복호화에 $E_k$가 필요하다.
분류에서 동기식(Synchronous)는 키 스트림의 생성 과정이 이전 평문과 암호문과 완전히 독립적으로 이뤄지는 방식을 말한다.
OFB, CTR, GCM이 동기식 암호 방식이다.
앞으로 사용할 수식의 기호를 정리해놓으면 다음과 같다.
- $P_i$: $i$번째 평문 블록 (Plaintext)
- $C_i$: $i$번째 암호문 블록 (Ciphertext)
- $K$: 대칭키 (Key)
- $E_K()$: 키 $K$를 사용하는 블록 암호 암호화 함수
- $D_K()$: 키 $K$를 사용하는 블록 암호 복호화 함수
- $\oplus$: 배타적 논리합 (XOR)
1. ECB (Electronic CodeBook)


ECB는 평문을 고정된 크기의 블록으로 나누고 각각 동일한 키를 사용해 암호화한다. 가장 쉽고 직관적으로 떠오르는 방법이다.
- 암호화: $C_i = E_K(P_i)$
- 복호화: $P_i = D_K(C_i)$
[상세 특징]
- 결정론적 암호화(Deterministic): 동일한 평문 블록은 항상 동일한 암호문 블록으로 변환된다. 이는 데이터의 통계적 패턴(예: 이미지의 단색 배경)을 숨기지 못하는 치명적인 보안 취약점을 야기한다.
- 독립성 및 병렬처리: 각 블록의 연산이 다른 블록과 완전히 독립적이다. 따라서 멀티스레딩을 활용한 초고속 병렬 암호화 및 복호화가 가능하다.
- 에러 전파 없음: 통신 중 특정 암호문 블록에 1비트 에러가 발생하더라도, 해당 블록의 복호화 결과만 손상될 뿐 다른 블록에는 전혀 영향을 주지 않는다.
- 활용처: 패턴이 드러나지 않는 아주 짧은 단일 블록의 데이터(예: 대칭키 자체를 암호화하여 전송할 때)를 전송하는 제한적인 용도로만 사용된다.
2. CBC (Cipher Block Chaining)


CBC는 평문과 키 스트림을 XOR한 후 Encryption한다. 이후 Encryption한게 다시 키 스트림이 되어 다음으로 전달되는 구조이다.
* 모든 운용모드에서 같은데 XOR 연산의 대상은 항상 plaintext이다. CBC에서는 이름대로 Cipher 된게 체이닝 되는 구조라고 기억하면 된다.
- 초기설정: $C_0 = IV$ (초기화 벡터)
- 암호화: $C_i = E_K(P_i \oplus C_{i-1})$
- 복호화: $P_i = D_K(C_i) \oplus C_{i-1}$
[상세 특징]
- 확률론적 암호화(Probabilistic): 동일한 평문이라도 이전 암호문 블록의 영향을 받으므로 다른 암호문으로 변환된다. 이를 통해 패턴 분석 공격을 효과적으로 방어한다.
- 순차적 연산 및 병렬처리 제한: 암호화 시 이전 블록의 결과($C_{i-1}$)가 반드시 필요하므로 암호화 과정은 병렬 처리가 불가능하다. 단, 복호화 과정은 암호문 블록들을 이미 모두 수신한 상태이므로 병렬 처리가 가능하다.
- 에러 전파(Error Propagation): $C_i$ 전송 중 1비트 에러가 발생하면, 복호화 시 $D_K(C_i)$ 결과 전체가 깨져 $P_i$는 완전히 손상된다. 또한 $P_{i+1} = D_K(C_{i+1}) \oplus C_i$ 식에 의해 $P_{i+1}$의 동일한 비트 위치에도 1비트 에러가 발생한다. (총 2개 평문 블록에 영향)
- 패딩(Padding) 필수: 평문의 길이가 블록 크기의 배수가 아닐 경우, 마지막 블록을 채우는 패딩 처리가 반드시 필요하다.
3. CFB (Cipher FeedBack)


FeedBack이 붙은 애들은 plaintext가 아니라 키 스트림을 암호화한다. CFB는 Encryption한 키스트림과 평문을 XOR 연산한다. 이후 CFB 이름대로 평문과 XOR 연산한 Cipher 값을 다음 키스트림으로 넘기고 다시 Encryption 시키는 구조이다.
- 초기설정: $C_0 = IV$
- 암호화: $C_i = P_i \oplus E_K(C_{i-1})$
- 복호화: $P_i = C_i \oplus E_K(C_{i-1})$
[상세 특징]
- 스트림 암호화 구조: 블록 암호 알고리즘을 난수 발생기처럼 활용하여 키 스트림을 생성한 뒤, 평문과 XOR 연산한다. 패딩이 필요하지 않다.
- 복호화 시 '암호화' 함수 사용: 암호화시 평문이 암호화의 대상이 아니었다. 암호화된 키 스트림에 평문을 XOR 연산 했을 뿐이다. 따라서 복호화할 때도 암호문에 키스트림을 XOR 연산해야하고 키 스트림을 똑같이 얻으려면 복호화때도 암호화때와 동일하게 Decryption이 아닌 Encryption을 해야하는 것이다. 이로 인해 암호화 모듈만 구현하면 복호화까지 처리할 수 있어 하드웨어 구현 면적이 절약된다.
- 자가 동기화(Self-synchronizing): 통신 중 비트 손실이 발생하더라도 시프트 레지스터를 사용하는 구조적 특성상 일정 블록(레지스터 크기)이 지나면 자동으로 동기화가 회복된다.
4. OFB (Output FeedBack)


OFB는 키 스트림을 Encryption 하고 이를 평문과 XOR 해서 암호문을 만든다. 키 스트림을 암호화한 직후 평문과 XOR 연산하기 전에 다음 키 스트림으로 넘기는 것이 CFB와는 다른 점이다.
- 초기설정: $O_0 = IV$
- 키 스트림 생성: $O_i = E_K(O_{i-1})$
- 암호화: $C_i = P_i \oplus O_i$
- 복호화: $P_i = C_i \oplus O_i$
[상세 특징]
- 키 스트림의 독립성 (사전 연산 가능): 키 스트림($O_i$) 생성 과정에 평문이나 암호문이 전혀 개입하지 않는다. 따라서 암호화할 데이터가 도착하기 전에 키 스트림을 미리 계산해 둘 수 있어 실시간 처리 속도를 극대화할 수 있다.
- 에러 전파 없음: $C_i$에 1비트 에러가 발생하더라도 XOR 연산의 특성상 복호화된 $P_i$의 해당 위치 1비트만 손상되며 다른 부분으로 전파되지 않는다. 노이즈가 많은 통신 환경(위성 통신, 무선 영상 전송 등)에 유리하다.
- 동기화 취약점: 키 스트림이 평문, 암호문과 무관하게 독립적으로 돌아가므로, 송수신자 간에 1비트라도 유실되어 동기화(Sync)가 어긋나면 이후의 모든 데이터 복호화가 불가능해진다.
5. CTR (Counter)


CTR은 매 블록 증가하는 카운터 값을 Encryption하여 키 스트림을 생성하고 이를 평문과 XOR 연산한다. 독립 연산이 가능하기 때문에 병렬 처리가 가능하다.
- 키 스트림 생성: $O_i = E_K(Nonce \parallel Counter_i)$ (카운터 값은 매 블록마다 증가)
- 암호화: $C_i = P_i \oplus O_i$
- 복호화: $P_i = C_i \oplus O_i$
[상세 특징]
- 임의 접근(Random Access) 및 완벽한 병렬성: 각 블록의 키 스트림 생성이 이전 블록에 의존하지 않고 오직 카운터 값에만 의존한다. 따라서 $i$번째 블록을 복호화하기 위해 앞선 블록들을 처리할 필요가 없고, 암호화와 복호화 양쪽 모두 완벽한 멀티코어 병렬 처리가 가능하다.
- 최고의 성능: 사전 연산 기능, 병렬 처리 능력, 패딩 불필요 등의 장점이 결합되어 현대 고속 네트워크 아키텍처(IPSec, TLS 등)에서 가장 선호되는 베이스 모드이다.
- Nonce 재사용의 치명적 위험: 같은 키에서 동일한 카운터 값(Nonce)이 재사용될 경우 키 스트림이 중복 생성되어, 다중 연결 공격(Many-Time Pad Attack) 등에 의해 평문이 통째로 노출될 수 있는 치명적인 구현상 취약점이 존재한다.
6. GCM (Galois Counter Mode)

GCM은 암호화와 인증 두가지를 동시에 제공하는 방법이다.
[암호화 과정]
- 암호문 생성: $C_i = P_i \oplus E_k(CTR_i)$
CTR과정과 완전히 똑같다. Counter를 놓고 Encryption 후 plaintext와 XOR 연산한다.
[인증 태그 생성]
- 해시 키 생성: 0으로 채워진 128비트 블록을 암호화하여 비밀 곱셈 키 $H$를 만든다.
$$H = E_k(0^{128})$$ - AAD 체인 연산: AAD 블록($AD_1 \dots AD_m$)들을 차례로 누적한다. ($g_0 = 0$)
$$g_i = (g_{i-1} \oplus AD_i) \otimes H \quad (\text{for } i = 1 \dots m)$$ - 암호문 체인 연산: 생성된 암호문 블록($C_1 \dots C_n$)들을 이어서 누적한다.
$$g_{m+j} = (g_{m+j-1} \oplus C_j) \otimes H \quad (\text{for } j = 1 \dots n)$$ - 길이 블록 연산: 길이 연장 공격을 방어하기 위해 AAD의 비트 길이와 평문의 비트 길이를 결합한 128비트 블록($L$)을 마지막으로 곱한다.
$$g_{m+n+1} = (g_{m+n} \oplus (len(AD) \parallel len(P))) \otimes H$$ - 최종 태그 마스킹: 다항식 곱셈 결과값이 그대로 노출되는 것을 막기 위해, 카운터가 0인 블록($CTR_0 = IV \parallel 0^{32}$)을 암호화한 값과 XOR 연산하여 태그를 산출한다.
$$T = g_{m+n+1} \oplus E_k(CTR_0)$$
[상세 특징]
- AEAD (Authenticated Encryption with Associated Data): 기밀성(데이터 암호화)과 무결성/인증(데이터가 변조되지 않았음 및 정당한 송신자임)을 동시에 제공하는 현대 표준 운용 모드이다.
- 고속 인증 연산: 전통적인 MAC은 해시 함수를 여러 번 구동해야 하지만, GCM은 기밀성을 위해 이미 구동된 블록 암호 아키텍처 위에서 단순한 논리 연산만 추가하므로 하드웨어 가속 시 지연이 매우 적다.
- 인프라 친화적: TLS 1.3, QUIC 등 최신 프로토콜의 표준 암호(예: AES-GCM)로 채택되어 사용 중이다.
* 참고


'컴퓨터공학 > 정보보안' 카테고리의 다른 글
| [정보보안] 난수 생성기 (Random Number Generator) (1) | 2026.04.22 |
|---|---|
| [정보보안] 대칭키 암호 - AES (0) | 2026.04.22 |
| [정보보안] 대칭키 암호 - DES (0) | 2026.04.16 |
| [정보보안] 스트림 암호 vs 블록 암호 (Stream Cipher vs Block Cipher) (0) | 2026.04.15 |
| [정보보안] 고전 암호 기법 (이동 암호, 치환 암호, 전치 암호) (2) | 2026.04.14 |