• 基于TOTP算法的Github两步验证2FA(双因子)机制Python3.10实现


    从今年(2023)三月份开始,Github开始强制用户开启两步验证2FA(双因子)登录验证,毫无疑问,是出于安全层面的考虑,毕竟Github账号一旦被盗,所有代码仓库都会毁于一旦,关于双因子登录的必要性请参见:别让你的服务器(vps)沦为肉鸡(ssh暴力破解),密钥验证、双向因子登录值得拥有

    双因子登录说白了就是通过第三方设备证明"你是你自己"的一个措施,Github官方推荐在移动端下载1Password、Authy、Microsoft Authenticator等APP来通过扫码进行验证,其实大可不必如此麻烦,本次我们通过Python/Golang代码来实现双因子登录验证。

    TOTP算法

    Time-based One-Time Password(TOTP)是一种基于时间的一次性密码算法,用于增强身份验证的安全性。

    TOTP基于HMAC(Hash-based Message Authentication Code)算法和时间戳生成一次性密码。用户和服务器之间共享一个密钥,通常在初始化身份验证时交换。基于该密钥,服务器生成一个用于验证的初始值。

    在每个时间步长(通常是30秒),基于当前时间戳和共享密钥,使用HMAC算法生成一个哈希值。然后,从哈希值中提取一个固定长度的动态密码。这个动态密码在设定的时间步长内有效,之后会自动失效。

    用户在进行身份验证时,需要输入当前时间步长内生成的动态密码。服务器会使用相同的算法和共享密钥,验证用户提供的密码是否匹配。由于动态密码在时间步长过期后就会失效,即使被截获,也无法在下一个时间步长内重复使用。

    TOTP广泛应用于双因素身份验证(2FA)和多因素身份验证(MFA)的实现中。通过结合用户的密码和每次生成的动态密码,TOTP提供了一层额外的安全保护,有效降低了密码被盗用或猜测的风险。

    常见的TOTP应用包括Google Authenticator和Authy等身份验证应用程序,它们生成基于TOTP算法的动态密码,并与用户的在线账户相绑定,提供更安全的登录方式。

    说白了,就是一个带生命周期的密钥,30秒之后这个密钥就会过期,客户端和服务端共享一个密钥,通过HMAC算法来验证密钥的合法性。

    TOTP算法实现(Python3.10)

    首先在服务端应该先生成一个密钥,该密钥在客户端和认证服务器之间共享。密钥可以是字符串,但Github官方把该密钥弄成了二维码,以方便用户在移动端扫码验证,打开Github账户,选择设置-》两步验证:

    点击绿色按钮,选择开启两步验证。

    此时系统会自动生成一个二维码,这就是我们共享的密钥:

    该密钥的字符串形式可以通过点击setup key超链接来获取。

    拿到系统密钥之后,我们安装基于Python的TOTP库:

    pip3 install pyotp
    
    • 1

    随后编写代码生成当前时序的验证码:

    import pyotp  
    import time  
      
    # 设置服务端密钥  
    secret_key = "Github服务端生成的密钥(即二维码)"  
      
    # 使用密钥和时间间隔(默认为 30 秒)创建一个 TOTP 对象  
    totp = pyotp.TOTP(secret_key)  
      
    # 生成当前的 OTP  
    current_otp = totp.now()  
    print(f"当前OTP: {current_otp}")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    运行结果:

    python -u "d:\jiyun\积云\boo3_public\test_totp.py"  
    当前OTP: 809888
    
    • 1
    • 2

    可以看到根据密钥我们生成了30秒以内有效期的验证码,随后将该验证码填入页面中的Verify the code from the app文本框即可。简单方便,并不需要移动端的参与。

    Golang1.21实现TOTP算法

    如果客户端的语言是Golang,也可以轻松实现TOTP算法,首先确保本机安装Golang1.18以上的版本,这里我们使用的是最新的Golang1.21:

    PS C:\Users\zcxey> go version  
    go version go1.21.1 windows/amd64
    
    • 1
    • 2

    随后通过go get安装对应的totp包:

    go get github.com/pquerna/otp  
    go get github.com/pquerna/otp/totp
    
    • 1
    • 2

    接着编写入口代码main.go文件:

    package main  
      
    import (  
    	"encoding/base32"  
    	"fmt"  
    	"time"  
      
    	"github.com/pquerna/otp"  
    	"github.com/pquerna/otp/totp"  
    )  
      
    // Demo function, not used in main  
    // Generates Passcode using a UTF-8 (not base32) secret and custom parameters  
    func GeneratePassCode(utf8string string) string {  
    	secret := base32.StdEncoding.EncodeToString([]byte(utf8string))  
    	passcode, err := totp.GenerateCodeCustom(secret, time.Now(), totp.ValidateOpts{  
    		Period:    30,  
    		Skew:      1,  
    		Digits:    otp.DigitsSix,  
    		Algorithm: otp.AlgorithmSHA512,  
    	})  
    	if err != nil {  
    		panic(err)  
    	}  
    	return passcode  
    }  
      
    func main() {  
      
    	passcode := GeneratePassCode("Github官方生成的密钥")  
      
    	fmt.Print(passcode)  
      
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    这里通过GeneratePassCode函数来生成验证码,默认有效期同样是30秒,算法基于otp.AlgorithmSHA512。

    运行结果:

    go run "d:\jiyun\积云\boo3_public\main.go"  
    692540
    
    • 1
    • 2

    随后同样将该验证码填入页面中的Verify the code from the app文本框即可。和Python不同的是,Golang直接编译好以后可以在任意平台直接运行,理论上要比Python要方便的多。

    结语

    总体而言,GitHub的双因子登录提供了更高的账户安全性,保护用户免受未经授权的访问和潜在的数据泄露。它是一种简单而有效的安全措施,值得用户采取以保护他们的GitHub账户和相关代码资产,不过话说回来,Github官方力推收费的1Password软件,应该是有一些利益上的绑定,但对于会代码的我们来说,这都不算事儿。

  • 相关阅读:
    SCP命令在不同远程服务器之间发送文件(指定端口)
    javascript 基础知识点整理
    原生JS实现拖拽排序
    动态库静态库对比
    机器人中的数值优化(八)——拟牛顿方法(上)
    React组件之间的通信方式总结(上)
    OpenHarmony后代组件双向同步,跨层级传递:@Provide装饰器和@Consume装饰器
    shell脚本——正则表达式
    Web(一)Web前端开发概述
    深入了解JS中for...in和for...of的区别
  • 原文地址:https://blog.csdn.net/zcxey2911/article/details/133417344