在信息安全领域,一般把Cryptography称为密码,而把Password称为口令。日常用户的认知中,以及我们开发人员沟通过程中,绝大多数被称作密码的东西其实都是Password(口令),而不是真正意义上的密码。本文保持这种语义,采用密码来代指Password,而当密码和口令同时出现时,用英文表示以示区分。

0. OTP一次性密码

OTP是One Time Password的简写,即一次性密码。在平时生活中,我们接触一次性密码的场景非常多,比如在登录账号、找回密码,更改密码和转账操作等等这些场景,其中一些常用到的方式有:

  1. 手机短信+短信验证码;
  2. 邮件+邮件验证码;
  3. 认证器软件+验证码,比如Microsoft Authenticator App,Google Authenticator App等等;
  4. 硬件+验证码:比如网银的电子密码器;

这些场景的流程一般都是在用户提供了账号+密码的基础上,让用户再提供一个一次性的验证码来提供一层额外的安全防护。通常情况下,这个验证码是一个6-8位的数字,只能使用一次或者仅在很短的时间内可用(比如5分钟以内)。

1. HOTP基于消息认证码的一次性密码

HOTP是HMAC-Based One Time Password的缩写,即是基于HMAC(基于Hash的消息认证码)实现的一次性密码。算法细节定义在RFC4226(https://tools.ietf.org/html/rfc4226),算法公式为: HOTP(Key,Counter)  ,拆开是 Truncate(HMAC-SHA-(Key,Counter)) 。

  1. Key:密钥;
  2. Counter:一个计数器;
  3. HMAC-SHA-1:基于SHA1的HMAC算法的一个函数,返回MAC的值,MAC是一个20bytes(160bits)的字节数组;
  4. Truncate:一个截取数字的函数,以3中的MAC为参数,按照指定规则,得到一个6位或者8位数字(位数太多的话不方便用户输入,太少的话又容易被暴力猜测到);

C#实现基于HMAC的OTP的代码:

 public static string HOTP(byte[] key, byte[] counter, int length = )
{
var hmac = counter.ToHMACSHA1(key); var offset = hmac[hmac.Length - ] & 0xF; var b1 = (hmac[offset] & 0x7F) << ;
var b2 = (hmac[offset + ] & 0xFF) << ;
var b3 = (hmac[offset + ] & 0xFF) << ;
var b4 = (hmac[offset + ] & 0xFF); var code = b1 | b2 | b3 | b4; var value = code % (int)Math.Pow(, length); return value.ToString().PadLeft(length, '');
}

调用一下试试看:

 //密钥key
var key = "lnh_key".ToBytes(Encoding.UTF8);
//计数器
var counter = "lnh_counter".ToBytes(Encoding.UTF8);
//otp6=752378
var otp6 = SecurityHelper.HOTP(key, counter,);
//otp8=49752378
var otp8 = SecurityHelper.HOTP(key, counter, );

其中key是HOTP算法需要的一个密钥(不可泄露);counter是每次生成HOTP的时候使用的计数器,使用一次就更换一个。然后就可以用来生成OTP了,第一此截取了6位,第二此截取了8位。

2. TOTP基于时间的一次性密码

TOTP是Time-Based One Time Password的缩写。TOTP是在HOTP的基础上扩展的一个算法,算法细节定义在RFC6238(https://tools.ietf.org/html/rfc6238),其核心在于把HOTP中的counter换成了时间T,可以简单的理解为一个当前时间的时间戳(unixtime)。一般实际应用中会固定一个时间的步长,比如30秒,60秒,120秒等等,也就是说再这个步长的时间内,基于TOTP算法算出的OTP值是一样的。废话不多说,看看TOTP算法的核心代码:

 public static string TOTP(byte[] key, int step = , int length = )
{
var unixTime = (DateTime.UtcNow - new DateTime(, , , , , , , DateTimeKind.Utc)).TotalSeconds;
var counter = ((int)unixTime) / step;
var counterBytes = BitConverter.GetBytes(counter);
return HOTP(key, counterBytes, length);
}

调用一下试试看:

//密钥key
var key = "lnh_key".ToBytes(Encoding.UTF8);
//在10秒内生成,otp是一样的
for (var i = ; i < 10; i++)
{
var otp = SecurityHelper.TOTP(key, 1, );
Console.WriteLine(otp);
Thread.Sleep();
}

3. 身份认证三要素

首先解释下什么是身份认证?其实很简单,就是让对方相信你就是你。那么如何让对方相信你就是你呢?按照你能提供的信息的等级来划分,大致有如下三种信息可以证明你就是你自己:

  1. 你所知道的信息:比如我们最广泛使用的“用户名+密码”,因为只有你自己知道“用户名+密码”这个信息组合,那么当你把这个组合提供给我的时候,我就可以相信你就是你。
  2. 你所拥有的信息:假如你的“用户名+密码”泄露给了第三方,这个时候你就会有被第三方冒充的危险了。怎么办呢,再进一步提供一个只有你自己拥有的信息,即可防止被第三方冒充的危险。
  3. 你所独有的信息:再假设一下,你拥有的信息也被泄露给了第三方,这个时候你又会面临被冒充的危险。再进一步,提供一个只有你自己所独有的的信息,比如你的指纹,虹膜,面部特征等等。

3.1 2SV 两步验证(Two Steps Verification)

两步验证现在是一个再加强认证安全方面广泛使用的一个解决方案。比如Google的2SV(https://www.google.com/landing/2step/),Microsoft的2SV(https://support.microsoft.com/zh-cn/help/12408/microsoft-account-about-two-step-verification)等等,通常的做法是当用户输入了"用户名+密码"的基础上,会让用户再提供一个一次性密码(以短信、邮件,或者动态密码生成器app的方式发放给用户)。再有比如在一些服务中需要用户额外设置的安全问题,比如“你的出生地在哪?”等等此类。

3.2 2FA双因素认证(Two Factor Authentication)

2SV有个孪生兄弟2FA(双因素认证:Two Factor Authentication),那么关于2SV和2FA有什么区别呢,比如让用户在“用户名+密码”的基础上提供的额外的一次性密码,关于这个一次性密码到底是属于“你所知道的信息”还是“你所拥有的信息”呢?并没有明显的区分界限,有兴趣的可以看看这里的讨论:https://security.stackexchange.com/questions/41939/two-step-vs-two-factor-authentication-is-there-a-difference 。 如果你觉得这个一次性密码属于“你所知道的信息”,那么你可以认为它是2SV;如果你觉得这个一次性密码属于“你所拥有的信息”,那么你可以认为它是2FA。

总结来说,2FA就是使用了身份认证中的2个要素。

总结 & 参考

简单的介绍了下一次性密码的原理以及其应用场景,完整的代码请移步:https://github.com/linianhui/code/blob/master/src/SecurityHelper.cs。如有错误之处,欢迎指正!

参考资料

OTP(One Time Password)Wiki:https://en.wikipedia.org/wiki/One-time_password

One Time Password System:https://tools.ietf.org/html/rfc2289

HOTP(HMAC-Based One Time Password) Wiki:https://en.wikipedia.org/wiki/HMAC-based_One-time_Password_Algorithm

HOTP(HMAC-Based One Time Password)RFC:https://tools.ietf.org/html/rfc4226

TOTP(Time-Based One Time Password)Wiki:https://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm

TOTP(Time-Based One Time Password)RFC:https://tools.ietf.org/html/rfc6238

2SV vs 2FA (1):https://security.stackexchange.com/questions/41939/two-step-vs-two-factor-authentication-is-there-a-difference

2SV vs 2FA (2):https://paul.reviews/the-difference-between-two-factor-and-two-step-authentication/

MFA/2FA(Multi Factor Authentication) Wiki:https://en.wikipedia.org/wiki/Multi-factor_authentication

示例

Google Authenticator : https://github.com/google/google-authenticator/wiki

DEMO: https://authenticator.ppl.family/

[信息安全] 4.一次性密码 && 身份认证三要素的更多相关文章

  1. 深入解读 ASP.NET Core 身份认证过程

    长话短说:上文我们讲了 ASP.NET Core 基于声明的访问控制到底是什么鬼? 今天我们乘胜追击:聊一聊ASP.NET Core 中的身份验证. 身份验证是确定用户身份的过程. 授权是确定用户是否 ...

  2. Apache shiro集群实现 (三)shiro身份认证(Shiro Authentication)

    Apache shiro集群实现 (一) shiro入门介绍 Apache shiro集群实现 (二) shiro 的INI配置 Apache shiro集群实现 (三)shiro身份认证(Shiro ...

  3. asp.net core 使用identityServer4的密码模式来进行身份认证(一)

    IdentityServer4是ASP.NET Core的一个包含OpenID和OAuth 2.0协议的框架.具体Oauth 2.0和openId请百度. 前言本博文适用于前后端分离或者为移动产品来后 ...

  4. python作业设计:输入用户名密码,认证成功后显示欢迎信息,输错三次后锁定

    作业需求: 1.输入用户名密码 2.认证成功后显示欢迎信息 3.输错三次后锁定实现思路: 1.判断用户是否在黑名单,如果在黑名单提示账号锁定. 2.判断用户是否存在,如果不存在提示账号不存在. 3.判 ...

  5. Angular SPA基于Ocelot API网关与IdentityServer4的身份认证与授权(三)

    在前面两篇文章中,我介绍了基于IdentityServer4的一个Identity Service的实现,并且实现了一个Weather API和基于Ocelot的API网关,然后实现了通过Ocelot ...

  6. 重新整理 .net core 实践篇————网关中的身份签名认证[三十七]

    前言 简单整理一下网关中的jwt,jwt用于授权认证的,其实关于认证授权这块https://www.cnblogs.com/aoximin/p/12268520.html 这个链接的时候就已经写了,当 ...

  7. influxdb数据库增加身份认证(windows)三

    接上一节,增加数据库身份认证 1.修改Config配置文件auth-enabled为true 2.然后重新载入最新的config配置文件打开数据库 3.验证身份认证功能是否已打开 说明身份认证功能已打 ...

  8. 理解ASP.NET Core - 基于JwtBearer的身份认证(Authentication)

    注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 在开始之前,如果你还不了解基于Cookie的身份认证,那么建议你先阅读<基于Cookie ...

  9. "用户增长"--快速身份认证实现用户增长的技术和产品方案

    "用户增长"--快速身份认证实现用户增长的技术和产品方案 1   引言 作为一个互联网产品,用户量的增长是一个非常重要的衡量指标. 这是一个集合了销售,市场,运营,技术的综合能力. ...

随机推荐

  1. 微信小程序多张图片上传

    微信小程序上传图片每次只能上传一张,所有很多朋友就会问想要多张图片上传怎么办? 首先,我们来看一看wx.chooseImage(object)和wx.uploadFile(OBJECT)这两个个api ...

  2. Oracle ORA-39726压缩表删除字段处理方法

    今天在往一个压缩表增加一个字段可以增加成功,但在删除的时候报了个ORA-39726 unsupported add/drop column operation on compressed tables ...

  3. js变量提升和函数提升

    变量,作为编程语言最基础的部分,每种语言的变量不尽相同,但又大径相庭.大部分编程语言的变量有块级作用域,如if.for.while... 但JavaScript不纯在块级作用域,而是函数作用域,并且有 ...

  4. 第4章 ext文件系统机制

    本文目录: 4.1 文件系统的组成部分 4.2 文件系统的完整结构 4.3 Data Block 4.4 inode基础知识 4.5 inode深入 4.6 单文件系统中文件操作的原理 4.7 多文件 ...

  5. .NET和JAVA 反射对比

    反射是一个程序集发现及运行的过程,通过反射可以得到*.exe或*.dll等程序集内部的信息.使用反射可以看到一个程序集内部的接口.类.方法.字段.属性.特性等等信息.在System.Reflectio ...

  6. .NET中使用Redis总结

    注:关于如何在windows,linux下配置redis,详见这篇文章:) 启动遇到问题 使用命令[redis-server.exe redis.windows.conf],启动redis 服务[如果 ...

  7. Angularjs1.2版本与1.3版本中控制器的问题

    写写今天用ng遇到的一个问题吧.因为刚学习就学视频里面写例子,视频里用的是ng1.2.10版本,我用的是1.5.0. 刚开始的时候我按照ng视频的里面的写,但是控制器就是不能绑定好,后来和同学讨论加搜 ...

  8. 关于MATLAB处理大数据坐标文件2017528

    第一次提交数据 增加了部分特征 3000数据测试中得分99 但是10万数据出现过拟化现象,正确率下降 总结:1.某些特征数据本身波动不大应该考虑放弃 2.一些特征虽然表面觉得差异显而易见,但是数据表达 ...

  9. python selenium-webdriver 通过cookie登陆(十一)

    上节介绍了浏览器的常用方法,涉及到了cookie的使用,本节介绍一下如何利用cookie进行登陆系统,这里使用到了request模块,我们首先利用request模块,请求登陆地址进行登陆,登陆成功以后 ...

  10. 开源Inno Setup官网下载、安装、打包教程(官网安装向导中文语言包)

    安装Inno Setup篇 1.搜索Inno Setup 2.下载Inno Setup 3.选择下载最新 innosetup-5.5.9-unicode.exe 版本(innosetup-5.5.9. ...