Python生成腾讯云实时音视频的UserSig签名
1.UserSig 简介
官方文档链接:https://cloud.tencent.com/document/product/647/16790
腾讯云 IM 的前身是 QQ 的即时通讯消息系统,我们将 QQ 的消息模块进行了抽离,变成了适合移动端接入的 IM SDK。将消息后台进行改造,使其脱离对 QQ 号码的绑定,构成了现在的 IM 云通讯后台。
QQ 可以用来收发单聊和群聊的消息,但前提是您必须先登录才能使用。登录 QQ 用的是 QQ 号和密码,登录 IM SDK 也是一样,只是肯定不能再用 QQ 号和密码了,而是使用您指定的用户名(userid)和密码(usersig)。
用户名(userid)
可以是您目前 App 里的用户 ID,比如您有一个用户,他/她的账号 ID 是 27149, 那么您就可以用 27149 作为登录 IM SDK 的 userid。密码(usersig)
既然您指定了 27149 是您的用户,腾讯云如何才能确认该用户是您认可的合法用户呢?usersig 就是用于解决这个问题的,usersig 本质是对 userid、appid 等信息的
非对称加密非对称加密用的加密密钥和解密密钥是不同的,您的服务器可以持有私钥并对 userid 和 appid 进行非对称加密,加密之后的结果就是 usersig ;而腾讯云同步持有您的公钥,这样一来,腾讯云就可以确认 usersig 是否合法,从而可以确认它是否是由您的服务器签发的
2.生成 UserSig
官网的 SDK 下载区提供了一份计算 UserSig 的简单版源码,有 Java 和 PHP 两个版本的:https://github.com/TencentVideoCloudMLVBDev/usersig_server_source
下面的代码是用Python生成UserSig的方法,用的sanic框架,主要参考:http://bbs.qcloud.com/thread-14366-1-1.html
from sanic.views import HTTPMethodView
from sanic import response
from sanic import Blueprint
import OpenSSL
import base64
import zlib
import json
import time UserSigList_Blueprint = Blueprint(__name__,url_prefix='/api/banpai/v1.2/') #ec格式的私钥
# ecdsa_pri_key ="""
# -----BEGIN EC PRIVATE KEY-----
# MHcCAQEEIP+EunCa1keJ/ymk+MXhyb22+SHGgtdbYmdsBRzkWhohoAoGCCqGSM49
# AwEHoUQDQgAEXFBfDBCbwt0ZjBUMP9jJ/iqAcPeDi1UVzh51GuhGfNkRezQBTK/C
# 4rgi6oH24Asxeo1jnhFywp13qxFVYiKhtA==
# -----END EC PRIVATE KEY-----
# """ ecdsa_pri_key ="""
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIKLXR3F2OJkMrrzJtzhH52OnK+rVoUA4pcns3XdYoSfDoAoGCCqGSM49
AwEHoUQDQgAEbRGCpFwUNOjIMUHy7lcF3rDqZ0KvJpoua3VAiP3+5kjlYFHzLneg
0olpV4eJDb3RhGZ3bANgoOZdRxtlI1TR/Q==
-----END EC PRIVATE KEY-----
""" # sdk_appid =
sdk_appid = 注册官方账号会提供 def list_all_curves():
list = OpenSSL.crypto.get_elliptic_curves()
for element in list:
print(element) def get_secp256k1():
print(OpenSSL.crypto.get_elliptic_curve('secp256k1')) def base64_encode_url(data):
base64_data = base64.b64encode(data)
base64_data = base64_data.replace(b'+', b'*')
base64_data = base64_data.replace(b'/', b'-')
base64_data = base64_data.replace(b'=', b'_')
return base64_data def base64_decode_url(base64_data):
base64_data = base64_data.replace(b'*', b'+')
base64_data = base64_data.replace(b'-', b'/')
base64_data = base64_data.replace(b'_', b'=')
raw_data = base64.b64decode(base64_data)
return raw_data class TLSSigAPI:
""""""
__acctype = 0
__identifier = ""
__appid3rd = ""
__sdkappid = 0
__version = 20151204
__expire = 3600 * 24 * 30 # 默认一个月,需要调整请自行修改
__pri_key = ""
__pub_key = ""
_err_msg = "ok" def __get_pri_key(self):
return OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, self.__pri_key) def __init__(self, sdkappid, pri_key):
self.__sdkappid = sdkappid self.__pri_key = pri_key def __create_dict(self):
return {"TLS.account_type": "%d" % self.__acctype, "TLS.identifier": "%s" % self.__identifier,
"TLS.appid_at_3rd": "%s" % self.__appid3rd, "TLS.sdk_appid": "%d" % self.__sdkappid,
"TLS.expire_after": "%d" % self.__expire, "TLS.version": "%d" % self.__version,
"TLS.time": "%d" % time.time()} def __encode_to_fix_str(self, m):
fix_str = "TLS.appid_at_3rd:" + m["TLS.appid_at_3rd"] + "\n" \
+ "TLS.account_type:" + m["TLS.account_type"] + "\n" \
+ "TLS.identifier:" + m["TLS.identifier"] + "\n" \
+ "TLS.sdk_appid:" + m["TLS.sdk_appid"] + "\n" \
+ "TLS.time:" + m["TLS.time"] + "\n" \
+ "TLS.expire_after:" + m["TLS.expire_after"] + "\n" return fix_str def tls_gen_sig(self, identifier):
self.__identifier = identifier m = self.__create_dict()
fix_str = self.__encode_to_fix_str(m)
pk_loaded = self.__get_pri_key()
sig_field = OpenSSL.crypto.sign(pk_loaded, fix_str, "sha256")
sig_field_base64 = base64.b64encode(sig_field)
m["TLS.sig"] = sig_field_base64.decode('utf-8')
json_str = json.dumps(m)
sig_compressed = zlib.compress(json_str.encode('utf-8'))
base64_sig = base64_encode_url(sig_compressed)
return base64_sig
下面用文字简要描述下,
1.将用户的信息组装成一个字符串(json格式的,是直接拼装的,因为顺序不能乱),是哪些信息,可以看 __encode_to_fix_str;
2.使用 sha256 将字符串 hash,然后再用私钥签名,一般加密接口都会一把搞定,加密曲线使用的是 secp256k1;
3.把第2步得到的缓冲区进行base64;
4.将所有用户的信息以及第3步得到签名写进一个 json 串,此时可以不论顺序;
5.将 json 进行序列化,再 zlib 压缩,最后 base64(替换了某些字符,具体哪些看代码),出炉。
特别注意,这段代码在 windows 上验证没问题,但是红帽系(rel 和 centos)上不支持我们使用的曲线,list_all_curves 可以打印所有支持的曲线,红帽系的没有 secp256k1。
如果发现系统所带的 openssl 扩展不支持我们选定的曲线,可以参考 http://bbs.qcloud.com/thread-23280-1-1.html。
Python生成腾讯云实时音视频的UserSig签名的更多相关文章
- 云-腾讯云-实时音视频:实时音视频(TRTC)
ylbtech-云-腾讯云-实时音视频:实时音视频(TRTC) 支持跨终端.全平台之间互通,从零开始快速搭建实时音视频通信平台 1.返回顶部 1. 腾讯实时音视频(Tencent Real-Time ...
- 一、Uniapp+vue+腾讯IM+腾讯音视频开发仿微信的IM聊天APP,支持各类消息收发,音视频通话,附vue实现源码(已开源)-项目引言
项目文章索引 1.项目引言 2.腾讯云后台配置TXIM 3.配置项目并实现IM登录 4.会话好友列表的实现 5.聊天输入框的实现 6.聊天界面容器的实现 7.聊天消息项的实现 8.聊天输入框扩展面板的 ...
- 融云携新版实时音视频亮相 LiveVideoStack 2019
4 月 19 日,LiveVideoStack 2019 音视频大会在上海隆重开幕,全球多媒体创新专家.音视频技术工程师.产品负责人.高端行业用户等共襄盛会,聚焦音频.视频.图像.AI 等技术的最新探 ...
- Python+moviepy音视频剪辑:视频帧数据的本质、Clip的fl方法进行变换处理的原理以及滚屏案例
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt+moviepy音视频剪辑实战 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一. ...
- 音视频入门-20-BMP、PNG、JPG、GIF静态图生成GIF动态图
* 音视频入门文章目录 * 静态图 -> 动态图 前面 [18-手动生成一张GIF图片] 和 [19-使用giflib处理GIF图片] 生成的 GIF 每一帧都是一个颜色,平时用到的 GIF 每 ...
- moviepy音视频剪辑:使用fl_time进行时间特效处理报错ValueError: Attribute duration not set
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt+moviepy音视频剪辑实战 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 在使 ...
- moviepy音视频剪辑:使用fl_time报错OSError: MoviePy error: failed to read the first frame of video file
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt+moviepy音视频剪辑实战 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 在m ...
- moviepy音视频剪辑:使用fl_time进行诸如快播、慢播、倒序播放等时间特效处理的原理和可能遇到的坑
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt+moviepy音视频剪辑实战 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一. ...
- moviepy音视频剪辑:moviepy中的剪辑基类Clip的属性和方法详解
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt+moviepy音视频剪辑实战 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一. ...
随机推荐
- 为什么要进行 URL 编码???
作者:降瑞雪 cnblogs.com/jerrysion/p/5522673.html 我们都知道Http协议中参数的传输是"key=value"这种简直对形式的,如果要传多个参数 ...
- pyhon if分支
在python中,最常用的就是if判断,if判断可以分为单次判断和多次判断 单次判断 if 条件 : (条件成立执行我) else:(else也可以没有,最近的else对应最近的if语句) (条件 ...
- 使用MySQL Workbench查询超时的错误
MySQL Workbench是MySQL提供的连接工具,一直在用它.但是今天运行了一个SQL缺报出如下的错误: errcode 2013 lost connection to mysql serve ...
- c# DataTable第二行改为各列标题字段
DataTable dt = ExcelHelper.ToDataTable(fileinfo.FilePath); //将datatable的第二行变为列标题字段 DataTable dt2 = n ...
- MySQL 复制参数详解
log-bin 二进制日志 server-id 早起版本必须添加 1-pow(2,32)-1 推荐使用 端口号+ip最后一位 5.6后可以动态修改 server-uuid (5.6以后) 默认存在 ...
- Codeforces 747F Igor and Interesting Numbers DP 组合数
题意:给你一个数n和t,问字母出现次数不超过t,第n小的16进制数是多少. 思路:容易联想到数位DP, 然而并不是...我们需要知道有多少位,在知道有多少位之后,用试填法找出答案.我们设dp[i][j ...
- express 的路由学习
使用步骤 - :获取路由中间件对象 `let router = express.Router();` - :配置路由规则 `router.请求方式(URL,fn事)` - fn中参数有req,res, ...
- 项目实战 - 混合式App开发
为何要使用混合式开发? 要说为什么使用Hybrid App [混合式开发],就要先了解什么是Native App[原生程序], Web App[网站程序]. Native App 是专门针对某一类移动 ...
- pip install RISE报错解决
ERROR: Cannot uninstall 'tornado' ERROR: Cannot uninstall 'tornado'. It is a distutils installed pro ...
- mysql-一行分隔成多行数据
mysql将某个字段有分隔符号分隔成多行数据 SELECT a.id, a. NAME, substring_index( substring_index( a.name, ',', b.help_t ...