What it is
The Molto2 / Molto2v2 is a standalone TOTP token. You load account seeds into numbered slots, and the device displays the current code for each — entirely offline. Unlike a phone authenticator, there's no OS to compromise and nothing syncing to a cloud; unlike a single-account token, it holds many. It programs over a smart-card (PC/SC) interface.
keyroost's Molto2 support was built by observing the device protocol and its public
reference tool — it is not a fork of any vendor software. The wire format, SM4-CBC
MAC, and config TLV are documented in the project's PROTOCOL.md.
Programming & bulk import
Load a single slot from an otpauth:// URI, or migrate a whole set of
accounts at once:
- Aegis export (plaintext or encrypted)
- 2FAS export
- a list of
otpauth://URIs
keyroost can also sync the device clock to the host — important, because TOTP depends on accurate time, and a drifted clock shows wrong codes.
The customer key
Writes to the Molto2 are authenticated with a device customer key — a secret that gates programming so that not just anyone with physical access can reprogram your token. Sensitive commands are wrapped in an SM4-CBC MAC keyed by it.
- keyroost can rotate the customer key to a value you control.
- Treat it like any other key secret: if you lose it you may be unable to reprogram the device without a factory reset.
- As with all secrets, provide it via the environment/stdin paths keyroost exposes — never on the command line, and the tool won't print it back.
Rotating the customer key or factory-resetting the token changes what it will accept. A factory reset wipes the loaded profiles and restores the default customer key, and the token makes you confirm it with its own button. Make sure you can re-derive every seed before you do either. See resetting →
What keyroost does with the Molto2
Read slot occupancy and titles; program a slot from an otpauth:// URI;
set a slot's title or delete it; bulk-import from Aegis / 2FAS / an
otpauth:// list; sync the host clock; rotate the customer key; and
factory-reset — over a pure-Rust protocol layer (SM4, SHA-1, APDU builders, MAC)
with no external crypto dependencies.
The single-profile siblings (OTPC, miniOTP, C30x)
The Molto2 holds many accounts; Token2 also makes a family of single-profile programmable tokens that hold exactly one. These are card- and fob-shaped tokens — OTPC-P1-i / OTPC-P2-i, miniOTP-2-i / miniOTP-3-i, C301-i, and C302-i — that show one rolling code on a small display. keyroost programs them over the same kind of smart-card (PC/SC) interface as the Molto2, over a contactless or contact (chip) reader.
- Write the TOTP seed for the single account the token carries.
- Set the configuration — HMAC algorithm (SHA1 / SHA256), time-step (30 s / 60 s), and display timeout — and sync the device clock to the host.
- keyroost reads back the device serial and model and refuses to program a token whose serial doesn't match a known model.
Unlike the Molto2, these tokens don't have a per-device customer key. They
authenticate with a single fixed device key, so there's nothing to rotate or lose —
but equally, anyone with physical access and a reader can reprogram one. The wire
protocol (a close relative of the Molto2's, same SM4 cipher and MAC) is documented
independently in the project's PROTOCOL-token2prog.md.
From the CLI: keyroostctl prog info (serial, model, on-device clock),
keyroostctl prog seed (seed from stdin or an environment variable —
--base32-stdin / --base32-env, so it stays out of
ps and shell history), and
keyroostctl prog config (algorithm, time-step, display timeout). The GUI
offers the same on a dedicated programmable-token pane.
Troubleshooting
These are behaviors of the Molto2 hardware and the smart-card layer, not bugs in keyroost — any smart-card software talks to the token the same way and sees the same thing.
The token stops charging while it's plugged into a computer
The Molto2 stops charging the moment your operating system's smart-card
service enumerates it — on Linux, when pcscd brings up the card
interface. This happens as soon as the token is detected, before any program
authenticates or writes to it, so no particular application causes it. To
charge the token, use a plain USB power source — a charger
or power-only cable with no computer attached. (On a nearly full battery it
tops off in about half a minute and then stops, which is normal.)
The token isn't detected / doesn't show up
The Molto2's card interface sometimes fails to initialize on first contact, so the token is present on USB but no smart-card reader ever appears. The smart-card service only attempts initialization at the moment the token is plugged in — so waiting doesn't help, and neither does restarting the service. Each replug is a fresh attempt:
- Power the token off (unplug and leave it unplugged for ~10 seconds — a failed session can leave its card interface wedged, and only a power-off clears that).
- Plug it back in and give it a few seconds, then check
with
keyroostctl list(the app's device list updates by itself). - Still missing? Just replug again. It can take two or three cycles; no service restart is needed in between.
Restarting pcscd can't help here — it only retries a token's
initialization when the token is plugged in — and restarting it while
the token has a healthy, active connection pulls the card interface
out from under it and hangs the firmware: the screen freezes. If that
happens, power-cycle the token (turn it off and back on)
and it comes back cleanly.
I programmed a slot but it doesn't show a code
A slot shows a rolling code only once it has a seed (the TOTP secret). Writing only a title sets a label and nothing else — use the full write (seed + title + settings), not the title-only action, when you want the slot to generate codes.
Can anyone read my slot titles without the customer key?
Yes. The Molto2 answers title and occupancy reads without the customer key, so anyone with physical access to the token can list which slots are used and how they're labeled. Don't put secrets in slot titles. Seeds and codes are never readable back off the device.