def create_or_recall_keys(replace: bool = False): """Generate keys and save to .keys file.""" if not os.path.exists('.keys') or replace: # Create keypair and write to file my_vk, my_sk = crypto.create_keypair() did = crypto.bytes_to_b58(my_vk[:16]) print('DID:', did) print('VK:', crypto.bytes_to_b58(my_vk)) their_vk = input('Their VK: ') endpoint = input('Their Endpoint: ') with open('.keys', 'w+') as key_file: json.dump( { 'did': did, 'my_vk': crypto.bytes_to_b58(my_vk), 'my_sk': crypto.bytes_to_b58(my_sk), 'their_vk': their_vk, 'endpoint': endpoint }, key_file) else: with open('.keys', 'r') as key_file: info = json.load(key_file) did = info['did'] my_vk = info['my_vk'] my_sk = info['my_sk'] their_vk = info['their_vk'] endpoint = info['endpoint'] return did, my_vk, my_sk, their_vk, endpoint
async def test_simple_messaging(backchannel): """Show simple messages being passed to and from the test subject.""" expected_schema = MessageSchema({ '@type': 'test/protocol/1.0/test', '@id': str, 'msg': 'pong' }) ping = Message({ '@type': 'test/protocol/1.0/test', 'msg': 'ping' }) print('Sending message:', ping.pretty_print()) pong = await backchannel.send_and_await_reply_async( ping, timeout=1 ) print('Received message:', pong.pretty_print()) assert pong.mtc[ CONFIDENTIALITY | INTEGRITY | AUTHENTICATED_ORIGIN | DESERIALIZE_OK ] assert not pong.mtc[NONREPUDIATION] assert pong.mtc.ad['sender_vk'] == crypto.bytes_to_b58(backchannel.their_vk) assert pong.mtc.ad['recip_vk'] == crypto.bytes_to_b58(backchannel.my_vk) assert expected_schema.validate(pong)
def generate_test_info(seed=None): """Generate connection information from seed.""" test_keys = StaticConnection.Keys(*crypto.create_keypair(seed)) test_keys_b58 = StaticConnection.Keys( crypto.bytes_to_b58(test_keys.verkey), crypto.bytes_to_b58(test_keys.sigkey)) test_did = crypto.bytes_to_b58(test_keys.verkey[:16]) return ConnectionInfo(test_keys, test_keys_b58, test_did)
def store_connection(conn: StaticConnection): if hasattr(conn, 'state') and (conn.state.state == ConnectionStates.COMPLETE or conn.state.state == ConnectionStates.RESPONDED): with open('.keys', 'w+') as key_file: json.dump( { 'did': crypto.bytes_to_b58(conn.my_vk[:16]), 'my_vk': crypto.bytes_to_b58(conn.my_vk), 'my_sk': crypto.bytes_to_b58(conn.my_sk), 'their_vk': crypto.bytes_to_b58(conn.their_vk), 'endpoint': conn.endpoint }, key_file)
async def test_cron_example(example_keys, test_keys, connection, listening_endpoint): """Test the cron example.""" with connection.next() as next_msg: process = await asyncio.create_subprocess_exec( 'env/bin/python', 'examples/cron.py', '--my-verkey', crypto.bytes_to_b58(example_keys.verkey), '--my-sigkey', crypto.bytes_to_b58(example_keys.sigkey), '--their-verkey', crypto.bytes_to_b58(test_keys.verkey), '--endpoint', listening_endpoint) assert await process.wait() == 0 msg = await asyncio.wait_for(next_msg, 30) assert 'basicmessage' in msg.type assert msg['content'] == 'The Cron script was executed.'
def test_pack_unpack_auth(keys, alice, bob): """ Test the pack-unpack loop with authcrypt. """ alice_vk, _alice_sk, bob_vk, _bob_sk = keys msg = Message({'@type': 'doc;protocol/1.0/name'}) packed_msg = alice.pack(msg) assert isinstance(packed_msg, bytes) unpacked_msg = bob.unpack(packed_msg) assert isinstance(unpacked_msg, Message) assert hasattr(unpacked_msg, 'mtc') assert unpacked_msg.mtc[ CONFIDENTIALITY | INTEGRITY | DESERIALIZE_OK | AUTHENTICATED_ORIGIN ] assert unpacked_msg.mtc[NONREPUDIATION] is False assert unpacked_msg.mtc.ad['sender_vk'] == crypto.bytes_to_b58(alice_vk) assert unpacked_msg.mtc.ad['recip_vk'] == crypto.bytes_to_b58(bob_vk)
def new_frontchannel( self, *, their_vk: Union[bytes, str] = None, recipients: [Union[bytes, str]] = None, routing_keys: [Union[bytes, str]] = None, endpoint: str = None) -> StaticConnection: """ Create a new connection and add it as a frontchannel. Args: fc_vk: The new frontchannel's verification key fc_sk: The new frontchannel's signing key their_vk: The test subject's verification key for this channel endpoint: The HTTP URL to the endpoint of the test subject. Returns: Returns the new front channel (static connection). """ fc_keys = crypto.create_keypair() new_fc = StaticConnection( fc_keys, their_vk=their_vk, endpoint=endpoint, recipients=recipients, routing_keys=routing_keys ) frontchannel_index = crypto.bytes_to_b58(new_fc.verkey) self.frontchannels[frontchannel_index] = new_fc return new_fc
async def responder(connection, query, comment): """Send a query request and return the response.""" # Send the request req = Message({ '@type': 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/discover-features/1.0/query', 'query': query, 'comment': comment, }) resp = await connection.send_and_await_reply_async(req, timeout=1) # Validate the response assert resp.mtc.is_authcrypted() assert resp.mtc.sender == crypto.bytes_to_b58(connection.recipients[0]) assert resp.mtc.recipient == connection.verkey_b58 resp_schema = MessageSchema({ '@type': 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/discover-features/1.0/disclose', '@id': str, 'protocols': [{ 'pid': str, 'roles': [str] }] }) resp_schema(resp) # Return the response return resp
async def test_trust_ping_sender(backchannel, connection): """Test that subject sends a trust ping.""" expected_trust_ping_schema = MessageSchema({ "@type": Any(TYPE, ALT_TYPE), "@id": str, Optional("~timing"): { Optional("out_time"): str, Optional("expires_time"): str, Optional("delay_milli"): int }, Optional("comment"): str, "response_requested": bool }) with connection.next() as next_msg: await backchannel.trust_ping_v1_0_send_ping(connection) msg = await asyncio.wait_for(next_msg, 5) assert expected_trust_ping_schema(msg) assert msg.mtc.is_authcrypted() assert msg.mtc.sender == crypto.bytes_to_b58(connection.recipients[0]) assert msg.mtc.recipient == connection.verkey_b58 await connection.send_async({ "@type": TYPE, "~thread": { "thid": msg.id }, })
def new_frontchannel( self, their_vk: Union[bytes, str], endpoint: str) -> StaticConnection: """ Create a new connection and add it as a frontchannel. Args: fc_vk: The new frontchannel's verification key fc_sk: The new frontchannel's signing key their_vk: The test subject's verification key for this channel endpoint: The HTTP URL to the endpoint of the test subject. Returns: Returns the new front channel (static connection). """ fc_vk, fc_sk = crypto.create_keypair() new_fc = StaticConnection( fc_vk, fc_sk, their_vk, endpoint ) frontchannel_index = crypto.bytes_to_b58(fc_vk) self.frontchannels[frontchannel_index] = new_fc return new_fc
async def responder(connection, query, comment): """Send a query request and return the response.""" # Send the request req = Message({ '@type': Suite.TYPE_PREFIX + 'discover-features/1.0/query', 'query': query, 'comment': comment, }) resp = await connection.send_and_await_reply_async(req, timeout=1) # Validate the response assert resp.mtc.is_authcrypted() assert resp.mtc.sender == crypto.bytes_to_b58(connection.recipients[0]) assert resp.mtc.recipient == connection.verkey_b58 msg_type = Suite.TYPE_PREFIX + 'discover-features/1.0/disclose' alt_msg_type = Suite.ALT_TYPE_PREFIX + 'discover-features/1.0/disclose' resp_schema = MessageSchema({ '@type': Any(msg_type, alt_msg_type), '@id': str, 'protocols': [{ 'pid': str, 'roles': [str] }] }) resp_schema(resp) # Return the response return resp
async def query(self, msg, conn): """Handle a discover-features query message. """ # Verify the query message assert msg.mtc.is_authcrypted() assert msg.mtc.sender == crypto.bytes_to_b58(conn.recipients[0]) assert msg.mtc.recipient == conn.verkey_b58 msg_schema = MessageSchema({ '@type': str(self.type('query')), '@id': str, 'query': str, Optional('comment'): str, }) msg_schema(msg) query = msg['query'] # Find the protocols which match the query message matchingProtocols = [] for proto in self.protocols: if re.match(query, proto['pid']): matchingProtocols.append(proto) # Send the disclose message await conn.send_async({ "@type": self.type("disclose"), "protocols": matchingProtocols, }) self.query_message_count = self.query_message_count + 1
async def test_trust_ping_with_response_requested_true(connection): """Test that subject responds to trust pings.""" expected_trust_pong_schema = MessageSchema({ "@type": Any(TYPE, ALT_TYPE), "@id": str, "~thread": { "thid": str }, Optional("~timing"): { Optional("in_time"): str, Optional("out_time"): str }, Optional("comment"): str }) trust_ping = Message({ "@type": TYPE, # "@id" is added by the staticagent lib "response_requested": True }) #print('Sending message:', trust_ping.pretty_print()) trust_pong = await connection.send_and_await_reply_async(trust_ping, timeout=1) #print('Received message:', trust_pong.pretty_print()) assert trust_pong.mtc.is_authcrypted() # are you, you and am I, me? assert trust_pong.mtc.sender == crypto.bytes_to_b58( connection.recipients[0]) assert trust_pong.mtc.recipient == connection.verkey_b58 assert expected_trust_pong_schema(trust_pong) assert trust_pong['~thread']['thid'] == trust_ping.id
async def test_webserver_with_websockets(example_keys, test_keys, connection_ws, listening_endpoint, unused_tcp_port_factory): """Test the webserver with websockets example.""" example_port = unused_tcp_port_factory() connection_ws.target.update( endpoint="http://*****:*****@type": "https://didcomm.org/" "basicmessage/1.0/message", "~l10n": { "locale": "en" }, "sent_time": utils.timestamp(), "content": "Your hovercraft is full of eels.", }, return_route="all", ) msg = await queue.get(timeout=30) assert "basicmessage" in msg.type assert msg["content"] == "You said: Your hovercraft is full of eels." process.terminate() await process.wait()
async def test_connection_started_by_suite(config, temporary_channel): """ Test a connection as started by the suite. """ with temporary_channel() as conn: invite_str = build_invite('test-suite-connection-started-by-suite', conn.my_vk_b58, config['endpoint']) print('Encoding invitation:', parse_invite(invite_str)) print("\n\nInvitation encoded as URL: ", invite_str) print("Awaiting request from tested agent...") def condition(msg): print(msg) return msg.type == REQUEST request = await conn.await_message(condition=condition, timeout=30) REQUEST_SCHEMA(request) print("\nReceived request:\n", request.pretty_print()) (_, conn.their_vk_b58, conn.endpoint) = ( request['connection']['DIDDoc']['publicKey'][0]['controller'], request['connection']['DIDDoc']['publicKey'][0]['publicKeyBase58'], request['connection']['DIDDoc']['service'][0]['serviceEndpoint']) conn.their_vk = crypto.b58_to_bytes(conn.their_vk_b58) conn.my_vk, conn.my_sk = crypto.create_keypair() conn.did = crypto.bytes_to_b58(conn.my_vk[:16]) conn.my_vk_b58 = crypto.bytes_to_b58(conn.my_vk) response = build_response(request.id, conn.did, conn.my_vk_b58, config['endpoint']) print("\nSending Response (pre signature packing):\n", response.pretty_print()) response['connection~sig'] = crypto.sign_message_field( response['connection'], signer=conn.my_vk_b58, secret=conn.my_sk) del response['connection'] print("\nSending Response (post signature packing):\n", response.pretty_print()) await conn.send_async(response)
async def invitation(self, msg, _agent): """ Process an invitation. """ print(msg.pretty_print()) their_conn_key = msg['recipientKeys'][0] my_vk, my_sk = crypto.create_keypair() new_connection = StaticConnection(my_vk, my_sk, msg['recipientKeys'][0], msg['serviceEndpoint'], dispatcher=self.dispatcher) new_connection.did = crypto.bytes_to_b58(my_vk[:16]) new_connection.vk_b58 = crypto.bytes_to_b58(my_vk) new_connection.state = ConnectionState() new_connection.state.role = Roles.INVITEE new_connection.state.transition(Events.RECV_INVITE) self.connections[their_conn_key] = new_connection await new_connection.send_async({ '@type': self.type('request'), 'label': 'apts-demo-agent-as-invitee', 'connection': { 'DID': new_connection.did, 'DIDDoc': { "@context": "https://w3id.org/did/v1", "id": new_connection.did, "publicKey": [{ "id": new_connection.did + "#keys-1", "type": "Ed25519VerificationKey2018", "controller": new_connection.did, "publicKeyBase58": new_connection.vk_b58 }], "service": [{ "id": new_connection.did + ";indy", "type": "IndyAgent", "recipientKeys": [new_connection.vk_b58], "routingKeys": [], "serviceEndpoint": self.endpoint, }], } } }) new_connection.state.transition(Events.SEND_REQ)
def verify_msg(self, typ, msg, conn, pid, schema): assert msg.mtc.is_authcrypted() assert msg.mtc.sender == crypto.bytes_to_b58(conn.recipients[0]) assert msg.mtc.recipient == conn.verkey_b58 schema['@type'] = "{}/{}".format(pid, typ) schema['@id'] = str msg_schema = MessageSchema(schema) msg_schema(msg) self._received_msg(msg, conn)
def test_b58_inputs_without_their_info(my_test_info): """Test that valid b58 inputs yield expected values.""" conn = Connection.from_parts( (my_test_info.keys.verkey_b58, crypto.bytes_to_b58(my_test_info.keys.sigkey))) assert conn.verkey == my_test_info.keys.verkey assert conn.sigkey == my_test_info.keys.sigkey assert conn.verkey_b58 == my_test_info.keys.verkey_b58 assert conn.did == my_test_info.did
def remove_frontchannel(self, connection: StaticConnection): """ Remove a frontchannel. Args: fc_vk: The frontchannel's verification key """ frontchannel_index = crypto.bytes_to_b58(connection.verkey) if frontchannel_index in self.frontchannels: del self.frontchannels[frontchannel_index]
def remove_frontchannel(self, connection: StaticConnection): """ Remove a frontchannel. Args: fc_vk: The frontchannel's verification key """ fc_vk = crypto.bytes_to_b58(connection.my_vk) if fc_vk in self.frontchannels: del self.frontchannels[fc_vk]
async def test_webserver_aiohttp(example_keys, test_keys, connection, listening_endpoint, unused_tcp_port_factory): """Test the webserver aiohttp example.""" example_port = unused_tcp_port_factory() connection.update(endpoint='http://*****:*****@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/" "basicmessage/1.0/message", "~l10n": { "locale": "en" }, "sent_time": utils.timestamp(), "content": "Your hovercraft is full of eels." }) msg = await asyncio.wait_for(next_msg, 30) assert 'basicmessage' in msg.type assert msg['content'] == 'You said: Your hovercraft is full of eels.' process.terminate() await process.wait()
async def test_connection_started_by_tested_agent(config, temporary_channel): """Test a connection as started by the agent under test.""" invite_url = input('Input generated connection invite: ') invite_msg = parse_invite(invite_url) print("\nReceived Invite:\n", invite_msg.pretty_print()) # Create my information for connection with temporary_channel(invite_msg['recipientKeys'][0], invite_msg['serviceEndpoint']) as conn: did = crypto.bytes_to_b58(conn.my_vk[:16]) my_vk_b58 = crypto.bytes_to_b58(conn.my_vk) # Send Connection Request to inviter request = build_request('test-connection-started-by-tested-agent', did, my_vk_b58, config['endpoint']) print("\nSending Request:\n", request.pretty_print()) print("Awaiting response from tested agent...") response = await conn.send_and_await_reply_async( request, condition=lambda msg: msg.type == RESPONSE, timeout=30) RESPONSE_SCHEMA_PRE_SIG_VERIFY(response) print("\nReceived Response (pre signature verification):\n", response.pretty_print()) signer, response['connection'] = \ crypto.verify_signed_message_field(response['connection~sig']) assert signer == invite_msg['recipientKeys'][0], 'Unexpected signer' del response['connection~sig'] RESPONSE_SCHEMA_POST_SIG_VERIFY(response) assert response['~thread']['thid'] == request.id print("\nReceived Response (post signature verification):\n", response.pretty_print())
async def test_cron_example(example_keys, test_keys, connection, listening_endpoint): """Test the cron example.""" async with connection.queue() as queue: process = await asyncio.create_subprocess_exec( "poetry", "run", "python", "examples/cron.py", "--my-verkey", crypto.bytes_to_b58(example_keys.verkey), "--my-sigkey", crypto.bytes_to_b58(example_keys.sigkey), "--their-verkey", crypto.bytes_to_b58(test_keys.verkey), "--endpoint", listening_endpoint, ) assert await process.wait() == 0 msg = await queue.get(timeout=30) assert "basicmessage" in msg.type assert msg["content"] == "The Cron script was executed."
async def test_simple_messaging(connection): """Show simple messages being passed to and from the test subject.""" expected_schema = MessageSchema({ '@type': 'test/protocol/1.0/test', '@id': str, 'msg': 'pong' }) ping = Message({'@type': 'test/protocol/1.0/test', 'msg': 'ping'}) print('Sending message:', ping.pretty_print()) pong = await connection.send_and_await_reply_async(ping, timeout=1) print('Received message:', pong.pretty_print()) assert pong.mtc.is_authcrypted() assert pong.mtc.sender == crypto.bytes_to_b58(connection.recipients[0]) assert pong.mtc.recipient == connection.verkey_b58 assert expected_schema(pong)
def create_invitation(self): """ Create and return an invite. """ conn_vk, conn_sk = crypto.create_keypair() connection = StaticConnection(conn_vk, conn_sk, b'', '', dispatcher=self.dispatcher) conn_vk_b58 = crypto.bytes_to_b58(conn_vk) self.connections[conn_vk_b58] = connection connection.state = ConnectionState() connection.state.role = Roles.INVITER connection.state.transition(Events.SEND_INVITE) invitation = Message({ '@type': self.type('invitation'), 'label': 'static-iiw', 'recipientKeys': [conn_vk_b58], 'serviceEndpoint': self.endpoint, 'routingKeys': [] }) invitation_url = '{}?c_i={}'.format( self.endpoint, crypto.bytes_to_b64(invitation.serialize().encode())) return connection, invitation_url
from aries_staticagent import crypto vk_bytes, sk_bytes = crypto.create_keypair() did_bytes = vk_bytes[0:16] vk = crypto.bytes_to_b58(vk_bytes) sk = crypto.bytes_to_b58(sk_bytes) did = crypto.bytes_to_b58(did_bytes) print('For full agent:\n\tDID: {}\n\tVK: {}\n'.format(did, vk)) print('For static agent:\n\tVK: {}\n\tSK: {}'.format(vk, sk))
async def request(self, msg, _agent): """ Process a request. """ print(msg.pretty_print()) connection = self.connections[msg.mtc.ad['recip_vk']] connection.state.transition(Events.RECV_REQ) # Old connection keys, need to sign new keys with these conn_vk, conn_sk = connection.my_vk, connection.my_sk # Relationship keys, replacing connection keys my_vk, my_sk = crypto.create_keypair() # Update connection connection.my_vk, connection.my_sk = my_vk, my_sk connection.did = crypto.bytes_to_b58(my_vk[:16]) connection.vk_b58 = crypto.bytes_to_b58(my_vk) connection.their_did = msg['connection']['DIDDoc']['publicKey'][0][ 'controller'] connection.their_vk = crypto.b58_to_bytes( msg['connection']['DIDDoc']['publicKey'][0]['publicKeyBase58']) connection.endpoint = msg['connection']['DIDDoc']['service'][0][ 'serviceEndpoint'] del self.connections[msg.mtc.ad['recip_vk']] self.connections[connection.vk_b58] = connection # Prepare response connection_block = { 'DID': connection.did, 'DIDDoc': { "@context": "https://w3id.org/did/v1", "id": connection.did, "publicKey": [{ "id": connection.did + "#keys-1", "type": "Ed25519VerificationKey2018", "controller": connection.did, "publicKeyBase58": connection.vk_b58 }], "service": [{ "id": connection.did + ";indy", "type": "IndyAgent", "recipientKeys": [connection.vk_b58], "routingKeys": [], "serviceEndpoint": self.endpoint, }], } } connection.state.transition(Events.SEND_RESP) await connection.send_async({ '@type': self.type('response'), '~thread': { 'thid': msg.id, 'sender_order': 0 }, 'connection~sig': crypto.sign_message_field(connection_block, crypto.bytes_to_b58(conn_vk), conn_sk) })
def add_frontchannel(self, connection: StaticConnection): """Add an already created connection as a frontchannel.""" frontchannel_index = crypto.bytes_to_b58(connection.my_vk) self.frontchannels[frontchannel_index] = connection