Key Wrap / Unwrap
This guide shows you how to protect existing symmetric keys (AES, ChaCha20, HMAC) using Qpher quantum-safe KEM key wrapping. Wrap your keys with Kyber768 or X-Wing so they can be safely stored, distributed, or backed up without changing your existing encryption flow.
What is Key Wrapping?
Key wrapping uses a quantum-safe KEM to encrypt an existing symmetric key. Instead of encrypting your data directly with Qpher, you encrypt only the key that protects your data. This is ideal when:
- You already have an encryption pipeline using AES or ChaCha20
- You need to protect keys at rest or in transit
- You want quantum-safe key protection without re-architecting your system
The wrapped key can be safely stored anywhere — a database, a config file, or a cloud secret manager — because it is encrypted with your Qpher KEM public key. Only the Qpher secure enclave can unwrap it.
When to Use Key Wrap
| Use Case | Description |
|---|---|
| Protect AES-256 master keys | Wrap your data encryption keys (DEKs) with a quantum-safe key encryption key (KEK) |
| Secure key distribution | Wrap keys before sending them to other services or regions |
| HSM key import/export | Wrap keys for secure import into or export from hardware security modules |
| Encrypted key backup | Store wrapped keys in cold storage with quantum-safe protection |
| Key escrow / key recovery | Wrap recovery keys so only authorized Qpher tenants can unwrap them |
Prerequisites
- A Qpher account with an active API key
- At least one active Kyber768 key pair (see Key Management), or an active X-Wing key pair for hybrid wrapping
- The
key_versionof the active key you want to use - A symmetric key to wrap (16, 24, 32, 48, or 64 bytes)
Step 1: Prepare Your Symmetric Key
Base64-encode your symmetric key before sending it to the API.
Your symmetric key is sensitive material. Never log, print, or persist the raw key in plaintext. Base64-encode it only in memory immediately before calling the wrap API.
Step 2: Wrap the Key
curl -X POST https://api.qpher.ai/api/v1/kem/key/wrap \
-H "Content-Type: application/json" \
-H "x-api-key: qph_your_key_here" \
-d '{
"symmetric_key": "MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY=",
"key_version": 1
}'Step 3: Unwrap the Key
When you need the symmetric key again, send the wrapped key back to Qpher for unwrapping.
curl -X POST https://api.qpher.ai/api/v1/kem/key/unwrap \
-H "Content-Type: application/json" \
-H "x-api-key: qph_your_key_here" \
-d '{
"wrapped_key": "base64-encoded-wrapped-key...",
"key_version": 1
}'Understand the Responses
Wrap Response
/api/v1/kem/key/wrapContent-Type: application/json
x-api-key: qph_your_key_here{
"symmetric_key": "MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY=",
"key_version": 1
}{
"data": {
"wrapped_key": "base64-encoded-wrapped-key...",
"key_version": 1,
"algorithm": "Kyber768",
"wrapping_method": "KEM-DEM"
},
"request_id": "660e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-02-15T10:35:00Z"
}| Field | Description |
|---|---|
wrapped_key | Base64-encoded wrapped key containing the KEM ciphertext and encrypted symmetric key |
key_version | The KEM key version used for wrapping — store this alongside the wrapped key |
algorithm | The KEM algorithm used (Kyber768 or X-Wing) |
wrapping_method | The wrapping method used (always KEM-DEM) |
Unwrap Response
/api/v1/kem/key/unwrapContent-Type: application/json
x-api-key: qph_your_key_here{
"wrapped_key": "base64-encoded-wrapped-key...",
"key_version": 1
}{
"data": {
"symmetric_key": "MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY=",
"key_version": 1,
"algorithm": "Kyber768"
},
"request_id": "660e8400-e29b-41d4-a716-446655440001",
"timestamp": "2026-02-15T10:36:00Z"
}Always store the key_version alongside the wrapped key. You will need the exact same key_version to unwrap the key later. There is no implicit "latest" key — Qpher requires explicit versioning on every operation.
Supported Key Sizes
The wrap API accepts symmetric keys of the following sizes:
| Key Size (bytes) | Key Size (bits) | Common Use |
|---|---|---|
| 16 | 128-bit | AES-128 |
| 24 | 192-bit | AES-192 |
| 32 | 256-bit | AES-256, ChaCha20 |
| 48 | 384-bit | Extended key material |
| 64 | 512-bit | HMAC-SHA512 |
The API validates the symmetric key length before wrapping. Keys that do not match one of the supported sizes above will be rejected with ERR_KEM_010.
Algorithm Support
Kyber768 (Default)
PQC-only key wrapping using ML-KEM-768. Available on all plans.
X-Wing Hybrid KEM (Starter+)
For defense-in-depth, add "algorithm": "X-Wing" to combine X25519 classical key exchange with ML-KEM-768. This ensures your wrapped keys remain protected even if a breakthrough in lattice cryptanalysis is discovered. Requires an active X-Wing key pair — see Hybrid Cryptography.
curl -X POST https://api.qpher.ai/api/v1/kem/key/wrap \
-H "Content-Type: application/json" \
-H "x-api-key: qph_your_key_here" \
-d '{
"symmetric_key": "MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY=",
"key_version": 1,
"algorithm": "X-Wing"
}'Recommendation: Use Kyber768 unless you have a regulatory requirement for classical cryptography fallback.
Key Version Behavior
| Key Status | Wrap | Unwrap |
|---|---|---|
active | Allowed | Allowed |
retired | Not allowed | Allowed |
archived | Not allowed | Not allowed |
When you rotate your KEM key, existing wrapped keys remain valid. You can still unwrap them using the retired key version. Re-wrap with the new active key version at your convenience.
Error Handling
| HTTP Status | Error Code | Cause | Resolution |
|---|---|---|---|
| 400 | ERR_KEM_010 | Invalid symmetric key length | Ensure the key is 16, 24, 32, 48, or 64 bytes |
| 400 | ERR_KEM_011 | Invalid wrapped key format | Ensure the wrapped_key is valid base64 from a previous wrap call |
| 400 | ERR_KEM_012 | Integrity check failed on unwrap | The wrapped key may be corrupted or tampered with |
| 400 | ERR_INVALID_001 | Missing required field | Ensure symmetric_key/wrapped_key and key_version are provided |
| 401 | ERR_AUTH_001 | Invalid or missing API key | Check your x-api-key header |
| 404 | ERR_KEM_003 | Key version not found | Verify the key_version exists for your tenant |
| 409 | ERR_KEM_004 | Key is not in a valid status for this operation | Active keys for wrap; active or retired keys for unwrap |
| 429 | ERR_RATE_001 | Rate limit exceeded | Reduce request frequency or upgrade your plan |
Security Considerations
All API calls must use HTTPS (TLS 1.2+). The symmetric key is encrypted in transit and then immediately wrapped server-side. The server zeroes the raw symmetric key from memory after wrapping.
- Wrapped keys are safe to store anywhere: The wrapped key is encrypted with your Qpher KEM public key. Without access to the corresponding private key inside the Qpher secure enclave, the wrapped key cannot be unwrapped.
- Server-side key zeroing: After a wrap operation, the raw symmetric key is zeroed from server memory. After an unwrap operation, the symmetric key is returned in the response and then zeroed from server memory.
- No key logging: Symmetric keys and wrapped keys are never written to server logs.
- Audit trail: All wrap and unwrap operations are recorded in the audit log with the key version used but without any key material.
Related Guides
- Encrypt Data — Encrypt data directly with KEM-DEM
- Key Management — Generate and manage your KEM keys
- Key Versioning — Understand key lifecycle and rotation
- Hybrid Cryptography — Use X-Wing for classical+PQC defense-in-depth