Non-Exportable Keys
Your PQC private keys are the most sensitive assets in Qpher. A leaked private key would allow an attacker to decrypt your ciphertexts or forge signatures in your name. That is why Qpher follows one rule: private keys are generated and used only inside the isolated key service (KMS-Orchestrator), and are never exported.
There is no API endpoint to retrieve private keys — by design.
How It Works​
When you generate a PQC key pair through Qpher, the following happens:
- Key generation occurs inside the KMS-Orchestrator service.
- The public key is returned to you and stored in the database. You can retrieve it at any time.
- The private key is encrypted by a key held in Google Cloud KMS and stored as an envelope file in the KMS-Orchestrator's key store.
- The database stores only a handle (a file path reference), never the raw key bytes.
You receive: Stored by the KMS-Orchestrator:
+--------------------------+ +----------------------------------+
| Public Key | | Private key, encrypted by a |
| (1184 bytes | | Google Cloud KMS key |
| for Kyber768) | | -> {version}.key.envelope |
+--------------------------+ +----------------------------------+
|
Database stores only:
"handle" = {tenant}/{algorithm}/{version}
No Export API​
Qpher intentionally provides no endpoint for downloading or exporting private keys. This is not a missing feature -- it is a deliberate security decision.
| Operation | Available? | How It Works |
|---|---|---|
| Generate key pair | Yes | Private key created and stored inside KMS-Orchestrator |
| Get public key | Yes | Public key returned from the database |
| Get private key | No | No such endpoint exists |
| Export private key | No | No such endpoint exists |
| Encrypt / Decrypt | Yes | KMS-Orchestrator performs the operation using the private key internally |
| Sign / Verify | Yes | KMS-Orchestrator performs the operation using the private key internally |
Server-Side Cryptographic Operations​
Since you cannot download private keys, all cryptographic operations that require a private key happen inside Qpher:
- Decrypt: You send the ciphertext to Qpher. The KMS-Orchestrator loads the private key, performs Kyber768 decapsulation, and returns the plaintext.
- Sign: You send the message to Qpher. The KMS-Orchestrator loads the private key, performs Dilithium3 signing, and returns the signature.
Operations that use only the public key (encrypt, verify) can also be performed client-side if you prefer, since public keys are freely available.
You can verify signatures locally using the public key and any ML-DSA-65 (FIPS 204) implementation. This is useful when you want to verify data integrity without making an API call.
Private Key Storage Details​
In production:
- Encryption: each private key is encrypted by a key held in Google Cloud KMS (authenticated encryption); an envelope cannot be read without a Cloud KMS Decrypt call.
For more details on the encryption scheme, see Encryption at Rest.
Key Lifecycle Respect​
The non-exportable rule applies across the entire key lifecycle:
| Key Status | Can Load Private Key? | Allowed Operations |
|---|---|---|
| Active | Yes (internally only) | Encrypt, decrypt, sign, verify |
| Retired | Yes (internally only) | Decrypt, verify only |
| Archived | No | No operations allowed |
Even when a key is active, only the KMS-Orchestrator's code loads it.
Why This Matters​
Why it is built this way:
- One place loads keys: only the KMS-Orchestrator's code loads private keys.
- No accidental exposure: private keys are never written to logs, error messages, API responses or the database — the database holds only a handle.
- Auditability: each private-key operation writes an audit event.