def test_encrypt(self): testcases = [ { "input": ["pvUPIk0YG6MnxCEMIUUVFrbDmQwbhICXUcy", "kkkT5OOkOkO5kT5TOO5TkOT5TTk5O55T", "OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5", "XAJI0Y6DPBHSAHXTHV3A3ZMF"], "expected": { "nonce": "WEFKSTBZNkRQQkhTQUhYVEhWM0EzWk1G", "ciphertext": "tsYJa2JgGDOpVIYFe4aNVWAvZlpB7z7CjN9mpIdbATE0Yc4izN8aM8D6VigBxnIQ" }, } ] # do the actual testing for t in testcases: channel_test_val = t["input"][0] payload_test_val = t["input"][1] encr_key_test_val = ensure_binary(t["input"][2],'t["input"][2]') nonce_test_val = t["input"][3] self.assertEqual( crypto.encrypt( channel_test_val, payload_test_val, encr_key_test_val, nonce_test_val ), t["expected"] )
def test_generate_shared_secret(self): testcases = [{ "input": [ "pvUPIk0YG6MnxCEMIUUVFrbDmQwbhICXUcy", "OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5" ], "expected": b"p\x9e\xf3\t\n$\xbf\xa9\x83\x82\xcb]\x02\\\xa3b,\x82\xd3\x1f\xa2\x7f\x10\xb0\x05\xc0\xdc\xa2{\xaee\x16" }] # do the actual testing for t in testcases: self.assertEqual( crypto.generate_shared_secret( ensure_binary(t["input"][0], 't["input"][0]'), ensure_binary(t["input"][1], 't["input"][1]')), t["expected"])
def __init__(self, app_id, key, secret, ssl=True, host=None, port=None, timeout=5, cluster=None, encryption_master_key=None, json_encoder=None, json_decoder=None, backend=None, **backend_options): if backend is None: from .requests import RequestsBackend backend = RequestsBackend self._app_id = ensure_text(app_id, "app_id") if not app_id_re.match(self._app_id): raise ValueError("Invalid app id") self._key = ensure_text(key, "key") self._secret = ensure_text(secret, "secret") if not isinstance(ssl, bool): raise TypeError("SSL should be a boolean") self._ssl = ssl if port and not isinstance(port, six.integer_types): raise TypeError("port should be an integer") self._port = port or (443 if ssl else 80) if not isinstance(timeout, six.integer_types): raise TypeError("timeout should be an integer") self._timeout = timeout self._json_encoder = json_encoder self._json_decoder = json_decoder if encryption_master_key is not None: encryption_master_key = ensure_binary(encryption_master_key, "encryption_master_key") self._encryption_master_key = encryption_master_key self.http = backend(self, **backend_options)
def test_generate_shared_secret(self): testcases = [ { "input": ["pvUPIk0YG6MnxCEMIUUVFrbDmQwbhICXUcy", "OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5"], "expected": b"p\x9e\xf3\t\n$\xbf\xa9\x83\x82\xcb]\x02\\\xa3b,\x82\xd3\x1f\xa2\x7f\x10\xb0\x05\xc0\xdc\xa2{\xaee\x16" } ] # do the actual testing for t in testcases: self.assertEqual( crypto.generate_shared_secret( ensure_binary(t["input"][0],'t["input"][0]'), ensure_binary(t["input"][1],'t["input"][1]') ), t["expected"] )
def __init__( self, app_id, key, secret, ssl=True, host=None, port=None, timeout=5, cluster=None, encryption_master_key=None, json_encoder=None, json_decoder=None, backend=None, **backend_options): if backend is None: from .requests import RequestsBackend backend = RequestsBackend self._app_id = ensure_text(app_id, "app_id") if not app_id_re.match(self._app_id): raise ValueError("Invalid app id") self._key = ensure_text(key, "key") self._secret = ensure_text(secret, "secret") if not isinstance(ssl, bool): raise TypeError("SSL should be a boolean") self._ssl = ssl if port and not isinstance(port, six.integer_types): raise TypeError("port should be an integer") self._port = port or (443 if ssl else 80) if not isinstance(timeout, six.integer_types): raise TypeError("timeout should be an integer") self._timeout = timeout self._json_encoder = json_encoder self._json_decoder = json_decoder if encryption_master_key is not None: encryption_master_key = ensure_binary(encryption_master_key, "encryption_master_key") self._encryption_master_key = encryption_master_key self.http = backend(self, **backend_options)
def parse_master_key(encryption_master_key, encryption_master_key_base64): """ parse_master_key validates, parses and returns the bytes of the encryption master key from the constructor arguments. At present there is a deprecated "raw" key and a suggested base64 encoding. """ if encryption_master_key is not None and encryption_master_key_base64 is not None: raise ValueError( "Do not provide both encryption_master_key and encryption_master_key_base64. " + "encryption_master_key is deprecated, provide only encryption_master_key_base64" ) if encryption_master_key is not None: warnings.warn( "`encryption_master_key` is deprecated, please use `encryption_master_key_base64`" ) if len(encryption_master_key) == 32: return ensure_binary(encryption_master_key, "encryption_master_key") else: raise ValueError("encryption_master_key must be 32 bytes long") if encryption_master_key_base64 is not None: if is_base64(encryption_master_key_base64): decoded = base64.b64decode(encryption_master_key_base64) if len(decoded) == 32: return decoded else: raise ValueError( "encryption_master_key_base64 must be a base64 string which decodes to 32 bytes" ) else: raise ValueError( "encryption_master_key_base64 must be valid base64") return None
def authenticate(self, channel, socket_id, custom_data=None): """Used to generate delegated client subscription token. :param channel: name of the channel to authorize subscription to :param socket_id: id of the socket that requires authorization :param custom_data: used on presence channels to provide user info """ channel = validate_channel(channel) if not channel_name_re.match(channel): raise ValueError('Channel should be a valid channel, got: %s' % channel) socket_id = validate_socket_id(socket_id) if custom_data: custom_data = json.dumps(custom_data, cls=self._json_encoder) string_to_sign = "%s:%s" % (socket_id, channel) if custom_data: string_to_sign += ":%s" % custom_data signature = sign(self.secret, string_to_sign) auth = "%s:%s" % (self.key, signature) response_payload = {"auth": auth} if is_encrypted_channel(channel): shared_secret = generate_shared_secret( ensure_binary(channel, "channel"), self._encryption_master_key) shared_secret_b64 = base64.b64encode(shared_secret) response_payload["shared_secret"] = shared_secret_b64 if custom_data: response_payload['channel_data'] = custom_data return response_payload