go版本,google-authenticator动态口令算法,二次安全校验

server/2024/11/20 8:40:19/

go版本,google-authenticator动态口令算法,二次安全校验

登录安全二次校验,可以有效的提升账户安全等级,目前常用的方法:手机短信二次校验、动态口令
本文介绍google-authenticator动态口口令算法,以及加解密以及二维码生成
动态安全口令,秘钥一般通过二维码少吗形式自动获得

系统身份认证快速升级:
活体人脸实名认证H5版,让您的系统身份认证更人性化

一、生成和解密秘钥

随机生成字符串,加密转成base32,encoding.go

package mainimport ("crypto/rand""fmt""log""strconv""strings"
)// Base32 字符表 33个字符
var Base32Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567="// SourceCreatSecret 生成秘钥:长度在16~128之间,从允许的base32字符中随机选择。
func SourceCreatSecret(secretLen int) string {// 有效的秘密长度是80到640位:16*5~128*5,base32每个5位一个字节if secretLen<16 || secretLen >128{log.Fatalln("随机字符长度异常:16~128")}randomBytes := make([]byte, secretLen)_, err := rand.Read(randomBytes)if err != nil {log.Fatalln("随机字符异常:", err.Error())}var secret stringfor _, i := range randomBytes {secret += string(Base32Chars[i&31])}return secret
}// SourceDecodeSecret 解码 Base32 编码的字符串
func SourceDecodeSecret(secret string) string {padChar := Base32Chars[32:]paddingCharCount := strings.Count(secret, padChar)allowedValues := []int{6, 4, 3, 1, 0}if !InArray(paddingCharCount, allowedValues) {log.Fatalln("填充字符数量错误:", paddingCharCount)}// 校验秘钥带的填充字符数量,与实际应该填充的字符是否相同for i := 0; i < 4; i++ {if paddingCharCount == allowedValues[i] {if secret[strings.Index(secret, padChar):] != strings.Repeat(padChar, allowedValues[i]) {log.Fatalln("填充字符错误:", secret[strings.Index(secret, padChar):])}}}secret = strings.Replace(secret, "=", "", -1)// 每 8 个字符进行分组解码var strs []bytefor i := 0; i < len(secret); i += 8 {var x string// 查看当前字符是否是合法字符if !strings.Contains(Base32Chars, string(secret[i])) {log.Fatalln("秘钥包含非法字符:", string(secret[i]))}// 将当前的8个字符转成二进制、拼接在一起,空值使用0for j := 0; j < 8; j++ {// 将字符转成二进制if len(secret) > (i + j) {x += fmt.Sprintf("%05b", strings.Index(Base32Chars, string(secret[i+j])))} else {x += fmt.Sprintf("%05b", 0)}}l := len(x)for i := 0; i < l; i += 8 {end := i + 8if end > l {end = l}}for i := 0; i < len(x)/8; i++ {it, _ := strconv.ParseInt(x[i*8:(i+1)*8], 2, 64)strs = append(strs, uint8(it))}}return string(strs)
}

2、生成动态口令和校验

动态口令生成和校验

package mainimport ("crypto/hmac""crypto/sha1""encoding/binary""fmt""time"
)func InArray(check int, origin []int) bool {var exits boolfor _, i := range origin {if i == check {exits = truebreak}}return exits
}// getCode 根据解密的秘钥,获取动态口令码
func GetCode(key string, timeSlice int) string {var code stringtime := make([]byte, 8)binary.BigEndian.PutUint64(time, uint64(timeSlice))h := hmac.New(sha1.New, []byte(key))h.Write(time)hm := h.Sum(nil)fmt.Println()// 计算偏移量offset := hm[len(hm)-1] & 0x0FhashPart := hm[offset : offset+4]// 将哈希值解包为整数value := binary.BigEndian.Uint32(hashPart) & 0x7FFFFFFFmodulo := uint32(1000000)code = fmt.Sprintf("%06d", value%modulo)return code
}// VerifyCode 动态码校验,其实就是生成当前时间戳,前后30秒的动态码,与输入的动态码进行对比;discrepancy:1:前后误差30秒;2:前后误差1分钟
func VerifyCode(secret, code string, discrepancy, currentTimeSlice int) bool {if currentTimeSlice <= 0 {currentTimeSlice = int(time.Now().Unix() / 30)}if discrepancy < 1 {discrepancy = 1}if len(code) != 6 {return false}for i := -discrepancy; i <= discrepancy; i++ {calculatedCode := GetCode(secret, currentTimeSlice+i)if calculatedCode == code {return true}}return false
}// GetQrCode 生成二维码:secret(秘钥) ,accountName(用户名:必填), issuer(系统名称),appKey(聚合数据接口key)
func GetQrCode(secret, accountName, issuer, appKey string) string {// otpauth://totp/Issuer:AccountName?secret=Base32Secret&issuer=IssuerNameurlEncode := url.QueryEscape(fmt.Sprintf("otpauth://totp/%s?secret=%s", accountName, secret))if issuer != "" {urlEncode += url.QueryEscape("&issuer=" + url.QueryEscape(issuer))}return fmt.Sprintf("https://apis.juhe.cn/qrcode/api?key=%s&text=%s&w=200&h=200&el=m&type=2", appKey, urlEncode)
}

