🎨 优化sign

master v0.0.3
loser 2 years ago
parent 36b8ce93f1
commit 672e497c29

@ -12,8 +12,7 @@ import (
"strings"
)
// base64Encode base64 encode a string.
func base64Encode(data []byte) string {
func base64urlEncode(data []byte) string {
str := base64.StdEncoding.EncodeToString(data)
str = strings.Replace(str, "+", "*", -1)
str = strings.Replace(str, "/", "-", -1)
@ -21,8 +20,7 @@ func base64Encode(data []byte) string {
return str
}
// base64Decode base64 decode a string.
func base64Decode(str string) ([]byte, error) {
func base64urlDecode(str string) ([]byte, error) {
str = strings.Replace(str, "_", "=", -1)
str = strings.Replace(str, "-", "/", -1)
str = strings.Replace(str, "*", "+", -1)

@ -14,28 +14,156 @@ import (
"crypto/sha256"
"encoding/base64"
"encoding/json"
"errors"
"io/ioutil"
"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)
/**
* TRTC IM 使 UserSig
*
*
* sdkappid - id
* key - usersig ,
* userid - id32a-zA-Z0-9线
* expire - UserSig 86400 UserSig 使
*/
/**
* Function: Used to issue UserSig that is required by the TRTC and IM services.
*
* Parameter description:
* sdkappid - Application ID
* userid - User ID. The value can be up to 32 bytes in length and contain letters (a-z and A-Z), digits (0-9), underscores (_), and hyphens (-).
* key - The encryption key used to calculate usersig can be obtained from the console.
* expire - UserSig expiration time, in seconds. For example, 86400 indicates that the generated UserSig will expire one day after being generated.
*/
func GenUserSig(sdkappid int, key string, userid string, expire int) (string, error) {
return genSig(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)
func GenUserSigWithBuf(sdkappid int, key string, userid string, expire int, buf []byte) (string, error) {
return genSig(sdkappid, key, userid, expire, buf)
}
// 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)
/**
*
* TRTC PrivateMapKey
* PrivateMapKey UserSig 使 PrivateMapKey UserSig
* - UserSig UserID 使 TRTC UserSig UserID
* - PrivateMapKey UserID
* PrivateMapKey =>=>
*
*
* sdkappid - id
* key - usersig ,
* userid - id32a-zA-Z0-9线
* expire - PrivateMapKey 86400 PrivateMapKey 使
* roomid - userid
* privilegeMap - 使 8
* - 1 0000 0001 = 1
* - 2 0000 0010 = 2
* - 3 0000 0100 = 4
* - 4 0000 1000 = 8
* - 5 0001 0000 = 16
* - 6 0010 0000 = 32
* - 7 0100 0000 = 64
* - 8 1000 0000 = 200
* - privilegeMap == 1111 1111 == 255 userid roomid
* - privilegeMap == 0010 1010 == 42 userid
*/
/**
* Function:
* Used to issue PrivateMapKey that is optional for room entry.
* PrivateMapKey must be used together with UserSig but with more powerful permission control capabilities.
* - UserSig can only control whether a UserID has permission to use the TRTC service. As long as the UserSig is correct, the user with the corresponding UserID can enter or leave any room.
* - PrivateMapKey specifies more stringent permissions for a UserID, including whether the UserID can be used to enter a specific room and perform audio/video upstreaming in the room.
* To enable stringent PrivateMapKey permission bit verification, you need to enable permission key in TRTC console > Application Management > Application Info.
*
* Parameter description:
* sdkappid - Application ID
* userid - User ID. The value can be up to 32 bytes in length and contain letters (a-z and A-Z), digits (0-9), underscores (_), and hyphens (-).
* key - The encryption key used to calculate usersig can be obtained from the console.
* roomid - ID of the room to which the specified UserID can enter.
* expire - PrivateMapKey expiration time, in seconds. For example, 86400 indicates that the generated PrivateMapKey will expire one day after being generated.
* privilegeMap - Permission bits. Eight bits in the same byte are used as the permission switches of eight specific features:
* - Bit 1: 0000 0001 = 1, permission for room creation
* - Bit 2: 0000 0010 = 2, permission for room entry
* - Bit 3: 0000 0100 = 4, permission for audio sending
* - Bit 4: 0000 1000 = 8, permission for audio receiving
* - Bit 5: 0001 0000 = 16, permission for video sending
* - Bit 6: 0010 0000 = 32, permission for video receiving
* - Bit 7: 0100 0000 = 64, permission for substream video sending (screen sharing)
* - Bit 8: 1000 0000 = 200, permission for substream video receiving (screen sharing)
* - privilegeMap == 1111 1111 == 255: Indicates that the UserID has all feature permissions of the room specified by roomid.
* - privilegeMap == 0010 1010 == 42: Indicates that the UserID has only the permissions to enter the room and receive audio/video data.
*/
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 genSig(sdkappid, key, userid, expire, userbuf)
}
/**
*
* TRTC PrivateMapKey
* PrivateMapKey UserSig 使 PrivateMapKey UserSig
* - UserSig UserID 使 TRTC UserSig UserID
* - PrivateMapKey UserID
* PrivateMapKey =>=>
*
*
* sdkappid - id
* key - usersig ,
* userid - id32a-zA-Z0-9线
* expire - PrivateMapKey 86400 PrivateMapKey 使
* roomStr - userid
* privilegeMap - 使 8
* - 1 0000 0001 = 1
* - 2 0000 0010 = 2
* - 3 0000 0100 = 4
* - 4 0000 1000 = 8
* - 5 0001 0000 = 16
* - 6 0010 0000 = 32
* - 7 0100 0000 = 64
* - 8 1000 0000 = 200
* - privilegeMap == 1111 1111 == 255 userid roomid
* - privilegeMap == 0010 1010 == 42 userid
*/
/**
* Function:
* Used to issue PrivateMapKey that is optional for room entry.
* PrivateMapKey must be used together with UserSig but with more powerful permission control capabilities.
* - UserSig can only control whether a UserID has permission to use the TRTC service. As long as the UserSig is correct, the user with the corresponding UserID can enter or leave any room.
* - PrivateMapKey specifies more stringent permissions for a UserID, including whether the UserID can be used to enter a specific room and perform audio/video upstreaming in the room.
* To enable stringent PrivateMapKey permission bit verification, you need to enable permission key in TRTC console > Application Management > Application Info.
*
* Parameter description:
* sdkappid - Application ID
* userid - User ID. The value can be up to 32 bytes in length and contain letters (a-z and A-Z), digits (0-9), underscores (_), and hyphens (-).
* key - The encryption key used to calculate usersig can be obtained from the console.
* roomstr - ID of the room to which the specified UserID can enter.
* expire - PrivateMapKey expiration time, in seconds. For example, 86400 indicates that the generated PrivateMapKey will expire one day after being generated.
* privilegeMap - Permission bits. Eight bits in the same byte are used as the permission switches of eight specific features:
* - Bit 1: 0000 0001 = 1, permission for room creation
* - Bit 2: 0000 0010 = 2, permission for room entry
* - Bit 3: 0000 0100 = 4, permission for audio sending
* - Bit 4: 0000 1000 = 8, permission for audio receiving
* - Bit 5: 0001 0000 = 16, permission for video sending
* - Bit 6: 0010 0000 = 32, permission for video receiving
* - Bit 7: 0100 0000 = 64, permission for substream video sending (screen sharing)
* - Bit 8: 1000 0000 = 200, permission for substream video receiving (screen sharing)
* - privilegeMap == 1111 1111 == 255: Indicates that the UserID has all feature permissions of the room specified by roomid.
* - privilegeMap == 0010 1010 == 42: Indicates that the UserID has only the permissions to enter the room and receive audio/video data.
*/
func GenPrivateMapKeyWithStringRoomID(sdkappid int, key string, userid string, expire int, roomStr string, privilegeMap uint32) (string, error) {
var userbuf []byte = genUserBuf(userid, sdkappid, 0, expire, privilegeMap, 0, roomStr)
return genSig(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 {
@ -47,7 +175,7 @@ func genUserBuf(account string, dwSdkappid int, dwAuthID uint32,
userBuf := make([]byte, length)
// ver
//ver
if len(roomStr) > 0 {
userBuf[offset] = 1
} else {
@ -64,8 +192,8 @@ func genUserBuf(account string, dwSdkappid int, dwAuthID uint32,
userBuf[offset] = account[offset-3]
}
// dwSdkAppid
userBuf[offset] = (byte)((int64(dwSdkappid) & 0xFF000000) >> 24)
//dwSdkAppid
userBuf[offset] = (byte)((dwSdkappid & 0xFF000000) >> 24)
offset++
userBuf[offset] = (byte)((dwSdkappid & 0x00FF0000) >> 16)
offset++
@ -74,7 +202,7 @@ func genUserBuf(account string, dwSdkappid int, dwAuthID uint32,
userBuf[offset] = (byte)(dwSdkappid & 0x000000FF)
offset++
// dwAuthId
//dwAuthId
userBuf[offset] = (byte)((dwAuthID & 0xFF000000) >> 24)
offset++
userBuf[offset] = (byte)((dwAuthID & 0x00FF0000) >> 16)
@ -84,7 +212,7 @@ func genUserBuf(account string, dwSdkappid int, dwAuthID uint32,
userBuf[offset] = (byte)(dwAuthID & 0x000000FF)
offset++
// dwExpTime now+300;
//dwExpTime now+300;
currTime := time.Now().Unix()
var expire = currTime + int64(dwExpTime)
userBuf[offset] = (byte)((expire & 0xFF000000) >> 24)
@ -96,7 +224,7 @@ func genUserBuf(account string, dwSdkappid int, dwAuthID uint32,
userBuf[offset] = (byte)(expire & 0x000000FF)
offset++
// dwPrivilegeMap
//dwPrivilegeMap
userBuf[offset] = (byte)((dwPrivilegeMap & 0xFF000000) >> 24)
offset++
userBuf[offset] = (byte)((dwPrivilegeMap & 0x00FF0000) >> 16)
@ -106,7 +234,7 @@ func genUserBuf(account string, dwSdkappid int, dwAuthID uint32,
userBuf[offset] = (byte)(dwPrivilegeMap & 0x000000FF)
offset++
// dwAccountType
//dwAccountType
userBuf[offset] = (byte)((dwAccountType & 0xFF000000) >> 24)
offset++
userBuf[offset] = (byte)((dwAccountType & 0x00FF0000) >> 16)
@ -130,11 +258,10 @@ func genUserBuf(account string, dwSdkappid int, dwAuthID uint32,
return userBuf
}
// hmacSha256 encrypt with HMAC SHA256.
func hmacSha256(sdkAppId int, key string, identifier string, currTime int64, expire int, base64UserBuf *string) string {
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.sdkappid:" + strconv.Itoa(sdkappid) + "\n"
contentToBeSigned += "TLS.time:" + strconv.FormatInt(currTime, 10) + "\n"
contentToBeSigned += "TLS.expire:" + strconv.Itoa(expire) + "\n"
if nil != base64UserBuf {
@ -146,23 +273,21 @@ func hmacSha256(sdkAppId int, key string, identifier string, currTime int64, exp
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) {
func genSig(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 := make(map[string]interface{})
sigDoc["TLS.ver"] = "2.0"
sigDoc["TLS.identifier"] = identifier
sigDoc["TLS.sdkappid"] = sdkAppId
sigDoc["TLS.sdkappid"] = sdkappid
sigDoc["TLS.expire"] = expire
sigDoc["TLS.time"] = currTime
var base64UserBuf string
if nil != userBuf {
base64UserBuf = base64.StdEncoding.EncodeToString(userBuf)
if nil != userbuf {
base64UserBuf = base64.StdEncoding.EncodeToString(userbuf)
sigDoc["TLS.userbuf"] = base64UserBuf
sigDoc["TLS.sig"] = hmacSha256(sdkAppId, key, identifier, currTime, expire, &base64UserBuf)
sigDoc["TLS.sig"] = hmacsha256(sdkappid, key, identifier, currTime, expire, &base64UserBuf)
} else {
sigDoc["TLS.sig"] = hmacSha256(sdkAppId, key, identifier, currTime, expire, nil)
sigDoc["TLS.sig"] = hmacsha256(sdkappid, key, identifier, currTime, expire, nil)
}
data, err := json.Marshal(sigDoc)
@ -172,7 +297,125 @@ func genUserSig(sdkAppId int, key string, identifier string, expire int, userBuf
var b bytes.Buffer
w := zlib.NewWriter(&b)
_, _ = w.Write(data)
_ = w.Close()
return base64Encode(b.Bytes()), nil
if _, err = w.Write(data); err != nil {
return "", err
}
if err = w.Close(); err != nil {
return "", err
}
return base64urlEncode(b.Bytes()), nil
}
// VerifyUserSig 检验UserSig在now时间点时是否有效
// VerifyUserSig Check if UserSig is valid at now time
func VerifyUserSig(sdkappid uint64, key string, userid string, usersig string, now time.Time) error {
sig, err := newUserSig(usersig)
if err != nil {
return err
}
return sig.verify(sdkappid, key, userid, now, nil)
}
// VerifyUserSigWithBuf 检验带UserBuf的UserSig在now时间点是否有效
// VerifyUserSigWithBuf Check if UserSig with UserBuf is valid at now
func VerifyUserSigWithBuf(sdkappid uint64, key string, userid string, usersig string, now time.Time, userbuf []byte) error {
sig, err := newUserSig(usersig)
if err != nil {
return err
}
return sig.verify(sdkappid, key, userid, now, userbuf)
}
type userSig struct {
Version string `json:"TLS.ver,omitempty"`
Identifier string `json:"TLS.identifier,omitempty"`
SdkAppID uint64 `json:"TLS.sdkappid,omitempty"`
Expire int64 `json:"TLS.expire,omitempty"`
Time int64 `json:"TLS.time,omitempty"`
UserBuf []byte `json:"TLS.userbuf,omitempty"`
Sig string `json:"TLS.sig,omitempty"`
}
func newUserSig(usersig string) (userSig, error) {
b, err := base64urlDecode(usersig)
if err != nil {
return userSig{}, err
}
r, err := zlib.NewReader(bytes.NewReader(b))
if err != nil {
return userSig{}, err
}
data, err := ioutil.ReadAll(r)
if err != nil {
return userSig{}, err
}
if err = r.Close(); err != nil {
return userSig{}, err
}
var sig userSig
if err = json.Unmarshal(data, &sig); err != nil {
return userSig{}, nil
}
return sig, nil
}
func (u userSig) verify(sdkappid uint64, key string, userid string, now time.Time, userbuf []byte) error {
if sdkappid != u.SdkAppID {
return ErrSdkAppIDNotMatch
}
if userid != u.Identifier {
return ErrIdentifierNotMatch
}
if now.Unix() > u.Time+u.Expire {
return ErrExpired
}
if userbuf != nil {
if u.UserBuf == nil {
return ErrUserBufTypeNotMatch
}
if !bytes.Equal(userbuf, u.UserBuf) {
return ErrUserBufNotMatch
}
} else if u.UserBuf != nil {
return ErrUserBufTypeNotMatch
}
if u.sign(key) != u.Sig {
return ErrSigNotMatch
}
return nil
}
func (u userSig) sign(key string) string {
var sb bytes.Buffer
sb.WriteString("TLS.identifier:")
sb.WriteString(u.Identifier)
sb.WriteString("\n")
sb.WriteString("TLS.sdkappid:")
sb.WriteString(strconv.FormatUint(u.SdkAppID, 10))
sb.WriteString("\n")
sb.WriteString("TLS.time:")
sb.WriteString(strconv.FormatInt(u.Time, 10))
sb.WriteString("\n")
sb.WriteString("TLS.expire:")
sb.WriteString(strconv.FormatInt(u.Expire, 10))
sb.WriteString("\n")
if u.UserBuf != nil {
sb.WriteString("TLS.userbuf:")
sb.WriteString(base64.StdEncoding.EncodeToString(u.UserBuf))
sb.WriteString("\n")
}
h := hmac.New(sha256.New, []byte(key))
h.Write(sb.Bytes())
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
// 错误类型
var (
ErrSdkAppIDNotMatch = errors.New("sdk appid not match")
ErrIdentifierNotMatch = errors.New("identifier not match")
ErrExpired = errors.New("expired")
ErrUserBufTypeNotMatch = errors.New("userbuf type not match")
ErrUserBufNotMatch = errors.New("userbuf not match")
ErrSigNotMatch = errors.New("sig not match")
)

Loading…
Cancel
Save