흐르는 시간의 블로그...

AES 관련 코딩을 하다보니 내가 연결하려는 서버측과 내가 가지고 있는 C++ 소스의 상황이 달랐다.


예제로 구한 코드에서 IV(초기화 벡터)값을 요구 했다.


하지만 고객사에서 보내온 Java 파일에는 해당 값들이 전혀 없었다.(링크된 내용과 동일한 코드였다)


알고 봤더니... 다음과 같은 Block Mode들이 존재 했다.

내쪽에서는 CBC를 사용하는 C++ 코드를 사용했고 상대측에서 보내온 자바파일은 디폴트를 사용했는데 자바는 ECB가 기본이었다


자료 출처는 AES-128-CBC 를 이용하는 방법 을 참고했다

아래의 자료는 위 출처의 자료이다.





AES-128-CBC 를 이용하는 방법

AES는 Block으로 나눠어서 암호화를 하는데 128, 192, 256비트로 나눌 수가 있다.
Block으로 암호화를 할때는 아래와 같이 4가지 모드가 있는데
1. ECB ( Electric Code Book )
2. CBC ( Cipher Block Chaining )
3. OFB ( Output Feed Back )
4. CFB ( Cipher Feed Back )
원래 위의 4개 모드는 DES 이용을 위해 고안되었는데 DES에 한정하지 않고 모든 Block암호에 적용이 가능하다.
이외에도 PCBC와 Counter Method등의 새로운 모드도 고안되고 있다고 한다.
먼저 ECB 모드를 살펴보자.
ECB모드는 1Block씩 단순히 처리를 한다.
암호문공격에 취약하며 사이즈가 큰 문서의 암호는 어울리지 않아 크게 쓰이고 있지는 않은듯하다.

http://jo.centis1504.net/wp-content/uploads/2010/11/Encryption-ECB_MODE.swf

두번째로 CBC모드인데 앞서의 ECB에서의 암호화한 Block의 결과를 다음의 Block에 XOR 연산하여 나가는게 특징이다. 이때 제일 처음의 암호화시에는 마지막 블럭결과를 이용하거나 IV (Initial Vector)를 이용하게 된다.

http://jo.centis1504.net/wp-content/uploads/2010/11/Encryption-CBC_MODE.swf

세번째로 OFB모드인데 IV를 암호화하여 그것을 다시 암호화한 후 계속 난수를 생성한다. 그렇게 생성된 난수리스트를 XOR 연산에 의해 원문에 적용하여 암호화하는 방식이다. 즉, Block암호를 Stream암호와 같이 사용한다고 보면 되겠다.

http://jo.centis1504.net/wp-content/uploads/2010/11/Encryption-OFB_MODE.swf

상세정보는 http://www.triplefalcon.com/Lexicon/Encryption-Block-Mode-1.htm 를 참조할것.
그럼 Java에서 AES-128-CBC를 이용하는 방법은 아래와 같다.
공통키를 생성하는 방법은 이전 포스트를 참조할것.

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secureKey);byte[] iv = cipher.getIV();
byte[] encryptedData = cipher.doFinal("".getBytes());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE,secureKey);
byte[] iv = cipher.getIV();byte[] encryptedData = cipher.doFinal("".getBytes());

복호화는 아래와 같다.

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
AlgorithmParameters iv = AlgorithmParameters.getInstance("AES");
iv.init("IV".getBytes());
cipher.init(Cipher.DECRYPT_MODE, secureKey, iv);
byte[] plainData = cipher.doFinal(encryptedData);