def test_verify_challenge_tx_sequence_not_zero(self): server_kp = Keypair.random() client_kp = Keypair.random() network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE anchor_name = "SDF" now = int(time.time()) nonce = os.urandom(48) nonce_encoded = base64.b64encode(nonce) server_account = Account(server_kp.public_key, 10086) challenge_te = ( TransactionBuilder(server_account, network_passphrase, 100) .append_manage_data_op( data_name="{} auth".format(anchor_name), data_value=nonce_encoded, source=client_kp.public_key, ) .add_time_bounds(now, now + 900) .build() ) challenge_te.sign(server_kp) challenge_te.sign(client_kp) challenge_tx_signed = challenge_te.to_xdr() with pytest.raises( InvalidSep10ChallengeError, match="The transaction sequence number should be zero.", ): verify_challenge_transaction( challenge_tx_signed, server_kp.public_key, network_passphrase )
def test_verify_challenge_tx_operation_value_is_none(self): server_kp = Keypair.random() client_kp = Keypair.random() network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE home_domain = "example.com" now = int(time.time()) nonce_encoded = None server_account = Account(server_kp.public_key, -1) challenge_te = (TransactionBuilder( server_account, network_passphrase, 100).append_manage_data_op( data_name="{} auth".format(home_domain), data_value=nonce_encoded, source=client_kp.public_key, ).add_time_bounds(now, now + 900).build()) challenge_te.sign(server_kp) challenge_te.sign(client_kp) challenge_tx_signed = challenge_te.to_xdr() with pytest.raises( InvalidSep10ChallengeError, match="Operation value should not be null.", ): verify_challenge_transaction( challenge_tx_signed, server_kp.public_key, home_domain, network_passphrase, )
def test_verify_challenge_tx_dont_contains_timebound(self): server_kp = Keypair.random() client_kp = Keypair.random() network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE anchor_name = "SDF" nonce = os.urandom(48) nonce_encoded = base64.b64encode(nonce) server_account = Account(server_kp.public_key, -1) challenge_te = ( TransactionBuilder(server_account, network_passphrase, 100) .append_manage_data_op( data_name="{} auth".format(anchor_name), data_value=nonce_encoded, source=client_kp.public_key, ) .build() ) challenge_te.sign(server_kp) challenge_te.sign(client_kp) challenge_tx_signed = challenge_te.to_xdr() with pytest.raises( InvalidSep10ChallengeError, match="Transaction requires timebounds." ): verify_challenge_transaction( challenge_tx_signed, server_kp.public_key, network_passphrase )
def test_verify_challenge_tx_not_within_range_of_the_specified_timebounds(self): server_kp = Keypair.random() client_kp = Keypair.random() network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE anchor_name = "SDF" now = int(time.time()) nonce = os.urandom(48) nonce_encoded = base64.b64encode(nonce) server_account = Account(server_kp.public_key, -1) challenge_te = ( TransactionBuilder(server_account, network_passphrase, 100) .append_manage_data_op( data_name="{} auth".format(anchor_name), data_value=nonce_encoded, source=client_kp.public_key, ) .add_time_bounds(now - 100, now - 50) .build() ) challenge_te.sign(server_kp) challenge_te.sign(client_kp) challenge_tx_signed = challenge_te.to_xdr() with pytest.raises( InvalidSep10ChallengeError, match="Transaction is not within range of the specified timebounds.", ): verify_challenge_transaction( challenge_tx_signed, server_kp.public_key, network_passphrase )
def test_verify_challenge_tx_source_is_different_to_server_account_id( self): server_kp = Keypair.random() client_kp = Keypair.random() network_passphrase = Network.TESTNET_NETWORK_PASSPHRASE anchor_name = "SDF" challenge = build_challenge_transaction(server_kp.secret, client_kp.public_key, anchor_name, network_passphrase) transaction = TransactionEnvelope.from_xdr(challenge, Network(network_passphrase)) transaction.sign(client_kp) challenge_tx = transaction.to_xdr() with pytest.raises( InvalidSep10ChallengeError, match= "Transaction source account is not equal to server's account.", ): verify_challenge_transaction(challenge_tx, Keypair.random().public_key, network_passphrase)
def test_verify_challenge_tx_transaction_is_not_signed_by_the_server(self): server_kp = Keypair.random() client_kp = Keypair.random() network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE anchor_name = "SDF" timeout = 900 now = int(time.time()) server_keypair = Keypair.from_secret(server_kp.secret) server_account = Account(account_id=server_keypair.public_key, sequence=-1) transaction_builder = TransactionBuilder( server_account, network_passphrase, 100 ) transaction_builder.add_time_bounds(min_time=now, max_time=now + timeout) nonce = os.urandom(48) nonce_encoded = base64.b64encode(nonce) transaction_builder.append_manage_data_op( data_name="{} auth".format(anchor_name), data_value=nonce_encoded, source=client_kp.public_key, ) challenge = transaction_builder.build().to_xdr() transaction = TransactionEnvelope.from_xdr(challenge, network_passphrase) transaction.sign(client_kp) challenge_tx = transaction.to_xdr() with pytest.raises( InvalidSep10ChallengeError, match="Transaction not signed by server: {}".format(server_kp.public_key), ): verify_challenge_transaction( challenge_tx, server_kp.public_key, network_passphrase )
def test_verify_challenge_tx_contain_subsequent_manage_data_ops_without_the_server_account_as_the_source_account( self, ): server_kp = Keypair.random() client_kp = Keypair.random() network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE home_domain = "example.com" now = int(time.time()) nonce = os.urandom(48) nonce_encoded = base64.b64encode(nonce) server_account = Account(server_kp.public_key, -1) challenge_te = (TransactionBuilder( server_account, network_passphrase, 100).append_manage_data_op( data_name="{} auth".format(home_domain), data_value=nonce_encoded, source=client_kp.public_key, ).append_manage_data_op( data_name="data key", data_value="data value", source=client_kp.public_key, ).add_time_bounds(now, now + 900).build()) challenge_te.sign(server_kp) challenge_te.sign(client_kp) challenge_tx_signed = challenge_te.to_xdr() with pytest.raises( InvalidSep10ChallengeError, match="The transaction has operations that are unrecognized.", ): verify_challenge_transaction( challenge_tx_signed, server_kp.public_key, home_domain, network_passphrase, )
def test_verify_challenge_tx_operation_value_is_not_a_64_bytes_base64_string( self): server_kp = Keypair.random() client_kp = Keypair.random() network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE anchor_name = "SDF" now = int(time.time()) nonce = os.urandom(32) server_account = Account(server_kp.public_key, -1) challenge_te = (TransactionBuilder( server_account, network_passphrase, 100).append_manage_data_op( data_name="{} auth".format(anchor_name), data_value=nonce, source=client_kp.public_key, ).add_time_bounds(now, now + 300).build()) challenge_te.sign(server_kp) challenge_te.sign(client_kp) challenge_tx_signed = challenge_te.to_xdr() with pytest.raises( InvalidSep10ChallengeError, match= "Operation value should be a 64 bytes base64 random string.", ): verify_challenge_transaction(challenge_tx_signed, server_kp.public_key, network_passphrase)
def test_verify_challenge_tx_contain_subsequent_manage_data_ops_with_server_account_as_source_account( self, ): server_kp = Keypair.random() client_kp = Keypair.random() network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE domain_name = "example.com" now = int(time.time()) nonce = os.urandom(48) nonce_encoded = base64.b64encode(nonce) server_account = Account(server_kp.public_key, -1) challenge_te = (TransactionBuilder( server_account, network_passphrase, 100).append_manage_data_op( data_name="{} auth".format(domain_name), data_value=nonce_encoded, source=client_kp.public_key, ).append_manage_data_op( data_name="data key", data_value="data value", source=server_kp.public_key, ).add_time_bounds(now, now + 900).build()) challenge_te.sign(server_kp) challenge_te.sign(client_kp) challenge_tx_signed = challenge_te.to_xdr() verify_challenge_transaction( challenge_tx_signed, server_kp.public_key, domain_name, network_passphrase, )
def test_verify_challenge_tx_contains_infinite_timebounds(self): server_kp = Keypair.random() client_kp = Keypair.random() network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE domain_name = "example.com" now = int(time.time()) nonce = os.urandom(48) nonce_encoded = base64.b64encode(nonce) server_account = Account(server_kp.public_key, -1) challenge_te = ( TransactionBuilder(server_account, network_passphrase, 100) .append_manage_data_op( data_name="{} auth".format(domain_name), data_value=nonce_encoded, source=client_kp.public_key, ) .add_time_bounds(now, 0) .build() ) challenge_te.sign(server_kp) challenge_te.sign(client_kp) challenge_tx_signed = challenge_te.to_xdr() with pytest.raises( InvalidSep10ChallengeError, match="Transaction requires non-infinite timebounds.", ): verify_challenge_transaction( challenge_tx_signed, server_kp.public_key, domain_name, network_passphrase, )
def test_verify_challenge_transaction_domain_name_mismatch_raise(self): server_kp = Keypair.random() client_kp = Keypair.random() timeout = 600 network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE domain_name = "example.com" invalid_domain_name = "invalid_example.com" challenge = build_challenge_transaction( server_secret=server_kp.secret, client_account_id=client_kp.public_key, domain_name=domain_name, network_passphrase=network_passphrase, timeout=timeout, ) transaction = TransactionEnvelope.from_xdr(challenge, network_passphrase) transaction.sign(client_kp) challenge_tx = transaction.to_xdr() with pytest.raises( InvalidSep10ChallengeError, match="The transaction's operation key name " "does not include the expected home domain.", ): verify_challenge_transaction( challenge_tx, server_kp.public_key, invalid_domain_name, network_passphrase, )
def test_verify_challenge_tx_donot_contain_managedata_operation(self): server_kp = Keypair.random() client_kp = Keypair.random() network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE domain_name = "example.com" now = int(time.time()) server_account = Account(server_kp.public_key, -1) challenge_te = ( TransactionBuilder(server_account, network_passphrase, 100) .append_set_options_op() .add_time_bounds(now, now + 900) .build() ) challenge_te.sign(server_kp) challenge_te.sign(client_kp) challenge_tx_signed = challenge_te.to_xdr() with pytest.raises( InvalidSep10ChallengeError, match="Operation type should be ManageData." ): verify_challenge_transaction( challenge_tx_signed, server_kp.public_key, domain_name, network_passphrase, )
def test_verify_challenge_tx_contain_zero_op(self, ): server_kp = Keypair.random() client_kp = Keypair.random() network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE domain_name = "example.com" now = int(time.time()) nonce = os.urandom(48) server_account = Account(server_kp.public_key, -1) challenge_te = (TransactionBuilder(server_account, network_passphrase, 100).add_time_bounds( now, now + 900).build()) challenge_te.sign(server_kp) challenge_te.sign(client_kp) challenge_tx_signed = challenge_te.to_xdr() with pytest.raises( InvalidSep10ChallengeError, match="Transaction should contain at least one operation.", ): verify_challenge_transaction( challenge_tx_signed, server_kp.public_key, domain_name, network_passphrase, )
def test_verify_challenge_tx_contain_subsequent_ops_that_secend_op_no_source_account( self, ): server_kp = Keypair.random() client_kp = Keypair.random() network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE domain_name = "example.com" now = int(time.time()) nonce = os.urandom(48) nonce_encoded = base64.b64encode(nonce) server_account = Account(server_kp.public_key, -1) challenge_te = (TransactionBuilder( server_account, network_passphrase, 100).append_manage_data_op( data_name="{} auth".format(domain_name), data_value=nonce_encoded, source=client_kp.public_key, ).append_manage_data_op(data_name="Hello", data_value="world").add_time_bounds( now, now + 900).build()) challenge_te.sign(server_kp) challenge_te.sign(client_kp) challenge_tx_signed = challenge_te.to_xdr() with pytest.raises( InvalidSep10ChallengeError, match="Operation should have a source account.", ): verify_challenge_transaction( challenge_tx_signed, server_kp.public_key, domain_name, network_passphrase, )
def _validate_envelope_xdr(envelope_xdr): """ Validate the provided TransactionEnvelope XDR (base64 string). Return the appropriate error if it fails, else the empty string. """ try: verify_challenge_transaction(challenge_transaction=envelope_xdr, server_account_id=settings.STELLAR_DISTRIBUTION_ACCOUNT_ADDRESS, network_passphrase=settings.STELLAR_NETWORK_PASSPHRASE) except InvalidSep10ChallengeError as err: return str(err) return ""
def test_verify_challenge_tx_donot_contain_any_operation(self): server_kp = Keypair.random() client_kp = Keypair.random() network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE now = int(time.time()) server_account = Account(server_kp.public_key, -1) challenge_te = (TransactionBuilder(server_account, network_passphrase, 100).add_time_bounds( now, now + 300).build()) challenge_te.sign(server_kp) challenge_te.sign(client_kp) challenge_tx_signed = challenge_te.to_xdr() with pytest.raises( InvalidSep10ChallengeError, match="Transaction requires a single ManageData operation.", ): verify_challenge_transaction(challenge_tx_signed, server_kp.public_key, network_passphrase)
def test_verify_challenge_transaction(self): server_kp = Keypair.random() client_kp = Keypair.random() timeout = 600 network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE anchor_name = "SDF" challenge = build_challenge_transaction( server_secret=server_kp.secret, client_account_id=client_kp.public_key, anchor_name=anchor_name, network_passphrase=network_passphrase, timeout=timeout, ) transaction = TransactionEnvelope.from_xdr(challenge, network_passphrase) transaction.sign(client_kp) challenge_tx = transaction.to_xdr() verify_challenge_transaction( challenge_tx, server_kp.public_key, network_passphrase )
def test_verify_challenge_tx_transaction_is_not_signed_by_the_client(self): server_kp = Keypair.random() client_account_id = "GBDIT5GUJ7R5BXO3GJHFXJ6AZ5UQK6MNOIDMPQUSMXLIHTUNR2Q5CFNF" timeout = 600 network_passphrase = Network.TESTNET_NETWORK_PASSPHRASE anchor_name = "SDF" challenge = build_challenge_transaction( server_secret=server_kp.secret, client_account_id=client_account_id, anchor_name=anchor_name, network_passphrase=network_passphrase, timeout=timeout, ) with pytest.raises( InvalidSep10ChallengeError, match="Transaction not signed by any client signer.", ): verify_challenge_transaction(challenge, server_kp.public_key, network_passphrase)
def test_verify_challenge_transaction_with_multi_domain_names(self): server_kp = Keypair.random() client_kp = Keypair.random() timeout = 600 network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE home_domain = "example.com" challenge = build_challenge_transaction( server_secret=server_kp.secret, client_account_id=client_kp.public_key, home_domain=home_domain, network_passphrase=network_passphrase, timeout=timeout, ) transaction = TransactionEnvelope.from_xdr(challenge, network_passphrase) transaction.sign(client_kp) challenge_tx = transaction.to_xdr() verify_challenge_transaction( challenge_tx, server_kp.public_key, ["example.com2", "example.com1", home_domain], network_passphrase)