| Name | Size |
|---|---|
| .gitignore | 20B |
| LICENSE | 1072B |
| PKGBUILD | 882B |
| README.md | 5363B |
| scripts/socket_client.py | 1410B |
| system/dbus.service | 95B |
| system/portal | 102B |
| system/systemd.service | 293B |
| system/systemd.socket | 108B |
| xikeyring/__init__.py | 0B |
| xikeyring/__main__.py | 2081B |
| xikeyring/crypto.py | 1385B |
| xikeyring/dbus.py | 14123B |
| xikeyring/dbus_sessions.py | 3591B |
| xikeyring/dumpable.py | 510B |
| xikeyring/kernel_keyring.py | 1291B |
| xikeyring/keyring.py | 6008B |
| xikeyring/org.freedesktop.Secrets.xml | 5747B |
| xikeyring/pidfd.py | 2112B |
| xikeyring/prompt.py | 2282B |
| xikeyring/socket_service.py | 3534B |
xi keyring
A simple and extensible alternative to gnome-keyring that implements
the
org.freedesktop.Secret
DBus interface and the XDG Desktop Portal Secrets
backend
as well as a simple JSON socket interface.
Design
Focus on Experimentation
gnome-keyring is tightly integrated into the Linux desktop. There are many
other password managers with interesting features. Just to name a few:
KeePassXC,
Bitwarden, pass, and
Himitsu. However, they do not all implement
the org.freedesktop.Secret interface, so they cannot be used as drop-in
replacements. On the other hand, gnome-keyring is so big and complex that it is
hard to experiment with new features.
The main focus of this project is to provide a simple code base that makes it easy to experiment with new features. While the result is usable, the focus is on experimentation rather than providing a complete product.
Limit access to secrets
With gnome-keyring, secrets in an unlocked collection can be read by any application that has access to the session bus. This does startle some users, but the developers have repeatedly explained that there is just no point in trying to protect against malicious un-sandboxed applications.
While I understand the sentiment, I feel like there is room for nuance here. These are some of the mechanisms xi-keyring uses to limit access to secrets:
- Prompt the user when an application tries to access a password to provide some degree of observability.
- Prevent malicious applications from taking memory dumps by using
PR_SET_DUMPABLE - Keep the keyring locked as much as possible without impacting user comfort too much. For example, don't unlock automatically on login.
- Allow to use different namespaces for different applications (see below for details)
Of course, a malicious application that is completely unrestricted can still work around these measures, e.g. by starting a modified keyring implementation. However, the amount of sandboxing necessary with these restrictions already in place is greatly reduced.
Compatibility with DBus interface
While this project aims to be a drop-in replacement for gnome-keyring, some
features of the org.freedesktop.Secrets interface have been simplified:
- There is only a single collection (called "it")
- Trying to create or delete a collection fails
- Whether the keyring is locked or not is not exposed
- All objects present themselves as unlocked
- The process of unlocking a keyring is transparent for the caller
- The
Unlockmethod fails - The
Lockmethod still has an effect though
- Prompts are transparent for the caller. No prompt is ever returned
- Labels are generated automatically and cannot be changed
Created/Modifiedis always 0
Compatibility with XDG Desktop Portal
It took me a while to understand the Secret Desktop Portal. When it finally clicked I wrote a blog post about it.
The main idea is that the backend only stores a single key for each applications, and the application uses that key to encrypt its own secrets.
Applications that are sandboxed with flatpak can reliably be identified by this mechanism. However, application running on the host can identify an arbitrary app ID using the Registry portal.
Simple socket interface
One major downside of DBus is that all services share a single socket. This means that a mount namespace has either access to all service, no services at all, or it has to use xdg-dbus-proxy.
From this perspective, using one socket per service is a much better approach.
That is the basic idea of
xi-desktop-portals. For the
keyring, a socket is available at $XDG_RUNTIME_DIR/xi.portal.Secret.
A client is included in scripts/socket_client.py. It has an interface similar
to the keyring CLI.
Namespacing
xi-keyring loads the keys from a file in the client's mount namespace. This
makes it easy to give each application its own set of secrets. Simply mount a
different folder into $XDG_DATA_HOME/xikeyring/. The mount namespace is the
secret namespace.
However, you need to be careful when using proxies:
- With flatpak,
xdg-dbus-proxyis the immediate client, and it has full access to$XDG_DATA_HOME. - With portal APIs,
xdg-desktop-portalis the immediate client, and it has full access to$XDG_DATA_HOME.
When using flatpak, I recommend using the portal APIs and their namespacing based in app IDs.
With other sandboxing mechanisms, I recommend using the socket interface because it allows to nest different sandboxes inside of each other and does not require a separate proxy process.