-
Notifications
You must be signed in to change notification settings - Fork 0
/
api_key.go
66 lines (55 loc) · 1.61 KB
/
api_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
/******************************************************************************
*
* Description :
*
* Authentication
*
*****************************************************************************/
package main
import (
"bytes"
"crypto/hmac"
"crypto/md5"
"encoding/base64"
"log"
)
// Singned AppID. Composition:
// [1:algorithm version][4:appid][2:key sequence][1:isRoot][16:signature] = 24 bytes
// convertible to base64 without padding
// All integers are little-endian
const (
APIKEY_VERSION = 1
// APIKEY_APPID is deprecated and will be removed in the future
APIKEY_APPID = 4
APIKEY_SEQUENCE = 2
APIKEY_WHO = 1
APIKEY_SIGNATURE = 16
APIKEY_LENGTH = APIKEY_VERSION + APIKEY_APPID + APIKEY_SEQUENCE + APIKEY_WHO + APIKEY_SIGNATURE
)
// Client signature validation
// key: client's secret key
// Returns application id, key type
func checkApiKey(apikey string) (isValid, isRoot bool) {
if declen := base64.URLEncoding.DecodedLen(len(apikey)); declen != APIKEY_LENGTH {
return
}
data, err := base64.URLEncoding.DecodeString(apikey)
if err != nil {
log.Println("failed to decode.base64 appid ", err)
return
}
if data[0] != 1 {
log.Println("unknown appid signature algorithm ", data[0])
return
}
hasher := hmac.New(md5.New, globals.apiKeySalt)
hasher.Write(data[:APIKEY_VERSION+APIKEY_APPID+APIKEY_SEQUENCE+APIKEY_WHO])
check := hasher.Sum(nil)
if !bytes.Equal(data[APIKEY_VERSION+APIKEY_APPID+APIKEY_SEQUENCE+APIKEY_WHO:], check) {
log.Println("invalid apikey signature")
return
}
isRoot = (data[APIKEY_VERSION+APIKEY_APPID+APIKEY_SEQUENCE] == 1)
isValid = true
return
}