L
o
a
d
i
n
g
.
.
.
https://michele.zonca.org

security

KeePass: History and the KDBX Format

By Michele Zonca

#security

#password-manager

#keepass

#cryptography

19 August 2026

4 minutes to read

August 19, 2026

I have used KeePass on and off for years, mostly for offline credentials I do not want sitting in a cloud-based vault. I never looked into where it came from or how the file format actually works, so I spent some time reading through the history and the KDBX specification.

History

KeePass was created by Dominik Reichl, a German developer, who released the first version on November 16, 2003. It was a Windows-only, C++ application, open source under the GPL, storing entries in a .kdb file encrypted with AES or Twofish.

Around 2009-2010 Reichl rewrote the application from scratch as KeePass 2.x, this time in C# on .NET. Running on Mono made it usable on Linux and macOS as well, not just Windows, and the new version introduced a new file format, .kdbx, based on XML rather than the flat binary structure of .kdb.

Because KeePass is open source and the format is documented, a separate Qt-based client called KeePassX appeared early on to cover Linux and macOS natively, without depending on Mono. KeePassX development slowed down considerably after 2013, and by 2016 a group of contributors forked it into KeePassXC to keep it moving: they added things like built-in browser integration (replacing the older KeePassHTTP plugin), TOTP support, and YubiKey challenge-response. KeePassXC is now the most actively developed desktop client, alongside mobile ports such as KeePassDX on Android and Strongbox on iOS/macOS, all reading and writing the same .kdbx files.

The KDBX format

A .kdbx file is a container, not just an encrypted blob. It starts with a header that is mostly unencrypted: it identifies the cipher used for the body (AES-256 by default, ChaCha20 as an option since the format’s 4th revision), the key derivation parameters, and a master seed. The rest of the file is the encrypted, and normally gzip-compressed, body, which is an XML document listing groups and entries: title, username, password, URL, notes, attachments, custom fields, and even a history of previous versions of each entry.

The master key is not the password itself but a combination of up to three factors: a password, a key file, and, on Windows, the current user account via DPAPI. This composite key then goes through a key derivation function before being usable to decrypt anything. Early KeePass versions used what is essentially repeated AES encryption of the key, with a configurable number of rounds (“transform rounds”) to slow down brute-force attempts. KeePass 2.35, released in 2017, introduced KDBX 4, which added Argon2 as a KDF option, a memory-hard function specifically designed to resist GPU and ASIC-based cracking far better than plain repeated AES.

KDBX 4 also changed how the file is protected against tampering. In earlier versions only a plain hash covered the body, and the header itself was not authenticated at all, meaning an attacker could, for instance, silently downgrade the KDF parameters without detection. From KDBX 4 onward, both the header and every block of the body are authenticated with HMAC-SHA256, so any modification is caught before the data is used.

One more detail I found interesting: fields marked as “protected” in the XML, passwords in particular, are not just decrypted once and kept in memory as plaintext while the database is open. KeePass XORs them with a separate keystream (Salsa20, later ChaCha20) so that a memory dump of the running process does not trivially expose them.

What stands out compared to most password managers today is that KDBX is just a local file format with no networking component built in. Syncing across devices is entirely up to the user, via Syncthing, a self-hosted WebDAV server, or whatever else, rather than a vendor’s own cloud service. That is also what makes the ecosystem of independent, compatible clients possible in the first place.

Sources: