Browse Source

add agora token gen

Muninn 5 years ago
parent
commit
78e4dc0c07
1 changed files with 412 additions and 0 deletions
  1. 412
    0
      agora.go

+ 412
- 0
agora.go View File

@@ -0,0 +1,412 @@
1
+package agora
2
+
3
+import (
4
+	"bytes"
5
+	"crypto/hmac"
6
+	"crypto/sha256"
7
+	"encoding/base64"
8
+	"encoding/binary"
9
+	"encoding/hex"
10
+	"fmt"
11
+	"hash/crc32"
12
+	"io"
13
+	"math/rand"
14
+	"sort"
15
+	"time"
16
+)
17
+
18
+// 这里引用了agoda给出的demo,写的并不好,若他们将来有sdk,可以替换成sdk
19
+
20
+// Role 角色
21
+type Role uint16
22
+
23
+// Roles
24
+const (
25
+	Role_Attendee   = 1
26
+	Role_Publisher  = 2
27
+	Role_Subscriber = 3
28
+	Role_Admin      = 4
29
+)
30
+
31
+var attendeePrivileges = map[uint16]uint32{
32
+	KJoinChannel:        0,
33
+	KPublishAudioStream: 0,
34
+	KPublishVideoStream: 0,
35
+	KPublishDataStream:  0,
36
+}
37
+var publisherPrivileges = map[uint16]uint32{
38
+	KJoinChannel:              0,
39
+	KPublishAudioStream:       0,
40
+	KPublishVideoStream:       0,
41
+	KPublishDataStream:        0,
42
+	KPublishAudiocdn:          0,
43
+	KPublishVideoCdn:          0,
44
+	KInvitePublishAudioStream: 0,
45
+	KInvitePublishVideoStream: 0,
46
+	KInvitePublishDataStream:  0,
47
+}
48
+
49
+var subscriberPrivileges = map[uint16]uint32{
50
+	KJoinChannel:               0,
51
+	KRequestPublishAudioStream: 0,
52
+	KRequestPublishVideoStream: 0,
53
+	KRequestPublishDataStream:  0,
54
+}
55
+
56
+var adminPrivileges = map[uint16]uint32{
57
+	KJoinChannel:         0,
58
+	KPublishAudioStream:  0,
59
+	KPublishVideoStream:  0,
60
+	KPublishDataStream:   0,
61
+	KAdministrateChannel: 0,
62
+}
63
+
64
+// RolePrivileges 角色权限
65
+var RolePrivileges = map[uint16](map[uint16]uint32){
66
+	Role_Attendee:   attendeePrivileges,
67
+	Role_Publisher:  publisherPrivileges,
68
+	Role_Subscriber: subscriberPrivileges,
69
+	Role_Admin:      adminPrivileges,
70
+}
71
+
72
+// SimpleTokenBuilder
73
+type SimpleTokenBuilder struct {
74
+	Token AccessToken
75
+}
76
+
77
+func CreateSimpleTokenBuilder(appID, appCertificate, channelName string, uid uint32) SimpleTokenBuilder {
78
+	return SimpleTokenBuilder{CreateAccessToken(appID, appCertificate, channelName, uid)}
79
+}
80
+
81
+func (builder *SimpleTokenBuilder) InitPrivileges(role Role) {
82
+	rolepri := uint16(role)
83
+	for key, value := range RolePrivileges[rolepri] {
84
+		builder.Token.Message[key] = value
85
+	}
86
+}
87
+
88
+func (builder *SimpleTokenBuilder) InitTokenBuilder(originToken string) bool {
89
+	return builder.Token.FromString(originToken)
90
+}
91
+
92
+func (builder *SimpleTokenBuilder) SetPrivilege(privilege Privileges, expireTimestamp uint32) {
93
+	pri := uint16(privilege)
94
+	builder.Token.Message[pri] = expireTimestamp
95
+}
96
+
97
+func (builder *SimpleTokenBuilder) RemovePrivilege(privilege Privileges) {
98
+	pri := uint16(privilege)
99
+	delete(builder.Token.Message, pri)
100
+}
101
+
102
+func (builder *SimpleTokenBuilder) BuildToken() (string, error) {
103
+	return builder.Token.Build()
104
+}
105
+
106
+// 官方的 AccessToken文件
107
+const VERSION_LENGTH = 3
108
+const APP_ID_LENGTH = 32
109
+
110
+type Privileges uint16
111
+
112
+const (
113
+	KJoinChannel        = 1
114
+	KPublishAudioStream = 2
115
+	KPublishVideoStream = 3
116
+	KPublishDataStream  = 4
117
+
118
+	KPublishAudiocdn           = 5
119
+	KPublishVideoCdn           = 6
120
+	KRequestPublishAudioStream = 7
121
+	KRequestPublishVideoStream = 8
122
+	KRequestPublishDataStream  = 9
123
+	KInvitePublishAudioStream  = 10
124
+	KInvitePublishVideoStream  = 11
125
+	KInvitePublishDataStream   = 12
126
+
127
+	KAdministrateChannel = 101
128
+)
129
+
130
+type AccessToken struct {
131
+	AppID          string
132
+	AppCertificate string
133
+	ChannelName    string
134
+	UidStr         string
135
+	Ts             uint32
136
+	Salt           uint32
137
+	Message        map[uint16]uint32
138
+	Signature      string
139
+	CrcChannelName uint32
140
+	CrcUid         uint32
141
+	MsgRawContent  string
142
+}
143
+
144
+func random(min int, max int) int {
145
+	rand.Seed(time.Now().UnixNano())
146
+	return rand.Intn(max-min) + min
147
+}
148
+
149
+func panichandler() {
150
+	if r := recover(); r != nil {
151
+		fmt.Println("error: ", r)
152
+	}
153
+}
154
+
155
+func getVersion() string {
156
+	return "006"
157
+}
158
+
159
+func CreateAccessToken(appID, appCertificate, channelName string, uid uint32) AccessToken {
160
+	var uidStr string
161
+	if uid == 0 {
162
+		uidStr = ""
163
+	} else {
164
+		uidStr = fmt.Sprintf("%d", uid)
165
+	}
166
+	ts := uint32(time.Now().Unix()) + 24*3600
167
+	salt := uint32(random(1, 99999999))
168
+	message := make(map[uint16]uint32)
169
+	return AccessToken{appID, appCertificate, channelName, uidStr, ts, salt, message, "", 0, 0, ""}
170
+}
171
+
172
+func (token *AccessToken) FromString(originToken string) bool {
173
+	defer panichandler()
174
+
175
+	dk6version := getVersion()
176
+	originVersion := originToken[:VERSION_LENGTH]
177
+	if originVersion != dk6version {
178
+		return false
179
+	}
180
+
181
+	//originAppID := originToken[VERSION_LENGTH:(VERSION_LENGTH + APP_ID_LENGTH)]
182
+	originContent := originToken[(VERSION_LENGTH + APP_ID_LENGTH):]
183
+	originContentDecoded, err := base64.StdEncoding.DecodeString(originContent)
184
+	if err != nil {
185
+		return false
186
+	}
187
+
188
+	signature_, crc_channel_name_, crc_uid_, msg_raw_content_, err := unPackContent(originContentDecoded)
189
+	if err != nil {
190
+		return false
191
+	}
192
+	token.Signature = signature_
193
+	token.CrcChannelName = crc_channel_name_
194
+	token.CrcUid = crc_uid_
195
+	token.MsgRawContent = msg_raw_content_
196
+
197
+	salt_, ts_, messages_, err := unPackMessages(token.MsgRawContent)
198
+	if err != nil {
199
+		return false
200
+	}
201
+	token.Salt = salt_
202
+	token.Ts = ts_
203
+	token.Message = messages_
204
+
205
+	return true
206
+}
207
+
208
+func (token *AccessToken) AddPrivilege(privilege Privileges, expireTimestamp uint32) {
209
+	pri := uint16(privilege)
210
+	token.Message[pri] = expireTimestamp
211
+}
212
+
213
+func (token *AccessToken) Build() (string, error) {
214
+	ret := ""
215
+	version := getVersion()
216
+
217
+	buf_m := new(bytes.Buffer)
218
+	if err := packUint32(buf_m, token.Salt); err != nil {
219
+		return ret, err
220
+	}
221
+	if err := packUint32(buf_m, token.Ts); err != nil {
222
+		return ret, err
223
+	}
224
+	if err := packMapUint32(buf_m, token.Message); err != nil {
225
+		return ret, err
226
+	}
227
+	bytes_m := buf_m.Bytes()
228
+
229
+	buf_val := new(bytes.Buffer)
230
+	val := token.AppID + token.ChannelName + token.UidStr
231
+	buf_val.Write([]byte(val))
232
+	buf_val.Write(bytes_m)
233
+	bytes_val := buf_val.Bytes()
234
+
235
+	buf_sig := hmac.New(sha256.New, []byte(token.AppCertificate))
236
+	buf_sig.Write(bytes_val)
237
+	bytes_sig := buf_sig.Sum(nil)
238
+
239
+	crc32q := crc32.MakeTable(0xedb88320)
240
+	crc_channel_name := crc32.Checksum([]byte(token.ChannelName), crc32q)
241
+	crc_uid := crc32.Checksum([]byte(token.UidStr), crc32q)
242
+
243
+	buf_content := new(bytes.Buffer)
244
+	if err := packString(buf_content, string(bytes_sig[:])); err != nil {
245
+		return ret, err
246
+	}
247
+	if err := packUint32(buf_content, crc_channel_name); err != nil {
248
+		return ret, err
249
+	}
250
+	if err := packUint32(buf_content, crc_uid); err != nil {
251
+		return ret, err
252
+	}
253
+	if err := packString(buf_content, string(bytes_m[:])); err != nil {
254
+		return ret, err
255
+	}
256
+	bytes_content := buf_content.Bytes()
257
+
258
+	ret = version + token.AppID + base64.StdEncoding.EncodeToString(bytes_content)
259
+	return ret, nil
260
+}
261
+
262
+func packUint16(w io.Writer, n uint16) error {
263
+	return binary.Write(w, binary.LittleEndian, n)
264
+}
265
+
266
+func packUint32(w io.Writer, n uint32) error {
267
+	return binary.Write(w, binary.LittleEndian, n)
268
+}
269
+
270
+func packString(w io.Writer, s string) error {
271
+	err := packUint16(w, uint16(len(s)))
272
+	if err != nil {
273
+		return err
274
+	}
275
+	_, err = w.Write([]byte(s))
276
+	return err
277
+}
278
+
279
+func packHexString(w io.Writer, s string) error {
280
+	b, err := hex.DecodeString(s)
281
+	if err != nil {
282
+		return err
283
+	}
284
+	return packString(w, string(b))
285
+}
286
+
287
+func packExtra(w io.Writer, extra map[uint16]string) error {
288
+	keys := []int{}
289
+	if err := packUint16(w, uint16(len(extra))); err != nil {
290
+		return err
291
+	}
292
+	for k := range extra {
293
+		keys = append(keys, int(k))
294
+	}
295
+	//should sorted keys
296
+	sort.Ints(keys)
297
+
298
+	for _, k := range keys {
299
+		v := extra[uint16(k)]
300
+		if err := packUint16(w, uint16(k)); err != nil {
301
+			return err
302
+		}
303
+		if err := packString(w, v); err != nil {
304
+			return err
305
+		}
306
+	}
307
+	return nil
308
+}
309
+
310
+func packMapUint32(w io.Writer, extra map[uint16]uint32) error {
311
+	keys := []int{}
312
+	if err := packUint16(w, uint16(len(extra))); err != nil {
313
+		return err
314
+	}
315
+	for k := range extra {
316
+		keys = append(keys, int(k))
317
+	}
318
+	//should sorted keys
319
+	sort.Ints(keys)
320
+
321
+	for _, k := range keys {
322
+		v := extra[uint16(k)]
323
+		if err := packUint16(w, uint16(k)); err != nil {
324
+			return err
325
+		}
326
+		if err := packUint32(w, v); err != nil {
327
+			return err
328
+		}
329
+	}
330
+	return nil
331
+}
332
+
333
+func unPackUint16(r io.Reader) (uint16, error) {
334
+	var n uint16
335
+	err := binary.Read(r, binary.LittleEndian, &n)
336
+	return n, err
337
+}
338
+
339
+func unPackUint32(r io.Reader) (uint32, error) {
340
+	var n uint32
341
+	err := binary.Read(r, binary.LittleEndian, &n)
342
+	return n, err
343
+}
344
+
345
+func unPackString(r io.Reader) (string, error) {
346
+	n, err := unPackUint16(r)
347
+	if err != nil {
348
+		return "", err
349
+	}
350
+
351
+	buf := make([]byte, n)
352
+	r.Read(buf)
353
+	s := string(buf[:])
354
+	return s, err
355
+}
356
+
357
+func unPackContent(buff []byte) (string, uint32, uint32, string, error) {
358
+	in := bytes.NewReader(buff)
359
+	sig, err := unPackString(in)
360
+	if err != nil {
361
+		return "", 0, 0, "", err
362
+	}
363
+
364
+	crc_channel_name, err := unPackUint32(in)
365
+	if err != nil {
366
+		return "", 0, 0, "", err
367
+	}
368
+	crc_uid, err := unPackUint32(in)
369
+	if err != nil {
370
+		return "", 0, 0, "", err
371
+	}
372
+	m, err := unPackString(in)
373
+	if err != nil {
374
+		return "", 0, 0, "", err
375
+	}
376
+
377
+	return sig, crc_channel_name, crc_uid, m, nil
378
+}
379
+
380
+func unPackMessages(msg_str string) (uint32, uint32, map[uint16]uint32, error) {
381
+	msg_map := make(map[uint16]uint32)
382
+
383
+	msg_byte := []byte(msg_str)
384
+	in := bytes.NewReader(msg_byte)
385
+
386
+	salt, err := unPackUint32(in)
387
+	if err != nil {
388
+		return 0, 0, msg_map, err
389
+	}
390
+	ts, err := unPackUint32(in)
391
+	if err != nil {
392
+		return 0, 0, msg_map, err
393
+	}
394
+
395
+	len, err := unPackUint16(in)
396
+	if err != nil {
397
+		return 0, 0, msg_map, err
398
+	}
399
+	for i := uint16(0); i < len; i++ {
400
+		key, err := unPackUint16(in)
401
+		if err != nil {
402
+			return 0, 0, msg_map, err
403
+		}
404
+		value, err := unPackUint32(in)
405
+		if err != nil {
406
+			return 0, 0, msg_map, err
407
+		}
408
+		msg_map[key] = value
409
+	}
410
+
411
+	return salt, ts, msg_map, nil
412
+}