개발을 하다보면 암복호화는 쉽게 만날 수 있는 개념입니다.
이번 포스팅에서는 단순히 암복호화의 정의 뿐만 아니라 양방향 암호화의 블록개념까지 다뤄보고자 합니다.

1️⃣ 양방향 암호화 vs 단방향 암호화
암호화는 크게 양방향과 단방향으로 나눌 수 있습니다.
복호화를 할 수 없는 것이 단방향 암호화이고, 복호화가 가능한 것은 양방향 암호화입니다.
암호화를 할 때 AES와 SHA를 많이 접하게 되는데
AES 암호화는 양방향 암호화의 구현방법 중 하나이고, SHA는 단방향 암호화의 구현방법 중 하나입니다.
단방향 암호화는 복호화를 할 수 없기 때문에 주로 유저의 비밀번호를 암호화할 때 많이 사용되고,
데이터를 외부서버로 전송하여 정보 보호가 필요할 때는 양방향 암호화를 사용합니다.
아래는 양방향 암호화와 단방향 암호화를 정리한 것입니다.
구분 | 양방향 암호화 | 단방향 암호화 |
정의 | 암호화한 데이터를 다시 복호화할 수 있는 방식 | 암호화한 데이터를 복호화할 수 없는 방식 |
사용예시 | 데이터 보호전송, VPN, SSL/TLS, 파일 암호화 등 | 비밀번호 저장 등 |
구현방법 종류 | <대칭키 암호화> AES, DES, 3DES <비대칭키 암호화> RSA, ECC |
SHA(SHA-256, SHA-512), MD5, PBKDF2, bcrypt, Argon2 |
2️⃣ 대칭키 암호화 vs 비대칭키 암호화

양방향 암호화는 두 종류로 나눌 수 있습니다.
대칭키 암호화와 비대칭키 암호화라는 개념이 존재합니다.
대칭키 암호화는 하나의 키를 이용하여 암호화와 복호화를 진행합니다.
암호화와 복호화에서 같은 키를 사용한다는 특징이 있습니다.
같은 키를 사용하기 때문에 비교적 암호화가 빠르다는 장점이 있지만,
키가 유출되면 보안이 취약해질 수 있다는 단점이 있습니다.
비대칭키 암호화는 두개의 키를 이용하여 암호화와 복호화를 진행합니다.
두개의 키는 공개된 키, 공개되지 않은 키가 있으며
암호화할 때는 공개된 키를 사용하고, 복호화를 할 때는 공개되지 않은 키를 사용합니다.
대칭키 암호화에 비해 키의 길이가 길어 연산량이 증가하다 보니 속도가 느리다는 단점이 있지만,
두 개의 키를 사용하여 암복호화를 사용하기 때문에 보안이 보다 강력하다는 장점이 있습니다.
아래는 대칭키 암호화와 비대칭키 암호화를 정리한 것입니다.
구분 | 대칭키 암호화 | 비대칭키 암호화 |
정의 | 동일한 키를 사용하여 데이터를 암호화하고 복호화하는 방식 | 공개키로 암호화하고 개인키로 복호화하는 방식 |
키 개수 | 1개 | 2개 |
속도 | 빠름 | 느림 |
보안 | 키 유출 시 보안 취약 | 복호화 키만 안전하게 관리하면 보안 유지 가능 |
3️⃣ 이런 것이 궁금했습니다..!
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
위처럼 양방향 암호화 코드를 작성하다 보면 AES, CBC, PKCS5Padding 들을 접할 수 있습니다.
이것들이 각각 어떤 개념인지, AES 뒤에 붙는 숫자들이 의미하는 것들에 대해 알아보려고 합니다.
🧩 AES + 숫자
숫자는 키의 길이를 의미하며 사용할 수 있는 숫자에는 128, 192, 256가 있습니다.
AES 알고리즘이 표준화될 때, 보안성과 성능을 고려해 이 세 가지 키 길이만 정의되었기 때문에 정의된 숫자는 세 종류 뿐이라고 합니다.
키의 길이가 길어질수록 보안은 강해지지만, 속도는 느려집니다.
그런데 그 속도가 얼마나 느릴지 궁금해져서 테스트해보기로 했습니다.
- 테스트 종류 : AES-128, AES-192, AES-256
- 테스트 상황 : 각 키 길이별로 100,000번 암호화를 수행하여 평균 수행 시간을 측정
그리고 결과는 다음과 같았습니다.

