密碼學中的一次性密碼 (OTP) 演算法



由於網路安全威脅數量的增加,增強線上應用程式的安全性變得至關重要。您必須確保使用者帳戶的安全。

如今,許多線上 Web 應用程式需要使用者為其帳戶新增額外的安全層。他們透過啟用雙因素身份驗證來滿足此需求。實現雙因素身份驗證有多種選擇,其中之一是 TOTP(基於時間的一次性密碼)。

在本章中,我們將瞭解它是什麼以及如何以及為什麼要使用它。但首先,讓我們定義雙因素身份驗證。

雙因素身份驗證

因此,我們可以說雙因素身份驗證,通常稱為多因素身份驗證,為使用者帳戶提供了額外的安全層。這意味著在啟用雙因素身份驗證後,使用者仍需要完成一個步驟才能成功登入。例如,以下是訪問沒有一次性密碼和有的一次性密碼的帳戶的標準程式 -

OTP Process

因此,登入過程需要額外的步驟。因為駭客在不知道常規密碼和一次性密碼的情況下無法訪問使用者帳戶,所以我們可以說這種技術更安全。

現在有兩種流行的方法來獲取一次性密碼 -

  • 基於簡訊的 - 使用此方法,每次使用者登入時,都會向用戶的註冊電話號碼傳送包含一次性密碼的簡訊。
  • 基於 TOTP 的 - 此方法需要使用者使用特定的智慧手機應用程式掃描 QR 影像以開啟雙因素身份驗證。然後,該程式會持續生成使用者的一次性密碼。

基於簡訊的方法無需解釋。雖然它很簡單,但也有一些缺點,例如每次您想要登入時都必須等待簡訊以及安全問題。基於 TOTP 的方法相對於基於簡訊的方法的優勢使其越來越受歡迎。現在我們將分析基於 TOTP 的方法的操作。

TOTP(基於時間的一次性密碼)如何工作?

基於時間的一次性密碼 (TOTP) 方法透過生成在一定秒數間隔內(通常為 30 秒或更少)過期的臨時密碼來工作。它透過允許使用者輸入靜態密碼(他們知道的內容)和裝置生成的臨時密碼來提高身份驗證安全性。基本上,基於 TOTP 的方法的工作原理如下 -

  • 初始化: - 使用者和服務提供商(網站或應用程式)在初始步驟中選擇一個共享金鑰。伺服器和使用者的裝置都維護此金鑰的安全性。
  • 基於時間生成
    • 要建立 TOTP,當前時間用作唯一性的來源。
    • TOTP 技術使用共享金鑰和當前時間建立一個一次性密碼。
    • 為了確保使用者裝置和伺服器之間的同步,時間通常被劃分為預定義的間隔,例如 30 秒或 1 分鐘的增量。
  • 密碼顯示
    • 生成的 TOTP 使用可信賴的裝置(智慧手機應用程式或硬體令牌)傳送給使用者。
    • 使用者在身份驗證過程中輸入 TOTP 和其靜態密碼。
  • 驗證
    • 服務提供商獨立生成 TOTP,並使用已儲存的共享金鑰將其與使用者提供的 TOTP 進行驗證。
    • 如果靜態密碼和兩個 TOTP 值都匹配,則使用者獲得訪問許可權。
    • TOTP 最多有 30 秒的有效期,之後它會過期並需要重新整理。
  • 持續身份驗證
    • 每次嘗試登入時,都會為每個身份驗證會話提供一個新的 TOTP。
    • 由於 TOTP 是基於時間的並且即使攻擊者攔截了先前的身份驗證嘗試,它也會頻繁更改,因此它對將來的嘗試沒有任何影響。
  • 安全措施
    • 透過向身份驗證過程新增第二個因素(使用者擁有的東西),TOTP 透過使其不易受到各種威脅(如重放攻擊和網路釣魚嘗試)的影響來提高安全性。
    • 由於 TOTP 的生命週期很短,因此攻擊者攔截和操縱它們的機會視窗較小。
    • 共享金鑰允許使用者生成有效的 TOTP,但前提是他們擁有相關裝置並知道靜態密碼。

TOTP 的安全性

與密碼不同,由於 TOTP 程式碼是一次性的,因此被洩露的憑據具有有限的生存期。當用戶需要將其 TOTP 程式碼輸入身份驗證頁面時,網路釣魚嘗試的可能性更大。由於 TOTP 程式碼具有有限的有效時間,因此攻擊者必須快速代理憑據。

