关于Google身份验证器、基于时间的一次性密码 (TOTP)算法的初步了解

article/2025/10/6 13:40:25

一、Google Authenticator

1、概述

        Google Authenticator是基于双因素身份验证 ( 2FA ) 的应用程序,有助于识别用户身份并确认用户声称自己是谁以及他是否真的是这个人。

        当您启用两步验证(也称为双重身份验证)时,您会为您的帐户添加额外的安全层。您使用您知道的信息(您的密码)和您拥有的信息(发送到您手机的代码)登录。

        双重身份验证降低了入侵者伪装成授权用户的可能性。身份验证因素是用于验证某人或某物是否是他们所宣称的身份或身份的凭证类别。分为三类: 知识因素是用户知道的凭证,通常是用户名和密码;占有因素是用户拥有的东西,通常是手机;固有因素是用户的事物,通常是生物特征,例如指纹或虹膜图案。

        与基于 SMS 的验证相比,使用 2FA 的优势在于,您的移动 sim 卡可能会使用您的社会安全号码被盗到新手机上,或者由于安全漏洞,短信可能会通过您的网络提供商被拦截。2FA 消除了这种可能性,并且完全取决于在其上注册的设备,而与网络提供商无关。

2、2FA

        双重身份验证( 2FA ) 是一种为您的帐户增加额外安全性的方法。第一个“因素”是任何帐户的标准密码。第二个“因素”是从移动设备或计算机上的应用程序检索到的验证码。

        2FA 在概念上类似于某些国家/地区的银行在线银行所需的安全令牌设备。就是我们日常用到的银行的USB-KEY。 

        2FA 系统的其他名称包括OTP(一次性密码)和TOTP(基于时间的一次性密码算法)。

3、工作原理

        身份验证器适用于任何启用了双因素身份验证的站点或服务。与大多数基于 Web 的 2FA 应用程序一样,该系统结合了知识和拥有功能。要访问网站或基于 Web 的服务,用户需要输入其正常的用户名和密码,然后输入由登录触发的一次性密码 ( OTP ),该密码会发送到他的设备。该组合可验证在网站上输入登录数据的同一个人是否拥有下载 Google Authenticator 应用程序的设备。

        密码可能很容易被破解或以其他方式窃取,但由于绝大多数攻击都是通过 Internet 进行的,因此黑客不太可能也可以访问用户的物理设备。

        Authenticator 应用程序基于IETF 的RFC 6238 文档中指定的基于时间的一次性密码 ( TOTP ) 系统。TOTP算法生成一个六位数的密码,该密码将当前时间考虑在内,以确保每个密码都是唯一的。密码每 30-60 秒更改一次,以提高安全性。

二、什么是TOTP

1、概述

        英文是Time-Based One-Time Password Algorithm,HOTP 算法基于HMAC-SHA-1 算法。

        关于详细算法可以查看下面文档,可能需要科学上网。

RFC 6238: TOTP: Time-Based One-Time Password Algorithmhttps://www.rfc-editor.org/rfc/rfc6238

