当前位置: 首页 > news >正文

TOTP 算法实现:双因素认证的基石(C/C++代码实现)

双因素认证(Two-Factor Authentication, 2FA)扮演着至关重要的角色。它像是一道额外的防线,确保即便密码被窃取,不法分子也难以轻易突破。在众多双因素认证技术中,基于时间的一次性密码(Time-Based One-Time Password, TOTP)算法因其安全性高、使用便捷而受到广泛应用。

TOTP算法是一种基于时间的一次性密码生成算法,它的核心思想是利用时间作为变化的因子来生成动态的密码。这种算法通常与用户的个人信息结合使用,如用户名或电子邮件地址,以及一个共享的秘密密钥。这个秘密密钥在用户端和服务端预先共享,是生成正确OTP的关键。

TOTP是如何工作的呢?

让我们通过一个简单的比喻来理解其原理。想象一下,你有一本只属于你和你的朋友的书,书中记载了一连串的故事,每个故事都有一个编号。每当你想要和朋友传递一个秘密信息时,你会查找当前日期对应的故事编号,并从中选取特定的段落来传递信息。在这个例子中,书就像是秘密密钥,故事编号对应于时间戳,而传递的信息则是一次性密码。

具体到TOTP算法,它使用了哈希函数(如SHA-1、SHA-256等)和时间戳。当用户想要登录系统时,用户的设备会计算当前时间与预设时间步长的差值,然后将这个差值与共享的秘密密钥一起输入到哈希函数中。哈希函数处理后输出一串较长的二进制数据,这串数据再经过模运算,得到一个较短的数字,这个数字就是OTP。用户需要在规定的时间内将这个OTP输入到验证系统中,系统同样会根据相同的秘密密钥和时间差值计算出一个OTP,并与用户提供的OTP进行比对,若两者一致,则认证成功。

在实现上,TOTP算法需要考虑到时间同步的问题。由于网络延迟或者设备时钟不准确,可能导致用户设备与服务器之间的时间有偏差。因此,TOTP算法通常会有一个时间窗口(如30秒),允许在这个时间范围内的OTP都是有效的。

TOTP的优势在于其安全性和用户体验。由于OTP是基于时间和共享秘密密钥生成的,即使黑客截获了某个时刻的OTP,它也无法在其他时间点使用,因为OTP每隔一段时间就会变化。此外,用户可以不需要记忆复杂的密码,只需拥有注册时分配的密钥(通常存储在硬件令牌或软件应用中),就可以轻松完成身份验证。

TOTP的实现

Base32编码与解码

Base32编码原理:
Base32编码是一种将二进制数据转换成32种可打印字符的编码方式。它主要用于电子邮件和URL中传输二进制数据。Base32使用A-Z的大写字母(不使用C, E, G, I, O, Q, U, V)和数字2-7来表示数据。每8位二进制数据可以编码为5个Base32字符,这意味着编码后的数据长度是原始数据的大约1.33倍。

实现Base32编码:
编码过程涉及将输入的字节数据分成5位一组,每组转换为对应的Base32字符。例如,如果输入字节是0x9A,它对应于二进制的10011010,然后将其分成两组:10011010。每组转换为Base32字符,分别是SK

实现Base32解码:
解码过程与编码相反,它将Base32字符转换回原始的字节数据。解码函数需要处理输入的Base32字符串,跳过任何非Base32字符(如填充的等号),并将每个字符转换回相应的5位二进制值。然后,这些值被重新组合成字节数据。

HMAC-SHA1算法

HMAC-SHA1基本概念:
HMAC(Hash-based Message Authentication Code)是一种消息认证码,它使用哈希算法(如SHA-1)和密钥来提供消息的完整性保护和认证。SHA-1是一种广泛使用的加密哈希函数,它可以产生一个160位(20字节)的哈希值。

在TOTP中的应用:
在TOTP中,HMAC-SHA1用于生成一个基于密钥、时间戳和算法参数的哈希值。这个哈希值随后被用来生成6位数的一次性密码。通过使用HMAC-SHA1,TOTP确保了即使密钥被泄露,生成的密码也难以被预测。

