Example #1
0
async def message_process(agent):
    """ Message processing loop task.
        Message routes are also defined here through the message router.
    """
    msg_router = agent['msg_router']
    msg_receiver = agent['msg_receiver']
    ui_event_queue = agent['ui_event_queue']

    await msg_router.register(CONN.REQUEST, connection.handle_request)
    await msg_router.register(CONN.RESPONSE, connection.handle_response)

    while True:
        encrypted_msg_bytes = await msg_receiver.recv()
        # TODO: make this logic work
        try:
            decrypted_msg_bytes = await crypto.anon_decrypt(
                    agent.wallet_handle,
                    agent.endpoint_vk,
                    encrypted_msg_bytes
                    )
        except Exception as e:
            print('Could not decrypt message: {}\nError: {}'.format(msg_bytes, e))
            continue

        try:
            msg = Serializer.unpack(encrypted_msg_bytes)
        except Exception as e:
            print('Failed to unpack message: {}\n\nError: {}'.format(msg_bytes, e))
            continue

        res = await msg_router.route(msg, agent['agent'])
        if res is not None:
            await ui_event_queue.send(Serializer.pack(res))
Example #2
0
async def ui_event_process(agent):
    ui_router = agent['ui_router']
    ui_event_queue = agent['ui_event_queue']
    connection = agent['modules']['connection']
    ui = agent['modules']['ui']

    ui_router.register(CONN_UI.FAMILY, connection)
    ui_router.register(UI.FAMILY, ui)
    ui_router.register(ADMIN_WALLETCONNECTION.FAMILY,
                       agent['modules']['admin_walletconnection'])

    while True:
        msg = await ui_event_queue.recv()

        if not isinstance(msg, Message):
            try:
                msg = Serializer.unpack(msg)
            except Exception as e:
                print('Failed to unpack message: {}\n\nError: {}'.format(
                    msg, e))
                continue

        if msg['ui_token'] != UI_TOKEN:
            print('Invalid token received, rejecting message: {}'.format(msg))
            continue

        res = await ui_router.route(msg)
        if res is not None:
            await ui_event_queue.send(Serializer.pack(res))
Example #3
0
    async def send_message_to_endpoint_and_key(self, my_ver_key, their_ver_key,
                                               their_endpoint, msg):
        wire_message = {
            'to':
            their_ver_key,
            'from':
            my_ver_key,
            'payload':
            serialize_bytes_json(await crypto.auth_crypt(
                self.wallet_handle, my_ver_key, their_ver_key,
                str_to_bytes(msg.as_json())))
        }

        wire_message = await crypto.pack_message(self.wallet_handle,
                                                 Serializer.pack(msg),
                                                 [their_ver_key], my_ver_key)

        async with aiohttp.ClientSession() as session:
            headers = {'content-type': 'application/ssi-agent-wire'}
            async with session.post(their_endpoint,
                                    data=wire_message,
                                    headers=headers) as resp:
                if resp.status != 202:
                    print(resp.status)
                    print(await resp.text())
Example #4
0
async def send_response(to_did, agent):
    """ sends a connection response should be anon_encrypted.

        a connection response will include:

        - user DID, and verkey
    """

    # find endpoint
    wallet_handle = agent.wallet_handle
    meta = json.loads(await did.get_did_metadata(wallet_handle, to_did))
    endpoint = meta['endpoint']
    endpoint_vk = meta['endpoint_vk']

    their_vk = await did.key_for_local_did(wallet_handle, to_did)

    pairwise_json = json.loads(await
                               pairwise.get_pairwise(wallet_handle, to_did))
    my_did = pairwise_json['my_did']
    my_vk = await did.key_for_local_did(wallet_handle, my_did)

    data = {'did': my_did, 'verkey': my_vk}

    data = await crypto.anon_crypt(their_vk, json.dumps(data).encode('utf-8'))

    envelope = json.dumps({'type': 'CONN_RES', 'id': to_did, 'data': data})

    encrypted_envelope = await crypto.anon_crypt(endpoint_vk,
                                                 Serializer.pack(envelope))

    async with aiohttp.ClientSession() as session:
        async with session.post(endpoint, data=envelope) as resp:
            print(resp.status)
            print(await resp.text())
    async def recieve_invite(self, msg):
        '''
        Recieve invitation from user to create a pending connection.
        :param msg: code generated from user
        '''
        invite_msg = Serializer.unpack(
            base64.urlsafe_b64decode(msg).decode('utf-8'))

        print("\nMESSAGE RECEIVED: ", invite_msg)

        pending_connection = Message({
            '@type':
            "INVITE_RECEIVED",
            'label':
            invite_msg['label'],
            'connection_key':
            invite_msg['recipientKeys'][0],
            'history': [{
                'date': str(datetime.datetime.now()),
                'msg': invite_msg.to_dict()
            }],
            'status':
            "Invite Received"
        })
        print("\nPENDING CONNECTION", pending_connection)
        # Store invitation in the wallet
        await non_secrets.add_wallet_record(
            self.agent.wallet_handle,
            'invitations', invite_msg['recipientKeys'][0],
            Serializer.pack(pending_connection), '{}')
        return True
