SecurityKeyrook Authenticator
Written as if our own server were hostile
Nothing in a Keyrook tool depends on trusting the server it syncs through. This page sets out what that means in Keyrook Authenticator 0.4.1, the version in the Chrome Web Store and Edge Add-ons, what it does not protect against, and how to tell us about a problem.
- AES-256-GCMseals your accounts on your own device
- 600,000rounds of PBKDF2-SHA256 behind a master password
- 160 bitsof randomness in your recovery key
- 0host permissions at install: it cannot read the sites you visit
On your device
- Your accounts are encrypted with AES-256-GCM under a random data key. What is written to disk is a sealed envelope, kept free of anything that identifies you or your accounts.
- The data key is never stored in the clear. It is wrapped either by a key the browser holds for this installation and will not hand out, or by a key made from your master password with PBKDF2-SHA256 at 600,000 rounds.
- A recovery key of 160 random bits wraps the same data key a second time, so it still works after you change your password.
- Codes are worked out on your device from the secret and the clock — six to ten digits, or Steam Guard's five characters. No server is asked for one.
- The extension asks for no host permissions at install. Reading a
QR code from a page and filling in a code both run under
activeTab, which the browser grants only for the tab you opened the extension on. A web page cannot drive the vault. - Nothing is fetched to show a service's logo: the artwork ships inside the extension.
Unlocking
- A vault with a master password can also open with the computer's own check — Touch ID, Windows Hello or its PIN — or with a USB security key and its PIN, instead of the typed password.
- Each is a key, never a screen in front of one. A passkey of the extension's own, which no website can ask for, answers only once it has checked you, and its answer is what unlocks the data key. The file on disk holds nothing that opens the vault without it, and a computer or key that cannot give such an answer is refused.
- Turning one on needs the master password; turning it off needs nothing. Removing the password turns both off, and so does a new data key — joining an account, or a key the account replaced. The password still opens the vault, and changes still ask for it.
Your Keyrook account
Sync is optional, through a Keyrook account. The same account works in Keyrook's other apps; Passhold, the password manager, is the first.
- Each app has a key of its own in the account: nothing Passhold holds opens Keyrook Authenticator's codes, nor the other way round. Your password and your recovery key open the account's root, and the root opens each app's key.
- Once a device has opened its key under that root, it refuses a key the server says belongs to another root, or to none: a server cannot slip it a key of its own choosing.
- When the account asks for a new key — after a recovery key has leaked, say — Keyrook Authenticator replaces its key and seals every code again under the new one.
- The account has a page of its own, account.keyrook.com, which Settings → Sync opens. Its password, passkeys, two-step sign-in and deletion are there, for every Keyrook app at once.
- Changing the password or the recovery key, and deleting the account, need the account password — or, on an account made with Google or GitHub, signing in there again as the same person. A signed-in session alone is never enough.
- A passkey you added on account.keyrook.com can sign this browser in and open the account's root inside it, as the password would. The server checks the passkey's signature and never receives what opens the root. The extension asks for access to account.keyrook.com, where those passkeys belong, only on the click that chooses one; nothing runs on that page.
- With two-step sign-in turned on, a sign-in with your password, or with Google or GitHub, also needs the code from your authenticator app — or one of the account's passkeys, or your recovery key, of which only a proof is sent, never the key. Each code works once.
New browsers, and removed ones
- Signed in with Google or GitHub, an account has no password, and nothing Google, GitHub or our server holds opens your codes. The provider proves who is signing in, nothing more.
- A new browser gets your codes only from your recovery key, one of the account's passkeys, or a browser already signed in that approves it after you check both show the same 15-character code. The code is worked out from both browsers' one-time keys, so a server that swaps either one shows two different codes.
- A request to join shows on every browser already signed in, saying which sign-in it came from.
- Removing a device — under Signed-in devices, or on account.keyrook.com — takes the account's codes off it the next time it connects, keeping only codes added there that never reached the account.
- It happens only when the removal carries a proof made with this app's key, which the device checks first. A server that merely says a device was removed gets an ordinary sign-out, and every code stays where it is.
When sync is on
- Everything is encrypted on your device before it is uploaded. The server stores ciphertext, and only the little it needs to put changes in order: record ids, revision numbers, timestamps, and whether a record was deleted.
- Your account password is stretched on your device and split into two unrelated keys. One wraps the data key and never leaves the device. The other proves the password to the server, which never receives the password itself.
- Your devices refuse weak key-derivation settings from the server, so a server cannot make your password cheaper to attack.
- Each record is bound to its id and revision. A server that moves a record under another id, or replays an old revision as a new one, produces something that will not open — and a record that will not open is skipped and reported, never trusted.
- A deletion carries nothing to check, so deletions are always reported, and what was deleted stays restorable on your device.
- The recovery key's state is sealed under the data key, and a device never goes back to an older one: a retired recovery sheet cannot be brought back to life.
- A server restored from a backup says so, and your devices send back what it lost. Saying so falsely gains a server nothing: a device never swaps its copy for an older one.
What the server can still see
Encryption hides what is in your vault, not that you have an account. Whoever runs the sync server — today, that is us — can see your email address, the addresses and times you connect from, how many items your vault holds and when each changed, and how many devices you use and what they are called.
With two-step sign-in on, it also holds that step's secret, sealed with a key kept apart from its database but not hidden from it: it needs the secret to check your codes. That secret tells a right code from a wrong one, and opens none of your data.
They cannot see issuers, account names, secrets, notes or pictures, nor the codes in a link you share.
Known limits
- Without a master password, the key is kept by the browser. That does not protect against malware running as you on the same computer, and the extension's settings say so.
- Whoever can pass the computer's own check can open a vault set to unlock with it; on many computers, that includes whoever knows its password or PIN. Whoever holds your security key and knows its PIN can open the vault on a computer where it was set up, so if the key is lost, turn it off there.
- Whoever controls the Google or GitHub account behind yours, and persuades you to approve their browser, has your codes. The approval screen says so: the code check catches a swapped key, not a stranger you approve.
- A removed device that never connects again keeps what it had, locked as its vault was locked.
- If you keep your Keyrook account's own two-step code in Keyrook Authenticator, it lives only on the browsers signed in: lose them all, and the recovery key is what is left.
- A device that has never seen any recovery-key state accepts the first genuine one it is given. A server cannot forge one, but could hand a newly joined device an older one it kept.
- The extension's code is public; the sync server's is not. That is why the extension is written so that the server need not be trusted.
Check it yourself
Every claim above about the extension can be checked against its
code, which you can read: Keyrook Authenticator is open source under
GPL-3.0. One of its tests,
packages/core/test/hostile-server.test.ts, plays a
server that tries each of the attacks under “When sync is on”, and
another swaps the keys two browsers compare.
Report a security problem
Found a way to weaken any of this — in Keyrook Authenticator, its sync server at api.keyrook.com, or the Keyrook account? Write to hello@keyrook.com with “Security” in the subject line, rather than opening a public issue. Please include:
- what an attacker could do, and what they would need first;
- the version you tested (Settings → About) and your browser;
- steps, or a proof of concept that shows it.
We will reply to confirm we have it, keep you told as we work on a fix, and credit you in the release notes if you would like that.