pqtransport logopqtransport

Pure-Dart post-quantum transport

Hybrid TLS 1.3 (RFC 10024), encrypted UDP, DNS/DoH/DoT, mDNS, QUIC, and HTTP/1.1–3. Cryptography is pqforge. Infrastructure is swissarmyknife. Zero FFI.

RFC 10024 hybrid concatenation for X25519MLKEM768

pqtransport is the protocol layer of the TurkanaNation post-quantum stack. It speaks UDP, TLS 1.3 hybrid key exchange, DNS / DoH / DoT, mDNS, QUIC frames, and HTTP/1.1–3. Cryptography is exclusively package:pqforge. Infrastructure is exclusively package:swissarmyknife. There is no dart:ffi and no platform TLS (SecureSocket) on the PQ path.

v0.1.0 is a self-interop vertical slice. 174 tests pass, 90.7% line coverage of `lib/`, `dart analyze` clean. Live handshake is **all three RFC 10024 groups**. RFC 8446-shaped hellos (IANA `0x1302` SHA-384 default, `0x1303` ChaCha). Not OpenSSL interop. Not a FIPS 140 module.

pub.dev
version
Wiki
CI
Pages
CodeQL

RFC 10024
X25519MLKEM768
NIST groups
CMVP
OpenSSL
runtime

import 'package:pqtransport/pqtransport.dart';

final crypto = PqTransportCrypto();
final identity = PqTlsServerIdentity.generate(crypto);
final (a, b) = MemoryByteSocket.pair();
final client = PqTlsSocket.client(a, crypto: crypto);
final server = PqTlsSocket.server(b, crypto: crypto, identity: identity);
await Future.wait([server.handshake(), client.handshake()]);
final key = client.exporter('app', Uint8List(0), 32);

Signal#

GateValue
Version0.1.0
SDK>=3.12.0 <4.0.0
Tests153 passed
Line coverage90.7% of lib/
Hybrid groups3 RFC 10024 codecs + live KEX
Live KEXX25519, P-256, P-384
FFInone
Platform TLS on PQ pathnone

Hybrid groups (RFC 10024)#

Concatenation order is group-dependent. X25519MLKEM768 does not follow RFC 9954 naming order. ML-KEM is first on the wire. NIST-curve groups put ECDHE first. Concat uses concatenateSharedSecrets; PqForgeCombiner.combine() (always classical then PQ) is not on this path.

GroupCodepointClientServerSSOrderLive
X25519MLKEM768 0x11EC 1216 1120 64 ML-KEM then X25519 Yes
SecP256r1MLKEM768 0x11EB 1249 1153 64 ECDHE then ML-KEM Yes (balanced)
SecP384r1MLKEM1024 0x11ED 1665 1665 80 ECDHE then ML-KEM Yes (maximum)

P-256 / P-384 ECDH is live via pqforge 0.4.4. Profile/group mismatches fail closed (requireGroup) rather than silently dropping to classical. See Hybrid Groups and Claim Boundary.

The shape#

LayerWhat it gives you
Core HybridGroup , requireLength , Transcript , PqTransportCrypto , every protocol size in lengths.dart
UDP AES-256-GCM datagrams, replay before AEAD, Throttler, encrypted session (all three groups)
TLS 1.3 swissarmyknife StateMachine , RFC 8446 hellos, IANA 0x1302 / 0x1303 , ML-DSA-65 CertificateVerify, exporter
DNSA/AAAA/CNAME/MX/TXT/SRV/CAA/HTTPS/SVCB/OPT/PTR/NS, CircuitBreaker, TTL Cache
mDNSProbe / announce / browse, optional ML-DSA-65 TXT
QUIC / HTTP 1-RTT packet protect, CRYPTO/STREAM frames, HTTP/1.1 over PqTlsSocket

Family#

application  (HTTP, DNS, mDNS, QUIC frames)
     │
pqtransport  — this package. Protocol. No primitives.
     │
pqforge      — ML-KEM, ML-DSA, X25519, P-256/P-384 ECDH, AES-256-GCM, ChaCha, HKDF
     │
pqcrypto     — FIPS 203/204/205 primitives + KAT evidence

swissarmyknife supplies Result, StateMachine, Cache, CircuitBreaker, and Throttler. Read Sister packages.

Do not overclaim#

This layer may not invent a stronger claim than pqcrypto / pqforge.

  • Not a FIPS 140 module. No CMVP listing.
  • Best-effort side-channel posture in Dart. Best-effort zeroization.
  • RFC 10024-aligned hybrid encoding with unit-tested concatenation — not "interoperable with OpenSSL."
  • Live KEX in 0.1.0 is all three RFC 10024 groups.
  • TLS default suite is IANA TLS_AES_256_GCM_SHA384 (0x1302, SHA-384). 0x1303 (ChaCha + SHA-256) is offered and completes on dart2js. Private-use 0xFF00 is retired.

Full wording: Claim Boundary.

Start#

dependencies:
  pqtransport: ^0.1.0
  pqforge: ^0.4.5
  swissarmyknife: ^0.1.0

Then read Getting Started, the API Guide, and keep the Cookbook nearby. Canonical markdown lives in doc/INDEX.md.