密码学中的一次性密码 (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
广告