With LastPass making a habit of getting pwned and generally sucking, I started to look for a proper™ cloud-based password manager that I could recommend to friends and family.
Requirements
- A non-lame security level, by a entity that won't crash and burn in 3 months, and whose sole interest is keeping their customer's passwords safe: managing passwords can't be a side-hustle.
- Compromised passwords monitoring: I don't trust people to have used proper passwords before, and would like to make sure that they stop doing this.
- Usable in a web browser, as well as on a smartphone: anything more complex
than "Or I can just put
azerty1234
in the password field and call it a day" won't do. - Data should be exportable.
Being open-source doesn't really matter, since supply-chain attacks are way more likely than source-level backdooring. I don't know much about web browser extension security, so those are off the scope this article. Firefox and Chrome do offer passwords manager, but those won't autofill smartphone apps. Moreover, tying all your passwords to your Google account sounds like a recipe for disaster, given how infamous Google is for closing accounts on a whim without any kind of possible recourse.
Cryptographic aparté
To my disappointment (and mild horror), almost all password managers are using PBKDF2, which is known to be completely suboptimal to store passwords, and has been for the last 15 years, but it's apparently the only one without abysmal performance in Javascript. Soatok Dreamseeker wrote a great blogpost on the current state of the art with regard to "cryptography with passwords" if you want to know more about what all the cool kids are using nowadays.
Anyway, using PBKDF2 is lame and has been for more than a decade, but with the proper difficulty parameters, it might still be considered ok-ish.
Here is what the OWASP recommends:
- PBKDF2-HMAC-SHA512: 120,000 iterations
- PBKDF2-HMAC-SHA256: 310,000 iterations
- PBKDF2-HMAC-SHA1: 720,000 iterations
Sc00bz, who knows a thing or two about cracking passwords (and about LastPass too), recommends as of today around two times the OWASP's values:
- PBKDF2-HMAC-SHA512: 210,000 iterations
- PBKDF2-HMAC-SHA256: 600,000 iterations
- PBKDF2-HMAC-SHA1: 1,300,000 iterations
But those values are for "Password storage". For "Password-based key derivation", aka what we want here, Soatok has the following numbers:
- PBKDF2-HMAC-SHA512: 2,100,000 iterations
- PBKDF2-HMAC-SHA256: 6,000,000 iterations
- PBKDF2-HMAC-SHA1: 13,000,000 iterations
But this obviously won't fly for smartphones, sigh.
Candidates
Bitwarden
This was my first choice, since it's open-source and even has an alternative server implementation. It uses PBKDF2 with AES-CBC:
The default iteration count used with PBKDF2 is 100,001 iterations on the client (client-side iteration count is configurable from your account settings), and then an additional 100,000 iterations when stored on our servers (for a total of 200,001 iterations by default).
Moreover, as Vladimir Palant said, an attacker only has to bruteforce 100k iterations.
This means that someone with read-access to the server before the second iterations pass only has to bruteforce 100k iterations. There is an issue open (continued here) since 2017 about moving from PBKDF2 to Argon2. Moreover, AES-CBC doesn't provide integrity, which isn't critical here, but is still a worrying practise.
It has various clients, but all are written in Typescript and running in Electron, meaning that they're equivalent to using the web app, but absolutely worse. There is also a command-line interface, weighting 80MB, also in TypeScript, also in Electron. Amazing.
There is a bug bounty, but most reports aren't public and there are no payouts. Their audits are either compliance-related (GDPR, HIPAA, CCPA, …) or "Network Security Assessment", aka "Run Nessus and generate a report". So nobody was ever paid to audit the codebase and make the vulnerabilities public beside some people at Bitwarden Inc.
[edit] They had an audit in 2021, but its scope is unclear: it seems that only the web interface of the server was audited?
[edit] As for February 2023, Bitwarden now supports argon2id, and bumped the number of PBKDF2 iterations from 100k to 600k.
1Password
I think that it's LastPass' direct competitor. According to their whitepaper, they're using AES-256-GCM and PBKDF2-HMAC-SHA256 with 100,000 iterations. Interestingly, to protect against weak passwords, there is also a device-stored secret key mixed with the password. This is a neat trick excusing the low number of iterations. This adds complexity and I don't trust people to not lose it; but odds are that everyone has a phone and a computer, so this could act as a backup.
They're using SRP for authentication, which is not only known to be "meh" since 2008 and deprecated since 2021, but also kinda useless except if the TLS connection to 1password.com is compromised. In this case, odds are that you've already lost, but why not.
They have a substantial bug bounty up to USD 1,000,000, but the reports aren't public. They're also doing regular pentests of their various components by reputable firms.
Dashlane
Dash is the only one using Argon2d, the winner of the Password Hashing Competition held in 2015.
Unfortunately, their choice of parameters is on the low side:
We use Argon2d, by default, with the following parameters: iterations = 3, memory = 32Mo, parallelization = 2 We also support PBKDF2-SHA2 with 200,000 iterations. Then, the data is (en|de)crypted using AES CBC-HMAC mode.
AES CBC-HMAC isn't a thing, what they're doing is AES-256-CBC then HMAC-SHA256 (and not CBC-MAC), which is perfectly acceptable, albeit using the same key for AES and HMAC feels shaky: an authenticated mode should be used like AES-GCM, or another key derivation to produce two subkeys, instead of using the same key for two different purposes.
The intern who wrote their whitepaper had a confused understanding of how https works: OCSP doesn't replace trust stores, key exchanges are more complex than "the client encrypts a random number with the server’s public key and sends it to the server, the server decrypts this number, and both sides use this number to generate a symmetric key, used to encrypt and decrypt data.", …
Worryingly, their "benchmark of attempts to decrypt AES files" is done on a "4 cores Xeon 1.87GHz", which doesn't make sense: cracking a password doesn't mean going through the whole keyspace of alphanumeric characters of a fixed length, and nobody uses CPU to crack passwords, let alone a 4 cores one. I would expect a firm in the business of protecting passwords to be up to date with the current state of the art of password cracking.
They have a bug bounty with payouts up to USD 5,000 and no public reports. The gpg key that should be used to contact them is an RSA one of 1024 bits (worryingly small in 2023), and belongs to someone called "anish".
NordPass
Being from the spammy NordVPN people, I wouldn't put much trust in it. Their handwavy whitepaper says that they're using:
- Argon2id, but without specifying the parameters, not why they chose this particular variant over another variant like Argon2d.
- XChaCha20-Poly1305 for encryption instead of AES because "the performance of the latter heavily relies on the hardware features (such as the AES instruction set for x86 processors), which are rarely available on mobile devices". The whitepaper says they're using NaCl, but it doesn't provide XChaCha20, and XChaCha20-Poly1305-IETF is a draft which expired two years ago. So I thought that maybe they meant XSalsa20-Poly1305, which is implemented in NaCl, but apparently they're using xChaCha20 and xSalsa20.
There is also a bunch of public-key cryptography going on for sharing material that surely isn't susceptible to any kind of MITM, and metadata are stored in clear-text. Sounds like someone wanted the very bestest cryptography but didn't really understand why.
They have a bug bounty with payouts up to USD 50,000 and some reports are public.
Keeper
Their website says AES-256-GCM and PBKDF2-SHA-256 (or maybe PBKDF2-SHA-512, it's unclear) with 100,000 rounds.
All encrypted payloads sent to the Keeper servers are additionally wrapped by a 256-bit AES transmission key in addition to TLS, to protect against MITM attacks. The transmission key is generated on the client device and transferred to the server using ECIES encryption via the server's public EC key.
A Master Password Key is derived from the Master Password using PBKDF2 and used to unwrap the Data Key, which is then used to unwrap the Record Keys and Folder Keys. Record Keys are then used to decrypt the stored record information in the vault.
A second PBKDF2 key is generated locally and then hashed with HMAC_SHA256 to derive an authentication token.
The vault data stored offline is AES-GCM encrypted with a 256-bit “Client Key” that is generated randomly and protected by PBKDF2-HMAC-SHA512 with up to 100,000 iterations and a random salt.
KSI deploys TLS certificates signed by Digicert using the SHA2 algorithm, the most secure signature algorithm currently offered by commercial certificate authorities. SHA2 is significantly more secure than the more widely used SHA1, which could be exploited due to mathematical weakness identified in the algorithm. SHA2 helps protect against the issuance of counterfeit certificates that could be used by an attacker to impersonate a website.
On the Keeper end-user client device, when BreachWatch is activated, a HMAC_SHA512 hash is generated based on each stored password and sent to the server. On the server, a second hash is created using HMAC_SHA512 via the Hardware Security Module (HSM) using a non-exportable key. These Hashes-of-Hashes are compared to determine if a password has been breached.
This all sounds like bullshit/poor design resulting from a confusing threat model and terminology.
Apparently "Keeper works with NCC Group and Cybertest to perform ongoing vulnerability testing of the browser extension platform, which includes source code level analysis.", but the reports aren't available. They have a bug bounty with payouts up to USD 10,000, but there as well, reports aren't public.
Roboform
According to their whitepaper from 2018:
Generation of AES encryption keys uses PBKDF2 (Password-Based Key Derivation Function 2) algorithm with SHA-256 hash function and long random salt (32-byte). PBKDF2 is an iterative algorithm with a sufficiently large number of iterations (4,000 by default). A higher number of iterations provides greater protection against brute force and dictionary attacks by not only slowing them down, but also by making RoboForm Clients proportionally slower, especially on slow devices (Android, iOS) or applications (RoboForm Online web site). Intentionally making a slow algorithm is an accepted practice targeted at preventing dictionary attacks against compromised authentication stores. This technique is called “key strengthening” or “key stretching”.
We recommend increasing the length of the Master Password instead of increasing the number of iterations as, according to some researchers, the addition of two characters to the length of the password is roughly equivalent to multiplying the number of iterations by 1,000 yet it does not slow down the algorithm. A combination of 10,000 iterations and a 7-letter password is already insecure and it can be brute-forced relatively quickly, as demonstrated some time ago on one of RoboForm’s competitor products. Only the password hash derived from Master Password is shared with the RoboForm Server. It is computationally infeasible to recover the user’s Master Password or the AES-256 key from that password hash due to the one-way nature of the algorithm used to generate it.
By nature, “Read” permission is only different from “Use” permission for the Login RoboForm Data Objects. Without the “Read” permission, the Limited User cannot view the contents of the Login type RoboForm Data Object. Combined with the fact that most applications and websites mask the contents of the password field, this option provides an additional control to conceal passwords from the users.
This is complete nonsensical keyword-oriented garbage. There is also MITM-by-design on the between-users-data-sharing protocol. I haven't found how one should report security issues to them.
Enpass
According to their website, they're using 100,000 rounds of PBKDF2-HMAC-SHA512 and SQLCipher, which uses AES-CBC and HMAC-SHA512 under the hood, with different derived subkeys. Albeit Enpass' documentation mentions HMAC-SHA1 instead of HMAC-SHA512. Their threat model is a bit weird, with funky security things for their browser extensions like:
When a browser extension tries to connect to main Enpass App, we verify the origin of the connection, it must be the unique identifier of our browser extension and browser will not allow installation of any two extensions with the same ID.
I fail to see against what this is defending.
They also have a "time-based verification code" to prevent MITM for their Wi-Fi Sync Server, which doesn't say much nor inspire confidence.
They had some security audits
last year for their Windows App and backend,
in which we discover that their server is written in cpp but with calls to
malloc
,
with files like httpserver.cpp
and functions like file_upload_cb
,
meaning that they implemented their own http stack. Interestingly, they don't
provide synchronisation: it's up to the user to use either iCloud, Dropbox,
Google Drive, OneDrive, or WebDAV, even for businesses.
Despite the report mentioning that their CSP policy might benefit from some tightening, it's still useless:
curl -s -I https://console.enpass.io | grep -i content-security-policy:
content-security-policy: default-src 'self'; font-src 'self' fonts.gstatic.com; img-src 'self' d1f8f9xcsvx3ha.cloudfront.net enpass.onfastspring.com license-enpass-io.s3.amazonaws.com https://i.ytimg.com/vi_webp/96FY_bKQGrU/mqdefault.webp data: w3.org/svg/2000; script-src 'self' 'unsafe-inline' d1f8f9xcsvx3ha.cloudfront.net;connect-src license.enpass.io enpass.onfastspring.com d1f8f9xcsvx3ha.cloudfront.net;style-src 'self' 'unsafe-inline' fonts.googleapis.com; frame-src 'self' enpass.onfastspring.com youtube.com www.youtube.com;frame-ancestors 'self'
They don't seem to have a bug bounty.
Conclusion
- 1Password if your friends and family are smart enough to not permanently lose their "secret key", and/or have multiple devices. They seems to know what they're doing crypto-wise with their trick to mitigate their low amount of derivation rounds, are spending money doing regular technical audits and have a significant bug bounty cash prize. I think it's the right choice if you want a ton of features and security.
- Bitwarden if you prefer open-source, a small company, and simple things. Just make sure to bump the number of iterations.
- Dashlane if you don't like 1Password.
Everything else is either looking shaky, lacking features that I want, or simply absolutely horrible.