Project

pq_crypto

0.0
The project is in a healthy, maintained state
Native Ruby wrapper around ML-KEM, ML-DSA, and an optional hybrid ML-KEM-768+X25519 KEM, backed by PQ Code Package native sources and OpenSSL.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

~> 5.0
~> 13.0
 Project Readme

pq_crypto

pq_crypto is a primitive-first Ruby gem for post-quantum cryptography. It provides small Ruby APIs for ML-KEM, ML-DSA, and one hybrid X-Wing KEM, with standard key serialization where available.

The gem intentionally stays close to cryptographic primitives. It does not provide protocol, session, transport, certificate-chain, or application-level handshake helpers.

Installation

Add the gem to your Gemfile:

# Gemfile
gem "pq_crypto"

Then install it:

bundle install

When working from a source checkout, compile the native extension before running tests or examples:

bundle exec rake compile
bundle exec rake test

What this gem provides

Area Capabilities
ML-KEM Key generation, seed-aware secret keys, encapsulation, decapsulation, raw key import/export, SPKI public keys, PKCS#8 private keys.
ML-DSA Key generation, seed-aware secret keys, signing/verification with optional FIPS 204 context, streaming signing/verification for large inputs, raw key import/export, SPKI public keys, PKCS#8 private keys.
Hybrid KEM ML-KEM-768 + X25519 using the X-Wing combiner.
Serialization Standard SPKI / PKCS#8 for NIST PQC keys, encrypted PKCS#8 private keys, auto-dispatch key loading, plus frozen pqc_container_* compatibility formats for the original algorithms.
Safety helpers Best-effort secret wiping and constant-time equality for key comparisons.
Introspection Supported algorithm lists, algorithm metadata, backend/version helpers.

Supported algorithms

Family Algorithms Notes
KEM :ml_kem_512, :ml_kem_768, :ml_kem_1024 FIPS 203 ML-KEM. Standard SPKI public keys and PKCS#8 private keys.
Signature :ml_dsa_44, :ml_dsa_65, :ml_dsa_87 FIPS 204 ML-DSA. Standard SPKI public keys and PKCS#8 private keys.
Hybrid KEM :ml_kem_768_x25519_xwing ML-KEM-768 + X25519 hybrid KEM using the X-Wing construction.

Standard encodings use RFC 9935 OIDs for ML-KEM and RFC 9881 OIDs for ML-DSA. AlgorithmIdentifier.parameters are omitted, not encoded as NULL.

The pqc_container_* format is project-local and kept only for backward compatibility. It is not ASN.1, SPKI, or PKCS#8. It remains limited to the original algorithms:

  • :ml_kem_768
  • :ml_dsa_65
  • :ml_kem_768_x25519_xwing

Requirements

  • Ruby 3.1 or later
    • Ruby 3.4+ keeps the optimized Fiber Scheduler offload path via RB_NOGVL_OFFLOAD_SAFE
    • Ruby 3.1-3.3 use the compatibility no-GVL path without scheduler offload guarantees
  • a C toolchain with C11 support
  • OpenSSL 3.0 or later with SHA3-256 and SHAKE256 available
  • vendored minimal PQ Code Package native snapshot in ext/pqcrypto/vendor

Native backend

Version 0.5.0 moves ML-KEM and ML-DSA to PQ Code Package mlkem-native / mldsa-native sources. PQClean is no longer built and there is no runtime or build-time PQClean fallback. The repository and source gem ship a minimal vendor snapshot containing only the mlkem/ and mldsa/ source trees plus license/docs; upstream examples, tests, proofs, .git directories, and symlink-heavy trees are intentionally omitted. If the native vendor snapshot is missing, the extension build fails early.

From a source checkout, refresh the native vendor snapshot before compiling:

bundle exec rake vendor
bundle exec rake compile

The default build uses the portable native source path. Upstream native assembly can be tested explicitly with:

PQCRYPTO_NATIVE_ASM=1 bundle exec rake compile

Security status

pq_crypto is experimental and not audited. Treat it as a low-level primitive library, not a complete security protocol. See SECURITY.md for audit status, serialization caveats, hybrid-KEM notes, and interoperability warnings.

Useful entry points

PQCrypto.version
PQCrypto.backend
PQCrypto.supported_kems
PQCrypto.supported_signatures
PQCrypto.supported_hybrid_kems

PQCrypto::KEM.generate(:ml_kem_768)
PQCrypto::KEM.secret_key_from_seed(:ml_kem_768, seed_64_bytes)

PQCrypto::Signature.generate(:ml_dsa_65)
PQCrypto::Signature.secret_key_from_seed(:ml_dsa_65, seed_32_bytes)

PQCrypto::HybridKEM.generate(:ml_kem_768_x25519_xwing)
PQCrypto::Key.from_pem(pem, passphrase: passphrase)

More examples

Detailed usage examples live in GET_STARTED.md:

  • generating keys
  • ML-KEM encapsulation / decapsulation
  • ML-DSA signing / verification with optional FIPS 204 context
  • streaming ML-DSA for large files
  • SPKI, PKCS#8, encrypted PKCS#8, and auto-dispatch key loading
  • pqc_container_* compatibility serialization
  • native backend / vendoring notes
  • seed-aware keys, secure wiping, and practical safety notes