This repository has been archived by the owner on Jul 5, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 59
/
objects.go
250 lines (198 loc) · 7.21 KB
/
objects.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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
package authy
import (
"crypto/rsa"
"crypto/x509"
"encoding/base32"
"encoding/hex"
"encoding/pem"
"errors"
"fmt"
"strings"
)
// ViaMethod represents the methods available for new device registration
type ViaMethod string
const (
// ViaMethodPush to recieve an Authy app-based push notification
ViaMethodPush ViaMethod = "push"
// ViaMethodCall to receive a phone call
ViaMethodCall ViaMethod = "call"
// ViaMethodSMS to receive an SMS message
ViaMethodSMS ViaMethod = "sms"
)
// UserStatus is the response from:
// https://api.authy.com/json/users/{Country}-{Phone}/status
type UserStatus struct {
// Presumably, force device validation over HTTP rather than
// allowing a phone call or SMS. ("Over the top").
ForceOTT bool `json:"force_ott"`
// How many devices are registered to this Authy user
DevicesCount int `json:"devices_count"`
// Authy User ID
AuthyID uint64 `json:"authy_id"`
// Presumably some kind of opaque status string
Message string
// Whether this request was successful
Success bool
}
// IsActiveUser reports whether this is an an active, registered
// Authy user.
func (us UserStatus) IsActiveUser() bool {
return us.Success && us.AuthyID > 0 && us.Message == "active"
}
// StartDeviceRegistrationResponse is the response from:
// https://api.authy.com/json/users/{User_ID}/devices/registration/start
type StartDeviceRegistrationResponse struct {
// Message to display to the user upon receiving this response
Message string `json:"message"`
// The Request ID is used to poll the status of the device registration process
RequestID string `json:"request_id"`
// Purpose unclear
ApprovalPIN int `json:"approval_pin"`
// The ViaMethod
Provider string `json:"provider"`
// Whether the device registration request was accepted.
// This is distinct to the device registration being successful/complete.
Success bool `json:"success"`
}
// DeviceRegistrationStatus is the response from:
// https://api.authy.com/json/users/{User_ID}/devices/registration/{Request_ID}/status?api_key={API_Key}&locale=en-GB&signature=b54ff1b646b207ff2da50ecb9a0bc2c770a1357b04278c8dd402f835db2824f4
type DeviceRegistrationStatus struct {
// pending, accepted, rejected, ??
Status string `json:"status"`
// PIN is required to complete the device registration
PIN string `json:"pin"`
// Whether this status request was successful, distinct to whether the
// registration process is complete.
Success bool `json:"success"`
}
// CompleteDeviceRegistrationResponse is the response from:
// https://api.authy.com/json/users/16480/devices/registration/complete
type CompleteDeviceRegistrationResponse struct {
Device struct {
// The Device ID
ID uint64 `json:"id"`
// The Device Secret Seed (hex-encoded, 32-bytes). It is the TOTP
// secret that protects the authenticated endpoints.
SecretSeed string `json:"secret_seed"`
// Purpose not known.
APIKey string `json:"api_key"`
// Purpose not known, but probably whether this device is being
// re-installed.
Reinstall bool `json:"reinstall"`
} `json:"device"`
// The Authy User ID
AuthyID uint64 `json:"authy_id"`
}
// DevicePrivateKeyResponse is the response from
// https://api.authy.com/json/devices/{Device_ID}/rsa_key?api_key={API_Key}&&otp1={OTP_1}&otp2={OTP_2}&otp3={OTP_3}&device_id={DEVICE_ID}
type DevicePrivateKeyResponse struct {
Message string `json:"message"`
PrivateKey string `json:"private_key"`
Success bool `json:"success"`
}
// AsPrivateKey parses the PEM private key in PrivateKey
func (r DevicePrivateKeyResponse) AsPrivateKey() (*rsa.PrivateKey, error) {
if !r.Success || r.PrivateKey == "" {
return nil, errors.New("This response does not contain a device private key")
}
blk, _ := pem.Decode([]byte(r.PrivateKey))
pk, err := x509.ParsePKCS1PrivateKey(blk.Bytes)
if err != nil {
return nil, fmt.Errorf("Couldn't parse private key: %v", err)
}
return pk, nil
}
// AuthenticatorTokensResponse is the response from:
// https://api.authy.com/json/users/{User_ID}/authenticator_tokens?api_key={API_Key}&otp1={OTP_1}&otp2={OTP_2}&otp3={OTP_3}&device_id={Device_ID
type AuthenticatorTokensResponse struct {
// Display to user
Message string `json:"message"`
// Active encrypted authenticator token
AuthenticatorTokens []AuthenticatorToken `json:"authenticator_tokens"`
// Recently deleted, but not removed encrypted authenticator tokens
Deleted []AuthenticatorToken `json:"deleted"`
// Whether this request succeeded
Success bool `json:"success"`
}
// AuthenticatorToken is embedded in AuthenticatorTokensResponse
type AuthenticatorToken struct {
// In the Authy app, this is the visual icon type of this token
AccountType string `json:"account_type"`
// How many digits this TOTP token is
Digits int `json:"digits"`
// The encrypted TOTP seed
EncryptedSeed string `json:"encrypted_seed"`
// The number of rounds for password-based key derivation
KDFRounds int `json:"key_derivation_iterations"`
// User-nominated name for the token
Name string `json:"name"`
// Purpose not known
OriginalName string `json:"original_name"`
// Purpose not known
PasswordTimestamp uint64 `json:"password_timestamp"`
// The salt used to encrypt the EncryptedSeed
Salt string `json:"salt"`
// The ID of this token
UniqueID string `json:"unique_id"`
}
// Decrypt returns the base32-encoded seed for this TOTP token, decrypted
// by passphrase.
func (t AuthenticatorToken) Decrypt(passphrase string) (string, error) {
secret, err := decryptToken(t.KDFRounds, t.EncryptedSeed, t.Salt, passphrase)
if err != nil {
return "", err
}
buf, err := hex.DecodeString(secret)
if err != nil {
return "", err
}
return strings.ToUpper(string(buf)), nil
}
// Description returns OriginalName if not empty, otherwise Name,
// otherwise `Token-{UniqueID}`.
func (t AuthenticatorToken) Description() string {
if t.OriginalName != "" {
return t.OriginalName
}
if t.Name != "" {
return t.Name
}
return "Token-" + t.UniqueID
}
// AuthenticatorAppsResponse is the response from:
// https://api.authy.com/json/users/{User_ID}/devices/{Device_ID}/apps/sync
type AuthenticatorAppsResponse struct {
// Display to user
Message string `json:"message"`
// Active encrypted authenticator apps
AuthenticatorApps []AuthenticatorApp `json:"apps"`
// Recently deleted, but not removed encrypted authenticator apps
Deleted []AuthenticatorApp `json:"deleted"`
// Whether this request succeeded
Success bool `json:"success"`
}
// AuthenticatorApp is embedded in AuthenticatorAppsResponse
type AuthenticatorApp struct {
ID string `json:"_id"`
// Display name of the token
Name string `json:"name"`
SerialID int `json:"serial_id"`
Version int `json:"version"`
AssetsGroup string `json:"assets_group"`
AuthyID uint64 `json:"authy_id"`
// The Device Secret Seed (hex-encoded). It is the TOTP
// secret that protects the authenticated endpoints.
SecretSeed string `json:"secret_seed"`
// How many digits in the TOTP
Digits int `json:"digits"`
}
// Token produces the base32-encoded TOTP token backing
// this app. It has a period of 10.
func (a AuthenticatorApp) Token() (string, error) {
decoded, err := hex.DecodeString(a.SecretSeed)
if err != nil {
return "", err
}
encoder := base32.StdEncoding.WithPadding(base32.NoPadding)
return encoder.EncodeToString(decoded), nil
}