A claims adjuster uploads photos from a loss site. The blockchain anchor proves they existed before the storm hit. But how do you actually verify that proof without calling external APIs? You need local verification that works offline.
That's what I built the verify-proof package for. Hash a file, check it against a blockchain proof, get a clear verified/not-verified result. No network calls required.
Install and Hash Files
The package gives you both CLI tools and Python functions. Start with installation:
pip install verify-proof
The CLI can hash any file:
verify-proof hash document.pdf
# SHA256: a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456
# File: document.pdf
In Python, use hash_file() for the same thing:
from verify_proof import hash_file
# Hash any file type
file_hash = hash_file("evidence.jpg")
print(f"SHA256: {file_hash}")
# SHA256: a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456
The function returns a 64-character hex string. Same algorithm the blockchain anchors use.
Working with Proof Dictionaries
Blockchain proofs come as JSON files with specific fields. The package expects these keys:
proof_dict = {
"hash": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
"algorithm": "sha256",
"blockchain": "polygon",
"tx_id": "0x1234567890abcdef1234567890abcdef12345678",
"anchored_at": "2024-03-15T10:30:00Z",
"service": "ProofLedger"
}
If the proof includes a merkle path (for Bitcoin batch anchoring), add:
proof_dict["merkle_path"] = [
{"position": "left", "hash": "abc123..."},
{"position": "right", "hash": "def456..."}
]
The verify_proof() function takes your file hash and this proof dictionary:
from verify_proof import verify_proof
result = verify_proof(file_hash, proof_dict)
if result["verified"]:
print(f"✓ Verified on {result['blockchain']}")
print(f" Transaction: {result['tx_id']}")
print(f" Anchored: {result['anchored_at']}")
else:
print(f"✗ Verification failed: {result['error']}")
Complete Verification Script
Here's a working script that loads a proof file and verifies any document:
import sys
from verify_proof import hash_file, verify_proof, load_proof
def verify_document(file_path, proof_path):
"""Verify a file against its blockchain proof."""
# Hash the file
print(f"Hashing {file_path}...")
file_hash = hash_file(file_path)
print(f"SHA256: {file_hash}")
# Load the proof
print(f"Loading proof from {proof_path}...")
proof = load_proof(proof_path)
# Verify
result = verify_proof(file_hash, proof)
if result["verified"]:
print("\n✓ VERIFICATION SUCCESSFUL")
print(f" Blockchain: {result['blockchain']}")
print(f" Transaction ID: {result['tx_id']}")
print(f" Anchored at: {result['anchored_at']}")
print(f" Service: {result['service']}")
# Show merkle verification if present
if result.get("merkle_verified"):
print(f" Merkle root: {result['merkle_root']}")
else:
print("\n✗ VERIFICATION FAILED")
print(f" Error: {result['error']}")
print(f" File hash: {result['file_hash']}")
print(f" Proof hash: {result['proof_hash']}")
return result["verified"]
if __name__ == "__main__":
if len(sys.argv) != 3:
print("Usage: python verify.py <file> <proof.json>")
sys.exit(1)
file_path = sys.argv[1]
proof_path = sys.argv[2]
verified = verify_document(file_path, proof_path)
sys.exit(0 if verified else 1)
Run it like this:
python verify.py contract.pdf contract_proof.json
The script handles both simple proofs and merkle-tree proofs. It prints clear success/failure output and exits with the right code for shell scripting.
What This Gets You
Offline verification means opposing counsel can't claim the proof service was down when they tried to verify. The adjuster can verify evidence without internet access. The forensic examiner can validate timestamps from an air-gapped machine.
The package does pure cryptographic verification. It checks that your file hash matches the proof, validates merkle paths if present, and confirms all the signatures line up. It doesn't make network calls to confirm the transaction exists on-chain, but that's often fine. You're proving the file existed when the anchor was created, not that the blockchain transaction was valid.
For batch verification of many files, wrap this in a loop. For CI/CD integration, there's a GitHub Action. For command-line work, the CLI tools work in any shell script.
The verify-proof package source is on GitHub. The PyPI page has more examples. I built it to give everyone the same verification logic, whether you're running ProofLedger, ProofAnchor, or any other blockchain anchoring service that produces compatible proofs.