[Note: this post is somewhat long.]
I just rotated my master passwords. This marks my first time doing so in my current scheme, so it seems like a good time to talk about what I’m doing. The scheme has some advantages and some disadvantages, but it’s been working well for me and I think it’s pretty secure overall, so maybe it’ll be of some use to you to read about it.
First, what am I trying to accomplish with this scheme?
- I want unguessable passwords for everything.
- I want to maximize my resilience to data loss events, e.g. my laptop dying, a cloud service going under, a software bug eating my password list, etc.
- I want to minimize the harm done by any individual password getting leaked somehow.
- I want to have a reasonable and configurable guess at the security level for a given password, e.g. “it’d take x many years to crack it given y hardware”.
- I want it to be easy to use from day to day, without requiring me to frequently do anything weird or complicated.
If you have similar goals, then this may be useful to you.
So, on to the scheme. At a high level, there are basically three major moving parts involved:
- Two master passwords that are generated in as non-deterministic a way as possible.
- Site-specific passwords for everything under the sun, generated deterministically from one of the master passwords.
- Traditional password manager(s), used as a caching layer for the passwords in 2 so I don’t need to enter my master password too often.
And now, each part in detail:
These are the most critical part of the scheme. If one of them gets out, it’s going to be a real pain for me to recover. Therefore it’s critical that they be as unguessable as possible, and that they be entered as infrequently as possible.
I generate these diceware-style, with casino dice and this wordlist. I print the actual word list out, and use a pen and piece of paper on a hard surface to write down the dice rolls. I throw enough rolls in advance for the number of words in each passphrase. Then I convert the rolls to words by looking them up in the word list. Then I burn the paper with the rolls on it.
I use one of these passwords as the source for all the site-specific passwords mentioned in part 2. The other is the password to my primary email account. Why are these separate? So that, as a last ditch effort, if my site master is compromised, I can at least use the password recovery feature on each site to regain control of my account on it. (If my email master is compromised, I just have to go through Google’s account recovery process, and then recover every site that the attacker gained control of using that method.)
The site master needs to be at least as strong as the strongest password it ever needs to generate, and strong enough to resist an attacker who can make guesses as often as her hardware permits, since if any site leaks a hashed password, an offline brute-force attack against the master becomes possible. I use 7 words, for an entropy of roughly 90 bits. In combination with a work factor for the site-specific password generation (which I’ll get to in a second), it’s enough that brute-forcing the site master is not the easiest way to break the system for even state-level attackers.
How strong the email master is depends on the specifics of your email provider. You can probably get away with 4 words if you’re using a provider like Google. I use 5.
I generate each site-specific password deterministically from the site master. The mechanism for doing this (if
| is a concatenation operator) is not quite but almost
SHA3(site_master | base_url | 10Mb of '\0'), translated into a form that the given site accepts. Specifically, I use passacre. The 10 megabytes of null are just a work factor—the main point is that each site’s password is a deterministic one-way function of its URL and my site master.
One major benefit of doing it this way is that this totally solves the data loss issue. The only data I need to store is the specific schema (e.g. “must contain one lowercase letter, one uppercase letter, one digit” and so on) that each site accepts, and I can safely store that publicly and redundantly.
(Incidentally it’s even possible for passacre to hash the site names so that you can’t tell by looking at the list where you have accounts. I don’t do this currently because it means each time you rotate site masters, you lose your old schemas, but maybe that trade-off makes sense for you.)
So at this point my passwords are unguessable, I am invulnerable to data loss events that don’t permanently affect my muscle memory or my ability to compute SHA-3, and each site-specific password yields nothing of any use about any other passwords in my scheme. (There’s an increment parameter to the generation function, so you can easily rotate individual sites without rotating the master.)
Another benefit to doing things this way is that the whole question of whether you can trust your password generation algorithm gets much simpler. It’s no longer a big involved expedition into “who wrote the CSPRNG, are the sources of entropy it uses trustworthy, is the program successfully acquiring random bytes, is the language the program is written in using the appropriate API for randomness,” etc. etc. etc. It’s just two questions: is SHA-3 broken? Is the site master leaked? Done.
There’s one obvious weak point in the scheme presented so far. Maybe it’s not obvious to you yet, but it would be after a few days of using it: the site master gets typed in way too often.
This is terrible not only from a usability perspective—you have to type in an incredibly long secure passphrase every time you want to log into anything anywhere—but also from a security perspective: each and every time you enter your site master, it’s possible for an attacker to observe it. Even if you think no one’s watching, it’s not too hard to acoustically analyze keystrokes, for instance.
The solution to this problem is simple: use a traditional password manager like LastPass or pass. But just use it as a caching layer. Generate site passwords in a secure location, then insert them into a different password manager, and use that password manager to log into sites the rest of the time.
The only major caution to take about this is to be careful about using Chrome’s password store if you’re also using Gmail as your email provider. If you do this, then your Gmail master password has suddenly become the single point of failure in this scheme, unlocking not just your email but all of your accounts everywhere. (It already sorta is this, but if you use the Chrome password store, the compromise is much faster and more comprehensive.)
If you want to use the Chrome password store anyway—it is damn convenient, after all—then you just need to use a separate passphrase to generate your Chrome password key. It’s possible to do this in the Chrome sync settings. It’s okay if you use the site master to generate that passphrase—the crucial thing is just that it be separate from your email master.
[Updated 2017-02-01: that’s actually not what I’d been doing until now. I noticed the issue with using your Gmail password for Chrome password sync in the course of writing this post, and gave the above recommendation after thinking about it but without having first tried it myself.
It turns out, you can’t access passwords.google.com if you use a separate Chrome sync passphrase. This is the only somewhat convenient way I know of to enter a password into an app on Android without having to look at another device and type it in manually. So that recommendation wouldn’t work for me, and probably won’t work for you.
Instead, I’m now using pass along with its Android app. I recommend either that or LastPass.]
So, that’s the scheme: from day to day, about as easy to use as it gets while maintaining minimum opsec; yet also about as secure as it gets with the resources available to an individual human. And the only data needed is a couple short, easy-to-memorize passphrases.
There are weaknesses—you have to be familiar with the command line, you have to be willing and able to buy some dice, and passacre is not exactly a usability dream just yet—but overall, I think it’s not that bad. If you can improve it, please let me know—I’d love to find out I could do better on any of this.