본문 바로가기

Language/Java

Java Cipher

반응형

자바에서 *대칭키 알고리즘을 사용하여 데이터를 암호화 / 복호화할 때 Cipher클래스를 사용한다.

이 클래스는 정적 메서드인 Cipher.getInstance()를 호출하여 사용할 수 있는데 사용시 사용할 알고리즘, 운용 모드, 패딩 방식을 인자로 넘겨줘야 한다. 대칭키 암호화에서 알고리즘, 운용 모드, 패딩을 무엇이고 어떤 역할을 하는지 알아보자.

- 혼돈과 확산

안전한 암호문은 공격자가 이를 보고 원본 메시지나 암호화에 사용된 키를 유추할 수 없어야 한다. 이러한 성질을 혼돈과 확산이라고 하며 각각 다음과 같은 의미를 갖는다.

@ 혼돈은 *암호문으로부터 키를 알아낼 수 없게 하는 성질이다.

@ 확산은 암호문으로부터 원문을 알아낼 수 없게 하는 성질이다.

 

다르게 말하면 혼돈이란 키의 비트 하나만 바꿔도 암호문 전체가 바뀌도록 하는 성질이다. 안전한 암호는 공격자가 아무리 많은 평문-암호문 쌍을 알고 있어도 그 속에서 키의 패턴을 발견할 수 없어야 한다. 마찬가지로 확산은 원문의 비트를 하나만 바꿔도 암호문 전체가 바뀌도록 하는 성질이다. 

 

- 암호 알고리즘

암호 알고리즘에서는 혼돈과 확산을 달성하기 위해 Substitution(치환)과 Permutation(순열)을 이용한다. 치환은 문자를 다른 문자로 바꾸는 것이고 순열은 문자들의 순서를 바꾸는 것이다. 치환과 순열을 한번 수행하는 것이 암호 알고리즘의 기본 수행 단위이다. 암호문은 이를 여러번 수행할 수 록 안전하다. 치환-순열을 연속하여 수행하도록 이어 놓은 것을 SPN(Subsititution Permutation Network)라고 한다. SPN에서 한 번의 S-P 수행을 라운드 또는 레이어라고 한다. 아래 그림은 3라운드로 이루어진 SPN이다.

 

SPN을 이용하는 대표적인 암호 알고리즘으로 AES(Advanced Encryption Standard)가 있다. SPN을 이용하는 알고리즘은 보통 데이터를 블록 단위로 처리한다. AES의 경우 블록의 크기는 128비트(16바이트)이다. 그런데 모든 데이터가 16바이트 크기를 가질 수 없으므로 데이터를 블록 단위로 나누어 처리하고 합치는 과정이 필요하다. 

- 운용 모드

데이터를 블록으로 나누어 처리하고 합치는 것, 그것이 암호화에서 운용 모드가 하는 역할이다. 대표적인 운용 모드로는 ECB(Electronic Code Book)와 CBC(Cipher Block Chaining)가 있다.

 

@ ECB

ECB는 단순히 블록 단위로 처리한 결과를 이어붙이는 방법이다. 아래 그림은 ECB 처리 방식을 보여준다.

ECB는 단순하지만 같은 값을 갖는 원문 블록은 같은 암호 블록을 출력하기 떄문에 원문의 원문의 패턴이 그대로 드러난다. 이는 암호문에서 원문을 유추할 수 있음을 의미하기 떄문에 ECB는 확산의 성질을 달성하지 못한다고 볼 수 있다. 

 

@ CBC

CBC는 원문 블록을 그대로 암호화하지 않고 직전에 암호화된 블록과 *XOR 연산을 한 다음에 암호화를 수행한다. 그렇기 때문에 같은 내용을 갖는 원문 블록이라도 전혀 다른 암호문을 갖게 된다. 그런데 첫번째 블록은 직전 암호문이 없으므로 XOR 연산 대상이 없다. 이를 위해 CBC 모드는 초기화 벡터(initialization vector)를 입력받는다. 초기화 벡터는 원문 블록을 XOR하는데 쓰이기 때문에 당연히 블록 사이즈와 동일한 크기여야 한다. 아래는 CBC 방식을 나타낸 그림이다.

