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)
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
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