一款 Kroxylicious 过滤器插件,使用 ML-KEM(FIPS 203)密钥封装和 AES-256-GCM 对称加密,为 Apache Kafka 提供透明的 后量子密码学(PQC) 记录级加密。
Kafka 生产者和消费者零代码更改。Kroxylicious 代理 拦截流量,并在 Produce 时自动加密、在 Fetch 时自动解密。``` Producer ──plaintext──> Kroxylicious ──encrypted──> Kafka Broker Consumer <──plaintext── Kroxylicious <──encrypted── Kafka Broker
## 为什么要为 Kafka 使用 PQC?
经典密钥建立算法(RSA、ECDH)容易受到未来量子计算机的攻击。如果使用经典 KEM 建立每条记录的加密密钥,量子对手可以从存储在 broker 上、与密文一起保存的封装数据中恢复出这些密钥。
该插件使用 ML-KEM(FIPS 203)进行抗量子密钥封装,确保即使对手拥有具备密码学相关能力的量子计算机,也无法解密 Kafka broker 上的静态数据。
**注意:** 此过滤器保护的是 **broker 上的静态数据**,而不是传输中的 TLS 信道。有关哪些攻击受到防御、哪些未受到防御的完整分析,请参阅 [THREAT_MODEL.md](https://github.com/oscerd/kroxylicious-pqc-filter/blob/main/THREAT_MODEL.md)。
| Standard | Algorithm | 本插件中的用途 |
|----------|-----------|------------------------|
| 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+ recommended) |
| 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 profile 构建:```bash
mvn clean package -Pvault -DskipTests
This bundles `spring-vault-core` and the `VaultKeyProvider` into the JAR.
### 2. Generate ML-KEM keys```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 to translate. Please provide the Markdown content for chunk 9 of 33.``` 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 环境变量将其添加到 classpath:```bash
export KROXYLICIOUS_CLASSPATH="/opt/kroxylicious/plugins/*"
使用 Docker 时,请在容器环境中设置:```yaml
environment:
KROXYLICIOUS_CLASSPATH: /opt/kroxylicious/plugins/*
然后启动代理。生产者和消费者连接到代理端口,而不是直接连接 broker。
| 属性 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
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 部分)。 |
Filesystem(keyProviderType: filesystem,默认):
从磁盘上的 DER 文件加载 ML-KEM 密钥。如果文件不存在,则生成新的密钥对并保存。需要 publicKeyPath 和 privateKeyPath。
HashiCorp Vault(keyProviderType: vault,需要 -Pvault 构建):
从 Vault KV v2 机密引擎获取 ML-KEM 密钥。密钥以 base64 编码的 DER 形式存储于 publicKey 和 privateKey 字段中。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 位 | 822 B | 1,730 B | ~854 B | 轻量级、物联网 |
| ML-KEM-768 | 192 位 | 1,206 B | 2,498 B | ~1,174 B | **推荐默认** |
| ML-KEM-1024 | 256 位 | 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 | | |
+--------+-----------+--------------------+---------+--------+-----------------+
版本字节允许解密器无需配置即可确定模式。