Skip to main content

Command Palette

Search for a command to run...

Verify Blockchain File Proofs with Python's verify-proof Package

Your application receives a file and a JSON proof claiming the file was timestamped on a blockchain before a critical event occurred. How do you verify that claim programmatically? The verify-proof Python package handles this exact scenario, providing offline verification of blockchain-anchored file hashes without network dependencies.

Updated
5 min read
Verify Blockchain File Proofs with Python's verify-proof Package
C
Founder, Fulcrum Enterprises. Building the foundation for an AI driven future.

Installing and Basic Usage

The verify-proof package is available on PyPI and works entirely offline. It doesn't make network calls to validate blockchain transactions — instead, it performs cryptographic verification of the proof structure itself.

pip install verify-proof

The package provides two main functions: hash_file() for generating SHA-256 hashes and verify_proof() for validating proof documents.

from verify_proof import hash_file, verify_proof

# Generate SHA-256 hash of a file
file_hash = hash_file("document.pdf")
print(f"SHA-256: {file_hash}")
# Output: SHA-256: a1b2c3d4e5f6789...

The hash_file() function returns a 64-character hexadecimal string representing the SHA-256 digest. This is the same hash that gets anchored to blockchain networks.

Hash and Proof Verification Workflow

The verification process involves two steps: confirming the file matches its claimed hash, then validating the proof document structure.

import json
from verify_proof import hash_file, verify_proof

def verify_file_and_proof(file_path, proof_path):
    # Step 1: Hash the file
    calculated_hash = hash_file(file_path)
    
    # Step 2: Load the proof document
    with open(proof_path, 'r') as f:
        proof_data = json.load(f)
    
    # Step 3: Verify the proof
    result = verify_proof(calculated_hash, proof_data)
    
    return calculated_hash, result

# Example usage
file_hash, verification_result = verify_file_and_proof(
    "contract.pdf", 
    "contract_proof.json"
)

print(f"File hash: {file_hash}")
print(f"Verification result: {verification_result}")

The verify_proof() function returns a dictionary with several fields:

  • verified: Boolean indicating whether verification passed

  • blockchain: The blockchain network used (e.g., "polygon", "bitcoin")

  • tx_id: Transaction ID on the blockchain

  • anchored_at: Timestamp when the hash was anchored

  • service: The anchoring service that created the proof

Complete Verification Script

Here's a production-ready script that handles multiple files and includes proper error handling:

#!/usr/bin/env python3

import json
import sys
import os
from pathlib import Path
from verify_proof import hash_file, verify_proof

def verify_file_proof(file_path, proof_path):
    """
    Verify a file against its blockchain proof.
    Returns tuple: (success: bool, details: dict)
    """
    try:
        # Check if files exist
        if not os.path.exists(file_path):
            return False, {"error": f"File not found: {file_path}"}
        
        if not os.path.exists(proof_path):
            return False, {"error": f"Proof not found: {proof_path}"}
        
        # Generate file hash
        file_hash = hash_file(file_path)
        
        # Load proof document
        with open(proof_path, 'r') as f:
            proof_data = json.load(f)
        
        # Verify proof
        result = verify_proof(file_hash, proof_data)
        
        if result['verified']:
            return True, {
                "file_hash": file_hash,
                "blockchain": result['blockchain'],
                "tx_id": result['tx_id'],
                "anchored_at": result['anchored_at'],
                "service": result['service']
            }
        else:
            return False, {
                "file_hash": file_hash,
                "error": "Proof verification failed",
                "proof_data": result
            }
            
    except json.JSONDecodeError:
        return False, {"error": "Invalid JSON in proof file"}
    except Exception as e:
        return False, {"error": f"Verification failed: {str(e)}"}

def main():
    if len(sys.argv) != 3:
        print("Usage: python verify_script.py <file_path> <proof_path>")
        sys.exit(1)
    
    file_path = sys.argv[1]
    proof_path = sys.argv[2]
    
    success, details = verify_file_proof(file_path, proof_path)
    
    if success:
        print("✅ VERIFICATION PASSED")
        print(f"File: {file_path}")
        print(f"Hash: {details['file_hash']}")
        print(f"Blockchain: {details['blockchain']}")
        print(f"Transaction: {details['tx_id']}")
        print(f"Anchored: {details['anchored_at']}")
        print(f"Service: {details['service']}")
    else:
        print("❌ VERIFICATION FAILED")
        print(f"File: {file_path}")
        print(f"Error: {details['error']}")
        sys.exit(1)

