암호화 알고리즘에는 단방향 암호화와 양방향 암호화가 있다.
1. 단방향 암호화
- 암호화를 시키면 복호화 할 수 없음
- 복원 방법이 없으므로 주로 패스워드로 사용함
- SHA1, SHA244, SHA256, SHA512 등이 있음
2. 양방향 암호화
- 데이터 통신에 주로 사용
- 중요한 정보들을 보안조치 하기 위해 암호화 하여 보냄
- DES(3중 암호화), AES128, AES192, AES256 등이 있음
Aes256로 암호화, 복호화 하는 방법을 알아보자.
암호화
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public static String AES_Encode(String str, int vendorType) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException, BadPaddingException, IllegalBlockSizeException, IllegalStateException, UnsupportedEncodingException { byte[] keyData = null; //3rd if (vendorType == 1) { keyData = secretKey_3rd.getBytes(); } SecretKey secureKey = new SecretKeySpec(keyData, "AES"); Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); c.init(Cipher.ENCRYPT_MODE, secureKey, new IvParameterSpec(IV)); byte[] encrypted = c.doFinal(str.getBytes("UTF-8")); String enStr = new String (Base64.encodeBase64(encrypted)); return enStr; } | cs |
복호화
1 2 3 4 5 6 7 8 9 | public static String AES_Decode(String str) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException, UnsupportedEncodingException, BadPaddingException, IllegalBlockSizeException, IllegalStateException { SecretKey secureKey = new SecretKeySpec(keyData, "AES"); Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); c.init(Cipher.DECRYPT_MODE, secureKey, new IvParameterSpec(IV)); byte[] byteStr = Base64.decodeBase64(str.getBytes()); return new String(c.doFinal(byteStr), "UTF-8"); } | cs |
사용 방법
- GET방식으로 전달 시 특수문자가 깨질 수 있으므로 URLDecoder로 디코딩 해준 후 복호화 한다.
1 2 3 | String ssoKey = (String) map.get("ssoKey"); ssoKey = URLDecoder.decode(ssoKey); String aesDecodeTest = new String(Aes256.AES_Decode(ssoKey)); | cs |
그런데, JDK 8u161 이전 버전을 사용할 경우 AES-256 암호화 작업중에 다음과 같은 예외가 발생한다.
- java.security.InvalidKeyException: Illegal key size or default parameters
이전 버전에서는 키 길이에 제한이 걸려 있기 때문에 JDK 8u161 업데이트 릴리즈 부터 제한하지 않는 것이 기본값으로 설정되어 있다.
따라서, 이전 버전의 JDK 를 사용할 때는 AES-256을 사용하기 위해서 jce policy 파일을 패치해야 한다.
JCE(Java Cryptography Extension) 모듈 다운로드 URL: https://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
해당 URL로 접속하여 파일 다운로드 후 jre/lib/security/ 아래에 local_policy.jar, US_export_policy.jar 파일을 교체해준다.
참고: Aes256.java Full 소스코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | package com.xxx.kr.common.util; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Map; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; public class Aes256 { public static void main(String[] args) throws Exception { } private static volatile Aes256 INSTANCE; final static String secretKey_3rd = "XXXSecurity123#XXXSecurity123#"; //sender=3rd final static byte[] IV = new byte[]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; public static Aes256 getInstance() { if (INSTANCE == null) { synchronized (Aes256.class) { if ( INSTANCE == null) { INSTANCE = new Aes256(); } } } return INSTANCE; } private Aes256() { } public static String AES_Encode(String str, int vendorType) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException, BadPaddingException, IllegalBlockSizeException, IllegalStateException, UnsupportedEncodingException { byte[] keyData = null; if (vendorType == 1) { keyData = secretKey_3rd.getBytes(); } SecretKey secureKey = new SecretKeySpec(keyData, "AES"); Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); c.init(Cipher.ENCRYPT_MODE, secureKey, new IvParameterSpec(IV)); byte[] encrypted = c.doFinal(str.getBytes("UTF-8")); String enStr = new String (Base64.encodeBase64(encrypted)); return enStr; } public static String AES_Decode(String str) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException, UnsupportedEncodingException, BadPaddingException, IllegalBlockSizeException, IllegalStateException { byte[] keyData = secretKey_3rd.getBytes(); SecretKey secureKey = new SecretKeySpec(keyData, "AES"); Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); c.init(Cipher.DECRYPT_MODE, secureKey, new IvParameterSpec(IV)); byte[] byteStr = Base64.decodeBase64(str.getBytes()); return new String(c.doFinal(byteStr), "UTF-8"); } public static String getShaEncrypt(String planText) { try{ MessageDigest md = MessageDigest.getInstance("SHA-256"); md.update(planText.getBytes()); byte byteData[] = md.digest(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < byteData.length; i++) { sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1)); } StringBuffer hexString = new StringBuffer(); for (int i=0;i<byteData.length;i++) { String hex=Integer.toHexString(0xff & byteData[i]); if(hex.length()==1){ hexString.append('0'); } hexString.append(hex); } return hexString.toString(); }catch(Exception e){ e.printStackTrace(); throw new RuntimeException(); } } } | cs |