FFkeystore: technical details


Your passwords are stored encrypted - always. The decryption is done in memory. The Apple AES256 algorithm *) is used with their cryptlib. You can check this by encrypting a known value with AES256, it should be the same value as this application (if you actually try this - which is a very good idea - you must append the salt to you password. You will find the salt in the saved plist store as clear text)

*) with apple here I mean: I used the apple crypto libs and not some homebrewed stuff

decrypted passwords

The decrypted passwords are living only in memory and will be cleared after 60 seconds (default). You should use other methods because hibernation and app nap can enlarge these 60 seconds (which makes your key store password in cleartext more vulnerable). I suggest, that you use the secure key store method with name "when copy to paste board" this will erase the key store password immediately from the app and it will only reside in the pasteboard (which is dangerous enough you should overwrite it as soon as possible)

key store password and the protected password

Please do not forget, that when your key store password is compromised, then ALL of your encrypted passwords are lost - this is the reason why the password should not live not longer then 60 seconds (which forces you to enter it more often - yes I know).

When you have retrieved a password from the store, remember to use it immediately and then copy something else to the paste board. Please do this frequentely to avoid to paste your password into a chat or something else which can be read by outside world.

As a paranoid side node: do not forget that the paste board is a "public device" and can be read by any running application on your mac. Do not consider it as a save place - it is very easy to spy on the paste board for any app with only a few lines of code.

how secure is the password store?

That depends somewhat on how strong your key store password is (I encourage you to NOT use the unsecure default password but create strong ones).

The overall design is shown is the following picture:

FFkeystore data model The key store itself is unencrypted - always (white color)
The payload (user passwords) is encrypted - always (black color)

key store password

The key store password does not exist as data entity - it must be provided by the user every time. The nearest thing you can spot in the key store file is the FF_key store_SALT (which is used to enlarge the password to 256 bits if needed). If you use unsafe mode, you provide clear text to an potential attacker (this is the reason for its name, you are then living on the promise, that this is not a problem for AES - this holds true for now...).

for each password

Each saved password in the key store (the red thingies) has its own (orange thingies) IV and SALT. The IV is used during decryption for ofb mode. The SALT is a 64 chars string randomly generated out of: [A-Za-z0-9]. The SALT will be removed and the raw password is presented to the user.

To decrypt a password from the key store you need 4 things:

  1. the key store SALT (provided in the key store) *)
  2. the password IV (provided in the key store)
  3. the password SALT (provided in the key store)
  4. the key store password (provided by user)
The last thing is provided by the user, the other 3 things are in place to make a brute force attack as expensive as possible.

*) If you are using a key store password, which is 32 bytes long, then the key store salt will not be used. However, this is unknown to an attacker, because there is no information in the key store file, where you can derive the length of the password. Please keep in mind, that with multiple passwords in N,kma mode, you may have key store passwords which are using the key store SALT.

How does the strength meter work?

Please keep in mind, that this method is designed to be defensive to make up somewhat for the human behavior to pick "easy to remember passwords" which you should not do and this app will help you in doing that.

It starts with alphabet size of 0 and will increase the alphabet on found chars in the password:

A-Z +26
a-z +26
0-9 +10
.,;:=-_+*#'&@%/?!$     +10
(not listed above) +10

So the max. size of the alphabet you can reach is 26+26+10+10+10 = 82, which is somewhat defensive as you normally have more chars available on your keyboard (with defensive I mean: the real entropy is maybe higher then the displayed one but should not be lower - if you are choosing strong passwords). Max. entropy per char is about 6 bits ( log2(82) ). I consider anything below 50 bits as not secure (red) and below 90 bits as too weak (orange). To get green - 90 bits - you will have to use at least 15 chars with triggering all 5 classes (please note, that when you don't collect all 5 classes, your password must be longer to reach green...).

Hopefully a green one will survive the next 10 years. Unfortunately I'm paranoid enough to fear, that that will be not enough, so please feel free to make your password more secure than just 90 bits.

Why can I not read the app defaults?

This app is sandboxed, so it has its "own domain", you will find the app settings in ~/Library/Containers/eu.fftools.Weisse-Rose.FFkeystore/Data/Library/Preferences

Be careful when you modify it directly, it can make the app fail (your passwords are contained THERE...Your key store password SALT is there. Make backups before you try to be a master in password zapping...)

How come that I can use AES256 passwords not 32 chars long?

Passwords, which are normally to short (that is: shorter than 32 bytes) will be extended with CCKeyDerivationPBKDF (see CommonKeyDerivation.h). The salt I use will (and must) be stored in the key store file.

Note: If you are using multiple passwords with N,kma-Mode, the salt is EQUAL for all used passwords. I suggest, that you pick very strong passwords. If your passwords are 32 bytes in length, CCKeyDerivationPBKDF will not be used BUT the salt is written to the key store file (otherwise it would be a hint, that your password is 32 bytes long).

Note: Because of the salt which is used to extend your password, the salt must not change. If you change the salt, your password will change! Do not do that. The app will generate a new salt if there is none in the key store. Generating a new salt with a key store password < 32 bytes is a painful way to delete all your passwords. Do not do that. And by the way: When generating a new salt, there is only a very small chance (consider: NO) that you will get the same salt (I use SecRandomCopyBytes - do not wait for 2 equal salts).
Just do not mess with the key store file (the salt is stored there, unencrypted but base64 encoded).

Speaking of AES256, where is IV and what mode is used?

The used mode is OFB (output feed back).

The IV (initialization vector) is kept in the key store file. It is not encrypted but base64 encoded. Modifying the IV will result in trouble as it is required on decryption. The IV is generated when the password is saved first time and will not change after that. Modifying the IV will render the current password to a new value. Something that generally not needed when you deal with passwords.). Modifying the password SALT will result in an error message during decryption (because FFkeystore can not remove the SALT part from the password, that password itself still can be decrypted).

If you see that the creation date for the SALT and the creation date from IV (both are stored in the key store file) are different, you should be in trouble (because both are created when the key is finally saved to the key store file). If your current password is working with different dates that could mean, that some older passwords are not working any more (you can use the dates in the key store file, to see, what passwords may be wrong).

What parts are weak to "padding oracle" (side channel attack)

To provide security against "padding oracle" the following data is unpadded encrypted

This was done, to provide no clue that an entered password is invalid or not (you normally would see this, if the encrypted data is padded because if the given password is wrong the padding algorithm will fail and rejecting you input data because it "knows" that either the given password or the given cipher text (or both) are wrong).

If you are not in unsafe mode, you can enter any string as password and the application will use it. If you provide a valid password, you might get readable data (if you decrypt not an default password, only your own passwords can provide reasonable data).

Why generate random passwords random data?

This is because how FFkeystore works. The cipherdata is an archived NSDictionary which is encryted afterwards. Because unarchiving is failing when you feed random data into the unarchiver, the cipherdata is replaced by random data (each time when you access the data).

Because the decryption with a random password can create valid data (which is unarchivable) you sometimes dont get random data but a decrypted random data. If the password is not matching you don't see much difference between this and random data but it stays the same each time you try to decrypt it with that password while the random data is changing each time you access the password.

This is intended behaviour and it can make default passwords look like true passwords and vince versa.