Issue a SpendEnvelope.
Real ML-DSA-65 + ECDSA P-256 dual-signature. Ephemeral keypairs generated in your browser, JCS canonicalization per RFC 8785. Nothing is sent to PQSafe servers. Paste the result into the verifier with the public keys shown below.
@pqsafe/cli or the issuer API.
This page demonstrates the cryptographic shape so integrators can wire up a verifier against a known good envelope.
Public keys (paste into a verifier)
ECDSA P-256 (compressed hex, 33 bytes)
ML-DSA-65 (base64url, 1952 bytes)
ML-DSA-65 public key fingerprint (first 8 bytes SHA-256, hex)
Issued SpendEnvelope
JCS canonical: — bytes
ECDSA sig: — bytes DER
ML-DSA sig: — bytes
Fingerprint: —
How issuance works
- 1. Capture intent. The agent records what it wants to spend, where, and under what policy. These become the mandate fields above.
- 2. Canonicalize. Mandate fields (without
signature) are serialized via RFC 8785 JCS — sorted keys, normalized numbers, deterministic encoding. Any equivalent JSON produces identical bytes. - 3. Fingerprint. SHA-256 of the canonical bytes produces a 32-byte fingerprint. The signature is over the fingerprint, not the raw JSON.
- 4. Dual-sign. The fingerprint is signed with both ECDSA P-256 (~71 bytes DER) and ML-DSA-65 (3309 bytes per FIPS 204). Either signing key alone produces a valid signature; the verifier checks both.
For production
Ephemeral keys are for exploration only. In production, the canonical PQSafe issuer holds the long-lived keypair, registers the public key fingerprint on-chain (Arbitrum), and exposes a controlled HTTP issuance API.
npm i -g @pqsafe/cli pqsafe issue \ --agent did:web:youragent.com:agent-1 \ --amount 50.00 --currency USD \ --recipient did:web:merchant.com:payee \ --output envelope.json