优秀的编程知识分享平台

网站首页 > 技术文章 正文

一次性密码TOTP算法的Python的20行实现

nanyue 2024-12-20 17:45:45 技术文章 4 ℃

更多互联网新鲜资讯、工作奇淫技巧关注原创【飞鱼在浪屿】(日更新)

TOTP(Time-based One-Time Password)代表基于时间的一次性密码。许多网站和服务需要两因素身份验证(2FA)或多因素身份验证(MFA),其中要求用户提供两个或更多要素:

  • 只有用户知道的内容,例如密码,密码短语等。
  • 只有用户拥有的东西,例如硬件令牌,手机等。
  • 例如,只有用户才可以使用生物识别。

TOTP值用作第二个因素,即,它证明用户拥有包含TOTP秘密密钥的设备(例如,移动电话),并从中生成TOTP值。通常,提供用户帐户的服务提供商还会发布一个加密为Base32字符串或QR码的密钥。此密钥被添加到移动设备上的身份验证器应用程序(例如Google Authenticator)中。然后,该应用可以根据当前时间生成TOTP值。默认情况下,它每30秒生成一个新的TOTP值。

MinTOTP是一个Python工具,可用于从密钥生成TOTP值。此外,它为Python开发人员将其功能公开为模块级功能。它可以在安装了Python 3.4或更高版本的任何系统上使用。


源代码

TOTP算法的核心是HOTP算法。HOTP代表基于HMAC的一次性密码。HMAC代表基于哈希的消息身份验证代码。以下是相关的RFC,以了解有关这些算法的更多信息:

  • RFC 2104:HMAC:消息身份验证的键哈希
  • RFC 4226:HOTP:基于HMAC的一次性密码算法
  • RFC 6238:TOTP:基于时间的一次性密码算法
#!/usr/bin/python3

import base64
import hmac
import struct
import sys
import time


def hotp(key, counter, digits=6, digest='sha1'):
    key = base64.b32decode(key.upper() + '=' * ((8 - len(key)) % 8))
    counter = struct.pack('>Q', counter)
    mac = hmac.new(key, counter, digest).digest()
    offset = mac[-1] & 0x0f
    binary = struct.unpack('>L', mac[offset:offset+4])[0] & 0x7fffffff
    return str(binary)[-digits:].rjust(digits, '0')


def totp(key, time_step=30, digits=6, digest='sha1'):
    return hotp(key, int(time.time() / time_step), digits, digest)


def main():
    args = [int(x) if x.isdigit() else x for x in sys.argv[1:]]
    for key in sys.stdin:
        print(totp(key.strip(), *args))


if __name__ == '__main__':
    main()

在上面的代码中,使用hmacPython标准库中提供的模块来实现HOTP。可以在hotp()函数中找到实现。这是RFC 2104的非常简单的实现 :第5节:HOTP算法。它采用Base32编码的秘密密钥和计数器作为输入。它返回一个6位数的HOTP值作为输出。

该totp()函数实现了TOTP算法。它是围绕HOTP算法的精简包装。通过使用密钥和自Unix纪元(1970-01-01 00:00:00 UTC)起经过的时间间隔数(默认为30秒间隔)调用HOTP函数来获得TOTP值。


安装:

输入以下命令以在系统上安装MinTOTP:pip3 install mintotp

测试MinTOTP是否可以作为命令正常工作:mintotp <<< ZYTYYE5FOAGW5ML7LRWUL4WTZLNJAMZS,应输出6位数的TOTP值。

测试MinTOTP可以用作库模块:

$ python3 
>>>import mintotp 
>>> mintotp.totp(' ZYTYYE5FOAGW5ML7LRWUL4WTZLNJAMZS ') 
>>> mintotp.hotp(' ZYTYYE5FOAGW5ML7LRWUL4WTZLNJAMZS ',42)

该totp()函数调用应返回基于当前时间的6位TOTP值。该hotp()呼叫应返回以下HOTP值:626854。

路径在:https://github.com/susam/mintotp


更多:bash版本的实现:

https://github.com/jakwings/bash-totp/blob/git/nerd/underdog/eunuch/moron/ass/cunt/shit/totp

Tags:

最近发表
标签列表