Proof Verification
How to verify ProofPacks and attestations from Zipwire Attest users, including technical verification steps and developer integration.
Overview
When someone shares a ProofPack with you, you can verify its authenticity and integrity without needing access to the original documents. This page explains how to verify ProofPacks and understand what information has been shared.
Note: This page covers technical verification of ProofPack data structures. For general wallet verification and trust assessment, see Verifying Attested Wallets.
Understanding Proof vs. Wallet Verification
There are two complementary levels of verification:
Wallet Verification (General)
Purpose: Determine if a wallet owner is trustworthy
Focus: Who owns the wallet, when it was attested, transaction patterns
When to use: Before accepting any data from a wallet owner
Tools: EAS Scan, block explorers, transaction history
Proof Verification (Technical - This Page)
Purpose: Verify the authenticity and integrity of shared data
Focus: Cryptographic verification of ProofPack structures and attestations
When to use: After establishing wallet trust, to verify specific shared data
Tools: Code libraries, cryptographic verification, blockchain APIs
Workflow: First verify the wallet is trustworthy, then verify the specific data they share.
What is a ProofPack?
A ProofPack is a layered, privacy-preserving data exchange format that contains:
Merkle Exchange Document - The actual data with selective disclosure
Attested Merkle Exchange Document - Blockchain attestation metadata
JWS Envelope - Cryptographic signatures for tamper-proofing
For complete technical details, see the ProofPack specification on GitHub.
AI and LLM Integration
ProofPack's structured JSON format is ideal for AI-driven automation and verification. Large Language Models (LLMs) can already:
Current LLM Capabilities
Decode ProofPack JSON - Parse and understand the structure automatically
Extract leaf data - Decode hex-encoded content from leaves
Write verification scripts - Generate code to verify Merkle proofs
Execute verification logic - Run scripts to check data integrity
Analyze proof content - Understand what data has been revealed
Example: LLM Verification
LLMs like Google Gemini (June 2025) have demonstrated the ability to:
Parse ProofPack JSON structure
Decode hex-encoded leaf data
Write Python scripts to verify leaf hashes against the root hash
Execute verification without human intervention
Blockchain Connectivity Limitation
The only current limitation for LLMs is blockchain connectivity:
EAS verification - Checking attestations on Base blockchain
Chain connectivity - Accessing on-chain attestation data
MCP requirement - Need Model Context Protocol (MCP) server for Base connection
Future Potential
With MCP servers providing blockchain connectivity, LLMs could:
Fully automated verification - Complete end-to-end proof verification
Real-time attestation checking - Verify on-chain attestation status
Trust chain validation - Follow complete verification chains
Intelligent proof analysis - Understand context and validity
This represents a significant step toward AI-driven, secure verification without human intervention.
Simple Future Workflow
In the future, users will be able to simply drop a ProofPack JSON into an AI and it will automatically:
Parse the structure and understand what type of proof it is
Decode the data and extract the relevant information
Write verification scripts to check the proof's integrity
Connect to blockchain (via MCP) to verify attestations
Provide results with confidence levels and explanations
No technical knowledge required - just paste and verify.
Verification Process
1. Verify JWS Envelope (Outermost Layer)
The JWS envelope provides cryptographic signatures to ensure the document hasn't been tampered with.
What to Check:
Signature Validity: Verify at least one valid signature (RS256, ES256K)
Tamper Detection: Ensure the signature covers both header and payload
No Blockchain Required: JWS verification can be done offline
Example Verification:
// NOTE: This is conceptual code - no JavaScript SDK is currently available
// Manual verification (alternative to SDK)
const isValidSignature = await verifyJWS(proofPack, publicKey);
if (!isValidSignature) {
throw new Error("ProofPack signature is invalid");
}
2. Verify Merkle Tree (Innermost Layer)
The Merkle tree ensures data integrity and enables selective disclosure.
What to Check:
Minimum Leaves: Confirm at least two leaves exist
Metadata Leaf: First leaf must contain valid metadata
Content Types: Validate MIME types of revealed data
Hash Verification: Recompute leaf hashes and verify against root
Example Verification:
// NOTE: This is conceptual code - no JavaScript SDK is currently available
// Manual verification (alternative to SDK)
// Verify Merkle tree structure
const leaves = proofPack.merkleTree.leaves;
if (leaves.length < 2) {
throw new Error("ProofPack must have at least 2 leaves");
}
// Verify first leaf is metadata
const metadataLeaf = leaves[0];
if (metadataLeaf.contentType !== "application/json") {
throw new Error("First leaf must contain metadata");
}
// Verify revealed data hashes
for (const leaf of leaves) {
if (leaf.data && leaf.salt) {
const computedHash = hash(leaf.data + leaf.salt);
if (computedHash !== leaf.hash) {
throw new Error("Leaf hash verification failed");
}
}
}
3. Verify Blockchain Attestation (Middle Layer)
The blockchain attestation links the data to verifiable on-chain trust records.
What to Check:
EAS Attestation: Verify attestation exists on Base blockchain
Attester Validation: Confirm attestation from Zipwire's address
Schema Validation: Ensure correct schema type (IsAHuman or Private Data)
Revocation Check: Verify attestation is not revoked
Timestamp Validation: Check attestation is current
Example Verification:
// NOTE: This is conceptual code - no JavaScript SDK is currently available
// Manual verification (alternative to SDK)
// Verify on-chain attestation
const attestation = await eas.getAttestation(proofPack.attestation.eas.attestationUid);
// Check attester
const isValidAttester = attestation.attester === "0x2651e..."; // Zipwire's address
if (!isValidAttester) {
throw new Error("Invalid attester");
}
// Check revocation
if (attestation.revoked) {
throw new Error("Attestation has been revoked");
}
// Check schema
const isValidSchema = attestation.schema === expectedSchemaUid;
if (!isValidSchema) {
throw new Error("Invalid schema");
}
Trust Chain Verification
ProofPack enables verifiable trust chains through blockchain attestations.
Example Trust Chain:
Date of Birth ← Passport ← Zipwire ← Yoti ← iBeta ← NIST
Verification Steps:
Verify NIST attestation to iBeta's testing capabilities
Verify iBeta attestation to Yoti's MyFace technology
Verify Yoti attestation to Zipwire's implementation
Verify Zipwire attestation to passport verification
Verify passport authority to the date of birth
Real-World Verification Examples
Note: The following examples show simplified data for clarity. In practice, leaf data is normally hex-encoded JSON key-value pairs, but can conceivably be any data including images or audio.
Age Verification
{
"merkleTree": {
"leaves": [
{
"contentType": "application/json",
"data": "{\"documentType\":\"passport\",\"verificationDate\":\"2024-01-01\"}"
},
{
"contentType": "text/plain",
"data": "1990-05-15",
"salt": "random_salt_bytes",
"hash": "computed_hash"
}
],
"root": "0x1316fc0f..."
},
"attestation": {
"eas": {
"network": "base",
"attestationUid": "...",
"schema": "PrivateData"
}
}
}
Actual Implementation: Leaf data would be hex-encoded JSON like:
{
"contentType": "application/json",
"data": "0x7b22646f63756d656e7454797065223a2270617373706f7274222c22766572696669636174696f6e44617465223a22323032342d30312d3031227d",
"salt": "0x1234567890abcdef...",
"hash": "0xabcdef1234567890..."
}
Nationality Verification
{
"merkleTree": {
"leaves": [
{
"contentType": "application/json",
"data": "{\"documentType\":\"passport\"}"
},
{
"contentType": "text/plain",
"data": "United Kingdom",
"salt": "random_salt_bytes",
"hash": "computed_hash"
}
],
"root": "0x1316fc0f..."
}
}
Actual Implementation: Leaf data would be hex-encoded like:
{
"contentType": "text/plain",
"data": "0x556e69746564204b696e67646f6d",
"salt": "0xfedcba0987654321...",
"hash": "0x9876543210fedcba..."
}
Developer Integration
ProofPack SDK Verification (Recommended)
Important: The ProofPack SDK is now available on NPM for easy verification.
// Install the SDK: npm install @zipwire/proofpack @zipwire/proofpack-ethereum
import {
AttestedMerkleExchangeReader,
JwsSignatureRequirement,
createVerificationContextWithAttestationVerifierFactory
} from '@zipwire/proofpack';
import {
EasAttestationVerifierFactory,
ES256KVerifier
} from '@zipwire/proofpack-ethereum';
async function verifyProofPackDocument(jwsEnvelopeJson, coinbaseApiKey) {
// 1. Configure blockchain networks for EAS attestation verification
const networks = {
'base-sepolia': {
rpcUrl: `https://api.developer.coinbase.com/rpc/v1/base-sepolia/${coinbaseApiKey}`,
easContractAddress: '0x4200000000000000000000000000000000000021'
},
'base': {
rpcUrl: `https://api.developer.coinbase.com/rpc/v1/base/${coinbaseApiKey}`,
easContractAddress: '0x4200000000000000000000000000000000000021'
}
};
// 2. Create EAS attestation verifier
const attestationVerifierFactory = EasAttestationVerifierFactory.fromConfig(networks);
// 3. Create JWS verifier resolver that uses attester addresses from attestation
const resolveJwsVerifier = (algorithm, signerAddresses) => {
if (algorithm === 'ES256K') {
// signerAddresses contains the attester address from attestation verification
// We trust the attestation to tell us who should have signed
// No need to pass expected signer addresses as parameters - the blockchain attestation is the source of truth!
for (const signerAddress of signerAddresses) {
return new ES256KVerifier(signerAddress);
}
}
return null;
};
// 4. Define verification rules
const maxAge = 24 * 60 * 60 * 1000; // 24 hours
const hasValidNonce = async (nonce) => {
// Validate nonce format (32-character hex)
return /^[0-9a-fA-F]{32}$/.test(nonce);
};
// 5. Create comprehensive verification context
const verificationContext = createVerificationContextWithAttestationVerifierFactory(
maxAge, // Maximum document age
resolveJwsVerifier, // JWS verifier resolver function
JwsSignatureRequirement.AtLeastOne, // Require at least one valid signature
hasValidNonce, // Nonce validation function
attestationVerifierFactory // EAS attestation verifier factory
);
// 6. Verify the complete document
const reader = new AttestedMerkleExchangeReader();
const result = await reader.readAsync(jwsEnvelopeJson, verificationContext);
// 7. Handle results
if (result.isValid) {
console.log('✅ Document verified successfully!');
console.log('Message:', result.message);
// Access verified data
const document = result.document;
console.log('Merkle Root:', document.merkleTree.root);
console.log('Attestation Network:', document.attestation.eas.network);
console.log('Timestamp:', document.timestamp);
// 8. Verify recipient matches expected wallet
const expectedRecipient = '0x1234567890123456789012345678901234567890'; // User's wallet
const attestedRecipient = result.document.attestation.eas.to;
if (attestedRecipient && attestedRecipient.toLowerCase() !== expectedRecipient.toLowerCase()) {
return { success: false, error: `Wrong recipient. Expected: ${expectedRecipient}, Got: ${attestedRecipient}` };
}
return {
success: true,
document: document,
recipientAddress: attestedRecipient
};
} else {
console.error('❌ Verification failed:', result.message);
return { success: false, error: result.message };
}
}
// Usage
const jwsDocument = `{
"payload": "eyJtZXJrbGVUcmVlIjp7ImxlYXZlcyI6W3siZGF0YSI6IjB4N2I3MDcyNmY3NDY...",
"signatures": [{"protected": "eyJhbGciOiJFUzI1NksiLCJ0eXAiOiJKV1MifQ", "signature": "..."}]
}`;
const apiKey = process.env.COINBASE_API_KEY;
try {
const result = await verifyProofPackDocument(jwsDocument, apiKey);
if (result.success) {
console.log('Document verified successfully!');
} else {
console.error('Verification failed:', result.error);
}
} catch (error) {
console.error('Error during verification:', error.message);
}
Verification Options
ProofPack SDK (recommended) - Easy to use, handles all verification steps
Install:
npm install @zipwire/proofpack @zipwire/proofpack-ethereum
Repository: https://github.com/zipwireapp/ProofPack
Supports ES256K (Ethereum) and RS256 signature algorithms
Provides flexible parsing and verification methods
Security Considerations
Privacy Protection
Selective Disclosure: Only requested data is revealed
Salt Protection: Prevents preimage attacks on hashes
No Original Data: Original documents are never shared
Integrity Assurance
Cryptographic Proofs: Merkle trees ensure data integrity
Blockchain Verification: On-chain attestations prevent tampering
Signature Validation: JWS envelopes provide tamper-proofing
Trust Verification
Attester Validation: Confirm trusted source (Zipwire)
Revocation Checking: Ensure attestation is still valid
Timestamp Validation: Verify attestation is current
Common Verification Scenarios
For Age-Restricted Services
User shares ProofPack revealing only date of birth
Service verifies ProofPack integrity
Service checks attestation is from Zipwire
Service calculates age from date of birth
Service grants access if age requirement met
For Compliance Requirements
User shares ProofPack revealing specific compliance fields
Platform verifies ProofPack and attestation
Platform checks attestation is not revoked
Platform uses verified data for compliance reporting
For Identity Verification
User shares ProofPack revealing nationality
Service verifies ProofPack authenticity
Service confirms attestation from trusted source
Service grants access based on nationality
Troubleshooting
Common Issues
Invalid Signature: Check JWS envelope and public keys
Merkle Tree Error: Verify leaf structure and hash computations
Attestation Not Found: Check EAS Scan for attestation existence
Revoked Attestation: Attestation may have been revoked by Zipwire
Expired Attestation: Check timestamp and validity period
Verification Tools
EAS Scan: https://base.easscan.org/
JWS Verification: Use standard JWS libraries
Merkle Tree Tools: Implement hash verification functions
ProofPack Specification: Manual verification using the official specification
Related Resources
Verifying Attested Wallets - General wallet trust assessment
Last updated