使用 Go 構建基於時間的一次性密碼 -TOTP- 生成器


前言

現在很多網站都開啓了 2FA(Two-Factor Authentication,雙因素認證),如 GitHub、Google、微軟等。這種額外的安全層顯著提高了賬戶的安全性。本文將深入探討如何使用 Go 語言實現 TOTP 生成器,並詳細解釋其工作原理和安全考慮

原理解析

兩步驗證要求用戶提供兩種不同形式的身份驗證:

  1. 知識因素:用戶知道的信息(如密碼)

  2. 所有權因素:用戶擁有的設備(如手機)

  3. 生物特徵因素:用戶的生物特徵(如指紋)

使用 2FA 可以大大增加賬戶的安全性,因爲即使攻擊者獲取了用戶的密碼,沒有第二個驗證因素,他們也無法訪問賬戶.

如上圖所示的這種

  1. TOTP 技術原理

基於時間的一次性密碼(Time-based One-Time Password,TOTP)是 HOTP(基於事件的一次性密碼)的一種變種,它引入了時間作爲動態因素。 TOTP 算法使用一個祕密密鑰和當前時間來生成一次性密碼。這個密碼每 30 秒(或者配置的其他時間段)就會變化,因此即便泄露,效用也很短暫。

TOTP 遵循 RFC 6238 標準,並且通常用於實現 2FA。每個 TOTP 都是通過以下步驟生成的:

  1. TOTP 工作流程詳解

實現 TOTP 生成器

基礎設置

Go 語言中可以使用 github.com/pquerna/otp 庫來實現 TOTP

package main

import (
    "github.com/pquerna/otp/totp"
    "github.com/skip2/go-qrcode"
)

核心功能實現

package main

import (
 "fmt"
 "log"
 "time"

 "github.com/pquerna/otp/totp"
)

func main() {
 // 生成共享密鑰
 key, err := totp.Generate(totp.GenerateOpts{
  Issuer:      "Github",
  AccountName: "pfinal@pfinalclub.top",
 })
 if err != nil {
  log.Fatalf("Failed to generate TOTP key: %v", err)
 }

 fmt.Println("Generated TOTP Key URI:")
 fmt.Println(key.URL())

 // 獲取當前時間戳生成的 TOTP
 code, err := totp.GenerateCode(key.Secret(), time.Now())
 if err != nil {
  log.Fatalf("Failed to generate TOTP code: %v", err)
 }

 fmt.Printf("Generated TOTP Code: %s\n", code)

 // 驗證 TOTP
 isValid := totp.Validate(code, key.Secret())
 if isValid {
  fmt.Println("TOTP Code is valid!")
 } else {
  fmt.Println("Invalid TOTP Code.")
 }
}

代碼詳解:

  1. 生成密鑰 totp.Generate 方法生成一個共享密鑰,可以通過二維碼或文本形式分發給用戶。

  2. 生成動態密碼 使用 totp.GenerateCode 方法,將共享密鑰和當前時間戳結合,生成 6 位動態密碼。

  3. 驗證密碼 totp.Validate 方法通過對比用戶輸入的動態密碼和服務端生成的密碼進行驗證。

import (
    "os"
    "github.com/pquerna/otp/totp"
    "github.com/skip2/go-qrcode"
)

func generateQRCode(key *totp.Key) {
    qrCode, _ := qrcode.New(key.URL(), qrcode.Medium)
    qrCode.WriteFile(256, "qrcode.png")
    fmt.Println("QR Code generated: qrcode.png")
}
isValid := totp.ValidateCustom(code, key.Secret(), time.Now(), totp.ValidateOpts{
    Skew: 1, // 寬容時間窗口
})

安全性考慮

在實現和部署兩步驗證(2FA)系統時,有多個方面需要考慮以確保系統的安全性和用戶體驗。以下是需要注意的一些關鍵點

  1. 密鑰安全:密鑰應該是隨機生成的,並且在傳輸和存儲過程中保持安全。密鑰泄露可能導致 TOTP 碼被惡意使用。

  2. 時間同步:服務器和客戶端的時間應該保持同步,以確保生成的 TOTP 碼的正確性。時間差異可能導致驗證失敗。

  3. 重放攻擊:攻擊者可能嘗試重放已經使用過的 TOTP 碼,以繞過驗證。爲了防止重放攻擊,可以使用一次性密碼或者時間戳來確保每個 TOTP 碼只能使用一次。

  4. 密碼長度:TOTP 碼的長度應該足夠長,以防止暴力破解。建議使用至少 6 位數的 TOTP 碼。

  5. 密碼有效期:TOTP 碼應該有一個有效期限,以防止攻擊者在有效期內多次嘗試。建議使用短期的有效期限,如 30 秒。

  6. 密碼存儲:TOTP 碼不應該以明文形式存儲,以防止數據泄露。可以使用加密算法對 TOTP 碼進行加密存儲。

  7. 密鑰更新:密鑰應該定期更新

總結

使用 Go 語言構建 TOTP 生成器不僅能夠提供強大的安全保護,還能確保良好的用戶體驗。通過遵循安全最佳實踐並實現適當的錯誤處理,我們可以創建一個可靠的雙因素認證解決方案。

記住,安全性是一個持續的過程,定期更新和維護你的實現以應對新的安全挑戰是很重要的。通過適當的規劃和實現,TOTP 可以顯著提高你的應用程序的安全性。

參考資源

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/SuyUHi08BdnchaC8KQ0F3Q?poc_token=HFpZd2ejoHgH-xpL6trR7MtrRp7a5bgVyY16U2Gg