{ OTP }

  • 淺談TOTP(Time-based One-time Password)

    | /

    TOTP 是利用 Application and services 上時間是一致,拿二邊共同的 key ,並且作一樣的 Hash 後,結果會產生一樣的 token,即可拿來作驗證,常被使用來作二次驗證(two-step verification)。 因為這部份的演算法是 RFC6238,所以可使用任何的 apps 來協助驗證,例如:Google Authenticator, Duo 之類的。

    怎麼實作的

    PHP 有人作好了: otphp 跟據 wikipedia 裡的 Implementation 章節中,有一段描述如何產生 token:

    1. Calculate C as the number of times TI has elapsed after T0.
    2. Compute the HMAC hash H with C as the message and K as the key (the HMAC algorithm is defined in the previous section, but also most cryptographical libraries support it). K should be passed as it is, C should be passed as a raw 64-bit unsigned integer.
    3. Take the least 4 significant bits of H and use it as an offset, O.
    4. Take 4 bytes from H starting at O bytes MSB, discard the most significant bit and store the rest as an (unsigned) 32-bit integer, I.
    5. The token is the lowest N digits of I in base 10. If the result has fewer digits than N, pad it with zeroes from the left.

    如果覺得太復雜,我挖了一下 otphp,應該在 otphp/src/OTP.php 裡面的 protected function generateOTP($input) 中有實作。

    使用

    安裝 composer require spomky-labs/otphp sample code: [php title=”Sample code”] <?php require __DIR__ . ‘/vendor/autoload.php’; use OTPHP\TOTP; $totp = new TOTP( “whatup.tw@gmail.com“ // The label (string) ); $google_chart = $totp->getQrCodeUri(); $otpCode = $totp->now(); echo “
    “; echo “Current OTP: “ . $totp->now() . “
    \n”; echo “Current Secret: “ . $totp->getSecret() . “
    \n”; echo “Verify OTP: “ . $totp->verify($otpCode) . “
    \n”; ?> [/php] 到 browser 執行後會產生下面畫面: totp example result 接下來你就拿出你的 Google Authenticator 來掃這個條碼,就可以新增一組新驗證碼。 Google Authenticator 預設是 30s ,所以 30s 後,這個 OTP 產生出來的 token 應該會無法使用。如果你的 application 可以看到 secret 的話,應該會看到 app & service 的 secret 應該要一樣。 剩下的可以參考 document 說的很清楚。

    限制

    • 其實無法防止 phishing 網頁用假的頁面來騙你資料,在你輸入 token 後,壞人在 30s 之內也可以同時登入。
    • secret key 如果被人拿走,別人也同時擁有通過二次驗證的能力。
    • app & services 之間的時間一定不能差太多,所以手機不能調整時間(有人喜歡看時鐘快五分鐘)。