Example #6
0
async def ui_event_process(agent):
    ui_router = agent['ui_router']
    ui_event_queue = agent['ui_event_queue']

    await ui_router.register(UI.SEND_OFFER, connection.send_offer)
    await ui_router.register(UI.STATE_REQUEST, ui.ui_connect)
    await ui_router.register(UI.INITIALIZE, init.initialize_agent)
    await ui_router.register(UI.SEND_OFFER_ACCEPTED, connection.send_offer_accepted)
    await ui_router.register(UI.SENDER_SEND_OFFER_REJECTED, connection.sender_send_offer_rejected)
    await ui_router.register(UI.RECEIVER_SEND_OFFER_REJECTED, connection.receiver_send_offer_rejected)
    await ui_router.register(UI.SEND_CONN_REJECTED, connection.send_conn_rejected)

    while True:
        msg_bytes = await ui_event_queue.recv()
        try:
            msg = Serializer.unpack(msg_bytes)
        except Exception as e:
            print('Failed to unpack message: {}\n\nError: {}'.format(msg_bytes, e))
            continue

        if msg.id != UI_TOKEN:
            print('Invalid token received, rejecting message: {}'.format(msg_bytes))
            continue

        res = await ui_router.route(msg, agent['agent'])
        if res is not None:
            await ui_event_queue.send(Serializer.pack(res))
Example #7
0
async def send_request(offer, agent):
    """ sends a connection request.

        a connection request contains:
         - data concerning the request:
           - Name of Sender
           - Purpose

           - DID@A:B
           - URL of agent
           - Public verkey
    """

    conn_name = offer['name']
    our_endpoint = agent.endpoint
    endpoint_vk = offer['verkey']

    # get did and vk
    (my_did,
     my_vk) = await did.create_and_store_my_did(agent.wallet_handle, "{}")

    msg = Message(
        CONN.REQUEST,
        offer['nonce'],
        {
            'did': my_did,
            'verkey': my_vk,
            'endpoint': {
                'url': agent.endpoint,
                'verkey': agent.endpoint_vk,
            },

            #Extra Metadata
            'owner': agent.owner,
        })
    serialized_msg = Serializer.pack(msg)

    # add to queue
    agent.connections[my_did] = {
        "name": offer['name'],
        "endpoint": offer['endpoint'],
        "time": str(datetime.datetime.now()).split(' ')[1].split('.')[0],
        "status": "pending"
    }

    # send to server
    print("Sending to {}".format(offer['endpoint']))
    async with aiohttp.ClientSession() as session:
        async with session.post(offer['endpoint'],
                                data=serialized_msg) as resp:
            print(resp.status)
            print(await resp.text())

    return {
        'type': 'CONN_REQ_SENT',
        'id': None,
        'data': agent.connections[my_did]
    }
Example #8
0
    async def receive_invite(self, msg: Message) -> Message:
        """ Receive and save invite.

            This interaction represents an out-of-band communication channel. In the future and in
            practice, these sort of invitations will be received over any number of channels such as
            SMS, Email, QR Code, NFC, etc.

            In this iteration, invite messages are received from the admin interface as a URL
            after being copied and pasted from another agent instance.

            The URL is formatted as follows:

                https://<domain>/<path>?c_i=<invitationstring>

            The invitation string is a base64 url encoded json string.

            Structure of an invite message:

                {
                    "@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/invitation",
                    "label": "Alice",
                    "did": "did:sov:QmWbsNYhMrjHiqZDTUTEJs"
                }

            Or, in the case of a peer DID:

                {
                    "@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/invitation",
                    "label": "Alice",
                    "key": "8HH5gYEeNc3z7PYXmd54d4x6qAfCNrqQqEB3nS7Zfu7K",
                    "endpoint": "https://example.com/endpoint"
                }

            Currently, only peer DID format is supported.
        """

        # Parse invite string
        matches = re.match("(.+)?c_i=(.+)", msg['invite'])
        if not matches:
            raise BadInviteException("Invite string is improperly formatted")

        invite_msg = Serializer.unpack(
            base64.urlsafe_b64decode(matches.group(2)).decode('utf-8'))

        record = uuid.uuid4().hex

        await self.agent.send_admin_message(
            Message({
                '@type': AdminConnection.INVITE_RECEIVED,
                'label': invite_msg['label'],
                'key': invite_msg['key'],
                'endpoint': invite_msg['endpoint']
            }))

        await non_secrets.add_wallet_record(self.agent.wallet_handle,
                                            'invitation', invite_msg['key'],
                                            Serializer.pack(invite_msg), '{}')
