Security
Threat Model
A security tool is only meaningful relative to a specific adversary. This page lists the attackers we designed against, states honestly where the design stops working, and tells you when you should be using something else.
Why an explicit threat model matters
"Is this secure?" is not an answerable question. "Secure against whom, doing what?" is. A tool that comprehensively defeats a database breach may be useless against malware on your laptop, and saying so is the difference between a security product and a security-flavoured one.
The cost of vagueness is real. Someone who believes a tool protects them against an adversary it does not defend against will take a risk they would otherwise have avoided. That is a worse outcome than using nothing.
Adversaries Inkrypt defends against
An attacker who breaches our database
Strongly defended. An attacker who exfiltrates every row obtains AES-256-GCM ciphertext, per-note random salts and IVs. There is no master key to steal, because none exists. Each note must be attacked independently, offline, against whatever password protects it — and per-note salting means cracking one gives no advantage on the next.
A network attacker
Strongly defended. All traffic is TLS, but more importantly the plaintext never enters the network at all. Even a complete break of TLS on a given connection would reveal only ciphertext, a salt and an IV.
Us — the service operator
Strongly defended, structurally. There is no code path in which our servers hold a decryption key. This is not a promise not to look; it is the absence of the capability to look. It follows that a legal demand can only produce ciphertext.
Someone who obtains only the share link
Defended, provided you split the channels. A share token retrieves ciphertext; the password decrypts it. Someone with just the link holds unreadable data. This protection evaporates entirely if you send both in the same message — see secure link sharing.
Long-term accumulation of secrets
Defended by expiry. The specific risk that a credential shared in 2023 is still readable in a chat archive today is addressed directly: expiry and view limits mean a stale link stops working by default, rather than staying live because nobody remembered to revoke it.
Adversaries only partially mitigated
An offline password-guessing attack
Partially mitigated. PBKDF2 at 310,000 iterations multiplies the cost of every guess, and per-note salts prevent precomputation and amortisation. But an attacker holding your ciphertext can grind at their own pace with no rate limit we can impose. Against a weak password, key stretching buys time and nothing more.
Your password is the binding constraint on this entire system. Four or more random words moves it from "hours" to "not worth attempting".
Automated link scanners
Partially mitigated. Corporate mail filters and chat link-preview bots fetch URLs automatically, which can consume a view-limited link before the human clicks. They obtain only ciphertext, so this is an availability problem rather than a confidentiality one — but it is a real and common annoyance. Allow two or three views when sending into a filtered environment.
Traffic and metadata analysis
Partially mitigated. We cannot read notes, but we necessarily observe that a request occurred, when, and against which slug. Slugs are not encrypted. An observer with access to our logs learns nothing about content but does learn that a note by a given name existed and was fetched.
Adversaries Inkrypt does not defend against
Malware on your device
Not defended. A keylogger or infostealer on your machine sees plaintext as you type it and captures the password as you enter it. Encryption happens after that point. No browser-based tool can defend below its own layer — if your endpoint is compromised, nothing running on it can be trusted.
The recipient
Not defended, and not defensible. Once someone can read a note they can screenshot it, copy it, photograph the screen or simply remember it. Expiry controls availability from our servers; it has no reach into anyone's memory or clipboard. Any product implying otherwise is misleading you.
A compromised or malicious code-delivery layer
Not defended. We serve the JavaScript that performs the encryption. A compromised operator — or an attacker with control of our delivery pipeline — could serve modified code that exfiltrates passwords. This is the fundamental limitation of all browser-delivered cryptography, and it applies to every web-based encryption tool without exception.
If this is your adversary, use something else
A forgotten password
Not defended, by design. There is no recovery. If we could restore access, we could read your notes — the two capabilities are identical. Availability is deliberately traded away for confidentiality.
Physical or legal coercion of the password holder
Not defended. Nothing here helps if someone can compel *you* to reveal the password. There is no duress mode and no plausible-deniability construction.
Known limitations we accept
The sections above describe adversaries. This one describes decisions — places where the current implementation is weaker than a reader might reasonably assume from the headline parameters. We publish them because a threat model that omits its own awkward parts is not a threat model, and because each one changes how you should use the product.
Share passwords are stored as an unsalted SHA-256 hash
What it is. When you protect a share link with a password, the server keeps a single-round, unsalted SHA-256 of it to check against what a recipient types. Hashes of that kind are fast to compute, which is exactly what you do not want: they are open to precomputed lookup tables and to very high-rate guessing, unlike the 310,000-iteration derivation protecting the content.
What it does not mean. That hash is not the decryption key and the ciphertext is not protected by it. The snapshot remains AES-256-GCM under a PBKDF2-derived key with a fresh random salt, exactly as described on the security architecture page. A database breach does not hand anyone your share contents.
What it does mean. For a password-protected share, the password you type *is* the key the content is derived from. So if an attacker holds both the stored hash and the ciphertext, recovering a weak password from the fast hash also recovers the content — and the expensive key derivation buys you nothing, because it is no longer the slow step.
What to do about it. If you set a share password, make it long and random rather than memorable — a generated passphrase, not a word you will recognise. If you do not specifically need the recipient to type something, use a passwordless share instead: the key is then a random value your browser generates and places in the link fragment, which is never transmitted to us and never stored in any form.
Notes do not expire; only share links do
Expiry times and view limits are properties of a share link, not of the note behind it. A note itself has no expiry mechanism: once created, its encrypted record persists until you overwrite it. When a share link expires, the share snapshot stops being retrievable — the note is untouched and still opens with its own password.
This surprises people who read "self-destructing" as applying to everything. It does not. If you need a note to stop existing, you must overwrite its contents yourself; there is no scheduled deletion to rely on.
Note names are stored in the clear
A note's name is its URL, and it is stored unencrypted. We can see that a note exists at a given name, when it was created and when it was last written — we simply cannot read what is inside it. Names also travel further than content does: into browser history, bookmarks, and anywhere the link is pasted. Treat the name as public, and keep the meaning inside the note.
The code-delivery problem is not solved, only disclosed
We describe this above as an adversary we do not defend against, and it belongs here too, because it is a limitation we have accepted rather than one we have mitigated. Every visit fetches our JavaScript and runs it, so the integrity of the encryption depends on the integrity of what we serve. What we can offer is that the claims on this site are checkable in your own browser — the method is set out in what zero-knowledge encryption actually means — and that we would rather document the gap than let it be inferred.
Summary
| Adversary | Defended | Basis |
|---|---|---|
| Database breach | Yes | Server holds only ciphertext; no master key exists |
| Network interception | Yes | Plaintext never transmitted |
| The service operator | Yes | No key ever present on our infrastructure |
| Legal demand for content | Yes | Only ciphertext can be produced |
| Leaked share link alone | Yes | Link retrieves ciphertext; password is separate |
| Offline password guessing | Partial | 310,000-iteration KDF; bounded by password strength |
| Metadata observation | Partial | Slugs and request timing are visible to us |
| Malware on your device | No | Plaintext exists before encryption runs |
| The recipient copying it | No | Outside any technical boundary |
| Compromised code delivery | No | Inherent to browser-delivered cryptography |
| Forgotten password | No | Deliberate — recovery would mean we hold a key |
| Coercion of the password holder | No | No duress or deniability mechanism |
If your situation falls in the bottom half of that table, the honest answer is that Inkrypt is not the right tool, and we would rather tell you that here than have you find out later.
The primitives referenced above are specified in NIST FIPS 197 for AES, NIST SP 800-38D for GCM and its authentication tag, and RFC 8018 for PBKDF2. The limits of key stretching against weak passwords are discussed in the OWASP Password Storage Cheat Sheet, and the browser-delivery problem is a property of the Web Cryptography API execution model rather than of any particular implementation.
Frequently asked questions
Is Inkrypt safe for highly sensitive information?
What is the single biggest weakness?
Could Inkrypt be forced to serve me modified code?
Does encryption protect me from the person I share with?
How often is this threat model reviewed?
Related reading
Security architecture
Exact algorithms, parameters and stored fields.
Read moreZero-knowledge encryption
How to verify a provider-blind claim on any service.
Read morePassword protection
Why your password is the binding constraint on all of this.
Read moreResponsible disclosure
Found something we got wrong? Tell us.
Read moreThink we have the model wrong?
We would rather be corrected than be confidently mistaken. Our responsible disclosure policy explains how to reach the people who maintain this page.
Open the notepad