자바 JCE 에서의 AES 관련 질문
JCE를 이용해 AES 암 복호화를 구현을 했습니다.
그런데 문제가
긴 문자열을 암호화 한 값 중 일부만 다른 값으로 변조하여
복호화를 한 경우 일부만 문자열이 깨질 뿐 나머지는 정상적으로 복호화가 됩니다.
예를들어
평문
144662ba1c07a11633c051c42b77d455b82b9613aa2181f9cda9941d53e44389
암호화 하면 아래의 암호문을 얻어옵니다.
9d886adfea492e0f503a98e0f80d33d6c6eafeeb9a360e44fdc392bcb9249db2bf700945c65ea7018fa60d5c403f6b5b4965d5212a3e1cd74e13f50bad080e7d5015133e6f78ce131106f5442000aac1
이때 위 암호문 중 첫 글자 9만 변조하여 복호화를 했다면 완전히 깨져서 나와야 정상 아닙니까
그런데 아래처럼 일부만 깨지고 잘 복호화 되어 나옵니다.
@#!!@#$!@#$!@#!@a33c051c42b77d455b82b9613aa2181f9cda9941d53e44389
(실제는 더 이상하게 깨져서 나오나 이 게시판에서 깨진글자가 인식이 안되 저렇게 대체합니다.)
즉 평문 33c051c~ 부터는 잘 복호화 되서 나옵니다.
글자가 완전히 깨져서 나올 수 있는 방법은 없는건가요?
아래는 소스 전문입니다.
소스는 아래 URL을 참고했습니다.
http://java.sun.com/developer/technicalArticles/Security/AES/AES_v1.html
-------------------------------------------------------------------
// 암호화
public String encrypt(String plainText) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
byte[] raw = new byte[] { -121, 7, 49, 40, -95, -16, -118, -85, 28, -67, -63, 2, 101, 56, -72, 111};
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(plainText.getBytes());
return asHex(encrypted);
}
// 복호화
public String decrypt(String cipherText) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
byte[] raw = new byte[] { -121, 7, 49, 40, -95, -16, -118, -85, 28, -67, -63, 2, 101, 56, -72, 111};
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] original = cipher.doFinal(fromString(cipherText));
String originalString = new String(original);
return originalString;
}
private static String asHex(byte buf[]) {
StringBuffer strbuf = new StringBuffer(buf.length * 2);
int i;
for (i = 0; i < buf.length; i++) {
if (((int) buf[i] & 0xff) < 0x10) strbuf.append("0");
strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
}
return strbuf.toString();
}
private static byte[] fromString(String hex) {
int len = hex.length();
byte[] buf = new byte[((len + 1) / 2)];
int i = 0, j = 0;
if ((len % 2) == 1)
buf[j++] = (byte) fromDigit(hex.charAt(i++));
while (i < len) {
buf[j++] =
(byte) ((fromDigit(hex.charAt(i++)) << 4)
| fromDigit(hex.charAt(i++)));
}
return buf;
}
private static int fromDigit(char ch) {
if (ch >= '0' && ch <= '9')
return ch - '0';
if (ch >= 'A' && ch <= 'F')
return ch - 'A' + 10;
if (ch >= 'a' && ch <= 'f')
return ch - 'a' + 10;
throw new IllegalArgumentException("invalid hex digit '" + ch + "'");
}
AES 알고리즘은 블록
AES 알고리즘은 블록 암호 알고리즘입니다. 따라서 별도의 운영모드 없이 암호화 하게 되면 말씀하신대로 암호화된 문자열중 일부만 변경하였을 때 변경된 부분의 암호만 복호화가 되지 않고 나머지는 정상적으로 복호화 하게 됩니다.
이럴 경우 암호의 패턴이 쉽게 드러날 수 있으므로 AES 암호의 강도가 유지된다고 보기 힘들지요. 그래서 CBC 모드 같은 것들을 사용하게 되는데 첫 블록을 암호화 하고 이를 그 다음 블록의 암호화 블록과 XOR 시키고 이를 다시 그 다음 암호화 블록과 XOR 시키는 등의 방식으로 마지막 블록까지 이어 나가게 됩니다. 그리고 제일 처음 암호화 되는 블록은 보통 임의의 이니셜 벡터와 암호화 시키게 되구요.
복호화 할 때에는 XOR 의 특징을 이용해서 a xor b xor b=a
CBC 모드 이외에도 여러가지 운영모드가 존재하고 블록 암화 알고리즘을 효과적으로 이용하기 위해서는 이런 운영모드들을 잘 이해하는게 중요합니다.
블럭 암호화의
블럭 암호화의 특성상 암/복호화가 블럭 단위로 이루어집니다.
예를들어 16바이트 단위로 암호화를 하는 알고리즘을 사용할 경우
처음 16바이트가 암호화되고 그다음 16바이트가 암호화 됩니다.
헌데 동작모드에 따라서 이들 블럭들을 다루는 방식이 틀려집니다.
모드에 대해서 살펴보면 답을 얻을 수 있을 겁니다.
http://java.sun.com/j2se/1.5.0/docs/guide/security/jce/JCERefGuide.html#SimpleEncrEx
---------
간디가 말한 우리를 파괴시키는 7가지 요소
첫째, 노동 없는 부(富)/둘째, 양심 없는 쾌락
셋째, 인격 없는 지! 식/넷째, 윤리 없는 비지니스
이익추구를 위해서라면..
다섯째, 인성(人性)없는 과학
여섯째, 희생 없는 종교/일곱째, 신념 없는 정치
---------
간디가 말한 우리를 파괴시키는 7가지 요소
첫째, 노동 없는 부(富)/둘째, 양심 없는 쾌락
셋째, 인격 없는 지! 식/넷째, 윤리 없는 비지니스
이익추구를 위해서라면..
다섯째, 인성(人性)없는 과학
여섯째, 희생 없는 종교/일곱째, 신념 없는 정치
댓글 달기