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').encode()).hexdigest()
        validator_id = signed_object.generate_identifier(key)
        name = 'DasValidator'
        signup_info = \
            SignupInfo.create_signup_info(
                validator_address='1660 Pennsylvania Avenue NW',
                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))
Пример #2
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))
Пример #3
0
def do_keygen(args):
    if args.key_name is not None:
        key_name = args.key_name
    else:
        key_name = getpass.getuser()

    if args.key_dir is not None:
        key_dir = args.key_dir
        if not os.path.exists(key_dir):
            raise CliException('no such directory: {}'.format(key_dir))
    else:
        key_dir = os.path.join(os.path.expanduser('~'), '.sawtooth', 'keys')
        if not os.path.exists(key_dir):
            if not args.quiet:
                print('creating key directory: {}'.format(key_dir))
            try:
                os.makedirs(key_dir)
            except IOError as e:
                raise CliException('IOError: {}'.format(str(e)))

    wif_filename = os.path.join(key_dir, key_name + '.wif')
    addr_filename = os.path.join(key_dir, key_name + '.addr')

    if not args.force:
        file_exists = False
        for filename in [wif_filename, addr_filename]:
            if os.path.exists(filename):
                file_exists = True
                print('file exists: {}'.format(filename), file=sys.stderr)
        if file_exists:
            raise CliException(
                'files exist, rerun with --force to overwrite existing files')

    privkey = signing.generate_privkey()
    encoded = signing.encode_privkey(privkey)
    pubkey = signing.generate_pubkey(privkey)
    addr = signing.generate_identifier(pubkey)

    try:
        wif_exists = os.path.exists(wif_filename)
        with open(wif_filename, 'w') as wif_fd:
            if not args.quiet:
                if wif_exists:
                    print('overwriting file: {}'.format(wif_filename))
                else:
                    print('writing file: {}'.format(wif_filename))
            wif_fd.write(encoded)
            wif_fd.write('\n')

        addr_exists = os.path.exists(addr_filename)
        with open(addr_filename, 'w') as addr_fd:
            if not args.quiet:
                if addr_exists:
                    print('overwriting file: {}'.format(addr_filename))
                else:
                    print('writing file: {}'.format(addr_filename))
            addr_fd.write(addr)
            addr_fd.write('\n')
    except IOError as ioe:
        raise CliException('IOError: {}'.format(str(ioe)))
    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').encode()).hexdigest()
        key2 = signed_object.generate_signing_key()
        validator_id = signed_object.generate_identifier(key)
        name = 'DasValidator'
        signup_info = \
            SignupInfo.create_signup_info(
                validator_address='1660 Pennsylvania Avenue NW',
                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")
Пример #5
0
def generate_identifier(signingkey):
    """Generates encoded version of the public key associated with
    signingkey.

    Args:
        signingkey (str): A private key.

    Returns:
        str: An encoded 'address' associated with the public key.
    """
    return signing.generate_identifier(signing.generate_pubkey(signingkey))
Пример #6
0
    def _sign_block(block):
        """ The block should be complete and the final
        signature from the publishing validator (this validator) needs to
        be added.
        """
        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
Пример #7
0
    def __init__(self,
                 base_url,
                 store_name=None,
                 name='SawtoothClient',
                 txntype_name=None,
                 msgtype_name=None,
                 keystring=None,
                 keyfile=None,
                 disable_client_validation=False):
        self._base_url = base_url
        self._message_type = msgtype_name
        self._transaction_type = txntype_name

        # an explicit store name takes precedence over a store name
        # implied by the transaction type
        self._store_name = None
        if store_name is not None:
            self._store_name = store_name.strip('/')
        elif txntype_name is not None:
            self._store_name = txntype_name.strip('/')

        self._communication = _Communication(base_url)
        self._last_transaction = None
        self._signing_key = None
        self._identifier = None
        self._update_batch = None
        self._disable_client_validation = disable_client_validation

        if keystring:
            LOGGER.debug("set signing key from string\n%s", keystring)
            self._signing_key = signing.encode_privkey(
                signing.decode_privkey(keystring, 'wif'), 'hex')
        elif keyfile:
            LOGGER.debug("set signing key from file %s", keyfile)
            try:
                self._signing_key = signing.encode_privkey(
                    signing.decode_privkey(
                        open(keyfile, "r").read().strip(), 'wif'), 'hex')
            except IOError as ex:
                raise ClientException(
                    "Failed to load key file: {}".format(str(ex)))

        if self._signing_key is not None:
            self._identifier = signing.generate_identifier(
                signing.generate_pubkey(self._signing_key))
    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"))
Пример #9
0
def do_init(args, config):
    username = config.get('DEFAULT', 'username')
    if args.username is not None:
        username = args.username

    url = config.get('DEFAULT', 'url')
    if args.url is not None:
        url = args.url

    config.set('DEFAULT', 'username', username)
    print("set username: {}".format(username))
    config.set('DEFAULT', 'url', url)
    print("set url: {}".format(url))

    save_config(config)

    wif_filename = config.get('DEFAULT', 'key_file')
    if wif_filename.endswith(".wif"):
        addr_filename = wif_filename[0:-len(".wif")] + ".addr"
    else:
        addr_filename = wif_filename + ".addr"

    if not os.path.exists(wif_filename):
        try:
            if not os.path.exists(os.path.dirname(wif_filename)):
                os.makedirs(os.path.dirname(wif_filename))

            privkey = signing.generate_privkey()
            encoded = signing.encode_privkey(privkey, 'wif')
            pubkey = signing.generate_pubkey(privkey)
            addr = signing.generate_identifier(pubkey)

            with open(wif_filename, "w") as wif_fd:
                print("writing file: {}".format(wif_filename))
                wif_fd.write(encoded)
                wif_fd.write("\n")

            with open(addr_filename, "w") as addr_fd:
                print("writing file: {}".format(addr_filename))
                addr_fd.write(addr)
                addr_fd.write("\n")
        except IOError as ioe:
            raise XoException("IOError: {}".format(str(ioe)))
Пример #10
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
Пример #11
0
def get_address_from_private_key_wif(key):
    return signing.generate_identifier(
        signing.generate_pubkey(signing.decode_privkey(key, 'wif')))
Пример #12
0
def create_random_public_key():
    return signing.generate_pubkey(create_random_private_key())
    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_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)
