GoKey – A simple vaultless password manager in Go
github.com
github.com
Ignoring the question about security compared to a normal password manager, the biggest practical issues are
1) Once you need to handle password changes and special password requirements (length/containing or not containing symbols), you end up having a list of exceptions that's similar to a password vault anyway (once you're synchronizing an encryption key and list of exceptions you might as well just use a vault-based password manager like Pass)
2) You can't see what sites you have "stored" passwords for (since there are no stored passwords). This means it can be hard to determine whether you have an account on a given site, and if your key is compromised you may not be able to determine all the sites you need to change the passwords for.
3) The password is also tied to the domain, so without a list of stored passwords it can be extremely confusing if a company switches domains without you realizing it or remembering what the previous domain was. Ideally this shouldn't happen a lot but it's not as infrequent as you would think among companies that have multiple brands if they change their sso system or something. (I guess this would also break fido so maybe companies will stop doing it if fido really catches on.)
4) You can't store information other than passwords. This is really annoying on sites where you have to create usernames if you don't/can't use the same username everywhere. You can put this information in the exception file from 1 but the more information you put there the less point there is in using a "vaultless" password manager.
I did actually use a vaultless password manager for a period in the past, but based on that experience I concluded that the downsides hugely outweigh any advantages and would not recommend that anyone use them.
5) You have a problem if you need to cycle a password for a site either due to some password rotating policy of theirs, or a security breach requiring a reset.
From the readme. So, yes, but then you have to remember your username and that you made that site's password as such...
With a vault, I can choose whether I want the URL to be matched to the base domain/public suffix, to the host/subdomain, to the whole path, etc., for each entry. And in fact I do have pretty much every option my manager (Bitwarden) offers in use (except maybe "regular expression"). Without a vault, you have to remember which option you chose, which means you effectively have to use the same method for every site (or at least for most sites, whatever you don't log in to often enough to remember).
It also causes problems for those companies which have "SSO" by using the same credentials across multiple different subsidiaries/affiliates on different domains - I'm thinking here about United Healthcare, who have sign-in at `healthsafe-id.com` for insurance, and at `healthsafeid.optumbank.com` for FSA, using the same set of credentials (and yes, obviously this is a terrible practice on their part, but you often don't have any real choice about using companies with these terrible practices).
And it also makes any integration/automation (i.e. at its most basic "press a hotkey to inject password keystrokes for the current selection") need, as you mention, a list of exceptions/mappings (or else to not work for any sites like these).
Firstly, if your password must be changed, maybe due to a data breach- you can't change it in your password manager.
Secondly, different sites have different requirements on passwords- length, the presence of certain characters, etc.
Thirdly, while low probability, it is possible to have such a system compromised, and then passwords could be derived. This is no worse than a password vault, but a password vault can be changed easily.
A nice idea but not something to use in real life
Just go ahead and generate random passwords for each site, encrypt them with the master key, and store them in the metadata file! Since they're encrypted, the encrypted passwords are no longer more sensitive than the other metadata in the file and you just reinvented a normal password manager.
I can take a copy of my pwd vault with me. I'm using pass, so the vault is a directory of files encrypted with a private key, which itself is encrypted with a strong passphrase. Even if I do end up losing that copy; What are the chances that someone breaks todays encryption standards, and does so before I notice the loss and simply change all my passwords?
Typically, a protocol like this would have the master key in a vault/hsm, and your first user key would be derived from that master, and you do derivations from that, and when you need a new identity, you derive a new user key from the vault key.
Concievably, we could replace the vault with hashes of just really long passphrases that you remember and generate on some trusted interface, and then derive new RP site passwords from the hash of each long passphrase. Mnemonic password storage essentially. What you would usually do is include a counter in the authN protocol, so each instance of the session password going over the wire has forward secrecy, but that requires your relying parties to speak that protocol, where the proposal here is just for password management.
I'm sure the people behind this are very competent and clever, but again, the problem it solves and how it solves it would be more useful than a command line UX and "trust us!" What I can't stand about security and some crypto people is they challenge people to reason about something without providing the objective details of a protocol, and then expect us to trust them when we can't reason about it as effectively. I'm merely ignorant, not stupid, and asking me to trust something because I can't reason about it borders on offensive sometimes.
On second thought, maybe the fact that this only has a command line interface is a good indicator that it isn’t meant to be what I think of as a password manager.
It's all based on a PRNG, which is based on an AES-256 in CTR mode (making it a stream cipher) seeded with a key generated by 4096 iterations of PBKDF2-SHA256. PRNG just decrypts a stream of zeroes with a KDF-generated key. All standard library algorithms, nothing custom.
To generate a password, it builds an alphabet, picks a random character from it by reading a byte from the PRNG. It is looping until it reads a byte is less than `255 - (255 % max)` where `max` is length of the alphabet, then returns `b / (255 / max)` where `b` is the byte from the RNG. Basically, dividing [0-254] range (255 is never accepted) into equal-length `max` pieces and figuring out where it falls. The generated password is checked for compliance (i.e. that randomness had produced a special character, etc.) and returned if it's good, otherwise it loops and tries to generate a password again. Given that RNG is fully deterministic, this produces consistent results.
I haven't bothered looking into keypair generation - I just woke up, sipping on my "morning" coffee as I'm typing this, so I'm kinda lazy.
SQRL went through all these things in slow motion. Or at least that's how it felt listening to the "Security Now" podcast.
Note that the recommended operation for GoKey requires the use of a seed file. Instead of deriving passwords directly from the master password, it derives them from a file of random data that is decrypted by the master password.
While it's true that this seed file doesn't require the ongoing synchronization that a vault does, it's something that you need to have, and to manage with care.
Double plus ungood.
But even if it rarely changes, how would that file be synced in practice? Probably dropped in a Syncthing or Nextcloud folder. And if you do that, you may as well drop a Keepass file in there, and not have to deal with the many problems that this "vaultless" solution cause.
Check out BIP-39 [0] for more details.
[0] - https://github.com/bitcoin/bips/blob/master/bip-0039.mediawi...
On my to-do list is a little project that takes many password "managers" like these, which are really just hash functions with an interface (called "vaultless" here), takes as second input a dump of password hashes that nobody has cracked yet, and goes to down the hashes list trying the usual password list but running it through these "managers"' algorithms first. I wonder how many people turn out to use weak passwords as their master key for this sort of thing. Maybe this is more clear:
foreach linkedin_hashlist as hash do
foreach brainpwdmgr_algorithms as algo do
foreach wordlist as word do
c = algo(pwd=word, site='linkedin.com')
if c == hash then
print(c, word)
fi
end
end
end
If the --password input for these tools is guessable, an attacker can use this to retrieve the key that this tool will generate for any website. I can then go on and try likely usernames (I've already got one, presumably) on various sites with what I know is probably the correct password. A handful of failed logins per website don't attract attention, and I'm already virtually certain of the login credentials.This "gokey" does have the option to add a seed file, which would make such an attack impossible if generated securely. How many people use that option is the question. In the readme the seed-file-less mode is labeled as the "simple mode", perhaps that sounds attractive to some readers that don't realize the danger of the simple mode (kind of sounds like "default mode", when you don't want fancy options, just a standard password vault?).
(If someone wants to steal this idea, feel free to pick it up of course; the actual work is in the execution as always.)
It just takes one compromised password to start a dictionary based or other offline attack to brute force the master password which would then allow the attacker to regenerate other realms.
Disagree. I'd even call required rotation a smell.
Requiring rotation leads to people coming up with passwords more frequently, meaning they'll likely choose weaker passwords. On top of that, regular rotation isn't necessary for passwords generated independently by a password manager.
The issue here is that there's no way to deal with revocation / password changes if a service is compromised.
https://github.com/cloudflare/gokey/blob/v0.1.0/csprng.go#L2...
https://www.usenix.org/sites/default/files/conference/protec...
Whereas the README uses URLs as the realm string, the slides uses realm strings like "root-password" or "ssh-v2" to derive keys from a seed stored in a UEFI variable.
I think the idea is that you can administer all of your servers with one master password, while each server derives different passwords locally from its own seed. If a given seed is compromised, rederive the passwords from a new seed (or reprovision the server from scratch). If your master password is compromised ... well, try not to let that happen.
Good thing that keyloggers don't exist then... :'(
.....because if so, let me introduce you to the Toyota Mega Cruiser: https://en.wikipedia.org/wiki/Toyota_Mega_Cruiser
Eg Gmail has been over the last decade: gmail.com, mail.google.com and now www.google.com/mail
The biggest problem with password managers is that you become completely dependent on them (and therefore completely helpless without them) once you start using them. This scenario still allows you to remain decoupled from that dependency.
In either case you're going to need a copy of the software itself and some sort of shared file with either a list of password changes/rules, the actual encrypted passwords, and a master password or key to log in to anything.
Once you've given up on being able to log into sites without having a specific program handy and synchronizing some sort of data, why not simply store the encrypted passwords in the data you're synchronizing?
Details in BIP-32 [0] and BIP-44 [1].
[0] - https://github.com/bitcoin/bips/blob/master/bip-0032.mediawi... [1] - https://github.com/bitcoin/bips/blob/master/bip-0044.mediawi...
I'm the author of the tool and thank you very much for all your comments so far. Let me address some points raised in the comments and put some context around the tool:
1) Why the tool was developed
The tool was actually developed for internal Cloudflare use. We use it to manage secrets and cryptographic keys on our stateless servers. The main problem it solves is how to make sure various cryptographic keys and credentials stay the same on an otherwise stateless server (which can be rebooted/wiped any time). We do use it exclusively with the "seed" mode.
It is just when we developed the tool, we saw it may be an alternative to a traditional password manager and follows the approach of some other existing "stateless" password managers, so decided to open source it. The main reason though we needed to develop our own tool instead of using an existing one is that we needed the ability not only to derive passwords from a seed, but also cryptographic keys (RSA, ECC, x25519). However, the tool does not intend to compete with existing established password managers.
For more details on how we use the tool internally check out my presentation from https://youtu.be/2RPcIbP2xsM. The presentation shows some nice secret rotation capabilities we get from using this approach.
2) "Vaultless" does not mean "stateless"
The tool actually somewhat explicitly calls itself "vaultless", but not "stateless" (unlike other similar password managers). After looking into similar solutions we do recognise that a fully stateless password manager would probably have a bad UX (because of all the points raised in the comments here and probably more). However, as some commenters rightfully noticed, managing state for this password manager would be somewhat different from managing a vault from a traditional password manager:
* you don't need "ongoing" seed replication unlike a traditional vault replication - in a multidevice scenario, if you add a password on one device, you would need to replicate vault to other devices after each new password added (before you can actually use the password on the other device). With this approach you would need to replicate the seed file once, and thus all your current (and future!) passwords will be automatically replicated
* if you do choose to store per account state (like password requirements, username etc) - this information is less critical from security point of view (but still critical from a privacy point of view). This file can still be encrypted with a key derived from the seed file though (before storing it on a public cloud for example). Also, if you lose access to your vault (your cloud provider suddenly has an outage) - you lose access to all your accounts. With this separate seed/account metadata approach - if you lose access to the metadata file, you can still reasonably get access to your accounts (although with a worse UX - as you would have to check the service password requirements, if any and remember your username). You would likely remember these for your often accessed (and critical) services, like primary email, bank account etc
3) Inconvenient UXWe do recognise that while we can talk about better UX by replicating a seed file or managing an account state/metadata file, the tool doesn't actually implement these. This is partially because of 1) (we don't need this at this point and we don't compete with password managers), however the code was structured in a way that it can be used as a library in other Go projects. Therefore, other user interfaces can be developed on top of it, which can also provide a GUI, seed replication and metadata management. Think of this code as a building block rather than a full-featured password manager and we would be happy to see more frontend applications developed based on it.
Definitely useful for managing key pairs tho
my interest is piqued, will be looking into this further, thanks!