Example #9
0
    async def generate_invite(self, msg: Message) -> Message:
        """ Generate new connection invitation.

            This interaction represents an out-of-band communication channel. In the future and in
            practice, these sort of invitations will be received over any number of channels such as
            SMS, Email, QR Code, NFC, etc.

            Structure of an invite message:

                {
                    "@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/invitation",
                    "label": "Alice",
                    "did": "did:sov:QmWbsNYhMrjHiqZDTUTEJs"
                }

            Or, in the case of a peer DID:

                {
                    "@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/invitation",
                    "label": "Alice",
                    "did": "did:peer:oiSqsNYhMrjHiqZDTUthsw",
                    "key": "8HH5gYEeNc3z7PYXmd54d4x6qAfCNrqQqEB3nS7Zfu7K",
                    "endpoint": "https://example.com/endpoint"
                }

            Currently, only peer DID is supported.
        """
        connection_key = await did.create_key(self.agent.wallet_handle, "{}")

        # Store connection key
        await non_secrets.add_wallet_record(
            self.agent.wallet_handle,
            'connection_key',
            connection_key,
            connection_key,
            '{}'
        )

        invite_msg = Message({
            '@type': Connection.INVITE,
            'label': self.agent.owner,
            'recipientKeys': [connection_key],
            'serviceEndpoint': self.agent.endpoint,
            # routingKeys not specified, but here is where they would be put in the invite.
        })

        b64_invite = \
            base64.urlsafe_b64encode(bytes(Serializer.pack(invite_msg), 'utf-8')).decode('ascii')

        await self.agent.send_admin_message(
            Message({
                '@type': AdminConnection.INVITE_GENERATED,
                'invite': '{}?c_i={}'.format(self.agent.endpoint, b64_invite)
            })
        )
Example #10
0
    async def send_admin_message(self, msg: Message):
        if self.agent_admin_key and self.admin_key:
            msg = await crypto.pack_message(self.wallet_handle,
                                            Serializer.pack(msg),
                                            [self.admin_key],
                                            self.agent_admin_key)
            msg = msg.decode('ascii')
        else:
            msg = msg.as_json()

        await self.outbound_admin_message_queue.put(msg)
Example #11
0
    async def send_message_to_endpoint_and_key(self, my_ver_key, their_ver_key,
                                               msg):
        '''
        Message is encrypted and sent to the other user through the server
        '''
        print("\nSend message to end and key")
        print(my_ver_key, their_ver_key, msg)

        wire_message = await crypto.pack_message(self.wallet_handle,
                                                 Serializer.pack(msg),
                                                 [their_ver_key], my_ver_key)
        print("wire:", wire_message)
        socket_client.send(wire_message)
        print("SEND MESSAGE")
Example #12
0
    async def send_message_to_endpoint_and_key(self,
                                               their_ver_key,
                                               their_endpoint,
                                               msg,
                                               my_ver_key=None):
        # If my_ver_key is omitted, anoncrypt is used inside pack.
        wire_message = await crypto.pack_message(self.wallet_handle,
                                                 Serializer.pack(msg),
                                                 [their_ver_key], my_ver_key)

        async with aiohttp.ClientSession() as session:
            headers = {'content-type': 'application/ssi-agent-wire'}
            async with session.post(their_endpoint,
                                    data=wire_message,
                                    headers=headers) as resp:
                if resp.status != 202:
                    print(resp.status)
                    print(await resp.text())
Example #13
0
async def sender_send_offer_rejected(msg, agent):
    conn_name = msg.message['name']
    nonce = msg.message['id']

    receiver_endpoint = agent.pending_offers[nonce]['endpoint']
    del agent.pending_offers[nonce]

    rej_msg = Message(CONN.SENDER_REJECTION, nonce, {'name': conn_name})
    serialized_msg = Serializer.pack(rej_msg)
    async with aiohttp.ClientSession() as session:
        async with session.post(receiver_endpoint,
                                data=serialized_msg) as resp:
            print(resp.status)
            print(await resp.text())

    return Message(UI.SENDER_OFFER_REJECTED, agent.ui_token, {
        'name': conn_name,
        'id': nonce
    })
Example #14
0
async def conn_process(agent):
    conn_router = agent['conn_router']
    conn_receiver = agent['conn_receiver']
    ui_event_queue = agent['ui_event_queue']
    connection = agent['modules']['connection']

    conn_router.register(CONN.FAMILY, connection)

    while True:
        msg_bytes = await conn_receiver.recv()
        try:
            msg = Serializer.unpack(msg_bytes)
        except Exception as e:
            print('Failed to unpack message: {}\n\nError: {}'.format(msg_bytes, e))
            continue

        res = await conn_router.route(msg)
        if res is not None:
            await ui_event_queue.send(Serializer.pack(res))
Example #15
0
    async def send_invite(self, msg: Message) -> Message:
        """ UI activated method.
        """

        their_endpoint = msg['endpoint']
        conn_name = msg['name']

        (endpoint_did_str, connection_key) = await did.create_and_store_my_did(
            self.agent.wallet_handle, "{}")

        meta_json = json.dumps({"conn_name": conn_name})

        await did.set_did_metadata(self.agent.wallet_handle, endpoint_did_str,
                                   meta_json)

        msg = Message({
            '@type': Connection.INVITE,
            'content': {
                'name': conn_name,
                'endpoint': {
                    'url': self.agent.endpoint,
                },
                'connection_key': connection_key
            }
        })
        serialized_msg = Serializer.pack(msg)
        async with aiohttp.ClientSession() as session:
            async with session.post(their_endpoint,
                                    data=serialized_msg) as resp:
                print(resp.status)
                print(await resp.text())

        await self.agent.send_admin_message(
            Message({
                '@type': AdminConnection.INVITE_SENT,
                'id': self.agent.ui_token,
                'content': {
                    'name': conn_name
                }
            }))
    async def credential_received(self, msg: Message) -> Message:
        '''
        Prover receives the credential
        '''
        print("\n\n CREDENTIAL RECIEVED\n\n")
        data = msg['data']
        schematype = data['schematype']
        nonce = data['nonce']
        their_did = data['my_did']  # this message comes from other agent
        my_did = data['their_did']  # this message comes form other agent

        await anoncreds.prover_store_credential(self.agent.wallet_handle, None,
                                                data['cred_request_meta'],
                                                data['cred'], data['cred_def'],
                                                None)
        if (schematype == 'medical'):
            self.agent.medical_cred_def_id = data['cred_def_id']
            self.agent.medical_cred_offer = data['cred_offer']
            self.agent.got_medical_credential = True

        if (schematype == 'consent'):
            self.agent.got_consent_credential = True

        print("+++ Credential prover stores credential: their did: " +
              their_did)
        print("Credential: got credential. Sending to view." +
              self.agent.owner)

        credential_msg = Message({
            '@type': Credential.CREDENTIAL_OBTAINED,
            'label': self.agent.owner,
            'schematype': schematype,
            'data': data['cred']
        })

        b64_cred = \
            base64.urlsafe_b64encode(bytes(Serializer.pack(credential_msg), 'utf-8')).decode('ascii')

        print("CREDENTIAL: done storing credential")
