- 密码学教程
- 密码学 - 首页
- 密码学 - 起源
- 密码学 - 历史
- 密码学 - 原理
- 密码学 - 应用
- 密码学 - 优点与缺点
- 密码学 - 现代
- 密码学 - 传统密码
- 密码学 - 加密的需求
- 密码学 - 双重强度加密
- 密码系统
- 密码系统
- 密码系统 - 组成部分
- 密码系统的攻击
- 密码系统 - 彩虹表攻击
- 密码系统 - 字典攻击
- 密码系统 - 暴力破解攻击
- 密码系统 - 密码分析技术
- 密码学的类型
- 密码系统 - 类型
- 公钥加密
- 现代对称密钥加密
- 密码学哈希函数
- 密钥管理
- 密码系统 - 密钥生成
- 密码系统 - 密钥存储
- 密码系统 - 密钥分发
- 密码系统 - 密钥吊销
- 分组密码
- 密码系统 - 流密码
- 密码学 - 分组密码
- 密码学 - Feistel 分组密码
- 分组密码的工作模式
- 分组密码的工作模式
- 电子密码本 (ECB) 模式
- 密码分组链接 (CBC) 模式
- 密码反馈 (CFB) 模式
- 输出反馈 (OFB) 模式
- 计数器 (CTR) 模式
- 经典密码
- 密码学 - 反向密码
- 密码学 - 凯撒密码
- 密码学 - ROT13 算法
- 密码学 - 换位密码
- 密码学 - 加密换位密码
- 密码学 - 解密换位密码
- 密码学 - 乘法密码
- 密码学 - 仿射密码
- 密码学 - 简单替换密码
- 密码学 - 简单替换密码的加密
- 密码学 - 简单替换密码的解密
- 密码学 - 维吉尼亚密码
- 密码学 - 维吉尼亚密码的实现
- 现代密码
- Base64 编码与解码
- 密码学 - XOR 加密
- 替换技术
- 密码学 - 单字母替换密码
- 密码学 - 单字母替换密码的破解
- 密码学 - 多字母替换密码
- 密码学 - Playfair 密码
- 密码学 - 希尔密码
- 多字母替换密码
- 密码学 - 一次性密码本密码
- 一次性密码本密码的实现
- 密码学 - 换位技术
- 密码学 - 栅栏密码
- 密码学 - 列置换密码
- 密码学 - 隐写术
- 对称算法
- 密码学 - 数据加密
- 密码学 - 加密算法
- 密码学 - 数据加密标准
- 密码学 - 三重 DES
- 密码学 - 双重 DES
- 高级加密标准
- 密码学 - AES 结构
- 密码学 - AES 变换函数
- 密码学 - 字节替换变换
- 密码学 - 行移位变换
- 密码学 - 列混淆变换
- 密码学 - 轮密钥加变换
- 密码学 - AES 密钥扩展算法
- 密码学 - Blowfish 算法
- 密码学 - SHA 算法
- 密码学 - RC4 算法
- 密码学 - Camellia 加密算法
- 密码学 - ChaCha20 加密算法
- 密码学 - CAST5 加密算法
- 密码学 - SEED 加密算法
- 密码学 - SM4 加密算法
- IDEA - 国际数据加密算法
- 公钥(非对称)密码学算法
- 密码学 - RSA 算法
- 密码学 - RSA 加密
- 密码学 - RSA 解密
- 密码学 - 创建 RSA 密钥
- 密码学 - 破解 RSA 密码
- 密码学 - ECDSA 算法
- 密码学 - DSA 算法
- 密码学 - Diffie-Hellman 算法
- 密码学中的数据完整性
- 密码学中的数据完整性
- 消息认证
- 密码学数字签名
- 公钥基础设施
- 哈希
- MD5(消息摘要算法 5)
- SHA-1(安全哈希算法 1)
- SHA-256(安全哈希算法 256 位)
- SHA-512(安全哈希算法 512 位)
- SHA-3(安全哈希算法 3)
- 哈希密码
- Bcrypt 哈希模块
- 现代密码学
- 量子密码学
- 后量子密码学
- 密码学协议
- 密码学 - SSL/TLS 协议
- 密码学 - SSH 协议
- 密码学 - IPsec 协议
- 密码学 - PGP 协议
- 图像和文件加密
- 密码学 - 图像
- 密码学 - 文件
- 隐写术 - 图像
- 文件加密和解密
- 密码学 - 文件的加密
- 密码学 - 文件的解密
- 物联网中的密码学
- 物联网安全挑战、威胁和攻击
- 物联网安全的加密技术
- 物联网设备的通信协议
- 常用的加密技术
- 自定义构建加密算法(混合加密)
- 云密码学
- 量子密码学
- 密码学中的图像隐写术
- DNA 密码学
- 密码学中的一次性密码 (OTP) 算法
- 区别
- 密码学 - MD5 与 SHA1
- 密码学 - RSA 与 DSA
- 密码学 - RSA 与 Diffie-Hellman
- 密码学与密码学
- 密码学 - 密码学与密码分析
- 密码学 - 经典与量子
- 密码学与隐写术
- 密码学与加密
- 密码学与网络安全
- 密码学 - 流密码与分组密码
- 密码学 - AES 与 DES 密码
- 密码学 - 对称与非对称
- 密码学有用资源
- 密码学 - 快速指南
- 密码学 - 讨论
密码学中的一次性密码 (OTP) 算法
由于网络安全威胁数量的增加,增强在线应用程序的安全性变得至关重要。您必须确保用户帐户的安全。
如今,许多在线 Web 应用程序需要用户为其帐户添加额外的安全层。他们通过启用双因素身份验证来满足此需求。实现双因素身份验证有多种选择,其中之一是 TOTP(基于时间的一次性密码)。
在本章中,我们将了解它是什么以及如何以及为什么要使用它。但首先,让我们定义双因素身份验证。
双因素身份验证
因此,我们可以说双因素身份验证,通常称为多因素身份验证,为用户帐户提供了额外的安全层。这意味着在启用双因素身份验证后,用户仍需要完成一个步骤才能成功登录。例如,以下是访问没有一次性密码和有的一次性密码的帐户的标准程序 -
因此,登录过程需要额外的步骤。因为黑客在不知道常规密码和一次性密码的情况下无法访问用户帐户,所以我们可以说这种技术更安全。
现在有两种流行的方法来获取一次性密码 -
- 基于短信的 - 使用此方法,每次用户登录时,都会向用户的注册电话号码发送包含一次性密码的短信。
- 基于 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 错误,则显示“访问被拒绝”。
使用 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!"); } } }