What it is
Token2 keys can store OATH-style OTP entries directly on a hardware applet, read over CCID/NFC or USB-HID. Unlike an authenticator app, the seeds are sealed on the secure element: keyroost provisions them with an encrypted write and reads live codes, but the secret material cannot be exported.
Adding & reading codes
In the On-device OTP tab, choose + Add entry, then enter the issuer/app, account and Base32 secret and pick TOTP (time-based) or HOTP (counter-based), the algorithm, digits, and — for TOTP — the period (commonly 30 or 60 seconds). TOTP entries show a live code with a countdown ring that refreshes when the window rolls over. Entries marked require touch show a Read button — press it and touch the key to reveal the code.
Importing codes from an authenticator app
keyroost can add every code in an authenticator export to the key's OTP storage in
one step: an Aegis export (plain or encrypted), a 2FAS export, a text file with one
otpauth:// URI per line, or a QR screenshot, including a Google
Authenticator export. In the On-device OTP tab, click
Import file… (or drop the file on the window); the Import
authenticator codes dialog shows what each entry will become before anything
is written. On the command line:
keyroostctl otp import -i export.json --dry-run # show what would happen; writes nothing
keyroostctl otp import -i export.json # asks once, then adds the codes
An entry whose app and account are already on the key is left as is
(exists); --replace replaces it. An entry the key can't
store is skipped, with the reason. keyroost asks once, writes one
code at a time, and stops at the first error, saying what was added and what wasn't.
What the OTP storage takes:
- up to 50 codes;
- app and account names of up to 64 bytes each, in plain ASCII characters;
- SHA-1 or SHA-256 (no SHA-512), 4 to 10 digits;
- HOTP codes only with a counter of 0, because the key always starts the counter at 0.
When both the export's password and the OTP PIN are piped in, the export's password
(--file-password stdin) is the first line and the PIN the second. Import
into OTP storage follows Token2's published OTP specification.
HID-HOTP (HOTP-on-touch)
HID-HOTP is a single dedicated slot that makes the key act like a keyboard: touch it outside any session and it types a fresh HOTP code wherever your cursor is — handy for systems that accept a typed one-time code.
HID-HOTP types over the key's keyboard (HID) interface, so that interface must be
enabled. keyroost shows an Enable HID-HOTP /
Disable HID-HOTP item in the pane's … menu; because
it reconfigures the key's USB interfaces you must type the phrase
change interface to confirm, and the change needs a re-plug to take
effect. keyroost refuses any change that would leave fewer than two interfaces
enabled, so you can't lock yourself out.
Provisioning
From the pane's … (more actions) menu choose Configure HID-HOTP…, enter the Base32 secret, choose 6 or 8 digits, and set the typing options: Send Enter (append Return), Long touch (2s) (require a two-second press), Numeric keypad (type with keypad scancodes). Save, and the card shows the slot as configured.
Changing options without re-entering the seed
Once a seed is provisioned you can change the typing options without re-entering the secret: reopen the form, leave the secret field blank, and press Save. The seed slot is left untouched (digit length can only change as part of a seed write, so it is grayed out until you type a new secret). To replace the seed, enter a new secret and Save; to remove it, use Clear slot.
Putting codes behind a PIN (R3.4+)
Keys running the R3.4 OTP applet can require a PIN before they hand out any codes. Set one and the entry list stays sealed until you unlock it; the key keeps the window open for a few minutes and then closes it again. Older keys simply don't have the feature — they answer the capability question with "no such command", and everything on this page works exactly as it always did.
In the GUI, the On-device OTP tab shows an unlock prompt in place of the list, and the pane's … menu grows Set PIN…, Change PIN…, Remove PIN… and Lock now.
On the command line:
keyroostctl otp pin status # is a PIN set, and how many tries are left
keyroostctl otp pin set # protect this key (asks for the new PIN twice, hidden)
keyroostctl otp pin verify # open the read window for this connection
keyroostctl otp pin change # asks for the current PIN, then the new one
keyroostctl otp pin clear # back to unprotected
keyroostctl otp list # asks for the PIN when the key needs it; same for add and delete
keyroostctl otp pin change --pin stdin --new-pin stdin # in a script: current PIN on line 1, new on line 2
The PIN comes from a hidden prompt in a terminal or, in a script, from
--pin env:NAME (an environment variable) or --pin stdin
— never from the command line, where it would land in your shell history
and in the process list. list,
add and delete all take --pin.
Unlocking with a fingerprint (Bio3)
On a Bio3 key with at least one fingerprint enrolled, a fingerprint touch can release the protected codes as an alternative to entering the PIN. Fingerprint enrollment itself is done through the key's FIDO2 fingerprint setup, not here; keyroost turns the OTP-side option on or off and unlocks with it. Turning it on or off needs the current PIN; turning it on also needs an enrolled fingerprint.
keyroostctl otp fingerprint status # is fingerprint unlock available, and is it on
keyroostctl otp fingerprint enable # turn it on (asks for the current PIN)
keyroostctl otp fingerprint disable # turn it off (asks for the current PIN)
keyroostctl otp list --unlock fingerprint # touch the sensor to unlock, then list
keyroostctl otp list --unlock auto --pin env:OTP_PIN # try the fingerprint, fall back to that PIN
When fingerprint unlock is on, the GUI's unlock prompt shows a fingerprint-touch button alongside the PIN field, and either one opens the read window.
There is no PIN reset. Wrong attempts count down a retry counter, and once it
reaches zero the applet refuses the PIN for good — the only way back is
keyroostctl otp reset, which destroys every OTP entry on the key.
Keep a record of the PIN somewhere you trust before you set one.
The PIN never travels in the clear: host and key agree a session key first, and the PIN is only ever sent encrypted under it. The key enforces the retry counter itself, so guessing costs attempts on the key, not on the host. Treat the PIN as protection against someone picking up your key; what it protects against beyond that is a property of the key's firmware rather than of keyroost, and Token2 is the authority on it.
Command line
keyroostctl otp list # stored entries
keyroostctl otp code --account <name> # read a live code
keyroostctl otp info # interface states & slot status
keyroostctl otp import -i export.json # add every code in an authenticator export
keyroostctl otp button set --digits 6 # provision HID-HOTP (asks for the base32 seed, hidden)
keyroostctl otp interface --fido --ccid --keyboard # enable interfaces (re-plug after)
Some keys answer otp info with a short configuration
block, which doesn't include the on-device OTP and HOTP-on-touch details; keyroost
then shows those three rows as unknown rather than guessing.
Every otp subcommand accepts
--transport auto|hid|ccid (default auto: over USB first —
through the key's FIDO interface, using Token2's documented vendor command, then
the older HID framing — with CCID/NFC as the fallback). Token2 models without
HOTP-over-HID ship with that HID channel disabled by design; if a command still
reports the key declining over USB, --transport ccid is the path, with the smart-card service
(pcscd) running or the key on a reader.
With several Token2 keys connected, a terminal shows a numbered list
to pick from; a script names one with --device (or --reader /
--path). delete, reset,
button clear, and button set on a key that already has
a button seed name the key and ask y/N first; a script, or a command
whose seed or PIN is piped in, adds --yes. interface asks you
to type reconfigure interfaces at the terminal, or takes
--yes.
Authoritative resources
From the command line: see Authenticator codes on a key and Import codes from an authenticator app on the Command line page.