tencent-im/internal/sign/sign.go
2022-09-27 11:31:23 +08:00

179 lines
5.0 KiB
Go

/**
* @Author: Echo
* @Author:1711788888@qq.com
* @Date: 2021/5/27 19:11
* @Desc: Transmission signature.
*/
package sign
import (
"bytes"
"compress/zlib"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"strconv"
"time"
)
// GenUserSig gen a user sign.
func GenUserSig(sdkAppId int, key string, userid string, expire int) (string, error) {
return genUserSig(sdkAppId, key, userid, expire, nil)
}
// GenPrivateMapKey gen a private map.
func GenPrivateMapKey(sdkAppId int, key string, userid string, expire int, roomId uint32, privilegeMap uint32) (string, error) {
var userBuf []byte = genUserBuf(userid, sdkAppId, roomId, expire, privilegeMap, 0, "")
return genUserSig(sdkAppId, key, userid, expire, userBuf)
}
// GenPrivateMapKeyWithRoomId gen a private map with room id.
func GenPrivateMapKeyWithRoomId(sdkAppId int, key string, userid string, expire int, roomId string, privilegeMap uint32) (string, error) {
var userBuf []byte = genUserBuf(userid, sdkAppId, 0, expire, privilegeMap, 0, roomId)
return genUserSig(sdkAppId, key, userid, expire, userBuf)
}
// genUserBuf gen a user buffer.
func genUserBuf(account string, dwSdkappid int, dwAuthID uint32,
dwExpTime int, dwPrivilegeMap uint32, dwAccountType uint32, roomStr string) []byte {
offset := 0
length := 1 + 2 + len(account) + 20 + len(roomStr)
if len(roomStr) > 0 {
length = length + 2
}
userBuf := make([]byte, length)
// ver
if len(roomStr) > 0 {
userBuf[offset] = 1
} else {
userBuf[offset] = 0
}
offset++
userBuf[offset] = (byte)((len(account) & 0xFF00) >> 8)
offset++
userBuf[offset] = (byte)(len(account) & 0x00FF)
offset++
for ; offset < len(account)+3; offset++ {
userBuf[offset] = account[offset-3]
}
// dwSdkAppid
userBuf[offset] = (byte)((int64(dwSdkappid) & 0xFF000000) >> 24)
offset++
userBuf[offset] = (byte)((dwSdkappid & 0x00FF0000) >> 16)
offset++
userBuf[offset] = (byte)((dwSdkappid & 0x0000FF00) >> 8)
offset++
userBuf[offset] = (byte)(dwSdkappid & 0x000000FF)
offset++
// dwAuthId
userBuf[offset] = (byte)((dwAuthID & 0xFF000000) >> 24)
offset++
userBuf[offset] = (byte)((dwAuthID & 0x00FF0000) >> 16)
offset++
userBuf[offset] = (byte)((dwAuthID & 0x0000FF00) >> 8)
offset++
userBuf[offset] = (byte)(dwAuthID & 0x000000FF)
offset++
// dwExpTime now+300;
currTime := time.Now().Unix()
var expire = currTime + int64(dwExpTime)
userBuf[offset] = (byte)((expire & 0xFF000000) >> 24)
offset++
userBuf[offset] = (byte)((expire & 0x00FF0000) >> 16)
offset++
userBuf[offset] = (byte)((expire & 0x0000FF00) >> 8)
offset++
userBuf[offset] = (byte)(expire & 0x000000FF)
offset++
// dwPrivilegeMap
userBuf[offset] = (byte)((dwPrivilegeMap & 0xFF000000) >> 24)
offset++
userBuf[offset] = (byte)((dwPrivilegeMap & 0x00FF0000) >> 16)
offset++
userBuf[offset] = (byte)((dwPrivilegeMap & 0x0000FF00) >> 8)
offset++
userBuf[offset] = (byte)(dwPrivilegeMap & 0x000000FF)
offset++
// dwAccountType
userBuf[offset] = (byte)((dwAccountType & 0xFF000000) >> 24)
offset++
userBuf[offset] = (byte)((dwAccountType & 0x00FF0000) >> 16)
offset++
userBuf[offset] = (byte)((dwAccountType & 0x0000FF00) >> 8)
offset++
userBuf[offset] = (byte)(dwAccountType & 0x000000FF)
offset++
if len(roomStr) > 0 {
userBuf[offset] = (byte)((len(roomStr) & 0xFF00) >> 8)
offset++
userBuf[offset] = (byte)(len(roomStr) & 0x00FF)
offset++
for ; offset < length; offset++ {
userBuf[offset] = roomStr[offset-(length-len(roomStr))]
}
}
return userBuf
}
// hmacSha256 encrypt with HMAC SHA256.
func hmacSha256(sdkAppId int, key string, identifier string, currTime int64, expire int, base64UserBuf *string) string {
var contentToBeSigned string
contentToBeSigned = "TLS.identifier:" + identifier + "\n"
contentToBeSigned += "TLS.sdkappid:" + strconv.Itoa(sdkAppId) + "\n"
contentToBeSigned += "TLS.time:" + strconv.FormatInt(currTime, 10) + "\n"
contentToBeSigned += "TLS.expire:" + strconv.Itoa(expire) + "\n"
if nil != base64UserBuf {
contentToBeSigned += "TLS.userbuf:" + *base64UserBuf + "\n"
}
h := hmac.New(sha256.New, []byte(key))
h.Write([]byte(contentToBeSigned))
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
// genUserSig gen a sign
func genUserSig(sdkAppId int, key string, identifier string, expire int, userBuf []byte) (string, error) {
currTime := time.Now().Unix()
var sigDoc map[string]interface{}
sigDoc = make(map[string]interface{})
sigDoc["TLS.ver"] = "2.0"
sigDoc["TLS.identifier"] = identifier
sigDoc["TLS.sdkappid"] = sdkAppId
sigDoc["TLS.expire"] = expire
sigDoc["TLS.time"] = currTime
var base64UserBuf string
if nil != userBuf {
base64UserBuf = base64.StdEncoding.EncodeToString(userBuf)
sigDoc["TLS.userbuf"] = base64UserBuf
sigDoc["TLS.sig"] = hmacSha256(sdkAppId, key, identifier, currTime, expire, &base64UserBuf)
} else {
sigDoc["TLS.sig"] = hmacSha256(sdkAppId, key, identifier, currTime, expire, nil)
}
data, err := json.Marshal(sigDoc)
if err != nil {
return "", err
}
var b bytes.Buffer
w := zlib.NewWriter(&b)
_, _ = w.Write(data)
_ = w.Close()
return base64Encode(b.Bytes()), nil
}