def wrap_payload_in_txn_batch(txn_key, payload, header, batch_key): """Takes the serialized RBACPayload and creates a batch_list, batch signature tuple. Args: txn_key (Key): The txn signer's public/private key pair. payload (bytes): The serialized RBACPayload. header (bytes): The serialized TransactionHeader. batch_key (Key): The batch signer's public/private key pair. Returns: tuple The zeroth element is a BatchList, and the first element is the batch header_signature. """ transaction = transaction_pb2.Transaction(payload=payload, header=header, header_signature=signing.sign( header, txn_key.private_key)) batch_header = batch_pb2.BatchHeader( signer_pubkey=batch_key.public_key, transaction_ids=[transaction.header_signature]).SerializeToString() batch = batch_pb2.Batch(header=batch_header, header_signature=signing.sign( batch_header, batch_key.private_key), transactions=[transaction]) batch_list = batch_pb2.BatchList(batches=[batch]) return batch_list, batch.header_signature
def _generate_batch(self, payload): payload_encoded = payload.encode('utf-8') hasher = hashlib.sha512() hasher.update(payload_encoded) header = TransactionHeader() header.batcher_pubkey = self.public_key # txn.dependencies not yet header.family_name = 'test' header.family_version = '1' header.nonce = _generate_id(16) header.payload_encoding = "text" header.payload_sha512 = hasher.hexdigest().encode() header.signer_pubkey = self.public_key txn = Transaction() header_bytes = header.SerializeToString() txn.header = header_bytes txn.header_signature = signing.sign(header_bytes, self.signing_key) txn.payload = payload_encoded batch_header = BatchHeader() batch_header.signer_pubkey = self.public_key batch_header.transaction_ids.extend([txn.header_signature]) batch = Batch() header_bytes = batch_header.SerializeToString() batch.header = header_bytes batch.header_signature = signing.sign(header_bytes, self.signing_key) batch.transactions.extend([txn]) return batch
def create_transaction(name, private_key, public_key): payload = name addr = '000000' + hashlib.sha512(name.encode()).hexdigest() header = transaction_pb2.TransactionHeader( signer_pubkey=public_key, family_name='scheduler_test', family_version='1.0', inputs=[addr], outputs=[addr], dependencies=[], payload_encoding="application/cbor", payload_sha512=hashlib.sha512(payload.encode()).hexdigest(), batcher_pubkey=public_key) header_bytes = header.SerializeToString() signature = signing.sign(header_bytes, private_key) transaction = transaction_pb2.Transaction( header=header_bytes, payload=payload.encode(), header_signature=signature) return transaction
def create_intkey_transaction(verb, name, value, private_key, public_key): payload = IntKeyPayload( verb=verb, name=name, value=value) # The prefix should eventually be looked up from the # validator's namespace registry. addr = make_intkey_address(name) header = transaction_pb2.TransactionHeader( signer_public_key=public_key, family_name='intkey', family_version='1.0', inputs=[addr], outputs=[addr], dependencies=[], payload_sha512=payload.sha512(), batcher_public_key=public_key, nonce=time.time().hex().encode()) header_bytes = header.SerializeToString() signature = signing.sign(header_bytes, private_key) transaction = transaction_pb2.Transaction( header=header_bytes, payload=payload.to_cbor(), header_signature=signature) return transaction
def _create_blocks(self, block_count, batch_count, valid_block=True, valid_batch=True): block_list = [] for i in range(block_count): batch_list = self._create_batches(batch_count, 2, valid_batch=valid_batch) batch_ids = [batch.header_signature for batch in batch_list] block_header = BlockHeader(signer_pubkey=self.public_key, batch_ids=batch_ids) header_bytes = block_header.SerializeToString() if valid_block: signature = signing.sign(header_bytes, self.private_key) else: signature = "bad_signature" block = Block(header=header_bytes, batches=batch_list, header_signature=signature) block_list.append(block) return block_list
def _create_batches(self, batch_count, txn_count, valid_batch=True, valid_txn=True, valid_structure=True, valid_batcher=True): batch_list = [] for i in range(batch_count): txn_list = self._create_transactions(txn_count, valid_txn, valid_batcher) txn_sig_list = [txn.header_signature for txn in txn_list] if not valid_structure: txn_sig_list.pop() batch_header = BatchHeader(signer_pubkey=self.public_key) batch_header.transaction_ids.extend(txn_sig_list) header_bytes = batch_header.SerializeToString() if valid_batch: signature = signing.sign( header_bytes, self.private_key) else: signature = "bad_signature" batch = Batch(header=header_bytes, transactions=txn_list, header_signature=signature) batch_list.append(batch) return batch_list
def create_noop_transaction(private_key, public_key): payload = NoopPayload() header = transaction_pb2.TransactionHeader( signer_pubkey=public_key, family_name='noop', family_version='1.0', inputs=[], outputs=[], dependencies=[], payload_encoding="none", payload_sha512=payload.sha512(), batcher_pubkey=public_key, nonce=time.time().hex().encode()) header_bytes = header.SerializeToString() signature = signing.sign(header_bytes, private_key) transaction = transaction_pb2.Transaction( header=header_bytes, payload=payload.nonce, header_signature=signature) return transaction
def _create_batches(self, batch_count, txn_count, valid_batch=True, valid_txn=True, valid_structure=True, valid_batcher=True): batch_list = [] for i in range(batch_count): txn_list = self._create_transactions(txn_count, valid_txn, valid_batcher) txn_sig_list = [txn.header_signature for txn in txn_list] if not valid_structure: txn_sig_list.pop() batch_header = BatchHeader(signer_pubkey=self.public_key) batch_header.transaction_ids.extend(txn_sig_list) header_bytes = batch_header.SerializeToString() if valid_batch: signature = signing.sign(header_bytes, self.private_key) else: signature = "bad_signature" batch = Batch(header=header_bytes, transactions=txn_list, header_signature=signature) batch_list.append(batch) return batch_list
def _create_blocks(self, block_count, batch_count, valid_block=True, valid_batch=True): block_list = [] for i in range(block_count): batch_list = self._create_batches( batch_count, 2, valid_batch=valid_batch) batch_ids = [batch.header_signature for batch in batch_list] block_header = BlockHeader(signer_pubkey=self.public_key, batch_ids=batch_ids) header_bytes = block_header.SerializeToString() if valid_block: signature = signing.sign( header_bytes, self.private_key) else: signature = "bad_signature" block = Block(header=header_bytes, batches=batch_list, header_signature=signature) block_list.append(block) return block_list
def test_deserialized_wait_timer(self): wait_timer = \ EnclaveWaitTimer( validator_address='1600 Pennsylvania Avenue NW', duration=3.14159, previous_certificate_id='Bond. James Bond.', local_mean=2.71828) serialized = wait_timer.serialize() signing_key = self._create_random_key() wait_timer.signature = \ signing.sign(serialized, signing_key) copy_wait_timer = \ EnclaveWaitTimer.wait_timer_from_serialized( serialized, wait_timer.signature) self.assertEqual(wait_timer.validator_address, copy_wait_timer.validator_address) self.assertAlmostEqual(wait_timer.request_time, copy_wait_timer.request_time) self.assertAlmostEqual(wait_timer.duration, copy_wait_timer.duration) self.assertEqual(wait_timer.previous_certificate_id, copy_wait_timer.previous_certificate_id) self.assertAlmostEqual(wait_timer.local_mean, copy_wait_timer.local_mean) self.assertEqual(wait_timer.signature, copy_wait_timer.signature) self.assertEqual(serialized, copy_wait_timer.serialize())
def _create_transactions(self, count): txn_list = [] for i in range(count): payload = {'Verb': 'set', 'Name': 'name', 'Value': 1} intkey_prefix = \ hashlib.sha512('intkey'.encode('utf-8')).hexdigest()[0:6] addr = intkey_prefix + \ hashlib.sha512(payload["Name"].encode('utf-8')).hexdigest() payload_encode = hashlib.sha512(cbor.dumps(payload)).hexdigest() header = TransactionHeader(signer_public_key=self.public_key, family_name='intkey', family_version='1.0', inputs=[addr], outputs=[addr], dependencies=[], payload_sha512=payload_encode) header.batcher_public_key = self.public_key header_bytes = header.SerializeToString() signature = signing.sign(header_bytes, self.private_key) transaction = Transaction(header=header_bytes, payload=cbor.dumps(payload), header_signature=signature) txn_list.append(transaction) return txn_list
def create_intkey_transaction(verb, name, value, private_key, public_key): payload = IntKeyPayload( verb=verb, name=name, value=value) # The prefix should eventually be looked up from the # validator's namespace registry. addr = make_intkey_address(name) header = transaction_pb2.TransactionHeader( signer_pubkey=public_key, family_name='intkey', family_version='1.0', inputs=[addr], outputs=[addr], dependencies=[], payload_encoding="application/cbor", payload_sha512=payload.sha512(), batcher_pubkey=public_key, nonce=time.time().hex().encode()) header_bytes = header.SerializeToString() signature = signing.sign(header_bytes, private_key) transaction = transaction_pb2.Transaction( header=header_bytes, payload=payload.to_cbor(), header_signature=signature) return transaction
def _create_batches(self, batch_count, txn_count, missing_dep=False): batch_list = [] for i in range(batch_count): txn_list = self._create_transactions(txn_count, missing_dep=missing_dep) txn_sig_list = [txn.header_signature for txn in txn_list] batch_header = BatchHeader(signer_pubkey=self.public_key) batch_header.transaction_ids.extend(txn_sig_list) header_bytes = batch_header.SerializeToString() signature = signing.sign( header_bytes, self.private_key) batch = Batch(header=header_bytes, transactions=txn_list, header_signature=signature) batch_list.append(batch) return batch_list
def test_authorization_challenge_submit(self): """ Test the AuthorizationChallengeSubmitHandler returns an AuthorizationViolation and closes the connection if the permission verifier does not permit the public_key. """ private_key = signing.generate_private_key() public_key = signing.generate_public_key(private_key) payload = os.urandom(10) signature = signing.sign(payload, private_key) auth_challenge_submit = AuthorizationChallengeSubmit( public_key=public_key, payload=payload, signature=signature, roles=[RoleType.Value("NETWORK")]) roles = {"network": AuthorizationType.TRUST} network = MockNetwork(roles, connection_status={ "connection_id": ConnectionStatus.AUTH_CHALLENGE_REQUEST }) permission_verifer = MockPermissionVerifier(allow=False) gossip = MockGossip() handler = AuthorizationChallengeSubmitHandler(network, permission_verifer, gossip) handler_status = handler.handle( "connection_id", auth_challenge_submit.SerializeToString()) self.assertEqual(handler_status.status, HandlerStatus.RETURN_AND_CLOSE) self.assertEqual(handler_status.message_type, validator_pb2.Message.AUTHORIZATION_VIOLATION)
def _create_role_txn(public_key, signing_key, role_name, policy_name): role = Role(name=role_name, policy_name=policy_name) payload = IdentityPayload(type=IdentityPayload.ROLE, data=role.SerializeToString()) policy_address = _policy_to_address(policy_name) role_address = _role_to_address(role_name) header = TransactionHeader( signer_public_key=public_key, family_name='sawtooth_identity', family_version='1.0', inputs=[_REQUIRED_INPUT, policy_address, role_address], outputs=[role_address], dependencies=[], payload_sha512=hashlib.sha512(payload.SerializeToString()).hexdigest(), batcher_public_key=public_key, nonce=time.time().hex().encode()) header_bytes = header.SerializeToString() signature = signing.sign(header_bytes, signing_key) transaction = Transaction(header=header_bytes, payload=payload.SerializeToString(), header_signature=signature) return transaction
def create_transaction(payload, private_key, public_key, inputs=None, outputs=None, dependencies=None): addr = '000000' + hashlib.sha512(payload).hexdigest()[:64] if inputs is None: inputs = [addr] if outputs is None: outputs = [addr] if dependencies is None: dependencies = [] header = transaction_pb2.TransactionHeader( signer_pubkey=public_key, family_name='scheduler_test', family_version='1.0', inputs=inputs, outputs=outputs, dependencies=dependencies, nonce=str(time.time()), payload_encoding="application/cbor", payload_sha512=hashlib.sha512(payload).hexdigest(), batcher_pubkey=public_key) header_bytes = header.SerializeToString() signature = signing.sign(header_bytes, private_key) transaction = transaction_pb2.Transaction( header=header_bytes, payload=payload, header_signature=signature) return transaction, header
def create_wait_timer(cls, sealed_signup_data, validator_address, previous_certificate_id, local_mean, minimum_wait_time): with cls._lock: # Extract keys from the 'sealed' signup data signup_data = \ json2dict( base64.b64decode(sealed_signup_data.encode()).decode()) poet_private_key = signup_data['poet_private_key'] if poet_private_key is None: raise \ ValueError( 'Invalid signup data. No poet private key.') # In a TEE implementation we would increment the HW counter here. # We can't usefully simulate a HW counter though. # Create some value from the cert ID. We are just going to use # the seal key to sign the cert ID. We will then use the # low-order 64 bits to change that to a number [0, 1] tag = \ base64.b64decode( signing.sign( previous_certificate_id, cls._seal_private_key)) tagd = float(struct.unpack('Q', tag[-8:])[0]) / (2**64 - 1) # Now compute the duration with a minimum wait time guaranteed duration = minimum_wait_time - local_mean * math.log(tagd) # Create and sign the wait timer wait_timer = \ EnclaveWaitTimer( validator_address=validator_address, duration=duration, previous_certificate_id=previous_certificate_id, local_mean=local_mean) wait_timer.signature = \ signing.sign( wait_timer.serialize(), poet_private_key) return wait_timer
def create_wait_timer(cls, validator_address, previous_certificate_id, local_mean, minimum_wait_time): with cls._lock: # If we don't have a PoET private key, then the enclave has not # been properly initialized (either by calling create_signup_info # or unseal_signup_data) if cls._poet_private_key is None: raise \ ValueError( 'Enclave must be initialized before attempting to ' 'create a wait timer') # Create some value from the cert ID. We are just going to use # the seal key to sign the cert ID. We will then use the # low-order 64 bits to change that to a number [0, 1] tag = \ base64.b64decode( signing.sign( previous_certificate_id, cls._seal_private_key)) tagd = float(struct.unpack('Q', tag[-8:])[0]) / (2**64 - 1) # Now compute the duration with a minimum wait time guaranteed duration = minimum_wait_time - local_mean * math.log(tagd) # Create and sign the wait timer wait_timer = \ EnclaveWaitTimer( validator_address=validator_address, duration=duration, previous_certificate_id=previous_certificate_id, local_mean=local_mean) wait_timer.signature = \ signing.sign( wait_timer.serialize(), cls._poet_private_key) # Keep track of the active wait timer cls._active_wait_timer = wait_timer return wait_timer
def _sign_block(self, block, identity_signing_key): """ The block should be complete and the final signature from the publishing validator(this validator) needs to be added. :param block: the Block to sign. :param identity_signing_key: the key to sign the block with. """ header_bytes = block.block_header.SerializeToString() signature = signing.sign(header_bytes, identity_signing_key) block.set_signature(signature)
def _sign_block(self, block): """ The block should be complete and the final signature from the publishing validator(this validator) needs to be added. """ block_header = block.block_header header_bytes = block_header.SerializeToString() signature = signing.sign(header_bytes, self._identity_signing_key) block.set_signature(signature) return block
def _create_transactions(self, count, matched_payload=True, valid_signature=True, valid_batcher=True): txn_list = [] for i in range(count): payload = {'Verb': 'set', 'Name': 'name' + str(random.randint(0, 100)), 'Value': random.randint(0, 100)} intkey_prefix = \ hashlib.sha512('intkey'.encode('utf-8')).hexdigest()[0:6] addr = intkey_prefix + \ hashlib.sha512(payload["Name"].encode('utf-8')).hexdigest() payload_encode = hashlib.sha512(cbor.dumps(payload)).hexdigest() header = TransactionHeader( signer_pubkey=self.public_key, family_name='intkey', family_version='1.0', inputs=[addr], outputs=[addr], dependencies=[], payload_encoding="application/cbor", payload_sha512=payload_encode) if valid_batcher: header.batcher_pubkey = self.public_key else: header.batcher_pubkey = "bad_batcher" header_bytes = header.SerializeToString() if valid_signature: signature = signing.sign( header_bytes, self.private_key) else: signature = "bad_signature" if not matched_payload: payload['Name'] = 'unmatched_payload' transaction = Transaction( header=header_bytes, payload=cbor.dumps(payload), header_signature=signature) txn_list.append(transaction) return txn_list
def _sign_block(self, block): """ The block should be complete and the final signature from the publishing validator (this validator) needs to be added. """ 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 _generate_block(self, payload, previous_block_id, block_num): header = BlockHeader(previous_block_id=previous_block_id, signer_pubkey=self.public_key, block_num=block_num) block_builder = BlockBuilder(header) block_builder.add_batches([self._generate_batch_from_payload(payload)]) header_bytes = block_builder.block_header.SerializeToString() signature = signing.sign(header_bytes, self.identity_signing_key) block_builder.set_signature(signature) return BlockWrapper(block_builder.build_block())
def create_jvm_sc_transaction(verb, private_key, public_key, bytecode=None, methods=None, byte_addr=None, method=None, parameters=None, addresses=None): payload = JVM_SC_Payload(verb=verb, bytecode=bytecode, methods=methods, byte_addr=byte_addr, method=method, parameters=parameters) if addresses is None: addresses = [] # The prefix should eventually be looked up from the # validator's namespace registry. if byte_addr is not None: addr = byte_addr elif bytecode is not None: addr = get_address('jvm_sc', bytecode) else: raise Exception addresses.append(addr) header = transaction_pb2.TransactionHeader( signer_pubkey=public_key, family_name='jvm_sc', family_version='1.0', inputs=addresses, outputs=addresses, dependencies=[], payload_encoding="application/protobuf", payload_sha512=payload.sha512(), batcher_pubkey=public_key, nonce=str(time.time())) header_bytes = header.SerializeToString() signature = signing.sign(header_bytes, private_key) transaction = transaction_pb2.Transaction(header=header_bytes, payload=payload.payload_bytes, header_signature=signature) return transaction
def create_intkey_transaction(verb, name, value, deps, private_key, public_key): """Creates a signed intkey transaction. Args: verb (str): the action the transaction takes, either 'set', 'inc', or 'dec' name (str): the variable name which is altered by verb and value value (int): the amount to set, increment, or decrement deps ([str]): a list of transaction header_signatures which are required dependencies which must be processed prior to processing this transaction private_key (str): the private key used to sign the transaction public_key (str): the public key associated with the private key - the public key is included in the transaction as signer_pubkey Returns: transaction (transaction_pb2.Transaction): the signed intkey transaction """ payload = IntKeyPayload( verb=verb, name=name, value=value) # The prefix should eventually be looked up from the # validator's namespace registry. addr = make_intkey_address(name) header = transaction_pb2.TransactionHeader( signer_pubkey=public_key, family_name='intkey', family_version='1.0', inputs=[addr], outputs=[addr], dependencies=deps, payload_encoding="application/cbor", payload_sha512=payload.sha512(), batcher_pubkey=public_key, nonce=time.time().hex().encode()) header_bytes = header.SerializeToString() signature = signing.sign(header_bytes, private_key) transaction = transaction_pb2.Transaction( header=header_bytes, payload=payload.to_cbor(), header_signature=signature) return transaction
def create_intkey_transaction(verb, name, value, deps, private_key, public_key): """Creates a signed intkey transaction. Args: verb (str): the action the transaction takes, either 'set', 'inc', or 'dec' name (str): the variable name which is altered by verb and value value (int): the amount to set, increment, or decrement deps ([str]): a list of transaction header_signatures which are required dependencies which must be processed prior to processing this transaction private_key (str): the private key used to sign the transaction public_key (str): the public key associated with the private key - the public key is included in the transaction as signer_pubkey Returns: transaction (transaction_pb2.Transaction): the signed intkey transaction """ payload = IntKeyPayload(verb=verb, name=name, value=value) # The prefix should eventually be looked up from the # validator's namespace registry. intkey_prefix = hashlib.sha512('intkey'.encode('utf-8')).hexdigest()[0:6] addr = intkey_prefix + hashlib.sha512(name.encode('utf-8')).hexdigest() header = transaction_pb2.TransactionHeader( signer_pubkey=public_key, family_name='intkey', family_version='1.0', inputs=[addr], outputs=[addr], dependencies=deps, payload_encoding="application/cbor", payload_sha512=payload.sha512(), batcher_pubkey=public_key, nonce=time.time().hex().encode()) header_bytes = header.SerializeToString() signature = signing.sign(header_bytes, private_key) transaction = transaction_pb2.Transaction(header=header_bytes, payload=payload.to_cbor(), header_signature=signature) return transaction
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.generate_pubkey(key) 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_batch(transactions, private_key, public_key): transaction_signatures = [t.header_signature for t in transactions] header = batch_pb2.BatchHeader(signer_pubkey=public_key, transaction_ids=transaction_signatures) header_bytes = header.SerializeToString() signature = signing.sign(header_bytes, private_key) batch = batch_pb2.Batch(header=header_bytes, transactions=transactions, header_signature=signature) return batch
def _generate_block(self, payload, previous_block_id, block_num): header = BlockHeader( previous_block_id=previous_block_id, signer_pubkey=self.public_key, block_num=block_num) block_builder = BlockBuilder(header) block_builder.add_batches( [self._generate_batch_from_payload(payload)]) header_bytes = block_builder.block_header.SerializeToString() signature = signing.sign(header_bytes, self.identity_signing_key) block_builder.set_signature(signature) block_wrapper = BlockWrapper(block_builder.build_block()) LOGGER.debug("Generated %s", dumps_block(block_wrapper)) return block_wrapper
def create_batch(transactions, private_key, public_key): transaction_ids = [t.header_signature for t in transactions] header = batch_pb2.BatchHeader( signer_pubkey=public_key, transaction_ids=transaction_ids) header_bytes = header.SerializeToString() signature = signing.sign(header_bytes, private_key) batch = batch_pb2.Batch( header=header_bytes, transactions=transactions, header_signature=signature) return batch
def send(self, transactions): """ Package up transactions into a batch and send them to the network via the provided batch_sender. :param transactions: list of transactions to package and broadcast. :return: None """ txn_signatures = [txn.header_signature for txn in transactions] header = BatchHeader( signer_pubkey=self._identity_public_key, transaction_ids=txn_signatures).SerializeToString() signature = signing.sign(header, self._identity_signing_key) batch = Batch(header=header, transactions=transactions, header_signature=signature) self._batch_sender.send(batch)
def _make_txn(public_key, signing_key, setting_key, payload): """Creates and signs a sawtooth_settings transaction with with a payload. """ serialized_payload = payload.SerializeToString() header = TransactionHeader( signer_public_key=public_key, family_name='sawtooth_settings', family_version='1.0', inputs=_config_inputs(setting_key), outputs=_config_outputs(setting_key), dependencies=[], payload_sha512=hashlib.sha512(serialized_payload).hexdigest(), batcher_public_key=public_key).SerializeToString() signature = signing.sign(header, signing_key) return Transaction(header=header, header_signature=signature, payload=serialized_payload)
def send(self, transactions): """ Package up transactions into a batch and send them to the network via the provided batch_sender. :param transactions: list of transactions to package and broadcast. :return: None """ txn_signatures = [txn.header_signature for txn in transactions] header = BatchHeader( signer_pubkey=self._identity_public_key, transaction_ids=txn_signatures ).SerializeToString() signature = signing.sign(header, self._identity_signing_key) batch = Batch( header=header, transactions=transactions, header_signature=signature) self._batch_sender.send(batch)
def _create_batch(public_key, signing_key, transactions): """Creates a batch from a list of transactions and a public key, and signs the resulting batch with the given signing key. Args: public_key (str): The public key associated with the signing key. signing_key (str): The private key for signing the batch. transactions (list of `Transaction`): The transactions to add to the batch. Returns: `Batch`: The constructed and signed batch. """ txn_ids = [txn.header_signature for txn in transactions] batch_header = BatchHeader(signer_public_key=public_key, transaction_ids=txn_ids).SerializeToString() return Batch(header=batch_header, header_signature=signing.sign(batch_header, signing_key), transactions=transactions)
def create_block(self, payload='payload', batch_count=1, previous_block_id=NULL_BLOCK_IDENTIFIER, block_num=0): header = BlockHeader( previous_block_id=previous_block_id, signer_pubkey=self.public_key, block_num=block_num) block_builder = BlockBuilder(header) block_builder.add_batches( [self._generate_batch_from_payload(payload) for _ in range(batch_count)]) block_builder.set_state_hash('0'*70) header_bytes = block_builder.block_header.SerializeToString() signature = signing.sign(header_bytes, self.identity_signing_key) block_builder.set_signature(signature) block_wrapper = BlockWrapper(block_builder.build_block()) LOGGER.debug("Generated %s", dumps_block(block_wrapper)) return block_wrapper
def _create_blocks(self, block_count, batch_count, missing_predecessor=False, missing_batch=False, find_batch=True): block_list = [] pred = 0 for i in range(0, block_count): batch_list = self._create_batches(batch_count, 2) batch_ids = [batch.header_signature for batch in batch_list] if missing_predecessor: predecessor = "Missing" else: predecessor = (block_list[i-1].header_signature if i > 0 else NULL_BLOCK_IDENTIFIER) block_header = BlockHeader( signer_pubkey=self.public_key, batch_ids=batch_ids, block_num=i, previous_block_id= predecessor ) header_bytes = block_header.SerializeToString() signature = signing.sign( header_bytes, self.private_key) if missing_batch: if find_batch: self.completer.add_batch(batch_list[-1]) batch_list = batch_list[:-1] block = Block(header=header_bytes, batches=batch_list, header_signature=signature) block_list.append(block) return block_list
def test_deserialized_wait_certificate(self): wait_timer = \ EnclaveWaitTimer( validator_address='1600 Pennsylvania Avenue NW', duration=3.14159, previous_certificate_id='Smart, Maxwell Smart', local_mean=2.71828) wait_certificate = \ EnclaveWaitCertificate.wait_certificate_with_wait_timer( wait_timer=wait_timer, nonce='Eeny, meeny, miny, moe.', block_hash='Indigestion. Pepto Bismol.') serialized = wait_certificate.serialize() signing_key = self._create_random_key() wait_certificate.signature = \ signing.sign(serialized, signing_key) copy_wait_certificate = \ EnclaveWaitCertificate.wait_certificate_from_serialized( serialized, wait_certificate.signature) self.assertAlmostEqual(wait_certificate.request_time, copy_wait_certificate.request_time) self.assertAlmostEqual(wait_certificate.duration, copy_wait_certificate.duration) self.assertEqual(wait_certificate.previous_certificate_id, copy_wait_certificate.previous_certificate_id) self.assertAlmostEqual(wait_certificate.local_mean, copy_wait_certificate.local_mean) self.assertEqual(wait_certificate.validator_address, copy_wait_certificate.validator_address) self.assertEqual(wait_certificate.nonce, copy_wait_certificate.nonce) self.assertEqual(wait_certificate.block_hash, copy_wait_certificate.block_hash) self.assertEqual(wait_certificate.signature, copy_wait_certificate.signature) self.assertEqual(serialized, copy_wait_certificate.serialize())
def _create_policy_txn(pubkey, signing_key, policy_name, rules): entries = [] for rule in rules: rule = rule.split(" ") if rule[0] == "PERMIT_KEY": entry = Policy.Entry(type=Policy.PERMIT_KEY, key=rule[1]) entries.append(entry) elif rule[0] == "DENY_KEY": entry = Policy.Entry(type=Policy.DENY_KEY, key=rule[1]) entries.append(entry) policy = Policy(name=policy_name, entries=entries) payload = IdentityPayload(type=IdentityPayload.POLICY, data=policy.SerializeToString()) policy_address = _policy_to_address(policy_name) header = TransactionHeader( signer_pubkey=pubkey, family_name='sawtooth_identity', family_version='1.0', inputs=[policy_address], outputs=[policy_address], dependencies=[], payload_encoding="application/protobuf", payload_sha512=hashlib.sha512( payload.SerializeToString()).hexdigest(), batcher_pubkey=pubkey, nonce=time.time().hex().encode()) header_bytes = header.SerializeToString() signature = signing.sign(header_bytes, signing_key) transaction = Transaction( header=header_bytes, payload=payload.SerializeToString(), header_signature=signature) return transaction
def create_transaction(payload, private_key, public_key, inputs=None, outputs=None, dependencies = None): addr = '000000' + hashlib.sha512(payload).hexdigest()[:64] if inputs is None: inputs = [addr] else: inputs = inputs.copy().append(addr) if outputs is None: outputs = [addr] else: outputs.copy().append(addr) if dependencies is None: dependencies = [] header = transaction_pb2.TransactionHeader( signer_pubkey=public_key, family_name='scheduler_test', family_version='1.0', inputs=inputs, outputs=outputs, dependencies=dependencies, nonce=str(time.time()), payload_encoding="application/cbor", payload_sha512=hashlib.sha512(payload).hexdigest(), batcher_pubkey=public_key) header_bytes = header.SerializeToString() signature = signing.sign(header_bytes, private_key) transaction = transaction_pb2.Transaction( header=header_bytes, payload=payload, header_signature=signature) return transaction, header
def _inbound_challenge_authorization_callback(self, request, result, connection=None): if result.message_type != \ validator_pb2.Message.AUTHORIZATION_CHALLENGE_RESPONSE: LOGGER.debug("Unable to complete Challenge Authorization.") return auth_challenge_response = AuthorizationChallengeResponse() auth_challenge_response.ParseFromString(result.content) payload = auth_challenge_response.payload signature = signing.sign(payload, self._priv_key) auth_challenge_submit = AuthorizationChallengeSubmit( public_key=self._public_key, payload=payload, signature=signature, roles=[RoleType.Value("NETWORK")]) self.send(validator_pb2.Message.AUTHORIZATION_CHALLENGE_SUBMIT, auth_challenge_submit.SerializeToString(), connection)
def _make_txn(pubkey, signing_key, setting_key, payload): """Creates and signs a sawtooth_settings transaction with with a payload. """ serialized_payload = payload.SerializeToString() header = TransactionHeader( signer_pubkey=pubkey, family_name='sawtooth_settings', family_version='1.0', inputs=_config_inputs(setting_key), outputs=_config_outputs(setting_key), dependencies=[], payload_encoding='application/protobuf', payload_sha512=hashlib.sha512(serialized_payload).hexdigest(), batcher_pubkey=pubkey ).SerializeToString() signature = signing.sign(header, signing_key) return Transaction( header=header, header_signature=signature, payload=serialized_payload)
def _create_batch(pubkey, signing_key, transactions): """Creates a batch from a list of transactions and a public key, and signs the resulting batch with the given signing key. Args: pubkey (str): The public key associated with the signing key. signing_key (str): The private key for signing the batch. transactions (list of `Transaction`): The transactions to add to the batch. Returns: `Batch`: The constructed and signed batch. """ txn_ids = [txn.header_signature for txn in transactions] batch_header = BatchHeader(signer_pubkey=pubkey, transaction_ids=txn_ids).SerializeToString() return Batch( header=batch_header, header_signature=signing.sign(batch_header, signing_key), transactions=transactions )
def test_deserialized_wait_timer(self): wait_timer = \ EnclaveWaitTimer( validator_address='1600 Pennsylvania Avenue NW', duration=3.14159, previous_certificate_id='Bond. James Bond.', local_mean=2.71828) serialized = wait_timer.serialize() signing_key = self._create_random_key() wait_timer.signature = \ signing.sign(serialized, signing_key) copy_wait_timer = \ EnclaveWaitTimer.wait_timer_from_serialized( serialized, wait_timer.signature) self.assertEqual( wait_timer.validator_address, copy_wait_timer.validator_address) self.assertAlmostEqual( wait_timer.request_time, copy_wait_timer.request_time) self.assertAlmostEqual( wait_timer.duration, copy_wait_timer.duration) self.assertEqual( wait_timer.previous_certificate_id, copy_wait_timer.previous_certificate_id) self.assertAlmostEqual( wait_timer.local_mean, copy_wait_timer.local_mean) self.assertEqual( wait_timer.signature, copy_wait_timer.signature) self.assertEqual(serialized, copy_wait_timer.serialize())
def _register_signup_information(self, block_header, poet_enclave_module): # Create signup information for this validator, putting the block ID # of the block previous to the block referenced by block_header in the # nonce. Block ID is better than wait certificate ID for testing # freshness as we need to account for non-PoET blocks. public_key_hash = \ hashlib.sha256( block_header.signer_pubkey.encode()).hexdigest() nonce = SignupInfo.block_id_to_nonce(block_header.previous_block_id) signup_info = \ SignupInfo.create_signup_info( poet_enclave_module=poet_enclave_module, originator_public_key_hash=public_key_hash, nonce=nonce) # Create the validator registry payload payload = \ vr_pb.ValidatorRegistryPayload( verb='register', name='validator-{}'.format(block_header.signer_pubkey[:8]), id=block_header.signer_pubkey, signup_info=vr_pb.SignUpInfo( poet_public_key=signup_info.poet_public_key, proof_data=signup_info.proof_data, anti_sybil_id=signup_info.anti_sybil_id, nonce=nonce), ) serialized = payload.SerializeToString() # Create the address that will be used to look up this validator # registry transaction. Seems like a potential for refactoring.. validator_entry_address = \ PoetBlockPublisher._validator_registry_namespace + \ hashlib.sha256(block_header.signer_pubkey.encode()).hexdigest() # Create a transaction header and transaction for the validator # registry update amd then hand it off to the batch publisher to # send out. output_addresses = \ [validator_entry_address, PoetBlockPublisher._validator_map_address] input_addresses = \ output_addresses + \ [SettingsView.setting_address( 'sawtooth.poet.report_public_key_pem'), SettingsView.setting_address( 'sawtooth.poet.valid_enclave_measurements'), SettingsView.setting_address( 'sawtooth.poet.valid_enclave_basenames')] header = \ txn_pb.TransactionHeader( signer_pubkey=block_header.signer_pubkey, family_name='sawtooth_validator_registry', family_version='1.0', inputs=input_addresses, outputs=output_addresses, dependencies=[], payload_encoding="application/protobuf", payload_sha512=hashlib.sha512(serialized).hexdigest(), batcher_pubkey=block_header.signer_pubkey, nonce=time.time().hex().encode()).SerializeToString() signature = \ signing.sign(header, self._batch_publisher.identity_signing_key) transaction = \ txn_pb.Transaction( header=header, payload=serialized, header_signature=signature) LOGGER.info( 'Register Validator Name=%s, ID=%s...%s, PoET public key=%s...%s, ' 'Nonce=%s', payload.name, payload.id[:8], payload.id[-8:], payload.signup_info.poet_public_key[:8], payload.signup_info.poet_public_key[-8:], nonce) self._batch_publisher.send([transaction]) # Store the key state so that we can look it up later if need be and # set the new key as our active key LOGGER.info( 'Save key state PPK=%s...%s => SSD=%s...%s', signup_info.poet_public_key[:8], signup_info.poet_public_key[-8:], signup_info.sealed_signup_data[:8], signup_info.sealed_signup_data[-8:]) self._poet_key_state_store[signup_info.poet_public_key] = \ PoetKeyState( sealed_signup_data=signup_info.sealed_signup_data, has_been_refreshed=False) self._poet_key_state_store.active_key = signup_info.poet_public_key
def do_genesis(args): """Executes the `poet genesis` subcommand. This command generates a validator registry transaction and saves it to a file, whose location is determined by the args. The signup data, generated by the selected enclave, is also stored in a well-known location. """ pubkey, signing_key = _read_signing_keys(args.key) public_key_hash = sha256(pubkey.encode()).hexdigest() with PoetEnclaveModuleWrapper( enclave_module=args.enclave_module, config_dir=config.get_config_dir(), data_dir=config.get_data_dir()) as poet_enclave_module: signup_info = SignupInfo.create_signup_info( poet_enclave_module=poet_enclave_module, originator_public_key_hash=public_key_hash, nonce=SignupInfo.block_id_to_nonce(NULL_BLOCK_IDENTIFIER)) print( 'Writing key state for PoET public key: {}...{}'.format( signup_info.poet_public_key[:8], signup_info.poet_public_key[-8:])) # Store the newly-created PoET key state, associating it with its # corresponding public key poet_key_state_store = \ PoetKeyStateStore( data_dir=config.get_data_dir(), validator_id=pubkey) poet_key_state_store[signup_info.poet_public_key] = \ PoetKeyState( sealed_signup_data=signup_info.sealed_signup_data, has_been_refreshed=False) # Create the validator registry payload payload = \ vr_pb.ValidatorRegistryPayload( verb='register', name='validator-{}'.format(pubkey[:8]), id=pubkey, signup_info=vr_pb.SignUpInfo( poet_public_key=signup_info.poet_public_key, proof_data=signup_info.proof_data, anti_sybil_id=signup_info.anti_sybil_id, nonce=NULL_BLOCK_IDENTIFIER)) serialized = payload.SerializeToString() # Create the address that will be used to look up this validator # registry transaction. Seems like a potential for refactoring.. validator_entry_address = \ VR_NAMESPACE + sha256(pubkey.encode()).hexdigest() # Create a transaction header and transaction for the validator # registry update amd then hand it off to the batch publisher to # send out. output_addresses = [validator_entry_address, VALIDATOR_MAP_ADDRESS] input_addresses = \ output_addresses + \ [SettingsView.setting_address('sawtooth.poet.report_public_key_pem'), SettingsView.setting_address('sawtooth.poet.' 'valid_enclave_measurements'), SettingsView.setting_address('sawtooth.poet.valid_enclave_basenames')] header = \ txn_pb.TransactionHeader( signer_pubkey=pubkey, family_name='sawtooth_validator_registry', family_version='1.0', inputs=input_addresses, outputs=output_addresses, dependencies=[], payload_encoding="application/protobuf", payload_sha512=sha512(serialized).hexdigest(), batcher_pubkey=pubkey, nonce=time.time().hex().encode()).SerializeToString() signature = signing.sign(header, signing_key) transaction = \ txn_pb.Transaction( header=header, payload=serialized, header_signature=signature) batch = _create_batch(pubkey, signing_key, [transaction]) batch_list = batch_pb.BatchList(batches=[batch]) try: print('Generating {}'.format(args.output)) with open(args.output, 'wb') as batch_file: batch_file.write(batch_list.SerializeToString()) except IOError as e: raise CliException( 'Unable to write to batch file: {}'.format(str(e)))
def create_wait_certificate(cls, wait_timer, block_hash): with cls._lock: # If we don't have a PoET private key, then the enclave has not # been properly initialized (either by calling create_signup_info # or unseal_signup_data) if cls._poet_private_key is None: raise \ ValueError( 'Enclave must be initialized before attempting to ' 'create a wait certificate') # Several criteria need to be met before we can create a wait # certificate: # 1. We have an active timer # 2. The caller's wait timer is the active wait timer. We are not # going to rely the objects, being the same, but will compute # a signature over the object and verify that the signatures # are the same. # 3. The active timer has expired # 4. The active timer has not timed out # # Note - we make a concession for the genesis block (i.e., a wait # timer for which the previous certificate ID is the Null # identifier) in that we don't require the timer to have expired # and we don't worry about the timer having timed out. if cls._active_wait_timer is None: raise \ ValueError( 'There is not a current enclave active wait timer') if wait_timer is None or \ cls._active_wait_timer.signature != \ signing.sign( wait_timer.serialize(), cls._poet_private_key): raise \ ValueError( 'Validator is not using the current wait timer') is_not_genesis_block = \ (cls._active_wait_timer.previous_certificate_id != NULL_BLOCK_IDENTIFIER) now = time.time() expire_time = \ cls._active_wait_timer.request_time + \ cls._active_wait_timer.duration if is_not_genesis_block and now < expire_time: raise \ ValueError( 'Cannot create wait certificate because timer has ' 'not expired') time_out_time = \ cls._active_wait_timer.request_time + \ cls._active_wait_timer.duration + \ TIMER_TIMEOUT_PERIOD if is_not_genesis_block and time_out_time < now: raise \ ValueError( 'Cannot create wait certificate because timer ' 'has timed out') # Create a random nonce for the certificate. For our "random" # nonce we will take the timer signature, concat that with the # current time, JSON-ize it and create a SHA-256 hash over it. # Probably not considered random by security professional # standards, but it is good enough for the simulator. random_string = \ dict2json({ 'wait_timer_signature': cls._active_wait_timer.signature, 'now': datetime.datetime.utcnow().isoformat() }) nonce = hashlib.sha256(random_string.encode()).hexdigest() # First create a new enclave wait certificate using the data # provided and then sign the certificate with the PoET private key wait_certificate = \ EnclaveWaitCertificate.wait_certificate_with_wait_timer( wait_timer=cls._active_wait_timer, nonce=nonce, block_hash=block_hash) wait_certificate.signature = \ signing.sign( wait_certificate.serialize(), cls._poet_private_key) # Now that we have created the certificate, we no longer have an # active timer cls._active_wait_timer = None return wait_certificate
def _signed_header(self, header): return signing.sign( header, self.signing_key)
def _sign(content, private): return signing.sign(content, private)