Six months of tinkering produced IRLid — two people meet, scan each other's QR codes, get a cryptographically signed receipt proving co-location within 12 metres. No app, no accounts, no biometrics, no central server. Just ECDSA P-256 and a bit of GPS, running entirely in the browser via Web Crypto API.
The 4am Bug
Shipped v3 last week. Thought it was done. Four hours later — every receipt showing 23% verified instead of 100%.
Root cause: GPS coordinates were being stripped server-side before returning to the client. But the ECDSA signature was computed with those coordinates. Strip them → client can't recompute the original hash → signature check fails. Every. Single. Receipt.
Obvious in hindsight. Not obvious at 4am.
The Deeper Lesson: Canonical Serialisation
Moved from JSON.stringify() to canonical() for payload hashing before ECDSA signing. JSON property order isn't guaranteed across environments — same object, different hash, broken signature.
New: Embeddable Widget
Any site can embed IRLid as a human-verification step — one iframe, postMessage API, no SDK. Think reCAPTCHA but you prove you've met a real human. Demo: https://irlid.co.uk/demo-login.html
Honest Limitations
GPS is self-reported. Cooperative trust model only — not proof-of-presence to a sceptical third party. Documented honestly in PROTOCOL.md on GitHub.
Top comments (0)