def multiply_privkeys(p1, p2, n): f1, f2 = get_privkey_format(p1), get_privkey_format(p2) p = decode_privkey(p1, f1) while n > 0: p = (p + decode_privkey(p2, f2)) % N n -= 1 return encode_privkey(p, f1)
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(pybitcointools.base64.b32decode(sealed_signup_data)) with cls._lock: cls._poet_public_key = \ pybitcointools.decode_pubkey( signup_data.get('poet_public_key'), 'hex') cls._poet_private_key = \ pybitcointools.decode_privkey( signup_data.get('poet_public_key'), 'hex') cls._active_wait_timer = None return signup_data.get('poet_public_key')
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 = pybitcointools.decode_privkey(keystring, 'wif') elif keyfile: LOGGER.debug("set signing key from file %s", keyfile) try: self._signing_key = pybitcointools.decode_privkey( open(keyfile, "r").read().strip(), 'wif') except IOError as ex: raise ClientException("Failed to load key file: {}".format( str(ex))) if self._signing_key is not None: self._identifier = pybitcointools.pubtoaddr( pybitcointools.privtopub(self._signing_key))
def test_pbt_match(self): """ Tests matching results between pybitcointools and native ECDSA key recovery """ # This key has a small public key value which tests padding wifstr = '5JtMb6tmM9vT6QHyM7RR8pjMViqccukgMFNCPvG5xhLVf6CMoGx' priv = pbt.decode_privkey(wifstr, 'wif') msg = 'foo' sig = pbt.ecdsa_sign(msg, priv) native_recovered = gossip.signed_object.get_verifying_key(msg, sig) py_recovered = pbt.ecdsa_recover(msg, sig) self.assertEquals(native_recovered, py_recovered)
def test_register_permissioned_validator_valid(self): signing_key = signed_object.generate_signing_key() try: priv_key1 = pybitcointools.decode_privkey( open('./tests/unit/keys/pv1.wif', "r") .read().strip(), 'wif') priv_key2 = pybitcointools.decode_privkey( open('./tests/unit/keys/pv2.wif', "r") .read().strip(), 'wif') except IOError as ex: raise Exception('IOError: {}'.format(str(ex))) pub_key1 = pybitcointools.encode_pubkey( pybitcointools.privtopub(priv_key1), 'hex') pub_key2 = pybitcointools.encode_pubkey( pybitcointools.privtopub(priv_key2), 'hex') permissioned_public_keys = [pub_key1, pub_key2] addr1 = signed_object.generate_identifier(priv_key1) addr2 = signed_object.generate_identifier(priv_key2) permissioned_addrs = [addr1, addr2] update = { 'whitelist_name': "hyperledger.sawtooth-core.genesis-whitelist", 'verb': 'reg', 'permissioned_public_keys': permissioned_public_keys, 'permissioned_addrs': permissioned_addrs } minfo = {'Update': update} transaction = PermissionedValidatorRegistryTransaction(minfo) transaction.sign_object(signing_key) store = ObjectStore() try: transaction.check_valid(store) transaction.apply(store) except InvalidTransactionError as e: self.fail('Failed valid transaction: {}'.format(e))
def test_pbt_match(self): """ Tests matching results between pybitcointools and native ECDSA key recovery """ # This key has a small public key value which tests padding wifstr = '5JtMb6tmM9vT6QHyM7RR8pjMViqccukgMFNCPvG5xhLVf6CMoGx' priv = pbt.decode_privkey(wifstr, 'wif') msg = 'foo' sig = pbt.ecdsa_sign(msg, priv) native_recovered = gossip.signed_object.get_verifying_key(msg, sig) py_recovered = pbt.ecdsa_recover(msg, sig) self.assertEquals(native_recovered, py_recovered)
def generate_signing_key(wifstr=None): """Returns a decoded signing key associated with wifstr or generates a random signing key. Args: wifstr (str): A private key in wif format. Returns: str: a signing key. """ if wifstr: return pybitcointools.decode_privkey(wifstr, 'wif') return pybitcointools.random_key()
def generate_signing_key(wifstr=None): """Returns a decoded signing key associated with wifstr or generates a random signing key. Args: wifstr (str): A private key in wif format. Returns: str: a signing key. """ if wifstr: return pybitcointools.decode_privkey(wifstr, 'wif') return pybitcointools.random_key()
def test_register_permissioned_validator_valid(self): signing_key = signed_object.generate_signing_key() try: priv_key1 = pybitcointools.decode_privkey( open('./tests/unit/keys/pv1.wif', "r").read().strip(), 'wif') priv_key2 = pybitcointools.decode_privkey( open('./tests/unit/keys/pv2.wif', "r").read().strip(), 'wif') except IOError as ex: raise Exception('IOError: {}'.format(str(ex))) pub_key1 = pybitcointools.encode_pubkey( pybitcointools.privtopub(priv_key1), 'hex') pub_key2 = pybitcointools.encode_pubkey( pybitcointools.privtopub(priv_key2), 'hex') permissioned_public_keys = [pub_key1, pub_key2] addr1 = signed_object.generate_identifier(priv_key1) addr2 = signed_object.generate_identifier(priv_key2) permissioned_addrs = [addr1, addr2] update = { 'whitelist_name': "hyperledger.sawtooth-core.genesis-whitelist", 'verb': 'reg', 'permissioned_public_keys': permissioned_public_keys, 'permissioned_addrs': permissioned_addrs } minfo = {'Update': update} transaction = PermissionedValidatorRegistryTransaction(minfo) transaction.sign_object(signing_key) store = ObjectStore() try: transaction.check_valid(store) transaction.apply(store) except InvalidTransactionError as e: self.fail('Failed valid transaction: {}'.format(e))
def _decode_privkey(encoded_privkey, encoding_format='wif'): """ Args: encoded_privkey: an encoded private key string encoding_format: string indicating format such as 'wif' Returns: private key object useable with this module """ if encoding_format == 'wif': # base58 to int priv = pybitcointools.decode_privkey(encoded_privkey, encoding_format) # int to hex string priv = pybitcointools.encode_privkey(priv, 'hex') # hex string to bytes try: # check python 3 priv = priv.to_bytes(32, byteorder='big') except AttributeError: priv = binascii.unhexlify(priv) else: raise TypeError("unsupported private key format") return secp256k1.PrivateKey(priv)
class _PoetEnclaveSimulator(object): # 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 = \ pybitcointools.decode_privkey(__SEAL_PRIVATE_KEY_WIF, 'wif') _seal_public_key = pybitcointools.privtopub(_seal_private_key) # Minimum duration for PoET 1 simulator is 30 seconds __MINIMUM_DURATTION = 30.0 # 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 create_signup_info(cls, originator_public_key): # First we need to create a public/private key pair for the PoET # enclave to use. cls._poet_private_key = pybitcointools.random_key() cls._poet_public_key = pybitcointools.privtopub(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': pybitcointools.encode_pubkey(cls._poet_public_key, 'hex'), 'poet_private_key': pybitcointools.encode_privkey(cls._poet_private_key, 'hex') } sealed_signup_data = \ pybitcointools.base64.b32encode(dict2json(signup_data)) # Create a fake report report_data = { 'originator_public_key_hash': pybitcointools.sha256( pybitcointools.encode_pubkey(originator_public_key, 'hex')), 'poet_public_key': pybitcointools.encode_pubkey(cls._poet_public_key, 'hex') } report = {'report_data': pybitcointools.sha256(dict2json(report_data))} report = pybitcointools.base64.b32encode(dict2json(report)) # Fake our "proof" data. proof_data = { 'attestation_evidence_payload': pybitcointools.sha256(report), 'attestation_verification_report': pybitcointools.sha256('Shave and a haircut...Two bits!') } return \ EnclaveSignupInfo( anti_sybil_id='Sally Field', poet_public_key=signup_data['poet_public_key'], proof_data=proof_data, sealed_signup_data=sealed_signup_data) @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(pybitcointools.base64.b32decode(sealed_signup_data)) cls._poet_public_key = \ pybitcointools.decode_pubkey( signup_data.get('poet_public_key'), 'hex') cls._poet_private_key = \ pybitcointools.decode_privkey( signup_data.get('poet_public_key'), 'hex') cls._active_wait_timer = None return signup_data.get('poet_public_key') @classmethod def verify_signup_info(cls, serialized_signup_info): # For now, we are going to always indicate that the signup information # is valid return True @classmethod def create_wait_timer(cls, previous_certificate_id, local_mean): # 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 = \ pybitcointools.base64.b64decode( pybitcointools.ecdsa_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 = \ pybitcointools.ecdsa_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): return \ EnclaveWaitTimer.wait_timer_from_serialized( serialized_timer=serialized_timer, signature=signature) @classmethod def create_wait_certificate(cls, timer, block_digest): # TO DO - implement PoET 1 create certificate logic # 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_timer( timer=timer, block_digest=block_digest) wait_certificate.signature = \ pybitcointools.ecdsa_sign( wait_certificate.serialize(), cls._poet_private_key) 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, encoded_poet_public_key): # poet_public_key = \ # pybitcointools.decode_pubkey(encoded_poet_public_key, 'hex') # # TO DO - implement PoET 1 create certificate logic # return \ # pybitcointools.ecdsa_verify( # certificate.serialize(), # certificate.signature, # poet_public_key) return True
def decode_privkey(privkey, encoding_format='wif'): return pybitcointools.decode_privkey(privkey, encoding_format)
import pybitcointools # Generate a random private key valid_private_key = False while not valid_private_key: private_key = pybitcointools.random_key() decoded_private_key = pybitcointools.decode_privkey(private_key, 'hex') valid_private_key = 0 < decoded_private_key < pybitcointools.N print "Private Key (hex) is:", private_key print "Private Key (decimal) is:", decoded_private_key # Convert private key to WIF format wif_encoded_private_key = pybitcointools.encode_privkey( decoded_private_key, 'wif') print "Private Key (WIF) is:", wif_encoded_private_key # Add suffix "01" to indicate a compressed private key compressed_private_key = private_key + '01' print "Private Key Compressed (hex) is:", compressed_private_key # Generate a WIF format from the compressed private key (WIF-)
def get_address_from_private_key_wif(key): return pybitcointools.privtoaddr(pybitcointools.decode_privkey(key, 'wif'))
def get_address_from_private_key_wif(key): return pybitcointools.privtoaddr(pybitcointools.decode_privkey(key, 'wif'))
import pybitcointools import sys if __name__ == "__main__": if len(sys.argv) >= 2: priv_key = sys.argv[ 1] #"LmB72UZvRmJ5cUPZWpxqYWW5KkCgASa53GZQNhWNTPzJ9J1R4T8x" priv_data = pybitcointools.decode_privkey(priv_key) print(pybitcointools.encode_privkey(priv_data, "wif_compressed")) print(pybitcointools.privtoaddr(priv_key)) else: print("Usage: %s [private_key]" % sys.argv[0])
# - (see https://github.com/vbuterin/pybitcointools/issues/153 for the reason of the fork; there are conflicts with "import bitcoin") # # my pip freeze: # bitcoin==1.1.42 # pybitcointools==1.1.42 (installed as above) # python-bitcoinlib==0.10.1 # from __future__ import print_function import pybitcointools # Generate a random private key valid_private_key = False while not valid_private_key: private_key = pybitcointools.random_key() decoded_private_key = pybitcointools.decode_privkey(private_key, 'hex') valid_private_key = 0 < decoded_private_key < pybitcointools.N print("Private Key (hex) is: ", private_key) print("Private Key (decimal) is: ", decoded_private_key) # Convert private key to WIF format wif_encoded_private_key = pybitcointools.encode_privkey( decoded_private_key, 'wif') print("Private Key (WIF) is: ", wif_encoded_private_key) # Add suffix "01" to indicate a compressed private key compressed_private_key = private_key + '01' print("Private Key Compressed (hex) is: ", compressed_private_key) # Generate a WIF format from the compressed private key (WIF-compressed)
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 = \ pybitcointools.decode_privkey(__SEAL_PRIVATE_KEY_WIF, 'wif') _seal_public_key = pybitcointools.privtopub(_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 = \ pybitcointools.decode_privkey(__REPORT_PRIVATE_KEY_WIF, 'wif') _report_public_key = pybitcointools.privtopub(_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 = \ pybitcointools.sha256(kwargs.get('NodeName', 'validator')) @classmethod def create_signup_info(cls, originator_public_key, validator_network_basename, 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 = pybitcointools.random_key() cls._poet_public_key = \ pybitcointools.privtopub(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': pybitcointools.encode_pubkey(cls._poet_public_key, 'hex'), 'poet_private_key': pybitcointools.encode_privkey( cls._poet_private_key, 'hex') } sealed_signup_data = \ pybitcointools.base64.b32encode(dict2json(signup_data)) # Create a fake report report_data = { 'originator_public_key_hash': pybitcointools.sha256( pybitcointools.encode_pubkey( originator_public_key, 'hex')), 'poet_public_key': pybitcointools.encode_pubkey(cls._poet_public_key, 'hex') } report = { 'report_data': pybitcointools.sha256(dict2json(report_data)), 'validator_network_basename': validator_network_basename } # Fake our "proof" data. attestation_evidence_payload = { 'enclave_quote': pybitcointools.base64.b64encode(dict2json(report)), 'pse_manifest': pybitcointools.base64.b64encode( pybitcointools.sha256( 'manifest destiny')), 'nonce': most_recent_wait_certificate_id } attestation_verification_report = { 'attestation_evidence_payload': attestation_evidence_payload, 'anti_sybil_id': cls._anti_sybil_id } proof_data = { 'attestation_verification_report': attestation_verification_report, 'signature': pybitcointools.ecdsa_sign( dict2json(attestation_verification_report), cls._report_private_key) } return \ EnclaveSignupInfo( poet_public_key=signup_data['poet_public_key'], proof_data=proof_data, 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(pybitcointools.base64.b32decode(sealed_signup_data)) with cls._lock: cls._poet_public_key = \ pybitcointools.decode_pubkey( signup_data.get('poet_public_key'), 'hex') cls._poet_private_key = \ pybitcointools.decode_privkey( signup_data.get('poet_public_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, validator_network_basename, most_recent_wait_certificate_id): # Verify the attestation verification report signature attestation_verification_report = \ signup_info.proof_data.get('attestation_verification_report') if attestation_verification_report is None: raise \ SignupInfoError( 'Attestation verification report is missing from proof ' 'data') if not pybitcointools.ecdsa_verify( dict2json(attestation_verification_report), signup_info.proof_data.get('signature'), cls._report_public_key): raise \ SignupInfoError( 'Attestation verification report signature is invalid') # Verify the presence of the anti-Sybil ID anti_sybil_id = attestation_verification_report.get('anti_sybil_id') if anti_sybil_id is None: raise \ SignupInfoError( 'Attestation verification report does not contain an ' 'anti-Sybil ID') # Verify that the report data field in the report contains the SHA256 # digest of the originator's public key SHA 256 digest and the PoET # public key. attestation_evidence_payload = \ attestation_verification_report.get( 'attestation_evidence_payload') if attestation_evidence_payload is None: raise \ SignupInfoError( 'Attestation verification report does not contain ' 'attestation evidence payload') enclave_quote = attestation_evidence_payload.get('enclave_quote') if enclave_quote is None: raise \ SignupInfoError( 'Attestation evidence payload does not contain an ' 'enclave quote') report = json2dict(pybitcointools.base64.b64decode(enclave_quote)) report_data = report.get('report_data') if report_data is None: raise \ SignupInfoError('Enclave quote does not contain report data') target_report_data = { 'originator_public_key_hash': pybitcointools.sha256( pybitcointools.encode_pubkey( originator_public_key, 'hex')), 'poet_public_key': signup_info.poet_public_key } target_report_data_digest = \ pybitcointools.sha256(dict2json(target_report_data)) if report_data != target_report_data_digest: raise SignupInfoError('Enclave quote report data is invalid') # Verify that the validator base name in the enclave quote report # matches the provided validator network basename validator_net_basename = report.get('validator_network_basename') if validator_net_basename is None: raise \ SignupInfoError( 'Enclave quote report does not have a validator network ' 'basename') if validator_net_basename != validator_network_basename: raise \ SignupInfoError( 'Enclave quote report validator network basename [{0}] ' 'does not match [{1}]'.format( validator_net_basename, validator_network_basename)) # NOTE - this check is currently not performed as a transaction # does not have a good way to obtaining the most recent # wait certificate ID. # # Verify that the wait certificate ID in the attestation evidence # payload matches the provided wait certificate ID. The wait # certificate ID is stored in the AEP nonce field. # nonce = attestation_evidence_payload.get('nonce') # if nonce is None: # raise \ # SignupInfoError( # 'Attestation evidence payload does not have a nonce') # # 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 = \ pybitcointools.base64.b64decode( pybitcointools.ecdsa_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 = \ pybitcointools.ecdsa_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 pybitcointools.ecdsa_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 we 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 if cls._active_wait_timer is None: raise \ WaitCertificateError( 'Enclave active wait timer has not been initialized') # HACK ALERT!! HACK ALERT!! HACK ALERT!! HACK ALERT!! # # Today, without the genesis utility we cannot make these checks. # Once we have the genesis utility, this code needs to change to # Depend upon the timer not being expired or timed out. The # Original specification requires this check. # # HACK ALERT!! HACK ALERT!! HACK ALERT!! HACK ALERT!! # # if not cls._active_wait_timer.has_expired(): # raise \ # WaitCertificateError( # 'Cannot create wait certificate because timer has ' # 'not expired') # if wait_timer.has_timed_out(): # 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 = pybitcointools.sha256(random_string) # 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 = \ pybitcointools.ecdsa_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, encoded_poet_public_key): # poet_public_key = \ # pybitcointools.decode_pubkey(encoded_poet_public_key, 'hex') # # return \ # pybitcointools.ecdsa_verify( # certificate.serialize(), # certificate.signature, # poet_public_key) return True