Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Implementation Status

This chapter is the honest matrix of what the reference implementation in konstruct-msg/construct-core (and the surrounding repositories) actually does today, distinct from what this specification requires a fully-conforming implementation to do.

It is the chapter readers should consult before relying on Konstruct for any specific threat model. Every line is grounded in a source-tree reference so it can be re-verified independently.

7.1 Component matrix

ComponentImplementation statusWhere it lives
X3DH classical handshakeImplemented, shipped in iOS TestFlight buildconstruct-core/src/crypto/handshake/x3dh.rs:417-:424
PQXDH (ML-KEM-768) extensionImplemented, opt-in via Suite 2 flag, shippedconstruct-core/src/crypto/pq_x3dh.rs:12-:19, src/crypto/messaging/double_ratchet/internals.rs:62-:99
Sparse continuous PQ ratchet (Suite 3)Implemented, capability-gated by supports_pq_ratchet; negotiated only when both peers advertise supportconstruct-core/src/crypto/suite_id.rs:28-:33; negotiation test src/crypto/client_api.rs:1082-:1152; wire section src/wire_payload.rs:76-:129
Double RatchetImplemented, including DH ratchet, skipped-key handling, AD v3 (with v2 fallback), and Suite 3 PQ epoch tagsconstruct-core/src/crypto/messaging/double_ratchet/messaging.rs:307-:332; internals.rs:533-:554
PKCS#7 length padding (mod 255)Implemented, constant-time unpadconstruct-core/src/traffic_protection/padding.rs:96-:126
Session healing queueImplemented, platform-persisted via orchestrator actionsconstruct-core/src/orchestration/healing_queue.rs:144-:210
ACK deduplication storeImplementedconstruct-core/src/orchestration/ack_store.rs:83-:143
PQ contribution store (deferred KEM ss)Implemented, CFE-backed and persisted via secure-store actionsconstruct-core/src/orchestration/pq_contribution.rs:200-:217, :360-:385
CFE binary envelope at FFIImplemented, used by iOS / macOS / Android bindingsconstruct-core/src/cfe/envelope.rs:8-:25, :48-:65
WirePayload binary frameImplemented, little-endian fixed header + Suite 3 PQ sectionconstruct-core/src/wire_payload.rs:7-:17, :76-:129
MLS group chat (RFC 9420)Core present (OpenMLS, ciphersuite MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519), no shipping product surface; design documented in Chapter 12, not yet a normative interop specconstruct-core/src/group/mls_store.rs:1-:39
Argon2id proof-of-workImplementedconstruct-core/src/pow.rs
Account recovery — BIP39 (12-word) + SLIP-39 social recoveryImplemented. BIP39 restores account access on a new device (recovery Ed25519 keypair, server holds only the public key); SLIP-39 threshold-restores the identity vault. See Chapter 11.construct-core/src/crypto/social_recovery.rs; BIP39/BIP32 derivation in construct-core
Privacy Pass token issuanceImplemented (feature-gated)construct-core/src/crypto/privacy_pass/mod.rs:94-:165; server issuance construct-server/identity-service/src/main.rs:942-:1057
Key transparencyPer-bundle inclusion proofs live; split-view detection not. The server maintains an append-only Merkle log and returns a Signed Tree Head + inclusion proof inline with every bundle (key-service/src/kt.rs, migrations 044/054); the client verifies inclusion + STH signature on receipt (KeyTransparencyVerifier). Missing: a public monitor endpoint, in-practice consistency checking, and STH gossip/auditing — so the current STH catches a self-contradicting server but not one that equivocates consistently across victims. Design + gap in Chapter 13.server key-service/src/kt.rs:172-:309; client construct-core/src/crypto/key_transparency.rs:273-:332, construct-ios Security/KeyTransparencyVerifier.swift:94-:134
ML-DSA-65 hybrid PQ signatures (Ed25519 + ML-DSA-65)Implemented, optional/capability-gated; invalid hybrid identity rejects, missing SPK-level hybrid attestation degrades to classical Ed25519 pathconstruct-core/src/crypto/suites/hybrid.rs:1-:51; server crates/construct-crypto/src/pqc/hybrid.rs:45-:65; client construct-ios Security/HybridBundleVerifier.swift:34-:120
Sealed senderImplemented and on by default. All outgoing user traffic — messages, delivery receipts, call signalling, and the session-control handshake (session_ready / tie-break ping / SESSION_RESET_INIT / END_SESSION) — is sealed. Ordinary sends use the dedicated SendSealedMessage path; some session-control paths still use legacy authenticated Envelope.sealed_sender, but omit the outer sender, conversation id, and real content type. Identified-downgrade paths (retries, seal-failure, in-scope control channel) are closed and fail-closed: stealth-on ⇒ an in-scope application send is sealed or queued, never emitted identified.server messaging-service/src/grpc.rs:333-:360, :701-:750, messaging-service/src/envelope.rs:140-:270; client policy construct-ios Services/StealthPolicy.swift:42; sealed RPC Networking/gRPC/Services/MessagingServiceClient.swift:203-:225; sealed control Services/Session/SessionCoordinator.swift:1208-:1312, MessagingServiceClient.swift:269-:351
Client IP minimisationImplemented — the server never stores a raw client IP; anti-abuse rate-limit keys and logs use a salted one-way hash (hash_client_ip) of the address. Honest limit: a salted hash of the small IPv4 space is not perfectly anonymous against a salt-holder.construct-utils/src/lib.rs:92; applied in construct-user-service/src/account.rs:140, construct-auth-service/src/devices.rs:292
Privacy Pass token enforcementWarn mode in production (MSG_STEALTH_TOKEN_POLICY=warn); tokens are issued, attached to sealed sends, and redemption-validated, but a failed/absent token does not block delivery. enforce is deferred past 1.0 (needs verifiable-VOPRF client + soak).construct-server/messaging-service/src/envelope.rs:188-:248; construct-core/src/crypto/privacy_pass/mod.rs:94-:165
Federation (S2S)Implemented — inbound + outbound sealed delivery, Ed25519-signed, per-origin rate-limited. Multi-node interoperability test outstanding.construct-server/messaging-service/src/federation.rs:135-:258, :291-:360
QUIC / HTTP-3 transportIn production as the engine-QUIC direct path; HTTP/2 fallback remains mandatory. Release builds use plain QUIC; Salamander-style per-datagram obfuscation is forced off outside DEBUG.construct-ios Utilities/Constants.swift:414-:456, Networking/gRPC/GRPCChannelManager.swift:474-:535; construct-engine/src/transport/mod.rs:50-:113, src/transport/connection.rs:60-:107
Direct P2P deliveryNot implemented. All traffic via server.
Formal verification (Kani / Prusti)Not started.
External cryptographic auditNot performed.

