ToB企服应用市场:ToB评测及商务社交产业平台

标题: java和c#里的TOTP统一算法 [打印本页]

作者: tsx81429    时间: 2023-11-2 17:29
标题: java和c#里的TOTP统一算法
基础说明

本文根据 RFC4226 和 RFC6238 文档,详细的介绍 HOTP 和 TOTP 算法的原理和实现。
两步验证已经被广泛应用于各种互联网应用当中,用来提供安全性。对于如何使用两步验证,大家并不陌生,无非是开启两步验证,然后出现一个二维码,使用支持两步验证的移动应用比如 Google Authenticator 或者 LassPass Authenticator 扫一下二维码。这时候应用会出现一个6位数的一次性密码,首次需要输入验证从而完成开启过程。以后在登陆的时候,除了输入用户名和密码外,还需要把当前的移动应用上显示的6位数编码输入才能完成登陆。
这个过程的背后主要由两个算法来支撑:HOTP 和 TOTP。也分别对应着两份 RFC 协议 RFC4266 和 RFC6238。前者是 HOTP 的标准,后者是 TOTP 的标准。本文将使用图文并茂的方式详细介绍 HOTP 和 TOTP 的算法原理,并在最后分析其安全性。当然所有内容都是基于协议的,通过自己的理解更加直观的表达出来。
为了确保在不同语言下生成相同的 TOTP 结果,你需要确保使用相同的密钥和相同的时间戳步长。同时,你还需要确保使用相同的哈希算法(通常是 HMAC-SHA1 或 HMAC-SHA256)。
参数解释

HMAC-SHA1

HMAC-SHA1(Hash-based Message Authentication Code with SHA-1)是一种基于哈希函数的消息认证码算法,用于保护数据完整性和身份验证。它结合了两个主要的技术:哈希函数(SHA-1)和密钥(Key)。
下面是 HMAC-SHA1 算法的工作原理和说明:
HMAC-SHA1 的主要目的是确保数据的完整性和身份验证。由于它需要密钥,因此只有知道密钥的实体才能生成正确的 HMAC 值。这使得 HMAC-SHA1 在加密通信和身份验证中非常有用,例如在数字签名、认证协议(如OAuth)、以及一次性密码算法(如TOTP和HOTP)中广泛使用。
需要注意的是,SHA-1 已经不再被视为安全的哈希算法,因为它存在碰撞漏洞。因此,安全敏感的应用程序应该使用更强大的哈希算法,如SHA-256或SHA-3,来代替 SHA-1。如果可能,也应该使用更安全的 HMAC 变种,如HMAC-SHA-256。
核心代码

以下是一个 Java 和 C# 中可以生成相同 TOTP 结果的示例代码,使用的是 HMAC-SHA1 哈希算法和 Joda-Time 库来处理时间:
Java 示例:
[code]import javax.crypto.Mac;import javax.crypto.spec.SecretKeySpec;import org.apache.commons.codec.binary.Base32;import org.joda.time.DateTime;import org.joda.time.DateTimeZone;public class TOTPGenerator {    public static String generateTOTP(String base32Key, int timeStep, int digits) throws Exception {        long counter = (System.currentTimeMillis() / 1000) / timeStep;        byte[] key = new Base32().decode(base32Key);                SecretKeySpec secretKey = new SecretKeySpec(key, "HmacSHA1");        Mac mac = Mac.getInstance("HmacSHA1");        mac.init(secretKey);                byte[] counterBytes = new byte[8];        for (int i = 0; i < 8; i++) {            counterBytes[7 - i] = (byte) (counter >> (8 * i));        }                byte[] hash = mac.doFinal(counterBytes);        int offset = hash[hash.length - 1] & 0x0F;        int binary = ((hash[offset] & 0x7F)




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4