백앤드 이야기/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 를 추가 해줘야 예외가 발생되지 않는다.


commons-codec-1.13.jar

local_policy.jar

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 블로그 "안전한 패스워드 저장" 바로가기


반응형

댓글

💲 추천 글