def verify(self, message, encoded_signature, encoding='hex'):
        """
        verify the signature of a message from the agent

        :param message: the message for verification, no encoding
        :param signature: encoded signature
        :param encoding: the encoding used for the signature; one of raw, hex, b64
        """
        logger.debug("signature for verification: %s", encoded_signature)

        if type(message) is bytes:
            message_byte_array = message
        elif type(message) is tuple:
            message_byte_array = message
        else:
            message_byte_array = bytes(message, 'ascii')

        if encoding == 'raw':
            decoded_signature = encoded_signature
        elif encoding == 'hex':
            decoded_signature = crypto.hex_to_byte_array(encoded_signature)
        elif encoding == 'b64':
            decoded_signature = crypto.base64_to_byte_array(encoded_signature)
        else:
            raise ValueError('unknown encoding; {0}'.format(encoding))

        result = self._verifying_key.VerifySignature(message_byte_array,
                                                     decoded_signature)
        if result < 0:
            raise Error('malformed signature')

        return
def from_transaction_signature_to_id(transaction_signature):
    """function to transform a hex transaction signature (or transaction identifier)
    into a base64 id which is used (for instance) for a contract id
    """
    id = crypto.byte_array_to_base64(
        crypto.compute_message_hash(
            crypto.hex_to_byte_array(transaction_signature)))
    return id
    def pull_state_from_eservice(self, eservice, data_dir="./data"):
        """
        push the blocks associated with the state to the eservice

        :param eservice EnclaveServiceClient object:
        """

        if self.encrypted_state is '':
            return

        ContractState.__cache_block_from_eservice__(
            eservice, self.contract_id, self.get_state_hash(encoding='b64'),
            data_dir)

        for hex_block_id in self.component_block_ids:
            b64_block_id = crypto.byte_array_to_base64(
                crypto.hex_to_byte_array(hex_block_id))
            ContractState.__cache_block_from_eservice__(
                eservice, self.contract_id, b64_block_id, data_dir)
Beispiel #4
0
    def _secretreq(self, minfo):
        # unpack the request
        try:
            enclave_id = minfo['enclave_id']
            contract_id = minfo['contract_id']
            opk = minfo['opk']
            signature = minfo['signature']

        except KeyError as ke:
            raise Error(http.BAD_REQUEST,
                        'missing required field {0}'.format(ke))

        logger.debug('request for key for contract %s, enclave %s',
                     contract_id, enclave_id)

        # verify the signature, that is, make sure that the request was really signed by opk
        try:
            opkkey = pcrypto.SIG_PublicKey(opk)
            opkkey.VerifySignature(
                pcrypto.string_to_byte_array(enclave_id + contract_id),
                pcrypto.hex_to_byte_array(signature))
        except:
            logger.warn("Signature verification failed")
            raise Error(http.BAD_REQUEST, 'Signature Mismatch')

        # Get enclave state
        try:
            logger.debug('retrieve information for enclave %s', enclave_id)
            enclave_info = self.__registry_helper.get_enclave_info(enclave_id)
            logger.debug("enclave information retrieved: %s", enclave_info)
        except Exception as err:
            logger.error(
                'exception occurred when getting ledger information for enclave %s; %s',
                enclave_id, str(err))
            raise Exception(
                'could not retrieve enclave state; {0}'.format(err))

        # Get contract state
        try:
            logger.debug('retrieve information for contract <%s>', contract_id)
            contract_info = self.__registry_helper.get_contract_info(
                contract_id)
            logger.debug("contract_info from ledger: %s", contract_info)
        except Exception as err:
            logger.error(
                'exception occurred when getting ledger information for contract %s; %s',
                contract_id, str(err))
            raise Exception(
                'could not retrieve contract state; {0}'.format(err))

        # make sure that the signer of this request is really the owner of the contract
        try:
            # make sure that the signer of this request is really the owner of the contract
            # PdoContractInfo.pdo_contract_creator_pem_key is the VerifyingKey
            logger.debug("Contract creator's public key: %s",
                         contract_info['pdo_contract_creator_pem_key'])
            logger.debug("Expected public key: %s", opk)
            assert contract_info['pdo_contract_creator_pem_key'] == opk
        except:
            logger.error(
                'request to create secret did not come from the contract owner; %s != %s',
                contracttxn.OriginatorID, opk)
            raise Error(http.NOT_ALLOWED,
                        'operation not allowed for {0}'.format(opk))

        # make sure the provisioning service is allowed to access contract by the checking the list of allowed provisioning services
        try:
            logger.debug("Contract allowed service ids: %s",
                         contract_info['provisioning_service_ids'])
            logger.debug("Expected provisioning service id: %s", self.PSPK)
            assert self.PSPK in contract_info['provisioning_service_ids']
        except:
            logger.error(
                'This Pservice is not the list of allowed provisioning services, PSerivce ID: %s',
                self.PSPK)
            raise Error(http.NOT_ALLOWED,
                        'operation not allowed for {0}'.format(self.PSPK))

        # retrieve the sealed secret
        sealed_secret = self._GetContractSecret(contract_id)

        logger.debug("Enclave Info: %s", str(enclave_info))

        # Generate Secret for Contract Enclave, signs unsealed secret with contract enclave encryption key
        esecret = self.Enclave.generate_enclave_secret(
            self.SealedData,
            sealed_secret,
            contract_id,
            opk,
            json.dumps(enclave_info),
        )["enclave_secret"]

        logger.debug("Encrypted secret for contract %s: %s", contract_id,
                     esecret)

        # create the response
        response = dict()
        response['pspk'] = self.PSPK
        response['encrypted_secret'] = esecret

        logger.info('created secret for contract %s and enclave %s',
                    contract_id, enclave_id)
        return response
