***

title: AES(고급 암호화 표준)
description: AES(고급 암호화 표준)는 2001년에 미국 국립표준기술연구소(NIST)에서 설립한 대칭 키 암호화 알고리즘입니다.
keyword: AES, 암호화
-----------------

AES(Advanced Encryption Standard, 고급 암호화 표준)는 **2001년에 미국 국립표준기술연구소(NIST)에서 채택한 대칭 키 암호화 알고리즘**입니다. DES(Data Encryption Standard)를 대체하기 위해 만든 표준이며, Rijndael 알고리즘을 기반으로 설계되었어요. AES는 현재 전 세계적으로 많은 보안 시스템의 암호화 표준으로 자리 잡고 있습니다.

대칭 키 알고리즘이란, 암호화와 복호화 과정에서 동일한 키를 사용한다는 뜻입니다. AES는 128비트, 192비트, 256비트 길이의 키를 지원해요. 키 길이가 길수록 보안성이 높다는 특징도 있습니다. 암호화 알고리즘에서 블록 크기는 한 번에 처리되는 데이터의 크기를 가리키는데요. AES의 블록 크기는 128비트로 고정되어 있어요.

AES는 현재까지 알려진 취약점이 없기 때문에 다양한 공격에도 안전하게 사용할 수 있어요. ECB(전자 코드북), CBC(암호 블록 연결), GCM(갤로이스/카운터 모드)와 같이 다양한 암호화 모드에서 사용할 수 있다는 장점이 있습니다. 실제로 금융, 군사, 의료 등 많은 분야에서 널리 사용되고 있고요.

## AES 암호화 과정

![State](https://static.tosspayments.com/docs/glossary/aes-main.png#2894x1098)

AES 암호화 과정을 간략히 알아볼게요. 먼저 입력 데이터를 아래와 16바이트(128비트)의 4x4 행렬 블록으로 변환합니다. 이 블록을 State라고 합니다.

평문으로 구성된 State에 여러 차례의 Round Function 연산을 적용해서 암호화합니다. 적용되는 Round Function의 회차는 키의 길이에 따라 달라요. 128비트 키는 10 라운드, 192비트 키는 12 라운드, 256비트 키는 14 라운드의 연산을 수행합니다. 키가 길수록 더 많은 Round Function이 적용되기 때문에 보안성이 높아집니다.

Round Function에는 `SubBytes`, `ShiftRows`, `MixColumns`, `AddRoundKey` 함수 종류가 있어요. 각 함수는 대칭 키에서 비롯된 Round Key라는 키를 사용합니다. AES는 다양한 키와 함수를 사용해서 입력값과 출력값의 연관 관계를 줄입니다.

## AES 사용방법

프로젝트에서 AES를 사용할 때는 암호화 라이브러리를 활용해보세요. 아래 Java, Python 코드는 AES를 간단하게 적용할 수 있는 함수입니다. 프로젝트에 도입하기 전에는 키 종류, 암호화 환경 등을 고려해야 됩니다.

### Java

암호화
복호화

```java theme="grey"
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public static String encrypt(String plainText, String key) throws Exception {
    // 문자열 키를 SecretKey로 변환
    SecretKey secretKey = new SecretKeySpec(key.getBytes(), "AES");

    // Cipher 생성 및 초기화
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, secretKey);

    // 데이터 암호화 및 base64 인코딩
    byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
    return Base64.getEncoder().encodeToString(encryptedBytes);
}
```

```java theme="grey"
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public static String decrypt(String cipherText, String key) throws Exception {
    // 문자열 키를 SecretKey로 변환
    SecretKey secretKey = new SecretKeySpec(key.getBytes(), "AES");

    // Cipher 생성 및 초기화
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.DECRYPT_MODE, secretKey);

    // 데이터 Base64 디코딩 및 복호화
    byte[] decodedBytes = Base64.getDecoder().decode(cipherText);
    byte[] decryptedBytes = cipher.doFinal(decodedBytes);
    return new String(decryptedBytes);
}
```

### Python

암호화
복호화

```python theme="grey"
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.backends import default_backend
import base64

def encrypt_aes(plain_text, key):
    # Create a cipher object with AES and ECB mode
    cipher = Cipher(algorithms.AES(key.encode()), modes.ECB(), backend=default_backend())
    encryptor = cipher.encryptor()

    # Pad the plain text to make it a multiple of the block size (16 bytes)
    padder = padding.PKCS7(algorithms.AES.block_size).padder()
    padded_data = padder.update(plain_text.encode()) + padder.finalize()

    # Encrypt the padded data
    encrypted_data = encryptor.update(padded_data) + encryptor.finalize()

    # Encode the encrypted data in Base64 for safe transmission/storage
    return base64.b64encode(encrypted_data).decode()

```

```python theme="grey"
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.backends import default_backend
import base64

def decrypt_aes(cipher_text, key):
    # Decode the Base64-encoded ciphertext
    encrypted_data = base64.b64decode(cipher_text)

    # Create a cipher object with AES and ECB mode
    cipher = Cipher(algorithms.AES(key.encode()), modes.ECB(), backend=default_backend())
    decryptor = cipher.decryptor()

    # Decrypt the data
    padded_data = decryptor.update(encrypted_data) + decryptor.finalize()

    # Remove padding from the decrypted data
    unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
    plain_text = unpadder.update(padded_data) + unpadder.finalize()

    return plain_text.decode()

```
