async def pack(msg: Message, wallet: WalletConnection, their_ver_key, routing_keys: list, my_ver_key=None) -> bytes: if not routing_keys: raise RuntimeError('routing_keys must not be empty') payload = await wallet.pack_message( Serializer.serialize(msg).decode(RoutingMessage.ENC), their_ver_key, my_ver_key ) keys_map = {} for n in range(len(routing_keys)-1, 0, -1): # example: IF routing_keys = ['k1', 'k2', 'k3'] THEN n = [2,1] outer_key = routing_keys[n] inner_key = routing_keys[n-1] keys_map[outer_key] = inner_key keys_map[routing_keys[0]] = their_ver_key for outer_key in routing_keys: inner_key = keys_map[outer_key] forwarded = Message({ '@type': RoutingMessage.FORWARD, 'to': inner_key, 'msg': json.loads(payload.decode(RoutingMessage.ENC)) }) payload = await wallet.pack_message( Serializer.serialize(forwarded).decode(RoutingMessage.ENC), outer_key, ) return payload
async def unpack_agent_message(wire_msg_bytes, wallet: WalletConnection): if isinstance(wire_msg_bytes, str): wire_msg_bytes = bytes(wire_msg_bytes, 'utf-8') unpacked = await wallet.unpack_message(wire_msg_bytes) from_key = None from_did = None their_endpoint = None their_routing_keys = None context = Context() if 'sender_verkey' in unpacked: from_key = unpacked['sender_verkey'] from_did = await indy_sdk_utils.did_for_key( wallet, unpacked['sender_verkey']) pairwise_info = await wallet.get_pairwise(from_did) pairwise_meta = pairwise_info['metadata'] their_endpoint = pairwise_meta['their_endpoint'] their_routing_keys = pairwise_meta.get('their_routing_keys', None) to_key = unpacked['recipient_verkey'] to_did = await indy_sdk_utils.did_for_key(wallet, unpacked['recipient_verkey']) msg = Serializer.deserialize(unpacked['message']) context.their_did = from_did context.my_did = to_did context.my_ver_key = to_key context.their_verkey = from_key context.their_endpoint = their_endpoint context.their_routing_keys = their_routing_keys return msg, context
async def test_pack_message_multi_recp_keys(): sender = 'sender' recipient1 = 'recipient1' recipient2 = 'recipient2' pass_phrase = 'pass_phrase' await remove_wallets(sender, recipient1, recipient2) conn_sender = WalletConnection(sender, pass_phrase) conn_recipient1 = WalletConnection(recipient1, pass_phrase) conn_recipient2 = WalletConnection(recipient2, pass_phrase) await conn_sender.create() await conn_recipient1.create() await conn_recipient2.create() try: await conn_sender.open() await conn_recipient1.open() await conn_recipient2.open() did_recipient1, verkey_recipient1 = await conn_recipient1.create_and_store_my_did( ) did_recipient2, verkey_recipient2 = await conn_recipient2.create_and_store_my_did( ) message = BasicMessage.build(content='Test content') buf = Serializer.serialize(message).decode(), wired = await conn_sender.pack_message( buf, [verkey_recipient1, verkey_recipient2]) unpacked1 = await conn_recipient1.unpack_message(wired) unpacked2 = await conn_recipient2.unpack_message(wired) assert unpacked1['message'] == unpacked2['message'] assert unpacked1['recipient_verkey'] != unpacked2['recipient_verkey'] finally: await conn_sender.delete() await conn_recipient1.delete() await conn_recipient2.delete()
async def receive_invite_link( cls, link: str, agent_name: str, pass_phrase: str, my_label: str, my_endpoint: str, ttl: int, my_did: str=None ): await WalletAgent.ensure_agent_is_open(agent_name, pass_phrase) matches = re.match("(.+)?c_i=(.+)", link) if not matches: raise BadInviteException("Invite string is improperly formatted") invite_msg = Serializer.deserialize( base64.urlsafe_b64decode(matches.group(2)).decode('utf-8') ) if cls.endorsement(invite_msg): return await cls.receive_invite_message(invite_msg, agent_name, pass_phrase, my_label, my_endpoint, ttl) else: return None
async def send_message_to_endpoint_and_key(their_ver_key: str, their_endpoint: str, msg: Message, wallet: WalletConnection, my_ver_key: str=None): # If my_ver_key is omitted, anon-crypt is used inside pack. try: wire_message = await wallet.pack_message( Serializer.serialize(msg).decode('utf-8'), their_ver_key, my_ver_key ) except Exception as e: logging.exception(str(e)) raise else: transport = EndpointTransport(address=their_endpoint) await transport.send_wire_message(wire_message)
def build(label: str, connection_key: str, endpoint: str) -> str: msg = Message({ '@type': DIDExchange.INVITE, 'label': label, 'recipientKeys': [connection_key], 'serviceEndpoint': endpoint, # routing_keys not specified, but here is where they would be put in the invite. }) b64_invite = base64.urlsafe_b64encode( bytes( Serializer.serialize(msg).decode('utf-8'), 'ascii' ) ).decode('ascii') return '{}?c_i={}'.format(endpoint, b64_invite)
async def send_problem_report(wallet: WalletConnection, problem_code: str, problem_str: str, context: Context, thread_id: str = None): err_msg = IssueCredentialProtocol.build_problem_report_for_connections( problem_code, problem_str, thread_id) try: wire_message = await wallet.pack_message( Serializer.serialize(err_msg).decode('utf-8'), context.their_verkey, context.my_ver_key) except Exception as e: logging.exception(str(e)) raise else: transport = EndpointTransport(address=context.their_endpoint) await transport.send_wire_message(wire_message) return err_msg
def parse(invite_url: str) -> Message: matches = re.match('(.+)?c_i=(.+)', invite_url) assert matches, 'Improperly formatted invite url!' invite_msg = Serializer.deserialize( base64.urlsafe_b64decode(matches.group(2)).decode('ascii') ) invite_msg.check_for_attrs( [ ('@type', DIDExchange.INVITE), 'label', 'recipientKeys', 'serviceEndpoint' ] ) return invite_msg
async def unpack_agent_message(wire_msg_bytes, wallet: WalletConnection): if isinstance(wire_msg_bytes, str): wire_msg_bytes = bytes(wire_msg_bytes, 'utf-8') unpacked = await wallet.unpack_message(wire_msg_bytes) from_key = None from_did = None if 'sender_verkey' in unpacked: from_key = unpacked['sender_verkey'] from_did = await indy_sdk_utils.did_for_key(wallet, unpacked['sender_verkey']) to_key = unpacked['recipient_verkey'] to_did = await indy_sdk_utils.did_for_key(wallet, unpacked['recipient_verkey']) msg = Serializer.deserialize(unpacked['message']) msg.context = { 'from_did': from_did, # Could be None 'to_did': to_did, # Could be None 'from_key': from_key, # Could be None 'to_key': to_key } return msg
async def unpack_agent_message(wire_msg_bytes, wallet: WalletConnection): print('===== 0036 unpack_agent_message ======') if isinstance(wire_msg_bytes, str): wire_msg_bytes = bytes(wire_msg_bytes, 'utf-8') unpacked = await wallet.unpack_message(wire_msg_bytes) print('unpacked: \n' + json.dumps(unpacked, indent=2, sort_keys=True)) from_key = None from_did = None their_endpoint = None context = Context() if 'sender_verkey' in unpacked: from_key = unpacked['sender_verkey'] from_did = await indy_sdk_utils.did_for_key( wallet, unpacked['sender_verkey']) pairwise_info = await wallet.get_pairwise(from_did) pairwise_meta = pairwise_info['metadata'] their_endpoint = pairwise_meta['their_endpoint'] to_key = unpacked['recipient_verkey'] to_did = await indy_sdk_utils.did_for_key(wallet, unpacked['recipient_verkey']) msg = Serializer.deserialize(unpacked['message']) print('from_did: ' + str(from_did)) print('to_did: ' + str(to_did)) print('to_key: ' + str(to_key)) print('from_key: ' + str(from_key)) print('their_endpoint: ' + str(their_endpoint)) context.their_did = from_did context.my_did = to_did context.my_ver_key = to_key context.their_verkey = from_key context.their_endpoint = their_endpoint print('===========') return msg, context
async def __send_connection_request(self, invitation: Message): """Connection Request""" their = dict( label=invitation['label'], connection_key=invitation['recipientKeys'][0], endpoint=invitation['serviceEndpoint'] ) # Create my information for connection my_did, my_vk = await indy_sdk_utils.create_and_store_my_did(self.get_wallet()) await self.get_wallet().set_did_metadata(my_did, their) # Send Connection Request to inviter request = DIDExchange.Request.build(self.label, my_did, my_vk, self.endpoint) try: wire_message = await self.get_wallet().pack_message( message=Serializer.serialize(request).decode('utf-8'), their_ver_key=their['connection_key'], my_ver_key=my_vk ) transport = EndpointTransport(address=their['endpoint']) await transport.send_wire_message(wire_message) await self.__log('Send', request.to_dict()) except Exception as e: logging.exception(str(e)) raise
async def generate_invite_link(cls, label: str, endpoint: str, agent_name: str, pass_phrase: str, extra: dict=None): invite_msg = await cls.generate_invite_message(label, endpoint, agent_name, pass_phrase, extra) b64_invite = base64.urlsafe_b64encode(Serializer.serialize(invite_msg)).decode('ascii') return '?c_i=' + b64_invite, invite_msg
def test_invitation_ensure_exists(self): conn = WalletConnection(self.WALLET_UID, self.WALLET_PASS_PHRASE) wallet = Wallet.objects.create(uid=self.WALLET_UID, owner=self.account) endpoint = Endpoint.objects.create(uid='endpoint_uid', owner=self.account, wallet=wallet, url='http://example.com/endpoint') # first: create wallet run_async(conn.create()) run_async(conn.open()) my_did, my_verkey = run_async(conn.create_and_store_my_did()) run_async(conn.close()) try: seed = 'blablabla-seed-' expected_key = '3XvPjB4EDpmBBF4sRmqVbrQXQY5vk7zjiggSCGxSkPpV' cred = dict(pass_phrase=self.WALLET_PASS_PHRASE, seed=seed) url = self.live_server_url + '/agent/admin/wallets/%s/endpoints/%s/invitations/ensure_exists/' % ( self.WALLET_UID, endpoint.uid) resp = requests.post(url, json=cred, auth=HTTPBasicAuth(self.IDENTITY, self.PASS)) self.assertEqual(200, resp.status_code) i1 = resp.json() instance = Invitation.objects.get(endpoint=endpoint) self.assertEqual(seed, instance.seed) self.assertEqual(expected_key, instance.connection_key) self.assertIsNone(instance.my_did) resp = requests.post(url, json=cred, auth=HTTPBasicAuth(self.IDENTITY, self.PASS)) self.assertEqual(200, resp.status_code) i2 = resp.json() self.assertEqual( 1, Invitation.objects.filter(connection_key=expected_key).count()) matches = re.match("(.+)?c_i=(.+)", i1['url']) invite_msg1 = Serializer.deserialize( base64.urlsafe_b64decode( matches.group(2)).decode('utf-8')).to_dict() del invite_msg1['@id'] matches = re.match("(.+)?c_i=(.+)", i2['url']) invite_msg2 = Serializer.deserialize( base64.urlsafe_b64decode( matches.group(2)).decode('utf-8')).to_dict() del invite_msg2['@id'] self.assertDictEqual(invite_msg1, invite_msg2) cred['my_did'] = my_did resp = requests.post(url, json=cred, auth=HTTPBasicAuth(self.IDENTITY, self.PASS)) self.assertEqual(200, resp.status_code) instance = Invitation.objects.get(endpoint=endpoint) self.assertEqual(my_did, instance.my_did) self.assertEqual(1, Invitation.objects.count()) cred = dict(pass_phrase=self.WALLET_PASS_PHRASE, seed=seed + 'salt') resp = requests.post(url, json=cred, auth=HTTPBasicAuth(self.IDENTITY, self.PASS)) self.assertEqual(200, resp.status_code) self.assertEqual(2, Invitation.objects.count()) finally: os.popen("pkill -f run_wallet_agent") sleep(1) run_async(conn.delete())