Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
kroxylicious-pqc-filter — 一个 Kroxylicious 过滤器插件,为 Apache Kafka 提供透明的后量子(ML-KEM + AES-256-GCM)记录级加密,无需任何客户端代码改动。 | Kitploit
工具/GitHubGitHub/oscerd/kroxylicious-pqc-filter
云基础设施安全加密/解密工具密码学实用工具与框架
GitHuboscerd/kroxylicious-pqc-filter

kroxylicious-pqc-filter

一个 Kroxylicious 过滤器插件,为 Apache Kafka 提供透明的后量子(ML-KEM + AES-256-GCM)记录级加密,无需任何客户端代码改动。

查看仓库
13个月前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

Kroxylicious PQC 记录加密过滤器

一款 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

root@kitploit:~
## 为什么要为 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/HEAD/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

root@kitploit:~
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

root@kitploit:~
或者,在配置中省略密钥路径,过滤器将在首次启动时自动生成密钥。

### 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

4. 部署

将 JAR 放置在 Kroxylicious 可访问的目录中,并通过 KROXYLICIOUS_CLASSPATH 环境变量将其添加到 classpath:```bash export KROXYLICIOUS_CLASSPATH="/opt/kroxylicious/plugins/*"

root@kitploit:~
使用 Docker 时,请在容器环境中设置:```yaml
environment:
  KROXYLICIOUS_CLASSPATH: /opt/kroxylicious/plugins/*

然后启动代理。生产者和消费者连接到代理端口,而不是直接连接 broker。

配置参考

密钥提供程序

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 属性:

Vault 配置示例:```yaml filterDefinitions:

  • name: pqc-encryption type: PqcRecordEncryptionFilterFactory config: kemAlgorithm: ML_KEM_768 hybridMode: false keyProviderType: vault keyProviderConfig: vaultAddress: http://vault:8200 vaultToken: my-token secretPath: kroxylicious/pqc topicPatterns: - "sensitive-.*"
root@kitploit:~
### 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 |        |                 |
+--------+-----------+--------------------+---------+--------+-----------------+

版本字节允许解密器无需配置即可确定模式。

架构

模块结构```

kroxylicious-pqc-filter/ src/main/java/io/kroxylicious/filter/pqc/ PqcRecordEncryptionFilterFactory.java # FilterFactory entry point (@Plugin) PqcRecordEncryptionFilter.java # ProduceRequestFilter + FetchResponseFilter PqcKeyGeneratorCli.java # CLI key generation utility config/ PqcEncryptionConfig.java # Jackson-deserialized configuration POJO crypto/ KeyProvider.java # SPI interface for pluggable key backends FileSystemKeyProvider.java # Default: loads/generates keys from disk PqcCryptoEngine.java # ML-KEM encapsulation + AES-256-GCM PqcKeyManager.java # Resolves KeyProvider via ServiceLoader src/main/java-vault/ # (vault profile only) .../crypto/ VaultKeyProvider.java # HashiCorp Vault KV v2 key provider src/main/resources/ META-INF/services/ io.kroxylicious.proxy.filter.FilterFactory # ServiceLoader: filter registration io.kroxylicious.filter.pqc.crypto.KeyProvider # ServiceLoader: key provider src/main/resources-vault/ # (vault profile only) META-INF/services/ io.kroxylicious.filter.pqc.crypto.KeyProvider # Registers both FS + Vault providers src/test/java/... # Unit tests (49 tests) src/test/java-vault/... # Vault provider tests (17 tests) examples/ standalone/ # Runs without Kafka (crypto engine demo) docker/ # Docker Compose: Kafka + Vault + Kroxylicious

root@kitploit:~
### 数据流

#### Vault 中存储的内容

Vault KV v2 在 `secret/<secretPath>`(例如 `secret/kroxylicious/pqc`)中保存 ML-KEM 密钥对:

| 字段 | 内容 | 格式 |
|-------|---------|--------|
| `publicKey` | ML-KEM 公钥(用于封装) | Base64 编码的 X.509 DER |
| `privateKey` | ML-KEM 私钥(用于解封装) | Base64 编码的 PKCS#8 DER |

每个 Vault secret 版本都充当一个密钥 ID,支持密钥轮换。新版本
加密新记录;旧版本仍可解密用它们加密的记录。

#### 启动流程```
┌─────────────────────────────────────────────────────────────────────┐
│                           STARTUP                                   │
│                                                                     │
│  1. Vault starts (dev mode, port 8200)                              │
│         │                                                           │
│  2. vault-init container:                                           │
│         │  • Reads pre-generated ML-KEM DER key files from disk     │
│         │  • Base64-encodes them                                    │
│         │  • POST /v1/secret/data/kroxylicious/pqc                  │
│         │  • Stores publicKey + privateKey in Vault KV v2           │
│         │  • Exits                                                  │
│         │                                                           │
│  3. Kafka starts (KRaft mode, port 9092)                            │
│         │                                                           │
│  4. Kroxylicious starts (port 9192):                                │
│         │                                                           │
│         │  FilterFactory.initialize()                                │
│         │    → PqcKeyManager resolves VaultKeyProvider               │
│         │      via ServiceLoader (matches keyProviderType: "vault")  │
│         │    → VaultKeyProvider.configure()                          │
│         │      connects to Vault (token/approle/kubernetes auth)     │
│         │    → Fetches ML-KEM key pair from Vault KV v2              │
│         │      (GET /v1/secret/data/kroxylicious/pqc)                │
│         │    → Decodes: base64 → DER bytes → Java Key objects        │
│         │    → PqcCryptoEngine initialized with key pair             │
│         ▼                                                           │
│       Proxy ready — Vault is NOT contacted again per-message         │
└─────────────────────────────────────────────────────────────────────┘

生成流程(加密)```

root@kitploit:~
                     Kroxylicious (:9192)
                    ┌───────────────────────────────────────────┐

Producer ──plaintext──> │ PqcRecordEncryptionFilter │ │ .onProduceRequest() │ │ │ │ For each record in matching topic: │ │ 1. ML-KEM encapsulate (public key) │ │ → fresh shared secret │ │ → encapsulation blob │ │ 2. SHA-256(shared secret) → AES-256 key │ │ 3. AES-GCM encrypt record value │ │ 4. Build binary envelope: │ │ [ver|encap_len|encap|IV|ciphertext] │ │ 5. Add x-pqc-encrypted header │ └────────────────┬──────────────────────────┘ │ ▼ Kafka Broker (:9092) stores encrypted blob

root@kitploit:~
#### 获取流程(解密)```
                                  Kafka Broker (:9092)
                                  returns encrypted blob
                                         │
                                         ▼
                        ┌────────────────┴──────────────────────────┐
                        │ PqcRecordEncryptionFilter                 │
                        │   .onFetchResponse()                      │
                        │                                           │
                        │ For each record with x-pqc-encrypted:     │
                        │   1. Parse envelope → extract encap +     │
                        │      ciphertext                           │
                        │   2. ML-KEM decapsulate (private key)     │
                        │      → recover shared secret              │
                        │   3. SHA-256(shared secret) → AES-256 key │
                        │   4. AES-GCM decrypt → plaintext          │
                        │   5. Remove x-pqc-encrypted header        │
Consumer <──plaintext── │                                           │
                        └───────────────────────────────────────────┘
                         Kroxylicious (:9192)

关键设计决策

  • Vault 仅在启动时被访问,而非逐条消息访问。没有每条记录延迟。
  • 如果 Vault 在启动后宕机,加密/解密继续不受影响。
  • 每条记录都会获得新的 ML-KEM 封装(新的共享密钥 + 随机 IV), 即使复用同一密钥对,也能确保语义安全(IND-CCA2)。
  • 密钥轮换通过写入新的 Vault 密钥版本并重启代理来完成。

过滤器生命周期```

Startup: FilterFactory.initialize() -> PqcKeyManager loads/generates ML-KEM key pair -> PqcCryptoEngine created with key pair -> Topic patterns compiled -> SharedPqcContext returned

Per connection: FilterFactory.createFilter() -> New PqcRecordEncryptionFilter instance -> Shares the same PqcCryptoEngine (thread-safe)

Produce request: onProduceRequest() -> For each topic matching topicPatterns: -> For each partition: -> For each record: -> ML-KEM encapsulate (fresh shared secret + encapsulation) -> Derive AES-256 key from shared secret -> AES-GCM encrypt the record value -> Replace value with encrypted envelope -> Add x-pqc-encrypted header -> Forward to broker

Fetch response: onFetchResponse() -> For each topic matching topicPatterns: -> For each partition: -> For each record with x-pqc-encrypted header: -> Read version + encapsulation from envelope -> ML-KEM decapsulate (recover shared secret) -> Derive AES-256 key -> AES-GCM decrypt -> Replace value with plaintext -> Remove x-pqc-encrypted header -> Forward to client

root@kitploit:~
### 关键类

**`PqcRecordEncryptionFilterFactory`** 实现 `FilterFactory<PqcEncryptionConfig, SharedPqcContext>`。
使用 `@Plugin(configType = PqcEncryptionConfig.class)` 进行注解。
通过 `META-INF/services/io.kroxylicious.proxy.filter.FilterFactory` 注册。
在启动时调用一次(`initialize`),每个客户端连接调用一次(`createFilter`)。

**`PqcRecordEncryptionFilter`** 实现 `ProduceRequestFilter` 和 `FetchResponseFilter`。
拦截 `onProduceRequest` 进行加密,拦截 `onFetchResponse` 进行解密。
每个连接一个实例;无需同步(Kroxylicious 线程模型)。

**`PqcCryptoEngine`** 执行所有密码学操作。
除密钥材料和 `SecureRandom` 外无状态。
`encrypt()` 返回自描述信封;`decrypt()` 解析该信封。
在静态初始化器中注册 Bouncy Castle 提供者(`BC`、`BCPQC`)。

**`PqcKeyManager`** 通过 `ServiceLoader` 解析 `KeyProvider`,依据
`keyProviderType` 进行匹配。将所有密钥操作委托给已解析的提供者。

**`KeyProvider`** 是可插拔密钥存储后端的 SPI 接口。
实现通过 `META-INF/services` 发现。内置提供者:
`FileSystemKeyProvider`(默认)和 `VaultKeyProvider`(使用 `-Pvault`)。

**`PqcEncryptionConfig`** 是 Jackson 注解的 POJO。
从 Kroxylicious 代理 YAML 的 `config:` 块中反序列化。
支持 `keyProviderType` 和 `keyProviderConfig` 用于后端选择。

## 构建与测试```bash
# Compile
mvn compile

# Run unit tests (38 core tests)
mvn test

# Package (creates shaded JAR with Bouncy Castle bundled)
mvn package

# Build with Vault support (55 tests: 38 core + 17 vault)
mvn package -Pvault

# Install to local Maven repository
mvn install

测试覆盖

总计:55 个测试(38 个核心 + 17 个 Vault)

依赖

运行时

测试

JUnit 5.11.4, Mockito 5.15.2, AssertJ 3.27.3, Jackson Databind 2.18.3.

性能

在独立演示环境中测量(JVM 预热,1,000 次迭代,1 KB 消息):

算法加密解密
ML-KEM-512~7,700 msg/s (0.13 ms/msg)~7,800 msg/s (0.13 ms/msg)
ML-KEM-768~9,600 msg/s (0.10 ms/msg)

每条消息的开销为亚毫秒级。对于典型的 Kafka 工作负载 (KB-MB 范围内的消息),与网络和磁盘 I/O 相比, 加密成本可以忽略不计。

安全注意事项

有关该过滤器防御什么、不防御什么的完整威胁模型, 请参阅 THREAT_MODEL.md。

  • 密钥保护(文件系统):私钥文件必须只能由 Kroxylicious 进程读取。 请使用文件系统权限(chmod 600)。
  • 密钥保护(Vault):使用 Vault 策略限制对 secret 路径的访问。 在生产环境中,优先使用 approle 或 kubernetes 认证,而非静态令牌。 切勿将 Vault 令牌提交到版本控制。
  • 密钥轮换:Vault 密钥提供程序通过 Vault secret 版本支持密钥版本化。 新版本用于加密;旧版本仍可解密。
  • 墓碑消息:值为 null 的记录(Kafka 墓碑消息) 将不加密直接透传。
  • 消息头:记录头不加密,仅加密值。 请勿在消息头中放置敏感数据。
  • 压缩:该过滤器使用 Compression.NONE 写入加密批次, 因为加密数据压缩效果不佳。

许可证

Apache License 2.0。详情请参阅 LICENSE。

下载工具
属性类型必填默认值描述
kemAlgorithmenum否ML_KEM_768ML-KEM 参数集。可为 ML_KEM_512、ML_KEM_768、ML_KEM_1024 之一。
hybridModeboolean否true将 ML-KEM 与 X25519 ECDH 结合以实现深度防御。
publicKeyPathstring仅文件系统-ML-KEM 公钥的文件系统路径(X.509 DER 编码)。
privateKeyPathstring仅文件系统-ML-KEM 私钥的文件系统路径(PKCS#8 DER 编码)。
topicPatternslist<string>否[".*"]Java 正则表达式模式。仅匹配主题中的记录会被加密/解密。
keyProviderTypestring否filesystem密钥存储后端。可选 filesystem、vault。
keyProviderConfigmap<string, string>仅 Vault{}后端专用配置(参见下文 Vault 部分)。
属性必填默认值描述
vaultAddress是VAULT_ADDR 环境变量Vault 服务器 URL(例如 http://vault:8200)
vaultTokentoken 认证时需要VAULT_TOKEN 环境变量Vault 认证令牌
secretPath是--机密引擎内的路径(例如 kroxylicious/pqc)
secretEngine否secretKV v2 机密引擎挂载名称
authMethod否token认证方法:token、approle 或 kubernetes
roleIdapprole 认证时需要--AppRole 角色 ID
secretIdapprole 认证时需要--AppRole 机密 ID
kubeRolekubernetes 认证时需要--Kubernetes 认证角色名称
kubeTokenPath否/var/run/secrets/.../token服务账户令牌文件路径
测试类测试数验证内容
PqcCryptoEngineTest12所有 3 种 ML-KEM 变体的加密/解密往返、null 处理、空载荷和 1MB 载荷、语义安全性、篡改检测、无效版本拒绝、密钥生成、信封版本字节
PqcEncryptionConfigTest9默认值、显式值、null 拒绝、JSON 反序列化、不可变性、枚举属性、keyProviderConfig 反序列化
PqcKeyManagerTest6KeyProvider 解析、引擎创建、委托给提供程序、文件系统类型的回退
FileSystemKeyProviderTest11密钥生成、加载现有密钥、默认密钥 ID、未知密钥 ID 拒绝、null 路径校验、ServiceLoader 发现、加密往返
VaultKeyProviderTest17配置校验(缺失 path/address/token/approle/kube)、从 Vault 获取密钥、带版本的密钥检索、缓存密钥、无效版本、secret 中缺失字段、加密往返、关闭行为
依赖版本作用域用途
io.kroxylicious:kroxylicious-api0.19.0providedFilter API 接口
org.apache.kafka:kafka-clients3.9.0providedKafka 协议消息类型
com.fasterxml.jackson.core:jackson-annotations2.18.3provided配置绑定
org.bouncycastle:bcprov-jdk18on1.83compileML-KEM、AES-GCM、X25519(捆绑在 shaded JAR 中)
org.bouncycastle:bcutil-jdk18on1.83compileBouncy Castle 工具类(捆绑在 shaded JAR 中)
org.slf4j:slf4j-api2.0.17provided日志
org.springframework.vault:spring-vault-core3.1.2compile(vault profile)Vault KV v2 客户端(使用 -Pvault 构建时捆绑)
~10,200 msg/s (0.10 ms/msg)
ML-KEM-1024~8,500 msg/s (0.12 ms/msg)~6,900 msg/s (0.14 ms/msg)