if __name__ == "__main__":
    main()

Run this script with any file and its corresponding proof:

python verify_script.py document.pdf document_proof.json

Batch Processing and Error Handling

For applications processing multiple files, you can extend the verification logic to handle batches:

import os
from concurrent.futures import ThreadPoolExecutor
from verify_proof import hash_file, verify_proof
import json

def verify_single_item(item):
    """Worker function for parallel verification."""
    file_path, proof_path = item
    
    try:
        file_hash = hash_file(file_path)
        
        with open(proof_path, 'r') as f:
            proof_data = json.load(f)
        
        result = verify_proof(file_hash, proof_data)
        
        return {
            "file": file_path,
            "verified": result['verified'],
            "hash": file_hash,
            "details": result
        }
    except Exception as e:
        return {
            "file": file_path,
            "verified": False,
            "error": str(e)
        }

def batch_verify(file_proof_pairs, max_workers=4):
    """Verify multiple file/proof pairs in parallel."""
    
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        results = list(executor.map(verify_single_item, file_proof_pairs))
    
    return results

# Example usage
pairs = [
    ("file1.pdf", "file1_proof.json"),
    ("file2.jpg", "file2_proof.json"),
    ("file3.docx", "file3_proof.json")
]

verification_results = batch_verify(pairs)

for result in verification_results:
    status = "✅" if result['verified'] else "❌"
    print(f"{status} {result['file']}: {result.get('hash', 'ERROR')}")

Note that the ThreadPoolExecutor approach works because we're using a proper function, not a lambda. The verify-proof package performs only local cryptographic operations, so parallel processing is safe and efficient.

Understanding What Gets Verified

It's important to understand exactly what the verify-proof package validates. The package performs structural verification of the proof document — it confirms that required fields are present and the proof format is correct. However, it doesn't make network calls to validate that the transaction actually exists on the blockchain.

# This is what verify_proof() checks:
# 1. Does the calculated hash match the hash in the proof?
# 2. Is the proof structure valid JSON with required fields?
# 3. Is the tx_id field non-empty?
# 4. Are timestamps properly formatted?

# This is what it does NOT check:
# - Whether the transaction exists on the blockchain
# - Whether the transaction is confirmed
# - Whether the anchoring service is legitimate

For complete verification in a production system, you would combine verify-proof with blockchain explorer APIs to confirm the transaction exists on-chain.

Integration Patterns

The verify-proof package fits well into existing Python applications. Here are common integration patterns:

# Flask API endpoint
from flask import Flask, request, jsonify
from verify_proof import hash_file, verify_proof
import tempfile
import os

app = Flask(__name__)

@app.route('/verify', methods=['POST'])
def verify_endpoint():
    uploaded_file = request.files['file']
    proof_data = request.json.get('proof')
    
    # Save uploaded file temporarily
    with tempfile.NamedTemporaryFile(delete=False) as tmp:
        uploaded_file.save(tmp.name)
        file_hash = hash_file(tmp.name)
        os.unlink(tmp.name)
    
    # Verify against proof
    result = verify_proof(file_hash, proof_data)
    
    return jsonify({
        "verified": result['verified'],
        "hash": file_hash,
        "blockchain": result.get('blockchain'),
        "tx_id": result.get('tx_id')
    })

Next Steps

The verify-proof package provides the foundation for blockchain timestamp verification in Python applications. For complete verification workflows, you'll want to:

  1. Combine it with blockchain explorer APIs for on-chain validation

  2. Implement proper logging and audit trails for verification attempts

  3. Add database storage for verification results and file metadata

  4. Consider caching hash calculations for large files

The source code is available on GitHub at https://github.com/Fulcrum-Enterprises/verify-proof, and the package supports all major Python versions. For CLI usage, the package also provides command-line tools for quick verification tasks.