CRUMB a card from devarno-cloud

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 SourceOriginPurpose
IRIS stored hashsprite.fingerprint["hash"] from iris-serviceWhat IRIS claims the fingerprint is
MERIDIAN stored hashOptional, provided by MERIDIAN clientWhat MERIDIAN claims the fingerprint is
Computed hashFresh computation via 5-stage pipelineThe 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 agree

Critical 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}
end

FingerprintResult 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

ScenarioCauseImpact
IRIS hash ≠ computedTampering in IRIS registrySprite identity compromised in IRIS
MERIDIAN hash ≠ computedStale mapping or tamperingSprite identity compromised in MERIDIAN
Both mismatchDifferent canonical pipelinesPipeline drift between systems
Engine exceptionMissing blake3 libraryFalls 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"]
  1. Tamper detection: If any system’s stored hash differs from the computed hash, the data has been modified
  2. Consensus validation: Multiple independent systems must agree on the identity
  3. 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