def add_enclave_to_contract(ledger_config, creator_keys, contract_id, enclave_id, secrets, encrypted_state_encryption_key, signature, **extra_params): txn_keys = keys.TransactionKeys() enclave_secret_data_array = [] enclave_secret_data = dict() enclave_secret_data['contract_id'] = contract_id enclave_secret_data['contract_enclave_id'] = enclave_id enclave_secret_data[ 'encrypted_state_encryption_key'] = encrypted_state_encryption_key enclave_secret_data['signature'] = signature secret_list = [] for secret in secrets: secret_list.append(secret) enclave_secret_data['provisioning_key_state_secret_pairs'] = secret_list enclave_secret_data_array.append(enclave_secret_data) if 'wait' not in extra_params: extra_params['wait'] = 60 ss = Submitter(ledger_config['LedgerURL'], key_str=txn_keys.txn_private) txnsignature = ss.submit_add_enclave_from_data(creator_keys.signing_key, txn_keys.txn_public, contract_id, enclave_secret_data_array, **extra_params) return txnsignature
def create_new_enclave(cls, txn_keys=None): """create_new_enclave -- create a new enclave :param txn_keys: object of type TransactionKeys """ if txn_keys is None: txn_keys = keys.TransactionKeys() nonce = '{0:016X}'.format(random.getrandbits(64)) hashed_identity = txn_keys.hashed_identity try: enclave_data = pdo_enclave.create_signup_info( hashed_identity, nonce) except: raise Exception('failed to create enclave signup data') enclave_info = dict() enclave_info['nonce'] = nonce enclave_info['sealed_data'] = enclave_data.sealed_signup_data enclave_info['verifying_key'] = enclave_data.verifying_key enclave_info['encryption_key'] = enclave_data.encryption_key enclave_info['enclave_id'] = enclave_data.verifying_key enclave_info['proof_data'] = '' if not pdo_enclave.enclave.is_sgx_simulator(): enclave_info['proof_data'] = enclave_data.proof_data return cls(enclave_info, txn_keys)
def read_from_file(cls, basename, data_dir=None, txn_keys=None, block_store=None): """read_from_file -- read enclave data from a file and initialize a new Enclave object with the resulting data. :param file_name: string, name of the file :param search_path: list of strings, directories to search for the data file :param txn_keys: object of type TransactionKeys """ if txn_keys is None: txn_keys = keys.TransactionKeys() filename = putils.build_file_name(basename, data_dir=data_dir, extension='.enc') if os.path.exists(filename) is not True: raise FileNotFoundError(errno.ENOENT, "enclave information file does not exist", filename) logger.debug('load enclave information from %s', filename) with open(filename, "r") as enclave_file: enclave_info = json.load(enclave_file) try: assert 'nonce' in enclave_info assert 'sealed_data' in enclave_info assert 'interpreter' in enclave_info assert 'verifying_key' in enclave_info assert 'encryption_key' in enclave_info assert 'proof_data' in enclave_info assert 'enclave_id' in enclave_info except KeyError as ke: raise Exception('enclave data missing key {0}'.format(str(ke))) except: raise Exception('invalid enclave data file {0}'.format(filename)) try: public_enclave_data = pdo_enclave.get_enclave_public_info( enclave_info['sealed_data']) assert public_enclave_data and len(public_enclave_data) == 2 assert enclave_info['verifying_key'] == public_enclave_data[ 'verifying_key'] assert enclave_info['encryption_key'] == public_enclave_data[ 'encryption_key'] except: raise Exception( 'sealed storage does not match enclave data file; {}'.format( filename)) return cls(enclave_info, txn_keys, block_store)
def make_channel_keys(self, ledger_type=os.environ.get('PDO_LEDGER_TYPE')): if ledger_type == 'sawtooth': self.channel_keys = keys.TransactionKeys() self.channel_id = self.channel_keys.txn_public elif ledger_type == 'ccf': self.channel_keys = crypto.random_bit_string(64) # byte array self.channel_id = crypto.byte_array_to_base64( crypto.compute_message_hash(self.channel_keys)) else: raise Exception( "Invalid Ledger Type. Must be either sawtooth or ccf.")
def add_enclave_to_contract(self, contract_id, enclave_info_quintuples, **extra_params): txn_keys = keys.TransactionKeys() json_input = JsonPayloadBuilder.build_add_enclave_from_data( self.pdo_signer.signing_key, txn_keys.txn_public, contract_id, enclave_info_quintuples) extra_params['key_str'] = txn_keys.txn_private return self.submit_json(json_input, json_input['af'], **extra_params)
def make_channel_keys(self, ledger_type=os.environ.get('PDO_LEDGER_TYPE')): if ledger_type=='sawtooth': self.channel_keys = keys.TransactionKeys() self.channel_id = self.channel_keys.txn_public elif ledger_type=='ccf': ## the channel keys for CCF are really just a uniquifier since we don't ## need to hide the submitters ID (since CCF runs inside SGX) seed = crypto.random_bit_string(32) self.channel_id = crypto.byte_array_to_base64(seed) self.channel_keys = crypto.string_to_byte_array(self.channel_id) else: raise Exception("Invalid Ledger Type. Must be either sawtooth or ccf.")
def register_contract(self, contract_code_hash, provisioning_service_ids, **extra_params): txn_keys = keys.TransactionKeys() json_input = JsonPayloadBuilder.build_contract_registration_from_data( self.pdo_signer.signing_key, self.pdo_signer.verifying_key, txn_keys.txn_public, crypto.byte_array_to_base64(contract_code_hash), provisioning_service_ids) extra_params['key_str'] = txn_keys.txn_private return self.submit_json(json_input, json_input['af'], **extra_params)
def __init__(self, operation, request_originator_keys, enclave_service, contract, **kwargs) : if not self.__ops__[operation] : raise ValueError('invalid operation') self.operation = operation self.contract_id = contract.contract_id self.creator_id = contract.creator_id self.encrypted_state_encryption_key = contract.get_state_encryption_key(enclave_service.enclave_id) self.enclave_service = enclave_service self.originator_keys = request_originator_keys self.channel_keys = keys.TransactionKeys() self.session_key = crypto.SKENC_GenerateKey() self.contract_code = contract.contract_code self.contract_state = contract.contract_state self.message = ContractMessage(self.originator_keys, self.channel_keys, **kwargs)
def register_contract(ledger_config, creator_keys, contract_code, provisioning_service_ids, **extra_params): txn_keys = keys.TransactionKeys() if 'wait' not in extra_params: extra_params['wait'] = 60 ss = Submitter(ledger_config['LedgerURL'], key_str=txn_keys.txn_private) txnsignature = ss.submit_contract_registration_from_data( creator_keys.signing_key, creator_keys.verifying_key, txn_keys.txn_public, crypto.byte_array_to_base64(contract_code.compute_hash()), provisioning_service_ids, **extra_params) contract_id = putils.from_transaction_signature_to_id(txnsignature) return contract_id
def submit_json(self, json_input, address_family, **extra_params): # Get the write connect_helper. This cannot be attached to the class instance, since # the sawtooth header signing key must be unique for each transaction. # Previously, each class instance was used only for a single transaction, # so this was not a problem. The current implementation permits an instance to be reused key_str = extra_params.get('key_str', None) # this is the header signing key if key_str is None: txn_keys = keys.TransactionKeys() key_str = txn_keys.txn_private transaction_dependency_list = extra_params.get( 'transaction_dependency_list', None) # Sawtooth connector supports a few extra parameters. We shall fix these in PDO keyfile = None auto_generate = False exception_type = Exception verbose = False connect_helper = PdoClientConnectHelper(self.url, keyfile, key_str, auto_generate) json_payload = json.dumps(json_input) signature = connect_helper.\ execute_json_transaction( json_payload, address_family, self.wait, exception_type, verbose, transaction_dependency_list=transaction_dependency_list) logger.debug("json: %s", json_payload) logger.debug("signature: %s", signature) return signature
def verify(self, ledger_config): """ensure that the eservice still exists and hosts the enclave, and ensure that the enclave is registered with the ledger """ # first check: make sure the enclave hosted by the eservice is # the one we expect to be hosted try: if self.client.enclave_id != self.enclave_id: logger.info('mismatched enclave ids') self.last_verified_time = None return False except Exception as e: logger.info( 'failed to retrieve information from the hosting eservice; %s', str(e)) self.last_verified_time = "" return False # second check: make sure the ledger has an entry for the enclave if ledger_config and ledger_config.get('LedgerURL'): try: txn_keys = keys.TransactionKeys() sawtooth_client = PdoClientConnectHelper( ledger_config['LedgerURL'], key_str=txn_keys.txn_private) enclave_state = sawtooth_client.get_enclave_dict( self.enclave_id) except Exception as e: logger.info( 'failed to verify enclave registration with the ledger; %s', str(e)) self.last_verified_time = "" return False else: logger.info('skipping ledger verification, no ledger specified') self.last_verified_time = str(datetime.datetime.now()) return True