KDBX 3.1 FILE FORMAT

KDBX is the file format of the password manager KeePass Password Safe.

kdbx file layout

All multi-byte values in the header are stored in little-endian byte order. All length fields count the length in bytes.

SIGNATURE

Signature layout:
Offset Length Value in hex Description
0 8 03 D9 A2 9A 67 fb 4b b5 Magic number
8 2 01 00 Minor version
10 2 30 00 Major version

HEADER

The header is a Type-Length-Value list.

Header layout:
Offset Length Example bytes in hex Description
CIPHER ID
12 1 02 Cipher id type
13 2 10 00 Length of cipher id field
15 16 31 C1 F2 E6 BF 71 43 50 BE 58 05 21 6A FC 5A FF The UUID identifying the cipher algorithm AES256: {E6F2C131-71BF-5043-BE58-05216AFC5AFF}
COMPRESSION FLAGS
31 1 03 Compression flag type
32 2 04 00 Length of Compressoin flag field
34 4 01 00 00 00 0=payload not compressed, 1=payload compressed with GZip
MASTER SEED
38 1 04 Master seed field type
39 2 20 00 Master seed field length
41 32 The salt that will be concatenated to the transformed master key then hashed to create the final master key
TRANSFORM SEED
73 1 05 Transform Seed field type
74 2 20 00 Transform Seed field length
76 32 The key used by AES256 as seed to generate the transformed master key
Offset Length Example bytes in hex Description
TRANSFORM ROUNDS
108 1 06 Transform rounds field type
109 2 08 00 Transform rounds field length
111 8 70 17 00 00 00 00 00 00 The number of rounds you have to compute the transformed master key. QWORD = Unsigned 8 byte integer
ENCRYPTION IV
119 1 07 Encryption IV field type
120 2 10 Encryption IV field length
122 16 The IV used by the cipher AES256 that encrypted the database
STREAM CIPHER KEY
138 1 08 Stream cipher key field type
139 2 20 00 Stream cipher key field length
141 32 The key for the stream cipher Salsa20 used to encrypt the password of an entry in the database
DECRYPTED DATA VERIFICATON BYTES
173 1 09 Decrypted data verification bytes field type
174 2 20 00 Decrypted data verification bytes field length
176 32 indicates the first 32 decrypted bytes. Used to check if the file is corrupt, or the key correct. These 32 bytes should have been randomly generated when the file was saved.
STREAM CIPHER ID
208 1 0A Stream cipher id field type
209 2 04 00 Stream cipher id field length
211 4 02 00 00 00 00 ID of the stream cipher used to encrypted the password of an entry in the database: 0 = nothing, 2 = Salsa20
LIST END INDICATOR
215 1 00 List end indicator field type
216 2 04 00 List end indicator field length
218 4 0D 0A 0D 0A header field '0' indicates no more header field after this
210

Conceptually the header length can be variable. But as a matter of fact it is 210 bytes in length.

ENCRYPTED DATA

The AES256 encryption algorithm is a block cipher.

One block is exactly 16 bytes in length.

The AES256 decrypts the data in blocks

Therefore the encrypted data length must be a multiple of 16.

DECRYPTED DATA

The decrypted data consists of:

Layout of a block:


  4         Block number. First block has number 0. Example: 00 00 00 00
  32        Block data hash.
  4         Block data length.
  n         Block data

The whole decrypted data has following layout:


  LENGTH    DESCRIPTION
  ------    -----------
  32        VERIFICATION BYTES - check this 32 bytes against the 
			verification bytes from header to ensure decryption has worked.
  ----------- BEGIN OF BLOCKS  ------------------------------------------
  ----------- BEGIN OF FIRST BLOCK  -------------------------------------
  4         Block number. First block has number 0. Example: 00 00 00 00
  32        Block data hash.
  4         Block data length.
  n         Block data. Here is the payload with XML. Is gzipped if COMPRESSION FLAGS=1
  ----------- BEGIN OF SECONDS AND LAST BLOCK ----------------------------
  4         Block number. Last block has number 1. Example: 01 00 00 00
  32        Block data hash. All zeros.
  4         Block length. All zeros.
  ----------- END OF BLOCKS ----------------------------  

The payload data is contained in the 1. block.

Ignore the 2. block.

We need to read the data length of the 1. block to the variable n

Then we need to skip the
32 verification bytes +
4 block number bytes +
32 block data hash bytes +
4 block data length bytes
and read n bytes coming after that. This is our payload.

Now we must check if the payload is gzipped.

The payload data is gzipped if COMPRESSION FLAG from header is 1, and not compressed if COMPRESSION FLAGS is 0.

If compressed - uncompress the payload data to get the XML. Otherwise you have plain XML data.

Now you can parse the XML.

The XML is the Keepass database with all that information that we need

XML database

If the XML element ProtectPassword has value True:


<KeePassFile>
 <Meta>
  <MemoryProtection>
   <ProtectPassword>True</ProtectPassword>
then all passwords in XML are encrypted with a stream cipher (not with AES256).