Hybrid Attest
POST /v1/sign/hybrid
Create a hybrid attestation that pairs an ECDSA signature with a post-quantum ML-DSA signature. The server verifies both signatures before persisting the attestation.
Authentication: Secret key required (qs_sec_*)
Request
{
"message": "0x48656c6c6f20576f726c64",
"ecdsaSignature": "0x3045022100abc123...",
"ecdsaPublicKey": "0x04a1b2c3d4e5f6...",
"pqcSignature": "0x7a8b9c0d1e2f3a4b...",
"pqcPublicKey": "0x1a2b3c4d5e6f7a8b...",
"algorithm": "ml-dsa-65",
"chain": "ethereum",
"metadata": {
"txHash": "0xabc123...",
"label": "Treasury transfer approval"
}
}
Parameters
| Field | Type | Required | Description |
|---|
message | string | Yes | The signed message (hex-encoded) |
ecdsaSignature | string | Yes | ECDSA signature over the message (hex-encoded) |
ecdsaPublicKey | string | Yes | ECDSA public key (hex-encoded) |
pqcSignature | string | Yes | PQC signature over the message (hex-encoded) |
pqcPublicKey | string | Yes | PQC public key (hex-encoded) |
algorithm | string | Yes | PQC algorithm: ml-dsa-44, ml-dsa-65, ml-dsa-87 |
chain | string | No | Associated blockchain (default: ethereum) |
metadata | object | No | Arbitrary metadata to attach to the attestation |
All cryptographic fields (message, signatures, public keys) must be hex-encoded.
Server-Side Verification
Before storing the attestation, the server performs:
- ECDSA verification: Recovers the signer from
ecdsaSignature and verifies it matches ecdsaPublicKey
- PQC verification: Verifies
pqcSignature against message using pqcPublicKey and the specified algorithm
- Public key registration check: Confirms the
pqcPublicKey is registered in QuantumSafe
- Attestation creation: Links both signatures and stores the record
If either signature is invalid, the request is rejected with PQC_004.
Response 201 Created
{
"data": {
"id": "att_abc123def456",
"status": "verified",
"message": "0x48656c6c6f20576f726c64",
"ecdsaPublicKey": "0x04a1b2c3d4e5f6...",
"pqcPublicKey": "0x1a2b3c4d5e6f7a8b...",
"algorithm": "ml-dsa-65",
"chain": "ethereum",
"metadata": {
"txHash": "0xabc123...",
"label": "Treasury transfer approval"
},
"createdAt": "2026-01-15T10:30:00Z"
},
"meta": {
"requestId": "req_xyz789",
"timestamp": "2026-01-15T10:30:00Z"
}
}
Response Fields
| Field | Type | Description |
|---|
id | string | Unique attestation identifier |
status | string | Always verified on success |
message | string | The attested message |
ecdsaPublicKey | string | ECDSA signer public key |
pqcPublicKey | string | PQC signer public key |
algorithm | string | PQC algorithm used |
chain | string | Associated blockchain |
metadata | object | User-provided metadata |
createdAt | string | ISO 8601 timestamp |
Errors
| Code | Description |
|---|
AUTH_001 | Missing API key |
AUTH_003 | Publishable key used (Secret key required) |
PQC_001 | Unsupported algorithm |
PQC_002 | Invalid key format |
PQC_004 | Signature verification failed (ECDSA or PQC) |
RATE_001 | Rate limit exceeded |
PQC_004 is returned when either the ECDSA or the PQC signature fails verification. Check both signatures carefully before submitting.
Example
curl -X POST https://api.qsafe.dev/v1/sign/hybrid \
-H "Authorization: Bearer qs_sec_live_sk_abc123..." \
-H "Content-Type: application/json" \
-d '{
"message": "0x48656c6c6f20576f726c64",
"ecdsaSignature": "0x3045022100...",
"ecdsaPublicKey": "0x04a1b2c3...",
"pqcSignature": "0x7a8b9c0d...",
"pqcPublicKey": "0x1a2b3c4d...",
"algorithm": "ml-dsa-65",
"chain": "ethereum"
}'