Example #17
0
async def send_offer(msg, agent):
    endpoint = msg.message['endpoint']
    name = msg.message['name']
    nonce = uuid.uuid4().hex
    agent.pending_offers[nonce] = dict(name=name, endpoint=endpoint)

    msg = Message(
        CONN.OFFER, nonce, {
            'name': name,
            'endpoint': {
                'url': agent.endpoint,
                'verkey': agent.endpoint_vk,
            },
            'offer_endpoint': agent.offer_endpoint
        })
    serialized_msg = Serializer.pack(msg)
    async with aiohttp.ClientSession() as session:
        async with session.post(endpoint, data=serialized_msg) as resp:
            print(resp.status)
            print(await resp.text())

    return Message(UI.OFFER_SENT, agent.ui_token, {'name': name, 'id': nonce})
Example #18
0
async def conn_process(agent):
    conn_router = agent['conn_router']
    conn_receiver = agent['conn_receiver']
    ui_event_queue = agent['ui_event_queue']

    await conn_router.register(CONN.OFFER, connection.offer_recv)
    await conn_router.register(CONN.ACKNOWLEDGE, connection.offer_accepted)
    await conn_router.register(CONN.SENDER_REJECTION, connection.receiver_offer_rejected)
    await conn_router.register(CONN.RECEIVER_REJECTION, connection.sender_offer_rejected)
    await conn_router.register(CONN.REJECTION, connection.conn_rejected)

    while True:
        msg_bytes = await conn_receiver.recv()
        try:
            msg = Serializer.unpack(msg_bytes)
        except Exception as e:
            print('Failed to unpack message: {}\n\nError: {}'.format(msg_bytes, e))
            continue

        res = await conn_router.route(msg, agent['agent'])
        if res is not None:
            await ui_event_queue.send(Serializer.pack(res))
Example #19
0
async def send_offer_accepted(msg, agent):
    nonce = msg.message['id']
    receiver_endpoint = agent.received_offers[nonce]['endpoint']
    conn_name = msg.message['name']

    agent.connections[nonce] = dict(name=conn_name, endpoint=receiver_endpoint)
    del agent.received_offers[nonce]

    msg = Message(CONN.ACKNOWLEDGE, nonce, {
        'name': conn_name,
    })
    serialized_msg = Serializer.pack(msg)
    async with aiohttp.ClientSession() as session:
        async with session.post(receiver_endpoint,
                                data=serialized_msg) as resp:
            print(resp.status)
            print(await resp.text())

    return Message(UI.OFFER_ACCEPTED_SENT, agent.ui_token, {
        'name': conn_name,
        'id': nonce
    })
    async def generate_invite(self):
        '''
        Creates an invitation code to be send to the other user to process.
        '''
        connection_key = await did.create_key(self.agent.wallet_handle, "{}")
        print("Connection Key: ", connection_key)

        # store key
        await non_secrets.add_wallet_record(self.agent.wallet_handle,
                                            'connection_key', connection_key,
                                            connection_key, '{}')
        invite_msg = Message({
            '@type': "GENERATE_INVITE",
            'label': self.agent.owner,
            'initialized': self.agent.initialized,
            'recipientKeys': [connection_key],
        })
        print("INVITE_MSG: ", invite_msg)

        invite_code = \
            base64.urlsafe_b64encode(
                bytes(Serializer.pack(invite_msg), 'utf-8')).decode('ascii')
        return str(invite_code)
Example #21
0
async def handle_request_received(msg, agent):
    """ Handle reception of request, storing to be accepted later.
    """
    agent.received_requests[msg.did] = Serializer.pack(msg)