2、Java参考代码

 import java.lang.reflect.UndeclaredThrowableException;import java.security.GeneralSecurityException;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;import javax.crypto.Mac;import javax.crypto.spec.SecretKeySpec;import java.math.BigInteger;import java.util.TimeZone;/*** 这是 OATH TOTP 算法的示例实现。* Visit www.openauthentication.org for more information.*/public class TOTP {private TOTP() {}/*** 此方法使用 JCE 提供加密算法。 HMAC 使用加密散列算法作为参数计算散列消息验证码。** @param crypto: the crypto algorithm (HmacSHA1, HmacSHA256,*                             HmacSHA512)* @param keyBytes: the bytes to use for the HMAC key* @param text: the message or text to be authenticated*/private static byte[] hmac_sha(String crypto, byte[] keyBytes,byte[] text){try {Mac hmac;hmac = Mac.getInstance(crypto);SecretKeySpec macKey =new SecretKeySpec(keyBytes, "RAW");hmac.init(macKey);return hmac.doFinal(text);} catch (GeneralSecurityException gse) {throw new UndeclaredThrowableException(gse);}}/*** This method converts a HEX string to Byte[]** @param hex: the HEX string** @return: a byte array*/private static byte[] hexStr2Bytes(String hex){// Adding one byte to get the right conversion// Values starting with "0" can be convertedbyte[] bArray = new BigInteger("10" + hex,16).toByteArray();// Copy all the REAL bytes, not the "first"byte[] ret = new byte[bArray.length - 1];for (int i = 0; i < ret.length; i++)ret[i] = bArray[i+1];return ret;}private static final int[] DIGITS_POWER// 0 1  2   3    4     5      6       7        8= {1,10,100,1000,10000,100000,1000000,10000000,100000000 };/*** This method generates a TOTP value for the given* set of parameters.** @param key: the shared secret, HEX encoded* @param time: a value that reflects a time* @param returnDigits: number of digits to return** @return: a numeric String in base 10 that includes*              {@link truncationDigits} digits*/public static String generateTOTP(String key,String time,String returnDigits){return generateTOTP(key, time, returnDigits, "HmacSHA1");}/*** 此方法为给定的一组参数生成一个 TOTP 值。** @param key: the shared secret, HEX encoded* @param time: a value that reflects a time* @param returnDigits: number of digits to return** @return: a numeric String in base 10 that includes*              {@link truncationDigits} digits*/public static String generateTOTP256(String key,String time,String returnDigits){return generateTOTP(key, time, returnDigits, "HmacSHA256");}/*** This method generates a TOTP value for the given* set of parameters.** @param key: the shared secret, HEX encoded* @param time: a value that reflects a time* @param returnDigits: number of digits to return** @return: a numeric String in base 10 that includes*              {@link truncationDigits} digits*/public static String generateTOTP512(String key,String time,String returnDigits){return generateTOTP(key, time, returnDigits, "HmacSHA512");}/*** This method generates a TOTP value for the given* set of parameters.** @param key: the shared secret, HEX encoded* @param time: a value that reflects a time* @param returnDigits: number of digits to return* @param crypto: the crypto function to use** @return: a numeric String in base 10 that includes*              {@link truncationDigits} digits*/public static String generateTOTP(String key,String time,String returnDigits,String crypto){int codeDigits = Integer.decode(returnDigits).intValue();String result = null;// Using the counter// First 8 bytes are for the movingFactor// Compliant with base RFC 4226 (HOTP)while (time.length() < 16 )time = "0" + time;// Get the HEX in a Byte[]byte[] msg = hexStr2Bytes(time);byte[] k = hexStr2Bytes(key);byte[] hash = hmac_sha(crypto, k, msg);// put selected bytes into result intint offset = hash[hash.length - 1] & 0xf;int binary =((hash[offset] & 0x7f) << 24) |((hash[offset + 1] & 0xff) << 16) |((hash[offset + 2] & 0xff) << 8) |(hash[offset + 3] & 0xff);int otp = binary % DIGITS_POWER[codeDigits];result = Integer.toString(otp);while (result.length() < codeDigits) {result = "0" + result;}return result;}public static void main(String[] args) {// Seed for HMAC-SHA1 - 20 bytesString seed = "3132333435363738393031323334353637383930";// Seed for HMAC-SHA256 - 32 bytesString seed32 = "3132333435363738393031323334353637383930" +"313233343536373839303132";// Seed for HMAC-SHA512 - 64 bytesString seed64 = "3132333435363738393031323334353637383930" +"3132333435363738393031323334353637383930" +"3132333435363738393031323334353637383930" +"31323334";long T0 = 0;long X = 30;long testTime[] = {59L, 1111111109L, 1111111111L,1234567890L, 2000000000L, 20000000000L};String steps = "0";DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");df.setTimeZone(TimeZone.getTimeZone("UTC"));try {System.out.println("+---------------+-----------------------+" +"------------------+--------+--------+");System.out.println("|  Time(sec)    |   Time (UTC format)   " +"| Value of T(Hex)  |  TOTP  | Mode   |");System.out.println("+---------------+-----------------------+" +"------------------+--------+--------+");for (int i=0; i<testTime.length; i++) {long T = (testTime[i] - T0)/X;steps = Long.toHexString(T).toUpperCase();while (steps.length() < 16) steps = "0" + steps;String fmtTime = String.format("%1$-11s", testTime[i]);String utcTime = df.format(new Date(testTime[i]*1000));System.out.print("|  " + fmtTime + "  |  " + utcTime +"  | " + steps + " |");System.out.println(generateTOTP(seed, steps, "8","HmacSHA1") + "| SHA1   |");System.out.print("|  " + fmtTime + "  |  " + utcTime +"  | " + steps + " |");System.out.println(generateTOTP(seed32, steps, "8","HmacSHA256") + "| SHA256 |");System.out.print("|  " + fmtTime + "  |  " + utcTime +"  | " + steps + " |");System.out.println(generateTOTP(seed64, steps, "8","HmacSHA512") + "| SHA512 |");System.out.println("+---------------+-----------------------+" +"------------------+--------+--------+");}}catch (final Exception e){System.out.println("Error : " + e);}}}

3、 go实现参考

GitHub - tilaklodha/google-authenticatorContribute to tilaklodha/google-authenticator development by creating an account on GitHub.https://github.com/tilaklodha/google-authenticator

         下面的链接是评论区的小伙伴,说是正解,不过没时间看,这里记录一下,以供后面的人参考。

https://github.com/350984267/TOTPicon-default.png?t=N5F7https://github.com/350984267/TOTP 


http://chatgpt.dhexx.cn/article/S4jb4aNT.shtml

相关文章

深度学习--十折交叉验证

用scikit-learn来评价模型质量&#xff0c;为了更好地挑拣出结果的差异&#xff0c;采用了十折交叉验证&#xff08;10-fold cross validation&#xff09;方法。 本程序在输入层和第一个隐含层之间加入20%Dropout 采用十折交叉验证的方法进行测试。 # dropout in the input …

tensorflow2 交叉验证

交叉验证在fit()函数的参数里边&#xff0c;完整参数传送 https://blog.csdn.net/Forrest97/article/details/106635664 fit()里边相关交叉验证的参数 validation_datatest&#xff0c;就是自己划分好的测试集validation_steps&#xff0c; 验证样本总数 Total validation S…

验证的方法

一、概述 在开展验证时有一整套的工具箱&#xff0c;根据设计的特点选用不同的验证方法&#xff0c;最终取得满意的效果。实际的验证工作中&#xff0c;需要通过多种语言、方法、工具实现验证&#xff0c;比如仿真验证会协同形式验证一同来完善功能覆盖率&#xff0c;也有可能…

两步验证: 使用Python接入Google Authentiator

Google Authenticator 文章目录 Google Authenticator简介原理HOTPTOTP 实现生成密钥计算时间片HMAC-SHA1运算生成二维码校验 使用参考资料 简介 用户常常会在不同的网站使用相同的密码&#xff0c;一但一个网站账户的密码泄露&#xff0c;就会危及到其它使用相同密码的账户。…

用Abp实现两步验证(Two-Factor Authentication,2FA)登录(三):免登录验证

文章目录 原理修改请求报文配置JwtBearerOptions生成Token校验Token修改认证EndPoint修改前端登录登出 最终效果项目地址 免登录验证是用户在首次两步验证通过后&#xff0c;在常用的设备&#xff08;浏览器&#xff09;中&#xff0c;在一定时间内不需要再次输入验证码直接登录…

两步教你在Vue中设置登录验证拦截!

Hello&#xff0c;你好呀&#xff0c;我是灰小猿&#xff0c;一个超会写bug的程序猿&#xff01; 今天在做vue和springboot交互的一个项目的时候&#xff0c;想要基于前端实现一些只有登录验证之后才能访问某些页面的操作&#xff0c;所以在这里总结一下实现该功能的一个解决方…

HTTPS实战之单向验证和双向验证

&#xff08;全文太长&#xff0c;太懒不想看&#xff0c;-_-b 那就直接拉到底部看总结 &#xff09; 前面的文章中&#xff0c;提到了&#xff0c;https是在TCP协议与http之间加了一个控制安全传输的SSL协议&#xff0c;也就是说&#xff0c;直接运行在TCP之上的HTTP是普通的…

验证基础-验证方法

目录 动态仿真 静态检查 虚拟模型 硬件加速 效能验证 UVM简介 验证的方法主要分为六种&#xff1a; ※ 动态仿真&#xff08;dynamic simulation&#xff09; ※ 静态检查&#xff08;formal check&#xff09; ※ 虚拟模型&#xff08;virtual prototype&#xff09; ※…

用Abp实现两步验证(Two-Factor Authentication,2FA)登录(一):认证模块

文章目录 原理用户验证码校验模块双因素认证模块改写登录项目地址 在之前的博文 用Abp实现短信验证码免密登录&#xff08;一&#xff09;&#xff1a;短信校验模块 一文中&#xff0c;我们实现了用户验证码校验模块&#xff0c;今天来拓展这个模块&#xff0c;使Abp用户系统支…

用Abp实现两步验证(Two-Factor Authentication,2FA)登录(二):Vue网页端开发

文章目录 发送验证码登录退出登录界面控件获取用户信息功能项目地址 前端代码的框架采用vue.js elementUI 这套较为简单的方式实现&#xff0c;以及typescript语法更方便阅读。 首先添加全局对象&#xff1a; loginForm: 登录表单对象 twoFactorData: 两步验证数据&#xff0…

快速接入Google两步认证Google Authenticator

(一)介绍 既然来看该文章就应该知道Google的两步认证是干什么的&#xff0c;这边再提供一次app的下载链接 (apkpure搜索谷歌身份验证器) 验证原理讲解&#xff1a; 在数据库中查找该登陆用户之前绑定的32位随机码&#xff08;该码一般会存入数据库&#xff09;调用API传入32位…

两步验证 非双重认证

Two-factor authentication must be turned on for your Apple ID. After you turn it on, signing into your developer account will require both your password and access to your trusted devices or trusted phone number. 今天Xcode 真机调试, 突然不正常了. 本着热爱…

google账号异步新设备登录需要两次两步验证问题

备注&#xff1a;华为手机&#xff0c;在谷歌三件套插件已经下载的情况下&#xff0c;还是无法收到数字点击验证 先说下现象&#xff0c;比如你的谷歌账号从别人那购买的&#xff0c;然后辅助电话与邮箱已经全部替换成了自己的信息&#xff0c;一般为了安全我们会开启两步验证&…

谷歌两步验证器身份怎么开Authenticator安卓app下载安装方法教程

国内互联网公司一般采取手机收验证码的方式对账号进行身份验证&#xff0c;增强账号的安全性。但是在国外通常采取使用谷歌两步身份验证器 (Google Authenticator&#xff09;&#xff0c;谷歌谷歌两步身份验证器的方便之处主要体现在&#xff1a; 1.在无网络的情况下也可以使用…

如何开发两步验证功能

什么是两步验证 两步验证&#xff0c;是指用户登录账户的时候&#xff0c;除了要输入用户名和密码&#xff0c;还要求用户输入一个动态密码&#xff0c;为帐户添加了一层额外保护。这个动态密码要么是专门的硬件&#xff0c;要么由用户手机APP提供。即使入侵者窃取了用户密码&a…

兩步验证的原理

被盗号 “您的账号密码有误,请重新输入” 小卢盯着电脑屏幕看了5分钟,心里纳闷,昨天还能登录,怎么今天就密码错误了,难不成我被盗号了?想到这里,小卢赶紧给自己的程序员好友小王打电话。 小卢:“小王,我在XX网站的账号被盗了!” 小王:“确定被盗了?赶紧把密码找…

(01)Webrtc::Fec与Nack的二三事

写在前面&#xff1a;要理解Fec与Nack逻辑&#xff0c;我喜欢先从接受端看&#xff0c; 理解了Fec与Nack是如何被使用的&#xff0c;才能更好的明白不同的机制应该怎么用&#xff0c;在什么场合用。 更新丢包逻辑 void PacketBuffer::UpdateMissingPackets(uint16_t seq_num)…

Channel closed; cannot ack/nack

再一次用rabbmitmq的时候遇到了 Channel closed&#xff1b; cannot ack/nack的异常信息&#xff0c;这个可能是因为rabbmitmq默认的模式是自动ack&#xff0c;我没有配置手动ack 然后在代码里又basicack了。 MessageProperties properties message.getMessageProperties();l…

简述WebRTC中的丢包重传Nack的实现

一 简述 接收端发现序列号不连续&#xff0c;发送RTCP FB Nack包&#xff0c;发送端从历史队列中查找该包&#xff0c;再发送RTP包&#xff0c;但WebRTC用的RTX重发该包&#xff0c;ssrc和原视频流不同&#xff0c;pt也不同。 artpmap:96 H264/90000 artcp-fb:96 goog-remb a…

WEBRTC浅析(五)视频Nack包的发送判断逻辑以及数据流

这篇文章是对webrtc 中Nack包发送机制的梳理&#xff0c;主要包括三个部分&#xff1a; 第一部分&#xff0c;介绍RTCP包中&#xff0c;Nack包的规范。 第二部分&#xff0c;介绍在WEBRTC中&#xff0c;Nack发送机制的数据流程图。 第三部分&#xff0c;介绍在WEBRTC中&#xf…