def compute_pdo_ccl_signature(private_key, enclave_id, enclave_signature, channel_id, contract_id, creator_public_key_pem, contract_code_hash, message_hash, current_state_hash, previous_state_hash, dependency_list): k = crypto.SIG_PrivateKey(private_key) message_byte_array = crypto.string_to_byte_array(enclave_id) message_byte_array += crypto.base64_to_byte_array(enclave_signature) message_byte_array += crypto.string_to_byte_array(channel_id) message_byte_array += crypto.string_to_byte_array(contract_id) message_byte_array += crypto.string_to_byte_array(creator_public_key_pem) message_byte_array += crypto.base64_to_byte_array(contract_code_hash) message_byte_array += crypto.base64_to_byte_array(message_hash) message_byte_array += crypto.base64_to_byte_array(current_state_hash) #in ccl initialize, previous state hash and dependencies are supposed to be empty if previous_state_hash: message_byte_array += crypto.base64_to_byte_array(previous_state_hash) for d in dependency_list: message_byte_array += crypto.string_to_byte_array(d.contract_id) message_byte_array += crypto.string_to_byte_array(d.state_hash) signature = k.SignMessage(message_byte_array) encoded_signature = crypto.byte_array_to_base64(signature) logger.debug("signed message string: " + crypto.byte_array_to_base64(message_byte_array)) logger.debug("signed message hash: " + crypto.byte_array_to_hex( crypto.compute_message_hash(message_byte_array))) logger.debug("signature: %s", encoded_signature) return encoded_signature
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 __encryption_key__(password): """create an AES encryption/decryption key from the password """ try: password = password.encode('utf-8') except AttributeError: pass return crypto.compute_message_hash(password)[:16]
def compute_hash(self, encoding = 'raw') : # the code hash is a combination of the hash of the actual code, # and the hash of the nonce. # this makes it possible to use the nonce to verify the identity # of the actual code (think MRENCLAVE). code_hash = crypto.compute_message_hash(crypto.string_to_byte_array(self.code + self.name)) nonce_hash = crypto.compute_message_hash(crypto.string_to_byte_array(self.nonce)) message = code_hash + nonce_hash code_hash = crypto.compute_message_hash(message) if encoding == 'raw' : return code_hash elif encoding == 'hex' : return crypto.byte_array_to_hex(code_hash) elif encoding == 'b64' : return crypto.byte_array_to_base64(code_hash) else : raise ValueError('unknown hash encoding; {}'.format(encoding))
def compute_hash(self, encoding = 'raw') : serialized = self.__serialize_for_hashing() code_hash = crypto.compute_message_hash(crypto.string_to_byte_array(serialized)) if encoding == 'raw' : return code_hash elif encoding == 'hex' : return crypto.byte_array_to_hex(code_hash) elif encoding == 'b64' : return crypto.byte_array_to_base64(code_hash) else : raise ValueError('unknown hash encoding; {}'.format(encoding))
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 compute_hash(encrypted_state, encoding='raw'): """ compute the hash of the encrypted state """ state_byte_array = crypto.base64_to_byte_array(encrypted_state) state_hash = crypto.compute_message_hash(state_byte_array) if encoding == 'raw': return state_hash elif encoding == 'b64': return crypto.byte_array_to_base64(state_hash) elif encoding == 'hex': return crypto.byte_array_to_hex(state_hash) raise ValueError('unknown encoding; {}'.format(encoding))
def compute_hash(raw_state, encoding='raw'): """ compute the hash of the contract state :param raw_state string: root block of contract state, json string """ state_hash = crypto.compute_message_hash(raw_state) if encoding == 'raw': return state_hash elif encoding == 'b64': return crypto.byte_array_to_base64(state_hash) elif encoding == 'hex': return crypto.byte_array_to_hex(state_hash) raise ValueError('unknown encoding; {}'.format(encoding))
def build_contract_registration_from_data( contract_creator_keys, contract_code_hash, provisioning_service_ids): payloadblob = dict() payloadblob['contract_code_hash'] = contract_code_hash payloadblob['provisioning_service_ids'] = provisioning_service_ids payloadblob['contract_creator_verifying_key_PEM'] = contract_creator_keys.verifying_key # sign the payload after adding a nonce nonce = time.time().hex() payloadblob['nonce'] = nonce payloadblob['signature'] = compute_pdo_signature_contract_registration(contract_creator_keys.signing_key, contract_creator_keys.verifying_key, contract_code_hash, provisioning_service_ids, nonce) payloadblob['contract_id'] = \ crypto.byte_array_to_base64(crypto.compute_message_hash(payloadblob['signature'])) return payloadblob
def verify_state_encryption_key_signature(encrypted_state_key, secret_list, contract_id, creator_id, signature, enclave_keys): """verify the signature on the contract state encryption key received from the enclave :param encrypted_state_key; base64 encoded string :param secret_list: array of dictionary defines values for pspk and encrypted_secret :param contract_id: 16 character, hex encoded, sha256 hashed, registration transaction signature :param creator_id: PEM encoded ECDSA verifying key :param signature: base64 encoded signature :param enclave_keys: object of type :EnclaveKeys: """ message = serialize_for_signing(encrypted_state_key, secret_list, contract_id, creator_id) logger.debug( "signed message has length %d and hash %s", len(message), crypto.byte_array_to_base64(crypto.compute_message_hash(message))) return enclave_keys.verify(message, signature, encoding='b64')
def CreateAndRegisterContract(config, enclave, contract_creator_keys): global txn_dependencies data_dir = config['PDO']['DataPath'] ledger_config = config.get('Sawtooth') contract_creator_id = contract_creator_keys.identity contract_name = config['contract'] contract_code = contract_helper.ContractCode.create_from_scheme_file( contract_name, search_path=[".", "..", "contracts"]) # create the provisioning servers if use_pservice: pservice_urls = config.get("pservice-urls") provisioning_services = list( map(lambda url: pservice_helper.ProvisioningServiceClient(url), pservice_urls)) else: provisioning_services = secret_helper.create_provisioning_services( config['secrets']) provisioning_service_keys = list( map(lambda svc: svc.identity, provisioning_services)) try: if use_ledger: contract_id = contract_helper.register_contract( ledger_config, contract_creator_keys, contract_code, provisioning_service_keys) logger.info('contract registration successful; %s', contract_id) else: contract_id = crypto.byte_array_to_base64( crypto.compute_message_hash(crypto.random_bit_string(256))) logger.info('no ledger config; skipping contract registration') except Exception as e: logger.error('failed to register the contract; %s', str(e)) sys.exit(-1) contract_state = contract_helper.ContractState.create_new_state( contract_id) contract = contract_helper.Contract(contract_code, contract_state, contract_id, contract_creator_id) # -------------------------------------------------- logger.info('create the provisioning secrets') # -------------------------------------------------- if use_pservice: secret_list = [] for pservice in provisioning_services: logger.debug('ask pservice %s to generate a secret for %s', pservice.ServiceURL, contract_id) message = enclave.enclave_id + contract_id signature = contract_creator_keys.sign(message, encoding='hex') secret = pservice.get_secret(enclave.enclave_id, contract_id, contract_creator_keys.verifying_key, signature) if secret is None: logger.error('failed to create secret for %s', pservice.ServiceURL) sys.exit(-1) secret_list.append(secret) else: secret_list = secret_helper.create_secrets_for_services( provisioning_services, enclave.enclave_keys, contract_id, contract_creator_id) logger.debug('secrets: %s', secret_list) try: secretinfo = enclave.verify_secrets(contract_id, contract_creator_id, secret_list) assert secretinfo encrypted_state_encryption_key = secretinfo[ 'encrypted_state_encryption_key'] signature = secretinfo['signature'] except Exception as e: logger.error('failed to create the state encryption key; %s', str(e)) sys.exit(-1) try: if not secrets.verify_state_encryption_key_signature( encrypted_state_encryption_key, secret_list, contract_id, contract_creator_id, signature, enclave.enclave_keys): raise RuntimeError('signature verification failed') except Exception as e: logger.error('failed to verify the state encryption key; %s', str(e)) sys.exit(-1) logger.info('encrypted state encryption key: %s', encrypted_state_encryption_key) # -------------------------------------------------- logger.info('add the provisioned enclave to the contract') # -------------------------------------------------- try: if use_ledger: txnid = contract_helper.add_enclave_to_contract( ledger_config, contract_creator_keys, contract_id, enclave.enclave_id, secret_list, encrypted_state_encryption_key, signature, transaction_dependency_list=txn_dependencies) txn_dependencies = [txnid] logger.info('contract state encryption key added to contract') else: logger.info( 'no ledger config; skipping state encryption key registration') except Exception as e: logger.error('failed to add state encryption key; %s', str(e)) sys.exit(-1) contract.set_state_encryption_key(enclave.enclave_id, encrypted_state_encryption_key) contract.save_to_file(contract_name, data_dir=data_dir) # -------------------------------------------------- logger.info('create the initial contract state') # -------------------------------------------------- try: initialize_request = contract.create_initialize_request( contract_creator_keys, enclave) initialize_response = initialize_request.evaluate() contract.set_state(initialize_response.encrypted_state) except Exception as e: logger.error('failed to create the initial state; %s', str(e)) sys.exit(-1) logger.info('enclave created initial state') # -------------------------------------------------- logger.info('save the initial state in the ledger') # -------------------------------------------------- try: if use_ledger: logger.info("sending to ledger") # note that we will wait for commit of the transaction before # continuing; this is not necessary in general (if there is # confidence the transaction will succeed) but is useful for # testing txnid = initialize_response.submit_initialize_transaction( ledger_config, wait=30, transaction_dependency_list=txn_dependencies) txn_dependencies = [txnid] else: logger.info('no ledger config; skipping iniatialize state save') except Exception as e: logger.error('failed to save the initial state; %s', str(e)) sys.exit(-1) contract.contract_state.save_to_cache(data_dir=data_dir) return contract
def hashed_identity(self): key_byte_array = crypto.string_to_byte_array(self.txn_public) hashed_txn_key = crypto.compute_message_hash(key_byte_array) encoded_hashed_key = crypto.byte_array_to_hex(hashed_txn_key) encoded_hashed_key = encoded_hashed_key.lower() return encoded_hashed_key
"Symmetric decryption (random IV) invalid key detection test successful!" ) else: logger.error( "ERROR: Symmetric decryption (random IV) invalid key detection test failed: ", exc) sys.exit(-1) try: iv = crypto.SKENC_GenerateIV("A message") except Exception as exc: logger.error( "ERROR: Symmetric encryption deterministic iv generation test failed: ", exc) sys.exit(-1) logger.debug( "Symmetric encryption deterministic iv generation test successful!") try: rand = crypto.random_bit_string(16) except Exception as exc: logger.error("ERROR: Random number generation failed: ", exc) sys.exit(-1) logger.debug("Random number generation successful!") hash = crypto.compute_message_hash(rand) bhash = bytearray(hash) b64hash = crypto.byte_array_to_base64(bhash) logger.debug("Hash computed!") crypto.base64_to_byte_array(b64hash) logger.debug("SWIG CRYPTO_WRAPPER TEST SUCCESSFUL!") sys.exit(0)
def CreateAndRegisterContract(config, enclaves, contract_creator_keys): global txn_dependencies data_dir = config['Contract']['DataDirectory'] ledger_config = config.get('Sawtooth') contract_creator_id = contract_creator_keys.identity try: contract_class = config['Contract']['Name'] contract_source = config['Contract']['SourceFile'] source_path = config['Contract']['SourceSearchPath'] interpreter = config['Contract']['Interpreter'] contract_code = contract_helper.ContractCode.create_from_file( contract_class, contract_source, source_path, interpreter=interpreter) except Exception as e: raise Exception('unable to load contract source; {0}'.format(str(e))) # create the provisioning servers if use_pservice: try: pservice_urls = config['Service']['ProvisioningServiceURLs'] provisioning_services = list( map(lambda url: pservice_helper.ProvisioningServiceClient(url), pservice_urls)) except Exception as e: logger.error('failed to connect to provisioning service; %s', str(e)) ErrorShutdown() else: provisioning_services = secret_helper.create_provisioning_services( config['secrets']) provisioning_service_keys = list( map(lambda svc: svc.identity, provisioning_services)) try: if use_ledger: contract_id = contract_helper.register_contract( ledger_config, contract_creator_keys, contract_code, provisioning_service_keys) logger.info('contract registration successful; %s', contract_id) else: contract_id = crypto.byte_array_to_base64( crypto.compute_message_hash(crypto.random_bit_string(256))) logger.debug('no ledger config; skipping contract registration') except Exception as e: logger.error('failed to register the contract; %s', str(e)) ErrorShutdown() contract_state = contract_helper.ContractState.create_new_state( contract_id) contract = contract_helper.Contract(contract_code, contract_state, contract_id, contract_creator_id) # -------------------------------------------------- logger.info('create the provisioning secrets') # -------------------------------------------------- encrypted_state_encryption_keys = AddEnclaveSecrets( ledger_config, contract.contract_id, contract_creator_keys, enclaves, provisioning_services) for enclave_id in encrypted_state_encryption_keys: encrypted_key = encrypted_state_encryption_keys[enclave_id] contract.set_state_encryption_key(enclave_id, encrypted_key) #add replication information to contract AddReplicationParamsToContract(config, enclaves, contract) # Decide if the contract use a fixed enclave or a randomized one for each update. if use_eservice and config['Service']['Randomize_Eservice']: enclave_to_use = 'random' else: enclave_to_use = enclaves[0] # save the contract info as a pdo file contract_save_file = '_' + contract.short_id + '.pdo' contract.save_to_file(contract_save_file, data_dir=data_dir) # -------------------------------------------------- logger.info('create the initial contract state') # -------------------------------------------------- try: initialize_request = contract.create_initialize_request( contract_creator_keys, enclave_to_use) initialize_response = initialize_request.evaluate() if initialize_response.status is False: logger.error('contract initialization failed: %s', initialize_response.invocation_response) ErrorShutdown() contract.set_state(initialize_response.raw_state) except Exception as e: logger.error('failed to create the initial state; %s', str(e)) ErrorShutdown() logger.info('Created initial state') # submit the commit task: (a commit task replicates change-set and submits the corresponding transaction) try: initialize_response.commit_asynchronously(ledger_config) except Exception as e: logger.exception( 'failed to asynchronously start replication and transaction submission:' + str(e)) ErrorShutdown() # wait for the commit to finish. try: txn_id = initialize_response.wait_for_commit() if use_ledger and txn_id is None: logger.error("Did not receive txn id for the initial commit") ErrorShutdown() except Exception as e: logger.error(str(e)) ErrorShutdown() contract.contract_state.save_to_cache(data_dir=data_dir) return contract
def compute_hash(self): serialized = self.__serialize_for_hashing() report_hash = crypto.compute_message_hash(serialized) # the contract code class expects a string when serializing # for hashing, so use Base64 encoding return crypto.byte_array_to_base64(report_hash)
def compute_hash(self): return crypto.compute_message_hash( crypto.string_to_byte_array(self.serialize_for_hash()))