-
Notifications
You must be signed in to change notification settings - Fork 16
/
gate.go
61 lines (52 loc) · 1.21 KB
/
gate.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
package main
import (
"encoding/hex"
"errors"
"github.com/conformal/yubikey"
)
const (
OK = "OK"
REPLAYED_OTP = "REPLAYED_OTP"
MISSING_PARAMETER = "MISSING_PARAMETER"
BAD_OTP = "BAD_OTP"
BAD_SIGNATURE = "BAD_SIGNATURE"
NO_SUCH_CLIENT = "NO_SUCH_CLIENT"
)
func Gate(key *Key, otp string) (*Key, error) {
priv, err := getSecretKey(key.Secret)
if err != nil {
return nil, err
}
token, err := getToken(otp, priv)
if err != nil {
return nil, errors.New(BAD_OTP)
}
if token.Ctr < uint16(key.Counter) {
return nil, errors.New(REPLAYED_OTP)
} else if token.Ctr == uint16(key.Counter) && token.Use <= uint8(key.Session) {
return nil, errors.New(REPLAYED_OTP)
} else {
key.Counter = int(token.Ctr)
key.Session = int(token.Use)
}
return key, nil
}
func getSecretKey(key string) (*yubikey.Key, error) {
b, err := hex.DecodeString(key)
if err != nil {
return nil, err
}
priv := yubikey.NewKey(b)
return &priv, nil
}
func getToken(otpString string, priv *yubikey.Key) (*yubikey.Token, error) {
_, otp, err := yubikey.ParseOTPString(otpString)
if err != nil {
return nil, err
}
t, err := otp.Parse(*priv)
if err != nil {
return nil, err
}
return t, nil
}