Exemple #1
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)))
Exemple #2
0
 def test_valid_signature(self):
     signing_key = SigObj.generate_signing_key()
     pub_key = signing.generate_pubkey(signing_key)
     temp = SignedObject({"PublicKey": pub_key})
     # test valid signature
     temp.sign_object(signing_key)
     self.assertTrue(temp.is_valid("valid"))
    def test_libor_update_invalid_value_one_year(self):
        key = signed_object.generate_signing_key()
        store = ObjectStore()
        libor_key = TestCreateLIBORUpdate.libor_key
        libor_public_key = signing.generate_pubkey(libor_key)
        update = \
            CreateLIBORUpdate(
                update_type='CreateLIBOR',
                date='2016-05-24',
                rates={
                    'Overnight': 0.1,
                    'OneWeek': 0.1,
                    'OneMonth': 0.1,
                    'TwoMonth': 0.1,
                    'ThreeMonth': 0.1,
                    'SixMonth': 0.1,
                    'OneYear': 'invalid rate'
                },
                libor_public_key=libor_public_key)
        update.sign_update_object(libor_key)

        transaction = BondTransaction()
        transaction._updates = [update]
        transaction.sign_object(key)

        try:
            transaction.check_valid(store)
            self.fail('This transaction should be invalid')
        except InvalidTransactionError:
            pass
Exemple #4
0
    def test_register_validator_re_register(self):
        key = signed_object.generate_signing_key()
        public_key_hash = \
            hashlib.sha256(
                signing.encode_pubkey(
                    signing.generate_pubkey(key),
                    'hex')).hexdigest()
        validator_id = signed_object.generate_identifier(key)
        name = 'DasValidator'
        signup_info = \
            SignupInfo.create_signup_info(
                originator_public_key_hash=public_key_hash,
                most_recent_wait_certificate_id='0' * 16)

        store = ObjectStore()
        transaction = \
            ValidatorRegistryTransaction.register_validator(
                name,
                validator_id,
                signup_info)
        transaction.sign_object(key)
        try:
            transaction.check_valid(store)
            transaction.apply(store)
        except InvalidTransactionError as e:
            self.fail('Failed valid transaction: {}'.format(e))
        try:  # check if valid to register again
            transaction.check_valid(store)
        except InvalidTransactionError as e:
            self.fail('Failure: Double registered validator: {}'.format(e))
Exemple #5
0
    def test_register_validator_key_mismatch(self):
        key = signed_object.generate_signing_key()
        public_key_hash = \
            hashlib.sha256(
                signing.encode_pubkey(
                    signing.generate_pubkey(key),
                    'hex')).hexdigest()
        key2 = signed_object.generate_signing_key()
        validator_id = signed_object.generate_identifier(key)
        name = 'DasValidator'
        signup_info = \
            SignupInfo.create_signup_info(
                originator_public_key_hash=public_key_hash,
                most_recent_wait_certificate_id='0' * 16)

        store = ObjectStore()
        transaction = \
            ValidatorRegistryTransaction.register_validator(
                name,
                validator_id,
                signup_info)
        transaction.sign_object(key2)
        with self.assertRaises(InvalidTransactionError):
            transaction.check_valid(store)
            self.fail("Failure: Verified an invalid transaction")
 def setUp(self):
     self.private_key = signing.generate_privkey()
     self.public_key = signing.encode_pubkey(
         signing.generate_pubkey(self.private_key), "hex")
     self._out = queue.Queue()
     self._in = queue.Queue()
     self._in_condition = Condition()
     self._out_condition = Condition()
     self.verifier = SignatureVerifier(self._in, self._out,
                                       self._in_condition,
                                       self._out_condition)
Exemple #7
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))
Exemple #8
0
    def __init__(self, base_url, keyfile):

        self._base_url = base_url

        try:
            with open(keyfile) as fd:
                self._private_key = fd.read().strip()
                fd.close()
        except:
            raise IOError("Failed to read keys.")

        self._public_key = signing.generate_pubkey(self._private_key)
