UNPKG

tls-sig-api-v2

Version:

tls-sig-api-v2 适用于腾讯云通信生成用户账号签名。

241 lines (213 loc) 10.4 kB
var crypto = require('crypto'); var zlib = require('zlib'); var base64url = {}; var newBuffer = function (fill, encoding) { return Buffer.from ? Buffer.from(fill, encoding) : new Buffer(fill, encoding) }; base64url.unescape = function unescape(str) { return (str + Array(5 - str.length % 4)) .replace(/_/g, '=') .replace(/\-/g, '/') .replace(/\*/g, '+'); }; base64url.escape = function escape(str) { return str.replace(/\+/g, '*') .replace(/\//g, '-') .replace(/=/g, '_'); }; base64url.encode = function encode(str) { return this.escape(newBuffer(str).toString('base64')); }; base64url.decode = function decode(str) { return newBuffer(this.unescape(str), 'base64').toString(); }; function base64encode(str) { return newBuffer(str).toString('base64') } function base64decode(str) { return newBuffer(str, 'base64').toString() } var Api = function (sdkappid, key) { this.sdkappid = sdkappid; this.key = key; }; /** * 通过传入参数生成 base64 的 hmac 值 * @param identifier * @param currTime * @param expire * @returns {string} * @private */ Api.prototype._hmacsha256 = function (identifier, currTime, expire, base64UserBuf) { var contentToBeSigned = "TLS.identifier:" + identifier + "\n"; contentToBeSigned += "TLS.sdkappid:" + this.sdkappid + "\n"; contentToBeSigned += "TLS.time:" + currTime + "\n"; contentToBeSigned += "TLS.expire:" + expire + "\n"; if (null != base64UserBuf) { contentToBeSigned += "TLS.userbuf:" + base64UserBuf + "\n"; } const hmac = crypto.createHmac("sha256", this.key); return hmac.update(contentToBeSigned).digest('base64'); }; /** * TRTC业务进房权限加密串需使用用户定义的userbuf * @brief 生成 userbuf * @param account 用户名 * @param dwSdkappid sdkappid * @param dwAuthID 数字房间号 * @param dwExpTime 过期时间:该权限加密串的过期时间,建议300秒,实际过期时间:now+dwExpTime * @param dwPrivilegeMap 用户权限,255表示所有权限 * @param dwAccountType 用户类型,默认为0 * @param roomstr 字符串房间号 * @return userbuf {string} 返回的userbuf */ Api.prototype._genUserbuf = function (account, dwAuthID, dwExpTime, dwPrivilegeMap, dwAccountType, roomstr) { let accountLength = account.length; let roomstrlength = 0; let length = 1 + 2 + accountLength + 20 ; if (null != roomstr) { roomstrlength = roomstr.length; length = length + 2 + roomstrlength; } let offset = 0; let userBuf = new Buffer.alloc(length); //cVer if (null != roomstr) userBuf[offset++] = 1; else userBuf[offset++] = 0; //wAccountLen userBuf[offset++] = (accountLength & 0xFF00) >> 8; userBuf[offset++] = accountLength & 0x00FF; //buffAccount for (; offset < 3 + accountLength; ++offset) { userBuf[offset] = account.charCodeAt(offset - 3); } //dwSdkAppid userBuf[offset++] = (this.sdkappid & 0xFF000000) >> 24; userBuf[offset++] = (this.sdkappid & 0x00FF0000) >> 16; userBuf[offset++] = (this.sdkappid & 0x0000FF00) >> 8; userBuf[offset++] = this.sdkappid & 0x000000FF; //dwAuthId userBuf[offset++] = (dwAuthID & 0xFF000000) >> 24; userBuf[offset++] = (dwAuthID & 0x00FF0000) >> 16; userBuf[offset++] = (dwAuthID & 0x0000FF00) >> 8; userBuf[offset++] = dwAuthID & 0x000000FF; //过期时间:dwExpTime+now let expire = Date.now() / 1000 + dwExpTime; userBuf[offset++] = (expire & 0xFF000000) >> 24; userBuf[offset++] = (expire & 0x00FF0000) >> 16; userBuf[offset++] = (expire & 0x0000FF00) >> 8; userBuf[offset++] = expire & 0x000000FF; //dwPrivilegeMap userBuf[offset++] = (dwPrivilegeMap & 0xFF000000) >> 24; userBuf[offset++] = (dwPrivilegeMap & 0x00FF0000) >> 16; userBuf[offset++] = (dwPrivilegeMap & 0x0000FF00) >> 8; userBuf[offset++] = dwPrivilegeMap & 0x000000FF; //dwAccountType userBuf[offset++] = (dwAccountType & 0xFF000000) >> 24; userBuf[offset++] = (dwAccountType & 0x00FF0000) >> 16; userBuf[offset++] = (dwAccountType & 0x0000FF00) >> 8; userBuf[offset++] = dwAccountType & 0x000000FF; if (null != roomstr) { //roomstrlength userBuf[offset++] = (roomstr.length & 0xFF00) >> 8; userBuf[offset++] = roomstr.length & 0x00FF; //roomstr for (; offset < length; ++offset) { userBuf[offset] = roomstr.charCodeAt(offset - (length - roomstr.length)); } } return userBuf; } Api.prototype.genSig = function (userid, expire, userBuf) { var currTime = Math.floor(Date.now() / 1000); var sigDoc = { 'TLS.ver': "2.0", 'TLS.identifier': "" + userid, 'TLS.sdkappid': Number(this.sdkappid), 'TLS.time': Number(currTime), 'TLS.expire': Number(expire) }; var sig = ''; if (null != userBuf) { var base64UserBuf = base64encode(userBuf); sigDoc['TLS.userbuf'] = base64UserBuf; sig = this._hmacsha256(userid, currTime, expire, base64UserBuf); } else { sig = this._hmacsha256(userid, currTime, expire, null); } sigDoc['TLS.sig'] = sig; var compressed = zlib.deflateSync(newBuffer(JSON.stringify(sigDoc))).toString('base64'); return base64url.escape(compressed); } /** *【功能说明】用于签发 TRTC 和 IM 服务中必须要使用的 UserSig 鉴权票据 * *【参数说明】 * @param userid - 用户id,限制长度为32字节,只允许包含大小写英文字母(a-zA-Z)、数字(0-9)及下划线和连词符。 * @param expire - UserSig 票据的过期时间,单位是秒,比如 86400 代表生成的 UserSig 票据在一天后就无法再使用了。 */ Api.prototype.genUserSig = function (userid, expire) { return this.genSig(userid, expire, null); }; /** *【功能说明】 * 用于签发 TRTC 进房参数中可选的 PrivateMapKey 权限票据。 * PrivateMapKey 需要跟 UserSig 一起使用,但 PrivateMapKey 比 UserSig 有更强的权限控制能力: * - UserSig 只能控制某个 UserID 有无使用 TRTC 服务的权限,只要 UserSig 正确,其对应的 UserID 可以进出任意房间。 * - PrivateMapKey 则是将 UserID 的权限控制的更加严格,包括能不能进入某个房间,能不能在该房间里上行音视频等等。 * 如果要开启 PrivateMapKey 严格权限位校验,需要在【实时音视频控制台】=>【应用管理】=>【应用信息】中打开“启动权限密钥”开关。 * *【参数说明】 * @param userid - 用户id,限制长度为32字节,只允许包含大小写英文字母(a-zA-Z)、数字(0-9)及下划线和连词符。 * @param expire - PrivateMapKey 票据的过期时间,单位是秒,比如 86400 生成的 PrivateMapKey 票据在一天后就无法再使用了。 * @param roomid - 房间号,用于指定该 userid 可以进入的房间号 * @param 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 拥有加入房间和接收音视频数据的权限,但不具备其他权限。 */ Api.prototype.genPrivateMapKey = function (userid, expire, roomid, privilegeMap) { var userBuf = this._genUserbuf(userid, roomid, expire, privilegeMap, 0, null); return this.genSig(userid, expire, userBuf); }; /** *【功能说明】 * 用于签发 TRTC 进房参数中可选的 PrivateMapKey 权限票据。 * PrivateMapKey 需要跟 UserSig 一起使用,但 PrivateMapKey 比 UserSig 有更强的权限控制能力: * - UserSig 只能控制某个 UserID 有无使用 TRTC 服务的权限,只要 UserSig 正确,其对应的 UserID 可以进出任意房间。 * - PrivateMapKey 则是将 UserID 的权限控制的更加严格,包括能不能进入某个房间,能不能在该房间里上行音视频等等。 * 如果要开启 PrivateMapKey 严格权限位校验,需要在【实时音视频控制台】=>【应用管理】=>【应用信息】中打开“启动权限密钥”开关。 * *【参数说明】 * @param userid - 用户id,限制长度为32字节,只允许包含大小写英文字母(a-zA-Z)、数字(0-9)及下划线和连词符。 * @param expire - PrivateMapKey 票据的过期时间,单位是秒,比如 86400 生成的 PrivateMapKey 票据在一天后就无法再使用了。 * @param roomstr - 房间号,用于指定该 userid 可以进入的房间号 * @param 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 在该房间内的所有功能权限。 * - privilegeMap == 0010 1010 == 42 代表该 userid 拥有加入房间和接收音视频数据的权限,但不具备其他权限。 */ Api.prototype.genPrivateMapKeyWithStringRoomID = function (userid, expire, roomstr, privilegeMap) { var userBuf = this._genUserbuf(userid, 0, expire, privilegeMap, 0, roomstr); return this.genSig(userid, expire, userBuf); }; exports.Api = Api;