TOTP 憑據基於客戶端和伺服器都瞭解的共享金鑰,這提供了更多可以檢索金鑰的位置。如果攻擊者知道此共享金鑰,他們將能夠生成新的有效 TOTP 程式碼。如果攻擊者能夠訪問大型身份驗證資料庫,這將變得尤其危險。

OTP 演算法的實現

現在,我們將藉助 Python、Java 等不同的程式語言來實現一次性密碼演算法。因此,讓我們檢視以下程式以更好地理解此演算法。

使用 Python 的 OTP

在本節中,我們將使用 Python 的 `secrets` 模組來實現 OTP。該模組提供了一些函式,用於生成密碼學意義上的強隨機數,適用於管理密碼、帳戶身份驗證和安全令牌等資料。它也是 Python 標準庫的一部分,在 Python 3.6 中引入。

這段程式碼展示了一個基本的 OTP 身份驗證過程,包括 OTP 生成和驗證。透過使用 Python 的 `secrets` 模組,我們將確保生成安全且不可預測的 OTP,以增強身份驗證系統的安全性。

因此,使用 `secrets` 模組實現 OTP 的 Python 程式碼如下所示:

import secrets

# Function to generate a random secret key
def generate_random_key():
   return secrets.token_hex(16)  # 16 bytes (32 hex characters)

# Function to generate a One Time Password (OTP) using the secret key
def generate_otp(secret_key, length=6):
   # Define the characters allowed in the OTP
   allowed_characters = "0123456789"

   # Generate a random OTP using the secret key and allowed characters
   otp = ''.join(secrets.choice(allowed_characters) for _ in range(length))

   return otp

# Generate a random secret key (this should be kept secure)
secret_key = generate_random_key()

# Simulate sending the OTP to the user
otp = generate_otp(secret_key)
print("Generated OTP:", otp)

# Simulate user input for OTP verification
user_input = input("Please enter the received OTP: ")

# Verify the OTP entered by the user
if user_input == otp:
   print("OTP verification successful. Access granted!")
else:
   print("OTP verification failed. Access denied!")

輸出

執行上述程式後,我們將得到以下輸出。輸入正確的 OTP 程式碼將顯示訊息“訪問已授權!”,如果 OTP 錯誤,則顯示“訪問被拒絕”。

OTP using Python

使用 Java 實現 OTP

在此 Java 程式碼中,我們將使用 `java.security.SecureRandom` 類,它是 Java 標準庫的一部分,並提供了一個密碼學意義上的強隨機數生成器 (RNG)。`SecureRandom` 類用於生成密碼學安全的隨機數。OTP 透過使用 `SecureRandom` 從允許的字元集中(0 到 9)隨機選擇字元來建立。生成的 OTP 將顯示給使用者。系統將提示使用者輸入收到的 OTP。輸入的 OTP 將與生成的 OTP 進行比較以驗證其正確性。如果輸入的 OTP 與生成的 OTP 匹配,則授予訪問許可權;否則,拒絕訪問。

因此,使用 Java 的實現如下所示:

import java.security.SecureRandom;

// Driver Class
public class OTPGenerator {
   // Function to generate a random secret key
   public static String generateSecretKey() {
      SecureRandom secureRandom = new SecureRandom();
      byte[] bytes = new byte[16];

      secureRandom.nextBytes(bytes);
      StringBuilder secretKey = new StringBuilder();

      for (byte b : bytes) {
         secretKey.append(String.format("%02x", b));
      }

      return secretKey.toString();
   }

   // Function to generate a One Time Password (OTP) using
   // the secret key
   public static String generateOTP(String secretKey, int length) {
      String allowedCharacters = "0123456789";
      StringBuilder otp = new StringBuilder();
      SecureRandom secureRandom = new SecureRandom();

      for (int i = 0; i < length; i++) {
         int randomIndex = secureRandom.nextInt(allowedCharacters.length());
         otp.append(allowedCharacters.charAt(randomIndex));
      }

      return otp.toString();
   }

   public static void main(String[] args) {
      // Generate a random secret key 
      // (this should be kept secure)
      String secretKey = generateSecretKey();

      // Generate the OTP
      int otpLength = 6;
      String otp = generateOTP(secretKey, otpLength);
      System.out.println("Generated OTP: " + otp);

      // Simulating user input for OTP verification
      java.util.Scanner scanner = new java.util.Scanner(System.in);
      System.out.print("Please enter the received OTP: ");
      String userInput = scanner.next();

      // Verify the OTP entered by the user
      if (userInput.equals(otp)) {
         System.out.println("OTP verification successful. Access granted!");
      } else {
         System.out.println("OTP verification failed. Access denied!");
      }
   }
}

輸出

OTP using Java
廣告

© . All rights reserved.