Security Architecture
This page describes how requests reach Qpher's services, where private keys are used and stored, how tenants are separated, and what happens when a component fails.
Private keys are generated and used only inside the isolated key service (KMS-Orchestrator); API requests pass a policy engine that fails closed.
Service Diagramâ
Qpher uses a microservices architecture. Calls between Qpher services also go over HTTPS and are authenticated with a Google-signed identity token checked by Cloud Run, a Qpher service token, or both.
The KMS-Orchestrator is the service that loads private keys. The API Gateway routes KEM, signature and key-management calls to it. Qpher Vault and Qpher Legacy requests are authorized by vault-backend, which calls the KMS-Orchestrator directly, not through the API Gateway. The KMS-Orchestrator returns the results of operations â ciphertexts, plaintexts, signatures, shared secrets and unwrapped keys â never a private key.
Gateway Auth Pipelineâ
Every API request passes through a 7-stage authentication and authorization pipeline before reaching any backend service.
| Stage | What Happens | On Failure |
|---|---|---|
| 1. Skip check | The health endpoint, public sign-in and sign-up endpoints, and webhooks (verified separately) skip API-key authentication | -- |
| 2. Extract API key | Read the x-api-key header | 401 Missing API key |
| 3. Resolve tenant | Hash the key and look up the tenant | 401 Invalid API key |
| 4. Inject context | Attach X-Tenant-ID and X-Request-ID headers | -- |
| 5. Rate limit | Check per-tenant rate limits via Redis | 429 Rate limit exceeded |
| 6. Policy check | Evaluate access rules in the Policy Engine | 403 Access denied |
| 7. Route | Forward the request to the appropriate service | -- |
Every request that carries an API key passes all seven stages before it reaches a backend service.
Private Keys Are Used Only Inside the KMS-Orchestratorâ
The most important security boundary in Qpher is the KMS-Orchestrator, the isolated key service:
- Private keys are generated inside the KMS-Orchestrator, and no API returns them.
- In production, each private key is encrypted by a key held in Google Cloud KMS before it is stored (see Encryption at Rest).
- The database stores a handle (a reference path), not the key bytes themselves.
- There is no API endpoint to export or download a private key.
When you call /kem/decrypt or /signature/sign, the API Gateway forwards your request to the KMS-Orchestrator, which loads the private key, performs the operation, and returns only the result.
Tenant Isolationâ
Qpher is a multi-tenant platform. Each customer gets a separate tenant, isolated at four layers: repository filtering, database constraints, request context and gateway enforcement.
- Repository layer -- Every database query includes a
tenant_idfilter. - Database constraints -- Unique indexes are scoped to
(tenant_id, ...), preventing data collisions between tenants. - Context propagation -- The gateway injects
X-Tenant-IDinto every downstream request. Services never derive the tenant ID from user input. - Gateway enforcement -- The API key lookup determines the tenant. A tenant can only access resources associated with their own API key.
Fail-Closed Designâ
Qpher follows a fail-closed philosophy: when something goes wrong, the system denies access rather than allowing it.
| Scenario | Behavior |
|---|---|
| Policy Engine is unavailable | API requests are denied (503) |
| Tenant lookup fails | Request is rejected (401 for an unknown key, 503 if the Tenant Service cannot be reached) |
| Rate-limit store (Redis) is unavailable | The gateway counts requests per instance, with each limit divided by the number of instances, until Redis returns |
| Missing configuration at startup | Service refuses to start |
| PQC cryptographic operation fails | Error is returned, never falls back to weaker crypto |
This approach means a brief outage can block API requests rather than let them through unchecked.
Cryptographic Foundation â Open Quantum Safeâ
Qpher uses liboqs (Open Quantum Safe) for its post-quantum algorithms. Qpher does not implement post-quantum primitives from scratch; it builds on the Open Quantum Safe project's open-source library.
| Component | Role |
|---|---|
| liboqs (C library) | Post-quantum algorithms: ML-KEM (FIPS 203), ML-DSA (FIPS 204) and SLH-DSA (FIPS 205) |
| liboqs-python | Python bindings used by the KMS-Orchestrator |
| Validation | We implement NIST FIPS 203, 204 and 205; our cryptographic module has not been validated by NIST's CMVP. As of June 2026 the CMVP-validated AWS-LC 3 module (#5298) covers ML-KEM but not ML-DSA. |
Rolling your own cryptography is one of the most common security anti-patterns, so Qpher uses the Open Quantum Safe implementations instead of writing its own.
The liboqs version used in production is pinned and recorded in every Docker image build. The full list of open-source libraries Qpher depends on is published at qpher.ai/legal/open-source.
Hybrid PQC + Classical Cryptographyâ
Qpher supports two cryptographic modes, giving customers the choice based on their risk tolerance and compliance requirements.
Two Kinds of "Hybrid"â
The term "hybrid" appears in two different contexts in post-quantum cryptography. It is important to understand the distinction:
| Term | What It Means | In Qpher |
|---|---|---|
| KEM-DEM hybrid | Kyber768 (KEM) + AES-256-GCM (DEM) â combining a PQC key exchange with a symmetric cipher for payload encryption | Every /kem/encrypt call |
| PQC + classical hybrid | Combining a PQC algorithm with a traditional algorithm (e.g., X25519 + Kyber768) so that security holds even if one algorithm is broken | Opt-in: algorithm: "X-Wing" or "Composite-ML-DSA" |
Qpher's server-side encryption (/kem/encrypt) is KEM-DEM hybrid (see KEM-DEM Hybrid Encryption): each call combines the KEM (ML-KEM-768 by default) with AES-256-GCM.
PQC + Classical Hybrid Modeâ
Hybrid PQC + classical algorithms provide defense-in-depth by combining a PQC algorithm
with a battle-tested classical algorithm. Add "algorithm": "X-Wing" or
"algorithm": "Composite-ML-DSA" to your API requests. Omitting the parameter defaults
to PQC-only mode.
Qpher offers hybrid mode that combines PQC algorithms with classical algorithms for defense-in-depth. It is opt-in:
| Operation | PQC-Only (default) | Hybrid (opt-in) |
|---|---|---|
| KEM | ML-KEM-768 (Kyber768) | X-Wing: X25519 + ML-KEM-768 |
| Signatures | ML-DSA-65 (Dilithium3) | Composite-ML-DSA: ECDSA P-256 + ML-DSA-65 |
Why hybrid matters: PQC algorithms are rigorously standardized but relatively new. Classical algorithms like X25519 and ECDSA have decades of battle-testing. Hybrid mode ensures that even if a breakthrough in lattice cryptanalysis were discovered, the classical component would maintain security. Once PQC algorithms have accumulated more real-world deployment history, PQC-only mode will be the recommended long-term default.
What's Nextâ
- Non-Exportable Keys -- How private keys are protected
- Encryption at Rest -- AES-256-GCM key storage
- Zero Trust -- Per-request authorization
- Compliance -- Standards we implement, and what has not been validated or audited yet