Dev Language/JAVA

AES, SHA 암호화 1, JAVA

타카스 류지 2017. 3. 30. 11:33

java 언어를 이용해서 

블럭암호화는 AES 128/256으로,  해쉬함수는 SHA 256 알고리즘으로 암호화 진행해 보겠습니다.

SHA 128은 보안상 위험함으로 사용안하는것을 추천합니다.

java의 경우 AES 256 암호화를 하기 위해서는 주석에 나와 있는것처럼  http://www.oracle.com/technetwork/java/javase/downloads/index.html에서 파일을 다운받아 JCE관련 패치를 해야됩니다.

base64 인코딩을 위해 commons-codec 라이브러리 추가하였습니다. jdk에 포함되어 있는sun.misc.BASE64Encoder(), sun.misc.BASE64Decoder() 이 클래스들은 http://www.oracle.com/technetwork/java/faq-sun-packages-142232.html를 보면 지원도 보장도 안한다고 나와 있습니다.

pom.xml

<dependency>

        <groupId>commons-codec</groupId>

        <artifactId>commons-codec</artifactId>

        <version>1.10</version>

</dependency>


이클립스에 코딩~~

package com.tistory.aircook;

 

import java.security.MessageDigest;

 

import javax.crypto.Cipher;

import javax.crypto.spec.IvParameterSpec;

import javax.crypto.spec.SecretKeySpec;

 

import org.apache.commons.codec.CharEncoding;

import org.apache.commons.codec.binary.Base64;

import org.apache.commons.codec.binary.Hex;

 

public class Crypto {

 

        public static void main(String[] args) {

 

               String str1 = "암호화되지 않은 문자";

               System.out.println("plain : " + str1);

 

               String str2 = encryptAES128(str1);

               System.out.println("AES128 encrypted : " + str2);

 

               String str3 = decryptAES128(str2);

               System.out.println("AES128 decrypted : " + str3);

              

               String str4 = encryptAES256(str1);

               System.out.println("AES256 encrypted : " + str4);

              

               String str5 = decryptAES256(str4);

               System.out.println("AES256 decrypted : " + str5);

              

               String str6 = encryptSHA256(str1);

               System.out.println("SHA256 encrypted : " + str6);

 

        }

 

        // 

        private final static String KEY = "01234567890123456789012345678901";

 

        // 128bit (16자리)

        private final static String KEY_128 = KEY.substring(0, 128 / 8);

       

        // 256bit (32자리)

        private final static String KEY_256 = KEY.substring(0, 256 / 8);

 

        // AES 128 암호화

        public static String encryptAES128(String string) {

 

               try {

                       byte[] keyData = KEY_128.getBytes(CharEncoding.UTF_8);

 

                       // 운용모드 CBC, 패딩은 PKCS5Padding

                       Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

 

                       // key 와 iv 같게..

                       // 블록 암호의 운용 모드(Block engine modes of operation)가 CBC/OFB/CFB를 사용할 경우에는

                       // Initialization Vector(IV), IvParameterSpec를 설정해줘야한다. 아니면 InvalidAlgorithmParameterException 발생

                      

                       cipher.init(Cipher.ENCRYPT_MODEnew SecretKeySpec(keyData"AES"), new IvParameterSpec(keyData));

 

                       // AES 암호화

                       byte[] encrypted = cipher.doFinal(string.getBytes(CharEncoding.UTF_8));

 

                       // base64 인코딩

                       byte[] base64Encoded = Base64.encodeBase64(encrypted);

 

                       // 결과

                       String result = new String(base64Encoded, CharEncoding.UTF_8);

 

                       return result;

               }

               catch (Exception e) {

                       return null;

               }

        }

 

        // AES 128복호화

        public static String decryptAES128(String string) {

 

               try {

                       byte[] keyData = KEY_128.getBytes(CharEncoding.UTF_8);

 

                       // 운용모드 CBC, 패딩은 PKCS5Padding

                       Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

 

                       cipher.init(Cipher.DECRYPT_MODEnew SecretKeySpec(keyData"AES"), new IvParameterSpec(keyData));

 

                       // base64 디코딩

                       byte[] base64Decoded = Base64.decodeBase64(string.getBytes(CharEncoding.UTF_8));

 

                       // AES 복화화

                       byte[] decrypted = cipher.doFinal(base64Decoded);

 

                       // 결과

                       String result = new String(decrypted, CharEncoding.UTF_8);

 

                       return result;

               }

               catch (Exception e) {

                       return null;

               }

        }

       