Example #22
0
    async def send_message(self, msg: Message) -> Message:
        """ UI activated method.
        """

        their_did_str = msg['to']
        message_to_send = msg['message']

        pairwise_conn_info_str = await pairwise.get_pairwise(self.agent.wallet_handle, their_did_str)
        pairwise_conn_info_json = json.loads(pairwise_conn_info_str)

        my_did_str = pairwise_conn_info_json['my_did']
        time_sent = time.time()

        data_to_send = json.dumps(
            {
                "timestamp": time_sent,
                "content": message_to_send
            }
        )

        # store message in the wallet
        await non_secrets.add_wallet_record(
            self.agent.wallet_handle,
            "basicmessage",
            uuid.uuid4().hex,
            json.dumps({
                'from': my_did_str,
                'timestamp': time_sent,
                'content': message_to_send
            }),
            json.dumps({
                "their_did": their_did_str
            })
        )

        data_to_send_bytes = str_to_bytes(data_to_send)

        metadata_json = json.loads(pairwise_conn_info_json['metadata'])
        conn_name = metadata_json['conn_name']
        their_endpoint = metadata_json['their_endpoint']
        their_verkey_str = metadata_json['their_verkey']

        my_did_info_str = await did.get_my_did_with_meta(self.agent.wallet_handle,
                                                         my_did_str)
        my_did_info_json = json.loads(my_did_info_str)
        my_verkey_str = my_did_info_json['verkey']

        inner_msg = Message({
            '@type': BASICMESSAGE.MESSAGE,
            'from': my_did_str,
            'message': serialize_bytes_json(
                await crypto.auth_crypt(self.agent.wallet_handle, my_verkey_str,
                                        their_verkey_str, data_to_send_bytes))
        })

        outer_msg = Message({
            '@type': FORWARD.FORWARD,
            'to': "ABC",
            'content': inner_msg
        })

        serialized_outer_msg = Serializer.pack(outer_msg)

        serialized_outer_msg_bytes = str_to_bytes(serialized_outer_msg)

        all_message = Message({
            'content': serialize_bytes_json(await crypto.anon_crypt(their_verkey_str,
                                                                 serialized_outer_msg_bytes))
        })

        serialized_msg = Serializer.pack(all_message)

        async with aiohttp.ClientSession() as session:
            async with session.post(their_endpoint, data=serialized_msg) as resp:
                print(resp.status)
                print(await resp.text())

        return Message({
            '@type': ADMIN_BASICMESSAGE.MESSAGE_SENT,
            'id': self.agent.ui_token,
            'with': their_did_str,
            'message': {
                'from': my_did_str,
                'timestamp': time_sent,
                'content': message_to_send
            }
        })
Example #23
0
    async def send_message(self, msg: Message) -> Message:
        """ UI activated method.
        """

        their_did_str = msg['content']['their_did']
        message_to_send = msg['content']['message']

        pairwise_conn_info_str = await pairwise.get_pairwise(
            self.agent.wallet_handle, their_did_str)
        pairwise_conn_info_json = json.loads(pairwise_conn_info_str)

        my_did_str = pairwise_conn_info_json['my_did']

        data_to_send = json.dumps({"message": message_to_send})

        data_to_send_bytes = str_to_bytes(data_to_send)

        metadata_json = json.loads(pairwise_conn_info_json['metadata'])
        conn_name = metadata_json['conn_name']
        their_endpoint = metadata_json['their_endpoint']
        their_verkey_str = metadata_json['their_verkey']

        my_did_info_str = await did.get_my_did_with_meta(
            self.agent.wallet_handle, my_did_str)
        my_did_info_json = json.loads(my_did_info_str)
        my_verkey_str = my_did_info_json['verkey']

        inner_msg = Message({
            'type':
            CONN.MESSAGE,
            'to':
            "did:sov:ABC",
            'content':
            serialize_bytes_json(await
                                 crypto.auth_crypt(self.agent.wallet_handle,
                                                   my_verkey_str,
                                                   their_verkey_str,
                                                   data_to_send_bytes))
        })

        outer_msg = Message({
            'type': FORWARD.FORWARD,
            'to': "ABC",
            'content': inner_msg
        })

        serialized_outer_msg = Serializer.pack(outer_msg)

        serialized_outer_msg_bytes = str_to_bytes(serialized_outer_msg)

        all_message = Message({
            'content':
            serialize_bytes_json(await
                                 crypto.anon_crypt(their_verkey_str,
                                                   serialized_outer_msg_bytes))
        })

        serialized_msg = Serializer.pack(all_message)

        async with aiohttp.ClientSession() as session:
            async with session.post(their_endpoint,
                                    data=serialized_msg) as resp:
                print(resp.status)
                print(await resp.text())

        return Message({
            'type': CONN_UI.MESSAGE_SENT,
            'id': self.agent.ui_token,
            'content': {
                'name': conn_name
            }
        })
