백앤드 이야기/JAVA&Spring

[JAVA] 자바 비대칭키, 대칭키 암호화 하기

한희성 2019. 9. 16.

목차

    반응형

    java.security 라이브러리를 이용한 자바 암호화하기, 되새겨보려는 의도로 작성하는


    포스팅이기때문에 설명이 충분하지 않을 수 있습니다.


    요즘같은 개인정보 유출 사례가 많은시대에 암호화는 선택이 아닌 필수입니다.


    참고자료를 보기위해 대학교 수업때사용했던 알기쉬운 정보보호개론 책을 다시 책장에서 끄집어냈습니다. ㅋㅋ


    본문에 들어가기전 몇 교양으로 알고 넘어가야 할 기초 개념은 아래와 같습니다.


    암호 : 해독 불가능한 형태로 변환 또는 변환된 암호를 해독 가능한 형태로 변환

    평문(Plaintext) : 일반 텍스트, 즉 눈에 보이는 글자

    암호문(Chphertext) : 해독 불가능한 텍스트

    암호화(Encryption) : 평문을 암호문으로 변환

    복호화(Decryption) :  암호문을 평문으로 변환

    대칭키 암호화 알고리즘(비밀키) : 암호화키와 복호화키가 같다 

    비대칭키 암호화 알고리즘(공개키) : 암호화키와 복호화키가 서로 다르다


    1. MD5

    - MessageDigest 객체를 이용하여 알고리즘 타입을 "MD5"로 생성.

    - 128bit 의 해시 값.

    - 암호화 키가 없기때문에 역시 복호화 키도 없다. 패스워드 암호화 경우 복잡하게 하는것이 좋음.

    - 서로 다른 값에 같은 해시가 발생하는 충돌 취약점이 발견되어 사용은 권장하지 않음.


    2. SHA-256

    - MessageDigest 객체를 이용하여 알고리즘 타입을 "SHA-256"로 생성.

    - 256bit 의 해시 값.

    - 암호화 키가 없기때문에 역시 복호화 키도 없다.


    3. SHA-512

    - MessageDigest 객체를 이용하여 알고리즘 타입을 "SHA-512"로 생성.

    - 512bit 의 해시 값.

    - 암호화 키가 없기때문에 역시 복호화 키도 없다.


      public static String generateMD5(String message) {

    return hashString(message, "MD5","UTF-8");

    }

    public static String generateSHA256(String message)  {

    return hashString(message, "SHA-256","UTF-8");

    }


    public static String generateSHA512(String message)  {

    return hashString(message, "SHA-512","UTF-8" );

    }

    private static String hashString(String message, String algorithm, String charest) {

    try {

    MessageDigest digest = MessageDigest.getInstance(algorithm);


    byte[] hashedBytes = digest.digest(message.getBytes(charest));

    return convertByteArrayToHexString(hashedBytes);

    } catch (NoSuchAlgorithmException | UnsupportedEncodingException ex) {

    return "";

    }

    }

    private static String convertByteArrayToHexString(byte[] arrayBytes) {

    StringBuffer stringBuffer = new StringBuffer();

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

    stringBuffer.append(Integer.toString((arrayBytes[i] & 0xff) + 0x100, 16).substring(1));

    }

    return stringBuffer.toString();

    }


    대칭키 알고리즘


    복호화 키만 알고 있으면 암호화된 것을 복호화 할 수 있기때문에 유출되지 않도록 주의해야한다.


    AES256 : 16자리의 암호화 키가 필요하며 16자리 이하일경우는 UnsupportedEncodingException 가 발생된다.

    Cipher 객체에 존재하지 않는(오타) 알고리즘을 전달할 시 NoSuchAlgorithmException 가 발생되며

    인코딩 타입력시 잘못 전달할 시 UnsupportedEncodingException 발생된다.

    국내에서 지원하는 자바정책은 AES128 까지 이므로 jar 를 추가 해줘야 예외가 발생되지 않는다.


    [JAVA] 자바 비대칭키, 대칭키 암호화 하기commons-codec-1.13.jar

    [JAVA] 자바 비대칭키, 대칭키 암호화 하기local_policy.jar

    [JAVA] 자바 비대칭키, 대칭키 암호화 하기US_export_policy.jar


    최신버젼은 메이븐에서 확인

     

    import java.io.UnsupportedEncodingException;

    import java.security.GeneralSecurityException;

    import java.security.Key;

    import java.security.NoSuchAlgorithmException;


    import javax.crypto.Cipher;

    import javax.crypto.spec.IvParameterSpec;

    import javax.crypto.spec.SecretKeySpec;


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


    /**

     * 양방향 암호화 알고리즘인 AES256 암호화를 지원하는 클래스

     */

    public class AES256Util {

        private String iv;

        private Key keySpec;


        


        public AES256Util() {

    // TODO Auto-generated constructor stub

    }

        

        /**

         * 16자리의 키값을 입력하여 객체를 생성한다.

         * @param key 암/복호화를 위한 키값

         * @throws UnsupportedEncodingException 키값의 길이가 16이하일 경우 발생

         */

        public AES256Util(String key) throws UnsupportedEncodingException {

            this.iv = key.substring(0, 16);

            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);

            SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");


            this.keySpec = keySpec;

        }


    /**

         * AES256 으로 암호화 한다.

         * @param str 암호화할 문자열

         * @return

         * @throws NoSuchAlgorithmException

         * @throws GeneralSecurityException

         * @throws UnsupportedEncodingException

         */

        public String encrypt(String str) throws NoSuchAlgorithmException, GeneralSecurityException, UnsupportedEncodingException{

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

            c.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv.getBytes()));

            byte[] encrypted = c.doFinal(str.getBytes("UTF-144"));

            String enStr = new String(Base64.encodeBase64(encrypted));

            return enStr;

        }


        /**

         * AES256으로 암호화된 txt 를 복호화한다.

         * @param str 복호화할 문자열

         * @return

         * @throws NoSuchAlgorithmException

         * @throws GeneralSecurityException

         * @throws UnsupportedEncodingException

         */

        public String decrypt(String str) throws NoSuchAlgorithmException, GeneralSecurityException, UnsupportedEncodingException {

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

            c.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv.getBytes()));

            byte[] byteStr = Base64.decodeBase64(str.getBytes());

            return new String(c.doFinal(byteStr), "UTF-8");

        }


    출처 : http://github.kindler.io/java-encrypt


    * SHA256을 사용할 경우 발생할 수 있는 문제점에 대한 글 : 네이버 D2 블로그 "안전한 패스워드 저장" 바로가기


    반응형

    댓글