-
Notifications
You must be signed in to change notification settings - Fork 3
Serverpod Integration
Because pqcrypto is pure Dart, it naturally bridges the gap between Flutter clients and Dart backends like Serverpod.
This guide illustrates a highly secure, post-quantum handshake architecture combining our ML-KEM-768 and ML-DSA-65 algorithms with Serverpod.
In enterprise deployments, post-quantum algorithms should always be paired with classical algorithms (like X25519) to ensure hybrid security.
- Client Identity & Key Material: The Flutter client generates an ephemeral X25519 key and holds an ML-DSA-65 identity key.
- Server Identity: The Serverpod backend holds a long-term ML-KEM-768 key and an ML-DSA-65 signing key, rotated via a KMS/HSM.
- Encapsulation: The client encapsulates a shared secret to the server's ML-KEM public key.
- Transcript Binding: The client binds the classical material, the ML-KEM ciphertext, nonces, and timestamps into a canonical transcript.
- Authentication: The client signs this transcript using its ML-DSA-65 key.
-
Verification & Derivation: The server verifies the signature, decapsulates the ML-KEM secret, and derives a final session key using HKDF (
ss_classical || ss_lattice).
To securely pass this data over the network, you must enforce strict byte length constraints before any cryptographic operations. In Serverpod, define your payloads in .spy.yaml files:
class: PqcHandshakeRequest
fields:
keyId: String
clientNonce: ByteData
clientTimestampMs: int
clientX25519PublicKey: ByteData
mlKem768Ciphertext: ByteData
clientMlDsa65PublicKey: ByteData
clientSignature: ByteData
transcriptHash: ByteDataIn your Endpoint, validate the exact lengths of the incoming buffers. Do not attempt to decode or process malformed byte arrays:
_requireLength(ciphertext, 1088, 'mlKem768Ciphertext');
_requireLength(clientDsaPublicKey, 1952, 'clientMlDsa65PublicKey');
_requireLength(clientSignature, 3309, 'clientSignature');You must also enforce replay defenses (tracking clientNonce in Redis) and a strict timestamp window (e.g., 2000 ms) before running kem.decapsulate().
Cryptographic operations like ML-KEM encapsulation and ML-DSA signing are CPU-intensive. In a Flutter application, these must be offloaded from the UI isolate to prevent frame drops.
final output = await compute(
buildPqcHandshakeRequest,
ClientHandshakeInput(
// ... Pass public keys and nonces
),
);Note on Flutter Web: The
compute()function does not currently spawn a separate thread in Dart Web. On web targets, execution will block the main thread.
For a complete, copy-pasteable implementation sketch of the Serverpod Endpoint, Key Manager, and Flutter Client Service, please view the canonical SERVERPOD_FLUTTER_GUIDE.md in the repository docs.
pqcrypto — pure Dart, zero-dependency post-quantum cryptography (ML-KEM FIPS 203 · ML-DSA FIPS 204) for Dart, Flutter, and the web · MIT License · pub.dev · Repository · Documentation Index
Algorithm/KAT-conformance and interoperability evidence — not a CMVP/FIPS 140 module validation.
pqcrypto Wiki
Getting started
Algorithms
Design & internals
Assurance
Integration
Project
Links