
클라이언트 코드 변경이 전혀 필요 없이 Apache Kafka에 투명한 포스트퀀텀(ML-KEM + AES-256-GCM) 레코드 수준 암호화를 제공하는 Kroxylicious 필터 플러그인입니다.
Apache Kafka를 위한 투명한 양자 내성 암호화(PQC) 레코드 수준 암호화를 제공하는 Kroxylicious 필터 플러그인으로, ML-KEM(FIPS 203) 키 캡슐화와 AES-256-GCM 대칭 암호화를 사용합니다.
Kafka 프로듀서와 컨슈머는 코드 변경이 전혀 필요 없습니다. Kroxylicious 프록시가 트래픽을 가로채서 Produce 시 암호화하고 Fetch 시 자동으로 복호화합니다.``` Producer ──plaintext──> Kroxylicious ──encrypted──> Kafka Broker Consumer <──plaintext── Kroxylicious <──encrypted── Kafka Broker
## Kafka용 PQC가 필요한 이유?
기존 키 설정 알고리즘(RSA, ECDH)은 미래의 양자 컴퓨터에 취약합니다. 레코드별 암호화 키가 기존 KEM으로 설정되는 경우, 양자 공격자는 브로커에서 암호문과 함께 저장된 캡슐화로부터 해당 키를 복구할 수 있습니다.
이 플러그인은 양자 저항 키 캡슐화를 위해 ML-KEM(FIPS 203)을 사용하므로, Kafka 브로커에 저장된 데이터는 암호학적으로 유의미한 양자 컴퓨터를 가진 공격자도 복호화할 수 없습니다.
**참고:** 이 필터는 전송 중인 TLS 채널이 아닌 **브로커에 저장된 데이터**를 보호합니다. 방어 대상과 비대상에 대한 전체 분석은 [THREAT_MODEL.md](https://github.com/oscerd/kroxylicious-pqc-filter/blob/main/THREAT_MODEL.md)를 참조하세요.
| 표준 | 알고리즘 | 이 플러그인에서의 용도 |
|----------|-----------|------------------------|
| FIPS 203 | ML-KEM (Kyber) | 키 캡슐화 - 메시지별 AES 키를 안전하게 설정 |
| N/A | AES-256-GCM | 레코드 페이로드의 대칭 인증 암호화 |
| N/A | X25519 ECDH | 하이브리드 모드 심층 방어를 위한 기존 키 합의 |
## 기능
- **투명한 암호화/복호화** - 클라이언트 측 변경 불필요
- **ML-KEM-512, ML-KEM-768(기본값), ML-KEM-1024** 매개변수 세트
- **하이브리드 모드** (기본값) - ML-KEM + X25519 ECDH를 결합하여 둘 다 깨져야 함
- **레코드별 암호화** - 각 레코드는 새로운 KEM 캡슐화 + 무작위 IV를 얻음
- **토픽 필터링** - 정규식 패턴으로 암호화할 토픽 선택
- **변조 감지** - AES-GCM 인증 암호화가 수정된 암호문을 거부
- **의미론적 보안** - 동일한 평문이 다른 암호문을 생성(IND-CCA2)
- **키 자동 생성** - 첫 시작 시 ML-KEM 키가 없으면 생성 및 저장
- **`x-pqc-encrypted` 헤더** - 다운스트림 인식을 위해 암호화된 레코드 표시
- **플러그형 키 제공자** - `KeyProvider` SPI는 파일시스템(기본값) 및 HashiCorp Vault 백엔드 지원
## 사전 요구 사항
| 요구 사항 | 버전 |
|-------------|---------|
| JDK | 17+ (21+ 권장) |
| Maven | 3.8+ |
| Kroxylicious | 0.19.0 |
| Apache Kafka | 3.9.x |
## 빠른 시작
### 1. 플러그인 빌드```bash
git clone <this-repo>
cd kroxylicious-pqc-filter
mvn clean package -DskipTests
target/kroxylicious-pqc-filter-1.0.0-SNAPSHOT.jar의 shaded JAR은 Bouncy Castle을 번들로 포함하므로 추가 의존성 없이 Kroxylicious에 바로 넣을 수 있습니다.
HashiCorp Vault 키 제공자 지원을 포함하려면 vault 프로파일로 빌드하세요:```bash
mvn clean package -Pvault -DskipTests
이것은 `spring-vault-core`와 `VaultKeyProvider`를 JAR에 번들합니다.
### 2. ML-KEM 키 생성```bash
java -cp target/kroxylicious-pqc-filter-1.0.0-SNAPSHOT.jar \
io.kroxylicious.filter.pqc.PqcKeyGeneratorCli \
ML_KEM_768 \
/etc/kroxylicious/pqc/
I don't see any source text in the input. Please provide the chunk content you'd like me to translate.``` Generating ML-KEM-768 key pair... Public key: /etc/kroxylicious/pqc/pqc-public.der Size: 1206 bytes Format: X.509 Private key: /etc/kroxylicious/pqc/pqc-private.der Size: 2498 bytes Format: PKCS#8
또는 구성에서 키 경로를 생략하면 필터가 첫 시작 시 키를 자동으로
생성합니다.
### 3. Kroxylicious 구성
Kroxylicious 프록시 YAML 구성에 필터를 추가하세요:```yaml
filterDefinitions:
- name: pqc-encryption
type: PqcRecordEncryptionFilterFactory
config:
kemAlgorithm: ML_KEM_768
hybridMode: true
publicKeyPath: /etc/kroxylicious/pqc/pqc-public.der
privateKeyPath: /etc/kroxylicious/pqc/pqc-private.der
topicPatterns:
- "sensitive-.*"
- "pii-.*"
defaultFilters:
- pqc-encryption
JAR을 Kroxylicious가 접근할 수 있는 디렉터리에 배치하고 KROXYLICIOUS_CLASSPATH 환경 변수를 통해
클래스패스에 추가하세요:```bash
export KROXYLICIOUS_CLASSPATH="/opt/kroxylicious/plugins/*"
Docker 사용 시, 컨테이너 환경에서 설정하십시오:```yaml
environment:
KROXYLICIOUS_CLASSPATH: /opt/kroxylicious/plugins/*
그런 다음 프록시를 시작합니다. 생산자와 소비자는 브로커에 직접 연결하는 대신 프록시 포트에 연결합니다.
| 속성 | 유형 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
kemAlgorithm | enum | 아니요 | ML_KEM_768 | ML-KEM 매개변수 집합. ML_KEM_512, ML_KEM_768, ML_KEM_1024 중 하나입니다. |
hybridMode | boolean | 아니요 | true | 심층 방어를 위해 ML-KEM을 X25519 ECDH와 결합합니다. |
publicKeyPath | string | 파일 시스템 전용 | - | ML-KEM 공개 키(X.509 DER 인코딩)의 파일 시스템 경로입니다. |
privateKeyPath | string | 파일 시스템 전용 | - | ML-KEM 개인 키(PKCS#8 DER 인코딩)의 파일 시스템 경로입니다. |
topicPatterns | list<string> | 아니요 | [".*"] | Java 정규식 패턴입니다. 일치하는 토픽의 레코드만 암호화/복호화됩니다. |
keyProviderType | string | 아니요 | filesystem | 키 저장 백엔드. filesystem, vault 중 하나입니다. |
keyProviderConfig | map<string, string> | Vault 전용 | {} | 백엔드별 구성입니다(아래 Vault 섹션 참조). |
파일 시스템(keyProviderType: filesystem, 기본값):
디스크의 DER 파일에서 ML-KEM 키를 로드합니다. 파일이 없으면 새 키 쌍을 생성하여 저장합니다. publicKeyPath와 privateKeyPath가 필요합니다.
HashiCorp Vault(keyProviderType: vault, -Pvault 빌드 필요):
Vault KV v2 시크릿 엔진에서 ML-KEM 키를 가져옵니다. 키는 publicKey 및 privateKey 필드에 base64로 인코딩된 DER로 저장됩니다. Vault 시크릿 버전은 키 회전 지원을 위해 키 ID에 매핑됩니다.
Vault keyProviderConfig 속성:
| 속성 | 필수 | 기본값 | 설명 |
|---|---|---|---|
vaultAddress | 예 | VAULT_ADDR 환경 변수 | Vault 서버 URL(예: http://vault:8200) |
vaultToken | token 인증용 | VAULT_TOKEN 환경 변수 | Vault 인증 토큰 |
secretPath | 예 | -- | 시크릿 엔진 내 경로(예: kroxylicious/pqc) |
secretEngine | 아니요 | secret | KV v2 시크릿 엔진 마운트 이름 |
authMethod | 아니요 | token | 인증 방법: token, approle 또는 kubernetes |
roleId | approle용 | -- | AppRole 역할 ID |
secretId | approle용 | -- | AppRole 시크릿 ID |
kubeRole | kubernetes용 | -- | Kubernetes 인증 역할 이름 |
kubeTokenPath | 아니요 | /var/run/secrets/.../token | 서비스 계정 토큰 파일 경로 |
Vault 구성 예시:```yaml filterDefinitions:
### ML-KEM 파라미터 세트
| 알고리즘 | 보안 수준 | 공개 키 | 개인 키 | 암호문 오버헤드 | 사용 사례 |
|-----------|---------------|------------|-------------|--------------------:|----------|
| ML-KEM-512 | 128-bit | 822 B | 1,730 B | ~854 B | 경량, IoT |
| ML-KEM-768 | 192-bit | 1,206 B | 2,498 B | ~1,174 B | **권장 기본값** |
| ML-KEM-1024 | 256-bit | 1,590 B | 3,266 B | ~1,654 B | 기밀 / 장기 보존 데이터 |
### 암호화 모드
**PQC 전용** (`hybridMode: false`):
ML-KEM만 사용합니다. AES-256 키는 ML-KEM 공유 비밀키에서
`SHA-256(0x01 || "kroxylicious-pqc-v1" || secret)`를 통해 파생됩니다.
**하이브리드** (`hybridMode: true`, 기본값):
ML-KEM + X25519를 결합합니다. AES-256 키는 두 비밀키에서
`SHA-256(0x02 || "kroxylicious-pqc-hybrid-v1" || pqcSecret || x25519Secret)`를 통해 파생됩니다.
이렇게 하면 하나의 알고리즘이 깨져도 보안이 유지됩니다.
## 암호화 봉투 형식
모든 암호화된 레코드 값은 이진 봉투로 대체됩니다:```
PQC-only (version 0x01):
+--------+-----------+--------------------+--------+---------------------------+
| 1 byte | 2 bytes | N bytes | 12 B | remaining |
| 0x01 | encap len | ML-KEM encapsulat. | AES IV | AES-GCM ciphertext + tag |
+--------+-----------+--------------------+--------+---------------------------+
Hybrid (version 0x02):
+--------+-----------+--------------------+---------+--------+-----------------+
| 1 byte | 2 bytes | N bytes | 32 B | 12 B | remaining |
| 0x02 | encap len | ML-KEM encapsulat. | X25519 | AES IV | AES-GCM ct+tag |
| | | | eph pub | | |
+--------+-----------+--------------------+---------+--------+-----------------+
버전 바이트를 통해 복호화기는 설정 없이 모드를 결정할 수 있습니다.