aboutsummaryrefslogtreecommitdiff

OTP Wallet user guide

OTP Wallet keeps one-time passwords (TOTP, HOTP and Steam Guard) and barcodes (loyalty cards, tickets, QR codes) on your Garmin watch, encrypted. Nothing leaves the watch: there is no account, no cloud and no network access. You add entries from the Garmin Connect app on your phone; the watch is the only place they are stored.

Contents

Install

Garmin's app settings only work for apps installed from the Connect IQ Store, so OTP Wallet is installed as a private beta that only your Garmin account can see:

  1. The developer uploads the signed package (make package builds build/package/otp-wallet-<version>.iq) on Garmin's developer site as a beta app.
  2. On your phone, open the Connect IQ Store app, find the beta under your apps, and install it on your watch.
  3. Each new version is a new upload; the Store updates the watch, and your entries stay (check this once with the real-watch checklist).

From the beta to the Store app (1.0.0): the public Store app has a new application ID, so the watch treats it as a different app from the private beta (0.9.0 and earlier). Nothing carries over: install the Store app, import your entries again from your authenticator, set a PIN, check the codes, then delete the beta from the watch.

A sideloaded build (copied over USB) runs, but gets no phone settings, so you can't add entries to it. Sideloaded debug builds are for testing with fake demo entries only.

Where the settings are

In the Garmin Connect app: your watch, then Connect IQ apps, then OTP Wallet, then Settings. The settings are a set of forms. Each form has a switch at the bottom ("Add this entry", "Import now", "Apply"); the watch acts on a form only when its switch is on, and only when it receives the settings:

  • If OTP Wallet is open on the watch, it applies the forms within seconds of saving.
  • Otherwise it applies them the next time you open it.

Each form has a Result field the watch writes back, and the watch shows the same lines on its Settings results screen (also in its menu). After a form is applied the watch turns its switch off and clears it, the secret field first. After a problem only the secret field is cleared, so you can correct the rest and send it again. Sending exactly the same form twice does nothing the second time.

Close and reopen the settings page on the phone to see the cleared fields and the Result text. Garmin Connect on Android shows them after reopening (SETTINGS_SPIKE.md); changes reach an open app in about a second.

Add an authenticator code

Use the Add OTP form with the details the website shows when you set up two-factor authentication (choose "can't scan the code?" or "enter the key manually" to see them):

Field What to enter
Type TOTP (almost every site), HOTP (counter based) or Steam
Issuer (service) and Account For example "GitHub" and your user name. At least one of them
Secret The key in Base32 (letters A–Z and digits 2–7). Spaces, hyphens and lower case are fine
Algorithm, Digits, Period Leave SHA1, 6 and 30 unless the site says otherwise
Counter HOTP only: the starting counter, usually 0
Group Optional, shown in the list
Require PIN to display The code is only shown after you enter the app PIN

Turn on Add this entry and save. The result says, for example, "Added K7F2 GitHub (alice)", or exactly what to fix ("Secret: '1' is not a Base32 character (position 5)"). Check that the watch shows the same code as the website or your phone authenticator before you rely on it.

The Import form takes the text of an unencrypted Aegis export (Aegis: Settings, Import & Export, Export, plain JSON) or any number of otpauth:// links:

  1. Paste the text into Text, part 1. If it is longer than one field takes, continue in the next part; the watch joins parts 1 to 8 in order.
  2. Choose the mode: Add to my entries (default), or Replace imported entries (removes entries that came from earlier imports first; entries you added by hand are never touched).
  3. Turn on Require PIN for these entries if they should all be locked.
  4. Turn on Import now and save.

The report lists how many entries were imported and every one that wasn't, with the reason: duplicates of entries you already have, unsupported types (mOTP, Yandex), or bad values. Aegis favourites stay favourites (see the glance); icons and notes are not imported.

Long exports. If the text is still incomplete after joining the fields, the watch keeps what it got (encrypted) and says "Waiting for more: received ... characters". Paste the next part into the fields, turn Import now on again, and save. The waiting part expires after 24 hours and is limited to 32 KB; choose the mode Cancel waiting import to discard it. A compact export takes about 190 characters per entry; remove icons from the export if it is much larger.

Afterwards, delete the exported JSON file from your phone, and keep such files out of cloud-synced folders. The import fields are cleared on the phone by the watch.

iPhone: if Garmin Connect refuses the & in a link, write ; instead; the watch accepts both.

