Skip to content

Commit 0db409a

Browse files
committed
feat: 增加校验API
1 parent 3584477 commit 0db409a

File tree

3 files changed

+159
-5
lines changed

3 files changed

+159
-5
lines changed

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
module github.com/tencentyun/tls-sig-api-v2-golang
22

33
go 1.16
4+
5+
require github.com/stretchr/testify v1.7.0

tencentyun/TLSSigAPI.go

Lines changed: 123 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"crypto/sha256"
88
"encoding/base64"
99
"encoding/json"
10+
"errors"
11+
"io/ioutil"
1012
"strconv"
1113
"time"
1214
)
@@ -20,7 +22,6 @@ import (
2022
* userid - 用户id,限制长度为32字节,只允许包含大小写英文字母(a-zA-Z)、数字(0-9)及下划线和连词符。
2123
* expire - UserSig 票据的过期时间,单位是秒,比如 86400 代表生成的 UserSig 票据在一天后就无法再使用了。
2224
*/
23-
2425
func GenUserSig(sdkappid int, key string, userid string, expire int) (string, error) {
2526
return genSig(sdkappid, key, userid, expire, nil)
2627
}
@@ -90,6 +91,7 @@ func GenPrivateMapKeyWithStringRoomID(sdkappid int, key string, userid string, e
9091
var userbuf []byte = genUserBuf(userid, sdkappid, 0, expire, privilegeMap, 0, roomStr)
9192
return genSig(sdkappid, key, userid, expire, userbuf)
9293
}
94+
9395
func genUserBuf(account string, dwSdkappid int, dwAuthID uint32,
9496
dwExpTime int, dwPrivilegeMap uint32, dwAccountType uint32, roomStr string) []byte {
9597

@@ -183,6 +185,7 @@ func genUserBuf(account string, dwSdkappid int, dwAuthID uint32,
183185

184186
return userBuf
185187
}
188+
186189
func hmacsha256(sdkappid int, key string, identifier string, currTime int64, expire int, base64UserBuf *string) string {
187190
var contentToBeSigned string
188191
contentToBeSigned = "TLS.identifier:" + identifier + "\n"
@@ -200,8 +203,7 @@ func hmacsha256(sdkappid int, key string, identifier string, currTime int64, exp
200203

201204
func genSig(sdkappid int, key string, identifier string, expire int, userbuf []byte) (string, error) {
202205
currTime := time.Now().Unix()
203-
var sigDoc map[string]interface{}
204-
sigDoc = make(map[string]interface{})
206+
sigDoc := make(map[string]interface{})
205207
sigDoc["TLS.ver"] = "2.0"
206208
sigDoc["TLS.identifier"] = identifier
207209
sigDoc["TLS.sdkappid"] = sdkappid
@@ -223,7 +225,123 @@ func genSig(sdkappid int, key string, identifier string, expire int, userbuf []b
223225

224226
var b bytes.Buffer
225227
w := zlib.NewWriter(&b)
226-
w.Write(data)
227-
w.Close()
228+
if _, err = w.Write(data); err != nil {
229+
return "", err
230+
}
231+
if err = w.Close(); err != nil {
232+
return "", err
233+
}
228234
return base64urlEncode(b.Bytes()), nil
229235
}
236+
237+
// VerifyUserSig 检验UserSig在now时间点时是否有效
238+
func VerifyUserSig(sdkappid uint64, key string, userid string, usersig string, now time.Time) error {
239+
sig, err := newUserSig(usersig)
240+
if err != nil {
241+
return err
242+
}
243+
return sig.verify(sdkappid, key, userid, now, nil)
244+
}
245+
246+
// VerifyUserSigWithBuf 检验带UserBuf的UserSig在now时间点是否有效
247+
func VerifyUserSigWithBuf(sdkappid uint64, key string, userid string, usersig string, now time.Time, userbuf []byte) error {
248+
sig, err := newUserSig(usersig)
249+
if err != nil {
250+
return err
251+
}
252+
return sig.verify(sdkappid, key, userid, now, userbuf)
253+
}
254+
255+
type userSig struct {
256+
Version string `json:"TLS.ver,omitempty"`
257+
Identifier string `json:"TLS.identifier,omitempty"`
258+
SdkAppID uint64 `json:"TLS.sdkappid,omitempty"`
259+
Expire int64 `json:"TLS.expire,omitempty"`
260+
Time int64 `json:"TLS.time,omitempty"`
261+
UserBuf []byte `json:"TLS.userbuf,omitempty"`
262+
Sig string `json:"TLS.sig,omitempty"`
263+
}
264+
265+
func newUserSig(usersig string) (userSig, error) {
266+
b, err := base64urlDecode(usersig)
267+
if err != nil {
268+
return userSig{}, err
269+
}
270+
r, err := zlib.NewReader(bytes.NewReader(b))
271+
if err != nil {
272+
return userSig{}, err
273+
}
274+
data, err := ioutil.ReadAll(r)
275+
if err != nil {
276+
return userSig{}, err
277+
}
278+
if err = r.Close(); err != nil {
279+
return userSig{}, err
280+
}
281+
var sig userSig
282+
if err = json.Unmarshal(data, &sig); err != nil {
283+
return userSig{}, nil
284+
}
285+
return sig, nil
286+
}
287+
288+
func (u userSig) verify(sdkappid uint64, key string, userid string, now time.Time, userbuf []byte) error {
289+
if sdkappid != u.SdkAppID {
290+
return ErrSdkAppIDNotMatch
291+
}
292+
if userid != u.Identifier {
293+
return ErrIdentifierNotMatch
294+
}
295+
if now.Unix() > u.Time+u.Expire {
296+
return ErrExpired
297+
}
298+
if userbuf != nil {
299+
if u.UserBuf == nil {
300+
return ErrUserBufTypeNotMatch
301+
}
302+
if !bytes.Equal(userbuf, u.UserBuf) {
303+
return ErrUserBufNotMatch
304+
}
305+
} else if u.UserBuf != nil {
306+
return ErrUserBufTypeNotMatch
307+
}
308+
if u.sign(key) != u.Sig {
309+
return ErrSigNotMatch
310+
}
311+
return nil
312+
}
313+
314+
func (u userSig) sign(key string) string {
315+
var sb bytes.Buffer
316+
sb.WriteString("TLS.identifier:")
317+
sb.WriteString(u.Identifier)
318+
sb.WriteString("\n")
319+
sb.WriteString("TLS.sdkappid:")
320+
sb.WriteString(strconv.FormatUint(u.SdkAppID, 10))
321+
sb.WriteString("\n")
322+
sb.WriteString("TLS.time:")
323+
sb.WriteString(strconv.FormatInt(u.Time, 10))
324+
sb.WriteString("\n")
325+
sb.WriteString("TLS.expire:")
326+
sb.WriteString(strconv.FormatInt(u.Expire, 10))
327+
sb.WriteString("\n")
328+
if u.UserBuf != nil {
329+
sb.WriteString("TLS.userbuf:")
330+
sb.WriteString(base64.StdEncoding.EncodeToString(u.UserBuf))
331+
sb.WriteString("\n")
332+
}
333+
334+
h := hmac.New(sha256.New, []byte(key))
335+
h.Write(sb.Bytes())
336+
return base64.StdEncoding.EncodeToString(h.Sum(nil))
337+
}
338+
339+
// 错误类型
340+
var (
341+
ErrSdkAppIDNotMatch = errors.New("sdk appid not match")
342+
ErrIdentifierNotMatch = errors.New("identifier not match")
343+
ErrExpired = errors.New("expired")
344+
ErrUserBufTypeNotMatch = errors.New("userbuf type not match")
345+
ErrUserBufNotMatch = errors.New("userbuf not match")
346+
ErrSigNotMatch = errors.New("sig not match")
347+
)

tencentyun/TLSSigAPI_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package tencentyun
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func TestGenAndVerify(t *testing.T) {
12+
// 生成签名
13+
now := time.Now()
14+
sig, err := GenUserSig(1, "2", "3", 4)
15+
require.NoError(t, err)
16+
bufSig, err := GenUserSigWithBuf(1, "2", "3", 4, []byte{5})
17+
require.NoError(t, err)
18+
19+
// 验证签名
20+
assert.NoError(t, VerifyUserSig(1, "2", "3", sig, now))
21+
assert.Equal(t, ErrExpired, VerifyUserSig(1, "2", "3", sig, now.Add(time.Hour)))
22+
assert.Equal(t, ErrSdkAppIDNotMatch, VerifyUserSig(2, "2", "3", sig, now))
23+
assert.Equal(t, ErrIdentifierNotMatch, VerifyUserSig(1, "2", "4", sig, now))
24+
assert.Equal(t, ErrSigNotMatch, VerifyUserSig(1, "3", "3", sig, now))
25+
assert.Equal(t, ErrUserBufTypeNotMatch, VerifyUserSig(1, "3", "3", bufSig, now))
26+
27+
assert.NoError(t, VerifyUserSigWithBuf(1, "2", "3", bufSig, now, []byte{5}))
28+
assert.Equal(t, ErrExpired, VerifyUserSigWithBuf(1, "2", "3", bufSig, now.Add(time.Hour), []byte{5}))
29+
assert.Equal(t, ErrSdkAppIDNotMatch, VerifyUserSigWithBuf(2, "2", "3", bufSig, now, []byte{5}))
30+
assert.Equal(t, ErrIdentifierNotMatch, VerifyUserSigWithBuf(1, "2", "4", bufSig, now, []byte{5}))
31+
assert.Equal(t, ErrSigNotMatch, VerifyUserSigWithBuf(1, "3", "3", bufSig, now, []byte{5}))
32+
assert.Equal(t, ErrUserBufTypeNotMatch, VerifyUserSigWithBuf(1, "3", "3", bufSig, now, nil))
33+
assert.Equal(t, ErrUserBufNotMatch, VerifyUserSigWithBuf(1, "3", "3", bufSig, now, []byte{6}))
34+
}

0 commit comments

Comments
 (0)