Files
java-examples/docs/security/cipher.md
2025-03-12 10:43:35 +09:00

240 lines
14 KiB
Markdown

자바에서 AES와 RSA 암호화 알고리즘을 사용할 때 지원되는 운용 모드, 패딩, 키 길이, 그리고 필요한 매개변수를 표로 정리하겠습니다. JCA/JCE에서 제공하는 기본 설정을 기준으로 하며, JDK 버전(예: JDK 8, 11, 17 등) 및 사용 중인 제공자(Provider, 예: SunJCE, Bouncy Castle)에 따라 일부 차이가 있을 수 있습니다.
---
### **AES (Advanced Encryption Standard)**
| **항목** | **설명** |
|--------------------|--------------------------------------------------------------------------------------------|
| **운용 모드** | - **ECB (Electronic Codebook)**: 블록 단위로 독립적 암호화 (보안성 낮음, 권장되지 않음).<br> - **CBC (Cipher Block Chaining)**: 이전 블록과 XOR 연산, IV 필요.<br> - **CTR (Counter)**: 스트림 암호처럼 동작, IV 또는 논스 필요.<br> - **GCM (Galois/Counter Mode)**: 인증 암호화, IV 및 추가 인증 데이터(AAD) 지원.<br> - **CFB (Cipher Feedback)**: 스트림 암호화, IV 필요.<br> - **OFB (Output Feedback)**: 스트림 암호화, IV 필요. |
| **패딩** | - **PKCS5Padding** (또는 PKCS7Padding): 블록 크기에 맞게 패딩 추가 (기본값).<br> - **NoPadding**: 패딩 없음, 데이터 길이가 블록 크기의 배수여야 함.<br> - **ISO10126Padding**: 랜덤 패딩 (일부 제공자에서 지원). |
| **키 길이** | - 128비트 (기본값).<br> - 192비트.<br> - 256비트 (JCE Unlimited Strength Policy 필요 시 설치). |
| **필요한 매개변수** | - **IV (Initialization Vector)**: CBC, CTR, GCM, CFB, OFB 모드에서 필요 (일반적으로 16바이트).<br> - **Nonce**: CTR, GCM에서 사용 가능.<br> - **AAD (Additional Authenticated Data)**: GCM 모드에서 인증용 추가 데이터 (선택적).<br> - **Tag 길이**: GCM 모드에서 인증 태그 길이 (기본 128비트, 96, 104, 112, 120 등 조정 가능). |
| **Cipher 형식** | `"AES/[운용모드]/[패딩]"` 예: `"AES/CBC/PKCS5Padding"`, `"AES/GCM/NoPadding"`. |
#### **참고**
- AES는 블록 크기가 128비트(16바이트)로 고정되어 있습니다.
- ECB는 보안 취약성이 있어 권장되지 않으며, GCM은 인증과 암호화를 동시에 제공해 현대 애플리케이션에서 선호됩니다.
- 예제: `Cipher.getInstance("AES/GCM/NoPadding")`.
---
### **RSA (Rivest-Shamir-Adleman)**
| **항목** | **설명** |
|--------------------|--------------------------------------------------------------------------------------------|
| **운용 모드** | - RSA 자체는 블록 암호화로 동작하며, 별도의 운용 모드 없음.<br> - 단일 블록 암호화/복호화 또는 서명/검증 용도로 사용.<br> - 하이브리드 암호화 시 AES와 결합 가능 (RSA로 AES 키 암호화). |
| **패딩** | - **NoPadding**: 패딩 없음 (데이터 길이가 키 크기보다 작아야 함, 권장되지 않음).<br> - **PKCS1Padding**: PKCS#1 v1.5 패딩 (암호화/서명에 사용, 기본값).<br> - **OAEPWith<해시>AndMGF1Padding**: OAEP 패딩 (예: `"OAEPWithSHA-256AndMGF1Padding"`), 더 안전.<br> - **OAEPPadding**: 기본 OAEP (구형, 권장되지 않음). |
| **키 길이** | - 512비트 (취약, 사용 금지).<br> - 1024비트 (현재 취약, 권장되지 않음).<br> - 2048비트 (표준).<br> - 4096비트 (높은 보안 요구 시). |
| **필요한 매개변수** | - **PublicKey/PrivateKey**: 공개키/개인키 쌍.<br> - **OAEP 매개변수**: OAEP 사용 시 `OAEPParameterSpec`로 해시 알고리즘(SHA-256 등)과 MGF1(Mask Generation Function) 지정.<br> - **서명 시 해시**: 예: `"SHA256withRSA"` (RSA와 결합된 해시 알고리즘). |
| **Cipher 형식** | `"RSA/[운용모드]/[패딩]"` 예: `"RSA/None/PKCS1Padding"`, `"RSA/None/OAEPWithSHA-256AndMGF1Padding"`. |
#### **참고**
- RSA는 비대칭 알고리즘이므로 대량 데이터 암호화에는 적합하지 않습니다. 주로 키 교환이나 디지털 서명에 사용됩니다.
- OAEP 패딩은 PKCS#1 v1.5보다 안전하며, SHA-256 이상의 해시와 함께 사용하는 것이 권장됩니다.
- 최대 암호화 가능한 데이터 크기는 키 길이와 패딩에 따라 달라집니다 (예: 2048비트 키 + PKCS1Padding = 최대 245바이트).
---
### **AES와 RSA 비교 요약**
| **특징** | **AES** | **RSA** |
|--------------------|----------------------------------|----------------------------------|
| **유형** | 대칭키 암호화 | 비대칭키 암호화 |
| **주요 용도** | 데이터 암호화 | 키 교환, 디지털 서명 |
| **속도** | 빠름 | 느림 |
| **키 길이** | 128, 192, 256비트 | 1024, 2048, 4096비트 |
| **운용 모드** | ECB, CBC, GCM 등 다양 | 없음 (단일 블록 암호화) |
| **패딩** | PKCS5Padding, NoPadding 등 | PKCS1Padding, OAEP 등 |
---
### **예제 코드**
#### **AES 암호화**
```java
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
public class AesExample {
public static void main(String[] args) throws Exception {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256);
SecretKey key = keyGen.generateKey();
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = new byte[16]; // IV는 랜덤으로 생성해야 함
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] encrypted = cipher.doFinal("Hello, AES!".getBytes());
System.out.println(new String(encrypted));
}
}
```
#### **RSA 암호화**
```java
import javax.crypto.Cipher;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
public class RsaExample {
public static void main(String[] args) throws Exception {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(2048);
KeyPair keyPair = keyGen.generateKeyPair();
Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
byte[] encrypted = cipher.doFinal("Hello, RSA!".getBytes());
System.out.println(new String(encrypted));
}
}
```
---
추가로 궁금한 점이나 특정 항목에 대한 자세한 설명이 필요하면 말씀해주세요!
---
AES-GCM (Galois/Counter Mode)은 AES 암호화 알고리즘의 운용 모드 중 하나로, 대칭키 암호화와 인증을 동시에 제공하는 **인증 암호화 (Authenticated Encryption, AE)** 방식입니다. 이 모드는 현대 보안 애플리케이션에서 널리 사용되며, 특히 TLS/SSL, IPsec, 디스크 암호화 등에서 표준으로 채택되고 있습니다. 아래에서 AES-GCM의 상세한 특징, 동작 방식, 매개변수, 장단점 등을 정리하겠습니다.
---
### **AES-GCM의 주요 특징**
1. **대칭키 암호화**:
- AES 블록 암호를 기반으로 하며, 블록 크기는 128비트(16바이트)로 고정됩니다.
- 키 길이는 128비트, 192비트, 256비트 중 선택 가능.
2. **인증 제공**:
- 암호화된 데이터의 무결성과 출처 인증을 보장하기 위해 **인증 태그 (Authentication Tag)**를 생성합니다.
- 별도의 MAC(Message Authentication Code) 계산이 필요 없음.
3. **스트림 암호처럼 동작**:
- CTR(Counter) 모드를 기반으로 하여, 입력 데이터 길이에 관계없이 암호화 가능 (블록 크기의 배수일 필요 없음).
4. **Galois 필드 연산**:
- 인증 태그 생성에 GF(2^128) (Galois Field) 연산을 사용하며, 이를 통해 효율적이고 안전한 인증을 구현.
---
### **AES-GCM의 동작 방식**
1. **입력**:
- 평문 (Plaintext): 암호화할 데이터.
- 키 (Key): AES 키 (128, 192, 256비트).
- IV (Initialization Vector) 또는 Nonce: 초기화 벡터 (일반적으로 12바이트 권장).
- AAD (Additional Authenticated Data): 인증만 필요한 추가 데이터 (선택적, 암호화되지 않음).
2. **과정**:
- **CTR 모드 암호화**: IV와 카운터를 결합하여 AES로 키스트림(Key Stream)을 생성하고, 평문과 XOR 연산을 통해 암호문을 생성.
- **인증 태그 생성**: 암호문, AAD, IV 등을 Galois 필드 연산(GMAC)을 통해 인증 태그로 변환.
- 출력: 암호문(Ciphertext) + 인증 태그(Tag).
3. **출력**:
- 암호문과 인증 태그를 함께 반환하며, 복호화 시 태그를 검증하여 데이터 무결성을 확인.
---
### **주요 매개변수**
| **매개변수** | **설명** | **권장값/주의사항** |
|----------------------|--------------------------------------------------------------------------------------------|---------------------------------------------|
| **키 길이** | AES 암호화에 사용되는 키 크기. | 128, 192, 256비트 (256비트 권장). |
| **IV (Nonce)** | 초기화 벡터로, 암호화마다 고유해야 함. | 12바이트(96비트) 권장, 재사용 절대 금지. |
| **AAD** | 인증에만 사용되는 추가 데이터 (암호화되지 않음). | 선택적, 예: 프로토콜 헤더 등. |
| **태그 길이** | 인증 태그의 길이로, 무결성 검증에 사용. | 128비트(기본), 96, 104, 112, 120비트 가능. |
| **Cipher 형식** | 자바에서 GCM 모드를 지정하는 형식. | `"AES/GCM/NoPadding"` (패딩 불필요). |
#### **IV/Nonce에 대한 중요 참고**
- GCM은 IV(Nonce) 재사용 시 보안이 심각하게 손상됩니다. 동일한 키와 IV 조합을 두 번 사용하면 인증 태그가 의미를 잃고, 암호문이 노출될 수 있습니다.
- 12바이트(96비트) Nonce가 표준으로 권장되며, 더 긴 IV를 사용할 경우 내부적으로 해시 처리됩니다.
---
### **자바에서 AES-GCM 사용 예제**
```java
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
public class AesGcmExample {
public static void main(String[] args) throws Exception {
// 1. AES 키 생성
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256); // 256비트 키
SecretKey key = keyGen.generateKey();
// 2. IV (Nonce) 생성
byte[] iv = new byte[12]; // 12바이트 Nonce
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
// 3. 암호화 설정
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec spec = new GCMParameterSpec(128, iv); // 128비트 태그 길이
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
// 4. AAD 추가 (선택적)
byte[] aad = "AuthData".getBytes(StandardCharsets.UTF_8);
cipher.updateAAD(aad);
// 5. 암호화
byte[] plaintext = "Hello, AES-GCM!".getBytes(StandardCharsets.UTF_8);
byte[] ciphertext = cipher.doFinal(plaintext);
// 결과 출력
System.out.println("IV: " + bytesToHex(iv));
System.out.println("Ciphertext (with tag): " + bytesToHex(ciphertext));
// 6. 복호화
cipher.init(Cipher.DECRYPT_MODE, key, spec);
cipher.updateAAD(aad); // AAD 동일해야 함
byte[] decrypted = cipher.doFinal(ciphertext);
System.out.println("Decrypted: " + new String(decrypted, StandardCharsets.UTF_8));
}
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}
```
---
### **장점**
1. **효율성**: 암호화와 인증을 단일 패스로 처리하여 속도가 빠름.
2. **보안성**: 인증 태그로 무결성과 출처 인증을 보장.
3. **유연성**: AAD를 통해 추가 데이터를 인증 가능.
### **단점 및 주의사항**
1. **Nonce 재사용 금지**: 동일한 키와 Nonce를 재사용하면 보안이 완전히 무너질 수 있음 (키스트림 재사용 문제).
2. **태그 길이 조정 시 주의**: 짧은 태그(예: 64비트)는 충돌 위험이 증가할 수 있음.
3. **복잡성**: IV 관리와 AAD 처리가 추가적으로 필요.
---
### **응용 사례**
- **TLS 1.2/1.3**: AES-GCM은 TLS에서 널리 사용되는 cipher suite입니다 (예: `TLS_AES_256_GCM_SHA384`).
- **디스크 암호화**: 인증과 함께 데이터 보호.
- **메시징 시스템**: 메시지 무결성과 기밀성 보장.
---
AES-GCM은 현대 암호화에서 매우 강력하고 효율적인 선택이지만, IV 관리와 키 회전에 신경 써야 합니다. 추가로 궁금한 점이나 특정 부분에 대한 더 깊은 설명이 필요하면 말씀해주세요!