Exemplo n.º 1
0
 async def handle(self, content_type, data):
     try:
         if content_type == DIDExchange.MESSAGE_CONTENT_TYPE:
             kwargs = json.loads(data)
             msg = Message(**kwargs)
         elif content_type in WIRED_CONTENT_TYPES:
             msg = await DIDExchange.unpack_agent_message(data, self.get_wallet())
         else:
             raise RuntimeError('Unknown content_type "%s"' % content_type)
         await self.__log('Receive', msg.to_dict())
         if msg.type == DIDExchange.INVITE:
             await self.__receive_invitation(msg)
         elif msg.type == DIDExchange.RESPONSE:
             await self.__receive_connection_response(msg)
         elif msg.type == DIDExchange.PROBLEM_REPORT:
             if self.status == DIDExchangeStatus.Requested:
                 # Stay in same state - retryable
                 pass
             else:
                 raise ImpossibleStatus()
         else:
             logging.error('Unexpected message type: %s' % msg.type)
     except Exception as e:
         if not isinstance(e, MachineIsDone):
             logging.exception('Base machine terminated with exception')
         await self.done()
Exemplo n.º 2
0
 async def handle(cls,
                  agent_name: str,
                  wire_message: bytes,
                  my_label: str = None,
                  my_endpoint: str = None) -> bool:
     unpacked = await WalletAgent.unpack_message(agent_name, wire_message)
     kwargs = json.loads(unpacked['message'])
     message = Message(**kwargs)
     print('***** feature 0037 handle message *****')
     if 'sender_verkey' in unpacked:
         sender_verkey = unpacked['sender_verkey']
     else:
         sender_verkey = None
     if 'recipient_verkey' in unpacked:
         recipient_verkey = unpacked['recipient_verkey']
     else:
         recipient_verkey = None
     print('sender_verkey: ' + sender_verkey)
     print('recipient_verkey: ' + recipient_verkey)
     print(json.dumps(message.to_dict(), indent=2, sort_keys=True))
     print('***************************************')
     if message.get('@type', None) is None:
         return False
     if not cls.endorsement(message):
         return False
     state_machine_id = cls.get_state_machine_id(unpacked['sender_verkey'])
     if message.type in [
             PresentProofProtocol.REQUEST_PRESENTATION, AckMessage.ACK
     ]:
         if message.type == PresentProofProtocol.REQUEST_PRESENTATION:
             machine_class = PresentProofProtocol.ProverStateMachine
             await WalletAgent.start_state_machine(
                 status=PresentProofStatus.Null,
                 ttl=PresentProofProtocol.STATE_MACHINE_TTL,
                 agent_name=agent_name,
                 machine_class=machine_class,
                 machine_id=state_machine_id)
         await WalletAgent.invoke_state_machine(
             agent_name=agent_name,
             id_=state_machine_id,
             content_type=cls.WIRED_CONTENT_TYPE,
             data=wire_message)
         return True
     elif message.type in [PresentProofProtocol.PRESENTATION]:
         await WalletAgent.invoke_state_machine(
             agent_name=agent_name,
             id_=state_machine_id,
             content_type=cls.WIRED_CONTENT_TYPE,
             data=wire_message)
         return True
     elif message.type == PresentProofProtocol.PROBLEM_REPORT:
         await WalletAgent.invoke_state_machine(
             agent_name=agent_name,
             id_=state_machine_id,
             content_type=cls.WIRED_CONTENT_TYPE,
             data=wire_message)
         return True
     else:
         return False
Exemplo n.º 3
0
 async def handle(cls, agent_name: str, wire_message: bytes, my_label: str=None, my_endpoint: str=None) -> bool:
     unpacked = await WalletAgent.unpack_message(agent_name, wire_message)
     kwargs = json.loads(unpacked['message'])
     message = Message(**kwargs)
     if message.get('@type', None) is None:
         return False
     if message.type == cls.REQUEST:
         state_machine_id = unpacked['sender_verkey']
         machine_class = DIDExchange.DIDExchangeInviterStateMachine
         await WalletAgent.start_state_machine(
             agent_name=agent_name, machine_class=machine_class, machine_id=state_machine_id, endpoint=my_endpoint,
             label=my_label, status=DIDExchangeStatus.Invited
         )
         await WalletAgent.invoke_state_machine(
             agent_name=agent_name, id_=state_machine_id,
             content_type=cls.WIRED_CONTENT_TYPE, data=wire_message
         )
         return True
     elif message.type == DIDExchange.RESPONSE:
         state_machine_id = message['connection~sig']['signer']
         await WalletAgent.invoke_state_machine(
             agent_name=agent_name, id_=state_machine_id,
             content_type=cls.WIRED_CONTENT_TYPE, data=wire_message
         )
         return True
     elif message.type in [TrustPing.PING, TrustPing.PING_RESPONSE]:
         state_machine_id = unpacked['sender_verkey']
         await WalletAgent.invoke_state_machine(
             agent_name=agent_name, id_=state_machine_id,
             content_type=cls.WIRED_CONTENT_TYPE, data=wire_message
         )
         return True
     elif message.type == DIDExchange.PROBLEM_REPORT:
         state_machine_id = message.to_dict().get('connection~sig', {}).get('signer')
         if state_machine_id:
             await WalletAgent.invoke_state_machine(
                 agent_name=agent_name, id_=state_machine_id,
                 content_type=cls.WIRED_CONTENT_TYPE, data=wire_message
             )
             return True
         else:
             logging.error('Problem report', message.as_json())
             return True
     else:
         return False
