-
Notifications
You must be signed in to change notification settings - Fork 1
/
client_id.go
95 lines (78 loc) · 2.72 KB
/
client_id.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
package main
import (
"encoding/base64"
"errors"
"fmt"
"math"
"regexp"
"strconv"
"strings"
"time"
)
const (
clientIDTypeOther uint8 = 0
clientIDTypeStd uint8 = 1
clientIDTypeAmp uint8 = 2
)
const minimumTime = 1640995200 // 2022-01-01 00:00:00
var cidStandardRegex = regexp.MustCompile(`^(?P<InitTime>[0-9]{9,11}):(?P<SessionTime>[0-9]{9,11}):(?P<Random>[a-z0-9]{16})$`)
type clientID struct {
Valid bool `json:"v"`
CidType uint8 `json:"t"`
CidUserChecksum string `json:"uc"`
CidSessionChecksum string `json:"sc"`
CidStdInitTime int64 `json:"it"`
CidStdSessionTime int64 `json:"st"`
}
func clientIDNoneSTD(parts []string, clientType uint8) clientID {
if clientType == clientIDTypeStd {
panic("none std must type none std")
}
timestamp := time.Now().Unix()
sessionEach30Minutes := math.Floor(float64(timestamp) / 1800)
sessionEach30MinutesString := fmt.Sprint(sessionEach30Minutes)
userChecksum := checksum(strings.Join(parts, ":"))
cid := clientID{
Valid: true,
CidType: clientType,
CidUserChecksum: userChecksum,
CidSessionChecksum: checksum(userChecksum + ":" + sessionEach30MinutesString),
CidStdInitTime: 0,
CidStdSessionTime: 0,
}
return cid
}
func clientIDStandardParser(cidString string) (clientID, error) {
cidInvalid := clientID{
Valid: false,
}
decodedByte, err := base64.StdEncoding.DecodeString(cidString)
if err != nil {
return cidInvalid, err
}
decoded := string(decodedByte)
if ok := cidStandardRegex.MatchString(decoded); ok {
matched := cidStandardRegex.FindStringSubmatch(decoded)
initTime, err := strconv.ParseInt(matched[1], 10, 64)
if err != nil || initTime < minimumTime || initTime > time.Now().Add(time.Hour).Unix() {
return cidInvalid, errors.New("invalid client identifier init time")
}
sessionTime, err := strconv.ParseInt(matched[2], 10, 64)
if err != nil || sessionTime < initTime || sessionTime > time.Now().Add(time.Duration(12)*time.Hour).Unix() {
return cidInvalid, errors.New("invalid client identifier session time")
}
diffSession := sessionTime - initTime
if diffSession > 86400 {
return cidInvalid, errors.New("session time must be at least 86400 with initialize time and past 24 hours")
}
cidValid := clientID{}
cidValid.Valid = true
cidValid.CidType = clientIDTypeStd
cidValid.CidStdInitTime = time.Unix(initTime, 0).Unix()
cidValid.CidStdSessionTime = time.Unix(sessionTime, 0).Unix()
cidValid.CidUserChecksum = checksum(strings.Join([]string{matched[1], matched[3]}, ":"))
cidValid.CidSessionChecksum = checksum(strings.Join([]string{matched[1], matched[2], matched[3]}, ":"))
return cidValid, nil
}
return cidInvalid, errors.New("invalid client identifier")
}