How IM Verify works
Deepfakes Can Fool Anyone
AI-generated voice and video are now indistinguishable from real humans. A scammer can clone your family member's voice from a few seconds of audio, call you, and ask for money. How do you know it's really them?
Traditional solutions like voice recognition or video analysis are losing the arms race against AI. We need a completely different approach—one that doesn't try to detect fakes, but instead proves authenticity.
Cryptographic Identity Verification
IM Verify uses the same mathematics that secures your bank account and encrypted messages. When you set up the app, it generates a unique cryptographic identity that only you possess. When you add a contact, you establish a shared secret that only the two of you know.
During a call, both parties generate a time-based code from this shared secret. If the codes match, you know you're talking to the real person—not an AI impersonator.
Adding Contacts
Before you can verify someone, you need to establish a shared secret with them. IM Verify offers multiple methods, each with different trust levels.
QR Code
🟢 In PersonScan each other's QR codes when you're physically together, then confirm SAS codes match. The QR contains an ephemeral public key and identity fingerprint.
Bluetooth
🟢 In PersonExchange keys over encrypted Bluetooth Low Energy with SAS code confirmation. Works when cameras aren't convenient—in low light, crowds, or for accessibility.
Online (Async)
🌐 OnlineShare invite and encryption codes over any channel. The invitee accepts later, and you verify with SAS codes on a voice call.
Real-time
🌐 OnlineWhen both parties are on a call, exchange happens instantly via WebSocket. Both see codes at the same time for immediate verification.
Key Exchange Protocol
When you add a contact, the following cryptographic exchange occurs:
Generate Ephemeral Keys
Both parties generate a temporary X25519 key pair for the exchange. These are used only once and discarded.
Exchange Public Keys
Public keys are exchanged via QR, Bluetooth, or online (encrypted with a shared code). Identity fingerprints are also exchanged.
Derive Shared Secret
ECDH (Elliptic Curve Diffie-Hellman) derives a shared secret from the two public keys. Both parties compute the same value independently.
Derive Verification Seed
HKDF-SHA256 derives a verification seed from the shared secret plus both fingerprints. This ensures each relationship has a unique seed.
Store Locally
The verification seed is stored in the iOS Keychain, protected by hardware encryption and optional biometric authentication.
// Simplified key derivation
let sharedSecret = ECDH(myPrivateKey, theirPublicKey)
let sortedFingerprints = [myFingerprint, theirFingerprint].sorted()
let seed = HKDF-SHA256(sharedSecret, salt: sortedFingerprints, info: "itsme-verification-seed-v1")
Time-Based Codes
Verification codes are generated using a TOTP-like algorithm with modifications for voice readability:
Time Window
The current Unix timestamp is divided into 30-second windows. Both devices use the same time (synced via NTP).
HMAC Computation
HMAC-SHA256 is computed using the verification seed and time window as inputs.
Code Extraction
The hash is converted to a NATO phonetic word (26 options) and 3 digits (000-999), giving 26,000 possible codes.
Why NATO Words?
NATO phonetic words (Alpha, Bravo, Charlie...) are designed to be unambiguous over poor audio connections. Combined with numbers, they're easy to speak aloud and verify during a phone call.
Remote Contact Addition
When you can't meet in person, online exchange allows secure contact addition with end-to-end encryption.
How It Works
Generate Codes
The inviter generates two 8-character codes: an INVITE code (room identifier) and an ENCRYPTION code (key material).
Share Codes
Codes are shared via a separate secure channel (phone call, Signal, etc.). The encryption code should never be sent through the same channel as your main conversation.
Encrypted Exchange
Both parties' identity information is encrypted with a key derived from the encryption code (HKDF → AES-256-GCM). The server only sees encrypted blobs.
SAS Verification
After exchange, both parties verify a Short Authentication String (SAS) code on a voice call to confirm no man-in-the-middle attack occurred.
Server-Blind Security
The encryption code never touches our server. Even if our server were compromised, attackers could only see encrypted data they cannot decrypt.
Device Binding
Each contact relationship includes a "device secret" that ties your identity to your specific physical device. This acts as a second layer of protection — even if someone obtains your verification codes, they can't replicate your device secret.
| Scenario | What Happens |
|---|---|
| Normal verification | Code matches, device secret matches — all good ✓ |
| Contact changed phones | Code matches, device secret differs — "degraded" warning ⚠️ |
| Impersonation attempt | Code doesn't match — verification fails ✗ |
What Happens When Someone Changes Phones
Device secrets are bound to your physical device and do not transfer — not even when you use the identity export feature. This means any phone change will cause you to appear "degraded" to each of your contacts.
When this happens, the app displays a degradation code on your phone. You share this code with each affected contact (by telling them over a call, text, etc.). They enter the code in their app to confirm the phone change is legitimate. Once confirmed:
- Verification still works — your shared verification codes are unaffected because they're based on your cryptographic seed, not the device secret
- The contact is simply shown with a warning badge until device secrets are refreshed
Restoring Full Status
When you and your contact are next together in person, use the Security PIN Update feature. Both phones connect over encrypted Bluetooth and exchange fresh device secrets, restoring the contact to full verified status — no need to delete and re-add.
Trust Levels
Different exchange methods provide different levels of trust assurance:
| Method | Badge | Trust Level | Why |
|---|---|---|---|
| QR Code (In Person) | 🟢 In Person | Highest | Physical presence + SAS verbal confirmation |
| Bluetooth | 🟢 In Person | Highest | Physical proximity + SAS verbal confirmation |
| Online Exchange | 🌐 Online | High | E2EE payloads + SAS verbal confirmation |
Security Properties
- Forward secrecy: Ephemeral keys are discarded after exchange
- Replay protection: Codes change every 30 seconds; time windows are never reused
- Device binding: Detects if contact changes phones, with in-person recovery
- End-to-end encryption: Server cannot read exchange data or verification messages
- Online Verify: Challenge-response protocol with SAS confirmation over encrypted WebSocket — verify contacts during a phone call or even via instant messaging
- Offline capable: Voice Verify works without internet when you're together
- No accounts: No email, no phone number, no tracking
- Encrypted at rest: Contacts encrypted with AES-256-GCM using a device-bound key
- Biometric protection: Face ID / Touch ID secures access