# TOTP Generator

> 線上 TOTP 產生器：貼上 base32 secret 或 otpauth:// URI 就拿到 2FA 驗證碼。RFC 6238 實作全在瀏覽器裡跑，secret 不上傳，可選通行碼 AES-GCM 加密保存。

- URL: https://bytescope.dev/zh-Hant/totp-generator/
- Locale: zh-Hant · Also: [en](https://bytescope.dev/en/totp-generator.md) · [ja](https://bytescope.dev/ja/totp-generator.md)
- Runs: 全部在你的瀏覽器裡跑，什麼都不會上傳。
- Requires: Any modern browser (Chrome, Edge, Firefox, Safari), desktop and mobile.
- Updated: 2026-09-08

## What it does

TOTP 沒有魔法：拿共享的 secret 和目前時間做 HMAC，截短成六位數字，就這樣——RFC 6238 疊在 RFC 4226 的 HOTP 上的標準做法。幫你註冊的伺服器和產生驗證碼的那一端握著同一份 base32 secret，對同一個 30 秒的時間格做同一套運算，所以完全離線也對得上；也因此，裝置時鐘不準是驗證碼對不上的頭號原因。這頁做的就是這套運算，沒有別的，而且直接拿 RFC 附錄公佈的官方測試向量驗過。

先把話講白：TOTP secret 不是密碼。密碼洩漏了可以換，secret 是之後每一組驗證碼的種子，拿到它的人從今以後都能算出有效的驗證碼——把它貼進一個會上傳的網站，等於直接把第二道防線交出去。這頁是靜態檔案，背後沒有伺服器：驗證碼由你分頁裡的 JavaScript 算出來，secret 不會出現在任何網路請求裡，你自己開 devtools 就能驗證。這是讓人安心的那一半。另一半也得講：secret 存在瀏覽器的 localStorage，就是比鎖著的手機上的專用驗證器 App 弱。沒加密的項目，任何碰得到這個瀏覽器設定檔的東西都讀得到——權限開太大的擴充功能、機器上的惡意程式、路過你沒鎖電腦的人。通行碼加密選項就是為了這個風險存在的，也是它值得開的原因。

設了通行碼之後，項目會先用 AES-GCM 加密才寫進 localStorage，金鑰由你的通行碼經 PBKDF2 推導出來——用的是瀏覽器內建的 WebCrypto，不摻第三方加密程式碼。留在磁碟上的是密文，沒有通行碼就是一堆沒意義的 byte，而通行碼本身不會被存在任何地方。反過來說就是這個設計的重點：通行碼忘了，項目就是沒了。沒有救援、沒有重設信、沒有後門——留給你的後門，同時也是留給別人的後門。這是設計，不是 bug。實際損失也不大：拿備用碼登入該服務，重新註冊一次 2FA，就會拿到一份新的 secret。

新增帳號有三條路：直接貼 base32 secret、貼完整的 otpauth:// URI，或掃註冊用的 QR code——QR 不過就是那條 URI 畫成圖，一樣在本機解碼。多個帳號並排各自顯示驗證碼，點一下複製，倒數圓環告訴你這個 30 秒週期走到哪裡。一個值得養成的習慣：圓環快空的時候，多等一兩秒拿下一組，別跟到期賽跑——多數伺服器會容忍前後各一格，但在換碼瞬間送出的驗證碼，正是輸掉這場賽跑的經典方式。位數和演算法都可以調——6 或 8 位、SHA-1、SHA-256、SHA-512——留給少數不走預設值的服務。

## Limits

Does not store secrets across visits or replace an authenticator app; it computes codes from a secret you paste.

## FAQ

### 我的 secret 會被上傳嗎？

不會，而且這句話不用信我的，自己查。開瀏覽器的 devtools 切到 Network 分頁，新增一個帳號：沒有任何請求帶著 secret 出去；頁面載入完之後把網路整個關掉，驗證碼照樣算得出來。這頁是靜態檔案，背後沒有 API，想上傳也沒有地方可以收。這件事在這頁比在其他工具上都嚴重，因為 secret 洩漏一次就是永久淪陷——它不像密碼可以換掉，只能整個帳號重新註冊 2FA。

### 為什麼算出來的驗證碼是錯的、伺服器不收？

九成是時鐘。TOTP 把 Unix 時間切成 30 秒一格，兩邊要落在同一格才對得上，所以裝置時鐘慢一分鐘，算出來的驗證碼都『有效』——只是有效在錯的時間點。多數伺服器照 RFC 6238 的建議容忍前後各一格，大約 ±30 秒的誤差，所以半分鐘以內的漂移通常沒感覺，再大就開始被拒。解法是把系統時鐘修好——開網路自動對時——而不是懷疑 secret 抄錯。剩下一成再檢查：secret 抄寫時打錯字（base32 字母表裡沒有 `0`、`1`、`8`、`9`），或那個服務其實用 8 位數或 SHA-256，而你的項目還停在預設值。

### 演算法和位數設定是做什麼的？SHA-1 不是有問題嗎？

RFC 6238 定義的 TOTP 預設就是 HMAC-SHA-1、六位數、30 秒一格，市面上幾乎所有服務都用這一套。SHA-1 被攻破的是碰撞攻擊，這打不到 HMAC-SHA-1——要在不知道 secret 的情況下算出驗證碼，得先打穿 HMAC 本身，到今天沒人做到。所以這裡的 SHA-1 不是憑證簽章裡那種等級的問題。設定存在的理由是少數服務用 SHA-256、SHA-512 或發 8 位數的驗證碼；如果服務有講（或它的 otpauth:// URI 帶著 `algorithm=`、`digits=` 參數），項目就得跟著設，因為演算法對不上不是偶爾錯，是每一組都錯。

### 這可以取代驗證器 App 嗎？

不行，它也沒打算取代。這是個順手工具兼除錯工具：坐在電腦前查個驗證碼很方便、部署前驗證一份 secret 算出來的驗證碼跟伺服器期待的一不一致、或拆開一條 otpauth:// URI 看裡面裝什麼，都很好用。但手機上的專用驗證器把 secret 放在硬體層級的安全儲存裡、鎖在裝置的螢幕鎖後面，清瀏覽器資料不會消失，瀏覽器擴充功能也摸不到。放在 localStorage 的 secret——就算加了密——拿不到這些保護。主力 2FA 請放在真正的驗證器裡、做好備份，這頁拿來做瀏覽器工具擅長的事就好。

### 通行碼忘了，項目救得回來嗎？

救不回來，而且這是設計不是疏失：項目是 AES-GCM 密文，金鑰從你的通行碼經 PBKDF2 推導出來，沒有通行碼，這台機器上不存在任何能解開它的東西——沒有救援流程、沒有重設。如果存在救援，那就是一條別人也能走的路。實際處理很快：用手上還能用的驗證器或備用碼登入各服務，重新註冊 2FA 拿一份新 secret。這也是備用碼存在的意義——把它們放在不是這個瀏覽器的地方。

### 我掃的 QR code 會被送出去嗎？

不會。註冊用的 QR code 拆開來就是一條 otpauth:// URI——帳號名稱、發行方、base32 secret，包成一個 URL 而已。鏡頭畫面由你分頁裡的 JavaScript 解碼，URI 也在同一個地方解析，影像和內容都不會出現在網路請求裡——上面那招 devtools 檢查在這裡一樣適用。但 QR 本身要用對待 secret 的態度對待：註冊 QR 的截圖就是 secret 本人，只要該帳號沒重新註冊，它就一直有效。

## Related tools

- [Password Generator](https://bytescope.dev/zh-Hant/password-generator.md) — 除了兩步驟驗證，還缺一組夠強的密碼？在這裡產生。
- [Certificate Decoder](https://bytescope.dev/zh-Hant/certificate-decoder.md) — 要看的是另一種憑證？把 X.509 憑證拆開來讀。
- [File Hash](https://bytescope.dev/zh-Hant/file-hash.md) — 要確認的是檔案有沒有被改過、而不是身分？改算雜湊就好。
