def test_register_validator_key_mismatch(self): key = signed_object.generate_signing_key() public_key_hash = \ hashlib.sha256( signing.encode_pubkey( signing.generate_pubkey(key), 'hex')).hexdigest() key2 = signed_object.generate_signing_key() validator_id = signed_object.generate_identifier(key) name = 'DasValidator' signup_info = \ SignupInfo.create_signup_info( originator_public_key_hash=public_key_hash, most_recent_wait_certificate_id='0' * 16) store = ObjectStore() transaction = \ ValidatorRegistryTransaction.register_validator( name, validator_id, signup_info) transaction.sign_object(key2) with self.assertRaises(InvalidTransactionError): transaction.check_valid(store) self.fail("Failure: Verified an invalid transaction")
def test_register_validator_re_register(self): key = signed_object.generate_signing_key() public_key_hash = \ hashlib.sha256( signing.encode_pubkey( signing.generate_pubkey(key), 'hex')).hexdigest() validator_id = signed_object.generate_identifier(key) name = 'DasValidator' signup_info = \ SignupInfo.create_signup_info( originator_public_key_hash=public_key_hash, most_recent_wait_certificate_id='0' * 16) store = ObjectStore() transaction = \ ValidatorRegistryTransaction.register_validator( name, validator_id, signup_info) transaction.sign_object(key) try: transaction.check_valid(store) transaction.apply(store) except InvalidTransactionError as e: self.fail('Failed valid transaction: {}'.format(e)) try: # check if valid to register again transaction.check_valid(store) except InvalidTransactionError as e: self.fail('Failure: Double registered validator: {}'.format(e))
def setUp(self): self.private_key = signing.generate_privkey() self.public_key = signing.encode_pubkey( signing.generate_pubkey(self.private_key), "hex") self._out = queue.Queue() self._in = queue.Queue() self._in_condition = Condition() self._out_condition = Condition() self.verifier = SignatureVerifier(self._in, self._out, self._in_condition, self._out_condition)
def _sign_block(self, block): """ The block should be complete and the final signature from the publishing validator(this validator) needs to be added. """ # Temp signature creation to use as identifier temp_key = signing.generate_privkey() public_key = signing.encode_pubkey(signing.generate_pubkey(temp_key), "hex") block.block_header.signer_pubkey = public_key block_header = block.block_header header_bytes = block_header.SerializeToString() signature = signing.sign(header_bytes, temp_key) block.set_signature(signature) return block
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 check_valid(self, store, txn): """Determines if the update is valid. Check policy on each element of validator_name, validator_id, and signup_info Args: store (Store): Transaction store. txn (Transaction): Transaction encompassing this update. """ LOGGER.debug('check update %s from %s', str(self), self.validator_id) # Check name if not self.is_valid_name(): raise InvalidTransactionError( 'Illegal validator name {}'.format(self.validator_name[:64])) # Check registering validator matches transaction signer. if self.validator_id != txn.OriginatorID: raise InvalidTransactionError( 'Signature mismatch on validator registration with validator' ' {} signed by {}'.format(self.validator_id, txn.OriginatorID)) # Nothing to check for anti_sybil_id # Apply will invalidate any previous entries for this anti_sybil_id # and create a new entry. try: public_key_hash = \ hashlib.sha256( signing.encode_pubkey( txn.originator_public_key, 'hex')).hexdigest() self.signup_info.check_valid( originator_public_key_hash=public_key_hash, most_recent_wait_certificate_id='0' * 16) except SignupInfoError as error: raise InvalidTransactionError( 'Invalid Signup Info: {0}, Reason: {1}'.format( self.signup_info, error)) return True
def sign_object(self, signingkey): """Generates a string signature for the object using the signing key. Args: signingkey (str): hex encoded private key """ if self.public_key is None: self.public_key = signing.encode_pubkey( signing.generate_pubkey(signingkey), "hex") self._originator_id = None self._originator_public_key = None serialized = self.serialize(signable=True) self.Signature = signing.sign(serialized, signingkey) self._recover_verifying_address() self._identifier = hashlib.sha256(self.Signature).hexdigest()
def test_is_valid_pub_key(self): pubkey = signing.generate_pubkey("5KQ4iQQGgbQX9MmfiPUwwHBL1R" "GPa86NwFbqrWoodjuzruqFVDd") pub = signing.encode_pubkey(pubkey, "hex") minfo = { 'Nonce': 100, 'PublicKey': pub, 'TransactionType': '/Transaction', 'Dependencies': [] } sig = signing.sign( signed_object.dict2cbor(minfo), "5KQ4iQQGgbQX9MmfiPUwwHBL1RGPa86NwFbqrWoodjuzruqFVDd") # Create valid transaction minfo["Signature"] = sig temp = Transaction(minfo) self.assertTrue(temp.is_valid("unused")) # Change transaction after it was signed minfo["Nonce"] = time.time() temp = Transaction(minfo) self.assertFalse(temp.is_valid("unused"))
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["public_key"] = pub sig = signing.sign(_dict2cbor(transaction), key) transaction['Signature'] = sig txnid = hashlib.sha256(transaction['Signature']).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(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(dict2json(signup_data)) # 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)).hexdigest() } # Fake our "proof" data. verification_report = { 'id': base64.b64encode( hashlib.sha256( datetime.datetime.now().isoformat()).hexdigest()), 'isvEnclaveQuoteStatus': 'OK', 'isvEnclaveQuoteBody': base64.b64encode(dict2json(quote)), 'pseManifestStatus': 'OK', 'pseManifestHash': base64.b64encode( hashlib.sha256(b'Do you believe in ' 'manifest destiny?').hexdigest()), '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 initialization_complete(self, journal): """Processes all invocations that arrived while the ledger was being initialized. """ # Before we allow the base journal to do anything that might result # in a wait timer or wait certificate being created, we have to ensure # the PoET enclave has been initialized. This can be done in one of # two ways: # 1. If we have sealed signup data (meaning that we have previously # created signup info), we can request that the enclave unseal it, # in the process restoring the enclave to its previous state. # 2. Create new signup information. signup_info = None sealed_signup_data = journal.local_store.get('sealed_signup_data') if sealed_signup_data is not None: self.poet_public_key = \ SignupInfo.unseal_signup_data( validator_address=journal.local_node.signing_address(), sealed_signup_data=sealed_signup_data) else: 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 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 # propagate the maximum blocks to keep journal.maximum_blocks_to_keep = max( journal.maximum_blocks_to_keep, WaitTimer.certificate_sample_length) # initialize stats specifically for the block chain journal journal.JournalStats.add_metric(stats.Value('LocalMeanTime', 0)) journal.JournalStats.add_metric(stats.Value('AggregateLocalMean', 0)) journal.JournalStats.add_metric(stats.Value('PopulationEstimate', 0)) journal.JournalStats.add_metric( stats.Value('ExpectedExpirationTime', 0)) journal.JournalStats.add_metric(stats.Value('Duration', 0)) # initialize the block handlers poet_transaction_block.register_message_handlers(journal) # If we created signup information, then advertise self to network if signup_info is not None: # 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 with name %s', journal.local_node.Name) journal.gossip.broadcast_message(message)
def create_random_public_key_hash(): return \ hashlib.sha256( signing.encode_pubkey( create_random_public_key(), 'hex')).hexdigest()