Why you can't recover your KeePass password
It was a pretty vexing problem I faced; not only had I forgotten my password for the KeePass password manager, but the developer of this tool had made a concerted effort to drastically slow down my efforts when repeatedly guessing what my password could have been via a technique called brute-forcing.
What peeked my curiosity though, is why it wasn't feasible to recover the password via brute-forcing? Or by a dictionary attack for that matter. The following shows how KeePass intentionally slows down the process that is required to run in order to decrypt the stored credentials, and thus determine if the password is correct.
You can explore these steps further with a small tool I wrote.
Reading the Database's Header
Before asking the user for their password, KeePass first reads all the relevant data from the database's unencrypted header. This data is then used during the following steps to authenticate the key and decrypt the database's body.
Signature 1 Signature 2 File Version 0x00000000 0x00000000 0x00000000 Fields Type ID Data Size Data 0x04 = Master Seed 0x00000000 0x00... 0x05 = Transform Seed 0x00000000 0x00... 0x06 = Transform Rounds 0x0000000000000000 0x00... 0x07 = Encryption IV 0x0000 0x00... 0x09 = Expected Start Bytes 0x00000000 0x00... 0x00 = End of Header
Using the KeePasswd tool you can view the header of a KeePass database by calling the following:
Create the Composite Key
The process starts by creating a master key from all of the keys provided by the user (generally a password, key-file and/or Windows User Account). This is achieved by appending the bytes of the SHA256 hash for each of the keys into a single composite, which is then hashed with with SHA256.
The resulting composite key is then passed to the next process.
Transformation of the Key
The key transformation stage is rather clever in that it transforms the key many times to slow down the whole authentication process; thus reducing the feasibility of guessing the password via dictionary or brute-force attacks.
This process works by using the AES algorithm, with the Transform Seed (taken from the header), to transform each 16 bit half of the 32 bit key by the amount of times specified in the Transform Rounds header field.
As with the last step, the result of this transform is hashed using SHA256, which is then passed to the next part of the process.
Seed the Key
The resulting transformed key is now joined to the Master Seed (taken from the header) and then hashed with SHA256 once again to produce the seeded master key that is ready to be used for decrypting the database's body.
Compare Decrypted Stream with Expected Bytes
The last part of the process is to decrypt part of the encrypted stream (situated after the KeePass file's header) and then compare the first few bytes with the ExpectedStartBytes header field.
If the decrypted bytes match the bytes stored in the header field then the password is correct and the rest of the stream, containing the user's data, can be decrypted.
The whole process at the time of creating the database is configured to take approximately 1 second on the host's machine, which adds up to a considerable amount of time when you're trying to guess thousands of passwords.
To see the whole process in action with the KeePasswd tool you can call the following: