A tool to detect when your YubiKey is waiting for a touch (to send notification or display a visual indicator on the screen)
This is a tool that can detect when YubiKey is waiting for your touch. It is designed to be integrated with other UI components to display a visible indicator.
For example, an integration with i3wm and py3status looks like this:
See also: FAQ: Which UI components are already integrated with this app?
This tool only works on Linux. If you want to help implementing (at least partial) support for other OS, pull requests are very welcome!
On Arch Linux, you can install it with
pacman -S yubikey-touch-detector
The package also installs a systemd service and socket. If you want the app to launch on startup, just enable the service like so:
$ systemctl --user daemon-reload $ systemctl --user enable --now yubikey-touch-detector.service
If you want the service to be started only when there is a listener on Unix socket, enable the socket instead like so:
$ systemctl --user daemon-reload $ systemctl --user enable --now yubikey-touch-detector.socket
Alternatively you can download the latest release from the GitHub releases page. All releases are signed with my PGP key.
Finally you can install the app with
go:
$ go get -u github.com/maximbaz/yubikey-touch-detector
This places the binary in your
$GOPATH/binfolder, as well as the sources in
$GOPATH/srcfor you to use the detection functions in your own code.
To test how the app works, run it in verbose mode to print every event on STDERR:
$ yubikey-touch-detector -v
Now try different commands that require a physical touch and see if the app can successfully detect them.
You can make the app show desktop notifications using
libnotifyif you run it with corresponding flag:
$ yubikey-touch-detector --libnotify
The app supports the following environment variables and CLI arguments (CLI args take precedence):
| Environment var | CLI arg | | ---------------------------------- | ------------- | |
YUBIKEY_TOUCH_DETECTOR_VERBOSE|
-v| |
YUBIKEY_TOUCH_DETECTOR_LIBNOTIFY|
--libnotify|
You can configure the systemd service by defining any of these environment variables in
$XDG_CONFIG_HOME/yubikey-touch-detector/service.conf, e.g. like so:
YUBIKEY_TOUCH_DETECTOR_VERBOSE=true YUBIKEY_TOUCH_DETECTOR_LIBNOTIFY=true
First of all, make sure the app is always running (e.g. start a provided systemd user service or socket).
Next, in order to integrate the app with other UI components to display a visible indicator, use any of the available notifiers in the
notifiersubpackage.
unix_socketnotifier allows anyone to connect to the socket
$XDG_RUNTIME_DIR/yubikey-touch-detector.socketand receive the following events:
| event | description | | ------- | -------------------------------------------------- | |
GPG_1| when a
gpgoperation started waiting for a touch | |
GPG_0| when a
gpgoperation stopped waiting for a touch | |
U2F_1| when a
u2foperation started waiting for a touch | |
U2F_0| when a
u2foperation stopped waiting for a touch |
All messages have a fixed length of 5 bytes to simplify the code on the receiving side.
Your YubiKey may require a physical touch to confirm these operations:
sudorequest (via
pam-u2f)
gpg --sign
gpg --decrypt
sshto a remote host (and related operations, such as
scp,
rsync, etc.)
sshon a remote host to a different remote host (via forwarded
ssh-agent)
See also: FAQ: How do I configure my YubiKey to require a physical touch?
In order to detect whether a U2F/FIDO2 operation requests a touch on YubiKey, the app is listening on the appropriate
/dev/hidraw*device for corresponding messages as per FIDO spec.
See
detector/u2f.gofor more info on implementation details, the source code is documented and contains relevant links to the spec.
This detection is based on a "busy check" - when the card is busy (i.e.
gpg --card-statushangs), it is assumed that it is waiting on a touch. This of course leads to false positives, when the card is busy for other reasons, but it is a good guess anyway.
In order to not run the
gpg --card-statusindefinitely (which leads to YubiKey be constantly blinking), the check is being performed only after
$GNUPGHOME/pubring.kbx(or
$HOME/.gnupg/pubring.kbx) file is opened (the app is thus watching for
OPENevents on that file).
If the path to your
pubring.kbxfile differs, define$GNUPGHOMEenvironment variable, globally or in$XDG_CONFIG_HOME/yubikey-touch-detector/service.conf.
The requests performed on a local host will be captured by the
gpgdetector. However, in order to detect the use of forwarded
ssh-agenton a remote host, an additional detector was introduced.
This detector runs as a proxy on the
$SSH_AUTH_SOCK, it listens to all communications with that socket and starts a
gpg --card-statuscheck in case an event was captured.
For
sudorequests with
pam-u2f, please refer to the documentation on Yubico/pam-u2f and online guides (e.g. official one).
For
gpgand
sshoperations, install ykman and use the following commands:
$ ykman openpgp set-touch sig on # For sign operations $ ykman openpgp set-touch enc on # For decrypt operations $ ykman openpgp set-touch aut on # For ssh operations
If you are going to frequently use OpenPGP operations,
cachedor
cached-fixedmay be better for you. See more details here.
Make sure to unplug and plug back in your YubiKey after changing any of the options above.
.#lk*files in
~/.gnupgand how to clean them up?
These are temporary files being created by
gpgwhile
yubikey-touch-detectoris checking if YubiKey is waiting for a touch. The hope is that we can implement a different implementation to detect touch request using some sort of smartcard protocol (like it is done for WebAuthn / U2F), which would stop producing these files.
Until then, you have to manually clean them up. One way is to use
systemd-tmpfiles, which requires you to create
~/.config/user-tmpfiles.d/gnupg.confwith the contents below and if necessary enabling
systemd-tmpfiles-setupservice:
r %h/.gnupg/.#lk*