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.
This commit is contained in:
84
README.md
84
README.md
@@ -1,27 +1,87 @@
|
|||||||
# otp-import
|
# otp-import
|
||||||
|
|
||||||
Move TOTP credentials from saved authenticator **QR-code screenshots** onto a
|
Bulk-load your saved authenticator **QR-code screenshots** onto a **VivoKey
|
||||||
**VivoKey Apex** OTP applet (the ykneo-oath applet), by way of a plain,
|
Apex** OTP applet (the ykneo-oath applet) — or onto several implants at once — by
|
||||||
human-editable **CSV**.
|
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).
|
- `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.
|
- `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-<relying-party>-<account>`:
|
||||||
|
|
||||||
|
```
|
||||||
|
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
|
## The pipeline
|
||||||
|
|
||||||
```
|
```
|
||||||
QR screenshots otp-keys.csv Apex OTP applet
|
QR screenshots (*.png / *.jpg, each holding an otpauth:// URI)
|
||||||
┌───────────────┐ ┌──────────────┐ ┌───────────────┐
|
|
|
||||||
│ *.png / *.jpg │──(1)──▶ │ issuer │──(3)───────▶ │ TOTP creds │
|
| (1) qr_to_sheet.py
|
||||||
│ otpauth://... │ │ account │ PUT/auth │ (ykneo-oath) │
|
| decode each QR; append only NEW otpauth:// data to the CSV
|
||||||
└───────────────┘ │ otpauth_uri │ └───────────────┘
|
v
|
||||||
│ source_file │
|
otp-keys.csv columns: issuer | account | otpauth_uri | source_file
|
||||||
(2) edit labels here
|
|
|
||||||
└──────────────┘
|
| (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
|
1. **QR → CSV** (`qr_to_sheet.py`): decode each screenshot and append any
|
||||||
|
|||||||
Reference in New Issue
Block a user