Verify a Proofie

Upload any Proofie photo. The QR code embedded in the image contains all the cryptographic data needed to verify it independently.

📷
Upload a Proofie Photo
Drop a photo here or click to select.
The QR code in the photo contains all the verification data.

How Verification Works

1
Upload Photo
Drop or select any Proofie photo taken with the app
2
QR Code Scanned
The embedded QR code is decoded to extract the cryptographic proof data
3
Hash Verified
The verification hash is recomputed and matched to confirm authenticity

Why Verification Proves This Selfie Is Real

Every Proofie is cryptographically signed at the moment of creation using your device's biometric hardware. Here's why that matters.

🧬

Biometric Signature at Creation

When you take a Proofie, your iPhone requires a Face ID or Touch ID scan before it will sign the proof. The cryptographic signature is generated by a passkey locked inside your device's secure hardware — it can only be unlocked by your face or fingerprint. No biometric scan, no signature.

📍

Location Locked Into the Proof

Your GPS coordinates and what3words address are captured at the exact moment of the biometric scan and baked into the signed data. The location cannot be changed after signing because it would invalidate the cryptographic hash. The proof mathematically binds you to that place.

Blockchain Timestamp

The proof is anchored to a specific block on the blockchain, giving it an immutable timestamp. This block hash is part of the signed data, proving the photo couldn't have been created before that block existed. No one can backdate a Proofie.

🔍

QR Code = Independent Audit

The QR code embedded in every Proofie contains the public key, timestamp, location, and verification hash. Anyone can recompute the hash from these values and confirm nothing was tampered with — no app, account, or server needed.

What Would Make It Fail

If the person didn't scan their Face ID at that location, verification fails

The passkey signature can only be produced by the registered biometric on the specific device. If someone tries to fake a Proofie — using a different device, a different face, a spoofed location, or an altered timestamp — the verification hash won't match when recomputed. The math breaks. There is no way to produce a valid signature without the real person, at the real location, at the real time.

About the Identity Proof ID

Every Proofie displays an 8-character fingerprint — like 7C78-6C26 — derived directly from the person's Face ID passkey. Here is exactly how it works, and how you can verify it yourself without trusting this server.

🔑

How the Proof ID is Generated

When someone registers with the app, their iPhone creates a passkey — a cryptographic key pair stored inside Apple's Secure Enclave, unlockable only by Face ID. The public key from that pair is embedded in every Proofie's QR code.

The Proof ID is a fingerprint of that public key: SHA-256(publicKey) → first 8 hex characters → formatted XXXX-XXXX. Same person, same device, same Face ID = the same Proof ID every single time, computed deterministically. No database lookup required.

🔁

What If the Key Changes?

If someone gets a new phone, reinstalls the app, or resets Face ID, a new passkey is generated. This creates a new public key — and therefore a new Proof ID. The person's old Proof ID is archived in their account history.

⚠️ If you are verifying someone and the Proof ID differs from one you have seen before, it may mean they recently re-registered (legitimate) — or someone else is using their account (worth scrutinizing).

🛠️ Verify It Yourself (DIY) — Run the Full Script

💡 Verify it yourself! The QR code in every Proofie contains all the data needed for independent verification. Upload a Proofie above to get this script pre-filled with real values. Or copy the template below and fill in the values manually.

Run the script in any third-party JavaScript environment:

// Proof of Life — Independent Verification Script
// Copyright © 2026 Alibi Ledger, LLC. All rights reserved.
// US and international patents pending.
// Run in: playcode.io, replit.com, codesandbox.io, or Node.js
// No external packages needed — uses built-in Web Crypto API

// Upload a Proofie above to get a pre-filled version with real values.
// These values come from the QR code embedded in the proof photo.
const EXPECTED_HASH = 'XXXX-XXXX-XXXX'; // verification hash from QR
const PUBLIC_KEY_B64 = '...';            // public key from QR
const TIMESTAMP = 0;                     // unix timestamp from QR
const BLOCK_HASH = '0x...';             // block hash from QR
const BLOCK_NUMBER = 0;                  // block number from QR
const W3W = 'word.word.word';           // location from QR
const SIGNATURE_FINGERPRINT = null;      // SHA256(passkeySignature)[0:16] from QR (v3+ only)

async function verify() {
  console.log('=== Proof of Life \u2014 Independent Verification ===\n');

  console.log('1. Proof data (from QR code):');
  console.log('   Location:', W3W || 'N/A');
  console.log('   Timestamp:', TIMESTAMP, '(' + new Date(TIMESTAMP * 1000).toISOString() + ')');
  console.log('   Block:', BLOCK_NUMBER);
  console.log('   Signature fingerprint:', SIGNATURE_FINGERPRINT || 'N/A (legacy proof)');

  // Formula: SHA-256(publicKey:timestamp:ReallyYouReallyThere_v1[:blockHash][:w3w][:signatureFingerprint])
  console.log('\n2. Recomputing verification hash...');
  let hashInput = PUBLIC_KEY_B64 + ':' + TIMESTAMP + ':ReallyYouReallyThere_v1';
  if (BLOCK_HASH) hashInput += ':' + BLOCK_HASH;
  if (W3W) hashInput += ':' + W3W;
  if (SIGNATURE_FINGERPRINT) hashInput += ':' + SIGNATURE_FINGERPRINT;
  const hashBuffer = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(hashInput));
  const hashHex = Array.from(new Uint8Array(hashBuffer))
    .map(b => b.toString(16).padStart(2, '0')).join('');
  const first24 = hashHex.substring(0, 24);
  const base36 = BigInt('0x' + first24).toString(36).toUpperCase();
  const padded = base36.substring(0, 12).padEnd(12, '0');
  const computed = padded.substring(0, 4) + '-' + padded.substring(4, 8) + '-' + padded.substring(8, 12);

  console.log('   Expected:', EXPECTED_HASH);
  console.log('   Computed:', computed);
  console.log('   Match:', computed === EXPECTED_HASH ? 'YES \u2713' : 'NO \u2717');

  console.log('\n3. Anti-backdating (block binding):');
  console.log('   Block hash:', BLOCK_HASH);
  console.log('   Verify at: https://arbiscan.io/block/' + BLOCK_NUMBER);

  console.log('\n=== SUMMARY ===');
  console.log('Hash verified:', computed === EXPECTED_HASH ? 'YES \u2713' : 'NO \u2717');
  console.log('Public key present:', PUBLIC_KEY_B64.length > 10 ? 'YES' : 'NO');
  console.log('Block binding present:', BLOCK_HASH ? 'YES' : 'NO');
  console.log('Passkey bound:', SIGNATURE_FINGERPRINT ? 'YES (v4)' : 'NO (legacy)');
}

verify().catch(e => console.error('Error:', e));

ℹ️ Upload a Proofie photo above — this script will be automatically filled with the real values from the QR code.

Available Now
Download the App
Create biometric-verified Proofies™ with Face ID or biometrics. Prove you are real.