What leaves your server, and what we can learn from it.
Short version: you send six hex characters of a salted SHA-1 and an API key. We learn that one of your keys looked up one of 16,777,216 buckets at some time. We don’t learn the password, whether it matched, or whose it was.
What leaves the client
| Item | Sent to knownPass? |
|---|---|
| The password | Never. Hashing happens on your server. |
| The full hash | Never. You keep the 34-character suffix and compare locally. |
| 6-character prefix | Yes. The first six hex characters of SHA-1("Salted for knownpass.com: " + password). |
| API key | Yes, in the x-api-key header. Identifies your account, not your user. |
| IP, TLS, HTTP metadata | Yes, as with any HTTPS request from your server. Your end user’s IP is not involved unless you call us from the browser. |
| Username, email, user ID | Never. The endpoint has no field for them. |
What a prefix tells us
Six hex characters give 166 = 16,777,216 buckets. With 20 billion entries, each bucket holds about 1,200 candidate suffixes. Stated plainly: 20,000,000,000 ÷ 16,777,216 ≈ 1,192 entries per response, roughly 80 KB of JSON before compression. From a request we can tell:
- Yes: which bucket was asked for, by which key, when, and how often that key calls us.
- No: which of the candidates you were interested in, whether any of them matched, or who the end user is. The comparison never leaves your server.
A prefix on its own does not identify a password. Even for a known-weak password, the bucket contains over a thousand strong ones with the same first six characters.
Why the salt is public, and what it does
The salt string Salted for knownpass.com: is fixed and published. It adds no secrecy; its job is domain separation:
- A knownPass prefix cannot be looked up in Pwned Passwords or any other unsalted SHA-1 dataset, so our request logs, if they ever leaked, would be useless outside knownPass.
- An unsalted SHA-1 prefix captured from another service cannot be replayed against knownPass, and vice versa.
- SHA-1 is used as a lookup key over a public dataset, not to protect a stored secret. Your password store should keep using Argon2id, scrypt or bcrypt.
What we log
Per request: key ID, timestamp, response code and latency, for rate limiting, abuse prevention and debugging. Access logs rotate; we keep no long-term per-key request history and have no way to connect a prefix to a person. The privacy policy is the binding version of this list.
The Try-it demo on knownpass.com sends the same 6-character prefix, from the browser, with a public shared demo key. Nothing else.
If the API is down
Design the check to fail open: on timeout, network error, 429 or 5xx, let the flow continue, log that the check was skipped, and re-check at the next login or password change. What’s at risk during an outage is that a weak password slips through until then. Nothing else in your auth flow depends on us. There is no uptime SLA yet; the status page is updated by hand.
Abuse considerations
Reconstructing the dataset
A full crawl means roughly 17 million authenticated requests, each returning about 1,200 entries, throttled per key. The response carries no counts and no plaintexts, so the result is a list of salted hashes. The core dataset is derived from public material and is planned to be released openly anyway, so we rate-limit this rather than treat it as a secret.
Using the API as an oracle
The API answers “is this password known”, never “does this password belong to user X”. It cannot confirm a credential for a target account. It could help an attacker prune a candidate list, which public wordlists already allow offline; we don’t consider that a meaningful uplift, and per-key limits cap it.
Key leakage
Keys identify a customer account, not an end user. A leaked key lets someone spend your quota; it exposes no data about your users. Rotate it in the console. The demo key is public by design and throttled.
Network observers
An observer between you and us sees TLS to api.knownpass.com and a response size. At most that narrows the request to a bucket, which is the same thing we see.
What this does not protect against
knownPass is one control. It won’t stop phishing, credential stuffing with a password that never leaked, or the absence of MFA. It removes the passwords an attacker will try first.