-
Notifications
You must be signed in to change notification settings - Fork 65
/
totp.go
83 lines (67 loc) · 1.9 KB
/
totp.go
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package gotp
import "time"
// time-based OTP counters.
type TOTP struct {
OTP
interval int
}
func NewTOTP(secret string, digits, interval int, hasher *Hasher) *TOTP {
otp := NewOTP(secret, digits, hasher)
return &TOTP{OTP: otp, interval: interval}
}
func NewDefaultTOTP(secret string) *TOTP {
return NewTOTP(secret, 6, 30, nil)
}
// Generate time OTP of given timestamp
func (t *TOTP) At(timestamp int64) string {
return t.generateOTP(t.timecode(timestamp))
}
func (t *TOTP) AtTime(timestamp time.Time) string {
return t.At(timestamp.Unix())
}
// Generate the current time OTP
func (t *TOTP) Now() string {
return t.At(currentTimestamp())
}
// Generate the current time OTP and expiration time
func (t *TOTP) NowWithExpiration() (string, int64) {
timeCodeInt64 := t.timecode(currentTimestamp())
expirationTime := (timeCodeInt64 + 1) * int64(t.interval)
return t.generateOTP(timeCodeInt64), expirationTime
}
/*
Verify OTP.
params:
otp: the OTP to check against
timestamp: time to check OTP at
*/
func (t *TOTP) Verify(otp string, timestamp int64) bool {
return otp == t.At(timestamp)
}
func (t *TOTP) VerifyTime(otp string, timestamp time.Time) bool {
return t.Verify(otp, timestamp.Unix())
}
/*
Returns the provisioning URI for the OTP.
This can then be encoded in a QR Code and used to provision an OTP app like Google Authenticator.
See also:
https://github.com/google/google-authenticator/wiki/Key-Uri-Format
params:
accountName: name of the account
issuerName: the name of the OTP issuer; this will be the organization title of the OTP entry in Authenticator
returns: provisioning URI
*/
func (t *TOTP) ProvisioningUri(accountName, issuerName string) string {
return BuildUri(
OtpTypeTotp,
t.secret,
accountName,
issuerName,
t.hasher.HashName,
0,
t.digits,
t.interval)
}
func (t *TOTP) timecode(timestamp int64) int64 {
return timestamp / int64(t.interval)
}