Improving storage of password-encrypted secrets in end-to-end encrypted apps

Many apps with client-side encryption that use passwords derive both encryption and server authentication keys from them.

One such example is Bitwarden, a cross-platform password manager. It uses PBKDF2-HMAC-SHA-256 with 100,000 rounds to derive an encryption key from a user’s master password, and an additional 1-round PBKDF2 to derive a server authentication key from that key. Bitwarden additionally hashes the authentication key on the server with 100,000-iteration PBKDF2 “for a total of 200,001 iterations by default”. In this post I’ll show you that these additional iterations for the server-side hashing are useless if the database is leaked, and the actual strength of the hashing is only as good as the client-side PBKDF2 iterations plus an AES decryption and one HMAC. I will also show you how to fix this.


My book on password authentication is out

I’m super excited to announce that my book, Password authentication for web and mobile apps, is out! I have a lot more to say about why I decided to write it and what the writing and publishing process was in future blog posts. Meanwhile, if you’re a developer who wants to understand password authentication and implement it for your web site or your app, please check it out:


Mac developers: don’t use AQDataExtensions

AQDataExtensions is an NSData category developed in 2005 by Lucas Newman and distributed with AquaticPrime framework which “allows for easily encrypting and decrypting NSData objects with AES/Rijndael (i.e. the Advanced Encryption Standard)“.

The methods are:

- (NSData*)dataEncryptedWithPassword:(NSString*)password
- (NSData*)dataDecryptedWithPassword:(NSString*)password

Unfortunately, AQDataExtensions has the following weaknesses:

  1. Weak key derivation function.
  2. No authentication.
  3. Weak random numbers.