More and more frequently, when I ask friends and family (people with a mainly non-computing background) how they manage their passwords their eyes cloud over, and I then feel the need to tell them that they ought to apply good password hygiene. (I tend to mensplain a bit.) As such I’ve been looking much more deeply into KeePassXC as a multi-platform, Open Source, and very decent password manager.
I ran away from 1Password many years ago when, IIRC, forced cloud upon their users and also converted to a subscription model and settled for EnPass at the time. Aside from a number of UI quirks in EnPass I’ve been happy enough with it, and I got it at the time when they had a purchase model; I believe that has meanwhile also changed to a subscription model. I want to be able to recommend a program which has a fixed price (Open Source is fine) and a UI which will hopefully remain somewhat consistent. I think KeePassXC matches the requirement.
These notes are intended as a reminder to myself of the features and possibilities I discovered in KeePassXC. (Start with some screenshots if you like.)
the database
KeePassXC databases (*.kdbx
; file format explained) are protected with either a password or a key file or both. The desktop app and the CLI program can optionally create these key files, and they contain 128 byte of random data which is used to augment the password. These key files can also be an image, a love letter — any file which doesn’t change. Think of it as a really complicated password that is read from a file, so you don’t have to remember or type it into your master password field.
I would likely suggest a key file created with random data and have a backup of the key file printed on paper (using a font with which I can easily differentiate zero and oh and one and ell …):
$ keyfile=kp.key
$ dd if=/dev/urandom bs=128 count=1 status=none of=$keyfile
$ openssl dgst -sha1 $keyfile
SHA1(kp.key)= f4e8b1dca0f2833d0596ba60664999fc0ca99a09
$ openssl enc -base64 -in $keyfile
MShDxixExQGpQpnoXrby0DI7lVpAr+zLuqg8P3FYOpBpRwVT+hrViMcc+tV0DMWB
nSh7ar8n4f3H5WNbT3pqI8zMJNZj23XwMc1NakzjzcZuiMxbwUK8LDuzkh2NXtjQ
464jy83ECfvomjBTQVo9B64+qeDSuaM1IHTvCYuGH3A=
$ openssl enc -A -base64 -in $keyfile |
qrencode -l Q -o $keyfile.png
In order to recover the binary key file I could scan the QR code, copy the resulting text (or even enter it manually from the base64 representation if necessary), and decode the base64 back into the key file’s data with
$ openssl enc -d -A -base64 -in /tmp/paper -out kp-new.key
$ openssl dgst -sha1 kp-new.key
SHA1(kp-new.key)= f4e8b1dca0f2833d0596ba60664999fc0ca99a09
KeePassXC databases can be synchronized via, say, syncthing, Dropbox, or a file share, etc., but the key files ought to be kept separately. Key files are also supported by KeePassium on iOS and possibly also by other apps such KeePassDX and KeePass2Android on Android, and Strongbox on iOS.
In addition to password and/or key file, the desktop apps can use a supported Yubikey (I chose a 5c nano) with HMAC-SHA1 to add additional entropy to the chosen password. While this works very well it has the disadvantage of not being supported by the mobile apps I looked at, meaning it would be a desktop-only feature. Also, it’s important to have a backup Yubikey (5c NFC here) for the feature; I wouldn’t want a lost/broken Yubikey to lock me out of the database!
Sadly, KeePassXC relies on external file synchronization, which might not be trivial to set up. As Alexander notes, the original Keepass2 (and Keepass2Android) are able to open database files directly from a WebDAV URL, and merge changes that have been made from a different device, but KeePassXC is likely the more modern choice with more features.
Python module
The Python pykeepass module interacts with KeePass databases (supports KDBX3 and KDBX4), and as such also works with KeePassXC. I can create a database (this is how I created the jane.kdbx
database for the examples on this page), create and find entries, add entries, change / add passwords and entry details, etc.
#!/usr/bin/env python3
from pykeepass import PyKeePass, create_database
import secrets
from xkcdpass import xkcd_password as xp
kp = create_database("jane.kdbx", password="tt", keyfile="kp.key", transformed_key=None)
g_work = kp.add_group(kp.root_group, "Work")
g_play = kp.add_group(kp.root_group, "Play")
g_social = kp.add_group(g_play, "socialmedia")
wordfile = xp.locate_wordfile()
mywords = xp.generate_wordlist(wordfile=wordfile, min_length=5, max_length=8)
password = xp.generate_xkcdpassword(mywords, acrostic="tonic", delimiter="-")
entry = kp.add_entry(g_work, "gmail", "myusername", password)
print(entry) # Entry: "email/gmail (myusername)"
e = kp.add_entry(g_social, "Mastodon", "janej", secrets.token_urlsafe(32))
e.url = "https://mastodon.example.com/@janej"
e.tags = [ "fediverse", "mastodon" ]
e.notes = "account created in 2018 with 2FA"
emails = [ "janej@example.com", "jane@example.com" ]
e.set_custom_property("mail", "\n".join(emails)) # custom property expects newline-separated
e.set_custom_property("uid", "12345678") # pykeepass > 4.0.3 will have: protect=True
# there doesn't appear to be a way of exiting cleanly without the .save()
kp.save()
keepassxc-cli
keepassxc-cli is a command-line tool for KeePassXC from which I can manipulate its databases.
$ kpc open -k tt.key jane.kdbx
Enter password to unlock jane.kdbx:
Passwords> help
Available commands:
add Add a new entry to a database.
analyze Analyze passwords for weaknesses and problems.
attachment-export Export an attachment of an entry.
attachment-import Imports an attachment to an entry.
attachment-rm Remove an attachment of an entry.
clip Copy an entry's attribute to the clipboard.
close Close the currently opened database.
db-create Create a new database.
db-edit Edit a database.
db-info Show a database's information.
diceware Generate a new random diceware passphrase.
edit Edit an entry.
estimate Estimate the entropy of a password.
exit Exit interactive mode.
generate Generate a new random password.
help Display command help.
ls List database entries.
merge Merge two databases.
mkdir Adds a new group to a database.
mv Moves an entry to a new group.
open Open a database.
quit Exit interactive mode.
rm Remove an entry from the database.
rmdir Removes a group from a database.
search Find entries quickly.
show Show an entry's information.
Passwords> generate
vbPf4p9VmxwhkyDehiQDQNR2XiiMUbjf
Passwords>
Using the --yubikey
option, I can also unlock a Yubikey-protected database from the command-line:
$ kpc ls other.kdbx -y 2
Enter password to unlock other.kdbx:
Please present or touch your YubiKey to continue.
...
In the example which follows, I attach an image to the database and then display all details (also the protected fields) of an entry.
$ alias kpc=/Applications/KeePassXC.app/Contents/MacOS/keepassxc-cli
$ kpc attachment-import -k kp.key jane.kdbx Mastodon mascot mastodon-mascot.jpg
Enter password to unlock jane.kdbx:
Successfully imported attachment mastodon-mascot.jpg as mascot to entry Mastodon.
$ kpc show jane.kdbx -k kp.key --show-protected --show-attachments Mastodon
Enter password to unlock jane.kdbx:
Title: Mastodon
UserName: janej
Password: REH1I0xz_iEM2VYvhiwfah5Rt1RROxqErmejlaoKY6A
URL: https://mastodon.example.com/@janej
Notes: account created in 2018 with 2FA
Uuid: {95275776-9a50-11ed-add7-f01898ef9fe7}
Tags: fediverse,mastodon
Attachments:
mascot (3.0 KiB)
It’s not actually documented anywhere that I could find, but keepassxc-cli
actually reads passwords from stdin. (tt
is the database password and the dice ware
subcommand creates four words as in ”subpar amusement crayfish footrest”
.)
$ (echo tt; kpc diceware -W 4) | kpc edit -k tt.key jane.kdbx -p gmail
Enter password to unlock jane.kdbx:
Enter new password for entry:
Successfully edited entry gmail.
I could add -q
to the command to completely silence prompts for database and entry’s new password.
the UI
- favicon downloaded from within the entry (add URL, hit download), but there is a menu for downloading URLs automatically, not possible here b/c it’s a fake address
- I didn’t understand the color square, but it’s a password-quality indicator
- Additional attributes. In future the Python module will be able to add protection (such as shown in the comment for 4.)
- Attachment names
- Group folders as created within Python
SSH agent
KeePassXC implements support for an SSH-agent, and I find it works very well. What I particularly appreciate is the possibility to override the agent socket path as I have a bit of a convoluted setup here which sets a specific path on login.
KeePassXC’s implementation can add SSH keys when unlocking a database, it can automatically remove keys from the agent after a selectable time, and it can optionally remove all keys it’s added when the database is locked (i.e. closed). Note there’s a setting with KeePassXC which can optionally ask for confirmation before using a key, but that requires the separate SSH ask-pass utility — this is not something that KeePassXC can implement as there’s no feedback from the agent itself.
There’s a very good writeup of how to manage SSH keys with KeePassXC.
TOTP
KeePassXC has built-in support for Time-based One-Time Passwords (TOTP). These are passwords which use the current time as a source of uniqueness. I prefer to use an app which does TOTP than to use SMS for two-factor authentication (2FA).
I have some doubts about the security of having TOTP within the password manager (I use Authy and not the support built-in to EnPass), so I asked on Mastodon:
Is there a consensus on whether it is better/safer to have TOTP generation done within the password safe (e.g. KeePassXC) or rather externally using a separate program (e.g. Authy)?
I think I’m summarizing correctly when I quote Thomas, who responded:
It’s better to have it on a separate device. But it’s also better to have it in any place than to not have it at all.
That’s probably very good advice.
Further reading
- If you’re into Ansible, there’s a lookup plugin called ansible-keepass which implements support for KeePassXC databases. They spawn a process which keeps the KDBX file open in order to save time.
Note that the included attachment module is lacking: it has no support for KDBX key filesI have supplied a patch with support for key files. - These 2022 comments regarding TOTP in a password manager (this has nothing to do with Bitwarden) are worth looking at.
- A curated list of KeePass-related projects
- Extract TOTP codes from Authy
- Password strength explained