4

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

 7 months ago
source link: https://v3u.cn/a_id_319
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
基于TOTP算法的Github两步验证2FA(双因子)机制Python3.10/Golang1.21实现

    从今年(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账户,选择设置-》两步验证:

20230929120924_81767.png

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

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

20230929120930_48335.png

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

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

pip3 install pyotp

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

import pyotp
import time

# 设置服务端密钥
secret_key = "Github服务端生成的密钥(即二维码)"

# 使用密钥和时间间隔(默认为 30 秒)创建一个 TOTP 对象
totp = pyotp.TOTP(secret_key)

# 生成当前的 OTP
current_otp = totp.now()
print(f"当前OTP: {current_otp}")

    运行结果:

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

    可以看到根据密钥我们生成了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

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

go get github.com/pquerna/otp
go get github.com/pquerna/otp/totp

    接着编写入口代码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)

}

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

    运行结果:

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

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

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK