keepassxc-specs
keepassxc-specs copied to clipboard
add kdbx binary format overview
Thanks for your work on this. To get this merged, we need to make a proper RFC from it, though. But I'll leave this open so we can use it as technical reference.
Wouldn't it be useful to have both an RFC and concise overview? Essentially a more complete version of https://keepass.info/help/kb/kdbx_4.html
Yes, but then we need to think about a format and I want it to he something more technical and consistent than simple Markdown lists. I plan on making all this (including the RFCs) available in a consistent format on the website once it's finished.
There is probably little point commenting here but I happen to have written a format documentation today before I found this pull request.
There are a few mistakes here:
-
minor_version
comes beforemajor_version
(KeePass actually considers it a single 4 byte field, and it’s little-endian, so…) - In the dynamic header, data for type 0x00 isn’t necessarily 0 bytes. Typically, it’s four bytes 0D 0A 0D 0A, for whatever reason.
- In the dynamic header, type 0x01 isn’t really supported – both KeePass and KeePassXC will silently remove this comment.
- In the dynamic header, type 0x03 isn’t really a flag – it’s the index of the compression algorithm. And it’s a uint32 field, not a padded uint8.
- In the dynamic header, type 0x07 isn’t always 16 bytes. It’s only 16 bytes for CBC-based ciphers, and it’s 12 bytes for ChaCha20.
- In KDFParameters,
$UUID
can also be 9e298b1956db4773b23d-fc3ec6f0a1e6 meaning Argon2id. All other parameters are identical to Argon2d then. - The calculation of
key_composite
is more complicated actually. There can also be data from key providers. Also, the keyfile isn’t necessarily hashed. If it’s an XML file, a binary file with 32 bytes or a file with 64 hex digits then no hashing is being performed. - KDFParameters specify Argon2d memory cost in bytes. This is important because in the algorithm spec (and all implementations) it’s kilobytes.
- Something is wrong in the AES-KDF description: ECB does not work with initialization vectors.
- The first sentence in the “payload” section is misleading. Payload is not being encrypted block-wise, this would have been a vulnerability (there is only one IV). It’s rather being encrypted in full, then split into blocks and signed block-wise.
- In the inner header, 0x00 is not actually a type – there is no length following. It’s the end marked, like for the dynamic header.
- In the inner header, binary_data is not plugin data – it’s file attachments.