mabutast/pqc_rails

GitHub: mabutast/pqc_rails

pqc_rails 是一个将 NIST 标准化抗量子密码算法(ML-KEM/ML-DSA)集成到 Rails 应用 session 和数据库加密中的 gem。

Stars: 0 | Forks: 0

# PqcRails [![Gem Version](https://badge.fury.io/rb/pqc_rails.svg)](https://badge.fury.io/rb/pqc_rails) [![Test](https://static.pigsec.cn/wp-content/uploads/repos/cas/ce/ce733292a922c08274cf5a2096f8fa4cf01023bfa51a36ef6beecaaef371a9d9.svg)](https://github.com/mabutast/pqc_rails/actions/workflows/test.yml) **pqc_rails** 是一个用于将抗量子密码(PQC: Post-Quantum Cryptography)集成到现有 Ruby on Rails 应用程序中的 gem。通过对 [liboqs](https://github.com/open-quantum-safe/liboqs) 的 FFI 绑定,在 Ruby 中原生调用 NIST 标准化算法。 运行生成器后,只需添加 2 行配置,即可将 Rails 应用的 session 和 DB 实现抗量子密码化。 ``` rails generate pqc_rails:install ``` ``` # config/application.rb config.session_store :pqc_cookie_store # config/initializers/pqc_rails.rb PqcRails::ActiveRecord::Context.install! ``` ## 为什么需要支持 PQC 没有理由等待 PQC 支持成为强制要求。就在此时此刻,通过“先收集,后解密”的 Harvest 攻击(Harvest Now, Decrypt Later:指现在窃听加密通信,待将来量子计算机成熟后再进行解密的攻击手段),数据仍在被不断地收集和囤积。 过去泄露的数据已无法挽回,但未来的通信可以从今天开始保护。`pqc_rails` 通过在现有的 Rails 应用程序中引入抗量子密码,来应对这种正在进行中的风险。 详细的威胁模型请参见 → [docs/THREAT_MODEL.md](docs/THREAT_MODEL.md) ## 当前支持状态 | 功能 | 状态 | | ----------------------------- | ------------------------------------------------ | | KEM(密钥封装机制) | ✅ 已支持(已在 ML-KEM-512/768/1024 上确认运行) | | DSA(签名算法) | ✅ 已支持(已在 ML-DSA-44/65/87 上确认运行) | | Session 加密 | ✅ 已支持(`PqcCookieStore`) | | ActiveRecord::Encryption 集成 | ✅ 已支持(`PqcRails::Cipher` + `KeyProvider`) | 除了 KEM 和 DSA 之外,session Cookie 和 ActiveRecord::Encryption 均通过基于 ML-KEM 的混合加密(KEM-DEM 结构)进行保护。liboqs 支持的其他算法,只需通过字符串指定算法名称即可使用(取决于 liboqs 侧的构建配置)。 ## 适用范围 - **目标范围是应用层的加密**(Session Cookie、DB 列)。TLS 通信信道本身的 PQC 化(Web 服务器、负载均衡器端的配置)不在范围内。虽然 Ruby / RubyGems 生态系统侧也在讨论将整个标准库支持 PQC([Ruby Feature #22068](https://bugs.ruby-lang.org/issues/22068)),但那是关于传输层的,与 `pqc_rails` 承担的应用层数据加密属于不同的层级。 - **不能替代 PKI 及证书管理基础设施**。不提供密钥颁发、生命周期管理、审计日志等功能。`pqc_rails` 承担的仅仅是 Rails 应用内 session 和 DB 列的加密。 - **使用量子计算机本身的加密方式(QKD、量子签名等)不在范围内**。`pqc_rails` 提供的是在经典计算机上运行且对量子计算机具有抵抗能力的加密(PQC: Post-Quantum Cryptography)。 - **JWT/Token 签名不在范围内**。虽然 `PqcRails::Sig`(ML-DSA)作为独立的签名原语提供,但与 session 和 DB 集成不同,它并未集成到 JWT 等 Token 格式中。针对此类用途,请考虑使用 [jwt-pq](https://rubygems.org/gems/jwt-pq) 等专用 gem(由于会加载与 `pqc_rails` 不同的 liboqs,即使同时使用也不会发生冲突)。 关于更详细的支持范围及排除项目,请参阅 [docs/THREAT_MODEL.md](docs/THREAT_MODEL.md#for-developers)。 ## 预期用例 该工具适用于所有处理需要长期保存的数据的 Rails 应用程序,特别是在以下用途中显得尤为紧迫: - 处理医疗记录、法务文件等需要 10 年或 20 年以上保密性的数据的应用程序 - 处理金融、加密资产相关的 session 管理或交易历史的应用程序(因为在量子计算机实用化后,私钥和交易数据的窃取将直接导致致命损失) ## 环境要求 - Ruby >= 3.2.0 - Rails >= 7.1 - 已构建并安装 [liboqs](https://github.com/open-quantum-safe/liboqs)(C 库) - 本 gem 不附带 liboqs。请提前构建共享库(`liboqs.dylib` / `liboqs.so`)并将其部署到系统中。 ## ⚠️ 关于 liboqs 的成熟度 本 gem 基于 [liboqs](https://github.com/open-quantum-safe/liboqs) 构建。liboqs 是由 [Open Quantum Safe (OQS)](https://openquantumsafe.org/) 项目开发的、基于 NIST 抗量子密码标准化项目的算法实现。 liboqs 官方文档明确指出了以下几点: - liboqs 仅供研究及原型设计使用,**目前不建议依赖其保护生产环境或机密数据** - 尽管已尽最大努力避免安全漏洞,但尚未进行投入生产环境所需的审计和分析水平 `pqc_rails` 负责“正确且安全地调用” liboqs,但不保证 liboqs 本身加密实现的正确性与安全性。在考虑引入生产环境时,请基于上述 liboqs 的现状,根据您所使用系统的重要程度进行风险评估。 NIST 标准化算法本身(ML-KEM, ML-DSA 等)虽已是确定的规范,但其“实现”的成熟度今后仍可能随着 liboqs 的改进而发生变化。 ## 安装 在 Gemfile 中添加以下内容: ``` gem "pqc_rails" ``` 然后执行: ``` bundle install rails generate pqc_rails:install ``` 生成器将生成 `config/initializers/pqc_rails.rb`,并将用于 session 和 DB 的密钥写入 Rails credentials。 ## 配置 ### liboqs 库路径 指定 liboqs 共享库的路径。如果未设置,将参考环境变量 `LIBOQS_PATH`;如果也不存在,则默认假定为各操作系统常见的存放位置(macOS: `/usr/local/lib/liboqs.dylib`,Linux: `/usr/local/lib/liboqs.so`)。 ``` # config/initializers/pqc_rails.rb PqcRails.configure do |config| config.liboqs_path = "/usr/local/lib/liboqs.dylib" end ``` ### Session 加密 ``` # config/application.rb config.session_store :pqc_cookie_store ``` 使用基于 ML-KEM 的 PQC 存储完全替换 Rails 的 `cookie_store`。现有的 session 在切换时将失效(所有用户都需要重新登录)。 密钥从 Rails credentials 的 `pqc_session_key` 中读取。可以使用环境变量 `PQC_SESSION_KEY` 进行覆盖。 ### ActiveRecord::Encryption ``` # config/initializers/pqc_rails.rb PqcRails::ActiveRecord::Context.install! ``` ``` # 模型 class User < ApplicationRecord encrypts :email, :phone_number end ``` 将 `ActiveRecord::Encryption` 的 Cipher 和 KeyProvider 替换为基于 ML-KEM 的实现。如果是全新引入,可直接使用。如果存在通过现有的 ActiveRecord::Encryption(Rails 默认)加密的数据,切换后默认将无法解密。如果难以进行批量重新加密,可以使用 Rails 标准的 `previous:` scheme 机制进行分阶段迁移 → [docs/MIGRATION.md](docs/MIGRATION.md) 密钥从 Rails credentials 的 `pqc_record_key` 中读取。可以使用环境变量 `PQC_RECORD_KEY` 进行覆盖。需与 session 用的密钥分开管理。 ## 使用方法 ### 指定算法 `PqcRails::Kem` / `PqcRails::Sig` 除了支持 liboqs 原生的算法名字符串(如 `"ML-KEM-512"`)外,也支持使用 Symbol(如 `:ml_kem_512`)。Symbol 会通过 `PqcRails::Algorithms` 注册表解析为 liboqs 的名称。 ``` PqcRails::Kem.new(:ml_kem_512) # シンボル指定(推奨) PqcRails::Kem.new("ML-KEM-512") # liboqs の生の名前を直接指定 ``` 目前注册表中已注册的算法: | 类别 | Symbol | NIST 安全级别 | | ---- | ---------------------------------------------- | ----------------------- | | KEM | `:ml_kem_512` / `:ml_kem_768` / `:ml_kem_1024` | 1 / 3 / 5 | | SIG | `:ml_dsa_44` / `:ml_dsa_65` / `:ml_dsa_87` | 2 / 3 / 5 | 如果传入未注册的 Symbol,将引发 `PqcRails::Algorithms::UnknownAlgorithmError`(`PqcRails::Error` 的子类)。 #### 使用注册表中未注册的算法(例如:Classic McEliece) 即使是 Symbol 注册表中没有的算法,只要在 liboqs 端进行了构建,就可以通过以字符串形式传入 liboqs 的原生名称来使用。例如,基于编码的密码学 Classic McEliece(已作为 [ISO/IEC 18033-2:2006/Amd 2:2026](https://www.iso.org/standard/86890.html) 标准化)可以像下面这样使用。 ``` PqcRails::Kem.open("Classic-McEliece-348864") do |kem| keypair = kem.generate_keypair keypair.public_key.bytesize # => 261120(約255KB。ML-KEM-512の800バイトと比べ大幅に大きい) end ``` 由于其公钥尺寸非常大(在 348864 参数集下约为 255KB),因此不适合用于像 TLS 握手这样频繁的密钥交换;但在密钥交换频率较低的长期数据加密中,它可以作为防范 ML-KEM 被攻破时的备选方案。其安全性的基础依赖于不同的数学难题(编码解码问题),因此具有与 ML-KEM(格问题)不同的风险特征。 同样地,被 NIST 选为 ML-KEM 备选方案的基于编码的 KEM“HQC”,在 liboqs 0.16.0 及以后版本中也已默认启用,通过传入原生名称(`"HQC-1"` / `"HQC-3"` / `"HQC-5"`)即可使用。但是,由于 HQC 仍处于 NIST 标准化制定过程中(FIPS 编号未定),因此尚未在 Symbol 注册表中注册。 ``` PqcRails::Kem.open("HQC-1") do |kem| keypair = kem.generate_keypair keypair.public_key.bytesize # => 2241 end ``` ### 密钥交换(KEM)的基本流程 ``` PqcRails::Kem.open("ML-KEM-512") do |kem| # 受信側: 鍵ペアを生成 keypair = kem.generate_keypair # 送信側: 受信側の公開鍵から共有秘密と ciphertext を生成 encapsulation = kem.encapsulate(keypair.public_key) # 受信側: ciphertext と自分の秘密鍵から共有秘密を復元 shared_secret = kem.decapsulate(encapsulation.ciphertext, keypair.secret_key) shared_secret == encapsulation.shared_secret # => true end ``` `PqcRails::Kem.open` 在退出代码块后会自动释放原生内存。如果想手动管理资源,也可以直接使用 `new` / `free`。 ``` kem = PqcRails::Kem.new("ML-KEM-512") # ... kem.free ``` #### 查看密钥长度 ``` kem = PqcRails::Kem.new("ML-KEM-512") kem.length_public_key # => 800 kem.length_secret_key # => 1632 kem.length_ciphertext # => 768 kem.length_shared_secret # => 32 ``` ### 签名(DSA)的基本流程 ``` PqcRails::Sig.open("ML-DSA-44") do |sig| # 署名者: 鍵ペアを生成 keypair = sig.generate_keypair # 署名者: メッセージに署名 signature = sig.sign("hello world", keypair.secret_key) # 検証者: 署名を検証 sig.verify("hello world", signature, keypair.public_key) # => true end ``` `verify` 在签名无效时不会引发异常,而是返回 `false`(遵循 liboqs 中 `OQS_SIG_verify` 的行为)。 ``` sig.verify("tampered message", signature, keypair.public_key) # => false ``` 与 `PqcRails::Kem` 一样,`PqcRails::Sig` 同时支持使用 `open` 的块形式和通过 `new` / `free` 进行手动管理。 #### 查看密钥与签名长度 ``` sig = PqcRails::Sig.new("ML-DSA-44") sig.length_public_key # => 1312 sig.length_secret_key # => 2560 sig.length_signature # => 2420(最大長。実際の署名はこれより短いことがあります) ``` ## 错误处理 - 如果指定了未知的算法名称,或指定了 liboqs 未启用的算法,将引发 `PqcRails::Error`。 - 如果传递给 `encapsulate` / `decapsulate` / `sign` 的字节序列长度不正确,将引发 `ArgumentError`。 - 对已执行过 `free` 的实例进行操作会引发 `PqcRails::Error`。 - 即使签名无效,`PqcRails::Sig#verify` 也不会引发异常,而是返回 `false`(这与 KEM 的设计不同)。 - 如果 `ActiveRecord::Encryption` 解密失败,将引发 `ActiveRecord::Encryption::Errors::Decryption`。 - 如果 session Cookie 不合法或被篡改,将作为空 session 处理(不会导致程序崩溃)。 ## 已验证的运行环境 - Ruby 3.2 / 3.3 / 3.4 - Rails 7.1 / 8.1 - liboqs 0.15.0 / 0.16.0 [CI](.github/workflows/test.yml) 会在每次提交 push 或 PR 时持续验证 Ruby 3.4 + Rails 8.1 + liboqs 0.15.0 的组合。liboqs 0.16.0 及其他 Ruby/Rails 版本的组合已通过手动验证(CI 的矩阵化是未来的计划任务)。 ## 开发 ``` bin/setup bundle exec rspec ``` ## 许可证 计划采用 [Business Source License (BSL)](https://mariadb.com/bsl11/)(详情未定,探讨中)。 - 源代码公开,开发、验证及非商业用途免费 - 商业性的生产环境使用需要另行签订许可协议 - 发布一定时间后,各版本将自动转换为开源许可证(设想为 Apache 2.0 或 MPL 2.0) 正式的许可条款确定后,将作为 [LICENSE.txt](LICENSE.txt) 公布。现阶段请勿将本仓库的代码用于商业用途。 ## 贡献 请在 [GitHub](https://github.com/mabutast/pqc_rails) 上提交 Issue 或 Pull Request。
标签:Ruby, Ruby on Rails, 内存转储, 后量子密码学, 密码学, 手动系统调用, 数据加密, 知识库