shurlinet/go-hqc

GitHub: shurlinet/go-hqc

go-hqc 是一个纯 Go 实现的后量子密钥封装机制,基于 HQC 算法,用于安全密钥交换以抵御量子计算机攻击。

Stars: 0 | Forks: 0

# go-hqc [![Go 测试](https://github.com/shurlinet/go-hqc/actions/workflows/ci.yml/badge.svg)](https://github.com/shurlinet/go-hqc/actions/workflows/ci.yml) [![Go 参考](https://pkg.go.dev/badge/github.com/shurlinet/go-hqc.svg)](https://pkg.go.dev/github.com/shurlinet/go-hqc) [![Go 报告卡](https://goreportcard.com/badge/github.com/shurlinet/go-hqc)](https://goreportcard.com/report/github.com/shurlinet/go-hqc) [![许可证:MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) **HQC**(准循环汉明码)的纯 Go 实现,这是一种基于编码的密钥封装机制,已被 NIST 选中作为 ML-KEM(基于格)的备用方案进行标准化。不同的密码学基础:如果格假设被破解,HQC 仍然安全。 NIST 于 2025 年 3 月[选择 HQC](https://csrc.nist.gov/projects/post-quantum-cryptography) 进行标准化,标准编号为 [FIPS 207](https://csrc.nist.gov/presentations/2025/fips-207-hqc-kem)。 正式标准预计会出台但尚未最终确定。标准调整了提交时的参数大小(种子从 40 位减至 32 位,共享密钥从 64 位减至 32 位)。核心密码构造(基于编码的 KEM,采用 Fujisaki-Okamoto 变换,Reed-Solomon/Reed-Muller 纠错)已经成熟(2017 年发表,已有 7 年多的密码分析历史)。go-hqc 跟踪官方 HQC v5.0.0 参考实现,并将在 FIPS 207 发布后进行更新。 ## 用法 ``` package main import ( "bytes" "fmt" "log" "github.com/shurlinet/go-hqc" ) func main() { // Generate a keypair. dk, err := hqc.GenerateKey128() if err != nil { log.Fatal(err) } defer dk.Destroy() // Encapsulate: peer gets the public key and produces shared secret + ciphertext. sharedSecret, ciphertext := dk.EncapsulationKey().Encapsulate() // Decapsulate: owner recovers the shared secret from ciphertext. recovered, err := dk.Decapsulate(ciphertext) if err != nil { log.Fatal(err) } fmt.Printf("match: %v, length: %d bytes\n", bytes.Equal(sharedSecret, recovered), len(sharedSecret)) } ``` ## 特性 - 纯 Go,零外部依赖(仅使用标准库的 `crypto/sha3`) - 三套参数集:HQC-128(1 级)、HQC-192(3 级)、HQC-256(5 级) - API 遵循 Go `crypto/mlkem` 模式(每参数集类型化密钥) - 使用 `crypto/subtle` 实现常数时间 FO 变换 - 通过 `Destroy()` 清零密钥(所有持久性秘密材料) - 从种子确定性生成密钥(`NewDecapsulationKey128(seed)`) - 用于测试的确定性封装(`EncapsulateWithEntropy` / `hqctest` 子包,镜像 `crypto/mlkem/mlkemtest`) - 解析时进行密钥一致性验证(`ParseDecapsulationKey128`) - 并发安全:`Decapsulate` 可安全地并发使用 - 通过 `Version()` 进行规范版本检查 ## 安全性 - **隐式拒绝**:无效密文会产生一个从 sigma 派生的、看起来随机的共享密钥(永远不会泄露解密成功/失败的错误) - **常数时间 FO 比较**:使用 `crypto/subtle.ConstantTimeSelect` - **密钥清零**:`Destroy()` 通过 `//go:noinline` 零化函数清零 seedDK、sigma、seedKem、x、y、sk - **解析验证**:`ParseDecapsulationKey` 会验证内嵌的公钥是否与 seed_dk 匹配(捕获损坏情况) - **WASM 注意事项**:常数时间保证适用于原生目标(amd64、arm64)。WASM 编译不提供时序保证。 - **无故障注入对策**:此实现不防御电压毛刺或 Rowhammer 攻击。详情请参见包文档。 ## 使用者职责 * **在解封装密钥不再需要时调用 `Destroy()`**。`Destroy()` 会清零秘密材料。Go 的垃圾回收器不保证及时清零释放的内存。丢弃密钥引用而不调用 `Destroy()` 会让秘密在内存中保留直到 GC 回收。 * **不要重复使用密文。** 每次 `Encapsulate()` 调用都会产生一个新的共享密钥和密文。将密文重放到不同的解封装密钥是没有意义的。 * **验证密文来源。** KEM 提供隐式拒绝(无效密文产生随机共享密钥),但它不认证发送方。使用共享密钥来建立认证通道。 * **编程检查 `Version()`**,如果你的应用需要跟踪正在使用的 HQC 规范版本。版本字符串将在实现 FIPS 207 时更改。 ## 测试 ``` make test # KAT + property + AI threat + accumulated-100 (~30s total) make bench # benchmarks for all 3 param sets (~15s) make fuzz # 30s fuzz per target, 2 targets (~1 min total) make fuzz-long # 5 min fuzz per target, 2 targets (~10 min total) make lint # go vet + staticcheck (~5s) ``` ### 累积验证层级 针对由 v5.0.0 C 生成的、经过 SHAKE128 累积的哈希值,验证 N 个完整的 KEM 周期(密钥生成 + 封装 + 解封装)。一个哈希证明 N 个周期在字节上正确。 ``` make accumulated-100 # 100 iterations (~10s total, runs in make test) make accumulated-1k # 1,000 iterations (~2 min total) make accumulated-10k # 10,000 iterations (~17 min total) make accumulated-100k # 100,000 iterations (~2.5 hours total, pre-release) make accumulated-1m # 1,000,000 iterations (~28 hours total, auditor) ``` 在 M3 Max 上的耗时。HQC-256 比 HQC-128 慢约 6 倍(多项式更大)。所有 3 个参数集顺序运行。 或者直接运行:`GOHQC_ACCUMULATED=10000 go test -run=TestAccumulated -v ./...` ### 测试清单 | 类别 | 数量 | 描述 | |------|------|------| | KAT 密钥生成 | 30 | v5.0.0 向量,逐字节匹配(每参数集 10 个) | | KAT 封装 | 30 | v5.0.0 向量,带解封装验证(每参数集 10 个) | | 往返测试 | 3 | 每参数集封装/解封装一致性 | | 密钥序列化 | 1 | 字节/解析/种子往返测试(HQC-128) | | 边界情况 | 4 | 零 ct、修改 salt、错误长度 | | 并发性 | 1 | 8 个 goroutine 并行解封装 | | Destroy 生命周期 | 1 | 调用 Destroy 后的错误,双重 Destroy 安全性 | | 切片隔离 | 1 | 返回的切片独立于内部状态 | | 常数时间 | 1 | 有效 ct 路径与无效 ct 路径的等价性 | | 大小常量 | 1 | 从参数计算得出,防篡改 | | 属性:往返 | 3 | 每参数集 5 次迭代 | | 属性:密钥序列化 | 3 | 每参数集 DK + EK 往返测试 | | 属性:种子 | 3 | 每参数集种子往返测试 | | AI 威胁防御 | 4 | 域字节(G/H/I/J/XOF/PRNG),hashG + hashH 独立性,nMu/rejThreshold 公式 | | 版本 | 1 | Version() 返回预期的规范字符串 | | 密钥生成验证 | 1 | 从 seed_dk 重新派生 y,x,验证 s = x + y*h | | 累积 | 3 | SHAKE128 累积哈希 vs v5.0.0 C(100-1M 层级) | | 基准测试 | 9 | 每参数集的密钥生成/封装/解封装 | | 模糊测试 | 2 | FuzzDecapsulate128,FuzzKeyRoundTrip128 | | Godoc 示例 | 3 | 基础用法、序列化、所有参数集 | | hqctest 确定性 | 6 | 确定性封装可重现性 + 大小检查(所有 3 个参数集) | | **组件测试** | 50 | GF、seedexpander、gf2x、向量、RM、RS、FFT、编码 | ## 验证 go-hqc 通过以下方式验证: * [KAT 向量](testdata/) - 60 个已知答案测试(30 个密钥生成 + 30 个封装/解封装),覆盖所有 3 个参数集,逐字节匹配官方 HQC v5.0.0 C 参考实现。使用 HQC 自定义的 SHAKE256 DRBG 生成([tools/gen-vectors/](tools/gen-vectors/))。 * [累积哈希锚点](testdata/accumulated.json) - 每参数集超过 100 万次密钥生成/封装迭代的 SHA256 哈希。Go 测试验证到 10 万次;100 万次哈希是供外部验证者参考的数据。 * [属性测试](hqc_property_test.go) - 15 次往返迭代(每参数集 5 次),3 次密钥序列化往返测试(Bytes/Parse + Seed/New + EK),3 个种子确定性证明。 * [模糊测试](hqc_fuzz_test.go) - 2 个目标:`FuzzDecapsulate128`(随机密文,无 panic,始终产生 32 字节隐式拒绝)和 `FuzzKeyRoundTrip128`(随机种子,生成/序列化/解析/解封装一致性,带有 5 个 VP1 长度断言)。 * [AI 威胁防御](hqc_property_test.go) - 4 项独立验证:域分离字节(G/H/I/J/XOF/PRNG 唯一性 + 固定值),通过独立的 SHA3-512 计算 hashG,通过独立的 SHA3-256 计算 hashH,为所有 3 个参数集重新计算 nMu/rejectionThreshold 公式。 * [组件测试](gf_test.go) - 50 个测试,覆盖 8 个子系统:GF(2^m) 全面 65,536 乘法预言机,seedexpander 直接抽取 + 固定回归,karatsuba 多项式乘法,Reed-Muller RM(1,7) 所有 256 字节往返测试,Reed-Solomon LFSR 编码 + Berlekamp 解码(不同错误数量),Gao-Mateer 加法 FFT 求根,级联码往返测试,sampler1/sampler2 权重 + 确定性 + 连续调用。 * 9 个[基准测试](hqc_property_test.go) - 所有 3 个参数集的密钥生成/封装/解封装。 ``` make test ``` 或者等效地:`go test -race -count=1 ./...` ## 示例 | 示例 | 描述 | |------|------| | [`examples/basic/`](examples/basic/) | HQC-128 密钥交换(生成、封装、解封装) | | [`examples/serialization/`](examples/serialization/) | 密钥持久化(Bytes/Parse、Seed/New、EK 往返测试) | ## 依赖 无。go-hqc 仅使用 Go 标准库(`crypto/sha3`、`crypto/subtle`、`crypto/rand`)。零外部模块依赖。 | 依赖 | 用途 | |------|------| | Go 1.26+ | `crypto/sha3` 所需 | ## 上游跟踪 来源:官方 HQC v5.0.0 (https://gitlab.com/pqc-hqc/hqc/)。完整跟踪详情和 FIPS 207 状态请参见 [UPSTREAM.md](UPSTREAM.md)。 ## AI 透明度 此库在 AI 协助下开发([Claude](https://claude.ai))。所有密码学决策均已针对官方 v5.0.0 C 参考实现进行验证。KAT 向量从 v5.0.0 测试工具生成并逐字节验证。测试套件包含 AI 威胁防御测试,旨在捕获人为和 AI 引入的错误。AI 生成代码;人类做出每一个设计决策,审查每一行代码,并对每一个 bug 负责。 ## 致谢 - 感谢 HQC 作者和前 PQClean 贡献者提供的清晰、可移植的 C 参考实现(公共领域) - 感谢 Carlos Aguilar Melchor、Nicolas Aragon、Slim Bettaieb、Loic Bidoux、Olivier Blazy、Jurjen Bos、Jean-Christophe Deneuville、Philippe Gaborit、Edoardo Persichetti、Jean-Marc Robert、Pascal Veron、Gilles Zemor 以及 HQC 设计团队创造了该算法 ## 未来:Go 标准库 当 FIPS 207 最终确定后,Go 很可能会将 `crypto/hqc` 添加到标准库(就像为 ML-KEM 添加 `crypto/mlkem` 一样)。届时: - `crypto/hqc` 成为官方 Go 实现 - go-hqc 作为独立模块继续工作(不会中断) - 迁移只需更改导入路径(API 遵循相同的 `crypto/mlkem` 模式) - go-hqc 可能仍然适用于 FIPS 部署前或固定使用旧 Go 版本的环境 这与 [`filippo.io/mldsa`](https://pkg.go.dev/filippo.io/mldsa)(被 [go-clatter](https://github.com/shurlinet/go-clatter) 使用的、标准库前的 ML-DSA 实现)的生命周期相同,它将在 Go 发布 `crypto/mldsa` 时迁移过去。 ## 参考文献 - [HQC 规范](https://pqc-hqc.org) - 官方 HQC 网站,包含算法规范、设计原理和参数选择 - [NIST 后量子密码学](https://csrc.nist.gov/projects/post-quantum-cryptography) - NIST PQC 标准化项目(HQC 被选为与 ML-KEM 并列的备用 KEM) - [FIPS 207](https://csrc.nist.gov/presentations/2025/fips-207-hqc-kem) - HQC 标准化(尚未最终确定,预计 2026 年末/2027 年初) - [HQC 官方](https://gitlab.com/pqc-hqc/hqc/) - 官方参考实现(v5.0.0) - [PQNoise 论文](https://doi.org/10.1145/3548606.3560577) - PQNoise 扩展(ACM CCS 2022),在 Noise 握手中使用像 HQC 这样的 KEM(由 [go-clatter](https://github.com/shurlinet/go-clatter) 实现) ## 许可证 MIT。参见 [LICENSE](LICENSE)。 HQC 参考代码属于公共领域(CC0)。参见 [THIRD_PARTY_LICENSES](THIRD_PARTY_LICENSES)。
标签:EVTX分析, Fujisaki-Okamoto变换, Go库, Go语言, Hamming Quasi-Cyclic, HQC算法, KEM, NIST FIPS 207, NIST标准, Reed-Muller纠错, Reed-Solomon纠错, 代码基密码学, 共享秘密, 加密库, 后量子安全, 后量子密码学, 安全通信, 密码学安全, 密码学实现, 密钥封装机制, 密钥生成, 封装解封装, 抗量子密码, 日志审计, 程序破解, 纠错码, 纯Go实现, 零依赖