Google Authenticator's export links (otpauth-migration://) are not supported. Import them into Aegis first and export from there.

Add a barcode or QR code

Use the Add code form:

Field What to enter
Card name For example "Gym card"
Barcode type QR, Code 128, Code 39, EAN-13, EAN-8, UPC-A, UPC-E, ITF, Codabar, Data Matrix, PDF417 or Aztec
Contents The text or digits the code holds (as printed under the code, or what a scanner app reads from it)
Error correction 2D codes: Medium is right for most uses
Check digit EAN, UPC and ITF: "Add or verify" checks the last digit; "Fix if wrong" corrects it
Show the text under the bars The digits under linear codes
Group, Require PIN to display As for OTP entries

The watch encodes the code to check it, and warns if it won't fit your screen at a scannable size. 2D codes are drawn the first time you open them ("Encoding… 40%"); after that they open at once.

Change, move or delete an entry

Use the Manage entry form with the entry's ID: four characters such as K7F2, shown at the bottom of each entry on the watch, under Entry IDs in the watch menu, and in the About group of the settings (the catalog). Case doesn't matter.

Action Fields used
Edit details New name, account or group; blank keeps a field, - clears it
Move to position The new position, 1 = top
Require PIN / Don't require PIN —
Replace secret or contents The new secret (Base32) or code contents
Set HOTP counter The counter
Delete —
Mark as favourite (glance) / Remove favourite —

Changes to locked entries wait for you. Anything that would change or reveal a locked entry (everything except moving it) is not applied when it arrives. The watch shows "Phone changes: N to confirm" at the top of its menu and in the list title. Open it ("Reading…" shows briefly), check the list, and choose Confirm all (it asks for the PIN, even if the app is unlocked) or Reject all. This way, someone with access to your phone alone can't unlock or rewrite your locked entries. A replacement secret or code contents is checked when it arrives, so a typo is reported in the Result at once. Require PIN sent while the watch is locked needs no confirming: it applies the next time you enter the PIN, and the list then says "Results ready (menu)".

The PIN and locked entries

  • Set PIN in the watch menu creates it (exactly 4 digits; the 4th digit enters it, there is no OK key). A PIN set with version 0.8.0 or earlier still works once; the watch then asks you for a new 4-digit PIN. You are also asked for one the first time an entry needs it.
  • Entering the PIN unlocks all locked entries until the app locks again: when you leave the app, after the auto-lock time (option), or with Lock now in the menu.
  • Wrong PINs: after 5 wrong PINs the watch makes you wait, longer with each further mistake. With the option Erase locked entries after 10 wrong PINs, the tenth wrong PIN erases the locked entries (unlocked entries stay).
  • Change PIN keeps your entries. Reset PIN, for a forgotten PIN, erases the locked entries and lets you set a new PIN; there is no other way back into them.
  • Locked entries are encrypted with a key that only your PIN opens. A 4-digit PIN stops someone using your watch (wrong PINs make it wait, and it can erase the locked entries after 10), but it can be guessed in seconds by someone who copies the watch's storage to a computer. Keep that in mind for very sensitive accounts.