        // AES 256 암호화

        public static String encryptAES256(String string) {

 

               try {

                       byte[] key256Data = KEY_256.getBytes(CharEncoding.UTF_8);

                       byte[] key128Data = KEY_128.getBytes(CharEncoding.UTF_8);

 

                       // 운용모드 CBC, 패딩은 PKCS5Padding

                       Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

 

                       // key 와 iv 같게..

                       // 블록 암호의 운용 모드(Block engine modes of operation)가 CBC/OFB/CFB를 사용할 경우에는

                       // Initialization Vector(IV), IvParameterSpec를 설정해줘야한다. 아니면 InvalidAlgorithmParameterException 발생

                      

                       // AES 256은 미국만 되는거라. JDK/JRE 패치를 해야된다.

                       // http://www.oracle.com/technetwork/java/javase/downloads/index.html 에서

                       // Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files for JDK/JRE 8 이런 링크 찾아서 다운

                       // $JAVA_HOME\jre\lib\security 아래에 local_policy.jar, US_export_policy.jar 파일 overwrite!

                      

                       // iv값이 16자리가 아니면..

                       // java.security.InvalidAlgorithmParameterException: Wrong IV length: must be 16 bytes long 발생

                      

                       cipher.init(Cipher.ENCRYPT_MODEnew SecretKeySpec(key256Data"AES"), new IvParameterSpec(key128Data));

 

                       // AES 암호화

                       byte[] encrypted = cipher.doFinal(string.getBytes(CharEncoding.UTF_8));

 

                       // base64 인코딩

                       byte[] base64Encoded = Base64.encodeBase64(encrypted);

 

                       // 결과

                       String result = new String(base64Encoded, CharEncoding.UTF_8);

 

                       return result;

               }

               catch (Exception e) {

                       return null;

               }

        }      

       

        // AES 256복호화

        public static String decryptAES256(String string) {

 

               try {

                       byte[] key256Data = KEY_256.getBytes(CharEncoding.UTF_8);

                       byte[] key128Data = KEY_128.getBytes(CharEncoding.UTF_8);

 

                       // 운용모드 CBC, 패딩은 PKCS5Padding

                       Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

 

                       cipher.init(Cipher.DECRYPT_MODEnew SecretKeySpec(key256Data"AES"), new IvParameterSpec(key128Data));

 

                       // base64 디코딩

                       byte[] base64Decoded = Base64.decodeBase64(string.getBytes(CharEncoding.UTF_8));

 

                       // AES 복화화

                       byte[] decrypted = cipher.doFinal(base64Decoded);

 

                       // 결과

                       String result = new String(decrypted, CharEncoding.UTF_8);

 

                       return result;

               }

               catch (Exception e) {

                       return null;

               }

        }      

       

 

        public static String encryptSHA256(String string) {

              

               try {

                       MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");

 

                       byte[] stringBytes = string.getBytes();

                       int stringBytesLength = stringBytes.length;

 

                       byte[] dataBytes = new byte[1024];

                       for (int i = 0; i < stringBytesLengthi++) {

                              dataBytes[i] = stringBytes[i];

                       }

 

                       messageDigest.update(dataBytes, 0, stringBytesLength);

 

                       byte[] encrypted = messageDigest.digest();

 

                       // hex, 16진수

                       // StringBuffer sb = new StringBuffer();

                       // for (int i = 0; i < encrypted.length; i++) {

                       //      sb.append(Integer.toString((encrypted[i] & 0xff) + 0x100, 16).substring(1));

                       // }

                       // 결과

                       // String result = sb.toString();

                      

                       // commons codec lib 사용하면 아래처럼 간단하게..

                       // String result = Hex.encodeHexString(encrypted);

                      

                      

                       // base64 인코딩

                       byte[] base64Encoded = Base64.encodeBase64(encrypted);

                       // 결과

                       String result = new String(base64Encoded, CharEncoding.UTF_8);

 

                       return result;

               }

               catch (Exception e) {

 

                       return null;

               }

        }

}


결과



출처: http://aircook.tistory.com/entry/AES-SHA-암호화-1-JAVA [aircook의 잡동사니]