分享python基于onetimepass的双因素身份验证(2FA)

 开发  双因素验证  2FA  python   2017-12-25 21:57   评论1次 
正文区

一、基础认识

    多因素身份验证(MFA)是一种计算机访问控制方法,在这种方法中,用户只有在成功向验证机制提交了几个单独的证据之后才被授予访问权限,通常是以下三类:

        秘密信息:只有该用户知道、其他人不知道的某种信息,比如密码。

        个人物品:该用户的私人物品,比如身份证、钥匙、手机。

        生理特征:该用户的遗传特征,比如指纹、相貌、虹膜等等。

    这三种证据因素越多,证明力越强,身份越可靠。

    1. 含义:

        双因素认证(也称为2FA,2 Factor Authentication)是通过利用两个不同组件的组合来确认用户所声称的身份的方法。双因素认证是一种多因素认证。

        双因素认证,是一种采用时间同步技术的系统,采用了基于时间、事件和密钥三变量而产生的一次性密码来代替传统的静态密码,是一种安全密码验证方式。

    2. 方案:

        密码+某种个人物品(手机、U盾、银行卡等)

    下文的介绍基于密码+手机(TOTP动态口令)方式。

    每个用户都有一个唯一的密钥,该密钥同时存放在服务器端,每次认证时用户令牌与服务器分别根据同样的密钥,同样的随机参数(时间、事件)和同样的算法计算了认证的动态密码,从而确保密码的一致性,从而实现了用户的认证。

二、OTP

    OTP全称叫One-time Password,也称动态口令,是根据专门的算法每隔30秒生成一个与时间相关的、不可预测的随机数字组合,每个口令只能使用一次,被认为是更安全的,因为密码不断变化,不容易受到重播攻击。

    1.OTP类型

        HOTP(HMAC-based One-Time Password的简写,表示基于HMAC算法加密的一次性密码):在RFC 4226中描述了它,该算法基于由令牌生成装置和认证服务器所知的秘密和计数器生成令牌。每次使用一个令牌时,计数器的两边都会递增,这样算法会为下一次登录尝试生成一个不同的令牌。

        TOTP(Time-based One-Time Password的简写,表示基于时间戳算法的一次性密码):在RFC 6238中描述了它,这个标准也使用了一个共享的密钥,但是用当前时间来替代计数器。使用该算法,令牌以预定的时间间隔(通常每30秒)改变一次。

        TOTP优于HOTP的好处在于,它是”基于时间的一次性密码”,因此在不断变化,这意味着,即使攻击者可以偷看智能手机应用程序上显示的当前令牌,几秒钟之后,它将被新的令牌代替。TOTP的缺点是它需要令牌生成器和认证服务器将其时钟设置为大致相同的时间。

    2.OTP令牌

        硬件令牌:如YubiKey、RSA SecurID

        软件令牌:Android、iOS、WP下均有应用程序,如FreeeOtp

        3

    3.认证流程

        以TOTP为例。

        场景一:用户注册时创建个人唯一密钥生成二维码并扫描,之后不提供二维码展示,登录时需要客户端的动态口令提交到服务端做认证,认证通过允许登录。

        场景二:已有用户,开启2FA功能时创建个人唯一密钥生成二维码,需要扫描认证通过后才正常开启(保证用户真的扫描了),开启之后为了安全亦不再显示二维码,登录时同上。

三、onetimepass

    1.github:https://github.com/tadeck/onetimepass

    2.使用

    QQ截图20171225214936

    2.web示例(flask版)

        https://github.com/miguelgrinberg/two-factor-auth-flask(场景一)

    3.个人实践(场景二,无法公开仅部分图)

        > 开启2FA验证弹出提示并显示二维码,需要FreeOtp扫描二维码验证通过方能开启设置;

        微信图片_20171225214010

        > 验证通过开启后,登录后跳转到验证页面,验证通过进入系统,否则跳回验证页。

        2


参考资料:

1.http://www.ruanyifeng.com/blog/2017/11/2fa-tutorial.html

2.https://blog.miguelgrinberg.com/post/two-factor-authentication-with-flask