Example #24
0
    async def request_received(self, msg: Message) -> Message:
        """ Received connection request.

            Request format:

                {
                  "@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/request",
                  "label": "Bob",
                  "connection":{
                      "did": "B.did@B:A",
                      "did_doc": {
                          "@context": "https://w3id.org/did/v1",
                          "publicKey": [{
                            "id": "did:example:123456789abcdefghi#keys-1",
                            "type": "Ed25519VerificationKey2018",
                            "controller": "did:example:123456789abcdefghi",
                            "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
                          }],
                          "service": [{
                            "type": "IndyAgent",
                            "recipientKeys" : [ "<verkey>" ], //pick one
                            "routingKeys": ["<example-agency-verkey>"],
                            "serviceEndpoint": "https://example.agency.com",
                          }]
                      }
                  }
                }
        """
        connection_key = msg.context['to_key']

        label = msg['label']
        their_did = msg['connection']['did']
        # NOTE: these values are pulled based on the minimal connectathon format. Full processing
        #  will require full DIDDoc storage and evaluation.
        their_vk = msg['connection']['did_doc']['publicKey'][0]['publicKeyBase58']
        their_endpoint = msg['connection']['did_doc']['service'][0]['serviceEndpoint']

        # Store their information from request
        await utils.store_their_did(self.agent.wallet_handle, their_did, their_vk)

        await did.set_did_metadata(
            self.agent.wallet_handle,
            their_did,
            json.dumps({
                'label': label,
                'endpoint': their_endpoint,

            })
        )

        # Create my information for connection
        (my_did, my_vk) = await utils.create_and_store_my_did(self.agent.wallet_handle)

        # Create pairwise relationship between my did and their did
        await pairwise.create_pairwise(
            self.agent.wallet_handle,
            their_did,
            my_did,
            json.dumps({
                'label': label,
                'req_id': msg['@id'],
                'their_endpoint': their_endpoint,
                'their_vk': their_vk,
                'my_vk': my_vk,
                'connection_key': connection_key  # used to sign the response
            })
        )

        pending_connection = Message({
            '@type': AdminConnection.REQUEST_RECEIVED,
            'label': label,
            'did': their_did,
            'connection_key': connection_key,
            'endpoint': their_endpoint,
            'history': [{
                'date': str(datetime.datetime.now()),
                'msg': msg.to_dict()}],
            'status': "Request Received"
            # routingKeys not specified, but here is where they would be put in the invite.
        })
        try:
            await non_secrets.add_wallet_record(
                self.agent.wallet_handle,
                'invitations',
                connection_key,
                Serializer.pack(pending_connection),
                '{}'
            )
        except error.IndyError as indy_error:
            if indy_error.error_code == error.ErrorCode.WalletItemAlreadyExists:
                pass
            raise indy_error
        await self.agent.send_admin_message(pending_connection)
Example #25
0
    async def send_request(self, msg: Message):
        """ Recall invite message from wallet and prepare and send request to the inviter.

            send_request message format:

                {
                  "@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/admin_connections/1.0/send_request",
                  "key": <key sent in invite>
                }

            Request format:

                {
                  "@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/request",
                  "label": "Bob",
                  "did": "B.did@B:A",
                  "did_doc": {
                      // did Doc here.
                  }
                }
        """
        pending_connection = Serializer.unpack(
            json.loads(
                await non_secrets.get_wallet_record(
                    self.agent.wallet_handle,
                    'invitations',
                    msg['connection_key'],
                    '{}'
                )
            )['value']
        )

        my_label = self.agent.owner
        label = pending_connection['label']
        their_connection_key = pending_connection['connection_key']
        their_endpoint = pending_connection['endpoint']

        # Create my information for connection
        (my_did, my_vk) = await utils.create_and_store_my_did(self.agent.wallet_handle)

        await did.set_did_metadata(
            self.agent.wallet_handle,
            my_did,
            json.dumps({
                'label': label,
                'their_endpoint': their_endpoint
            })
        )

        # Send Connection Request to inviter
        request = Message({
            '@type': Connection.REQUEST,
            'label': my_label,
            'connection': {
                'did': my_did,
                'did_doc': {
                    "@context": "https://w3id.org/did/v1",
                    "id": my_did,
                    "publicKey": [{
                        "id": my_did + "#keys-1",
                        "type": "Ed25519VerificationKey2018",
                        "controller": my_did,
                        "publicKeyBase58": my_vk
                    }],
                    "service": [{
                        "id": my_did + ";indy",
                        "type": "IndyAgent",
                        "recipientKeys": [my_vk],
                        #"routingKeys": ["<example-agency-verkey>"],
                        "serviceEndpoint": self.agent.endpoint,
                    }],
                }
            }
        })

        await self.agent.send_message_to_endpoint_and_key(
            my_vk,
            their_connection_key,
            their_endpoint,
            request
        )

        pending_connection['@type'] = AdminConnection.REQUEST_SENT
        pending_connection['status'] = "Request Sent"
        pending_connection['history'].append({
            'date': str(datetime.datetime.now()),
            'msg': msg.to_dict()})
        await non_secrets.update_wallet_record_value(self.agent.wallet_handle,
                                                     'invitations',
                                                     pending_connection['connection_key'],
                                                     Serializer.pack(pending_connection))

        await self.agent.send_admin_message(pending_connection)
