Exqub Protocol Technical Specification

Complete technical documentation for implementing Exqub credentials: cryptographic primitives, data structures, verification pipeline, and security model.

System Roles

Issuer

Enterprise or authority that creates and signs credentials with ML-DSA-65. Publishes revocation state via Sparse Merkle Tree.

issuer_key: ML-DSA-65 (1952 bytes public)

Holder

Agent, service, or device that receives credentials, stores in wallet, controls presentation and attribute disclosure.

device_key: ML-DSA-65 (bound to credential)

Verifier

Any party that receives presentations, checks signatures, revocation status, and attribute proofs. Stateless operation.

verification: <50ms (full credential)

Revocation Registry

Sparse Merkle Tree with signed root snapshots published by issuer, consumed by verifiers.

depth: 256, proof: ~8KB for 1M credentials

Credential Structure

ExqubCredential {
  version:          u8            // 0x01
  credential_id:    [u8; 32]      // unique, issuer-assigned
  credential_type:  u8            // 0x01=Standard, 0x02=Delegation, 0x04=Attestation
  issuer_id:        [u8; 32]      // SHA3-256(issuer public key)
  holder_id:        [u8; 32]      // holder identity
  issued_at:        u64           // Unix timestamp
  expires_at:       u64           // hard TTL
  attr_count:       u32           // number of attributes (≤64)
  attr_root:        [u8; 32]      // Merkle root of attribute tree
  signature:        [u8; 3309]    // ML-DSA-65 (FIPS 204)
}

Total wire size: 9-12 KB including attributes (smaller than most JWT-based tokens)

Attribute Tree & Selective Disclosure

Each attribute is a Merkle tree leaf computed as:

leaf = SHA3-256(
  EXQUB_ATTR_LEAF_     // domain separator
  || len(key)          // u16 big-endian
  || key               // UTF-8
  || salt              // [u8; 32], per-attribute
  || len(value) || value)

Per-Attribute Salts

Prevents dictionary attacks on undisclosed attributes

Independent Disclosure

Logarithmic scaling with attribute count

Merkle Proof

Holder provides key, value, salt, and sibling path

Signature Construction

The 166-byte sig_input uses fixed-layout concatenation for deterministic signing:

  • 0x00–0x0F: EXQUB_SIG_V1 domain separator (16 bytes)
  • 0x10: version (1 byte)
  • 0x11: credential_type (1 byte)
  • 0x12–0x31: credential_id (32 bytes)
  • 0x32–0x51: issuer_id (32 bytes)
  • 0x52–0x71: holder_id (32 bytes)
  • 0x72–0xA5: issued_at + expires_at + attr_count + attr_root

Note: Fixed-layout byte concatenation (not CBOR) ensures deterministic, implementation-independent signing

Presentation Format

ExqubPresentation {
  credential:       ExqubCredential
  disclosed_attrs:  Vec<(key, value, salt, proof)>
  device_signature: [u8; 3309]    // ML-DSA-65 over content
  nonce:            [u8; 32]      // verifier-provided
}

10-Step Verification Pipeline

DoS-resistant ordering: cheap checks first, expensive crypto last

1

Parse CBOR

Reject malformed input before any work

~1.14µs
2

Version and type check

Reject unknown versions or credential types

~0.001ms
3

Freshness + nonce check

Reject stale/wrong-session presentations

~0.01ms
4

Work bounding

Reject oversized proofs (DoS protection)

~0.001ms
5

SMT membership

Check non-revocation before expensive signature verification

~1ms (hashing)
6

Issuer signature

Verify credential authenticity (ML-DSA-65)

~144µs EXPENSIVE
7

Credential validity window

Check expiry (issued_at, expires_at)

~0.001ms
8

Attribute Merkle proofs

Verify disclosed attributes match the credential

~0.5ms (moderate)
9

Device signature

Verify holder controls the device key (ML-DSA-65)

~144µs EXPENSIVE
10

Policy evaluation

Application-layer constraints, replay cache

Variable

Full verify_presentation(): ~301µs on native hardware, ~1-4ms on WASM

Revocation System

Sparse Merkle Tree

  • • Depth 256, each credential ID maps to leaf
  • • Valid if leaf present, revoked if absent
  • • Signed, monotonically-indexed snapshots
  • • Transport-agnostic (HTTPS, CDN, P2P gossip)

Performance

  • • 1M credentials = 256 hashes (~8 KB proof)
  • • No bulk CRL downloads
  • • DoS resistance: check before signature verification
  • • Offline verification with cached snapshots

Device Binding

Mandatory Security Feature

  • Every credential bound to holder's device key (ML-DSA-65 public key embedded and issuer-signed)
  • Every presentation requires fresh device co-signature covering credential + disclosed attributes + verifier nonce
  • Prevents credential theft (different device lacks private key)
  • Prevents replay attacks (nonce binding)

Note: Mandatory in Exqub (unlike optional SD-JWT or absent W3C VC + BBS+)

Threat Model

Threat Mitigation Residual Risk
Forge credential ML-DSA-65 signatures (128-bit quantum security) None with current tech
Escalate privileges Merkle tree binds attributes cryptographically None
Replay attack Verifier nonce + device co-signature None
Steal credential Device binding (needs private key) Device compromise
Quantum attack ML-DSA-65 (NIST PQC standard) None known

Important Limitation: Exqub credentials attest scope and the verifier enforces it. If a backend service does not embed the verifier SDK, the credential cannot prevent unauthorised actions. This is analogous to TLS: the protocol secures the channel, but only if the server requires it.

Competitive Landscape

System What It Does Exqub Difference
W3C VC + BBS+ Verifiable credentials with multi-show unlinkability PQC sigs, mandatory device binding, native sub-delegation
Macaroons Attenuated capability tokens with contextual caveats PQC sigs, per-attribute selective disclosure, SMT revocation
SPIFFE / SPIRE Workload identity via x509-SVIDs Capability constraints, selective disclosure, PQC, agent delegation
OAuth DPoP / GNAP Proof-of-possession tokens for APIs Any-party verification, native sub-delegation, compound constraints
SD-JWT (eIDAS 2.0) Selective disclosure via salted hashes Logarithmic disclosure scaling, PQC, mandatory device binding

Implementation Status

Core Implementation

  • • Pure Rust, 8 crates
  • • 1,363+ tests, Clippy clean
  • • 63 conformance test vectors
  • • WASM verified, no_std core

Performance

  • • no_std core engine
  • • Zero heap allocations in verification
  • • ~144µs ML-DSA-65 verify
  • • ~301µs full presentation

Cryptography

  • • ML-DSA-65 (FIPS 204)
  • • 3,309 byte signatures
  • • 1,952 byte public keys
  • • 128-bit quantum security
# Integration example
from exqub import verifier, presenter

# Two lines to verify
result = verifier.verify(presentation)
if result.valid and result.spend_cap >= amount:
    process_transaction()

Protocol Roadmap

Q2 2026

V2 Production Hardening

Device key rotation, conformance tests, OID4VP + COSE interop, batch revocation, TypeScript/Python SDKs

Q4 2026

Agent Framework Integration

LangChain, AutoGen, CrewAI, LlamaIndex tooling with two-line integration

2027+

Research Directions

Threshold credentials (k-of-n), conditional disclosure, blind signatures, formal verification (Lean 4)