Cross-System Fingerprint Verification
iris advanced 6 min read
ELI5
Cross-system fingerprint verification is like when two banks compare their records of the same customer. Bank A says the customer’s PIN hash is A1B2, Bank B says it’s C3D4, and a neutral third party recomputes it from the original data. If all three match, everyone agrees this is the same person. If any differ, someone has the wrong data — or there’s been tampering.
Technical Deep Dive
Verification Actors
flowchart LR A["IRIS System"] -->|stores| B["iris_hash"] C["MERIDIAN System"] -->|stores| D["meridian_hash"] E["Verifier"] -->|recomputes| F["computed_hash"] B --> G{"Compare"} D --> G F --> G G -->|All match| H["VERIFIED ✓"] G -->|Any mismatch| I["FAILED ✗"]Three-Way Comparison
The FingerprintVerifier in iris-meridian-adapter performs a three-way comparison:
| Hash Source | Origin | Purpose |
|---|---|---|
| IRIS stored hash | sprite.fingerprint["hash"] from iris-service | What IRIS claims the fingerprint is |
| MERIDIAN stored hash | Optional, provided by MERIDIAN client | What MERIDIAN claims the fingerprint is |
| Computed hash | Fresh computation via 5-stage pipeline | The ground truth recomputed from canonical data |
Verification Algorithm
def _compare_hashes(iris_hash, computed_hash, meridian_hash=None): # Case-insensitive comparison if iris_hash.lower() != computed_hash.lower(): return False # IRIS data has been tampered with if meridian_hash and meridian_hash.lower() != computed_hash.lower(): return False # MERIDIAN data doesn't match return True # All present hashes agreeCritical rule: Returns True only if all present hashes match. A missing meridian_hash is ignored, but if provided, it must match.
Verification Flow
sequenceDiagram participant Client as MERIDIAN Client participant Adapter as iris-meridian-adapter participant Verifier as FingerprintVerifier participant IrisClient as IrisServiceClient participant Iris as iris-service
Client->>Adapter: VerifyFingerprint(iris_sprite_id, expected_hash?, algorithm?)
Adapter->>IrisClient: get_sprite(iris_sprite_id) IrisClient->>Iris: GET /v1/sprites/{id} Iris-->>IrisClient: Sprite IrisClient-->>Adapter: SpriteData
Adapter->>Verifier: verify_sprite_fingerprint(sprite, expected_hash, algorithm, meridian_hash)
Verifier->>Verifier: Build canonical dict from sprite Note over Verifier: Exclude: id, created, fingerprint Verifier->>Verifier: Stage 2: Normalize (sorted keys) Verifier->>Verifier: Stage 3: Canonical JSON (compact) Verifier->>Verifier: Stage 4: UTF-8 encode Verifier->>Verifier: Stage 5: Blake3 hash → computed_hash
Verifier->>Verifier: _compare_hashes(iris_hash, computed_hash, meridian_hash)
alt All match Verifier-->>Adapter: verified: true Adapter-->>Client: FingerprintResult {verified: true, iris_hash, meridian_hash, computed_hash} else Mismatch Verifier-->>Adapter: verified: false Adapter-->>Client: FingerprintResult {verified: false, mismatch_details} endFingerprintResult Protobuf
message FingerprintResult { HashAlgorithm algorithm = 1; // BLAKE3 or SHA256 string iris_hash = 2; // Hash from IRIS system string meridian_hash = 3; // Hash from MERIDIAN (optional) string computed_hash = 4; // Freshly computed hash bool verified = 5; // True if all present hashes match google.protobuf.Timestamp verified_at = 6; string summary = 7; // Human-readable summary}Algorithm Mapping
def _algorithm_name(algorithm_enum): mapping = { 1: "blake3", # HashAlgorithm.BLAKE3 2: "sha256", # HashAlgorithm.SHA256 } return mapping.get(algorithm_enum, "blake3")Failure Scenarios
| Scenario | Cause | Impact |
|---|---|---|
| IRIS hash ≠ computed | Tampering in IRIS registry | Sprite identity compromised in IRIS |
| MERIDIAN hash ≠ computed | Stale mapping or tampering | Sprite identity compromised in MERIDIAN |
| Both mismatch | Different canonical pipelines | Pipeline drift between systems |
| Engine exception | Missing blake3 library | Falls back to SHA-256; logged as warning |
Security Properties
flowchart TD A["Cross-System Fingerprint Verification"] --> B["Tamper Detection"] A --> C["Consensus Validation"] A --> D["Pipeline Integrity"] B --> E["Any hash mismatch = alarm"] C --> F["All systems must agree"] D --> G["Same 5-stage pipeline required"]- Tamper detection: If any system’s stored hash differs from the computed hash, the data has been modified
- Consensus validation: Multiple independent systems must agree on the identity
- Pipeline integrity: Both systems must implement the identical 5-stage canonical pipeline (DEC-005)
Key Terms
- Cross-system verification → Comparing identity hashes across independent systems to detect tampering or drift
- Three-way comparison → IRIS hash vs. MERIDIAN hash vs. freshly computed hash
- Ground truth → The freshly computed hash from canonical data; the ultimate arbiter
- Case-insensitive comparison → Hex strings are compared lowercase to avoid encoding mismatches
- Pipeline drift → When two systems use different canonical serialization rules, causing hash mismatches on identical data
- Tamper detection → Using cryptographic hashes to detect unauthorized modifications to stored data
Q&A
Q: What if the verifier itself is compromised?
A: The verifier fetches fresh sprite data from iris-service and recomputes the hash independently. To compromise verification, an attacker would need to control both the IRIS service and the verifier — a much harder attack than tampering with stored hashes alone.
Q: Why compare case-insensitively?
A: Hex encoding can vary in case (A1B2 vs a1b2). The hash value is identical regardless of case, so the comparison normalizes to lowercase to prevent false mismatches.
Q: Can verification work with SHA-256 instead of Blake3?
A: Yes. The HashAlgorithm enum supports both BLAKE3 (1) and SHA256 (2). The verifier uses the algorithm specified in the request, defaulting to Blake3. Both systems must agree on the algorithm.
Q: What happens if a sprite is updated in IRIS after mapping?
A: The mapping’s fingerprint_hash becomes stale. The next VerifyFingerprint call will detect the mismatch (IRIS hash ≠ computed hash), and the mapping status should transition to SUSPENDED until re-verification.
Q: How often should verification be run? A: Ideally before every sensitive operation (token generation, privileged access). For long-running mappings, a periodic re-verification schedule (e.g., hourly) balances security with performance.
Examples
Cross-system verification is like a diamond certification:
- IRIS = The jeweller who sold the diamond (has a certificate with the gem’s laser inscription)
- MERIDIAN = The insurance company (has their own copy of the certificate)
- Verifier = An independent gem lab (examines the actual diamond under a microscope)
- Laser inscription = The fingerprint (unique identifier etched into the gem)
- Three-way check = All three parties compare their records of the inscription
- Mismatch = If the lab’s reading differs from either certificate, the diamond may be a fake or the certificate forged
- Case-insensitive = The inscription reads the same whether photographed in bright light or shadow
neighbors on the map
- NFT-Style Capability Token System designing authorization for cross-system sprite access
- STRATT Protocol Overview learning STRATT for the first time