?
어라
당황한 저는 터미널에 아래의 명령어를 실행해보았습니다.
openssl speed -evp aes-128-cbc aes-192-cbc aes-256-cbc
이 명령어는 CPU에서 어떤 AES 모드를 더 빠르게 처리하는지 확인할 수 있는 명령어입니다.

그리고 그 결과는 다음과 같았습니다.
CPU에서 AES-128이 가장 빠르고, AES-192가 그 다음, AES-256이 가장 느리게 동작하는 것이 일반적인 성능 패턴이라고 합니다.
하지만, 결과가 256이 가장 빠른 것처럼 나온 것에는 Java는 실행 중 코드 최적화를 수행하는데, JVM이 AES-256 연산을 최적화했을 가능성이 있다고 합니다.
또는 ECB 모드와 CBC 모드 차이가 있을 수 있다고 합니다.
그렇다면 다음으로 두 모드에 대해서 알아보겠습니다.
🧩 ECB, CBC, PKCS5Padding
저를 당황하게 했던 것의 원인이 될 수 있었던 ECB 모드와 CBC 모드 그리고 PKCS5Padding 에 대해서 알아보려고 합니다.
먼저 이 개념들은 양방향 암호화와 관련이 있습니다.
이 개념들에 대해 알아보기 앞서, “블록” 과 “패딩” 이라는 것을 먼저 언급하려고 합니다.
AES는 데이터를 "블록 단위(16바이트)"로 암호화합니다.
데이터를 한 번에 16바이트씩 끊어서 암호화하며, 이 단위를 블록이라고 말합니다.
그런데 만약에, 데이터가 16바이트로 딱 나누어 떨어지지 않을 경우에는 어떻게 해야할까요?
그럴때는 부족한 바이트를 특정 규칙에 따라 추가하여 블록 크기를 맞춰주는 과정이 필요합니다.
그리고 이 과정을 “패딩” 이라고 합니다.
다시 돌아와서 ECB, CBC 에 대해 알아보겠습니다.
ECB는 각 블록을 독립적으로 암호화하는 방식이고,
CBC는 이전 블록의 암호문을 다음 블록의 암호화에 사용하는 방식입니다.
때문에 CBC가 ECB 보다 보안이 강하다는 특징을 가지고 있습니다.
아래는 두 개념을 정리한 표입니다.
구분 | ECB | CBC |
정의 | 각 블록을 독립적으로 암호화 | 이전 블록의 암호문을 다음 블록의 암호화 |
예제코드 | Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, secretKey); | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec); |
다음으로 PKCS5Padding에 대해서 알아보겠습니다.
PKCS5Padding는 여러 패딩 방식 중 하나입니다.
Hello(5바이트) 로 예를 들어보겠습니다.
Hello 는 5바이트 이므로 아래처럼 나머지 11바이트를 0x0B (11)을 추가하여 총 16바이트로 맞춥니다.

HelloWorld(10바이트) 로 예를 들어보겠습니다.
HelloWorld 는 10바이트이므로, 부족한 6바이트를 0x06으로 추가하여 총 16바이트로 맞춥니다.

그리고 복호화할 때 패딩을 자동으로 제거하여 원래의 데이터를 얻을 수 있습니다.
예를 들어, Hello 를 암호화한 후 복호화할 때는 자동으로 0x0B 패딩이 삭제되어 Hello 만 출력될 수 있습니다.
PKCS5Padding 의 패딩 규칙을 정리하면 아래와 같습니다.
데이터 크기 | 부족한 바이트 | 패딩 값 |
5바이트 | 11바이트 | 0x0B (11) |
10바이트 | 6바이트 | 0x06 (6) |
15바이트 | 1바이트 | 0x01 (1) |
16바이트 | 0바이트 | 패딩 없음 |
이때 0x는 16진수를 의미합니다. 그래서 0x06 = 6 (10진수), 0x0B = 11 (10진수), 0x01 = 1 (10진수)이 되는 것입니다.
패딩 규칙에는 PKCS5Padding 외에도 PKCS7Padding 도 있습니다.
PKCS5Padding는 블록 크기가 16인 것만 지원하지만,
PKCS7Padding는 16, 32, 64, 128 등 다양한 블록 크기를 지원합니다.
그래서 PKCS5Padding는 AES 에서 많이 사용됩니다.