AES256 암호화 테스트 - AES256 amhohwa teseuteu

박서희연구소

[문제]

자바 프로그래밍 중 보안 강화를 위해 암호화 알고리즘이 필요해 알아보던 중, AES256 의 존재를 알게되었다.

[목표]

AES256 의 개념을 학습하고, 적용해본다.

[해결]

환경 : Java 1.8

AES(Adavanced Encryption Standard AES)란?

한국어로 번역하면 고급 암호화 표준이며, 대칭키 를 쓰는 블럭 암호이다. 높은 안전성과 속도로 인해 인기를 얻어 전 세계적으로 사용되고 있다.

현재 AES  Rijndael(레인달) 알고리즘 을 가지고 만들었으며, 엄밀하게는 레인달 알고리즘 의 여러 가능성 중, 암호화 블럭

크기가 128 bit 이며 암호화 키의 길이가 128, 192, 256 bit인 세 가지 종류가 AES 표준 으로 지정되었다. 각각 AES-128, AES-192, AES-256으로 불린다.

AES 특징

대칭형, 블럭 암호화 알고리즘 이다. 대칭형 암호화 알고리즘 중 가장 유명하고, 128, 192, 256 bit 중 하나가 된다.

암호화 키의 길이에 따라 실행하는 라운드 수가 다른데, 각각 10, 12, 14 라운드를 실행한다.

AES 안전성

미국 정부가 채택하여 기밀문서를 암호화했을 정도로 신뢰가 가는 알고리즘이라고 생각하면 된다. 키 없이 해독하는 것이 거의 불가능하다고 믿어지며, 최신 cipher 와 마찬가지로, known-plaintext 해킹 기술로도 해독이 불 가능하다고 한다.

컴퓨팅 기술의 급속한 발전에 따라 현재 권장되는 암호화 수준은 192bit 이상이며 대다수의 금융기관들은 256bit 이상의 암호화 체계로 전환했다.

대칭키(비밀키) 방식의 AES256 암호화 장단점

예전 AES128(128bit 블록암호화) 를 사용하던 암호화가 보안에 취약하여, 개선된 버전이 AES256(256bit 블록암호화)다.

주로 평문 데이터를 암호화하는데 많이 쓰이며,비밀 키 하나로 데이터를 암호화 하고 복호화를 하며 사용하게 된다.

장점으로는 AES128 과 비교하였을때는 당연히 보안성과 안전성이 높다고 말할수 있으며, 더 멀리 나아가 비대칭키(공개키 암호화시스템) 보다 속도가 빠르다는 이점을 가지고 있다.

단점으로는 키 한개로 암호화와 복호화를 하기 때문에 유출이 된다면, 암호화는 의미가 없어진다.

패딩(padding) 이란?

아래 코드에도 나오겠지만, 위에서 블록 암호화 를 진행하기 위해서는 패딩 기법 이 필요하다. 데이터를 특정 크기로 맞추기 위해서, 특정 크기보다 부족한 부분의 공간을 의미없는 문자들로 채워서 비트수를 맞추는 것이다. 암호화 시에는 반드시 필요한 방법이다.

다음과 같이 쓰일수 있다.

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

AES256 암호화 및 복호화 코드

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidAlgorithmParameterException;

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

public class AES256Cipher {
    private static volatile AES256Cipher INSTANCE;

    final static String secretKey = "shplab123456789abcdefghijklmnopq"; // 32bit
    static String IV = ""; // 16bit

    public static AES256Cipher getInstance() {
        if (INSTANCE == null) {
            synchronized (AES256Cipher.class) {
                if (INSTANCE == null)
                    INSTANCE = new AES256Cipher();
            }
        }
        return INSTANCE;
    }

    private AES256Cipher() {
        IV = secretKey.substring(0, 16);
    }

    // 암호화
    public static String AES_Encode(String str)
            throws java.io.UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
        byte[] keyData = secretKey.getBytes();

        SecretKey secureKey = new SecretKeySpec(keyData, "AES");

        Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
        c.init(Cipher.ENCRYPT_MODE, secureKey, new IvParameterSpec(IV.getBytes()));

        byte[] encrypted = c.doFinal(str.getBytes("UTF-8"));
        String enStr = new String(Base64.encodeBase64(encrypted));

        return enStr;
    }

    // 복호화
    public static String AES_Decode(String str)
            throws java.io.UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
        byte[] keyData = secretKey.getBytes();
        SecretKey secureKey = new SecretKeySpec(keyData, "AES");
        Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
        c.init(Cipher.DECRYPT_MODE, secureKey, new IvParameterSpec(IV.getBytes("UTF-8")));

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

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

AES256 암호화 및 복호화 테스트 코드

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import org.junit.Test;

public class AES256CipherTest {
    String id = "shplab";
    String memberNo = "123";
    String memberName = "박서희연구실";

    @Test
    public void encDesTest() throws InvalidKeyException, UnsupportedEncodingException, NoSuchAlgorithmException,
            NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
        AES256Cipher a256 = AES256Cipher.getInstance();

        String enId = a256.AES_Encode(id);
        String enMemberNo = a256.AES_Encode(memberNo);
        String enMemberName = a256.AES_Encode(memberName);

        String desId = a256.AES_Decode(enId);
        String desMemberNo = a256.AES_Decode(enMemberNo);
        String desMemberName = a256.AES_Decode(enMemberName);

        assertThat(id, is(desId));
        assertThat(memberNo, is(desMemberNo));
        assertThat(memberName, is(desMemberName));
    }
}

java.security.InvalidKeyException: Illegal key size 에러

자주 나는 에러중 한개가 인데, 키 값 의 길이가 부족할때 발생하는 에러다.

UnsupportedEncodingException  에러

Java 의 기본 정책으로는 AES128 암호화 방식까지만 사용이 가능하므로 AES256 방식으로 암호화를 하게 되면 아래와 같은 Exceptioin이 발생한다. 미국에서는 자국에서만 허용하기로 하였기 때문에, 우리는 라이브러리 를 따로 추가 해야 한다.

총 3개의 라이브러리 가 필요하다.

local_policy.jar

0.00MB

US_export_policy.jar

0.00MB

commons-codec-1.10.jar

0.27MB

- 끝 -

출처 및 참고 :

jmlim.github.io/java/2018/12/06/java-aes256/

Java AES256 Sample 코드. · 기억하기 위한 개발노트

대칭형, 블럭 암호화 알고리즘이다. 대칭형 암호화 알고리즘 중 가장 유명하다. 암호화 키는 128, 192, 256의 세 가지 중 하나가 될 수 있으며, 각각 AES-128, AES-192, AES-256으로 불린다.

jmlim.github.io

https://choidev-1.tistory.com/67

(안드로이드) 고급 암호화 표준 (AES256)

고급 암호화 표준(Advanced Encryption Standard AES) AES란? 한국어로 번역하면 고급 암호화 표준 이며 대칭키를 쓰는 블럭 암호이다. 높은 안전성과 속도로 인해 인기를 얻어 전 세계적으로 사용되고 있다. 현재..

choidev-1.tistory.com

AES256 암호화 테스트 - AES256 amhohwa teseuteu