Daily use on the watch

  • List: your entries in your order. Unlocked TOTP and HOTP entries show the current code and a small countdown; locked entries show a lock; barcodes show an icon.
  • Open an entry (tap it, or START): the code in large digits with a countdown ring; in the last 5 seconds the next code is shown too. For HOTP, tap the code (or START) for the next one.
  • Barcodes open black on white, at the largest size that fits. They are shown at full brightness for about a minute on AMOLED watches (the screen's own limit; tap to brighten it again), and with the backlight on MIP watches. You can turn this off under Options.
  • Menu (hold MENU, or long-press the list on touch-only watches): Phone changes, Lock now, Set/Change/Reset PIN, Settings results, Entry IDs, Clock status, About (version, storage, self-test result).
  • BACK on the list leaves the app and locks everything.

The glance

In the watch's glance loop, OTP Wallet shows the number of entries. With the option Show the favourite code in the glance on, it shows instead the current code of your first favourite TOTP or Steam entry that doesn't require the PIN, with a bar for the seconds left:

  • Mark an entry as favourite with Manage entry, "Mark as favourite (glance)" (Aegis favourites already are).
  • Locked entries and HOTP entries never appear in the glance.
  • The glance updates the code once you've opened the app after changing your favourites; turning the option off hides the code at once.
  • Anyone who can see your glance loop sees that code, so choose an entry for which that's acceptable (SECURITY.md).

Options

Option Default Meaning
Lock after 1 min How long locked entries stay open without input: immediately, 15 s, 30 s, 1, 2 or 5 minutes
Erase locked entries after 10 wrong PINs Off See the PIN
Time offset in seconds 0 Seconds added to the watch clock if your codes are consistently early or late (−120 to 120)
Code size Large Size of the digits on the detail screen
Theme Dark Dark or light screens (barcodes are always black on white)
Show groups On The group in front of the account in the list
Encrypt names on the watch Off Keeps names and accounts in the encrypted part too; locked entries then show only "Locked entry" and the About catalog only IDs
Show the favourite code in the glance Off See the glance
Full brightness while showing a barcode On See daily use

Moving to a new watch, and backups

OTP Wallet never exports your secrets: they only flow into the watch. Your backup is your authenticator app or Aegis vault (and the recovery codes the websites gave you). To move to a new watch, install OTP Wallet there and import or add your entries again, then delete the app from the old watch (uninstalling removes all its data).

Troubleshooting

Problem What to do
Codes are rejected Open Clock status in the menu. The watch clock must be right to within a few seconds; sync the watch (GPS activity or phone sync). If it is always off by the same amount, set Time offset
Nothing happens after saving a form Open OTP Wallet on the watch; forms are applied when the app runs. Check that the form's switch was on
"Already added" or "Already imported" The watch has already applied exactly that form; change something to send a new one
"Waiting for more" after an import The JSON was incomplete: paste the rest and send again, or choose the mode "Cancel waiting import"
"Damaged entry K7F2" That entry's stored data can't be read. Delete it with Manage entry and add it again
A barcode says "Too large for this screen" The contents are too long for a scannable code on this watch. Use a shorter text, or a 2D symbology for long text
A barcode doesn't scan Turn brightness up (the option is on by default), hold the watch steady and flat, and try both closer and further away. Laser scanners at tills often can't read screens
"Data from a newer version" The app was downgraded; install the newest version again
"Crypto self-test failed" The watch's crypto didn't give the expected results; codes are hidden to be safe. Update the watch firmware and report it

Known limitations

  • Connect IQ limits
  • No unlocking with the watch's own passcode; the app has its own PIN.
  • App settings only work with the Store version, which is why the app is a private beta rather than sideloaded.
  • The phone shows what the watch writes back (Result fields, cleared forms, the About catalog) only after you reopen the settings.
  • Garmin Connect refuses to save text that contains a backslash \ (SETTINGS_SPIKE.md). otpauth:// links never contain one. Aegis on Android writes every / as \/, which happens in entry icons and in names with a /. If the phone refuses to save an Aegis export, replace every \/ with / in a text editor (the file stays valid), or remove the icons in Aegis and export again, or use otpauth:// links. A name with a " in it can only come over as an otpauth:// link.
  • Import
  • Encrypted Aegis exports can't be decrypted on a watch (it would need 32 MiB of memory); export unencrypted.
  • Google Authenticator export links aren't supported; mOTP and Yandex entries are skipped.
  • Icons and notes aren't imported.
  • Pasted text is limited to the eight import fields per sync, and a waiting import to 32 KB.
  • PIN
  • The PIN is fixed at 4 digits. It stops someone using your watch, but someone who copies the watch's storage to a computer can try all 10,000 PINs in seconds.
  • Storage
  • At most 150 entries and about 100 KB in total.
  • At most 16 phone changes can wait for the PIN at once.
  • The About catalog shows up to 800 characters; the rest are under Entry IDs on the watch.
  • Security
  • Locked entries are only as strong as the PIN against someone who copies the watch's storage; unlocked entries rely on the watch keeping its storage private.
  • Secrets and the import text pass through Garmin Connect's settings on your phone.
  • See SECURITY.md and PROJECT_PLAN section 8.
  • Barcodes
  • Data Matrix uses ASCII and Base256 encoding only (no C40, Text, X12 or EDIFACT), and Aztec a simple mode choice. Their symbols are valid, but sometimes larger than another encoder's.
  • PDF417 only fits short contents on small round screens (about 170 codewords on a 218-pixel screen).
  • Large 2D codes take a while to encode the first time: seconds for typical cards, up to about a minute for the largest QR codes on the Forerunner 255 and 255S. After that they open from the cache.
  • Glance: only the first favourite TOTP or Steam entry without the PIN.
  • No backup or export from the watch, by design.