Exemplo n.º 4
0
        async def __validate_cred_offer(self, msg: Message, context: Context):
            offer_attaches = msg.to_dict().get('offers~attach', None)
            if isinstance(offer_attaches, dict):
                offer_attaches = [offer_attaches]
            if (not type(offer_attaches) is list) or (
                    type(offer_attaches) is list and len(offer_attaches) == 0):
                await self.__send_problem_report(
                    problem_code=IssueCredentialProtocol.
                    OFFER_PROCESSING_ERROR,
                    problem_str=
                    'Expected offer~attach must contains credOffer and credDef',
                    context=context,
                    thread_id=msg.id)
                await self.done()

            offer = offer_attaches[0]
            offer_body = None
            cred_def_body = None
            for attach in offer_attaches:
                raw_base64 = attach.get('data', {}).get('base64', None)
                if raw_base64:
                    payload = json.loads(base64.b64decode(raw_base64).decode())
                    offer_fields = [
                        'key_correctness_proof', 'nonce', 'schema_id',
                        'cred_def_id'
                    ]
                    cred_def_fields = [
                        'value', 'type', 'ver', 'schemaId', 'id', 'tag'
                    ]
                    if all([field in payload.keys() for field in offer_fields
                            ]):  # check if cred offer content
                        offer_body = {
                            attr: val
                            for attr, val in payload.items()
                            if attr in offer_fields
                        }
                    if all(
                        [field in payload.keys() for field in cred_def_fields
                         ]):  # check if cred def content
                        cred_def_body = {
                            attr: val
                            for attr, val in payload.items()
                            if attr in cred_def_fields
                        }

            if not offer_body:
                await self.__send_problem_report(
                    problem_code=IssueCredentialProtocol.
                    OFFER_PROCESSING_ERROR,
                    problem_str=
                    'Expected offer~attach must contains Payload with offer',
                    context=context,
                    thread_id=msg.id)
                await self.done()
            if cred_def_body:
                cred_def_id = cred_def_body['id']
                await indy_sdk_utils.store_cred_def(self.get_wallet(),
                                                    cred_def_id, cred_def_body)
            else:
                await self.__send_problem_report(
                    problem_code=IssueCredentialProtocol.
                    OFFER_PROCESSING_ERROR,
                    problem_str=
                    'Expected offer~attach must contains Payload with cred_def data',
                    context=context,
                    thread_id=msg.id)
                await self.done()
            attaches = msg.to_dict().get('~attach', None)
            if attaches:
                if isinstance(attaches, dict):
                    attaches = [attaches]
                for attach in attaches:
                    if attach.get(
                            '@type', None
                    ) == IssueCredentialProtocol.ISSUER_SCHEMA_TYPE:
                        issuer_schema_body = attach['data']['json']
                        issuer_schema_id = issuer_schema_body['id']
                        await indy_sdk_utils.store_issuer_schema(
                            self.get_wallet(), issuer_schema_id,
                            issuer_schema_body)
            return offer, offer_body, cred_def_body
