// technical & threat-model overview

How ReallyFrom.me works

ReallyFrom.me exists because “take my word for it” stopped being good enough. It would be strange to ask you to take our word for it instead. So here is what happens when someone verifies a message, what the record does and does not prove, and where the limits are. The limits are the most important part.

01 · what it proves

The holder of this account's passkey approved these exact words

Your passkey — a private key held in your device's secure hardware, which cannot be copied off it — signs a challenge that is the fingerprint of the message. Because the signature covers the words themselves rather than a random number, a verification is checkable without trusting our database.

  • The passkey belongs to this account and was registered to it earlier.
  • The text recorded at that moment has not changed since.
  • The text you are checking is identical to it, after the normalization below.
02 · what it does not prove

Stated plainly

  • Not that the account holder is who they say they are. Anyone can register with any display name. What an account has actually proven is shown by its badges. An unbadged account has proven nothing beyond controlling an email address.
  • Not that the message is true. We verify authorship and wording, never accuracy.
  • Not that it was ever sent. We record approval, not delivery.
  • Not that the person's device was secure. A passkey proves possession of the device, not the identity of whoever is holding it.
  • Not which copy is honest. If your copy differs from what was approved, we say so — we cannot say who altered it.
03 · canonicalization

What “the exact words” means, exactly

Mail clients rewrap paragraphs, convert line endings and normalize Unicode differently. Comparing raw bytes would fail honest recipients constantly. So before hashing — at approval and at check time alike — we apply exactly this, and nothing else:

input.normalize("NFC").replace(/\s+/g, " ").trim()

Unicode goes to composed form; every run of whitespace becomes a single space; leading and trailing whitespace is dropped. Capitalization, punctuation, spelling, emoji, numbers and word order are never normalized. Changing “we will not proceed” to “we will now proceed” is a mismatch. Only the shape of whitespace is forgiven.

This is the single most important design decision in the product, which is why it is published rather than described. It lives in one function used by every path — web app, API and extension — and a test suite asserts the server and extension implementations agree character for character.

04 · fingerprints

A hash comparison, not a text comparison

The canonical text is hashed with SHA-256. Checking compares digests: match or no match, with no middle ground. When a check fails on a public verification we also show how close the text was, using Dice's coefficient over character bigrams — purely to distinguish a copying slip from a rewrite. It is never a verdict, never shown as a pass, and capped at 99 so only a true hash match can display as 100. On private verifications the score is withheld entirely, so it cannot be used to probe hidden wording one guess at a time.

05 · verify it yourself

Checking a verification without trusting us

Every content-bound verification publishes its proof. Fetch the record and the proof object carries the signature, the data it was signed over, and the public key that verifies it:

GET https://reallyfrom.me/api/public/<username>/<publicId>
  1. Canonicalize your copy of the message and take its SHA-256 digest.
  2. Base64url-encode it and confirm it equals the challenge inside clientDataJSON. This ties the signature to your copy.
  3. Confirm the origin is ours, the type is webauthn.get, and the RP ID hash in the first 32 bytes of authenticatorData is SHA-256 of reallyfrom.me.
  4. Verify the signature over authenticatorData ‖ SHA-256(clientDataJSON) with the published public key, per the WebAuthn specification.

If those pass, the holder of that passkey approved that exact message — whatever our database says, and whether or not we are still around.

06 · immutability

Records are added to, never rewritten

Revocation does not delete or alter a record; it adds a timestamp, and the page then shows both times — approved, and withdrawn. Corrections chain forward: a new verification points at an earlier one, which gains a link to its successor without being modified.

Administrators cannot alter verified content. They can suspend an account for impersonation or abuse and take a profile offline, and every such action is written to an append-only audit log. There is no interface — and no intended future interface — for editing what someone approved.

07 · what we store

And what we deliberately do not

  • Private verifications keep the fingerprint, not the words. The message is hashed and discarded — nothing to leak, disclose, or be compelled to produce. You cannot read it back from us either. Recipients still check by pasting their copy, because checking has always been a hash comparison.
  • Passwords are hashed with scrypt and a unique random salt; session tokens and email links are stored only as SHA-256 hashes, so a database leak cannot replay them.
  • We hold the public half of your passkey only. The private key never leaves your device.
  • ID documents and biometrics are never collected or received. Identity checks are run by a specialist partner who returns a pass or fail.
  • Inbound checking in the extension runs on your device: it fetches a record's fingerprint and hashes the message locally. Your inbox is never transmitted to us.
08 · known limitations

What we would rather you learn here than discover later

  1. Timestamps are ours. The signature proves what was approved and by which key — not when. There is no third-party timestamping authority or public transparency log, so a record's time is our clock in our database. A public append-only log would remove that assumption, and is the most valuable thing left on this list.
  2. Older records are not independently verifiable. Content binding shipped on 15 August 2026. Earlier records carry a genuine approval, but confirming one means trusting our database.
  3. Biometric confirmation is requested, not required. The server asks for user verification but currently accepts an assertion where the authenticator confirmed presence without a biometric or PIN.
  4. Display names are not locked below the identity rung, so an account can be renamed after earning a badge.
  5. Look-alike domains are unaddressed. Nothing currently stops a convincing imitation of a verification page on a similar domain.
  6. Rate limiting is per-instance and held in memory, so under scaling the effective limits are looser than configured.
  7. Sign-in has no second factor. Passkeys protect the act of approving; the account itself is protected by a password alone.
09 · reporting

Found a problem?

Security reports go to support@reallyfrom.me, or through the support form. Tell us what you found and how to reproduce it. We will not pursue anyone who reports a vulnerability in good faith, and we will credit you if you would like us to. If you find something on this page that is wrong, that counts too.

← Back to reallyfrom.me