Example #26
0
    async def request_received(self, msg: Message) -> Message:
        """ Received connection request.

            Request format:

                {
                  "@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/request",
                  "label": "Bob",
                  "connection":{
                      "did": "B.did@B:A",
                      "did_doc": {
                          "@context": "https://w3id.org/did/v1",
                          "publicKey": [{
                            "id": "did:example:123456789abcdefghi#keys-1",
                            "type": "Ed25519VerificationKey2018",
                            "controller": "did:example:123456789abcdefghi",
                            "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
                          }],
                          "service": [{
                            "type": "IndyAgent",
                            "recipientKeys" : [ "<verkey>" ], //pick one
                            "routingKeys": ["<example-agency-verkey>"],
                            "serviceEndpoint": "https://example.agency.com",
                          }]
                      }
                  }
                }
        """
        r = await self.validate_common_message_blocks(msg, Connection.FAMILY)
        if not r:
            return r

        try:
            ConnectionMessage.Request.validate(msg)
        except Exception as e:
            vk, endpoint = ConnectionMessage.extract_verkey_endpoint(msg)
            if None in (vk, endpoint):
                # Cannot extract verkey and endpoint hence won't send any message back.
                print('Encountered error parsing connection request ', e)
            else:
                # Sending an error message back to the sender
                err_msg = self.build_problem_report_for_connections(Connection.FAMILY, ConnectionMessage.REQUEST_NOT_ACCEPTED, str(e))
                await self.agent.send_message_to_endpoint_and_key(vk, endpoint, err_msg)
            return

        connection_key = msg.context['to_key']

        label = msg['label']

        their_did, their_vk, their_endpoint = ConnectionMessage.extract_their_info(msg)

        # Store their information from request
        await utils.store_their_did(self.agent.wallet_handle, their_did, their_vk)

        await did.set_did_metadata(
            self.agent.wallet_handle,
            their_did,
            json.dumps({
                'label': label,
                'endpoint': their_endpoint,

            })
        )

        # Create my information for connection
        (my_did, my_vk) = await utils.create_and_store_my_did(self.agent.wallet_handle)

        # Create pairwise relationship between my did and their did
        await pairwise.create_pairwise(
            self.agent.wallet_handle,
            their_did,
            my_did,
            json.dumps({
                'label': label,
                'req_id': msg['@id'],
                'their_endpoint': their_endpoint,
                'their_vk': their_vk,
                'my_vk': my_vk,
                'connection_key': connection_key  # used to sign the response
            })
        )

        pending_connection = Message({
            '@type': AdminConnection.REQUEST_RECEIVED,
            'label': label,
            'did': their_did,
            'connection_key': connection_key,
            'endpoint': their_endpoint,
            'history': [{
                'date': str(datetime.datetime.now()),
                'msg': msg.to_dict()}],
            'status': "Request Received"
            # routingKeys not specified, but here is where they would be put in the invite.
        })
        try:
            await non_secrets.add_wallet_record(
                self.agent.wallet_handle,
                'invitations',
                connection_key,
                Serializer.pack(pending_connection),
                '{}'
            )
        except error.IndyError as indy_error:
            if indy_error.error_code == error.ErrorCode.WalletItemAlreadyExists:
                pass
            raise indy_error
        await self.agent.send_admin_message(pending_connection)
Example #27
0
    async def send_request(self, msg: Message) -> Message:
        """ UI activated method.
        """

        their_endpoint = msg['content']['endpoint']
        conn_name = msg['content']['name']
        their_connection_key = msg['content']['key']

        my_endpoint_uri = self.agent.endpoint

        (my_endpoint_did_str,
         my_connection_key) = await did.create_and_store_my_did(
             self.agent.wallet_handle, "{}")

        data_to_send = json.dumps({
            "did": my_endpoint_did_str,
            "key": my_connection_key
        })

        data_to_send_bytes = str_to_bytes(data_to_send)

        meta_json = json.dumps({
            "conn_name": conn_name,
            "their_endpoint": their_endpoint
        })

        await did.set_did_metadata(self.agent.wallet_handle,
                                   my_endpoint_did_str, meta_json)

        inner_msg = Message({
            'type':
            CONN.REQUEST,
            'to':
            "did:sov:ABC",
            'endpoint':
            my_endpoint_uri,
            'content':
            serialize_bytes_json(await
                                 crypto.auth_crypt(self.agent.wallet_handle,
                                                   my_connection_key,
                                                   their_connection_key,
                                                   data_to_send_bytes))
        })

        outer_msg = Message({
            'type': FORWARD.FORWARD_TO_KEY,
            'to': "ABC",
            'content': inner_msg
        })

        serialized_outer_msg = Serializer.pack(outer_msg)

        serialized_outer_msg_bytes = str_to_bytes(serialized_outer_msg)

        all_message = Message({
            'type':
            CONN.REQUEST,
            'content':
            serialize_bytes_json(await
                                 crypto.anon_crypt(their_connection_key,
                                                   serialized_outer_msg_bytes))
        })

        serialized_msg = Serializer.pack(all_message)

        async with aiohttp.ClientSession() as session:
            async with session.post(their_endpoint,
                                    data=serialized_msg) as resp:
                print(resp.status)
                print(await resp.text())

        return Message({
            'type': CONN_UI.REQUEST_SENT,
            'id': self.agent.ui_token,
            'content': {
                'name': conn_name
            }
        })
