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-
2425func 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+
9395func 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+
186189func 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
201204func 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+ )
0 commit comments