From 08c77e112426f7686ff96a70e70c9efbad8c6980 Mon Sep 17 00:00:00 2001 From: Amal Graafstra Date: Wed, 8 Jul 2026 16:08:12 -0700 Subject: [PATCH] Fix pipeline diagram and document backup habits and dedup behavior Replace the misaligned box diagram with a clean vertical flow. Expand the intro to explain bulk-loading one or many authenticators and how duplicates are handled at each stage. Add a "Backing up your OTP keys" section covering screenshotting QR codes to secure storage with a filename convention, and saving one-time backup/recovery codes. --- README.md | 84 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 72 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 477f84e..4250f65 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,87 @@ # otp-import -Move TOTP credentials from saved authenticator **QR-code screenshots** onto a -**VivoKey Apex** OTP applet (the ykneo-oath applet), by way of a plain, -human-editable **CSV**. +Bulk-load your saved authenticator **QR-code screenshots** onto a **VivoKey +Apex** OTP applet (the ykneo-oath applet) — or onto several implants at once — by +way of a plain, human-editable **CSV**. -Two small command-line tools: +If you screenshot your two-factor QR codes as you enroll them (see +[Backing up your OTP keys](#backing-up-your-otp-keys) below), these two tools +turn that pile of screenshots into working TOTP credentials on a new or +replacement authenticator, and can load the identical set onto multiple devices. - `qr_to_sheet.py` — decode QR screenshots into the CSV (no hardware needed). - `apex_otp_import.py` — write the CSV's credentials onto the applet over PC/SC. +**Duplicates are handled at both stages, so you can re-run freely:** + +- **QR → CSV** deduplicates on the `otpauth://` data: re-scanning a folder only + appends codes that aren't already in the CSV; ones already present are silently + skipped. Two screenshots of the *same account with different secrets* (e.g. a + re-enrollment) are both kept — they are genuinely different credentials. +- **CSV → applet** keys credentials by name (`issuer:account`): if a name is + already on the applet you are asked to overwrite or skip it (or pass + `--overwrite-all` / `--skip-existing`). Loading the same CSV onto a second + implant just repeats the write. And before writing, the importer halts if two + rows would collide on the same name — so a re-enrollment with a new secret + can't silently clobber the old one; you relabel one of them first. + +## Backing up your OTP keys + +This utility is only useful if you saved your OTP keys in the first place. When +you turn on TOTP two-factor authentication somewhere, the site shows a QR code +(and usually a "can't scan it? enter this code instead" secret). That QR encodes +an `otpauth://` URI containing the shared secret — capture it **then**, because +you generally cannot retrieve it later without disabling and re-enrolling 2FA. + +A good habit, every time you enable 2FA: + +1. **Screenshot the QR code** and save the image to secure storage. The tools + read the `otpauth://` data inside the image, not the filename, so the naming + scheme is purely for your own organization — but a consistent one keeps the + folder browsable and sortable. A practical convention is + `YYYY-MM-DD--`: + + ``` + 2024-05-01-github-alice@example.com.png + 2025-11-02-aws-root@example.com.png + ``` + + Date first so the folder sorts chronologically, then the service (relying + party), then which account it is. + +2. **Save the one-time backup/recovery codes too.** Most sites offer a set of + single-use recovery codes next to the QR — copy them into a text file beside + the screenshot (e.g. `2024-05-01-github-alice@example.com-backup-codes.txt`). + If you ever lose every authenticator, those codes are how you get back in. + (This tool doesn't process them; they're your independent recovery path.) + +3. **Keep it all in secure storage.** These files contain live secrets — treat + them like passwords. Good homes: a password-manager vault, an encrypted + volume, or an end-to-end-encrypted cloud folder. Never commit them to a + repository (this repo's `.gitignore` deliberately excludes `*.png`, `*.csv`, + and backup-code text files). + +With that habit in place, provisioning a new, replacement, or spare Apex is just +pointing these tools at the folder. + --- ## The pipeline ``` - QR screenshots otp-keys.csv Apex OTP applet - ┌───────────────┐ ┌──────────────┐ ┌───────────────┐ - │ *.png / *.jpg │──(1)──▶ │ issuer │──(3)───────▶ │ TOTP creds │ - │ otpauth://... │ │ account │ PUT/auth │ (ykneo-oath) │ - └───────────────┘ │ otpauth_uri │ └───────────────┘ - │ source_file │ - (2) edit labels here - └──────────────┘ + QR screenshots (*.png / *.jpg, each holding an otpauth:// URI) + | + | (1) qr_to_sheet.py + | decode each QR; append only NEW otpauth:// data to the CSV + v + otp-keys.csv columns: issuer | account | otpauth_uri | source_file + | + | (2) optional: edit the issuer / account labels (never otpauth_uri) + | + | (3) apex_otp_import.py + | validate the CSV, authenticate if needed, PUT each credential + v + Apex OTP applet (ykneo-oath) one TOTP credential per row ``` 1. **QR → CSV** (`qr_to_sheet.py`): decode each screenshot and append any