forked from shaj13/go-guardian
/
key.go
179 lines (154 loc) · 3.7 KB
/
key.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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
package otp
import (
"net/url"
"strconv"
"strings"
)
// Key represnt Uri Format for OTP
// See https://github.com/google/google-authenticator/wiki/Key-Uri-Format
type Key struct{ *url.URL }
// Type returns the type for the Key (totp, hotp).
func (k *Key) Type() Type {
return Type(k.Host)
}
// SetType vaule in key.
func (k *Key) SetType(t Type) {
k.Host = string(t)
}
// Label returns the label for the Key.
func (k *Key) Label() string {
return strings.TrimPrefix(k.Path, "/")
}
// SetLabel value in key.
func (k *Key) SetLabel(label string) {
k.Path = "/" + label
}
// Secret returns the secret for the Key.
func (k *Key) Secret() string {
return k.Query().Get("secret")
}
// SetSecret value in key.
func (k *Key) SetSecret(secret string) {
q := k.Query()
q.Set("secret", secret)
k.RawQuery = q.Encode()
}
// Digits returns the length of pin code.
func (k *Key) Digits() Digits {
str := k.Query().Get("digits")
d, err := strconv.Atoi(str)
if err != nil {
return SixDigits
}
return Digits(d)
}
// SetDigits value in key.
func (k *Key) SetDigits(d Digits) {
q := k.Query()
q.Set("digits", d.String())
k.RawQuery = q.Encode()
}
// Issuer returns a string value indicating the provider or service.
func (k *Key) Issuer() string {
return k.Query().Get("issuer")
}
// SetIssuer value in key.
func (k *Key) SetIssuer(issuer string) {
q := k.Query()
q.Set("issuer", issuer)
k.RawQuery = q.Encode()
}
// IssuerLabelPrefix returns a string value indicating the provider or service extracted from label.
func (k *Key) IssuerLabelPrefix() string {
sub := strings.Split(k.Label(), ":")
if len(sub) == 2 {
return sub[0]
}
return ""
}
// AccountName returns the name of the user's account.
func (k *Key) AccountName() string {
sub := strings.Split(k.Label(), ":")
if len(sub) == 2 {
return sub[1]
}
return ""
}
// Algorithm return the hashing Algorithm name
func (k *Key) Algorithm() HashAlgorithm {
algo := k.Query().Get("algorithm")
if algo == "" {
return SHA1
}
return HashAlgorithm(algo)
}
// SetAlgorithm set hash algorithm in key.
func (k *Key) SetAlgorithm(algo HashAlgorithm) {
q := k.Query()
q.Set("algorithm", algo.String())
k.RawQuery = q.Encode()
}
// Period that a TOTP code will be valid for, in seconds. The default value is 30.
// if type not a topt the returned value is 0
func (k *Key) Period() uint64 {
if k.Type() == TOTP {
if period := k.Query().Get("period"); len(period) > 0 {
p, err := strconv.ParseUint(period, 10, 64)
if err != nil {
return 30
}
return p
}
return 30
}
return 0
}
// SetPeriod value in key.
// if type not a hopt the set operation ignored.
func (k *Key) SetPeriod(p uint64) {
if k.Type() == TOTP {
q := k.Query()
q.Set("period", strconv.FormatUint(p, 10))
k.RawQuery = q.Encode()
}
}
// Counter return initial counter value. for provisioning a key for use with HOTP
// // if type not a hopt the returned value is 0
func (k *Key) Counter() uint64 {
if k.Type() == HOTP {
if counter := k.Query().Get("counter"); len(counter) > 0 {
p, _ := strconv.ParseUint(counter, 10, 64)
return p
}
}
return 0
}
// SetCounter value in key .
// if type not a hopt the set operation ignored.
func (k *Key) SetCounter(count uint64) {
if k.Type() == HOTP {
q := k.Query()
q.Set("counter", strconv.FormatUint(count, 10))
k.RawQuery = q.Encode()
}
}
// NewKey return's new Key.
func NewKey(t Type, label, secret string) *Key {
key := new(Key)
key.URL = &url.URL{
Scheme: "otpauth",
}
key.SetType(t)
key.SetLabel(label)
key.SetSecret(secret)
return key
}
// NewKeyFromRaw return's key from raw string.
func NewKeyFromRaw(raw string) (*Key, error) {
url, err := url.Parse(raw)
if err != nil {
return nil, err
}
key := &Key{url}
return key, nil
}