{"id":50486532,"url":"https://github.com/systemslibrarian/xwing-kem","last_synced_at":"2026-06-01T23:00:30.044Z","repository":{"id":361931558,"uuid":"1256464595","full_name":"systemslibrarian/xwing-kem","owner":"systemslibrarian","description":"X-Wing hybrid KEM (X25519 + ML-KEM-768) for Python — correct implementation of draft-connolly-cfrg-xwing-kem","archived":false,"fork":false,"pushed_at":"2026-06-01T21:23:07.000Z","size":68,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-01T22:25:36.875Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/systemslibrarian.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-01T20:00:24.000Z","updated_at":"2026-06-01T21:22:58.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/systemslibrarian/xwing-kem","commit_stats":null,"previous_names":["systemslibrarian/xwing-kem"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/systemslibrarian/xwing-kem","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fxwing-kem","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fxwing-kem/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fxwing-kem/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fxwing-kem/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/systemslibrarian","download_url":"https://codeload.github.com/systemslibrarian/xwing-kem/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fxwing-kem/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33797128,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-01T23:00:25.079Z","updated_at":"2026-06-01T23:00:30.034Z","avatar_url":"https://github.com/systemslibrarian.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# xwing-kem\n\n**The X-Wing hybrid post-quantum KEM (X25519 + ML-KEM-768) for Python.**\n\n[![CI](https://github.com/systemslibrarian/xwing-kem/actions/workflows/ci.yml/badge.svg)](https://github.com/systemslibrarian/xwing-kem/actions/workflows/ci.yml)\n[![PyPI](https://img.shields.io/pypi/v/xwing-kem.svg)](https://pypi.org/project/xwing-kem/)\n[![Python](https://img.shields.io/pypi/pyversions/xwing-kem.svg)](https://pypi.org/project/xwing-kem/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/systemslibrarian/xwing-kem/blob/main/LICENSE)\n\n`xwing-kem` is a single, drop-in key-encapsulation mechanism that stays secure\nas long as **either** classical X25519 **or** post-quantum ML-KEM-768 holds. It\nimplements [draft-connolly-cfrg-xwing-kem](https://datatracker.ietf.org/doc/draft-connolly-cfrg-xwing-kem/)\nfaithfully, so you get the vetted hybrid construction without ever hand-rolling\na combiner — the single most common (and dangerous) post-quantum migration bug.\n\n\u003e ### ⚠️ Pre-1.0 — please read before production use\n\u003e\n\u003e `xwing-kem` is **validated against all three official X-Wing Known-Answer-Test\n\u003e (KAT) vectors** from the draft: key generation from seed and the SHA3-256\n\u003e combiner are checked **byte-for-byte**, and derandomized encapsulation is\n\u003e verified against the draft's **reference implementation**.\n\u003e\n\u003e Honest limits that still apply: no ML-KEM backend exposes *seeded*\n\u003e encapsulation, so the library's own randomized `encapsulate()` is validated\n\u003e **transitively** (round-trip + keygen KAT + combiner KAT + reference-encaps\n\u003e KAT), not by a direct ciphertext-byte match; constant-time guarantees come\n\u003e only from the C-backend primitives, **not** the Python glue; and secret keys\n\u003e are **not portable** between backends. The full, candid accounting is in\n\u003e **[KNOWN-GAPS.md](https://github.com/systemslibrarian/xwing-kem/blob/main/KNOWN-GAPS.md)**.\n\n---\n\n## Contents\n\n- [Key Features](#key-features)\n- [Quick Start](#quick-start)\n- [Installation](#installation)\n- [When to Use X-Wing](#when-to-use-x-wing)\n- [Why X-Wing?](#why-x-wing)\n- [The X-Wing Construction](#the-x-wing-construction)\n- [Backend Selection](#backend-selection)\n- [Performance](#performance)\n- [Validation \u0026 Limitations](#validation--limitations)\n- [Design Notes](#design-notes)\n- [Contributing \u0026 Security](#contributing--security)\n- [License](#license)\n\n## Key Features\n\n- 🛡️ **Hybrid by construction** — secure unless an attacker breaks *both*\n  X25519 *and* ML-KEM-768.\n- 🎯 **Concrete, not generic** — algorithms, combiner (SHA3-256), and security\n  level (NIST PQC level 1) are all fixed. Nothing to misconfigure.\n- 🔌 **Two real backends, auto-selected** — native `cryptography` preferred,\n  with a `liboqs` fallback. No simulated math.\n- ⚡ **Inherits native speed** — sits *above* the primitives, so it gets faster\n  the moment your platform ships native ML-KEM.\n- ✅ **KAT-validated** — checked byte-for-byte against the official draft\n  vectors (see the status note above).\n- 🧩 **Consistent, predictable API** — functional and class forms return values\n  in the same order; fixed 1216-byte public keys, 1120-byte ciphertexts, and a\n  32-byte shared secret.\n- 🪶 **Narrow, auditable scope** — X-Wing only, MIT-licensed.\n\n## Quick Start\n\nBoth APIs return values in the **same order** — `encapsulate()` gives you\n`(shared_secret, ciphertext)`.\n\n**Functional API:**\n\n```python\nfrom xwing_kem import generate_keypair, encapsulate, decapsulate\n\nkp = generate_keypair()                                  # kp.public_key, kp.secret_key\nshared_sender, ciphertext = encapsulate(kp.public_key)\nshared_recipient = decapsulate(ciphertext, kp.secret_key)\n\nassert shared_sender == shared_recipient                 # 32-byte shared secret\n```\n\n**Class-based API:**\n\n```python\nfrom xwing_kem import XWing\n\nkem = XWing()\npublic_key, secret_key = kem.generate_keypair()\nshared_sender, ciphertext = kem.encapsulate(public_key)\nshared_recipient = kem.decapsulate(ciphertext, secret_key)\n\nassert shared_sender == shared_recipient\n```\n\nThe only difference between the two forms is how the key pair is handed back:\nthe functional `generate_keypair()` returns a small `XWingKeyPair` object\n(`.public_key` / `.secret_key`), while `XWing.generate_keypair()` returns a\nplain `(public_key, secret_key)` tuple. Pick whichever reads better for you.\n\nMore runnable scripts live in\n[`examples/`](https://github.com/systemslibrarian/xwing-kem/tree/main/examples).\n\n## Installation\n\n```bash\npip install xwing-kem\n```\n\nThat's it — the library auto-detects an ML-KEM backend at import time, so most\nusers need nothing further. ML-KEM-768 is provided natively by `cryptography\u003e=48`\nwhen its wheel is built against OpenSSL 3.5+, AWS-LC, or BoringSSL. If your\nplatform's wheel lacks post-quantum support, install the optional `liboqs`\nfallback backend:\n\n```bash\npip install \"xwing-kem[liboqs]\"   # requires liboqs.so on the system\n```\n\nSee [Backend Selection](#backend-selection) to inspect or pin the active choice.\n\n## When to Use X-Wing\n\n**Reach for X-Wing when:**\n\n- You're adding **post-quantum protection to key exchange** and want\n  defense-in-depth — security that holds if *either* the classical *or* the\n  post-quantum component is later broken.\n- You want a **standards-track, opinionated** construction with no knobs to\n  tune, suitable for HPKE-style sealing, secure messaging, or wrapping data\n  keys.\n- You'd otherwise be tempted to **glue X25519 and ML-KEM together yourself** —\n  this library is exactly that glue, done to spec.\n\n**Look elsewhere when:**\n\n- You need a **bare ML-KEM or bare X25519** KEM (use `cryptography` or `liboqs`\n  directly).\n- You need **signatures or an authenticated KEM** — out of scope here.\n- You require **certified constant-time guarantees across the whole stack**;\n  the Python combiner layer offers no timing guarantee (see\n  [Validation \u0026 Limitations](#validation--limitations)).\n\n## Why X-Wing?\n\nMigrating to post-quantum cryptography, you almost never want a *raw* KEM — you\nwant a **hybrid** that survives the failure of either half. The dangerous part\nis the combiner that mixes the two shared secrets; a hand-rolled one is the\nclassic PQ-migration footgun, and getting the byte order or omitted inputs\nwrong silently produces incompatible or insecure secrets.\n\nX-Wing removes that risk by being **opinionated and concrete**:\n\n- **No parameters.** The constituent algorithms (X25519 + ML-KEM-768), the\n  combiner hash (SHA3-256), and the security target are all fixed by the spec.\n- **Belt-and-suspenders security.** An attacker must defeat *both* a\n  well-studied elliptic curve *and* a NIST-standardized lattice KEM.\n- **One obvious API.** `generate_keypair` / `encapsulate` / `decapsulate`, fixed\n  lengths, a 32-byte secret — easy to wire into HPKE, TLS-like handshakes, or\n  file/message encryption.\n\nThis library exists so you can adopt the vetted construction instead of writing\nthe combiner yourself.\n\n## The X-Wing Construction\n\nThe 32-byte shared secret is the SHA3-256 hash of the two component secrets, the\nX25519 ciphertext and public key, and a fixed label:\n\n```text\nss = SHA3-256( ss_M || ss_X || ct_X || pk_X || XWING_LABEL )\n```\n\n| Symbol        | Meaning                                            | Size |\n| ------------- | -------------------------------------------------- | ---- |\n| `ss_M`        | ML-KEM-768 shared secret                           | 32 B |\n| `ss_X`        | X25519 raw shared secret                           | 32 B |\n| `ct_X`        | X25519 ciphertext (the ephemeral public key)       | 32 B |\n| `pk_X`        | recipient's X25519 public key                      | 32 B |\n| `XWING_LABEL` | the 6-byte X-Wing sigil, appended **last**         |  6 B |\n\nThe ML-KEM ciphertext `ct_M` is **deliberately omitted** from the hash:\nML-KEM-768 is ciphertext-collision-resistant, so mixing it in is unnecessary,\nand leaving it out is exactly what gives X-Wing its performance edge over a\ngeneric combiner.\n\n## Backend Selection\n\n**By default, no choice is required.** The library auto-selects a backend at\nfirst use — native `cryptography` first, then `liboqs` — and caches it. You can\ninspect the active choice or pin it explicitly:\n\n```python\nimport xwing_kem\nfrom xwing_kem import generate_keypair, XWing\n\n# Which backend is active right now?\nprint(xwing_kem.active_backend())            # 'cryptography' or 'liboqs'\n\n# Force a specific backend for a single call...\nkp = generate_keypair(prefer_backend=\"liboqs\")\n\n# ...or for every operation on an object-style instance:\nkem = XWing(prefer_backend=\"cryptography\")\nprint(kem.backend_name)                      # 'cryptography'\npublic_key, secret_key = kem.generate_keypair()\n```\n\n`prefer_backend` accepts `\"cryptography\"`, `\"liboqs\"`, or `None` (auto). An\nunavailable choice **raises** rather than silently falling back, so pinning is\nalways explicit and predictable.\n\n## Performance\n\n`xwing-kem` is intentionally a thin, correct layer over the primitives — all the\nheavy lattice and curve math runs in vetted **C** inside the chosen backend, not\nin Python. That has two practical consequences:\n\n1. **It inherits native speed.** As native ML-KEM lands in `cryptography` /\n   OpenSSL, this package gets faster automatically — no code change on your side.\n2. **The construction itself is lean.** By omitting the ML-KEM ciphertext from\n   the combiner, X-Wing avoids extra hashing that a generic combiner would incur.\n\nIndicative single-thread timings (median of 300 runs, `cryptography` backend,\nPython 3.12, x86-64), compared against **pure X25519** used KEM-style (ephemeral\nkeygen + DH for \"encapsulate\", DH for \"decapsulate\"):\n\n| Operation     | X-Wing  | Pure X25519 | Overhead |\n| ------------- | ------: | ----------: | -------: |\n| keygen        | ~240 µs |      ~51 µs |     4.7× |\n| encapsulate   | ~145 µs |     ~117 µs |     1.2× |\n| decapsulate   | ~294 µs |      ~54 µs |     5.5× |\n\n**Takeaway:** full post-quantum protection costs roughly **2–6× a bare X25519\nexchange**, yet every operation still completes in **well under a millisecond**.\nEncapsulation is nearly free relative to X25519, because ML-KEM encapsulation is\nfast and X-Wing layers only a single curve operation on top. Numbers vary by\nmachine, Python version, and backend.\n\n## Validation \u0026 Limitations\n\nThis project follows an honest-documentation discipline. The short version:\n\n- ✅ **KAT-validated.** Key generation from seed and the SHA3-256 combiner are\n  checked **byte-for-byte** against all three official draft vectors;\n  derandomized encapsulation is verified against the reference implementation.\n- ⚠️ **Randomized `encapsulate()` is validated transitively.** No backend\n  exposes seeded encapsulation, so it is covered by round-trip + keygen KAT +\n  combiner KAT + reference-encaps KAT rather than a direct ciphertext-byte match.\n- ⚠️ **Constant-time only in the C primitives.** The Python combiner glue does\n  no secret-dependent branching, but Python offers no timing guarantees — don't\n  rely on this layer in a hostile co-located environment.\n- ⚠️ **Secret keys are not portable between backends** (`cryptography` stores\n  the 64-byte seed form; `liboqs` the expanded form).\n\nThe complete accounting lives in\n**[KNOWN-GAPS.md](https://github.com/systemslibrarian/xwing-kem/blob/main/KNOWN-GAPS.md)**.\nPlease read it before depending on this in production.\n\n## Design Notes\n\n- **Future-proof by position.** This package sits *above* the primitives, so it\n  inherits faster/native ML-KEM the moment your wheel has it.\n- **No simulated cryptography.** Both backends use real, vetted C implementations.\n- **Deliberately narrow scope.** X-Wing only — no ML-KEM-1024 variant, no\n  authenticated KEM, no signatures, no HPKE/TLS wiring.\n\n## Contributing \u0026 Security\n\nContributions are welcome — see\n[CONTRIBUTING.md](https://github.com/systemslibrarian/xwing-kem/blob/main/CONTRIBUTING.md).\nFor vulnerability reports and the disclosure process, see\n[SECURITY.md](https://github.com/systemslibrarian/xwing-kem/blob/main/SECURITY.md).\n\n## License\n\n[MIT](https://github.com/systemslibrarian/xwing-kem/blob/main/LICENSE).\n\n---\n\nX-Wing is the work of the IETF CFRG draft authors; this package is just a\nfaithful, well-tested Python home for it. If it helps you ship post-quantum\nprotection with a little more confidence, it's doing its job — issues and\nimprovements are always welcome.\n\n*Soli Deo Gloria — 1 Corinthians 10:31.*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsystemslibrarian%2Fxwing-kem","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsystemslibrarian%2Fxwing-kem","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsystemslibrarian%2Fxwing-kem/lists"}