时间戳处理

时间戳的重要性:
TOTP算法依赖于时间戳来生成密码,因此时间同步至关重要。如果客户端和服务器之间的时间不同步,生成的密码可能会无效。

确保时间同步:
为了确保时间同步,可以采取以下措施:

  • 使用网络时间协议(NTP)来同步客户端和服务器的时间。
  • 在用户设备上设置时间校验机制,确保时间偏差在可接受范围内。

密码生成逻辑

从HMAC-SHA1输出中提取密码:

  1. 使用HMAC-SHA1算法和当前时间戳生成一个20字节的哈希值。
  2. 对哈希值进行处理,提取出用于生成密码的部分。具体来说,取哈希值的最后一个字节的最低4位作为索引,从这个位置开始读取接下来的4个字节。
  3. 将这4个字节视为一个整数,然后对1000000取模,得到一个6位数的密码。

生成6位数的密码:

  • 将上述步骤得到的整数转换为字符串形式,并确保它是一个6位数的密码。如果需要,可以在前面补零。

TOTP 算法实现:双因素认证的基石(C/C++代码实现)

双因素认证(2FA)作为一种增强安全性的方法应运而生。基于时间的一次性密码(TOTP)是2FA的一种实现方式,它提供了一种动态生成、一次性使用的密码,极大地提高了账户的安全性。下面实现类似Google Authenticator这样的应用程序。


void hmac(void *dest,const void *key,uint32_t key_len,const void *msg,uint32_t msg_len,void (*hash)(char *dest, const char *str, int len),uint16_t block_size,uint16_t output_size
);
typedef struct
{uint32_t state[5];uint32_t count[2];unsigned char buffer[64];
} SHA1_CTX;void sha1_transform(uint32_t state[5], const unsigned char buffer[64]);
void sha1_init(SHA1_CTX * context);
void sha1_update(SHA1_CTX * context, const unsigned char *data, uint32_t len);
void sha1_final(unsigned char digest[20], SHA1_CTX * context);
void sha1(char *hash_out, const char *str, int len);
void bytes_array_reverse(uint8_t* bytes, int size);
int bytes_array_to_int(const uint8_t* bytes, int start, int end);
int base32_decode(const uint8_t *encoded, uint8_t *result, int bufSize);
char* str_upper(char* str);
char* str_pad_left(char* str, char pad, int len);
char* str_pad_right(char* str, char pad, int len);
int int_to_str(int i, char *buf, int buf_len);void get_2fa_code(char *secret, char code[7])
{char key[20];char hash[20];int key_len;uint64_t msg;str_upper(secret);  //转换为大写以获得有效的Base32格式key_len = base32_decode((uint8_t*)secret, (uint8_t*)key, 20);           // 将机密解码为字节数组msg = time(NULL) / 30;                                                  // TOTP是HOTP,种子为30秒。bytes_array_reverse((uint8_t*)&msg, 8);                                hmac(hash, key, key_len, (uint8_t*)&msg, 8, sha1, 64, 20);              // 生成hmac哈希int offset = hash[19] & 0xF;                                            int header = bytes_array_to_int((uint8_t*)hash, offset, offset + 4);    // 从偏移量开始截断4个字节header = header & 0x7fffffff;                                           // 删除最高有效位header = header % 1000000;                                              // 生成小于7位的余数int_to_str(header, code, 7);    // 将代码转换为字符串str_pad_left(code, '0', 6);     // 从左起用0填充代码,直到代码长度为6
}
int main(int argc, char **argv)
{
...if (argc != 2) {printf("./ga [secret]\n");return (0);}get_2fa_code(argv[1], code);printf("Code :\n%s\n", code);return (0);
}

运行结果:

If you need the complete source code, please add the WeChat number (c17865354792)

总结

Google Authenticator 的核心原理是利用共享密钥和一个随时间变化的因子来生成一次性密码,从而实现第二因素的身份验证。这种方法既方便又安全,因为它不需要额外的硬件令牌,只需要用户的智能设备即可。此外,由于 OTP 是一次性的,并且随时间变化,即使黑客截获了当前的 OTP,也无法在未来的时间点使用它来冒充用户。

