KeePassX Database Format

This information was distilled from reading the source code of the KeePassX Project. So it could be wrong too.

The entire encrypted database is read into memory at the beginning checked to make sure that it is greater than the minimum size of just the DB_HEADER.

The Contents of the binary file format are in the general format of an unencrypted 124 byte header followed by the encrypted data. The encrypted data has 2 sections, the Groups section followed by the Entries section. The number of Groups and Entries are listed in the header.

Header

Database Header fields, total byte length 124
Signature 1 4 byte int LE order constant: PWM_DBSIG_1 0×9AA2D903
Signature 2 4 byte int LE order constant: PWM_DBSIG_2 0xB54BFB65
Flags 4 byte int LE order Determine what algorithms are used
Version 4 byte int LE order Version of the database format
Final Random Seed 16 bytes Initial random number to start on the sha256 of the key
Init Vector 16 bytes Initialization vector used for all algorithms
Num Groups 4 byte int LE order Number of Groups in the Groups portion of the data
Num Entries 4 byte int LE order Number of Entries in the Entries portion of the data
Content Hash 32 bytes
Transformed Random Seed 32 bytes Random seed used to combine with the master key when calculating the final key
Key Encoding Rounds 4 byte int LE order Number of rounds to do AES block encryption on the Master Key
Flags for ‘Flags’ variable in header
PWM_FLAG_RIJNDAEL use the AES algorithm for entries
PWM_FLAG_TWOFISH use the twofish algorithm for entries
PWM_FLAG_ARCFOUR use the arc for algorithm for entires (unused)
PWM_FLAG_SHA2 use SHA256 for key stretching

Groups section

Immediately following the Header, and part of the encrypted content is the Groups section. The number of Groups in the Groups section is in the header as Num Groups.

A Single Group is really a collection of all the Group records until the END OF GROUP record is encountered. Then this counts as 1 group.

Each record in Groups has the format:

Group record format
Field Type 2 byte int LE order The type of the field, one of valid field types
Field Size 4 byte int LE order the number of bytes in the field’s data
Field data N bytes of data depends upon the Field Type

And the Field Types and their associated Field Data Structures are :

Field Type Field Type Field Data structure
Ignore 0×0000 Ignore the data
ID 0×0001 4 byte int LE order
Name 0×0002 UTF 8 encoded string
Creation Date 0×0003 5 bytes packed date for the creation date of the group
Last Modified 0×0004 5 bytes packed date for the last modified date of the group
Last access 0×0005 5 bytes packed date for the last access date of the group
Expiration 0×0006 5 bytes packed date for the expiration date of the group
Image ID 0×0007 4 byte int LE order, the id of an image for the group
Level 0×0008 2 byte int LE order, the level of the group
Flags 0×0009 4 byte int LE order, bitvector flags of the group
END OF GROUP 0xffff NA

Entries section

Following the Groups section is the Entries section. The number of Entries in this section is listed in the file header as Num Entries.

A Single Entry is really a collection of all the Entry records until the END OF GROUP record is encountered. Then this counts as 1 entry.

Each record in Entries has the format:

Entry record format
Field Type 2 byte int LE order The type of the field, one of valid field types
Field Size 4 byte int LE order the number of bytes in the field’s data
Field data N bytes of data depends upon the Field Type

And the Field Types and their associated Field Data Structures are :

Field Type Field Type Field Data structure
Ignore 0×0000 Ignore the data
UUID 0×0001 16 byte UUID
group id 0×0002 Group id this entry belongs to
ImageID 0×0003 Image ID of the icon for this entry
Title 0×0004 UTF8 String with the title of this entry
URL 0×0005 UTF8 encoded string of a URL
User Name 0×0006 UTF8 encoded string of the username
Password 0×0007 UTF8 encoded string of the password
Additional 0×0008 UTF8 encoded string of additional data
Creation Date 0×0009 5 bytes packed date for the creation date of the entry
Last Modified 0×000A 5 bytes packed date for the last modified date of the entry
Last Access 0×000B 5 bytes packed date for the last accessed date of the entry
Expiration 0×000C 5 bytes packed date for the expiration date of the entry
Binary Desc 0×000D Binary Description
Binary Data 0×000E Binary Data
END OF ENTRY 0xffff NA

Encrypt/Decrypt Process

  1. P = user pass phrase
  2. MasterKey = SHA-256(P)
  3. TMasterKey = AES-encrypt(RandomSeed, MasterKey, Rounds)
  4. FMasterKey = SHA-256(TMasterKey,FinalRandomSeed)
  5. Plaintext = AES-decrypt(FMasterKey, IV, Cipher Text)
  6. ContentHash = SHA-256(Plaintext)

A Master Key is calculated with either a password or file or both. Depending on the combination of password and file or both a SHA256 has is created of the input password information.

This Master Key SHA256 is Encrypted Key Encoding Rounds times with AES using Transformed Random Seed as the initialization of the encryption process. This producess a Transformed Master Key. This key is hashed together with the Final Random Seed to create the Final Key used for encryption.

After the Final Key has been created, the contents are decrypted and a sha256 hash of the decrypted contents is compared to the Content Hash in the header.

Then Num Groups groups are read from the decrypted data stream. Following that Num Entries are read.

Once the Groups and Entries are decoded and stored, the meta data streams in the entries are filtered and removed from the entry data rightly.

MetaData Entry Has
BinaryData not null
Additional not the empty string
BinaryDesc is “bin-stream”
Title is “Meta-Info”
UserName is “SYSTEM”
URL is ”$”
ImageID is 0