7.2 Platform matrix

PlatformBuild targetStatus
iOS deviceaarch64-apple-iosProduction-quality code, shipped via TestFlight beta. No public App Store release.
iOS simulatoraarch64-apple-ios-simBuilds and tests pass.
macOSaarch64-apple-darwin, x86_64-apple-darwinBuilds and runs; mid-migration from direct construct-core to a construct-engine-mediated path.
Androidaarch64-linux-android, armv7-linux-androideabi, x86_64-linux-androidconstruct-core cross-compiles cleanly; UniFFI bindings regenerated. No Kotlin VEIL surface yet (Phase 0).
Desktop (Linux / Windows)nativeCLI tools only; no application client.
Web (WASM)Planned, not started.

7.3 Open security issues

The table below lists residual risks that remain after the current code audit. It deliberately excludes items that have shipped since the older internal TODO list was written.

TagSeverityDescriptionTarget fix
BS-3HighIf no X25519 OPK is available at handshake time, the protocol falls back to 3-DH silently. Forward secrecy from the OPK contribution is lost; the user is not notified.Surface a warning to the application layer; consider hard-failing in Suite 2 when both OPK and ML-KEM-768 OPK are unavailable.
KT-1HighKey Transparency returns per-bundle inclusion proofs, but there is no public monitor endpoint, no in-practice consistency checking, and no STH gossip/auditor. A consistently equivocating server can still maintain a split view.Publish monitor/consistency API, persist and compare STHs, and add gossip/auditor path.
PQR-1MediumSuite 3 rekeys on a count of DH-ratchet turns with no time-based floor. A conversation that rarely changes direction can run indefinitely on a single ML-KEM epoch, and one that never alternates never rekeys at all — the condition Suite 3 exists to avoid. Both other deployed continuing designs bound this: Apple PQ3 guarantees a rekey at least every 7 days, Signal SPQR is continuous. See Appendix B §B.3.Add a wall-clock floor alongside the turn counter, and start an exchange when either trips.
PQR-2MediumEvery message key in a Suite 3 epoch is derived from the same pq_epoch_secret; the post-quantum component does not ratchet between rekeys. Forward secrecy therefore has message granularity classically and epoch granularity post-quantum. Signal SPQR carries a symmetric chain inside its PQ component and does not have this asymmetry. See Appendix B §B.6.Ratchet the epoch secret per message (or per chain step) rather than storing it as a constant.
PQR-3LowThe ML-KEM-768 encapsulation key (1184 B) and ciphertext (1088 B) are carried whole and re-attached to every outgoing frame until implicitly acknowledged, so an unacknowledged exchange costs that much per message for its duration. Signal SPQR spreads both across Reed–Solomon-coded chunks instead, bounding per-message overhead.Chunk the objects with a systematic erasure code, or bound re-attachment by a retry schedule.
PQR-4LowPQ_EPOCH_RETENTION = 4 completed epoch secrets are kept, while the skipped-message-key tolerance is 1000. A delivery reordered past four epochs is a hard decrypt error by design (no silent downgrade), so the two tolerances are set three orders of magnitude apart without a stated reason.Justify the bound against observed reordering depth, or raise it to match the skipped-key window.
SEC-006MediumThe AD v2 → v3 graceful migration uses a fallback decrypt path. Once no v2 messages can be in flight, the fallback SHOULD be removed.Remove AD_VERSION_PREV fallback after the in-flight window passes.
SEC-009LowSession JSON (containing dh_ratchet_private, RK, chain keys) is stored in the platform key store but without an additional encryption-at-rest layer. If the OS key store is compromised, an attacker reads the session state.Add wrap-with-master-key at the session-export boundary.

Items listed as "Out of scope" in Chapter 1 §1.2 are NOT on this list — they are not bugs, they are explicit non-goals.

7.4 Test coverage

The reference includes:

Test suiteScope
Unit tests (cargo test)Per-module: KDF labels, AD construction, padding edge cases, wire-payload round-trips, ratchet step invariants.
Integration tests (tests/)Cross-module: full X3DH handshake + first message exchange; PQ contribution apply; session healing round-trip; CFE envelope corner cases.
Cross-platform fixture testsiOS bridging-header parity, UniFFI binding generation.
Property / fuzz testsWirePayload decoder fuzz target (no panic on arbitrary bytes).
Cross-reference vectorsCryptographic library outputs cross-checked against published test vectors (NIST FIPS 203 for ML-KEM, RFC 8032 for Ed25519).

What is not covered today:

  • Full product-level multi-device interoperability coverage across all sealed-sender, sender-sync, and Suite 3 cases.
  • Multi-node (two-VPS) federation interoperability test — federation is implemented with contract-level tests, but the two-server integration test is outstanding.
  • Formal verification (planned, not done).
  • Adversarial / red-team testing by an external party.

7.5 Reproducibility

The reference is built from the commit indicated in the version metadata of the released artefact. To reproduce a build:

git clone https://github.com/konstruct-msg/construct-core
cd construct-core
# iOS staticlib:
./build_crypto_lib.sh --all     # see construct-ios repo for the wrapper
# Android shared library:
cd ../construct-android
./build_crypto_lib.sh --all

The Cargo.lock checked into the repository pins every transitive dependency, so two builds from the same commit will produce binaries that differ only in compiler-version-dependent ways (debug info, timestamp markers).

7.6 Versioning policy

This specification follows Semantic Versioning at the document level:

  • MAJOR — a wire-incompatible protocol change.
  • MINOR — a backwards-compatible normative addition (new field, new optional behaviour).
  • PATCH — editorial corrections that do not change implementer obligations.

The implementation's own versioning is separate; see the construct-core Cargo.toml for the crate version.

7.7 References

  • Open-issue tracker (internal): construct-core/TODO.md.
  • Disclosure & contact: Disclosure.
  • Document changelog: Changelog.