def aes_encrypt(self, plain, sec_key, enable_b64=True): """ 使用 ``aes`` 加密数据, 并由 ``base64编码`` 加密后的数据 - ``sec_key`` 加密 ``msg``, 最后选择 ``是否由base64编码数据`` - msg长度为16位数, 不足则补 'ascii \\0' .. warning:: msg长度为16位数, 不足则补 'ascii \\0' :param plain: :type plain: str :param sec_key: :type sec_key: str :param enable_b64: :type enable_b64: bool :return: :rtype: """ plain = helper.to_str(plain) sec_key = helper.to_str(sec_key) # 如果msg长度不为16倍数, 需要补位 '\0' plain += '\0' * (self.bs - len(plain) % self.bs) # 使用生成的 key, iv 加密 plain = helper.to_bytes(plain) cipher = self.aes_obj(sec_key).encrypt(plain) # 是否返回 base64 编码数据 cip = base64.b64encode(cipher) if enable_b64 else cipher return helper.to_str(cip)
def gen_rsa(dat, password=''): rp = int(dat.get('pubkey'), 16) key = rsa.PublicKey(rp, 65537) msg = '{}\t{}\n{}'.format(dat.get('servertime'), dat.get('nonce'), password) msg = helper.to_bytes(msg) sp = rsa.encrypt(msg, key) sp = binascii.b2a_hex(sp) return sp
def aes_obj(self, sec_key, encrypt_sec_key=True): """ 生成aes加密所需要的 ``key, iv`` .. warning:: 每个AES.new对象, 只能使用一次 :param sec_key: :type sec_key: str :param encrypt_sec_key: ``如果为true, 则md5加密 sec_key, 生成 key,iv, 否则直接使用 sec_key, 来作为key,iv`` :type encrypt_sec_key: bool :return: :rtype: """ # 使用 md5加密 key, 获取32个长度, 拆分为两个16长度作为 AES的 key, iv p = self.encrypt(sec_key) if encrypt_sec_key else sec_key key, iv = p[:self.bs], p[16:] return AES.new(helper.to_bytes(key), self.aes_mode, helper.to_bytes(iv))
def encrypt(self, plain, algorithm='md5'): """ 简单封装系统加密 :param plain: 待加密内容 :type plain: ``str/bytes`` :param algorithm: 加密算法 :type algorithm: str :return: :rtype: """ plain = helper.to_bytes(plain) return getattr(hashlib, algorithm)(plain).hexdigest()
def rsa_check_base64_sign_str(self, cipher, sign, b64=True): """ 验证服务端数据 ``rsa`` 签名 """ with open(self.key_file) as fp: key_ = RSA.importKey(fp.read()) v = pkcs.new(key_) sign = base64.b64decode(sign) if b64 else sign cipher = helper.to_bytes(cipher) # if hasattr(cipher, 'encode'): # cipher = cipher.encode('utf-8') return v.verify(SHA.new(cipher), sign)
def rsa_base64_sign_str(self, plain, b64=True): """ 对 msg rsa 签名, 然后使用 base64 encode 编码数据 """ with open(self.key_file) as fp: key_ = RSA.importKey(fp.read()) # h = SHA.new(plain if sys.version_info < (3, 0) else plain.encode('utf-8')) plain = helper.to_bytes(plain) # if hasattr(plain, 'encode'): # plain = plain.encode() h = SHA.new(plain) cipher = pkcs.new(key_).sign(h) cip = base64.b64encode(cipher) if b64 else cipher return helper.to_str(cip)
def rsa_base64_encrypt(self, plain, b64=True): """ 使用公钥加密 ``可见数据`` - 由于rsa公钥加密相对耗时, 多用来 ``加密数据量小`` 的数据 .. note:: 1. 使用aes加密数据 2. 然后rsa用来加密aes加密数据时使用的key :param plain: :type plain: :param b64: :type b64: :return: :rtype: """ with open(self.key_file) as fp: key_ = RSA.importKey(fp.read()) plain = helper.to_bytes(plain) cipher = PKCS1_v1_5.new(key_).encrypt(plain) cip = base64.b64encode(cipher) if b64 else cipher return helper.to_str(cip)
def pre_login(self, username='', password=''): params = { 'entry': 'weibo', 'su': base64.b64encode(helper.to_bytes(username))[:-1], 'rsakt': 'mod', 'checkpin': 1, 'client': 'ssologin.js(v1.4.19)', '_': helper.unixtime(mm=True) } raw = self.sess.get(M['pre_login'], params=params, headers=self.get_headers) dat = json.loads(raw.content) _sp = self.gen_rsa(dat, password=password) rt = { 'servertime': dat['servertime'], 'nonce': dat['nonce'], 'rsakv': dat['rsakv'], 'su': params['su'], 'sp': _sp, } return rt