15 KiB
자바의 Java Security API(JCA 및 JCE 포함)는 암호화, 인증, 키 관리 등 보안 기능을 제공하는 다양한 클래스를 포함하고 있습니다. 여기서는 자바 시큐리티에서 자주 사용되는 주요 클래스와 그 역할에 대해 설명하고, 각 클래스의 주요 메서드를 표로 정리하겠습니다.
주요 클래스와 역할
-
java.security.MessageDigest- 역할: 해시 함수(MD5, SHA-1, SHA-256 등)를 사용하여 데이터의 메시지 다이제스트(해시 값)를 생성. 데이터 무결성 확인에 사용.
- 특징: 단방향 함수로, 입력 데이터를 고정된 길이의 해시로 변환.
-
javax.crypto.Cipher- 역할: 대칭키(AES) 및 비대칭키(RSA) 암호화/복호화 작업을 수행.
- 특징: 운용 모드(예: CBC, GCM)와 패딩(예: PKCS5Padding)을 지정 가능.
-
java.security.KeyPairGenerator- 역할: 비대칭키 알고리즘(RSA, DSA, EC 등)의 공개키와 개인키 쌍을 생성.
- 특징: 키 크기(예: 2048비트)를 지정하여 생성.
-
javax.crypto.KeyGenerator- 역할: 대칭키 알고리즘(AES, DES 등)의 키를 생성.
- 특징: 고정된 길이의 무작위 키 생성.
-
javax.crypto.SecretKeyFactory- 역할: 패스워드 기반 키 생성(PBKDF2) 또는 키 변환 작업을 수행.
- 특징:
SecretKey객체를 생성하거나 키 사양(KeySpec)을 변환.
-
java.security.SecureRandom- 역할: 암호화에 적합한 고품질의 난수 생성.
- 특징: 일반
Random보다 안전성이 높음.
-
java.security.KeyStore- 역할: 키와 인증서를 저장하고 관리하는 저장소.
- 특징: JKS, PKCS12 등 다양한 형식 지원.
각 클래스의 주요 메서드
1. MessageDigest
| 메서드 | 설명 |
|---|---|
static getInstance(String algorithm) |
지정된 해시 알고리즘(MD5, SHA-256 등)의 인스턴스를 생성. |
update(byte[] input) |
해시 계산에 사용할 입력 데이터를 추가. |
digest() |
입력 데이터를 해시로 변환하여 바이트 배열로 반환. |
reset() |
인스턴스를 초기 상태로 재설정. |
2. Cipher
| 메서드 | 설명 |
|---|---|
static getInstance(String transformation) |
암호화 알고리즘, 모드, 패딩(예: "AES/GCM/NoPadding")을 지정하여 인스턴스 생성. |
init(int opmode, Key key, AlgorithmParameterSpec params) |
암호화(ENCRYPT_MODE) 또는 복호화(DECRYPT_MODE) 모드로 초기화. 매개변수(IV 등) 지정 가능. |
update(byte[] input) |
암호화/복호화할 데이터를 추가(스트리밍 처리 시 사용). |
doFinal(byte[] input) |
암호화/복호화를 완료하고 결과를 반환. |
updateAAD(byte[] aad) |
GCM 모드 등에서 인증용 추가 데이터(AAD)를 추가. |
3. KeyPairGenerator
| 메서드 | 설명 |
|---|---|
static getInstance(String algorithm) |
키 쌍 생성기 인스턴스를 반환(예: "RSA", "EC"). |
initialize(int keysize) |
키 크기(예: 2048비트)를 지정하여 초기화. |
generateKeyPair() |
공개키와 개인키 쌍(KeyPair)을 생성하여 반환. |
4. KeyGenerator
| 메서드 | 설명 |
|---|---|
static getInstance(String algorithm) |
대칭키 생성기 인스턴스를 반환(예: "AES"). |
init(int keysize) |
키 길이(예: 256비트)를 지정하여 초기화. |
generateKey() |
지정된 길이의 대칭키(SecretKey)를 생성하여 반환. |
5. SecretKeyFactory
| 메서드 | 설명 |
|---|---|
static getInstance(String algorithm) |
키 팩토리 인스턴스를 반환(예: "PBKDF2WithHmacSHA256"). |
generateSecret(KeySpec spec) |
키 사양(예: PBEKeySpec)을 기반으로 SecretKey를 생성. |
getKeySpec(SecretKey key, Class keySpec) |
주어진 키를 특정 사양(예: PBEKeySpec)으로 변환. |
6. SecureRandom
| 메서드 | 설명 |
|---|---|
SecureRandom() |
기본 알고리즘으로 안전한 난수 생성기 인스턴스를 생성. |
nextBytes(byte[] bytes) |
지정된 바이트 배열을 무작위 값으로 채움(예: IV, 솔트 생성에 사용). |
setSeed(byte[] seed) |
난수 생성기의 시드 값을 설정(보안상 권장되지 않음). |
7. KeyStore
| 메서드 | 설명 |
|---|---|
static getInstance(String type) |
키 저장소 인스턴스를 반환(예: "JKS", "PKCS12"). |
load(InputStream stream, char[] password) |
지정된 스트림에서 키 저장소를 로드하며, 비밀번호로 보호. |
getKey(String alias, char[] password) |
지정된 별칭에 해당하는 키를 반환. |
setKeyEntry(String alias, Key key, char[] password, Certificate[] chain) |
키와 인증서를 저장소에 추가. |
store(OutputStream stream, char[] password) |
키 저장소를 지정된 스트림에 저장. |
클래스 간 연계 예제
아래는 MessageDigest, Cipher, KeyGenerator, SecureRandom을 함께 사용하는 AES-GCM 암호화 예제입니다.
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Base64;
public class SecurityExample {
public static void main(String[] args) throws Exception {
// 1. 키 생성 (KeyGenerator)
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256);
SecretKey key = keyGen.generateKey();
// 2. IV 생성 (SecureRandom)
SecureRandom random = new SecureRandom();
byte[] iv = new byte[12];
random.nextBytes(iv);
// 3. 암호화 (Cipher)
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec spec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
byte[] plaintext = "Hello, Java Security!".getBytes();
byte[] ciphertext = cipher.doFinal(plaintext);
// 4. 해시 생성 (MessageDigest)
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(plaintext);
// 출력
System.out.println("Ciphertext: " + Base64.getEncoder().encodeToString(ciphertext));
System.out.println("Hash: " + Base64.getEncoder().encodeToString(hash));
}
}
추가 참고
- 제공자(Provider):
Security.getProviders()로 사용 가능한 제공자를 확인할 수 있으며, 기본 제공자는 SunJCE입니다. Bouncy Castle 같은 외부 제공자를 추가할 수도 있습니다. - 확장성: JCA는 플러그인 구조로 설계되어 새로운 알고리즘을 쉽게 추가 가능.
각 클래스에 대해 더 깊은 설명이나 특정 메서드의 사용 예제가 필요하면 말씀해주세요!
사용자가 "Bouncy Castle"에 대해 물었을 때, 문맥상 자바 보안과 암호화에 관련된 질문을 이어오셨으므로, 여기서는 Bouncy Castle 암호화 라이브러리(The Bouncy Castle Cryptography Library)에 대해 설명하겠습니다. 만약 실제 "바운시 캐슬"(어린이 놀이기구)을 의미한 것이라면, 말씀해 주시면 그에 맞춰 수정하겠습니다!
Bouncy Castle 암호화 라이브러리란?
Bouncy Castle은 자바(Java)와 C#(.NET)용으로 개발된 오픈소스 암호화 라이브러리로, 다양한 암호화 알고리즘과 보안 프로토콜을 구현할 수 있는 강력한 도구입니다. 이 라이브러리는 **Legion of the Bouncy Castle Inc.**라는 호주 기반의 등록된 자선 단체에서 개발 및 유지보수하며, 2000년 5월에 처음 출시되었습니다.
Bouncy Castle은 자바의 기본 JCE(Java Cryptography Extension)와 JCA(Java Cryptography Architecture)를 보완하거나 대체할 수 있으며, 경량 API와 JCE 제공자(Provider)라는 두 가지 주요 구성 요소로 설계되었습니다. 이를 통해 메모리 제약이 있는 환경(예: Java ME)부터 일반 JVM 환경까지 폭넓게 사용할 수 있습니다.
주요 특징
-
광범위한 알고리즘 지원:
- 대칭키 암호화: AES, DES, Blowfish 등.
- 비대칭키 암호화: RSA, ECDSA, Diffie-Hellman 등.
- 해시 함수: SHA-1, SHA-256, SHA-3 등.
- 인증 암호화: AES-GCM, CCM 등.
- 기타: OpenPGP, CMS, TLS/DTLS, X.509 인증서 생성 등.
-
경량 API와 JCE 제공자:
- 경량 API: 메모리 제약 환경에서 직접 사용할 수 있는 저수준 API.
- JCE 제공자: 자바의 표준 암호화 프레임워크와 통합 가능.
-
FIPS 인증:
- Bouncy Castle은 FIPS 140-2 인증 버전을 제공하며, 높은 보안 요구 사항이 있는 환경에서도 사용 가능.
-
오픈소스 및 커뮤니티 지원:
- MIT 기반 라이선스로 배포되며, 누구나 무료로 사용 가능.
- GitHub를 통해 소스 코드가 공개되고, 커뮤니티 피드백을 반영.
-
플랫폼 유연성:
- Java뿐만 아니라 C#도 지원하며, Android 환경에서는 Spongy Castle이라는 변형 버전으로 사용됨.
Bouncy Castle의 기원
Bouncy Castle은 두 명의 자바 개발자가 서버 측 애플리케이션에서 반복적으로 암호화 라이브러리를 작성해야 하는 상황에 지쳤을 때 시작되었습니다. 이들은 Java ME(J2ME)와 같은 제한된 환경에서도 동작할 수 있는 유연한 라이브러리를 목표로 설계했으며, 이는 현재의 아키텍처로 이어졌습니다. 초기 버전은 약 27,000줄의 코드로 시작했지만, 현재(최신 버전 기준) 약 39만 줄 이상으로 확장되었습니다.
주요 사용 사례
- 암호화 및 복호화: AES, RSA 등을 사용한 데이터 보호.
- 디지털 서명: ECDSA, RSA 기반 서명 생성 및 검증.
- 키 관리: 키 쌍 생성, 패스워드 기반 키 생성(PBKDF2 등).
- 프로토콜 구현: TLS, OpenPGP, S/MIME 등 보안 프로토콜 지원.
- 인증서 관리: X.509 인증서 생성 및 처리.
자바에서 Bouncy Castle 사용 예제
Bouncy Castle을 자바 프로젝트에 추가하려면 Maven 의존성을 추가하고, JCE 제공자로 등록한 뒤 사용할 수 있습니다.
Maven 의존성
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.78</version>
</dependency>
제공자 등록 및 AES 암호화 예제
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;
public class BouncyCastleExample {
public static void main(String[] args) throws Exception {
// Bouncy Castle 제공자 등록
Security.addProvider(new BouncyCastleProvider());
// 키와 데이터 준비
byte[] keyBytes = "ThisIsASecretKey".getBytes();
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
String input = "Hello, Bouncy Castle!";
// 암호화
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encrypted = cipher.doFinal(input.getBytes());
System.out.println("Encrypted: " + Base64.getEncoder().encodeToString(encrypted));
}
}
장점
- 풍부한 기능: JCE보다 더 많은 알고리즘과 프로토콜 지원.
- 유연성: 경량 API로 임베디드 시스템에서도 사용 가능.
- 제한 없음: 미국 암호화 수출 제한(JCE의 과거 제약)을 피할 수 있음.
- 커뮤니티와 지속적인 업데이트: 활발한 개발과 최신 보안 표준 반영.
단점
- 복잡성: JCE보다 학습 곡선이 다소 높을 수 있음.
- 성능: 일부 경우 JCE의 네이티브 최적화(AES-NI 등)에 비해 느릴 수 있음.
- 의존성 관리: Android 등 특정 환경에서는 별도 변형(Spongy Castle) 필요.
JCE와의 비교
- JCE: 자바 표준 라이브러리로, 간단한 사용과 기본 기능에 적합. 하지만 과거 키 길이 제한(현재는 완화됨)과 지원 알고리즘의 한계가 있음.
- Bouncy Castle: 더 많은 알고리즘과 프로토콜을 제공하며, FIPS 인증과 같은 고급 요구 사항을 충족. 그러나 추가 설정이 필요.
Bouncy Castle은 암호화가 필요한 개발자에게 강력한 도구로 자리 잡고 있으며, 특히 보안 요구 사항이 높은 프로젝트에서 유용합니다. 추가로 궁금한 점이나 특정 기능에 대한 깊은 설명이 필요하면 말씀해 주세요!