Exemple #1
0
    def _encrypt_message(self, msg, nonce, timestamp=None):
        """
        将公众号回复用户的消息加密打包

        :param msg: 待回复用户的消息,xml格式的字符串
        :param nonce: 随机串,可以自己生成,也可以用URL参数的nonce
        :param timestamp: 时间戳,可以自己生成,也可以用URL参数的timestamp,如为None则自动用当前时间
        :return: 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串
        """
        xml = """<xml>
            <Encrypt><![CDATA[{encrypt}]]></Encrypt>
            <MsgSignature><![CDATA[{signature}]]></MsgSignature>
            <TimeStamp>{timestamp}</TimeStamp>
            <Nonce><![CDATA[{nonce}]]></Nonce>
            </xml>"""
        nonce = to_binary(nonce)
        timestamp = to_binary(timestamp) or to_binary(int(time.time()))
        encrypt = self.__pc.encrypt(to_text(msg), self.__id)
        # 生成安全签名
        signature = get_sha1_signature(self.__token, timestamp, nonce, encrypt)
        return to_text(
            xml.format(encrypt=to_text(encrypt),
                       signature=to_text(signature),
                       timestamp=to_text(timestamp),
                       nonce=to_text(nonce)))
Exemple #2
0
    def __init__(self, token, encoding_aes_key, _id):
        """构造函数

        :param token: 公众平台上,开发者设置的Token
        :param encoding_aes_key: 公众平台上,开发者设置的EncodingAESKey
        :param _id: 公众号的 appid 或企业号的 corpid
        """
        self.__key = base64.b64decode(
            to_binary(encoding_aes_key) + to_binary('='))
        if len(self.__key) != 32:
            raise ValidateAESKeyError(encoding_aes_key)
        self.__token = to_binary(token)
        self.__id = to_binary(_id)
        self.__pc = BaseCrypto(self.__key)
 def __str__(self):
     if six.PY2:
         return to_binary('{code}: {msg}'.format(code=self.errcode,
                                                 msg=self.errmsg))
     else:
         return to_text('{code}: {msg}'.format(code=self.errcode,
                                               msg=self.errmsg))
Exemple #4
0
def get_sha1_signature(token, timestamp, nonce, encrypt):
    """
    用 SHA1 算法生成安全签名
    @param token: 票据
    @param timestamp: 时间戳
    @param nonce: 随机字符串
    @param encrypt: 密文
    @return: 安全签名
    """
    try:
        sortlist = [token, timestamp, nonce, to_binary(encrypt)]
        sortlist.sort()
        sha = hashlib.sha1()
        sha.update(to_binary("").join(sortlist))
        return sha.hexdigest()
    except Exception as e:
        raise CryptoComputeSignatureError(e)
Exemple #5
0
    def _decrypt_message(self, msg, msg_signature, timestamp, nonce):
        """
        检验消息的真实性,并且获取解密后的明文

        :param msg: 密文,对应POST请求的数据
        :param msg_signature: 签名串,对应URL参数的msg_signature
        :param timestamp: 时间戳,对应URL参数的timestamp
        :param nonce: 随机串,对应URL参数的nonce
        :return: 解密后的原文
        """
        timestamp = to_binary(timestamp)
        nonce = to_binary(nonce)
        if isinstance(msg, six.string_types):
            try:
                msg = xmltodict.parse(to_text(msg))['xml']
            except Exception as e:
                raise ParseError(e)
        encrypt = msg['Encrypt']
        signature = get_sha1_signature(self.__token, timestamp, nonce, encrypt)
        if signature != msg_signature:
            raise ValidateSignatureError()
        return self.__pc.decrypt(encrypt, self.__id)
Exemple #6
0
 def encode(cls, text):
     """
     对需要加密的明文进行填充补位
     @param text: 需要进行填充补位操作的明文
     @return: 补齐明文字符串
     """
     text_length = len(text)
     # 计算需要填充的位数
     amount_to_pad = cls.block_size - (text_length % cls.block_size)
     if amount_to_pad == 0:
         amount_to_pad = cls.block_size
     # 获得补位所用的字符
     pad = to_binary(chr(amount_to_pad))
     return text + pad * amount_to_pad
Exemple #7
0
    def encrypt(self, text, appid):
        """
        对明文进行加密

        @param text: 需要加密的明文
        @return: 加密得到的字符串
        """
        # 16位随机字符串添加到明文开头
        text = self.get_random_str() + struct.pack("I", socket.htonl(len(text))) + \
            to_binary(text) + appid
        # 使用自定义的填充方式对明文进行补位填充
        pkcs7 = PKCS7Encoder()
        text = pkcs7.encode(text)
        # 加密
        cryptor = AES.new(self.key, self.mode, self.key[:16])
        try:
            ciphertext = cryptor.encrypt(text)
            # 使用BASE64对加密后的字符串进行编码
            return base64.b64encode(ciphertext)
        except Exception as e:
            raise EncryptAESError(e)
 def __str__(self):
     if six.PY2:
         return to_binary(self.message)
     else:
         return to_text(self.message)