class _PoetEnclaveSimulator(object):
    # A lock to protect threaded access
    _lock = threading.Lock()

    # The private key we generate to sign the certificate ID when creating
    # the random wait timeout value
    _seal_private_key = signing.generate_privkey()
    _seal_public_key = signing.generate_pubkey(_seal_private_key)

    # The WIF-encoded private report key.  From it, we will create private
    # key we can use for signing attestation verification reports.
    __REPORT_PRIVATE_KEY_WIF = \
        '5Jz5Kaiy3kCiHE537uXcQnJuiNJshf2bZZn43CrALMGoCd3zRuo'

    _report_private_key = \
        signing.encode_privkey(
            signing.decode_privkey(__REPORT_PRIVATE_KEY_WIF, 'wif'), 'hex')
    _report_public_key = signing.generate_pubkey(_report_private_key)

    # The anti-sybil ID for this particular validator.  This will get set when
    # the enclave is initialized
    _anti_sybil_id = None

    # The PoET keys will remain unset until signup info is either created or
    # unsealed
    _poet_public_key = None
    _poet_private_key = None
    _active_wait_timer = None

    @classmethod
    def initialize(cls, **kwargs):
        # Create an anti-Sybil ID that is unique for this validator
        cls._anti_sybil_id = \
            hashlib.sha256(
                kwargs.get('NodeName', 'validator').encode()).hexdigest()

    @classmethod
    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)

    @classmethod
    def deserialize_signup_info(cls, serialized_signup_info):
        return \
            EnclaveSignupInfo.signup_info_from_serialized(
                serialized_signup_info=serialized_signup_info)

    @classmethod
    def unseal_signup_data(cls, sealed_signup_data):
        """

        Args:
            sealed_signup_data: Sealed signup data that was returned
                previously in a EnclaveSignupInfo object from a call to
                create_signup_info

        Returns:
            A string The hex encoded PoET public key that was extracted from
            the sealed data
        """

        # Reverse the process we used in creating "sealed" signup info.
        # Specifically, we will do a base 32 decode, which gives us json
        # we can convert back to a dictionary we can use to get the
        # data we need
        signup_data = \
            json2dict(base64.b64decode(sealed_signup_data).decode())

        with cls._lock:
            cls._poet_public_key = \
                signing.decode_pubkey(
                    signup_data.get('poet_public_key'),
                    'hex')
            cls._poet_private_key = \
                signing.decode_privkey(
                    signup_data.get('poet_private_key'),
                    'hex')
            cls._active_wait_timer = None

            return signup_data.get('poet_public_key')

    @classmethod
    def verify_signup_info(cls, signup_info, originator_public_key_hash,
                           most_recent_wait_certificate_id):
        # Verify the attestation verification report signature
        proof_data_dict = json2dict(signup_info.proof_data)
        verification_report = proof_data_dict.get('verification_report')
        if verification_report is None:
            raise ValueError('Verification report is missing from proof data')

        signature = proof_data_dict.get('signature')
        if signature is None:
            raise ValueError('Signature is missing from proof data')

        if not signing.verify(verification_report, signature,
                              cls._report_public_key):
            raise ValueError('Verification report signature is invalid')

        verification_report_dict = json2dict(verification_report)

        # Verify that the verification report contains a PSE manifest status
        # and it is OK
        pse_manifest_status = \
            verification_report_dict.get('pseManifestStatus')
        if pse_manifest_status is None:
            raise \
                ValueError(
                    'Verification report does not contain a PSE manifest '
                    'status')
        if pse_manifest_status != 'OK':
            raise \
                ValueError(
                    'PSE manifest status is {} (i.e., not OK)'.format(
                        pse_manifest_status))

        # Verify that the verification report contains a PSE manifest hash
        # and it is the value we expect
        pse_manifest_hash = \
            verification_report_dict.get('pseManifestHash')
        if pse_manifest_hash is None:
            raise \
                ValueError(
                    'Verification report does not contain a PSE manifest '
                    'hash')

        expected_pse_manifest_hash = \
            base64.b64encode(
                hashlib.sha256(
                    bytes(b'Do you believe in '
                          b'manifest destiny?')).hexdigest()
                .encode()).decode()

        if pse_manifest_hash != expected_pse_manifest_hash:
            raise \
                ValueError(
                    'PSE manifest hash {0} does not match {1}'.format(
                        pse_manifest_hash,
                        expected_pse_manifest_hash))

        # Verify that the verification report contains an enclave quote and
        # that its status is OK
        enclave_quote_status = \
            verification_report_dict.get('isvEnclaveQuoteStatus')
        if enclave_quote_status is None:
            raise \
                ValueError(
                    'Verification report does not contain an enclave quote '
                    'status')
        if enclave_quote_status != 'OK':
            raise \
                ValueError(
                    'Enclave quote status is {} (i.e., not OK)'.format(
                        enclave_quote_status))

        enclave_quote = verification_report_dict.get('isvEnclaveQuoteBody')
        if enclave_quote is None:
            raise \
                ValueError(
                    'Verification report does not contain an enclave quote')

        # Verify that the enclave quote contains a report body with the value
        # we expect (i.e., SHA256(SHA256(OPK)|PPK)
        report_data = '{0}{1}'.format(originator_public_key_hash.upper(),
                                      signup_info.poet_public_key.upper())
        expected_report_body = hashlib.sha256(
            dict2json(report_data).encode()).hexdigest()

        enclave_quote_dict = \
            json2dict(base64.b64decode(enclave_quote).decode())
        report_body = enclave_quote_dict.get('report_body')
        if report_body is None:
            raise ValueError('Enclave quote does not contain a report body')

        if report_body != expected_report_body:
            raise \
                ValueError(
                    'Enclave quote report body {0} does not match {1}'.format(
                        report_body,
                        expected_report_body))

        # Verify that the wait certificate ID in the verification report
        # matches the provided wait certificate ID.  The wait certificate ID
        # is stored in the nonce field.
        nonce = verification_report_dict.get('nonce')
        if nonce is None:
            raise \
                ValueError(
                    'Verification report does not have a nonce')

        # NOTE - this check is currently not performed as a transaction
        #        does not have a good way to obtaining the most recent
        #        wait certificate ID.
        #
        # if nonce != most_recent_wait_certificate_id:
        #     raise \
        #         ValueError(
        #             'Attestation evidence payload nonce {0} does not match '
        #             'most-recently-committed wait certificate ID {1}'.format(
        #                 nonce,
        #                 most_recent_wait_certificate_id))

    @classmethod
    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

    @classmethod
    def deserialize_wait_timer(cls, serialized_timer, signature):
        with cls._lock:
            # Verify the signature before trying to deserialize
            if not signing.verify(serialized_timer, signature,
                                  cls._poet_public_key):
                return None

        return \
            EnclaveWaitTimer.wait_timer_from_serialized(
                serialized_timer=serialized_timer,
                signature=signature)

    @classmethod
    def create_wait_certificate(cls, wait_timer, block_digest):
        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_digest=block_digest)
            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

    @classmethod
    def deserialize_wait_certificate(cls, serialized_certificate, signature):
        return \
            EnclaveWaitCertificate.wait_certificate_from_serialized(
                serialized_certificate=serialized_certificate,
                signature=signature)

    @classmethod
    def verify_wait_certificate(cls, certificate, poet_public_key):
        # Reconstitute the PoET public key and check the signature over the
        # serialized wait certificate.
        decoded_poet_public_key = \
            signing.decode_pubkey(poet_public_key, 'hex')

        if not \
            signing.verify(
                certificate.serialize(),
                certificate.signature,
                decoded_poet_public_key):
            raise ValueError('Wait certificate signature does not match')
