Security

How Human Sender codes work, what we store, and where.

How codes are generated

Every Verify code is a one-time token generated server-side and bound to the sender's verified account. Minting a code requires a biometric confirmation (Face ID or fingerprint) on the user's registered mobile device. This means no code can be generated via API alone, in bulk, or without a live human physically present.

There are two types of codes:

  • Message codes — generated when signing an email, SMS, or message. Valid for 30 days. Can optionally be bound to the exact content of the message via a SHA-256 hash stored at the moment of signing.
  • Live call codes — 4-digit rotating codes valid for 2 minutes. Designed for live phone or video calls to prove the person on the call is who they claim to be, right now.

Content binding

When a message code is created with content binding enabled (the default for email), the message body is hashed with SHA-256 and stored alongside the code. The verification page shows: "Joel signed this exact message to you on 14 May 2026 at 09:32."

If the message is altered after signing — by a man-in-the-middle attack, a forwarded thread edit, or any other modification — the hash on the verification page will not match the presented message, and a clear warning is shown to the recipient. This is the strongest anti-tampering guarantee Verify provides.

Anti-abuse mechanisms

  • Biometric gate: Every code minting requires Face ID or fingerprint. Bots and scripts cannot pass this.
  • Rate limits: Free accounts are limited to 50 codes per day. Higher tiers have higher limits but are still rate-capped.
  • Badge revocation: Accounts found to be misusing the platform can have their badge revoked. All existing codes from that account are immediately invalidated.
  • Recipient binding: Codes can be bound to a specific recipient email address. If anyone else tries to verify using that code, the verification page flags the mismatch.
  • Escalation guard: Verification levels can only be increased by the system after a completed verification step. No user can promote their own trust level via the API.

What we store — and what we do not

We store

  • Email address
  • Phone number (encrypted)
  • Display name and username
  • Profile photo (optional, stored in EU)
  • SHA-256 hash of signed message bodies
  • Code metadata (timestamps, expiry, recipient hint)
  • Verification level and audit trail

We do not store

  • The plaintext message body
  • Biometric data (processed by Didit.me, not retained)
  • Private keys (Level 4: stored in device secure enclave only)
  • Payment details (handled by Stripe)
  • Any data outside the EU

EU data residency

All Human Sender data is stored and processed in the European Union. Our infrastructure sub-processors are:

Sub-processorPurposeRegion
SupabaseDatabase and storageEU (Frankfurt)
VercelApplication hostingEU (Frankfurt)
Didit.meIdentity and liveness verificationEU

Verification levels

Human Sender uses a five-level assurance ladder based on eIDAS and NIST 800-63 standards. Each higher level requires all previous levels.

Level 0Registered

Badge: None · Email address confirmed.

Level 1Personal Verified

Badge: Grey checkmark · Live human face confirmed via passive liveness check (micro-movements, skin-tone pulse).

Level 2Identity Verified

Badge: Blue checkmark · Government-issued ID uploaded and matched to the live face.

Level 3Identity + Employer Verified

Badge: Blue checkmark + employer logo · Employer confirms the user's role via SSO or admin invitation.

Level 4Cryptographically Bound

Badge: Gold checkmark · Private key stored in device secure enclave; codes signed on-device.

For full details on data processing see our Privacy Policy and Terms of Service. Security concerns can be reported to legal@humansender.com.