def __init__(self): self.block_sender = MockBlockSender() self.batch_sender = MockBatchSender() self.block_store = BlockStore(DictDatabase()) self.block_cache = BlockCache(self.block_store) self.state_db = {} # add the mock reference to the consensus self.state_db[_setting_address('sawtooth.consensus.algorithm')] = \ _setting_entry('sawtooth.consensus.algorithm', 'test_journal.mock_consensus') self.state_view_factory = MockStateViewFactory(self.state_db) self.signing_key = signing.generate_privkey() self.public_key = signing.encode_pubkey( signing.generate_pubkey(self.signing_key), "hex") self.identity_signing_key = signing.generate_privkey() self.genesis_block = self._generate_genesis_block() self.set_chain_head(self.genesis_block) self.block_publisher = BlockPublisher( transaction_executor=MockTransactionExecutor(), block_cache=self.block_cache, state_view_factory=self.state_view_factory, block_sender=self.block_sender, batch_sender=self.block_sender, squash_handler=None, chain_head=self.genesis_block, identity_signing_key=self.identity_signing_key, data_dir=None)
def _read_signing_keys(key_filename): """Reads the given file as a WIF formatted key. Args: key_filename: The filename where the key is stored. Returns: tuple (str, str): the public and private key pair Raises: CliException: If unable to read the file. """ filename = key_filename try: with open(filename, 'r') as key_file: wif_key = key_file.read().strip() signing_key = signing.encode_privkey( signing.decode_privkey(wif_key, 'wif'), 'hex') pubkey = signing.encode_pubkey( signing.generate_pubkey(signing_key), 'hex') return pubkey, signing_key except IOError as e: raise CliException('Unable to read key file: {}'.format(str(e)))
def _read_signing_keys(key_filename): """Reads the given file as a WIF formatted key. Args: key_filename: The filename where the key is stored. If None, defaults to the default key for the current user. Returns: tuple (str, str): the public and private key pair Raises: CliException: If unable to read the file. """ filename = key_filename if filename is None: filename = os.path.join(os.path.expanduser('~'), '.sawtooth', 'keys', getpass.getuser() + '.wif') try: with open(filename, 'r') as key_file: wif_key = key_file.read().strip() signing_key = signing.encode_privkey( signing.decode_privkey(wif_key, 'wif'), 'hex') pubkey = signing.encode_pubkey( signing.generate_pubkey(signing_key), 'hex') return pubkey, signing_key except IOError as e: raise CliException('Unable to read key file: {}'.format(str(e)))
def _do_config_set(args): """Executes the 'set' subcommand. Given a key file, and a series of key/value pairs, it generates batches of sawtooth_config transactions in a BatchList instance, and stores it in a file. """ settings = [s.split('=', 1) for s in args.setting] with open(args.key, 'r') as key_file: wif_key = key_file.read().strip() signing_key = signing.encode_privkey( signing.decode_privkey(wif_key, 'wif'), 'hex') pubkey = signing.encode_pubkey(signing.generate_pubkey(signing_key), 'hex') txns = [ _create_config_txn(pubkey, signing_key, setting) for setting in settings ] txn_ids = [txn.header_signature for txn in txns] batch_header = BatchHeader(signer_pubkey=pubkey, transaction_ids=txn_ids).SerializeToString() batch = Batch(header=batch_header, header_signature=signing.sign(batch_header, signing_key), transactions=txns) batch_list = BatchList(batches=[batch]).SerializeToString() try: with open(args.output, 'wb') as batch_file: batch_file.write(batch_list) except: raise CliException('Unable to write to {}'.format(args.output))
def __init__(self, test_name, tester): super().__init__(test_name) self.tester = tester self.private_key = signing.generate_privkey() self.public_key = signing.encode_pubkey( signing.generate_pubkey(self.private_key), "hex") self.factory = ValidatorRegistryMessageFactory( private=self.private_key, public=self.public_key)
def _generate_genesis_block(self): """ Returns a blocker wrapper with the basics of the block header in place """ genesis_header = block_pb2.BlockHeader( block_num=0, previous_block_id=NULL_BLOCK_IDENTIFIER, signer_pubkey=signing.encode_pubkey( signing.generate_pubkey(self._identity_priv_key), "hex")) return BlockBuilder(genesis_header)
def setUp(self): self.block_store = BlockStore({}) self.gossip = MockGossip() self.completer = Completer(self.block_store, self.gossip) self.completer._on_block_received = self._on_block_received self.completer._on_batch_received = self._on_batch_received self.private_key = signing.generate_privkey() self.public_key = signing.encode_pubkey( signing.generate_pubkey(self.private_key), "hex") self.blocks = [] self.batches = []
def __init__(self, identity_signing_key, batch_sender): """Initialize the BatchPublisher. :param identity_signing_key: the validator's signing key. :param batch_sender: interface to an object that will post the built batch to the network. """ self.identity_signing_key = identity_signing_key self._batch_sender = batch_sender self._identity_signing_key = identity_signing_key self._identity_public_key = signing.encode_pubkey( signing.generate_pubkey(self._identity_signing_key), "hex")
def __init__(self, test_name, tester): super().__init__(test_name) self.tester = tester self.private_key = signing.generate_privkey() self.public_key = signing.encode_pubkey( signing.generate_pubkey(self.private_key), "hex") self.factory = ValidatorRegistryMessageFactory( private=self.private_key, public=self.public_key) self._report_private_key = \ signing.encode_privkey( signing.decode_privkey( '5Jz5Kaiy3kCiHE537uXcQnJuiNJshf2bZZn43CrALMGoCd3zRuo', 'wif'), 'hex')
def _sign_block(self, block): """ The block should be complete and the final signature from the publishing validator (this validator) needs to be added. """ public_key = signing.encode_pubkey( signing.generate_pubkey(self._identity_priv_key), "hex") block.block_header.signer_pubkey = public_key block_header = block.block_header header_bytes = block_header.SerializeToString() signature = signing.sign(header_bytes, self._identity_priv_key) block.set_signature(signature) return block
def __init__(self, transaction_executor, block_cache, state_view_factory, block_sender, batch_sender, squash_handler, chain_head, identity_signing_key, data_dir): """ Initialize the BlockPublisher object Args: transaction_executor (:obj:`TransactionExecutor`): A TransactionExecutor instance. block_cache (:obj:`BlockCache`): A BlockCache instance. state_view_factory (:obj:`StateViewFactory`): StateViewFactory for read-only state views. block_sender (:obj:`BlockSender`): The BlockSender instance. batch_sender (:obj:`BatchSender`): The BatchSender instance. squash_handler (function): Squash handler function for merging contexts. chain_head (:obj:`BlockWrapper`): The initial chain head. identity_signing_key (str): Private key for signing blocks """ self._lock = RLock() self._candidate_block = None # the next block in potentia self._consensus = None self._block_cache = block_cache self._state_view_factory = state_view_factory self._transaction_executor = transaction_executor self._block_sender = block_sender self._batch_publisher = BatchPublisher(identity_signing_key, batch_sender) self._pending_batches = [] # batches we are waiting for validation, # arranged in the order of batches received. self._committed_txn_cache = TransactionCache( self._block_cache.block_store) # Look-up cache for transactions that are committed in the current # chain. Cache is used here so that we can support opportunistically # building on top of a block we published. As well as hold the state # of the transactions already added to the candidate block. self._scheduler = None self._chain_head = chain_head # block (BlockWrapper) self._squash_handler = squash_handler self._identity_signing_key = identity_signing_key self._identity_public_key = signing.encode_pubkey( signing.generate_pubkey(self._identity_signing_key), "hex") self._data_dir = data_dir
def register_signup_information(self, journal): wait_certificate_id = journal.most_recent_committed_block_id public_key_hash = \ hashlib.sha256( signing.encode_pubkey(journal.local_node.public_key(), 'hex')).hexdigest() signup_info = \ SignupInfo.create_signup_info( validator_address=journal.local_node.signing_address(), originator_public_key_hash=public_key_hash, most_recent_wait_certificate_id=wait_certificate_id) # Save off the sealed signup data and cache the PoET public key journal.local_store.set('sealed_signup_data', signup_info.sealed_signup_data) journal.local_store.sync() self.poet_public_key = signup_info.poet_public_key LOGGER.debug('Register %s (%s)', journal.local_node.Name, journal.local_node.Identifier) # Create a validator register transaction and sign it. Wrap # the transaction in a message. Broadcast it to out. transaction = \ val_reg.ValidatorRegistryTransaction.register_validator( journal.local_node.Name, journal.local_node.Identifier, signup_info) transaction.sign_from_node(journal.local_node) message = \ val_reg.ValidatorRegistryTransactionMessage() message.Transaction = transaction LOGGER.info( 'Advertise PoET 1 validator %s (ID = %s) has PoET public key ' '%s', journal.local_node.Name, journal.local_node.Identifier, signup_info.poet_public_key) journal.gossip.broadcast_message(message)
def _sign_message_with_transaction(transaction, message_type, key): """ Signs a transaction message or transaction :param transaction (dict): :param key (str): A signing key returns message, txnid (tuple): The first 16 characters of a sha256 hexdigest. """ transaction['Nonce'] = time.time() pub = signing.encode_pubkey(signing.generate_pubkey(key), "hex") transaction["PublicKey"] = pub sig = signing.sign(_dict2cbor(transaction), key) transaction['Signature'] = sig txnid = hashlib.sha256(transaction['Signature'].encode()).hexdigest()[:16] message = { 'Transaction': transaction, '__TYPE__': message_type, '__NONCE__': time.time(), } cbor_serialized_message = _dict2cbor(message) signature = signing.sign(cbor_serialized_message, key) message['__SIGNATURE__'] = signature return message, txnid
def create_signup_info(self, originator_public_key_hash, most_recent_wait_certificate_id): # currently not used # _active_wait_timer = None # We are going to fake out the sealing the signup data. signup_data = { 'poet_public_key': signing.encode_pubkey(self.poet_public_key, 'hex'), 'poet_private_key': signing.encode_privkey(self._poet_private_key, 'hex') } # Build up a fake SGX quote containing: # 1. The basename # 2. The report body that contains: # a. The enclave measurement # b. The report data SHA256(SHA256(OPK)|PPK) sgx_basename = \ sgx_structs.SgxBasename(name=self.__VALID_BASENAME__) sgx_measurement = \ sgx_structs.SgxMeasurement( m=self.__VALID_ENCLAVE_MEASUREMENT__) hash_input = \ '{0}{1}'.format( originator_public_key_hash.upper(), signing.encode_pubkey( self.poet_public_key, 'hex').upper()).encode() report_data = hashlib.sha256(hash_input).digest() sgx_report_data = sgx_structs.SgxReportData(d=report_data) sgx_report_body = \ sgx_structs.SgxReportBody( mr_enclave=sgx_measurement, report_data=sgx_report_data) sgx_quote = \ sgx_structs.SgxQuote( basename=sgx_basename, report_body=sgx_report_body) # Create a fake PSE manifest. A base64 encoding of the # originator public key hash should suffice. pse_manifest = \ base64.b64encode(originator_public_key_hash.encode()) timestamp = '2017-02-16T15:21:24.437048' # Fake our "proof" data. verification_report = OrderedDict([ ('epidPseudonym', originator_public_key_hash), ('id', base64.b64encode( hashlib.sha256( timestamp.encode()).hexdigest().encode()).decode()), ('isvEnclaveQuoteStatus', 'OK'), ('isvEnclaveQuoteBody', base64.b64encode(sgx_quote.serialize_to_bytes()).decode()), ('pseManifestStatus', 'OK'), ('pseManifestHash', base64.b64encode( hashlib.sha256(pse_manifest).hexdigest().encode()).decode()), ('nonce', most_recent_wait_certificate_id), ('timestamp', timestamp) ]) proof_data = \ self.create_proof_data( verification_report=verification_report, evidence_payload={ 'pse_manifest': pse_manifest.decode() }) return \ SignUpInfo( poet_public_key=signup_data['poet_public_key'], proof_data=proof_data, anti_sybil_id=originator_public_key_hash)
def create_signup_info(self, originator_public_key_hash, most_recent_wait_certificate_id): # First we need to create a public/private key pair for the PoET # enclave to use. poet_private_key = \ "1f70fa2518077ad18483f48e77882d11983b537fa5f7cf158684d2c670fe4f1f" poet_public_key = \ signing.generate_pubkey(poet_private_key) # currently not used # _active_wait_timer = None # We are going to fake out the sealing the signup data. signup_data = { 'poet_public_key': signing.encode_pubkey(poet_public_key, 'hex'), 'poet_private_key': signing.encode_privkey(poet_private_key, 'hex') } # Create a fake report report_data = '{0}{1}'.format( originator_public_key_hash.upper(), signing.encode_pubkey(poet_public_key, 'hex').upper()) quote = { 'report_body': hashlib.sha256(json.dumps(report_data).encode()).hexdigest() } # Create a fake PSE manifest. A base64 encoding of the # originator public key hash should suffice. pse_manifest = \ base64.b64encode(originator_public_key_hash.encode()) timestamp = '2017-02-16T15:21:24.437048' # Fake our "proof" data. verification_report = { 'epidPseudonym': originator_public_key_hash, 'id': base64.b64encode( hashlib.sha256( timestamp.encode()).hexdigest().encode()).decode(), 'isvEnclaveQuoteStatus': 'OK', 'isvEnclaveQuoteBody': base64.b64encode(json.dumps(quote).encode()).decode(), 'pseManifestStatus': 'OK', 'pseManifestHash': base64.b64encode( hashlib.sha256(pse_manifest).hexdigest().encode()).decode(), 'nonce': most_recent_wait_certificate_id, 'timestamp': timestamp } proof_data = \ self.create_proof_data( verification_report=verification_report, evidence_payload={ 'pse_manifest': pse_manifest.decode() }) return \ SignUpInfo( poet_public_key=signup_data['poet_public_key'], proof_data=proof_data, anti_sybil_id=originator_public_key_hash)
def test_invalid_enclave_body(self): """ Test that a transaction whose enclave_body is invalid returns an invalid transaction. """ signup_info = self.factory.create_signup_info(self.factory.pubkey_hash, "000") proof_data = signup_info.proof_data proof_data_dict = json.loads(proof_data) # ------------------------------------------------------ # No isvEnclaveQuoteStatus verification_report = \ json.loads(proof_data_dict["verification_report"]) enclave_status = verification_report["isvEnclaveQuoteStatus"] verification_report["isvEnclaveQuoteStatus"] = None signup_info.proof_data = \ self.factory.create_proof_data( verification_report=verification_report, evidence_payload=proof_data_dict.get('evidence_payload')) self._test_bad_signup_info(signup_info) # ------------------------------------------------------ # Bad isvEnclaveQuoteStatus verification_report = \ json.loads(proof_data_dict["verification_report"]) verification_report["isvEnclaveQuoteStatus"] = "Bad" signup_info.proof_data = \ self.factory.create_proof_data( verification_report=verification_report, evidence_payload=proof_data_dict.get('evidence_payload')) self._test_bad_signup_info(signup_info) # ------------------------------------------------------ # No isvEnclaveQuoteBody verification_report = \ json.loads(proof_data_dict["verification_report"]) verification_report["isvEnclaveQuoteStatus"] = enclave_status verification_report['isvEnclaveQuoteBody'] = None signup_info.proof_data = \ self.factory.create_proof_data( verification_report=verification_report, evidence_payload=proof_data_dict.get('evidence_payload')) self._test_bad_signup_info(signup_info) # ------------------------------------------------------ # Malformed isvEnclaveQuoteBody (decode the enclave quote, chop off # the last byte, and re-encode) verification_report = \ json.loads(proof_data_dict["verification_report"]) verification_report['isvEnclaveQuoteBody'] = \ base64.b64encode( base64.b64decode( verification_report['isvEnclaveQuoteBody'].encode())[1:])\ .decode() signup_info.proof_data = \ self.factory.create_proof_data( verification_report=verification_report, evidence_payload=proof_data_dict.get('evidence_payload')) self._test_bad_signup_info(signup_info) # ------------------------------------------------------ # Invalid basename verification_report = \ json.loads(proof_data_dict["verification_report"]) sgx_quote = sgx_structs.SgxQuote() sgx_quote.parse_from_bytes( base64.b64decode( verification_report['isvEnclaveQuoteBody'].encode())) sgx_quote.basename.name = \ b'\xCC' * sgx_structs.SgxBasename.STRUCT_SIZE verification_report['isvEnclaveQuoteBody'] = \ base64.b64encode(sgx_quote.serialize_to_bytes()).decode() signup_info.proof_data = \ self.factory.create_proof_data( verification_report=verification_report, evidence_payload=proof_data_dict.get('evidence_payload')) self._test_bad_signup_info(signup_info) # ------------------------------------------------------ # Report data is not valid (bad OPK hash) verification_report = \ json.loads(proof_data_dict["verification_report"]) sgx_quote = sgx_structs.SgxQuote() sgx_quote.parse_from_bytes( base64.b64decode( verification_report['isvEnclaveQuoteBody'].encode())) hash_input = \ '{0}{1}'.format( 'Not a valid OPK Hash', signing.encode_pubkey( self.factory.poet_public_key, 'hex').upper()).encode() sgx_quote.report_body.report_data.d = \ hashlib.sha256(hash_input).digest() verification_report['isvEnclaveQuoteBody'] = \ base64.b64encode(sgx_quote.serialize_to_bytes()).decode() signup_info.proof_data = \ self.factory.create_proof_data( verification_report=verification_report, evidence_payload=proof_data_dict.get('evidence_payload')) self._test_bad_signup_info(signup_info) # ------------------------------------------------------ # Report data is not valid (bad PPK) verification_report = \ json.loads(proof_data_dict["verification_report"]) sgx_quote = sgx_structs.SgxQuote() sgx_quote.parse_from_bytes( base64.b64decode( verification_report['isvEnclaveQuoteBody'].encode())) hash_input = \ '{0}{1}'.format( self.factory.pubkey_hash, "Not a valid PPK").encode() sgx_quote.report_body.report_data.d = \ hashlib.sha256(hash_input).digest() verification_report['isvEnclaveQuoteBody'] = \ base64.b64encode(sgx_quote.serialize_to_bytes()).decode() signup_info.proof_data = \ self.factory.create_proof_data( verification_report=verification_report, evidence_payload=proof_data_dict.get('evidence_payload')) self._test_bad_signup_info(signup_info) # ------------------------------------------------------ # Invalid enclave measurement verification_report = \ json.loads(proof_data_dict["verification_report"]) sgx_quote = sgx_structs.SgxQuote() sgx_quote.parse_from_bytes( base64.b64decode( verification_report['isvEnclaveQuoteBody'].encode())) sgx_quote.report_body.mr_enclave.m = \ b'\xCC' * sgx_structs.SgxMeasurement.STRUCT_SIZE verification_report['isvEnclaveQuoteBody'] = \ base64.b64encode(sgx_quote.serialize_to_bytes()).decode() signup_info.proof_data = \ self.factory.create_proof_data( verification_report=verification_report, evidence_payload=proof_data_dict.get('evidence_payload')) self._test_bad_signup_info(signup_info)
def create_signup_info(cls, originator_public_key_hash, most_recent_wait_certificate_id): with cls._lock: # First we need to create a public/private key pair for the PoET # enclave to use. cls._poet_private_key = signing.generate_privkey() cls._poet_public_key = \ signing.generate_pubkey(cls._poet_private_key) cls._active_wait_timer = None # We are going to fake out the sealing the signup data. signup_data = { 'poet_public_key': signing.encode_pubkey(cls._poet_public_key, 'hex'), 'poet_private_key': signing.encode_privkey(cls._poet_private_key, 'hex') } sealed_signup_data = \ base64.b64encode(bytes(dict2json(signup_data).encode())) # Create a fake report report_data = '{0}{1}'.format( originator_public_key_hash.upper(), signing.encode_pubkey(cls._poet_public_key, 'hex').upper()) quote = { 'report_body': hashlib.sha256(dict2json(report_data).encode()).hexdigest() } # Fake our "proof" data. verification_report = { 'id': base64.b64encode( bytes( hashlib.sha256(datetime.datetime.now().isoformat( ).encode()).hexdigest().encode())).decode(), 'isvEnclaveQuoteStatus': 'OK', 'isvEnclaveQuoteBody': base64.b64encode(dict2json(quote).encode()).decode(), 'pseManifestStatus': 'OK', 'pseManifestHash': base64.b64encode( hashlib.sha256( bytes(b'Do you believe in ' b'manifest destiny?')).hexdigest().encode()). decode(), 'nonce': most_recent_wait_certificate_id } proof_data_dict = { 'verification_report': dict2json(verification_report), 'signature': signing.sign(dict2json(verification_report), cls._report_private_key) } proof_data = dict2json(proof_data_dict) return \ EnclaveSignupInfo( poet_public_key=signup_data['poet_public_key'], proof_data=proof_data, anti_sybil_id=originator_public_key_hash, sealed_signup_data=sealed_signup_data)
def create_random_public_key_hash(): return \ hashlib.sha256( signing.encode_pubkey( create_random_public_key(), 'hex').encode('ascii')).hexdigest()
def setUp(self): self.private_key = signing.generate_privkey() self.public_key = signing.encode_pubkey( signing.generate_pubkey(self.private_key), "hex")