Example #28
0
async def message_process(agent):
    """ Message processing loop task.
        Message routes are also defined here through the message router.
    """
    msg_router = agent['msg_router']
    msg_receiver = agent['msg_receiver']
    ui_event_queue = agent['ui_event_queue']
    connection = agent['modules']['connection']

    msg_router.register(CONN.FAMILY, connection)

    while True:
        encrypted_msg_bytes = await msg_receiver.recv()
        try:
            encrypted_msg_str = Serializer.unpack(encrypted_msg_bytes)
        except Exception as e:
            print('Failed to unpack message: {}\n\nError: {}'.format(
                encrypted_msg_bytes, e))
            continue

        encrypted_msg_bytes = base64.b64decode(
            encrypted_msg_str['content'].encode('utf-8'))

        agent_dids_str = await did.list_my_dids_with_meta(
            WEBAPP['agent'].wallet_handle)

        agent_dids_json = json.loads(agent_dids_str)

        this_did = ""

        #  trying to find verkey for encryption
        for agent_did_data in agent_dids_json:
            try:
                decrypted_msg = await crypto.anon_decrypt(
                    WEBAPP['agent'].wallet_handle, agent_did_data['verkey'],
                    encrypted_msg_bytes)
                this_did = agent_did_data['did']
                #  decrypted -> found key, stop loop
                break

            except IndyError as e:
                #  key did not work
                if e.error_code == error.ErrorCode.CommonInvalidStructure:
                    print('Key did not work')
                    continue
                else:
                    #  something else happened
                    print('Could not decrypt message: {}\nError: {}'.format(
                        encrypted_msg_bytes, e))
                    continue

        if not decrypted_msg:
            "Agent doesn't have needed verkey for anon_decrypt"
            continue

        try:
            msg = Serializer.unpack(decrypted_msg)
        except Exception as e:
            print('Failed to unpack message: {}\n\nError: {}'.format(
                decrypted_msg, e))
            continue

        #  pass this connections did with the message
        msg['content']['did'] = this_did
        msg = Serializer.unpack_dict(msg['content'])

        res = await msg_router.route(msg)

        if res is not None:
            await ui_event_queue.send(Serializer.pack(res))
    async def request_recieved(self, msg):
        '''
        Request received from user to create pending connection.
        '''
        print("request received")
        connection_key = msg.context['to_key']
        label = msg['label']
        their_did = msg['connection']['DID']
        their_vk = msg['connection']['DIDDoc']['publicKey'][0][
            'publicKeyBase58']

        # store info from request
        await utils.store_their_did(self.agent.wallet_handle, their_did,
                                    their_vk)

        await did.set_did_metadata(self.agent.wallet_handle, their_did,
                                   json.dumps({
                                       'label': label,
                                   }))
        # Create my information for connection
        (my_did,
         my_vk) = await utils.create_and_store_my_did(self.agent.wallet_handle)

        # Create pairwise relationship between my did and their did
        await pairwise.create_pairwise(
            self.agent.wallet_handle,
            their_did,
            my_did,
            json.dumps({
                'label': label,
                'req_id': msg['@id'],
                'their_vk': their_vk,
                'my_vk': my_vk,
                'connection_key': connection_key  # used to sign the response
            }))
        # pending connection message
        pending_connection = Message({
            '@type':
            "REQUEST_RECIEVED",
            'label':
            label,
            'did':
            their_did,
            'connection_key':
            connection_key,
            'history': [{
                'date': str(datetime.datetime.now()),
                'msg': msg.to_dict()
            }],
            'status':
            "Request Received"
        })
        print("CONNECTION REQUEST_RECEIVED: PENDING CONN: ",
              pending_connection)
        # Create pending connection between users
        try:
            await non_secrets.add_wallet_record(
                self.agent.wallet_handle, 'invitations', connection_key,
                Serializer.pack(pending_connection), '{}')
        except error.IndyError as indy_error:
            if indy_error.error_code == error.ErrorCode.WalletItemAlreadyExists:
                pass
            raise indy_error
    async def send_request(self, invitation):
        '''
        When button pressed, connection request is send to the other user.
        :param invitation: invitation from wallet record
        '''
        pending_connection = Serializer.unpack(  # recover invitation from wallet record
            json.loads(await non_secrets.get_wallet_record(
                self.agent.wallet_handle, 'invitations',
                invitation.get('connection_key'), '{}'))['value'])
        print("PENDING CONNECTION", pending_connection)

        my_label = self.agent.owner  # agent name
        label = pending_connection['label']  # name of other agent
        their_connection_key = pending_connection['connection_key']

        # create info for connection
        (my_did,
         my_vk) = await create_and_store_my_did(self.agent.wallet_handle)
        await did.set_did_metadata(self.agent.wallet_handle, my_did,
                                   json.dumps({'label': label}))

        # Send Connection Request to inviter
        request = Message({
            '@type': "SEND_REQUEST",
            '@sendTo': label,
            'label': my_label,
            'connection': {
                'DID': my_did,
                'DIDDoc': {
                    "@context":
                    "https://w3id.org/did/v1",
                    "id":
                    my_did,
                    "publicKey": [{
                        "id": my_did + "#keys-1",
                        "type": "Ed25519VerificationKey2018",
                        "controller": my_did,
                        "publicKeyBase58": my_vk
                    }],
                    "service": [{
                        "id": my_did + ";indy",
                        "type": "IndyAgent",
                        "recipientKeys": [my_vk],
                    }],
                }
            }
        })
        print("REQUEST", request)

        print("SEND MESSAGE TO END AND KEY")
        await self.agent.send_message_to_endpoint_and_key(  # Send request to other user
            my_vk, their_connection_key, request)

        # update pending request record
        pending_connection['@type'] = "REQUEST_SENT"
        pending_connection['status'] = "Request Sent"
        pending_connection['history'].append({
            'date':
            str(datetime.datetime.now()),
            'msg':
            Message(invitation).to_dict()
        })
        await non_secrets.update_wallet_record_value(
            self.agent.wallet_handle, 'invitations',
            pending_connection['connection_key'],
            Serializer.pack(pending_connection))