Blind Drops Protocol
Post-quantum encrypted CSR transport for zero-knowledge certificate requests.
Problem
Traditional certificate enrollment requires a pre-existing trust relationship. The user must already have a way to securely transmit their CSR to the CA. In many environments — especially air-gapped or high-security contexts — this chicken-and-egg problem is solved manually (USB sticks, in-person delivery).
Blind Drops solve this: they let a user encrypt a CSR so that only the Authority can read it, even if every relay in between is compromised.
Design Goals
- Post-Quantum Security — Resistant to quantum computing attacks via Kyber-1024 (ML-KEM).
- Zero Trust — The relay (Spirit/Connect) cannot decrypt or inspect the CSR.
- Forward Secrecy — Each drop uses an ephemeral shared secret. Compromising one drop reveals nothing about others.
- Bidirectional — The Authority can encrypt the signed certificate back to the client using the same shared secret.
Protocol Flow
Step 1: Client Creates Drop (Passport)
- Passport loads the Authority's Kyber-1024 public key (
transport.pub). - Passport calls
Encapsulate()on the public key, producing:- A ciphertext (1568 bytes) — only the Authority's private key can decode this.
- A shared secret (32 bytes) — known to both sides after decapsulation.
- The shared secret is fed into Blake2b-256 to derive a 256-bit AES key.
- The CSR is encrypted with AES-256-GCM using a random 12-byte nonce.
- The drop file is assembled:
[Header: "TRINITY-DROP-V1\n"] || [Kyber Ciphertext] || [Nonce] || [Encrypted CSR] - The shared secret is saved to the Passport vault (needed to decrypt the response later).
Step 2: Drop is Relayed
The encrypted drop file is transmitted to the Authority via any channel:
- Cloud — Base64-encoded and submitted to Spirit/Connect via the API.
- Manual — Copied to a USB stick, emailed, or printed as a QR code.
Zero Knowledge: The relay stores the encrypted blob verbatim. It has no way to decrypt, inspect, or modify the CSR.
Step 3: Authority Unpacks Drop
- The Authority loads its Kyber-1024 private key (
transport.key). - It calls
Decapsulate()on the ciphertext to recover the shared secret. - The shared secret is fed into Blake2b-256 to derive the AES key.
- The encrypted CSR is decrypted with AES-256-GCM.
- The Authority reviews and signs the CSR, producing a certificate.
Step 4: Authority Seals Response
- Using the same shared secret (recovered from decapsulation), the Authority:
- Derives a new AES key (Blake2b-256 of the shared secret).
- Encrypts the signed certificate with AES-256-GCM and a new random nonce.
- The encrypted response is sent back through the same relay channel.
Step 5: Client Imports Response (Passport)
- Passport retrieves the saved shared secret from its vault.
- It derives the AES key and decrypts the response.
- The signed certificate is imported into the identity.
- The shared secret is permanently deleted from the vault.
Drop File Format
| Offset | Length | Field |
|---|---|---|
| 0 | 16 | Header (TRINITY-DROP-V1\n) |
| 16 | 1568 | Kyber-1024 Ciphertext |
| 1584 | 12 | AES-GCM Nonce |
| 1596 | Variable | Encrypted CSR (AES-256-GCM) |
Cryptographic Primitives
| Step | Algorithm | Purpose |
|---|---|---|
| Key Exchange | Kyber-1024 (ML-KEM) | Post-quantum key encapsulation |
| Key Derivation | Blake2b-256 | Shared secret → AES key |
| Encryption | AES-256-GCM | Authenticated encryption of CSR/certificate |
Security Properties
- Post-Quantum Resistance — Kyber-1024 is NIST's selected standard for post-quantum key encapsulation (FIPS 203).
- Forward Secrecy — Each drop uses a fresh encapsulation. No long-term session keys.
- Authenticated Encryption — AES-GCM provides both confidentiality and integrity.
- Relay Blindness — The relay has zero knowledge of the encrypted content.
- Secret Destruction — The shared secret is deleted after successful import.
Breaking Change: The upgrade from Kyber-768 to Kyber-1024 means old
transport.pub / transport.key files generated with Kyber-768 are incompatible. Re-run trinity init to generate new keys.