Exemple #9
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.
        """
        # Temp signature creation to use as identifier
        temp_key = signing.generate_privkey()
        public_key = signing.encode_pubkey(signing.generate_pubkey(temp_key),
                                           "hex")

        block.block_header.signer_pubkey = public_key
        block_header = block.block_header
        header_bytes = block_header.SerializeToString()
        signature = signing.sign(header_bytes, temp_key)
        block.set_signature(signature)
        return block
Exemple #10
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))
Exemple #11
0
    def sign_object(self, signingkey):
        """Generates a string signature for the object using the signing
        key.

        Args:
            signingkey (str): hex encoded private key
        """

        if self.public_key is None:
            self.public_key = signing.encode_pubkey(
                signing.generate_pubkey(signingkey), "hex")

        self._originator_id = None
        self._originator_public_key = None
        serialized = self.serialize(signable=True)
        self.Signature = signing.sign(serialized, signingkey)

        self._recover_verifying_address()
        self._identifier = hashlib.sha256(self.Signature).hexdigest()
Exemple #12
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)))
Exemple #13
0
def find_or_create_test_key(key_base_name, key_dir=None, quiet=True):
    '''
    Interface to sawtooth cli: creates .wif key file if it does not exist, and
    returns a tupple containing all pertinent information.  Useful for testing.
    Args:
        key_base_name: (str)
        key_dir: (str)
    Returns: (tupple)
        key_file: (str)
        private_key: (str)
        public_key: (str)
    '''
    use_key_dir = key_dir is not None and not os.path.isabs(key_base_name)
    key_file = key_base_name
    if not key_file.endswith('.wif'):
        key_file += '.wif'
    if use_key_dir:
        key_file = os.path.join(key_dir, key_file)
    if not os.path.isfile(key_file):
        if key_base_name.endswith('.wif'):
            key_base_name = ''.join(key_base_name.split('.')[:-1])
        cmd = 'keygen %s' % key_base_name
        if use_key_dir:
            cmd += ' --key-dir %s' % key_dir
        if quiet is True:
            cmd += ' -q'
        sawtooth_cli_intercept(cmd)
    assert os.path.exists(key_file)

    with open(key_file, 'r') as f:
        key_str = f.read()
    signing_key = key_str.split('\n')[0]
    identifier = signing.generate_identifier(
        signing.generate_pubkey(signing_key))

    addr_file = '.'.join(key_file.split('.')[:-1]) + '.addr'
    if not os.path.exists(addr_file):
        with open(addr_file, 'w') as f:
            f.write('{}\n'.format(identifier))

    return key_file, signing_key, identifier
    def test_is_valid_pub_key(self):
        pubkey = signing.generate_pubkey("5KQ4iQQGgbQX9MmfiPUwwHBL1R"
                                         "GPa86NwFbqrWoodjuzruqFVDd")
        pub = signing.encode_pubkey(pubkey, "hex")
        minfo = {
            'Nonce': 100,
            'PublicKey': pub,
            'TransactionType': '/Transaction',
            'Dependencies': []
        }
        sig = signing.sign(
            signed_object.dict2cbor(minfo),
            "5KQ4iQQGgbQX9MmfiPUwwHBL1RGPa86NwFbqrWoodjuzruqFVDd")
        # Create valid transaction
        minfo["Signature"] = sig
        temp = Transaction(minfo)
        self.assertTrue(temp.is_valid("unused"))

        # Change transaction after it was signed
        minfo["Nonce"] = time.time()
        temp = Transaction(minfo)
        self.assertFalse(temp.is_valid("unused"))
    def submit_rates(self, effective_date, rates):
        """Submit a set of rates to the blockchain.

        Args:
            effective_date: The date the rates were published.  This may be
                provided as either a string in ISO-8601 format ("YYYY-MM-DD"),
                a datetime, or a date object.
            rate: A dictionary mapping maturity periods to rate values.  The
                following keys must be present:  Overnight, OneWeek, OneMonth,
                TwoMonth, ThreeMonth, SixMonth, OneYear
        """
        if self._libor_key_file is None:
            raise LIBORClientException(
                "Submitting LIBOR data requires a LIBOR signing key")

        # If we have a datetime or date object, get the ISO-8601 format string
        if isinstance(effective_date, datetime):
            effective_date = effective_date.date().isoformat()
        elif isinstance(effective_date, date):
            effective_date = effective_date.isoformat()

        signing_key = \
            signed_object.generate_signing_key(
                wifstr=open(self._libor_key_file, "r").read().strip())
        libor_public_key = signing.generate_pubkey(signing_key)
        # Add a signature to the actual update to simulate having a verified
        # source of information
        signed_update = LIBORObject(date=effective_date,
                                    rates=rates,
                                    libor_public_key=libor_public_key)
        signed_update.sign_object(signing_key)

        # Create the update and the submit the transaction
        update = {'UpdateType': 'CreateLIBOR'}
        update.update(signed_update.dump())

        return self.sendtxn(BondTransaction, BondTransaction.MessageType,
                            {'Updates': [update]})
Exemple #16
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["public_key"] = pub
    sig = signing.sign(_dict2cbor(transaction), key)
    transaction['Signature'] = sig

    txnid = hashlib.sha256(transaction['Signature']).hexdigest()[:16]
    message = {
        'Transaction': transaction,
        '__TYPE__': message_type,
        '__NONCE__': time.time(),
    }
    cbor_serialized_message = _dict2cbor(message)
    signature = signing.sign(cbor_serialized_message, key)
    message['__SIGNATURE__'] = signature
    return message, txnid
Exemple #17
0
 def __init__(self):
     self.SigningKey = signing.generate_privkey()
     self.Address = signing.generate_identifier(
         signing.generate_pubkey(self.SigningKey))
Exemple #18
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(dict2json(signup_data))

            # Create a fake report
            report_data = '{0}{1}'.format(
                originator_public_key_hash.upper(),
                signing.encode_pubkey(cls._poet_public_key, 'hex').upper())
            quote = {
                'report_body':
                hashlib.sha256(dict2json(report_data)).hexdigest()
            }

            # Fake our "proof" data.
            verification_report = {
                'id':
                base64.b64encode(
                    hashlib.sha256(
                        datetime.datetime.now().isoformat()).hexdigest()),
                'isvEnclaveQuoteStatus':
                'OK',
                'isvEnclaveQuoteBody':
                base64.b64encode(dict2json(quote)),
                'pseManifestStatus':
                'OK',
                'pseManifestHash':
                base64.b64encode(
                    hashlib.sha256(b'Do you believe in '
                                   'manifest destiny?').hexdigest()),
                'nonce':
                most_recent_wait_certificate_id
            }

            proof_data_dict = {
                'verification_report':
                dict2json(verification_report),
                'signature':
                signing.sign(dict2json(verification_report),
                             cls._report_private_key)
            }
            proof_data = dict2json(proof_data_dict)

            return \
                EnclaveSignupInfo(
                    poet_public_key=signup_data['poet_public_key'],
                    proof_data=proof_data,
                    anti_sybil_id=originator_public_key_hash,
                    sealed_signup_data=sealed_signup_data)
Exemple #19
0
class _PoetEnclaveSimulator(object):
    # A lock to protect threaded access
    _lock = threading.Lock()

    # The WIF-encoded enclave private seal key.  From it, we will create
    # private and public keys we can use for sealing and unsealing signup
    # info.
    __SEAL_PRIVATE_KEY_WIF = \
        '5KYsbooGBg51Gohakgq45enpXvCXmEBed1JivFfUZskmjLegHBG'

    _seal_private_key = \
        signing.decode_privkey(__SEAL_PRIVATE_KEY_WIF, 'wif')
    _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.decode_privkey(__REPORT_PRIVATE_KEY_WIF, 'wif')
    _report_public_key = signing.generate_pubkey(_report_private_key)

    # Minimum duration for PoET 1 simulator is 30 seconds
    __MINIMUM_DURATTION = 30.0

    # 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')).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(dict2json(signup_data))

            # Create a fake report
            report_data = '{0}{1}'.format(
                originator_public_key_hash.upper(),
                signing.encode_pubkey(cls._poet_public_key, 'hex').upper())
            quote = {
                'report_body':
                hashlib.sha256(dict2json(report_data)).hexdigest()
            }

            # Fake our "proof" data.
            verification_report = {
                'id':
                base64.b64encode(
                    hashlib.sha256(
                        datetime.datetime.now().isoformat()).hexdigest()),
                'isvEnclaveQuoteStatus':
                'OK',
                'isvEnclaveQuoteBody':
                base64.b64encode(dict2json(quote)),
                'pseManifestStatus':
                'OK',
                'pseManifestHash':
                base64.b64encode(
                    hashlib.sha256(b'Do you believe in '
                                   'manifest destiny?').hexdigest()),
                'nonce':
                most_recent_wait_certificate_id
            }

            proof_data_dict = {
                'verification_report':
                dict2json(verification_report),
                'signature':
                signing.sign(dict2json(verification_report),
                             cls._report_private_key)
            }
            proof_data = dict2json(proof_data_dict)

            return \
                EnclaveSignupInfo(
                    poet_public_key=signup_data['poet_public_key'],
                    proof_data=proof_data,
                    anti_sybil_id=originator_public_key_hash,
                    sealed_signup_data=sealed_signup_data)

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

        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 \
                SignupInfoError(
                    'Verification report is missing from proof data')

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

        if not signing.verify(verification_report, signature,
                              cls._report_public_key):
            raise \
                SignupInfoError('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 \
                SignupInfoError(
                    'Verification report does not contain a PSE manifest '
                    'status')
        if pse_manifest_status != 'OK':
            raise \
                SignupInfoError(
                    '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 \
                SignupInfoError(
                    'Verification report does not contain a PSE manifest '
                    'hash')

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

        if pse_manifest_hash != expected_pse_manifest_hash:
            raise \
                SignupInfoError(
                    '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 \
                SignupInfoError(
                    'Verification report does not contain an enclave quote '
                    'status')
        if enclave_quote_status != 'OK':
            raise \
                SignupInfoError(
                    '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 \
                SignupInfoError(
                    '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)).hexdigest()

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

        if report_body != expected_report_body:
            raise \
                SignupInfoError(
                    '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 \
                SignupInfoError(
                    '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 \
        #         SignupInfoError(
        #             '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, previous_certificate_id, local_mean):
        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 \
                    WaitTimerError(
                        '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('L', tag[-8:])[0]) / (2**64 - 1)

            # Now compute the duration
            duration = cls.__MINIMUM_DURATTION - local_mean * math.log(tagd)

            # Create and sign the wait timer
            wait_timer = \
                EnclaveWaitTimer(
                    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, 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 \
                    WaitCertificateError(
                        '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 active timer has expired
            # 3. 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 \
                    WaitCertificateError(
                        'Enclave active wait timer has not been initialized')

            is_not_genesis_block = \
                (cls._active_wait_timer.previous_certificate_id !=
                 NullIdentifier)

            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 \
                    WaitCertificateError(
                        '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 \
                    WaitCertificateError(
                        '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).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')

        return \
            signing.verify(
                certificate.serialize(),
                certificate.signature,
                decoded_poet_public_key)
    def test_libor_update(self):
        key = signed_object.generate_signing_key()
        store = ObjectStore()
        libor_key = TestCreateLIBORUpdate.libor_key
        libor_public_key = signing.generate_pubkey(libor_key)
        update = \
            CreateLIBORUpdate(
                update_type='CreateLIBOR',
                date='2016-05-24',
                rates={
                    'Overnight': 0.1,
                    'OneWeek': 0.1,
                    'OneMonth': 0.1,
                    'TwoMonth': 0.1,
                    'ThreeMonth': 0.1,
                    'SixMonth': 0.1,
                    'OneYear': 0.1
                },
                libor_public_key=libor_public_key)
        update.sign_update_object(libor_key)
        transaction = BondTransaction()
        transaction._updates = [update]
        transaction.sign_object(key)

        try:
            transaction.check_valid(store)
        except InvalidTransactionError as e:
            self.fail('This transaction should be valid\n error:' + str(e))

        try:
            store.lookup('libor:date', '2016-05-24')
            self.fail('LIBOR data for 2016-05-24 should not be in store')
        except KeyError:
            pass

        transaction.apply(store)

        self.assertIsNotNone(store.lookup('libor:date', '2016-05-24'))

        update = \
            CreateLIBORUpdate(
                update_type='CreateLIBOR',
                date='2016-05-25',
                rates={
                    'Overnight': '0.1',
                    'OneWeek': '-0.1',
                    'OneMonth': '0',
                    'TwoMonth': 0.1,
                    'ThreeMonth': -0.1,
                    'SixMonth': 0,
                    'OneYear': 1
                },
                libor_public_key=libor_public_key)
        update.sign_update_object(libor_key)

        transaction._updates = [update]
        transaction.sign_object(key)

        try:
            transaction.check_valid(store)
        except InvalidTransactionError as e:
            self.fail('This transaction should be valid\n error: ' + str(e))

        try:
            store.lookup('libor:date', '2016-05-25')
            self.fail('LIBOR data for 2016-05-25 should not be in store')
        except KeyError:
            pass

        transaction.apply(store)

        self.assertIsNotNone(store.lookup('libor:date', '2016-05-25'))
    def test_libor_update_invalid_date(self):
        key = signed_object.generate_signing_key()
        store = ObjectStore()
        libor_key = TestCreateLIBORUpdate.libor_key
        libor_public_key = signing.generate_pubkey(libor_key)
        update = \
            CreateLIBORUpdate(
                update_type='CreateLIBOR',
                date='2016-01-32',
                rates={
                    'Overnight': 0.1,
                    'OneWeek': 0.1,
                    'OneMonth': 0.1,
                    'TwoMonth': 0.1,
                    'ThreeMonth': 0.1,
                    'SixMonth': 0.1,
                    'OneYear': 0.1
                },
                libor_public_key=libor_public_key)
        update.sign_update_object(libor_key)
        transaction = BondTransaction()
        transaction._updates = [update]
        transaction.sign_object(key)

        try:
            transaction.check_valid(store)
            self.fail('This transaction should be invalid')
        except InvalidTransactionError:
            pass

        update = \
            CreateLIBORUpdate(
                update_type='CreateLIBOR',
                date='2016-12-32',
                rates={
                    'Overnight': 0.1,
                    'OneWeek': 0.1,
                    'OneMonth': 0.1,
                    'TwoMonth': 0.1,
                    'ThreeMonth': 0.1,
                    'SixMonth': 0.1,
                    'OneYear': 0.1
                },
                signature='HG/+Byml9CU13jdMD9TvOtlNlLvAO5jzBGUqoJGSng2ksojoh8'
                          'mUxYKJ4rTE5pZ4Q1S+lHRLuQLVgprhQkY25eQ=')

        transaction._updates = [update]
        transaction.sign_object(key)

        try:
            transaction.check_valid(store)
            self.fail('This transaction should be invalid')
        except InvalidTransactionError:
            pass

        update = \
            CreateLIBORUpdate(
                update_type='CreateLIBOR',
                date='2015-02-29',
                rates={
                    'Overnight': 0.1,
                    'OneWeek': 0.1,
                    'OneMonth': 0.1,
                    'TwoMonth': 0.1,
                    'ThreeMonth': 0.1,
                    'SixMonth': 0.1,
                    'OneYear': 0.1
                },
                libor_public_key=libor_public_key)
        update.sign_update_object(libor_key)

        transaction._updates = [update]
        transaction.sign_object(key)

        try:
            transaction.check_valid(store)
            self.fail('This transaction should be invalid')
        except InvalidTransactionError:
            pass

        update = \
            CreateLIBORUpdate(
                update_type='CreateLIBOR',
                date='2016-02-30',
                rates={
                    'Overnight': 0.1,
                    'OneWeek': 0.1,
                    'OneMonth': 0.1,
                    'TwoMonth': 0.1,
                    'ThreeMonth': 0.1,
                    'SixMonth': 0.1,
                    'OneYear': 0.1
                },
                libor_public_key=libor_public_key)
        update.sign_update_object(libor_key)

        transaction._updates = [update]
        transaction.sign_object(key)

        try:
            transaction.check_valid(store)
            self.fail('This transaction should be invalid')
        except InvalidTransactionError:
            pass

        update = \
            CreateLIBORUpdate(
                update_type='CreateLIBOR',
                date='2016-13-30',
                rates={
                    'Overnight': 0.1,
                    'OneWeek': 0.1,
                    'OneMonth': 0.1,
                    'TwoMonth': 0.1,
                    'ThreeMonth': 0.1,
                    'SixMonth': 0.1,
                    'OneYear': 0.1
                },
                signature='G4JyMWYLEWwwSQlOLHWDclAKB2kXersC/cuc3VbzyRTJ92Nj'
                          'e2nGPgSIsQzQ4uR94r9pYi1S6E4z7zQrdwCCKlg=')

        transaction._updates = [update]
        transaction.sign_object(key)

        try:
            transaction.check_valid(store)
            self.fail('This transaction should be invalid')
        except InvalidTransactionError:
            pass

        update = \
            CreateLIBORUpdate(
                update_type='CreateLIBOR',
                date='2016-00-15',
                rates={
                    'Overnight': 0.1,
                    'OneWeek': 0.1,
                    'OneMonth': 0.1,
                    'TwoMonth': 0.1,
                    'ThreeMonth': 0.1,
                    'SixMonth': 0.1,
                    'OneYear': 0.1
                },
                libor_public_key=libor_public_key)
        update.sign_update_object(libor_key)

        transaction._updates = [update]
        transaction.sign_object(key)

        try:
            transaction.check_valid(store)
            self.fail('This transaction should be invalid')
        except InvalidTransactionError:
            pass

        update = \
            CreateLIBORUpdate(
                update_type='CreateLIBOR',
                date='2016-01-00',
                rates={
                    'Overnight': 0.1,
                    'OneWeek': 0.1,
                    'OneMonth': 0.1,
                    'TwoMonth': 0.1,
                    'ThreeMonth': 0.1,
                    'SixMonth': 0.1,
                    'OneYear': 0.1
                },
                libor_public_key=libor_public_key)
        update.sign_update_object(libor_key)

        transaction._updates = [update]
        transaction.sign_object(key)

        try:
            transaction.check_valid(store)
            self.fail('This transaction should be invalid')
        except InvalidTransactionError:
            pass
    def test_libor_update_invalid_date_format(self):
        key = signed_object.generate_signing_key()
        store = ObjectStore()
        libor_key = TestCreateLIBORUpdate.libor_key
        libor_public_key = signing.generate_pubkey(libor_key)
        update = \
            CreateLIBORUpdate(
                update_type='CreateLIBOR',
                date='05/24/2016',
                rates={
                    'Overnight': 0.1,
                    'OneWeek': 0.1,
                    'OneMonth': 0.1,
                    'TwoMonth': 0.1,
                    'ThreeMonth': 0.1,
                    'SixMonth': 0.1,
                    'OneYear': 0.1
                },
                libor_public_key=libor_public_key)
        update.sign_update_object(libor_key)

        transaction = BondTransaction()
        transaction._updates = [update]
        transaction.sign_object(key)

        try:
            transaction.check_valid(store)
            self.fail('This transaction should be invalid')
        except InvalidTransactionError:
            pass

        update = \
            CreateLIBORUpdate(
                update_type='CreateLIBOR',
                date='05-24-2016',
                rates={
                    'Overnight': 0.1,
                    'OneWeek': 0.1,
                    'OneMonth': 0.1,
                    'TwoMonth': 0.1,
                    'ThreeMonth': 0.1,
                    'SixMonth': 0.1,
                    'OneYear': 0.1
                },
                signature='G7OL7YDOVHzOevEaGgg1PvnpxiRhws7vdut3F1RUdMXDNH6gH'
                          'sY9nk/Zt+WwQYo/4QhZOY6CO0Inv5HUi8MyrPo=')

        transaction._updates = [update]
        transaction.sign_object(key)

        try:
            transaction.check_valid(store)
            self.fail('This transaction should be invalid')
        except InvalidTransactionError:
            pass

        update = \
            CreateLIBORUpdate(
                update_type='CreateLIBOR',
                date='May 24, 2016',
                rates={
                    'OneWeek': 0.1,
                    'Overnight': 0.1,
                    'OneMonth': 0.1,
                    'TwoMonth': 0.1,
                    'ThreeMonth': 0.1,
                    'SixMonth': 0.1,
                    'OneYear': 0.1
                },
                libor_public_key=libor_public_key)
        update.sign_update_object(libor_key)

        transaction._updates = [update]
        transaction.sign_object(key)

        try:
            transaction.check_valid(store)
            self.fail('This transaction should be invalid')
        except InvalidTransactionError:
            pass

        update = \
            CreateLIBORUpdate(
                update_type='CreateLIBOR',
                date='24-May-2016',
                rates={
                    'OneWeek': 0.1,
                    'Overnight': 0.1,
                    'OneMonth': 0.1,
                    'TwoMonth': 0.1,
                    'ThreeMonth': 0.1,
                    'SixMonth': 0.1,
                    'OneYear': 0.1
                },
                libor_public_key=libor_public_key)
        update.sign_update_object(libor_key)

        transaction._updates = [update]
        transaction.sign_object(key)

        try:
            transaction.check_valid(store)
            self.fail('This transaction should be invalid')
        except InvalidTransactionError:
            pass

        update = \
            CreateLIBORUpdate(
                update_type='CreateLIBOR',
                date='May 24 2016',
                rates={
                    'Overnight': 0.1,
                    'OneWeek': 0.1,
                    'OneMonth': 0.1,
                    'TwoMonth': 0.1,
                    'ThreeMonth': 0.1,
                    'SixMonth': 0.1,
                    'OneYear': 0.1
                },
                libor_public_key=libor_public_key)
        update.sign_update_object(libor_key)

        transaction._updates = [update]
        transaction.sign_object(key)

        try:
            transaction.check_valid(store)
            self.fail('This transaction should be invalid')
        except InvalidTransactionError:
            pass

        update = \
            CreateLIBORUpdate(
                update_type='CreateLIBOR',
                date='24 May 2016',
                rates={
                    'Overnight': 0.1,
                    'OneWeek': 0.1,
                    'OneMonth': 0.1,
                    'TwoMonth': 0.1,
                    'ThreeMonth': 0.1,
                    'SixMonth': 0.1,
                    'OneYear': 0.1
                },
                libor_public_key=libor_public_key)
        update.sign_update_object(libor_key)

        transaction._updates = [update]
        transaction.sign_object(key)

        try:
            transaction.check_valid(store)
            self.fail('This transaction should be invalid')
        except InvalidTransactionError:
            pass

        update = \
            CreateLIBORUpdate(
                update_type='CreateLIBOR',
                date='',
                rates={
                    'Overnight': 0.1,
                    'OneWeek': 0.1,
                    'OneMonth': 0.1,
                    'TwoMonth': 0.1,
                    'ThreeMonth': 0.1,
                    'SixMonth': 0.1,
                    'OneYear': 0.1,
                },
                libor_public_key=libor_public_key)
        update.sign_update_object(libor_key)

        transaction._updates = [update]
        transaction.sign_object(key)

        try:
            transaction.check_valid(store)
            self.fail('This transaction should be invalid')
        except InvalidTransactionError:
            pass
Exemple #23
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 >> sys.stderr, 'file exists: {}'.format(filename)
        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:
Exemple #24
0
def get_address_from_private_key_wif(key):
    return signing.generate_identifier(
        signing.generate_pubkey(signing.decode_privkey(key, 'wif')))
Exemple #25
0
def create_random_public_key():
    return signing.generate_pubkey(create_random_private_key())