Keyroost is an open-source software tool designed to manage hardware security keys and TOTP tokens across multiple protocols and vendors. It provides a unified interface for handling FIDO2/CTAP2, OATH (TOTP/HOTP), OpenPGP, PIV, and Token2-specific operations, enabling users to interact with their security devices seamlessly.
Key Features:
Comprehensive support for FIDO2/CTAP2, including passkey management, PIN configuration, and device reset.
Management of OATH credentials for TOTP and HOTP tokens, with bulk import capabilities from Aegis, 2FAS, or QR codes.
Full control over OpenPGP cards, including key generation, signing, decryption, and PIN management.
PIV card provisioning, certificate handling, and secure PIN/PUK changes.
Integration with Token2 devices for TOTP token programming, bulk imports, clock synchronization, and customer-key rotation.
Support for both USB-HID and PC/SC interfaces, enabling communication over NFC or contact-based readers.
Audience & Benefit:
Ideal for security-conscious individuals, IT administrators, and organizations seeking to enhance their two-factor authentication (2FA) workflows. Keyroost streamlines the management of hardware security keys and TOTP tokens, ensuring secure access control and compliance with modern security standards. Its cross-platform support and vendor-neutral design make it a versatile tool for managing diverse security devices in one place.
Keyroost can be installed via winget, offering a straightforward setup process for users across supported platforms.
README
keyroost
An independent, vendor-neutral app for managing all your hardware security keys
in one place.
What it is
keyroost is an open-source Rust toolchain for hardware security keys, working
across vendors over PC/SC and USB HID. It speaks FIDO2/CTAP2, OATH (TOTP/HOTP),
and the OpenPGP and PIV card protocols, manages on-device OTP on Token2 FIDO keys,
and also programs the Token2 Molto2 / Molto2v2 TOTP token. Ships a Rust library,
a CLI (keyroostctl), and a desktop GUI (keyroost) with a dark and light
theme — implemented from public standards, with no vendor SDKs, no Python, and
no Qt.
> Built with AI. I saw a real need for this but never learned to code, so
> the parts I author — code, docs, and all — are written end-to-end with AI.
> (Contributions from others, such as Token2's, are their own human-designed and
> -developed work — see the Contributors section.) Since the AI I use learned
> from the vast commons of free and open-source software people have generously
> shared, releasing keyroost as FOSS isn't really a choice; it's giving back to
> what made it possible. Issues, review, and contributions are warmly welcome.
FIDO2 / CTAP2 — enumerate authenticators, read authenticatorGetInfo,
manage resident credentials (list / metadata / delete), set / change / verify
the PIN, reset a key. PIN protocols v1 and v2. CTAP 2.1 security policy over
authenticatorConfig (always-require-UV, minimum PIN length, force a PIN
change, enterprise attestation) and a large-blob store for plaintext notes
over authenticatorLargeBlobs. Works over USB-HID and over a PC/SC reader —
both NFC (CTAP-over-NFC) and a contact / ISO-7816 chip reader (T=0) — not just
direct USB. Resident-credential metadata surfaces the fuller passkey detail
too: the user's UPN, display name, user id, and the full credential id.
Resident SSH credentials can be listed and their stored OpenSSH certificate
extracted from largeBlob to a -cert.pub file (fido ssh-cert).
OATH (TOTP/HOTP) — list, add, delete, and compute codes over PC/SC,
including applet-password set / clear / unlock, and a factory reset of the
applet (oath reset --yes) — the recovery path for a forgotten password. In
the GUI, secret fields have a reveal (eye) toggle so you can check an OTP
secret before committing it.
OpenPGP card (v3.4) — read status; generate or import RSA-2048 keys (host
keygen or a PKCS#1/PKCS#8 PEM/DER file) for the signature, encryption, or
authentication slot — each writes the v4 fingerprint and a generation timestamp
so GnuPG recognizes the key; sign (SHA-256 or SHA-1); decrypt; authenticate (a
client/SSH signature with the Authentication key via INTERNAL AUTHENTICATE);
set cardholder name / URL; change the user / admin PIN and unblock a locked
PIN; factory-reset the applet.
PIV (SP 800-73-4) — full management: status (applet/firmware version,
serial, PIN retries, which slots 9A/9C/9D/9E hold a certificate), on-card key
generation, certificate import / export, self-signed certs or a CSR for a CA,
clearing a slot's certificate (delete-cert) or key (delete-key, on YubiKey
5.7+), moving a key between slots (move-key, on YubiKey 5.7+), and PIN / PUK
/ management-key changes and applet reset. Every slot-taking command addresses
9A/9C/9D/9E and the 20 Yubico retired key-management slots (82–95), so keys
can be archived and rotated. The GUI collects the
management key per operation (and wipes it after), which is ideal for a slot or
two; for provisioning many slots or keys, the CLI is the intended path — the
management key and PIN come from env/stdin once, so a shell loop does the batch
(see the PIV guide).
Token2 Molto2 / Molto2v2 — program a slot from an otpauth:// URI;
bulk-import from Aegis (plaintext or encrypted), 2FAS, a list of otpauth://
URIs, or a QR code scanned from a PNG/JPEG screenshot or the live screen; sync
the host clock; rotate the customer key; factory reset.
Token2 single-profile programmable TOTP token — program the seed and TOTP
configuration onto Token2's single-account card/fob tokens (OTPC-P1-i / P2-i,
miniOTP-2-i / 3-i, C301-i, C302-i) over a PC/SC reader. These authenticate
with a fixed device key rather than a customer key, and hold one account
rather than many; keyroost reads the device serial / model and on-device
clock, writes the seed, and sets the HMAC algorithm, time-step, and
display-timeout (prog info / seed / config, or the GUI's
programmable-token pane). The wire protocol is documented in
docs/PROTOCOL-token2prog.md.
Token2 on-device OTP (PIN+ Series FIDO keys) — store TOTP/HOTP credentials
directly on a Token2 FIDO security key and read their codes over USB-HID, NFC,
or CCID; configure the single HOTP-on-touch keystroke slot; read the serial;
and enable / disable the key's USB interfaces (FIDO / keyboard-HID / CCID).
One-shot factory reset — keyroostctl factory-reset --yes (and a card on
the GUI device Overview tab) resets every resettable applet on a key in turn:
OATH, OpenPGP, PIV, Token2 OTP, then FIDO2 (which needs an unplug/replug and a
touch at the end). Only manufacturer-intended resets are used, and each step
reports its own outcome rather than being folded into one "done".
Friendly device names — an opt-in keys.json registry to target a specific
physical key by name when several are connected, instead of by a reshuffling
/dev/hidrawN path. Destructive operations always resolve to an explicit
target, never a default. The registry lives under %APPDATA% on Windows (the
platform config dir elsewhere), and names are validated with anti-spoofing
checks while allowing a relaxed, readable character set.
On Windows and macOS the OS reports no USB position, so when two keys of the
same make could each own the same card reader keyroost shows them separately
rather than guessing which reader belongs to which key.
Supported devices
Device
Capabilities
Notes
Token2 Molto2 / Molto2v2
TOTP slot programming, bulk import
Hardware-verified. Programmed over the vendor-specific SM4-MAC protocol (docs/PROTOCOL.md); supports bulk import from Aegis / 2FAS / otpauth-list, clock sync, and customer-key rotation.
Programmed over the vendor-specific SM4-MAC protocol with a fixed device key (docs/PROTOCOL-token2prog.md); writes the seed and the TOTP algorithm / time-step / display-timeout over a contact or contactless PC/SC reader. The model is recognized from the device serial.
Token2 PIN+ Series
FIDO2 (+ bio), OTP, OpenPGP, PIV
FIDO2 with fingerprint/bio enrollment and FIDO Metadata Service (MDS) display, plus on-device OTP (TOTP/HOTP, incl. HID/keyboard HOTP) over USB-HID / NFC / CCID — all validated on PIN+ hardware. Contributed by @token2. The OATH / OpenPGP / PIV smart-card applets are handled by the standard byte layers but not yet exercised on PIN+ hardware by this project (experimental).
YubiKey (5 series)
FIDO2, OATH, OpenPGP, PIV
Built and verified against a YubiKey 5.7.
SoloKeys Solo 2
FIDO2, OATH
Trussed firmware; no OpenPGP applet. HOTP caveat: the last-shipped Solo 2 firmware (2.3.x) computes HOTP over a 4-byte counter where RFC 4226 specifies 8, so its HOTP codes won't verify against standards-compliant servers (hardware-verified; fixed in the current upstream Trussed secrets app, but Solo 2 no longer receives firmware updates). TOTP is unaffected — its 8-byte time challenge comes from the host.
Nitrokey 3
FIDO2, OATH
Shares the Solo 2 / Trussed stack.
Any standards-compliant FIDO2 key (e.g. Thales, Feitian, Titan)
FIDO2 / CTAP2; OATH / OpenPGP / PIV only if the key carries those applets
keyroost implements the published specs, not vendor-specific behavior, so the fido commands — getInfo, passkey management, PIN, reset — work on any CTAP2 authenticator, including ones not listed here. Optional features (fingerprint, large-blob, authenticatorConfig) surface only when the key advertises them in getInfo. The smart-card applets apply only to keys that expose an OATH / OpenPGP / PIV applet over PC/SC. Older U2F-only (CTAP1) keys are detected by list but don't support the CTAP2 management commands.
Each listed row notes what's actually been verified on that device; the final,
generic row describes the standards-based behavior expected on untested but
compliant keys.
Roadmap
Planned hardware support, not yet shipped:
OnlyKey — it speaks FIDO2/CTAP2 over USB-HID, so the fido commands will
apply, but it exposes no smart-card interface (no OATH / OpenPGP / PIV) and its
firmware reports a fixed, non-unique serial that needs placeholder handling
before it's first-class
(#37). Pending test
hardware.
Want a different key supported? Open an issue requesting it — hardware-support
requests are tracked here and added to this roadmap.
Independence, trademarks & acknowledgements
keyroost is an independent implementation, not affiliated with or endorsed by
any vendor named here. It works with their products by implementing publicly
documented protocols; vendor and product names are used descriptively.
Token2 / Molto2 — trademarks of Token2 Sàrl. The Molto2 protocol was
determined by observing the device and its public reference tool; SM4 and SHA-1
follow their published standards (GB/T 32907-2016, RFC 3174) and are checked
against independent test vectors.
YubiKey — trademark of Yubico AB.
Solo / Solo 2 — trademarks of SoloKeys; Nitrokey — trademark of
Nitrokey GmbH.
A genuine thank-you to these teams for their work on everyone's security: Yubico
for helping create and champion U2F and FIDO2/WebAuthn and for publishing open
specs and tooling; SoloKeys and Nitrokey for open, auditable security-key
firmware and hardware (Nitrokey maintains the Trussed-based Solo 2 line); and
Token2 for affordable programmable hardware TOTP. keyroost also rests on open
standards from the FIDO Alliance, the OATH/IETF TOTP–HOTP RFCs, and the OpenPGP
card specification.
Contributors
Beyond the maintainers, keyroost is grateful for community contributions:
@token2 — contributed on-device TOTP/HOTP
management for Token2 FIDO keys (PIN+ / FIDO2+), and published the protocol
reference it was built from
(#24). Followed up with
fingerprint/bio enrollment, FIDO Metadata Service (MDS) display, and a
rounding-out of the on-device OTP support — all validated on real PIN+
hardware (#29,
#30). Also added CTAP 2.1
authenticator-config (security policy) and large-blob storage management,
with a FIDO2 tab redesign
(#38).
(This credits their contribution to the codebase; it does not change keyroost's
independent status described above.)
Standards & protocols
keyroost is built entirely from published specifications — no vendor SDKs. Every
byte layer below is implemented in-tree against the documents named here. The
two vendor-specific protocols are called out distinctly; everything else is
an open industry standard.
FIDO2 / CTAP
FIDO CTAP 2.x (Client to Authenticator Protocol) over CTAP-HID — device
info, resident-credential management, client-PIN (protocols v1 and v2), and
bio (fingerprint) enrollment.
Spec
ECDH on NIST P-256 (FIPS 186-4) for the client-PIN/UV key agreement.
NIST SP 800-73-4 / FIPS 201 Personal Identity Verification card interface,
including X.509 certificate slots.
Spec
Token2 Molto2 / Molto2v2 (vendor-specific)
The Molto2 / Molto2v2 wire protocol, determined by observing the device and
its public reference tool and documented independently in
docs/PROTOCOL.md. It layers on:
SM4 block cipher — GB/T 32907-2016 — for seed/title encryption and the
per-command MAC.
SHA-1 — RFC 3174 — to derive
the SM4 key from the customer key.
The wire protocol of Token2's single-profile programmable TOTP tokens (OTPC /
miniOTP / C30x), a close relative of the Molto2 protocol — same NFC Type-4 /
ISO 7816 transport, SM4 cipher, and ISO/IEC 9797-1 MAC — but authenticated
with a fixed device key (no customer key) and addressing a single slot.
Documented independently in
docs/PROTOCOL-token2prog.md.
Token2 on-device OTP (vendor-specific)
The Token2 OTP-on-FIDO management protocol used by the PIN+ Series keys,
published as the
Token2 OTP SDK Protocol
(issue #41). Seed-bearing
commands use ECDH (NIST P-256) + AES payload encryption.
Cryptographic primitives & encodings
AES (FIPS 197) and HMAC (RFC 2104)
— client-PIN, OTP payload encryption, and PIV management-key auth (also 3DES).
CBOR (RFC 8949, canonical
encoding) — the CTAP2 message format.
base32 (RFC 4648) and the
otpauth:// URI scheme — OTP secret encoding and 2FA import.
ISO 7816-4 APDUs (with BER-TLV / simple-TLV data objects) — the common
framing for the OATH, OpenPGP, PIV, and Molto2 smart-card applets.
Design principles
Few dependencies, by design. The protocol and codec layers are hand-written:
the Molto2 wire protocol (SM4, SHA-1, the MAC), base32, hex, CBOR, CTAP-HID
framing, and the OATH / OpenPGP / PIV byte layers are all in-tree, pulling in
nothing beyond zeroize for wiping secret buffers.
External crates are added only when not doing so would be irresponsible or
impractical — audited cryptography we won't hand-roll under forbid(unsafe_code)
(RustCrypto: sha2 / hmac / aes / p256 / rsa / …) and platform glue
(pcsc, hidapi on macOS/Windows, clap, eframe/egui). The per-crate list
is in the table below, and the standing goal is to shrink it over time, not grow
it.
Pure-Rust crypto — no OpenSSL or other C crypto; the in-tree primitives are
checked against standard test vectors, and standard algorithms come from the
audited RustCrypto crates.
Secrets stay yours. PINs and passwords come from stdin or env vars, never
argv; the tool never prints or persists them.
Single static binary per OS — no scripts, no Python, no Qt.
Toward native installs everywhere. The longer-term goal is first-class
distribution through each platform's mainstream channels. Available today:
Homebrew, AUR, Flatpak, AppImage, and winget, plus the pre-built release
binaries and cargo. All while continuing to shrink external dependencies
toward a self-contained binary.
Install
keyroost ships through every mainstream channel below. The release archives, the
Flatpak, Homebrew, winget and the AUR package all carry both keyroost (the GUI)
and keyroostctl (the CLI); the AppImage is GUI-only. Pick whichever
fits your platform; the smart-card features need a host PC/SC daemon (see
Smart-card prerequisite).
> Pre-1.0, availability tracks the latest release:
> when a version is published, these channels are updated to point at it. Replace
> vX.Y.Z below with that release tag.
Each archive carries both keyroost and keyroostctl; unpack it and move the
two executables onto your PATH. Every release also publishes SHA256SUMS and
build-provenance attestation. For example, on Linux x86_64:
curl -L https://github.com/framefilter/keyroost/releases/download/vX.Y.Z/keyroost-vX.Y.Z-linux-x86_64.tar.gz \
| tar xz # then move keyroostctl / keyroost onto your PATH
The prebuilt binaries need libpcsclite at runtime — on a FIDO-only machine install it
(apt install libpcsclite1 / dnf install pcsc-lite) or use a package that declares the dependency.
cargo (from source)
Needs the Rust toolchain — 1.92+ for the GUI (keyroost), 1.85+ for the CLI
(keyroostctl) and libraries — and, on Linux, the PC/SC dev package plus the
GUI's X11/Wayland/GL libraries (see
Smart-card prerequisite):
cargo install keyroostctl keyroost
The release binaries and the AppImage are built with the optional qr feature
(scan a TOTP QR from the live screen). cargo install does not enable it — add
cargo install keyroost --features qr if you want it.
Or let cargo-binstall fetch the same pre-built release archive instead of
compiling — useful on atomic distros (e.g. Bazzite) where cargo install's
build step is awkward:
cargo install cargo-binstall # if you don't have it yet; ensure its dir is on PATH
cargo binstall keyroostctl keyroost
Homebrew (macOS + Linux)
brew tap framefilter/keyroost
brew install keyroost
AUR (Arch Linux)
The keyroost-bin package installs the prebuilt binaries plus the FIDO udev
rules. Use any AUR helper (or makepkg):
Flatpak (Linux — auto-updating, recommended for the GUI)
Add Flathub (for the shared runtime) and the maintainer's GPG-signed remote in
the same scope, then install the app (app-id
io.github.framefilter.keyroost). Using --user needs no root and avoids the
most common failure — a scope mismatch between Flathub and the keyroost remote,
which makes the install fail to find its runtime even when it's installed:
The Flatpak carries the CLI as well; run it with
flatpak run --command=keyroostctl io.github.framefilter.keyroost.
Prefer a system-wide install? Use --system on all three commands instead —
the key is keeping Flathub and the keyroost remote in the same scope.
Or grab the offline single-file bundle (keyroost.flatpak) attached to each
release:
flatpak install ./keyroost.flatpak
The Flatpak bundles the pcsc-lite client and talks to the hostpcscd, so
you still need that daemon running on the host (see
Smart-card prerequisite).
AppImage (Linux — no install, GUI only)
Download keyroost-x86_64.AppImage from the
latest release — the
asset name is version-less, so this URL always fetches the current build:
curl -LO https://github.com/framefilter/keyroost/releases/latest/download/keyroost-x86_64.AppImage
chmod +x keyroost-x86_64.AppImage
./keyroost-x86_64.AppImage
# On FUSE3-only distros, install libfuse2, or run without FUSE:
./keyroost-x86_64.AppImage --appimage-extract-and-run
> Needs the host's pcsc-lite. Unlike the other bundles, this AppImage does
> not ship the pcsc-lite client library — it uses the host's, so the smart-card
> client always matches the host's pcscd daemon. Practically that means the
> host must have pcsc-lite installed (it comes with pcscd; see
> Smart-card prerequisite). Pure-FIDO use still needs
> it present for now, since the GUI links libpcsclite at startup — a future
> release will load it lazily so FIDO-only hosts can run without it.
Smart-card prerequisite
The smart-card features (OATH / OpenPGP / PIV, and Token2 Molto2 programming)
talk to the card over PC/SC and need the pcscd daemon running on the host.
macOS and Windows have PC/SC built in. On Linux, install the PC/SC library +
daemon (the package name differs per distro). Building from source with cargo
additionally needs the PC/SC dev package, and the GUI needs the X11/Wayland/GL
libraries that eframe/egui link against.
Once installed, keyroostctl doctor checks all of this for you — PC/SC service,
readers, FIDO HID access, and udev rules — read-only, touching no key.
keyroost is otherwise distro-neutral — it talks to the kernel's hidraw/sysfs
and to PC/SC, both of which every mainstream distribution provides; only the
package names differ. Common distro one-liners:
(For the CLI only you can drop the libxkbcommon/wayland/xcb/mesa
packages — those are just for the GUI.) macOS and Windows have PC/SC built in,
and the FIDO HID backend uses hidapi (IOKit / hid.dll) automatically — no extra
packages. macOS/Windows are tier-2 (best-effort, not yet hardware-verified).
(Building the GUI on Windows compiles a small build script that embeds the
app icon and version info into keyroost.exe; it needs a resource compiler —
rc.exe, part of the Windows SDK that ships with the standard MSVC toolchain
setup. The CLI has no build script.)
> Windows and FIDO: Windows reserves raw FIDO HID access for elevated
> processes (the OS routes normal apps through its own WebAuthn API instead).
> Expect the fido commands and the GUI's FIDO2 tab to require an
> elevated ("Run as administrator") session on Windows; the Molto2, OATH,
> OpenPGP, and PIV features go over PC/SC and work unelevated. Elevate for
> the FIDO command you need, then drop back — don't run the whole tool
> elevated as a habit. Even without admin the GUI now detects an attached
> FIDO key (via readable HID metadata, without opening the protected
> interface) and shows an "Administrator rights needed" card with a button to
> relaunch elevated or open Windows' own security-key settings.
> Prebuilt binaries: the release artifacts are built on Ubuntu and linked
> against its glibc, so they run on glibc-current distros (Arch, recent Fedora)
> but may fail on older ones (e.g. RHEL 9) with a GLIBC_… error. When in doubt,
> build from source with the commands above — cargo install handles the rest.
> Wayland and clipboard auto-clear: after copying an OTP code the GUI
> clears the clipboard ~45 s later, but only if the clipboard still holds that
> code. The check reads the clipboard via X11/XWayland; on a pure-Wayland
> session without XWayland clipboard sync it can't see the contents and fails
> open (nothing is cleared) rather than clobbering whatever you copied since.
> GNOME and KDE sync the two clipboards, so the clear works there; on other
> compositors treat the auto-clear as best-effort.
> Forcing X11 (KEYROOST_X11=1): the GUI runs natively on Wayland by
> default. The egui/eframe 0.35 bump fixed a Wayland/KDE input bug where text
> entry under native Wayland — notably on KDE Plasma — could misbehave, but if
> you still hit broken text input set KEYROOST_X11=1 to force the GUI onto
> XWayland as a fallback. It's opt-in; leave it unset for the native-Wayland
> path.
FIDO HID access (Linux udev rules)
The OATH, OpenPGP, and PIV applets are reached over PC/SC and need no special
permissions. Talking to a key's FIDO interface (the fido commands, and the
GUI's FIDO2 tab), though, opens a /dev/hidraw* node, which is
root-only by default. Install the bundled udev rules to grant the logged-in user
access:
The rules use uaccess (and a plugdev fallback), are keyed by vendor/USB so
they apply before the hidraw node is created, and cover the common FIDO vendors
(Yubico, SoloKeys, Nitrokey, Feitian, Token2, and others). Re-plug the key after
installing them.
Quick start
# discover connected devices: PC/SC readers + FIDO authenticators (USB-HID and NFC)
keyroostctl list
# diagnose the local environment (PC/SC service, readers, FIDO HID access,
# udev rules, registry permissions) — read-only, touches no key
keyroostctl doctor
# --- FIDO2 (YubiKey / Solo 2 / Nitrokey 3), over USB-HID or an NFC reader ---
keyroostctl fido info
keyroostctl fido pin-retries
keyroostctl fido creds-list --pin-stdin # PIN read from stdin, never argv
keyroostctl fido ssh-cert list --pin-stdin # list SSH certs stored in resident credentials
keyroostctl fido ssh-cert extract --credential ssh:demo --out demo-cert.pub --pin-stdin
# --- OATH over PC/SC ---
keyroostctl oath list --reader yubikey
keyroostctl oath code 'GitHub:me@x.com' --reader yubikey
# --- OpenPGP card ---
keyroostctl openpgp status --reader yubikey
keyroostctl openpgp sign --in msg.txt --pin-stdin --reader yubikey
keyroostctl openpgp authenticate --in chal.bin --pin-stdin --reader yubikey # client/SSH auth (Auth key)
# --- PIV (read-only status) ---
keyroostctl piv status --reader yubikey
# bulk-provision several slots: management key + PIN from env once, loop the rest.
# (the GUI asks per operation; the CLI is the path for many slots/keys)
export PIV_MGMT=... # AES-192 / 3DES management key, hex; never put it in argv
export PIV_PIN=...
for slot in 9a 9c 9d 9e; do
keyroostctl piv generate-key --slot "$slot" --algorithm eccp256 \
--mgmt-key-env PIV_MGMT --reader yubikey
keyroostctl piv self-sign --slot "$slot" --subject "CN=$USER" \
--mgmt-key-env PIV_MGMT --pin-env PIV_PIN --reader yubikey
done
# --- Token2 Molto2 (TOTP programming) ---
keyroostctl molto info
keyroostctl molto import --profile 0 'otpauth://totp/GitHub:me@x.com?secret=JBSWY3DPEHPK3PXP'
keyroostctl molto import-file ~/Downloads/aegis.json --start 0 --dry-run # validate first
# --- Token2 single-profile programmable token (OTPC / miniOTP / C30x) ---
keyroostctl prog info # serial, model, and on-device clock
keyroostctl prog seed --base32-stdin # base32 seed from stdin, never argv
keyroostctl prog config --algorithm sha1 --time-step 30 --display-timeout 30
# --- Token2 on-device OTP (PIN+ Series FIDO keys) ---
keyroostctl otp list
keyroostctl otp add --app GitHub --account me@x.com --seed-stdin # seed from stdin, never argv
keyroostctl otp get --app GitHub --account me@x.com
# --- Destructive operations ---
keyroostctl factory-reset --device my-yubikey --yes # reset every applet on that key
# name a key to target it when several are plugged in (opt-in)
keyroostctl key-name list
# machine-readable output for scripts (status and query commands)
keyroostctl --json piv status --reader yubikey
# shell completions and man pages
keyroostctl completions bash > /etc/bash_completion.d/keyroostctl
keyroostctl manpage ./man && man -l ./man/keyroostctl-piv.1
# launch the GUI (per-device tabs: Overview, FIDO2, Authenticator, OpenPGP, PIV,
# On-device OTP, plus the distinct Molto2 and single-profile programmable-token views)
keyroost
Breaking changes & migration
Breaking changes are tracked per release on the site's
migration notes
page, with the exact before → after for scripts and library consumers. The
two to know about: v0.7.5 renames the global device selector from
--name to --device, and v0.6.0 moved the Molto2 / FIDO commands under
the molto and fido groups.
One name to watch: in ≤0.5.xkeyroostctl factory-reset meant the Molto2
profile reset (now keyroostctl molto reset). The name is live again, but it
now wipes every applet on a key. See the migration page before re-running an
old script.
QR 2FA import from PNG/JPEG screenshots and Google Authenticator export batches — always built in; the GUI's live screen capture is behind the qr feature (on in the release archives and the AppImage, off in the Flatpak)
rqrr, png, jpeg-decoder, zeroize
keyroost-winwebauthn
Windows-only helper for the non-admin FIDO2 path: detect a FIDO key via the HID access-denied signal, open Windows' security-key settings, and relaunch elevated; inert on non-Windows
windows-sys (Windows only)
keyroost-screengrab
Windows-only still screen capture (GDI BitBlt) for QR-from-screen; isolates the unsafe Win32 FFI from the GUI crate; inert on non-Windows
eframe, egui, arboard, rfd, pollster, png, base64, serde/serde_json, zeroize; x11rb/ashpd on Linux (qr feature); winresource build-dep on Windows
Protocol
The Molto2 wire protocol is documented in docs/PROTOCOL.md
— the APDUs, the SM4-based MAC, and the TLV config payload, described as facts
about the device rather than any one implementation. The sibling single-profile
programmable token (OTPC / miniOTP / C30x) is documented the same way in
docs/PROTOCOL-token2prog.md. The FIDO2, OATH,
and OpenPGP layers follow their respective public standards.
Contact
General questions, packaging notes, and other non-security correspondence are
welcome at framefilter@proton.me.
Security issues should not go to email — please use GitHub's private
vulnerability reporting (see SECURITY.md) so the report stays
private until a fix ships.
at your option. Unless you explicitly state otherwise, any contribution
intentionally submitted for inclusion in the work by you, as defined in the
Apache-2.0 license, shall be dual licensed as above, without any additional
terms or conditions.
This dual-license is the Rust ecosystem default and matches what serde,
tokio, clap, and most of the ecosystem use.