Skip to content

Reverse Engineered KeePass File Format

Integers are stored in little endian format.

*Magic bytes

8 bytes: 0x03, 0xd9, 0xa2, 0x9a, 0x67, 0xfb, 0x4b, 0xb5

The magic bytes are used as a first check to determine if a file could be a KDBX file.

*Format version

This field is uint32, where the upper 16 bits represent the major version, and the lower 16 bits represent the minor version.

Version 2.20.1: 0x003001

*Header

The header consists of a number of header fields. The order of the fields is not important. Header fields are read until the end of header field is encountered. A header field starts with a header with the following structure:

uint8 id uint16 size of field data

followed by the field data.

Header fields

end of header

id 0 size 4 data 0x0d, 0x0a, 0x0d, 0x0a

comment

id 1

The comment field seems to be ignored in KeePass.

cipher id

id 2

The cipher id is 16 bytes. For AES-CBC with PKCS7 padding, which is the default cipher, the id is 0x31,0xc1,0xf2,0xe6,0xbf,0x71,0x43,0x50,0xbe,0x58,0x05,0x21,0x6a,0xfc,0x5a,0xff

compression

id 3 size 4 data 0x00,0x00,0x00,0x00 (no compression)

master seed

id 4 size 32

The master seed is a 32 byte salt value for the key transformation.

transform seed

id 5 size KeePass writes 32 bytes of transform seed, but accepts a seed of any length when reading a file.

The transform seed is another salt value for the key transformation.

number of transform rounds

id 6 size 8

The number of key transformation rounds, expressed as an uint64.

iv

id 7 size KeePass always writes 16 bytes of IV, but the length is not checked when reading the file. Having the wrong IV length would cause an exception in the encryption engine, though.

The IV of the cipher.

protected stream key

id 8 size KeePass always writes 32 bytes, but length is not checked when reading the file.

the protected stream key seems to be a way to obfuscate some fields of the decrypted file.

stream start bytes

id 9 size 32

the initial 32 bytes of the decrypted stream, used to verify that the decryption key is probably correct before decrypting the entire stream

inner random stream id

id 10 size 4

an uint32 giving the algorithm used to produce the random stream used with the protected stream key for obfuscation