Cipher Block Chaining

CBC 모드는 직전 블록이 다음 블록의 암호화에 관여하므로 일부 블록만 복호화하고 싶어도 전체를 복호화해야 한다. 반면 ECB는 전체를 복호화하지 않고 일부만 복호화하는 것이 가능하다.

 

- 패딩

AES와 같은 16바이트 크기의 블록 암호 알고리즘을 사용하는데 원문의 크기가 16바이트의 배수가 아니라면 마지막 블록은 16바이트보다 작은 크기가 된다. 이 때 마지막 블록의 빈 부분을 채워주는 방식을 패딩이라고 한다. 가장 유명한 패딩 방식은 PKCS5와 PKCS7이다.

@ PKCS5

PKCS5는 8바이트 블록의 암호 알고리즘을 가정한다. 원문의 길이가 L 바이트이면 마지막 블록은 L *mod 8의 크기를 갖는다. 그럼 패딩 크기는 8 - (L mod 8)가 된다. PKCS5는 단순히 패딩 크기의 값을 갖는 바이트를 크기만큼 반복한다.

8 - (L mod 8)패딩 바이트

1 01
2 02 02
8 08 08 08 08 08 08 08 08

원문이 블록 크기로 나누어 떨어질 때도 패딩이 들어가는 것을 볼 수 있다. 왠지 나누어 떨어지면 패딩을 넣지 않아도 될 것 같지만 그렇지 않다. 블록 크기로 나누어 떨어지는 원문에 패딩을 넣지 않는다고 가정해보자. 이 때 원문의 마지막 바이트가 01이라면 이게 패딩인지 실제 데이터인지 구분할 방법이 없다. 그렇기 때문에 패딩을 할 때는 일관되게 패딩 바이트를 추가해주는 것이다. 

@PKCS7

PKCS7은 8바이트가 아닌 가변 길이를 갖는 다는 점에서 다르지만 원리는 PKCS5와 동일하다. PKCS7에서는 블록 크기가 1에서 255까지의 값을 가질 수 있다.(255는 한 바이트가 가지는 가장 큰 값이다.) 자바에서는 패딩 방식을 입력할 때 PKCS5와 PKCS7을 구분하지 않고 PKCS5Padding이라고 입력한다.

 

자바 코드 예제

자바코드 : http://happinessoncode.com/2019/04/06/java-cipher-algorithm-mode-padding/

 

 

* 대칭키 : 암호화 알고리즘의 한 종류로 암호화와 복호화에 같은 암호 키를 쓰는 알고리즘을 의미한다.

* 암호문 : 평문으로 된 정보를 암호 처리하여 특정인만 이용할 수 있도록 암호화한 문서이다.

* XOR(배타적 연산) : 0 : 0 = 0, 1 : 0 = 1, 0 : 1 = 1, 1 : 1 = 0 (두 숫자를 비교하였을 때 한 숫자가 1일때만 참)

* mod : 나머지 연산을 나타내는 기호로 사용된다. 주로 a MOD b라고 하면 a와 b를 나누었을 때의 나머지를 말한다.

a보다 b가 더 크면 a mod b = a가 된다. (10 mod 3 = 1, 9 mod 3 = 0, 1 mod 3 = 1)

 

출처 : http://happinessoncode.com/2019/04/06/java-cipher-algorithm-mode-padding/

반응형

'Language > Java' 카테고리의 다른 글

Java로 자료구조(LinkedList, Stack, Queue) 구현해보기  (0) 2021.04.26
자바 == 연산자  (0) 2021.04.12
제네릭(Generic)  (0) 2021.04.02
Interface Comparable  (0) 2020.11.29
자바 synchronized  (0) 2019.08.20