[AES] Java 암호화 -> javascript 복호화
javascript -> Java 는 정보가 많이 있었지만
Java -> javascript 는 찾기가 힘들었다. (이렇게는 잘 안하니.....)
또는 찾은 소스들 중에서는 key 값 외에 iv, salt 등의 추가적인 값들을 필요로 하였다.
그래서 생각해낸 방법은
Java 에서 암호화한 로직을 그대로 javascript에서 역으로 푸는 것!
우선,
---------- Java 암/복호화 하는 부분 ----------
public Key generateKey(String key) throws Exception {
Key keySpec;
byte[] keyBytes = new byte[16];
byte[] b = key.getBytes("UTF-8");
int len = b.length;
if (len > keyBytes.length) {
len = keyBytes.length;
}
System.arraycopy(b, 0, keyBytes, 0, len);
keySpec = new SecretKeySpec(keyBytes, "AES");
return keySpec;
}
위에 method 는 키값을 사용하여 암호화키를 만드는 부분. AES128, 196, 256 이 있는데
내가 찾은 걸로는 key 값의 길이에 따라 나뉘는 것 같다.
new byte[16] -> 배열의 길이를 16으로 만드는 것은 AES128 로 하겠다는 의미!
public String encryptText(String text, String key) {
String encrypted = "";
try {
SecretKeySpec ks = (SecretKeySpec) this.generateKey(key);
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, ks);
byte[] encryptedBytes = cipher.doFinal(text.getBytes());
String base64 = Base64.encode(encryptedBytes);
encrypted = new String(base64);
} catch (Exception e) {
// throw new IKEP4ApplicationException("", e);
}
return encrypted;
}
이 method 가 암호화 키값을 사용하여 평문을 암호화 하는 부분.
내가 참여하고있는 프로젝트는 AES 방식에 ECB 모드, PKCS5Padding 으로 암호화를 한다.
public String decAES(String enStr, String key) throws Exception {
SecretKeySpec ks = (SecretKeySpec) this.generateKey(key);
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE, ks);
byte[] byteStr = Base64.decode(enStr.getBytes("UTF-8"));
String decStr = new String(c.doFinal(byteStr), "UTF-8");
return decStr;
}
이 부분은 복호화를 하는 부분.
암호화 부분을 역순으로 진행한다.
-----------------------------------------------------------------------------------------------
그리고 이제 이 복호화 부분의 로직을 javascript 에서 구현할 생각인데....
쉽지가 않다......역시 난 개발자가 아닌 코더...복붙만 잘하는 코더....
뭐 애시당초 client side 인 javascript 에서 복호화를 하는게 좀 말이 안되는 거 같긴 하지만....
지금 환경은 javascript 에서 복호화를 해야만한다. 고로 한다.
우선,
---------- javascript 암/복호화 하는 부분 ----------
javascript 에서 암/복호화를 하기 위해
내가 사용한 javascript Library 는 CryptoJS
https://cryptojs.gitbook.io/docs/
여기에서 사용법을 익히고 라이브러리를 다운 받을 수 있다.
기본적인 사용법.
var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase");
암호화 하는 방법은 아주 간단!
var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase");
console.log(decrypted.toString(CryptoJS.enc.Utf8));
복호화 하는 방법도 아주 간단!
여기까지가 CryptoJS 를 사용한 javascript 암/복호화의 기본 사용법이다.
--------------------------------------------------------------------------------------------
그럼 이제 Java 의 복호화를 javascript 로 구현해보자는 생각으로 달려듬.
Java 와 javascript(CryptoJS) 확인해야할 사항들.
1. 암호화 방식
Java : AES128/ECB/PKCS5Padding
javascript : AES256/CBC/PKCS7Padding
2. 문자, key 사용 방식
Java : getBytet() 를 사용하여 처리
javascript : 문자 그대로 처리
3. 문자열 처리 방식
UTF-8, EUC-KR, ISO... 등 암호화할 때와 동일한 문자열로 복호화를 해야 제대로 나온다.
예로 한글을 EUC-KR 로 복호화 하면 2바이트 기준, UTF-8 로 복호화 하면 3바이트 기준이다.
하지만 우리는 UTF-8로 암복호화 하니 상관이 없스
--------------------------------------------------------------------------------------------
이제 해결해보기
1. 암호화 방식
CryptoJS 라이브러리는 기본 AES256/CBC/PKCS7 인데
복호화를 위해 Java에서 설정한 것과 동일하게 맞춰줘야한다.
AES256은 키값의 길이. 고로 이건 키의 길이를 맞춰주면 해결!
CBC 는 ECB 로 바꿔줘야하니깐 mode_ecb.js 를 사용 후.
var decrypt = CryptoJS.AES.decrypt(encrypted, key, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
console.log(decrypt.toString(CryptoJS.enc.Utf8));
위에서 처럼 mode 에 ECB 를 지정 해주면 해결!
PKCS7 은 PKCS5 의 상위 버전이라 PKCS5도 지원 한다. 위에서 선언해주긴 했지만 default 라 신경 안써도 됨.
혹시나 해서 이대로 복호화를 했는데 역시나 아무런 값이 안나옴.
2. 값 사용 방식
for 문을 사용하여 값들의 byte 를 다 받아와서 처리하였음.
역시 안나옴.
무엇이 문제일까......
Java 의 암/복호화 하는 부분을 보면 Base64 로 encode/decode 하는 부분이 있네?!
복호화할 값에 Base64 로 decode 를 한 다음 적용.
안나옴........젠장 젠장....역시 난 코더인가.....단순 따라하기만 가능한가.....
테스트 방법
값 | key | |
Base64 encode |
O | O |
O | X | |
X | O | |
X | X |
값 | key | |
Base64 parsing |
O | O |
O | X | |
X | O | |
X | X |
값 | key | |
byte 처리 |
O | O |
O | X | |
X | O | |
X | X |
이거 외에도 Base64 후 byte 로 처리도 해보고 다 했지만 안됨.
2일 고생하고
3일째 되는날 문득
검색을 하다
https://coderanch.com/t/637480/engineering/Java-encryption-javascript-decryption
여기에서 생각지 못한 부분을 발견함.
암호화된 텍스트는 그대로 사용하고 key 값을 Base64 로 인코딩 한 다음 그걸
CryptoJS 를 사용하여 다시 Base64 paring 을 한 후에 적용.
풀린다.
와.........Base64 한걸로 적용해보기는 했지만 한번더 parsing 을 해야하다니....
이렇게 풀리다니 내가 소스를 끝까지 다 안까본 잘못도 있지만....
역시 난 코더 ^^ ㅎㅎ 그냥 궁금증이 많은 코더로 남아야겠숴..
아래는 복호화 방법.
var base64 = btoa(key);
var decrypt = CryptoJS.AES.decrypt(encrypted, CryptoJS.enc.Base64.parse(base64)), {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
후우 해결이 되었다....이렇게 하루하루 근근히 살아간다.....
'일하딩 > Web' 카테고리의 다른 글
[CSS] Position 이란? (static, relative, sticky, fixed, absolute) (0) | 2020.07.26 |
---|---|
[Html] Button 태그 사용시 자동 submit 없애기 (0) | 2019.12.16 |
[Jsoup] Java 로 웹 크롤링 하기. (0) | 2019.12.03 |
[chart.js] javascript 로 차트 그리기 (2) | 2019.11.05 |
[Servlet] JSP 를 사용하지 않고 javascript 에서 Java 호출 하기. (0) | 2019.11.01 |
댓글