Composite Hybrid Keys — Troubleshooting Guide
Common issues and solutions when working with quantum-resistant composite cryptography.
Common Errors
Error: "Security level mismatch"
Full error:
{
"error": "SECURITY_LEVEL_MISMATCH",
"message": "Classical component security level (3) does not match PQC component security level (1)"
}
Cause: Classical and PQC algorithms have different NIST security levels.
Solution: Use matching security levels:
| Security Level | Classical | PQC KEM | PQC Signature |
|---|---|---|---|
| Level 1 | X25519 | ML-KEM-512 | ML-DSA-44 |
| Level 3 (recommended) | X25519 | ML-KEM-768 | ML-DSA-65 |
| Level 5 | RSA-4096 | ML-KEM-1024 | ML-DSA-87 |
Example fix:
{
"components": [
{"role": "classical", "algorithm": "X25519"},
{"role": "pqc", "algorithm": "ML-KEM-768"} // Was ML-KEM-512 (Level 1)
]
}
Error: "DUALSIGN requires signature algorithms"
Full error:
{
"error": "INVALID_COMPONENT_TYPE",
"message": "DUALSIGN mode requires signature algorithms, but received KEM algorithm ML-KEM-768"
}
Cause: Used encryption algorithm (ML-KEM) in DUALSIGN mode which requires signature algorithms.
Solution: Use signature algorithms for DUALSIGN:
{
"mode": "DUALSIGN",
"components": [
{"role": "classical", "algorithm": "Ed25519"}, // Signature
{"role": "pqc", "algorithm": "ML-DSA-65"} // Signature (not ML-KEM)
]
}
Error: "Cannot decrypt with single component"
Full error:
{
"error": "AND_DECRYPT_REQUIREMENT_NOT_MET",
"message": "Composite key requires BOTH classical and PQC components for decryption"
}
Cause: Attempted to decrypt with only one component of a composite key.
Explanation: This is the AND-decrypt security model working correctly. Both components are required.
Solution: Ensure both component private keys are available: - Classical component (X25519, RSA, etc.) - PQC component (ML-KEM)
If key is lost: Data cannot be recovered (by design). Always backup composite keys securely.
Error: "Verification policy not satisfied"
Full error:
{
"error": "VERIFICATION_POLICY_NOT_MET",
"message": "Policy ALL requires both signatures valid, but classical signature verification failed"
}
Cause: DUALSIGN verification policy requires both signatures to be valid, but one failed.
Solution: Check verification policy:
| Policy | Requirement |
|---|---|
| ALL | Both classical AND PQC must verify |
| ANY | At least one must verify |
| CLASSICAL_REQUIRED | Classical must verify (PQC optional) |
| PQC_REQUIRED | PQC must verify (classical optional) |
Debugging steps: 1. Verify both component private keys are available 2. Check signature was created with same key 3. Ensure document wasn't modified after signing
Performance Issues
Issue: Slower than expected
Symptom: Composite key operations take ~2-5ms, simple keys take ~3ms.
Expected behavior: Composite keys are ~2.0x slower than simple keys.
| Operation | Simple ML-KEM | Composite (X25519+ML-KEM) |
|---|---|---|
| Encryption | ~3 ms | ~5 ms (1.7x) |
| Decryption | ~3 ms | ~5 ms (1.7x) |
| Signature | ~4 ms | ~8 ms (2.0x) |
This is normal. Composite keys perform two cryptographic operations instead of one.
Mitigation strategies: - Use simple keys for high-frequency operations (>1000 ops/sec) - Use composite keys only for high-value data (10+ year retention) - Enable caching for frequently accessed keys - Use streaming APIs for large files (avoids memory overhead)
Issue: Large ciphertext size
Symptom: Composite key ciphertext is larger than simple key ciphertext.
Explanation: Composite keys use JWE General JSON Serialization (RFC 7516 §7.2) which includes metadata for both components.
Size comparison: - Simple keys: ~1.2× plaintext (compact format) - Composite keys: ~1.3× plaintext (JSON format)
Difference: ~8% larger (minor overhead for enhanced security).
If size is critical: Use simple keys for bandwidth-constrained scenarios or compress ciphertext before transmission.
Format Detection Issues
Issue: Content-Type confusion
Symptom: Client expects compact JWE string but receives JSON object (or vice versa).
Cause: Simple keys use compact format, composite keys use JSON format.
Solution: Detect format using Content-Type header:
EncryptResult result = sdk.encrypt(kid, plaintext);
if ("application/jose+json".equals(result.getContentType())) {
// Composite key - JSON format
Map<String, Object> jwe = result.getJweAsMap();
// Handle as JSON object
} else {
// Simple key - compact format
String jwe = result.getJweAsString();
// Handle as string
}
Auto-detection pattern:
Object jwe = result.getJwe();
if (jwe instanceof Map) {
// Composite key (JSON)
} else if (jwe instanceof String) {
// Simple key (compact)
}
Issue: Client-side parsing failure
Symptom: External JOSE library fails to parse composite key output.
Cause: Many JOSE libraries only support compact serialization, not General JSON Serialization.
Solution: 1. Use AnkaSecure SDK (handles both formats automatically) 2. Use JOSE library with General JSON support (e.g., Nimbus JOSE+JWT 9.0+) 3. Keep composite keys server-side (don't expose to external clients)
Interoperability note: Composite keys are designed for AnkaSecure ecosystem. For maximum interoperability with external systems, use simple keys.
Integration Issues
Issue: "Key not found"
Full error:
Debugging steps: 1. Verify key was created successfully:
-
Check key status (must be "active"):
-
Verify tenant context (multi-tenant environments):
- Ensure JWT token has correct tenant claim
- Keys are tenant-scoped (not shared across tenants)
Issue: Migration from simple to composite fails
Symptom: Re-encryption from simple key to composite key returns error.
Possible causes:
- Source key retired: Simple key was retired before migration
-
Solution: Reactivate source key temporarily
-
Target key wrong mode: Target key is DUALSIGN but source was encrypted
-
Solution: Use HYBRID_KEM_COMBINE for encryption migration
-
Insufficient permissions: API token lacks re-encryption permission
- Solution: Request elevated permissions from admin
Correct migration workflow:
# 1. Generate composite key
curl -X POST /api/key-management/composite-keys -d '{
"kid": "composite-replacement",
"mode": "HYBRID_KEM_COMBINE",
"components": [
{"role": "classical", "algorithm": "X25519"},
{"role": "pqc", "algorithm": "ML-KEM-768"}
]
}'
# 2. Re-encrypt (source must be active)
curl -X POST /api/crypto/re-encrypt -d '{
"sourceKid": "old-simple-key",
"targetKid": "composite-replacement",
"jweToken": "eyJhbGci..."
}'
# 3. Verify
curl -X POST /api/crypto/decrypt-jwe -d '...'
API Errors
HTTP 400 (Bad Request)
Common causes: - Missing required field (kid, mode, components) - Invalid algorithm name (typo: "ML-KEM-786" instead of "ML-KEM-768") - Invalid JSON syntax
Solution: Validate request against API spec before sending.
HTTP 422 (Unprocessable Entity)
Common causes: - Security level mismatch (X25519 + ML-KEM-512) - Wrong component type for mode (KEM in DUALSIGN) - Invalid KDF for combination (unsupported KDF)
Solution: Check error message for specific validation failure.
HTTP 500 (Internal Server Error)
Common causes: - Cryptographic library failure (rare) - HSM unavailability (if using HSM-backed keys) - Database connection issue
Solution: Retry with exponential backoff. If persistent, contact support.
Debugging Techniques
Enable debug logging (SDK)
AnkaSecureSdk sdk = AnkaSecureSdk.builder()
.baseUrl("https://api.ankatech.co")
.bearerToken("YOUR_TOKEN")
.enableDebugLogging(true) // Logs all requests/responses
.build();
Output:
[DEBUG] POST /api/key-management/composite-keys
[DEBUG] Request: {"kid": "test-key", "mode": "HYBRID_KEM_COMBINE", ...}
[DEBUG] Response: 201 Created
[DEBUG] {"kid": "test-key", "components": [...]}
Trace correlation IDs
Every API response includes X-Correlation-ID header. Use it to trace request through logs:
curl -v -X POST /api/crypto/encrypt -d '...'
# Response header: X-Correlation-ID: abc123-def456
# Contact support with correlation ID for investigation
FAQ
Q: Do I need to change my code to use composite keys? A: No. The API is transparent — same endpoints as simple keys.
Q: What's the performance impact? A: ~2.0x slower than simple keys (~5ms vs ~3ms per operation). Acceptable for high-value data.
Q: Can I mix simple and composite keys in the same application? A: Yes. Use composite for sensitive data (10+ year retention) and simple for everything else.
Q: How do I detect if a response is from a simple or composite key?
A: Check Content-Type header: application/jose (simple) vs application/jose+json (composite).
Q: Can external JOSE libraries decrypt composite key output? A: Only if they support General JSON Serialization (RFC 7516 §7.2). Use AnkaSecure SDK for best compatibility.
Q: What happens if I lose one component of a composite key? A: Data cannot be decrypted (AND-requirement). Always backup both components securely.
Q: Can I migrate from composite back to simple? A: Yes, using re-encryption API. But you lose quantum resistance — not recommended.
Q: How do I test composite keys before production? A: Use sandbox environment with test keys. See Quick Start Guide.
Need Help?
Documentation: - Composite Keys Quick Start - Flow 29 SDK Example - Best Practices
Support:
- Email: [email protected]
- Include correlation ID from X-Correlation-ID header
- Provide full error message and request/response (redact sensitive data)
Document Version 3.0.0 -- updated December 2025 © 2025 ANKATech Solutions INC. All rights reserved.