由于我们的用户使用的后台的工具和平台不尽相同,而我们 api 所能适应的平台是有限的,所以在此简要描述下 usersig 的生成算法,以便在用户需要而我们又没有提供时,用户可以自己进行实现。下面是 python 描述的算法(其实直接可以用的),
- #! /usr/bin/python
- # coding:utf-8
- __author__ = "tls@tencent.com"
- __date__ = "$Mar 3, 2016 03:00:43 PM"
- import OpenSSL
- import base64
- import zlib
- import json
- import time
- ecdsa_pri_key = """
- -----BEGIN EC PARAMETERS-----
- BgUrgQQACg==
- -----END EC PARAMETERS-----
- -----BEGIN EC PRIVATE KEY-----
- MHQCAQEEIEJDBDY4KVdj3dPBacADreB772ok45A57YWrUUvc5fMQoAcGBSuBBAAK
- oUQDQgAEaPVFHhWqRDnKnVlyU5JIzXOUyOJd/pPUwhLUovf+PYBm7otRBptnvJ4E
- oJ4qeSJNG0v4XdiqM3mtChkhUEFT3Q==
- -----END EC PRIVATE KEY-----
- """
- 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('+', '*')
- base64_data = base64_data.replace('/', '-')
- base64_data = base64_data.replace('=', '_')
- return base64_data
- def base64_decode_url(base64_data):
- base64_data = base64_data.replace('*', '+')
- base64_data = base64_data.replace('-', '/')
- base64_data = base64_data.replace('_', '=')
- 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):
- m = {}
- m["TLS.account_type"] = "%d" % self.__acctype
- m["TLS.identifier"] = "%s" % self.__identifier
- m["TLS.appid_at_3rd"] = "%s" % self.__appid3rd
- m["TLS.sdk_appid"] = "%d" % self.__sdkappid
- m["TLS.expire_after"] = "%d" % self.__expire
- m["TLS.version"] = "%d" % self.__version
- m["TLS.time"] = "%d" % time.time()
- return m
- 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
- json_str = json.dumps(m)
- sig_cmpressed = zlib.compress(json_str)
- base64_sig = base64_encode_url(sig_cmpressed)
- return base64_sig
- def main():
- api = TLSSigAPI(1400001052, ecdsa_pri_key)
- sig = api.tls_gen_sig("xiaojun")
- print sig
- if __name__ == "__main__":
- main()
复制代码
下面用文字简要描述下,
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。