We also undertake the development of program requirements here. If necessary, please follow the WeChat official account 【程序猿编码】and contact me

相关文章:

TOTP 算法实现:双因素认证的基石(C/C++代码实现)

双因素认证(Two-Factor Authentication, 2FA)扮演着至关重要的角色。它像是一道额外的防线,确保即便密码被窃取,不法分子也难以轻易突破。在众多双因素认证技术中,基于时间的一次性密码(Time-Based One-Tim…...

aws eks理解和使用podidentity为pod授权

参考链接 https://www.amazonaws.cn/new/2024/amazon-eks-introduces-eks-pod-identity/https://aws.amazon.com/cn/blogs/aws/amazon-eks-pod-identity-simplifies-iam-permissions-for-applications-on-amazon-eks-clusters/ 先决条件 集群版本需要符合要求,如果…...

面向可复用性和可维护性的设计模式 课程学习总结

什么是设计模式 设计模式:在软件设计中给定上下文中常见问题的通用的、可重用的解决方案。 设计模式分类 1. 创建型模式——Creational patterns 关注对象创建的过程 1.1 工厂方法模式 定义用于创建对象的接口,但让子类决定要实例化哪个类。工厂方…...

修复谷歌 AdSense 的 Ads.Txt 无效的有收益损失风险提示

明月的 AdSense 账号后台一直都有“有收益损失风险 - 您需要纠正 ads.txt 文件存在的一些问题,以免严重影响您的收入。”的提示长达一年多了,这次重新开始投放谷歌 AdSense 广告后感觉需要解决掉这个问题了,因为已经全站使用了 CloudFlare&am…...

使用向量叉乘,来计算一个点到一条线的距离

1. 使用向量叉乘,来计算一个点到一条线的距离 如果说一条线段的两个端点坐标分别是,A,B点,到线段外一点P的距离。 我们可以把,这三个点连接起来,得到一个三角形,此时的步骤就是这样的 计算这个…...

学习笔记——交通安全分析02

目录 前言 当天学习笔记整理 绪论 结束语 前言 #随着上一轮SPSS学习完成之后,本人又开始了新教材《交通安全分析》的学习 #整理过程不易,喜欢UP就点个免费的关注趴 当天学习笔记整理 绪论 美国在道路设施安全改善过程中,形成了数据基…...

pytest-sugar插件:对自动化测试用例加入进度条

摘要 在自动化测试过程中,测试进度的可视化对于开发者和测试工程师来说非常重要。本文将介绍如何使用pytest-sugar插件来为pytest测试用例添加进度条,从而提升测试的可读性和用户体验。 1. 引言 自动化测试是软件开发过程中不可或缺的一部分&#xff…...

AI大模型的口语练习APP

开发一个使用第三方大模型的口语练习APP涉及多个步骤,从需求分析到部署上线。以下是详细的开发流程和关键步骤,通过系统化的流程和合适的技术选型,可以有效地开发出一个功能丰富、用户体验良好的口语练习APP。北京木奇移动技术有限公司&#…...

Elasticsearch 详细介绍和经典应用

Elasticsearch是一个开源的分布式搜索和分析引擎,它建立在Apache Lucene搜索引擎库之上,提供了一个分布式、多租户的全文搜索引擎,能够实时地存储、检索和分析大规模的数据。以下是关于Elasticsearch的详细介绍和经典应用: 详细介…...

GEC210编译环境搭建

一、下载编译工具链 下载:点击跳转 二、解压到 /usr/local/arm 目录 sudo mv gec210.zip /usr/local/arm cd /usr/local/arm sudo unzip gec210.zip 三、添加到环境变量 PATH/usr/local/arm/arm-cortex_a8-linux-gnueabi-4.7.3/bin:$PATH 四、测试验证 在终端…...

Mysql中表之间的关系

表之间的关系 一对一、多对一(其实就是主从关系,在从表中设置一个外键关联上主表)、多对多关系(需要一个中间表,设置两个外键,分别关联到两个表的主键) 比如订单和商品之间:一个订单…...

文心智能体大赛:百度文心智能体平台初体验

写在前面 博文内容涉及:文心智能体大赛:文心智能体初体验理解不足小伙伴帮忙指正 😃,生活加油 我徒然忘记了热闹,却来不及悟透真正的清冷(《四喜忧国》) 前言 徒然忘记了热闹,却来不及悟透真正的清冷(《四喜忧国》),在…...

AI数据面临枯竭

Alexandr Wang:前沿研究领域需要大量当前不存在的数据,未来会受到这个限制 Alexandr Wang 强调了 AI 领域面临的数据问题。 他指出,前沿研究领域(如多模态、多语言、专家链式思维和企业工作流)需要大量当前不存在的数…...

2024.5组队学习——MetaGPT(0.8.1)智能体理论与实战(中):订阅智能体OSS实现

传送门: 《2024.5组队学习——MetaGPT(0.8.1)智能体理论与实战(上):MetaGPT安装、单智能体开发》《2024.5组队学习——MetaGPT(0.8.1)智能体理论与实战(下)&…...

LoadBalancer

一、手写随机负载均衡 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> </dependency><!--引入nacos discovery--> <dependency><groupId>com…...

【栈】Leetcode 71. 简化路径【中等】

简化路径 给你一个字符串 path &#xff0c;表示指向某一文件或目录的 Unix 风格 绝对路径 &#xff08;以 ‘/’ 开头&#xff09;&#xff0c;请你将其转化为更加简洁的规范路径。 在 Unix 风格的文件系统中&#xff0c;一个点&#xff08;.&#xff09;表示当前目录本身&am…...

简单操作一单利润500+,最新快手缺货赔付玩法,【找店教程+详细教程】

在如今快速变化的时代&#xff0c;寻找充满创新的收入来源已经成为了一种趋势。这不仅是为了实现财务的自由&#xff0c;更是为了在生活中拥有更多的选择权。一项革新的实践——利用手机进行快手缺货赔付单号的操作&#xff0c;已经成为许多人稳定“下车”的一个新途径。 据了…...

【软件设计师】先导

一、考试科目&#xff1a; 上午&#xff1a;计算机与软件工程知识&#xff0c;考试时间150min&#xff0c;75空单选题&#xff08;不一定一题一空&#xff09; 下午&#xff1a;软件设计&#xff0c;考试时间150分钟&#xff0c;问答题&#xff0c;6道只做5大题&#xff08;前四…...

npm : 无法将“npm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称

提示&#xff1a;我解决这个bug跟别人思路可能不太一样&#xff0c;因为我是之前好用&#xff0c;换个项目就不好使了&#xff0c;倦了 文章目录 前言项目场景&#xff1a;解决方案&#xff1a;下载 nvm安装 nvm重新下载所需Node 版本nvm常用命令 前言 提示&#xff1a;这里可…...

如何用 MoonBit 实现 diff?

你使用过 Unix 下的小工具 diff 吗&#xff1f; 没有也没关系&#xff0c;简而言之&#xff0c;它是一个比对两个文本文件之间有什么不同之处的工具。它的作用不止于此&#xff0c;Unix 下还有一个叫 patch 的小工具。 时至今日&#xff0c;很少有人手动为某个软件包打补丁了…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

二维FDTD算法仿真

二维FDTD算法仿真&#xff0c;并带完全匹配层&#xff0c;输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...

uni-app学习笔记三十五--扩展组件的安装和使用

由于内置组件不能满足日常开发需要&#xff0c;uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件&#xff0c;需要安装才能使用。 一、安装扩展插件 安装方法&#xff1a; 1.访问uniapp官方文档组件部分&#xff1a;组件使用的入门教程 | uni-app官网 点击左侧…...

Java并发编程实战 Day 11:并发设计模式

【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天&#xff0c;今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案&#xff0c;它们不仅提供了优雅的设计思路&#xff0c;还能显著提升系统的性能…...