[JAVA] AES128 암호화 예제

[JAVA] AES128 암호화 예제

[javascript] AES128 암호화 예제 바로가기 => https://blog.naver.com/bb_/221332298450

[JAVA/JS] AES128 암호화 예제 github 소스 바로 가기 => https://github.com/thkmon/AES128Test

AES128은 양방향 암호화를 지원한다. 즉, 키값을 안다면, 암호화한 스트링을 다시 복호화할 수 있다. 키값을 모를 경우, 복호화가 거의 불가능한만큼 안전하다고 알려져 있다.

1. 라이브러리 임포트

commons-codec-1.10.jar 임포트가 필요하다. 첨부파일로 첨부해두었다.

스프링에 적용하고 싶다면 pom.xml 에 아래와 같이 추가하면 된다.

<!– https://mvnrepository.com/artifact/commons-codec/commons-codec –>
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.10</version>
</dependency>

1-1. 임포트시 주의사항

노파심에 적어두지만, Base64 는 java.util.Base64 가 아니라 org.apache.commons.codec.binary.Base64 를 임포트해야 한다.

2. 소스코드

2-1. [AesUtil.java]

package com.bb;

import java.security.SecureRandom;
import java.security.spec.KeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

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

public class AesUtil {

    private static final int keySize = 128;
    private static final int iterationCount = 10000;
    private static String salt = “79752f1d3fd2432043c48e45b35b24645eb826a25c6f1804e9152665c345a552”;
    private static String iv = “2fad5a477d13ecda7f718fbd8a9f0443”;
    private static final String passPhrase = “passPhrase”;
    
    private final Cipher cipher;
    
    
    public AesUtil() {
        try {
            cipher = Cipher.getInstance(“AES/CBC/PKCS5Padding”);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    
    public String encrypt(String plaintext) throws Exception {
        return encrypt(salt, iv, passPhrase, plaintext);
    }
    
    
    public String decrypt(String ciphertext) throws Exception {
        return decrypt(salt, iv, passPhrase, ciphertext);
    }
    
    
    private String encrypt(String salt, String iv, String passPhrase, String plaintext) throws Exception {
        SecretKey key = generateKey(salt, passPhrase);
        byte[] encrypted = doFinal(Cipher.ENCRYPT_MODE, key, iv, plaintext.getBytes(“UTF-8”));
        return encodeBase64(encrypted);
    }

    
    private String decrypt(String salt, String iv, String passPhrase, String ciphertext) throws Exception {
        SecretKey key = generateKey(salt, passPhrase);
        byte[] decrypted = doFinal(Cipher.DECRYPT_MODE, key, iv, decodeBase64(ciphertext));
        return new String(decrypted, “UTF-8”);
    }

    
    private byte[] doFinal(int encryptMode, SecretKey key, String iv, byte[] bytes) throws Exception {
        cipher.init(encryptMode, key, new IvParameterSpec(decodeHex(iv)));
        return cipher.doFinal(bytes);
    }

    
    private SecretKey generateKey(String salt, String passPhrase) throws Exception {
        SecretKeyFactory factory = SecretKeyFactory.getInstance(“PBKDF2WithHmacSHA1”);
        KeySpec spec = new PBEKeySpec(passPhrase.toCharArray(), decodeHex(salt), iterationCount, keySize);
        SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), “AES”);
        return key;
    }
    
    
    private static String encodeBase64(byte[] bytes) {
        return Base64.encodeBase64String(bytes);
    }

    
    private static byte[] decodeBase64(String str) {
        return Base64.decodeBase64(str);
    }

    
    private static String encodeHex(byte[] bytes) {
        return Hex.encodeHexString(bytes);
    }

    
    private static byte[] decodeHex(String str) throws Exception {
        return Hex.decodeHex(str.toCharArray());
    }
    
    
    private static String getRandomHexString(int length) {
        byte[] salt = new byte[length];
        new SecureRandom().nextBytes(salt);
        return encodeHex(salt);

    }
}

– keySize : AES128 의 128을 의미한다.

– iterationCount : 암호화 관련키(PEBKey)을 생성하는 횟수를 의미한다. 10000 번은 기본값에 해당되고 횟수가 높을수록 암호화 강도가 강하다고 한다.

– salt : 해시값의 무작위성을 높이기 위한 보조키에 해당한다. 실제로 해시값에 소금을 친다(Adding Salt)는 표현을 쓴다.

– iv : AES암호화를 위한 메인키라고 볼 수 있다.

현재 salt값과 iv값은 정적변수(static)로 되어 있지만 실제 사용시에는 그때그때 생성해서 사용해도 된다.

salt는 32자리의 헥스값, iv는 16자리의 헥스값을 만들면 된다.

아래처럼 랜덤 헥스값을 만드는 메서드 getRandomHexString 를 사용하면 된다.

salt = getRandomHexString(32);
iv = getRandomHexString(16);

2-2. [AES128Test.java]

package com.bb;

public class AES128Test {

    public static void main(String[] args) {
        try {
            AesUtil aesUtil = new AesUtil();
            
            String encString = aesUtil.encrypt(“pass1234”);
            System.out.println(“encString : “ + encString);
            
            String decString = aesUtil.decrypt(encString);
            System.out.println(“decString : “ + decString);
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3. 실행결과

[javascript] AES128 암호화 예제 바로가기 => https://blog.naver.com/bb_/221332298450

[JAVA/JS] AES128 암호화 예제 github 소스 바로 가기 => https://github.com/thkmon/AES128Test