본 글은 개인 공부 기록용으로 작성된 글이니 참고용으로 보시기 바랍니다.
틀린점이 있다면 댓글을 통해 알려주세요!
1. AES 암호화 개요 및 구조
- 고급 암호화 표준이라는 의미 (Advanced Encryption Standard)
- 대칭키를 쓰는 블록암호
- 높은 안전성과 속도로 인해 인기를 얻어 많이 사용
- 암호화 키의 길이가 128, 192, 256비트인 세 가지 종류가 AES 표준으로 지정
- AES-128, AES-192, AES-256으로 불림.
- 암호화 키의 길이에 따라 실행하는 라운드의 수가 다름, (10, 12, 14 라운드 실행)
- DES와의 차이점은 Feistel 구조가 아닌 SPN 구조
- Feistel 구조와 SPN 구조 차이
- Feistel 구조는 암복호화 과정에서 역함수가 필요 없는 장점이 있고, SPN 구조는 역함수가 필요하도록 설계되어야 한다는 단점이 있음
- Feistel 구조는 구현 시 스왑(Swap) 단계 때문에 연산량이 많이 소요 되며 암호에 사용되는 라운드 함수를 안전하게 설계해야하는 단점이 있고, SPN은 중간에 비트의 이동없이 한번에 암복호화가 가능하기 때문에 Feistel 구조에 비해 효율적으로 설계할 수 있음.
- Feistel 구조와 SPN 구조 차이
2. AES 암호화 과정
- 아래와 같이 진행되며, 마지막 라운드에서는 MixColumn 단계가 없다.
- SubBytes 과정
- 128비트 입력(16진수) -> Sbox의 표 기준으로 값을 치환
- ShiftRows 과정
- 첫 번째 행은 회전되지 않음
- 두 번째 행은 1 bytes
- 세 번째 행은 2 bytes
- 네 번째 행은 3 bytes 만큼씩 왼쪽으로 Cyclic 회전
- MixColumns 과정
- 각 Column에 대해서 행렬 곱셉을 수행..
- 암호화 시 S-Box 사용
3. AES 특징 및 장, 단점
- 특징
- 구현이 쉽고 메모리를 적게 소모
- 대칭형 블록 암호화 알고리즘
- 128, 192, 256의 세 가지 암호키를 가지고 있음
- Rijndael(레인달) 알고리즘이 AES로 채택되어 사용되고 있음
- 장점
- 높은 안전성과 속도
- 보안이 우수함
- 구현이 쉬움
- 이식성이 좋음
- 단점
- 현재까지는 AES는 사실상 위협이 없음
- 하지만 키가 노출되면 무용지물.
4. AES 온라인 실습
- 아래 사이트에서 AES를 간단하게 실습해볼 수 있다.
- https://aesencryption.net/
- 접속 후, 위와 같은 화면에서 차례대로 입력하면 됨.
- ① 암호화할 데이터 값
- ② key값
- ③ 어떤 수순으로 암호화 할 지 선택 (위에서 언급했듯 128, 192, 256 3가지가 있음)
- 하단에 Encrypt 버튼을 누르면 아래와 같은 암호문이 나옴.
- 복호화는 반대로 하면 됨.
- 해당 암호문을 복사해서 ①에 넣어주고, ② 암호화한 key값을 넣어준 후 Decrypt 버튼을 누르면 복호화 가능.
- 단 key값이 틀리면 복호화가 되지 않음.
5. AES JAVA 코드로 실습
package cryptography;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AES_CBC {
private static final String key = "aesEncryptionKey"; // 16byte == 128bit
private static final String initVector = "encryptionIntVec"; // 16Byte
//인코더 생성
private static final Base64.Encoder enc = Base64.getEncoder();
//디코더 생성
private static final Base64.Decoder dec = Base64.getDecoder();
//Encrypt 암호화
public static String encrypt(String value) {
try {
//1.초기화벡터 byte로 변경
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
//2.key를 byte로 변경
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
//3. cipher를 만듬
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); //AES, CBC 모드, partial block 채우기
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); //ENCRYPT_MODE
//4.실제로 암호화 하는 부분
byte[] encrypted = cipher.doFinal(value.getBytes());
return enc.encodeToString(encrypted); //암호문을 base64로 인코딩하여 출력 해줌.
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//Decrypt 복호화
public static String decrypt(String encrypted) {
try {
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); //DECRYPT_MODE
//복호화 진행
byte[] original = cipher.doFinal(dec.decode(encrypted));
return new String(original);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// 테스트 메인 실행 메소드
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while(true) {
System.out.print("암호화(encrypt), 복호화(decrypt), 종료(exit) 입력해주세요 : ");
String mode = br.readLine();
if(mode.equals("encrypt")) {
System.out.print("암호화할 문자를 입력해주세요 : ");
String originalStr = br.readLine();
System.out.println("-------------------------");
System.out.println(">> 암호화 결과 : " + encrypt(originalStr));
System.out.println("-------------------------");
} else if(mode.equals("decrypt")) {
System.out.print("복호화할 문자를 입력해주세요 : ");
String encryptedStr = br.readLine();
System.out.println("-------------------------");
System.out.println(">> 복호화 결과 : " + decrypt(encryptedStr));
System.out.println("-------------------------");
} else if(mode.equals("exit")) {
System.out.println("프로세스 종료...");
break;
} else {
System.out.println("잘못 입력 하셨습니다. 다시 입력해주세요.");
}
}
}
}
- 해당 소스를 실행시켜보면 아래와 같이 테스트 할 수 있다.
Reference
https://www.javacodegeeks.com/2018/03/aes-encryption-and-decryption-in-javacbc-mode.html