Signature Verification
Verification basics
import { verifyEnvelope, createSignedEnvelope } from '@pqsafe/agent-pay'
const { publicKey, secretKey } = await generateKeyPair()const signed = createSignedEnvelope(envelope, secretKey)
// Should always be true if envelope wasn't mutatedconst valid = verifyEnvelope(signed, publicKey)Debugging verifyEnvelope() === false
1. Check for envelope mutation
The most common cause: the envelope object was modified after createSignedEnvelope().
// ❌ Bugconst env = createSpendEnvelope({ ... })const signed = createSignedEnvelope(env, secretKey)env.memo = 'changed' // Mutates the original object!verifyEnvelope(signed, publicKey) // false
// ✅ Fix: freeze the envelope objectconst env = Object.freeze(createSpendEnvelope({ ... }))const signed = createSignedEnvelope(env, secretKey)2. Verify key pair consistency
// Generate once and persist both keys togetherconst { publicKey, secretKey } = await generateKeyPair()
// ❌ Wrong: verifying with a different publicKeyconst other = await generateKeyPair()verifyEnvelope(signed, other.publicKey) // false — mismatched key pair
// ✅ Correct: use the publicKey that corresponds to the secretKey used for signingverifyEnvelope(signed, publicKey) // true3. Cross-runtime serialization
If you’re serializing a SignedEnvelope to JSON and deserializing it, ensure you’re not losing precision:
import { deserializeSignedEnvelope, serializeSignedEnvelope } from '@pqsafe/agent-pay'
// Use the SDK's serialization helpers — don't use JSON.stringify directlyconst json = serializeSignedEnvelope(signed)const restored = deserializeSignedEnvelope(json)verifyEnvelope(restored, publicKey) // true4. Cross-language verification
TypeScript-signed envelopes can be verified in Python:
from pqsafe_agent_pay import verify_envelope, deserialize_signed_envelope
# Load from JSONsigned = deserialize_signed_envelope(json_string)is_valid = verify_envelope(signed, public_key_hex)print(is_valid) # TrueDebug helper
import { debugEnvelopeSignature } from '@pqsafe/agent-pay'
const debug = debugEnvelopeSignature(signed, publicKey)console.log(debug)// {// valid: false,// canonicalJson: '{"agentId":"...","allowedRails":["airwallex"],...}',// signatureLength: 6586,// publicKeyLength: 3904,// error: 'Canonical JSON hash mismatch — envelope was likely mutated after signing',// }