Beispiel #5
0
    def _secretreq(self, minfo):
        # unpack the request
        try:
            enclave_id = minfo['enclave_id']
            contract_id = minfo['contract_id']
            opk = minfo['opk']
            signature = minfo['signature']

        except KeyError as ke:
            raise Error(http.BAD_REQUEST,
                        'missing required field {0}'.format(ke))

        logger.debug('request for key for contract %s, enclave %s',
                     contract_id, enclave_id)

        # verify the signature, that is, make sure that the request was really signed by opk
        try:
            opkkey = pcrypto.SIG_PublicKey(opk)
            opkkey.VerifySignature(
                pcrypto.string_to_byte_array(enclave_id + contract_id),
                pcrypto.hex_to_byte_array(signature))
        except:
            logger.warn("Signature verification failed")
            raise Error(http.BAD_REQUEST, 'Signature Mismatch')

        # Get enclave state
        try:
            logger.debug('retrieve information for enclave %s', enclave_id)
            enclave_info = self.__registry_helper.get_enclave_dict(enclave_id)
            logger.debug("enclave information retrieved: %s", enclave_info)
        except BaseException as err:
            logger.warn(
                'exception occurred when getting ledger information for enclave %s; %s',
                enclave_id, str(err))
            raise Error(http.BAD_REQUEST,
                        'could not retrieve enclave state; {0}'.format(err))
        except ClientConnectException as err:
            logger.warn(
                'client exception occurred when getting ledger information for enclave %s; %s',
                enclave_id, str(err))
            raise Error(http.BAD_REQUEST,
                        'could not retrieve enclave state; {0}'.format(err))

        # Get contract state
        try:
            logger.debug('retrieve information for contract <%s>', contract_id)
            contract_info = self.__registry_helper.get_contract_dict(
                contract_id)
            logger.debug("contract_info from ledger: %s", contract_info)
        except BaseException as err:
            logger.warn(
                'exception occurred when getting ledger information for contract %s; %s',
                contract_id, str(err))
            raise Error(http.BAD_REQUEST,
                        'could not retrieve contract state; {0}'.format(err))
        except ClientConnectException as err:
            logger.warn(
                'client exception occurred when getting ledger information for contract %s; %s',
                contract_id, str(err))
            raise Error(http.BAD_REQUEST,
                        'could not retrieve contract state; {0}'.format(err))

        # make sure that the signer of this request is really the owner of the contract
        try:
            # make sure that the signer of this request is really the owner of the contract
            # PdoContractInfo.pdo_contract_creator_pem_key is the VerifyingKey
            logger.debug("Contract creator's public key: %s",
                         contract_info['pdo_contract_creator_pem_key'])
            logger.debug("Expected public key: %s", opk)
            assert contract_info['pdo_contract_creator_pem_key'] == opk
        except:
            logger.error(
                'request to create secret did not come from the contract owner; %s != %s',
                contracttxn.OriginatorID, opk)
            raise Error(http.NOT_ALLOWED,
                        'operation not allowed for {0}'.format(opk))

        # make sure the provisioning service is allowed to access contract by the checking the list of allowed provisioning services
        try:
            logger.debug("Contract allowed service ids: %s",
                         contract_info['provisioning_service_ids'])
            logger.debug("Expected provisioning service id: %s",
                         self.PSPK.Serialize())
            assert self.PSPK.Serialize(
            ) in contract_info['provisioning_service_ids']
        except:
            logger.error(
                'This Pservice is not the list of allowed provisioning services, PSerivce ID: %s',
                self.PSPK.Serialize())
            raise Error(
                http.NOT_ALLOWED,
                'operation not allowed for {0}'.format(self.PSPK.Serialize()))

        # retrieve the secret
        secret = self._GetContractSecret(contract_id)

        # create the signature
        message = secret + enclave_id + contract_id + opk
        secretsig = pcrypto.byte_array_to_hex(
            self.SigningKey.SignMessage(pcrypto.string_to_byte_array(message)))

        # pad secret to required max size
        # TODO: Eventually this requirement needs to be fixed in the crypto library itself
        required_padding = 2 * pcrypto.MAX_SIG_SIZE - len(secretsig)
        secretsig = secretsig + ('0' * required_padding)

        enclavekey = pcrypto.PKENC_PublicKey(enclave_info['encryption_key'])
        esecret = pcrypto.byte_array_to_base64(
            enclavekey.EncryptMessage(
                pcrypto.string_to_byte_array(secret + secretsig)))

        logger.debug("Encrypted secret for contract %s: %s", contract_id,
                     esecret)

        # create the response
        response = dict()
        response['pspk'] = self.PSPK.Serialize()
        response['encrypted_secret'] = esecret

        logger.info('created secret for contract %s and enclave %s',
                    contract_id, enclave_id)
        return response