Пример #16
0
 def public_key(self):
     return signing.generate_pubkey(self.SigningKey)
Пример #17
0
    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

        _report_private_key = \
            signing.encode_privkey(
                signing.decode_privkey(
                    '5Jz5Kaiy3kCiHE537uXcQnJuiNJshf2bZZn43CrALMGoCd3zRuo',
                    'wif'), 'hex')

        # 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()
        }

        # Fake our "proof" data.
        verification_report = {
            'id':
            base64.b64encode(
                bytes(
                    hashlib.sha256(b'2017-02-16T15:21:24.437048').hexdigest().
                    encode())).decode(),
            'isvEnclaveQuoteStatus':
            'OK',
            'isvEnclaveQuoteBody':
            base64.b64encode(json.dumps(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':
            json.dumps(verification_report),
            'signature':
            signing.sign(json.dumps(verification_report), _report_private_key)
        }
        proof_data = json.dumps(proof_data_dict)

        return \
            SignUpInfo(
                poet_public_key=signup_data['poet_public_key'],
                proof_data=proof_data,
                anti_sybil_id=originator_public_key_hash)
Пример #18
0
    wif_filename = os.path.join(key_dir, key_name + '.wif')
    addr_filename = os.path.join(key_dir, key_name + '.addr')

    if not args.force:
        file_exists = False
        for filename in [wif_filename, addr_filename]:
            if os.path.exists(filename):
                file_exists = True
                print('file exists: {}'.format(filename), file=sys.stderr)
        if file_exists:
            raise ClientException(
                'files exist, rerun with --force to overwrite existing files')

    privkey = signing.generate_privkey()
    encoded = signing.encode_privkey(privkey)
    pubkey = signing.generate_pubkey(privkey)
    addr = signing.generate_identifier(pubkey)

    try:
        wif_exists = os.path.exists(wif_filename)
        with open(wif_filename, 'w') as wif_fd:
            if not args.quiet:
                if wif_exists:
                    print('overwriting file: {}'.format(wif_filename))
                else:
                    print('writing file: {}'.format(wif_filename))
            wif_fd.write(encoded)
            wif_fd.write('\n')

        addr_exists = os.path.exists(addr_filename)
        with open(addr_filename, 'w') as addr_fd:
 def __init__(self):
     self.SigningKey = signing.generate_privkey()
     self.Address = signing.generate_identifier(
         signing.generate_pubkey(self.SigningKey))
 def __init__(self):
     self.SigningKey = signing.generate_privkey()
     self.Address = signing.generate_identifier(
         signing.generate_pubkey(self.SigningKey))
Пример #21
0
 def setUp(self):
     self.private_key = signing.generate_privkey()
     self.public_key = signing.encode_pubkey(
         signing.generate_pubkey(self.private_key), "hex")