Beispiel #1
0
    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)
Beispiel #2
0
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)))
Beispiel #3
0
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)))
Beispiel #4
0
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))
Beispiel #5
0
 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)
Beispiel #6
0
    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)
Beispiel #7
0
 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")
Beispiel #9
0
 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')
Beispiel #10
0
    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
Beispiel #11
0
    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
Beispiel #12
0
    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)
Beispiel #13
0
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)
Beispiel #16
0
    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)
Beispiel #17
0
    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)
Beispiel #18
0
def create_random_public_key_hash():
    return \
        hashlib.sha256(
            signing.encode_pubkey(
                create_random_public_key(),
                'hex').encode('ascii')).hexdigest()
Beispiel #19
0
 def setUp(self):
     self.private_key = signing.generate_privkey()
     self.public_key = signing.encode_pubkey(
         signing.generate_pubkey(self.private_key), "hex")