Language/JAVA

[암/복호화] 로그인 시 암호화 (AES256/MD5Hash/CBC/PKCS5 패딩)

개랭갱깽스타 2020. 6. 2. 11:29

0. 

로그인 시에 암/복호화를 처음으로 적용해보았다.

1. 프로세스

   1) 암복호화 키 생성: byte[] 키 생성

   2) 암호화(AES256) - password

     (1) byte[] 키를 MD5해시 -> 키값의 명세 객체 생성 (AES256) && AlgorithmParameterSpec 객체 생성

     (2) Cipher를 이용해 암호화 진행

   3) RequestUser 로 서버와 통신

생각보다 간단하다!

 

2. 코드

1) 암복호화 키 생성: byte[] 키 생성

- 나의 경우에는 "서버와 약속한 키"에 "timeStamp"를 조합해 암복호화 키를 생성했다.

public void init(String timeStamp) throws UnsupportedEncodingException {
     this.timeStamp = timeStamp;
     StringBuilder seedKeyBuilder = new StringBuilder("서버와 약속 한 키");
     seedKeyBuilder.append(timeStamp);
     seedKey = seedKeyBuilder.toString().getBytes("UTF-8");
}

 

2) 암호화(AES256) - password

public String encrypt(String originPassword) throws Exception {
     AES256 aes256 = new AES256(seedKey);	//(1)키를 이용해 AES256 관련 객체 초기화
     byte[] encPassword = aes256.encrypt(originPassword.getBytes("UTF-8"));	//(2) 암호화
     return encodeToString(encPassword);
}

 

AES256 객체를 자세히 살펴보자!

AES256.java

import java.nio.ByteBuffer;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AES256 {
    private static final String KEY_SPEC = "AES";	//암호화 방식
    private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";//암호화방식/??/패딩방식

    private Key mKey;	//암호화키
    private AlgorithmParameterSpec mAlgorithmParameterSpec;	//알고리즘스펙

    //1. AES 객체 생성
    public AES256(byte[]... seeds) {
    	//(1) 키를 MD5방식으로 해시한다.
        byte[] key = KeyGenerator.generateKey(seeds);
        //(2) 키값의 명세 객체 생성 (AES256)
        this.mKey = new SecretKeySpec(key, KEY_SPEC);
        //(3) AlgorithmParameterSpec 객체 생성
        this.mAlgorithmParameterSpec = new IvParameterSpec(key);
    }

 	//2. 암호화
    public byte[] encrypt(byte[] plainData) throws Exception {
        if (mKey != null && mAlgorithmParameterSpec != null) {
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.ENCRYPT_MODE, mKey, mAlgorithmParameterSpec);
            return cipher.doFinal(plainData);
        }

        return null;
    }

	//3. 복호화
    public byte[] decrypt(byte[] encData) throws Exception {
        if (mKey != null && mAlgorithmParameterSpec != null) {
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.DECRYPT_MODE, mKey, mAlgorithmParameterSpec);
            return cipher.doFinal(encData);
        }
        return null;
    }

    public void destroy() {
        mKey = null;
        mAlgorithmParameterSpec = null;
    }

    private static class KeyGenerator {

        public static byte[] generateKey(byte[]... seeds) {
            ByteBuffer byteBuffer = toByteBuffer(seeds);

            byte[] key = getMD5Hash(byteBuffer.array());

            clearByteBuffer(byteBuffer);

            return key;
        }

        private static byte[] getMD5Hash(byte[] input) {
            byte[] result = null;
            try {
                MessageDigest md = MessageDigest.getInstance("MD5");
                result = md.digest(input);
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            return result;
        }

        private static ByteBuffer toByteBuffer(byte[]... bytesArray) {
            int capacity = 0;

            for (byte[] bytes : bytesArray) {
                capacity += bytes.length;
            }

            ByteBuffer byteBuffer = ByteBuffer.allocate(capacity);
            for (byte[] bytes : bytesArray) {
                byteBuffer.put(bytes);
            }

            return byteBuffer;
        }

        private static void clearByteBuffer(ByteBuffer byteBuffer) {
            Arrays.fill(byteBuffer.array(), (byte) 0);
            byteBuffer.clear();
        }
}

 

/*
  * AES256 암호화/base64 암호화
  */
 public static String encryptBase64(byte [] key, String data) throws NoSuchPaddingException,
   NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException,
   BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
  		Key secureKey = new SecretKeySpec(key, "AES");
  		IvParameterSpec ivParameterSpec = new IvParameterSpec(key);
  		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
  		cipher.init(Cipher.ENCRYPT_MODE, secureKey, ivParameterSpec);
  		
        return Base64.encodeBase64String(cipher.doFinal(data.getBytes("UTF-8")));
 }
 
 /*
  * base64 복호화/AES256 복호화
  */
 public static String decryptBase64(byte [] key, String data) throws NoSuchPaddingException,
   NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException,
   BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
  		Key secureKey = new SecretKeySpec(key, "AES");
  		IvParameterSpec ivParameterSpec = new IvParameterSpec(key);
  		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
  		cipher.init(Cipher.DECRYPT_MODE, secureKey, ivParameterSpec);
  
  		return new String(cipher.doFinal(Base64.decodeBase64(data)));
 }
반응형

'Language > JAVA' 카테고리의 다른 글

[java.lang.annotation]  (0) 2020.07.09
[SimpleDateFormat] 날짜 유효성 체크  (0) 2020.06.24
[javadoc] javadoc 만들기  (0) 2020.06.10
[Hex] byteArrayToHexString(byte[] bytes)  (0) 2020.06.02
Java Garbage Collection  (0) 2019.09.11