Exemplo n.º 5
0
        async def handle(self, content_type, data):
            try:
                msg_type_offer_credential = IssueCredentialProtocol.set_protocol_version(
                    IssueCredentialProtocol.OFFER_CREDENTIAL,
                    self.protocol_version or IssueCredentialProtocol.VERSION)
                msg_type_issue_credential = IssueCredentialProtocol.set_protocol_version(
                    IssueCredentialProtocol.ISSUE_CREDENTIAL,
                    self.protocol_version or IssueCredentialProtocol.VERSION)
                if content_type in WIRED_CONTENT_TYPES:
                    msg, context = await IssueCredentialProtocol.unpack_agent_message(
                        data, self.get_wallet())
                    self.to = context.their_did
                    success, err_msg = await IssueCredentialProtocol.validate_common_message_blocks(
                        msg, IssueCredentialProtocol.REQUEST_NOT_ACCEPTED,
                        context)
                    if not success:
                        if err_msg:
                            await IssueCredentialProtocol.send_message_to_agent(
                                context.their_did, err_msg, self.get_wallet())
                else:
                    raise RuntimeError('Unsupported content_type "%s"' %
                                       content_type)
                if msg.type == msg_type_offer_credential:
                    if self.status == IssueCredentialStatus.Null:
                        await self.__log('Received credential offer',
                                         msg.to_dict())
                        offer, offer_body, cred_def_body = await self.__validate_cred_offer(
                            msg, context)
                        self.cred_def_id = offer_body['cred_def_id']

                        link_secret_name = settings.INDY['WALLET_SETTINGS'][
                            'PROVER_MASTER_SECRET_NAME']
                        try:
                            await self.get_wallet(
                            ).prover_create_master_secret(link_secret_name)
                        except WalletOperationError as e:
                            if 'duplicate' in e.error_message.lower():
                                # nothing to do
                                pass
                            else:
                                raise e
                        # Create Credential request
                        self.cred_def_buffer = json.dumps(cred_def_body)
                        cred_request, metadata = await self.get_wallet(
                        ).prover_create_credential_req(
                            prover_did=context.my_did,
                            cred_offer=offer_body,
                            cred_def=cred_def_body,
                            master_secret_id=link_secret_name)

                        await self.__log(
                            'Cred request artifacts',
                            dict(cred_request=cred_request, metadata=metadata))

                        self.cred_metadata = json.dumps(metadata)
                        # Build request
                        data = {
                            "@type":
                            IssueCredentialProtocol.REQUEST_CREDENTIAL,
                            "~thread": {
                                Message.THREAD_ID: msg.id,
                                Message.SENDER_ORDER: 0
                            },
                            "requests~attach": [
                                {
                                    "@id": uuid.uuid4().hex,
                                    "mime-type": "application/json",
                                    "data": {
                                        "base64":
                                        base64.b64encode(
                                            json.dumps(cred_request).encode()).
                                        decode()
                                    }
                                },
                            ]
                        }
                        if self.comment:
                            data['comment'] = self.comment

                        message_request = Message(data)
                        await IssueCredentialProtocol.send_message_to_agent(
                            self.to, message_request, self.get_wallet())
                        await self.__log('Send credential request',
                                         message_request.to_dict())
                        self.status = IssueCredentialStatus.RequestCredential
                    else:
                        await self.__send_problem_report(
                            problem_code=IssueCredentialProtocol.
                            OFFER_PROCESSING_ERROR,
                            problem_str='Impossible state machine state',
                            context=context,
                            thread_id=msg.id)
                        raise ImpossibleStatus
                elif msg.type == msg_type_issue_credential:
                    if self.status == IssueCredentialStatus.RequestCredential:
                        await self.__log('Received Issue credential',
                                         msg.to_dict())
                        cred_attaches = msg.to_dict().get(
                            'credentials~attach', None)
                        if isinstance(cred_attaches, dict):
                            cred_attaches = [cred_attaches]

                        for cred_attach in cred_attaches:
                            cred_body = cred_attach.get('data').get('base64')
                            cred_body = base64.b64decode(cred_body)
                            cred_body = json.loads(cred_body.decode())
                            cred_def = json.loads(self.cred_def_buffer)
                            cred_id = cred_attach.get('@id', None)

                            # Store credential
                            cred_older = await self.get_wallet(
                            ).prover_get_credential(cred_id)
                            if cred_older:
                                # Delete older credential
                                await self.get_wallet(
                                ).prover_delete_credential(cred_id)
                            cred_id = await self.get_wallet(
                            ).prover_store_credential(
                                cred_req_metadata=json.loads(
                                    self.cred_metadata),
                                cred=cred_body,
                                cred_def=cred_def,
                                rev_reg_def=self.rev_reg_def,
                                cred_id=cred_id)
                            await self.__log(
                                'Store credential with id: %s' % str(cred_id),
                                cred_body)

                        ack_message_id = msg.to_dict().get(
                            '~please_ack', {}).get('message_id', None)
                        if not ack_message_id:
                            ack_message_id = msg.id
                        ack = AckMessage.build(ack_message_id)
                        await IssueCredentialProtocol.send_message_to_agent(
                            self.to, ack, self.get_wallet())
                        await self.__log('Send ACK', ack.to_dict())
                        await self.done()
                    else:
                        await self.__send_problem_report(
                            problem_code=IssueCredentialProtocol.
                            ISSUE_PROCESSING_ERROR,
                            problem_str='Impossible state machine state',
                            context=context,
                            thread_id=msg.id)
                        raise ImpossibleStatus
                elif msg.type == IssueCredentialProtocol.PROBLEM_REPORT:
                    await self.__log('Received problem report', msg.to_dict())
                    await self.done()
                else:
                    await self.__send_problem_report(
                        problem_code=IssueCredentialProtocol.
                        RESPONSE_FOR_UNKNOWN_REQUEST,
                        problem_str='Unknown message type',
                        context=context,
                        thread_id=msg.id)
            except Exception as e:
                if not isinstance(e, MachineIsDone):
                    logging.exception('Base machine terminated with exception')
                await self.done()