三、使用

使用二维码生成,需要申请二维码生成

package mainimport ("fmt""math""time"
)var (secret stringkey    stringtimes  intcode   stringchecked boolappKey string
)func main() {times = int(math.Floor(float64(time.Now().Unix() / 30)))// 生成秘钥secret = google2fa.SourceCreatSecret(101)fmt.Println(GetQrCode(secret, "juhe007", "聚合数据", appKey))// https://apis.juhe.cn/qrcode/api?key=883d38*******a6955df906ca&text=otpauth%3A%2F%2Ftotp%2Fjuhe007%3Fsecret%3D7GAKYUQRJDBZBAPTZO6RV7JHQBDWBBGHLGYDD5EFG3UOOGTWKWQYK5UOBPZCA2IS7B64MME5KBFT2W63ERZ6GJCNN23K67TNWBTWB%26issuer%3D%25E8%2581%259A%25E5%2590%2588%25E6%2595%25B0%25E6%258D%25AE&w=200&h=200&el=m&type=2fmt.Println(secret)// 解密生成的秘钥key = google2fa.SourceDecodeSecret(secret)// 根据秘钥和当前时间片生成动态码code = google2fa.GetCode(key, times)fmt.Println(key)fmt.Println("========================:动态口令验证=202:", code, "==", times, "==")// 校验一分钟(2)误差的动态码checked=google2fa.VerifyCode(key, code, 2, 0)fmt.Println(checked)fmt.Println()}

http://www.ppmy.cn/server/143430.html

相关文章

sql中的聚合函数

SQL中的聚合函数用于对表中的数据进行汇总计算&#xff0c;常用来生成统计信息&#xff0c;例如总和、平均值、最大值、最小值等。它们通常与GROUP BY子句一起使用&#xff0c;以对数据分组后再计算聚合结果。 以下是SQL中常用的聚合函数及其详细讲解&#xff1a; 1. COUNT( )…

【原创】如何备份和还原Ubuntu系统,非常详细!!

前言 我在虚拟机装了一个xfce4的Ubuntu桌面版&#xff0c;外加输入法、IDEA等&#xff0c;我想将这个虚拟机里的系统直接搬到物理机中&#xff0c;那我可以省的再重新装一遍、配置xfce4桌面、修改一堆快捷键还有配置idea了&#xff0c;那直接说干就干。 本教程基于Ubuntu24.0…

网络百问百答(一)

什么是链接&#xff1f; 链接是指两个设备之间的连接&#xff0c;它包括用于一个设备能够与另一个设备通信的电缆类型和协议。OSI参考模型的层次是什么&#xff1f; 有7个OSI层&#xff1a;物理层&#xff0c;数据链路层&#xff0c;网络层&#xff0c;传输层&#xff0c;会话层…

在ubuntu下将virtualbox虚拟机的磁盘重设大小的方法

1、VBoxManage modifyhd /home/beyond/xxx.vdi --resize 20480 {20480(单位&#xff1a;M)是你要扩容之后的总大小&#xff0c;/home/beyond 是你存放 vdi的目录&#xff0c;在执行这个之前&#xff0c;要先把虚拟机里的电脑关机&#xff0c;执行成功后&#xff0c;会看到如下图…

如何下载Instagram并了解其网络IP地址:完整指南

Instagram已经成为全球最受欢迎的社交媒体平台之一&#xff0c;不仅让用户分享生活照片和视频&#xff0c;还为品牌和创作者提供了重要的营销工具。无论您是初次接触Instagram&#xff0c;还是想要深入了解其背后的网络架构和技术细节&#xff0c;本文将为您提供一个全面的指南…

全新UI H5购物商城系统存在前台任意文件上传漏洞

免责声明: 本文旨在提供有关特定漏洞的深入信息,帮助用户充分了解潜在的安全风险。发布此信息的目的在于提升网络安全意识和推动技术进步,未经授权访问系统、网络或应用程序,可能会导致法律责任或严重后果。因此,作者不对读者基于本文内容所采取的任何行为承担责任。读者在…

递归算法专题一>合并两个有序数组

题目&#xff1a; 解析&#xff1a; 方法一&#xff1a; public ListNode mergeTwoLists(ListNode list1, ListNode list2) {//headH用来返回链表ListNode headH new ListNode(-1);ListNode tmp headH;//遍历两个链表while(list1 ! null && list2 ! null) {if(list…

数据结构(第三章)顺序表和链表

1.线性表 2.顺序表 3.链表 4.顺序表和链表的区别和联系 一、线性表 概念&#xff1a;线性表是N个具有相同特性的数据元素的有限序列。线性表是一种在实际中应用广泛的数据结构。 常见的线性表&#xff1a;顺序表&#xff0c;链表&#xff0c;栈 &#xff0c; 队列、字符串等…