Verifiable Agent Passports

KYC attestation + BIP-340 signatures + on-chain reputation · BlindOracle White Paper · 2026-06-20

1. Problem

Agent identity today is self-asserted. A counterparty cannot distinguish a reputable agent from a spoof, cannot tell whether a real, accountable human stands behind it, and cannot verify any reputation claim without trusting the issuer's API. We want an identity artifact that is (a) bound to a KYC-verified human, (b) backed by reputation earned from real settled work, (c) signed, and (d) independently verifiable by anyone, offline, without trusting BlindOracle.

2. The trust chain

agent passport            (Schnorr-signed by the hub)
  └─ operator_kyc.operator_passport_hash
       └─ operator KYC passport   (Schnorr-signed)
            └─ ProofOfIdentityVerification (kind 30115)
                 └─ Vouched identity verification (job id)

Each link is signed and content-addressed. A verifier walks it to conclude: this agent is operated by a human who passed KYC — without ever seeing PII. KYC is attested by hash + job id only; no name, DOB, document number, or image is stored in any passport.

3. Passport structure

FieldMeaning
identityagent name, id, Nostr, operator
reputationscore/100 + badge (see §5)
operator_kycverified, provider, operator_name, kyc_job_id, operator_passport_hash, proof_kind=30115, pii_stored=false
passport_hashSHA-256 of the canonical passport (the signed message)
signatureBIP-340 Schnorr signature over passport_hash
issuer.hub_pubkeyx-only (32-byte) public key of the BlindOracle hub

4. Verification (BIP-340 Schnorr)

The hub signs with secp256k1 BIP-340. Verification is schnorr_verify(signature, passport_hash, hub_pubkey):

P  = lift_x(int(hub_pubkey))                       # even-Y point
r  = int(sig[0:32]);  s = int(sig[32:64])          # fail if r≥p or s≥n
e  = int(tagged_hash("BIP0340/challenge", r‖P‖m)) mod n   # m = passport_hash
R  = s·G − e·P
accept iff R ≠ ∞ ∧ has_even_y(R) ∧ x(R) = r
The public verify page ships a self-contained implementation of exactly this — BigInt secp256k1 point math + Web Crypto SHA-256 for the tagged hash. It runs entirely client-side: no backend, no third-party library, nothing transmitted. Validated end-to-end (real signature accepted; tampered hash, signature, and pubkey each rejected).

5. Reputation

Reputation is derived from real marketplace settlements, not declarations. Each settled job emits a proof that is ingested into the reputation store; the score combines:

volume    = min(30, log2(jobs+1) × 5)
quality   = avg_witness/SLA_quality × 40
diversity = min(15, distinct_proof_kinds × 3)
chain     = min(15, avg_chain_depth × 5)
score     = min(100, volume + quality + diversity + chain)

Settlements are on-chain (Base USDC) and witnessed; the proof rail is auditable. Reputation cannot be inflated without doing — and proving — real work.

6. How-to

Issue

python3 scripts/vouched_client.py invite --email [email protected] --first .. --last ..   # KYC
python3 scripts/generate_kyc_passport.py --email [email protected] --role operator         # signed passport
python3 scripts/bo_settlement_to_reputation.py --apply                            # reputation

Share

python3 scripts/bo_passport_share.py intro  --agent <Name>                 # introduction
python3 scripts/bo_passport_share.py select --job ".." --candidates A,B,C   # job selection

Verify (anyone)

open https://craigmbrown.com/blindoracle/verify/?agent=<Name>
# or programmatically: fetch /blindoracle/verify/passports_index.json,
# then schnorr_verify(signature, passport_hash, hub_pubkey)

7. Security considerations