Score:2

Best practices on implementing a password manager

lk flag

I'm a dev new to security and cryptography.

I'm writing a password manager and Time-based OTP combo in dart/flutter to use in multiple devices and platform for fun and use it personally for real. I have done some reading over google, stackoverflow.com and crypto.stackexchange.com, came up with following skeleton, and here to ask for some further security advice, for encryption, implementation and software engineering.

Encryption algorithm

Similar to bit warden, the AES/CBC 256 with PKCS7 padding and shared master password with Argon2 ID KDF is used to encrypt the whole DB, each password and TOTP secrets, all with randomly generated salts and IVs.

Questions

  • various sources said IV and salt should be randomly generated each time when re-encrypt, and IV stored along with encrypted data.
    • How about the salt?
    • Is it secure to pack both salt and IV with the encrypted database? Honestly, I can't think of other way to transfer all three of them separately for now.
  • while I shuffle or reverse the encryption parameters a bit before applying them, some answers here tell me that it does not improve security. May I know why?

Storage

  1. on S3 storage, the whole DB is encrypted with above algorithm
  2. when app is started, the whole DB is partially decrypted, thus leaving username and website as plain text on disk
  3. when user retrieve passwords or request TOPT code, the password or the TOTP secret will be decrypted and display, not stored to disk
  4. when app is closed or put to background, the partially decrypted DB is deleted from disk
  5. when app is brought up again, start from step 2 again

Questions

  • is it secure enough to store Time based OTP secrets and login credentials two separate DB but open with same app?

Libraries

For portability, I chose the pure dart pointy castle for encryption and decryption.

I run tests on my mobile with other libraries and didn't see it attempts to connect with outside world.

Also, I crossed check the AES correctness with webcrypto (from browser) and argon2 with link1 and link2

Questions

  • other than "connecting to outside world" unintended, correctness of algorithm implementation, and trustworthiness (a.k.a. popularity) of libraries, what else should I be aware of?
fgrieu avatar
ng flag
I don't get "salts". I see why one salt and Argon2id KDF is useful for the master password, but don't see other use of salt or Argon2id in a password manager. Until I understand what the question envisions, I'll refrain from giving advice.
anthonychwong avatar
lk flag
Thanks @fgrieu. That is for encrypting each login passwords and TOTP secrets individually again in AES/CBC 256 with PKCS7 padding and Agron2id KDF. Since the whole database needs to be decrypted to disk to be accessed by the password manager, but login passwords and TOTP secrets shouldn't be leaved as plain text on disk, they are encrypted when stored to the database.
Score:1
in flag

Similar to bit warden, the AES/CBC 256 with PKCS7 padding and shared master password with Argon2 ID KDF is used to encrypt the whole DB, each password and TOTP secrets, all with randomly generated salts and IVs.

I'd use authenticated encryption, or possibly AES-SIV to encrypt the passwords instead. AES-CBC is kind of dangerous and a streaming mode by itself is also rather dependent on the quality of the RNG when encrypting.

I don't know the intrinsic details of BitWarden, but I'll assume that you have studied the protocol well.

various sources said IV and salt should be randomly generated each time when re-encrypt, and IV stored along with encrypted data

That depends on how they are used. If it is about a single encryption / decryption operation then the IV can be static, derived or even identical to the salt.

Is it secure to pack both salt and IV with the encrypted database? Honestly, I can't think of other way to transfer all three of them separately for now.

Well, that's assuming a lot. For instance, it assumes that the entire DB gets encrypted and decrypted each time something changes.

while I shuffle or reverse the encryption parameters a bit before applying them, some answers here tell me that it does not improve security. May I know why?

Each bit of the key will double the amount of operations that the attacker has to address. So say that there are $N$ possible ways to "reshuffle", then you basically add $\log_2(N)$ bits to the key, because in the end you also need to know how to decrypt. Let the security reside in the cipher and configure it using the key size.

on S3 storage, the whole DB is encrypted with above algorithm

That can be OK, but it is certainly not the most flexible option, especially if the DB is large & changes a lot.

when app is started, the whole DB is partially decrypted, thus leaving username and website as plain text on disk

You really don't want to perform partial CBC decryption. You run into things like padding issues and such. And this DB is for one website? That doesn't sound right.

when user retrieve passwords or request TOPT code, the password or the TOTP secret will be decrypted and display, not stored to disk

All right, but you haven't indicated how that thing can be found.

when app is closed or put to background, the partially decrypted DB is deleted from disk

Ah, right, so if you have to switch to the app and the password manager a few times then you have to decrypt each time? That's going to be...painful. I'd at least put in some configuration options for that.

For portability, I chose the pure dart pointy castle for encryption and decryption.

The disadvantage of languages with that kind of VM is that it might be impossible to be sure that you can remove the secrets from memory. Especially when it comes to string handling as those are often interned (which is why passwords are generally handled as character arrays instead of full blown strings in Java).

is it secure enough to store Time based OTP secrets and login credentials two separate DB but open with same app?

Well, if everything has it's own password then you might as well use a different instance if you ask me. I'd at least write down clearly when and how access is granted to the functionality.

other than "connecting to outside world" unintended, correctness of algorithm implementation, and trustworthiness (a.k.a. popularity) of libraries, what else should I be aware of?

Online synchronization, backup & restore. Clipboard handling. Destruction of password & key material. Keyboard security. Password validity checking. Integrity of the DB. Implementation security. Protocol specifications. Password generation. The hiding of the length of the password.

You've mentioned only 1 security check; I sincerely hope that you either study existing apps or keep the implementation private. One feature that I would consider rather important is to use some kind of looking up an older password. It may be internally reused or setting a new password may fail, requiring access to the old password.

I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.