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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
//get_token.go
package main
import (
"crypto/hmac"
"crypto/sha1"
"encoding/base32"
"encoding/binary"
"flag"
"fmt"
"time"
)
type TfActorAuthenticator struct {
Issuer string
Algorithm string
Period int64
Digits int
}
// NewGoogleAuthenticator google双因子认证
func NewGoogleAuthenticator(issuer string) *TfActorAuthenticator {
return &TfActorAuthenticator{
Issuer: issuer,
Algorithm: "SHA1",
Period: 30,
Digits: 6,
}
}
func (tfa *TfActorAuthenticator) TotpString(secret string) string {
// base32编码秘钥:K
key := make([]byte, base32.StdEncoding.DecodedLen(len(secret)))
base32.StdEncoding.Decode(key, []byte(secret))
// 根据当前时间计算随机数:C
message := make([]byte, 8)
binary.BigEndian.PutUint64(message, uint64(time.Now().Unix()/tfa.Period))
// 使用sha1对K和C做hmac得到20个字节的密串:HMAC-SHA-1(K, C)
hmacsha1 := hmac.New(sha1.New, key)
hmacsha1.Write(message)
hash := hmacsha1.Sum([]byte{})
// 从20个字节的密串取最后一个字节,取该字节的低四位
offset := hash[len(hash)-1] & 0xF
truncatedHash := hash[offset : offset+4]
// 按照大端方式组成一个整数
bin := (binary.BigEndian.Uint32(truncatedHash) & 0x7FFFFFFF) % 1000000
// 将数字转成特定长度字符串,不够的补0
return fmt.Sprintf(`%0*d`, tfa.Digits, bin)
}
var secret = flag.String("secret", "your default secret", "the tfa`s secret")
func main() {
flag.Parse()
authClient := NewGoogleAuthenticator("")
token := authClient.TotpString(*secret)
fmt.Println("your_password" + token)
}
|