def sign_token(claim, signing_private_key, subject, issuer=None, signing_algorithm="ES256K"): if signing_algorithm != 'ES256K': raise ValueError("Signing algorithm not supported") private_key_object = ECPrivateKey(signing_private_key) public_key_hex = private_key_object.public_key().to_hex() if not issuer: issuer = { "publicKey": public_key_hex } current_time = datetime.datetime.now() payload = { "claim": claim, "subject": subject, "issuer": issuer, "issuedAt": current_time.isoformat(), "expiresAt": current_time.replace(current_time.year + 1).isoformat() } token_signer = TokenSigner() token = token_signer.sign(payload, private_key_object.to_pem()) return token
def sign_token(claim, signing_private_key, subject, issuer=None, signing_algorithm="ES256K"): if signing_algorithm != 'ES256K': raise ValueError("Signing algorithm not supported") private_key_object = ECPrivateKey(signing_private_key) public_key_hex = private_key_object.public_key().to_hex() if not issuer: issuer = {"publicKey": public_key_hex} current_time = datetime.datetime.now() payload = { "claim": claim, "subject": subject, "issuer": issuer, "issuedAt": current_time.isoformat(), "expiresAt": current_time.replace(current_time.year + 1).isoformat() } token_signer = TokenSigner() token = token_signer.sign(payload, private_key_object.to_pem()) return token
def sign_token_records(profile_components, parent_private_key, signing_algorithm="ES256K"): """ Function for iterating through a list of profile components and signing separate individual profile tokens. """ if signing_algorithm != "ES256K": raise ValueError("Signing algorithm not supported") token_records = [] for profile_component in profile_components: private_key = ECPrivateKey(parent_private_key) public_key = private_key.public_key() subject = {"publicKey": public_key.to_hex()} token = sign_token(profile_component, private_key.to_hex(), subject, signing_algorithm=signing_algorithm) token_record = wrap_token(token) token_record["parentPublicKey"] = public_key.to_hex() token_records.append(token_record) return token_records
class ECPrivateKeyCompressedTest(unittest.TestCase): ref = _compressed_info def setUp(self): self.private_key = ECPrivateKey( self.ref['hex_private_key'], compressed=True) def tearDown(self): pass def test_random_private_key(self): private_key = ECPrivateKey() self.assertTrue(isinstance(private_key, ECPrivateKey)) def test_hex_private_key(self): self.assertEqual(self.private_key.to_hex(), self.ref['hex_private_key']) def test_wif_private_key(self): self.assertEqual(self.private_key.to_wif(), self.ref['wif_private_key']) def test_pem_private_key(self): self.assertEqual(self.private_key.to_pem(), self.ref['pem_private_key']) def test_der_private_key(self): self.assertEqual(self.private_key.to_der(), self.ref['der_private_key']) def test_to_public_key_conversion(self): public_key = self.private_key.public_key() self.assertEqual(public_key.to_hex(), self.ref['hex_public_key']) self.assertEqual(public_key.address(), self.ref['address'])
class TokeningTests(unittest.TestCase): def setUp(self): self.master_private_key = ECPrivateKey(compressed=True) self.profile_components = [{ "name": "Naval Ravikant" }, { "birthDate": "1980-01-01" }] def tearDown(self): pass def test_token_verification_and_recovery(self): # tokenize the profile profile_token_records = sign_token_records( self.profile_components, self.master_private_key.to_hex()) #print json.dumps(profile_token_records, indent=2) self.assertTrue(isinstance(profile_token_records, list)) # verify the token records for token_record in profile_token_records: public_key = self.master_private_key.public_key().to_hex() decoded_token = verify_token_record(token_record, public_key) self.assertTrue(isinstance(decoded_token, dict)) # recover the profile profile = get_profile_from_tokens( profile_token_records, self.master_private_key.public_key().to_hex()) # print json.dumps(profile, indent=2) self.assertTrue(isinstance(profile, object)) self.assertEqual(profile, reference_profiles["naval"]) def test_token_verification_with_address(self): profile_token_records = sign_token_records( self.profile_components, self.master_private_key.to_hex()) self.assertTrue(isinstance(profile_token_records, list)) for token_record in profile_token_records: address = self.master_private_key.public_key().address() decoded_token = verify_token_record(token_record, address) self.assertTrue(isinstance(decoded_token, dict)) def test_token_verification_with_public_key(self): public_key = "0273be63a7091923467111e09bbd54492a65b709c7a02416860bd55d7c496bf009" token_records = [] with open('test_data/sample_token.json', 'r') as f: data = f.read() token_records = json.loads(data) for token_record in token_records: token_verified = verify_token_record(token_record, public_key) self.assertTrue(token_verified) def test_token_file_verification(self): token_records = reference_profiles["naval_token_file"] public_key = "038354d097be9004f63a6409e2c7a05467b1950120b4c5f840f99832dad743ac1e" profile = get_profile_from_tokens(token_records, public_key)
class TokeningTests(unittest.TestCase): def setUp(self): self.master_private_key = ECPrivateKey(compressed=True) self.profile_components = [ {"name": "Naval Ravikant"}, {"birthDate": "1980-01-01"} ] def tearDown(self): pass def test_token_verification_and_recovery(self): # tokenize the profile profile_token_records = sign_token_records( self.profile_components, self.master_private_key.to_hex()) #print json.dumps(profile_token_records, indent=2) self.assertTrue(isinstance(profile_token_records, list)) # verify the token records for token_record in profile_token_records: public_key = self.master_private_key.public_key().to_hex() decoded_token = verify_token_record(token_record, public_key) self.assertTrue(isinstance(decoded_token, dict)) # recover the profile profile = get_profile_from_tokens( profile_token_records, self.master_private_key.public_key().to_hex()) # print json.dumps(profile, indent=2) self.assertTrue(isinstance(profile, object)) self.assertEqual(profile, reference_profiles["naval"]) def test_token_verification_with_address(self): profile_token_records = sign_token_records( self.profile_components, self.master_private_key.to_hex()) self.assertTrue(isinstance(profile_token_records, list)) for token_record in profile_token_records: address = self.master_private_key.public_key().address() decoded_token = verify_token_record(token_record, address) self.assertTrue(isinstance(decoded_token, dict)) def test_token_verification_with_public_key(self): public_key = "0273be63a7091923467111e09bbd54492a65b709c7a02416860bd55d7c496bf009" token_records = [] with open('test_data/sample_token.json', 'r') as f: data = f.read() token_records = json.loads(data) for token_record in token_records: token_verified = verify_token_record(token_record, public_key) self.assertTrue(token_verified) def test_token_file_verification(self): token_records = reference_profiles["naval_token_file"] public_key = "038354d097be9004f63a6409e2c7a05467b1950120b4c5f840f99832dad743ac1e" profile = get_profile_from_tokens(token_records, public_key)
class ECPrivateKeyTest(unittest.TestCase): reference = _reference_info def setUp(self): self.private_key = ECPrivateKey(self.reference['hex_private_key'], compressed=False) def tearDown(self): pass def test_random_private_key(self): private_key = ECPrivateKey() self.assertTrue(isinstance(private_key, ECPrivateKey)) def test_private_key_from_wif(self): self.private_key_from_wif = ECPrivateKey( self.reference['wif_private_key'], compressed=False) self.assertEqual( self.private_key.to_hex(), self.private_key_from_wif.to_hex()) def test_hex_private_key(self): self.assertEqual( self.private_key.to_hex(), self.reference['hex_private_key']) def test_wif_private_key(self): self.assertEqual( self.private_key.to_wif(), self.reference['wif_private_key']) def test_pem_private_key(self): self.assertEqual( self.private_key.to_pem(), self.reference['pem_private_key']) def test_der_private_key(self): self.assertEqual( self.private_key.to_der(), self.reference['der_private_key'])
class ECPrivateKeyTest(unittest.TestCase): reference = _reference_info def setUp(self): self.private_key = ECPrivateKey(self.reference['hex_private_key'], compressed=False) def tearDown(self): pass def test_random_private_key(self): private_key = ECPrivateKey() self.assertTrue(isinstance(private_key, ECPrivateKey)) def test_private_key_from_wif(self): self.private_key_from_wif = ECPrivateKey( self.reference['wif_private_key'], compressed=False) self.assertEqual(self.private_key.to_hex(), self.private_key_from_wif.to_hex()) def test_hex_private_key(self): self.assertEqual(self.private_key.to_hex(), self.reference['hex_private_key']) def test_wif_private_key(self): self.assertEqual(self.private_key.to_wif(), self.reference['wif_private_key']) def test_pem_private_key(self): self.assertEqual(self.private_key.to_pem(), self.reference['pem_private_key']) def test_der_private_key(self): self.assertEqual(self.private_key.to_der(), self.reference['der_private_key'])
def make_wallet(password, config_path=CONFIG_PATH, payment_privkey_info=None, owner_privkey_info=None, data_privkey_info=None, test_legacy=False, encrypt=True): """ Make a new, encrypted wallet structure. The owner and payment keys will be 2-of-3 multisig key bundles. The data keypair will be a single-key bundle. Return the new wallet on success. Return {'error': ...} on failure """ if test_legacy and not BLOCKSTACK_TEST: raise Exception("Not in testing but tried to make a legacy wallet") # default to 2-of-3 multisig key info if data isn't given payment_privkey_info = virtualchain.make_multisig_wallet( 2, 3 ) if payment_privkey_info is None and not test_legacy else payment_privkey_info owner_privkey_info = virtualchain.make_multisig_wallet( 2, 3 ) if owner_privkey_info is None and not test_legacy else owner_privkey_info data_privkey_info = ECPrivateKey().to_wif( ) if data_privkey_info is None and not test_legacy else data_privkey_info new_wallet = _make_encrypted_wallet_data(password, payment_privkey_info, owner_privkey_info, data_privkey_info, test_legacy=test_legacy) if 'error' in new_wallet: return new_wallet # sanity check if not test_legacy: jsonschema.validate(new_wallet, ENCRYPTED_WALLET_SCHEMA_CURRENT) if encrypt: return new_wallet # decrypt and return wallet_info = decrypt_wallet(new_wallet, password, config_path=config_path) assert 'error' not in wallet_info, "Failed to decrypt new wallet: {}".format( wallet_info['error']) return wallet_info['wallet']
def ecdsa_private_key(privkey_str=None): """ Make a private key, but enforce the following rule: * unless the key's hex encoding specifically ends in '01', treat it as uncompressed. """ compressed = False if privkey_str is not None: assert isinstance(privkey_str, (str, unicode)) privkey_str = str(privkey_str) if privkey_str is None or keylib.key_formatting.get_privkey_format(privkey_str).endswith('compressed'): compressed = True return ECPrivateKey(privkey_str, compressed=compressed)
def sign_token_records(profile_components, parent_private_key, signing_algorithm="ES256K"): """ Function for iterating through a list of profile components and signing separate individual profile tokens. """ if signing_algorithm != "ES256K": raise ValueError("Signing algorithm not supported") token_records = [] for profile_component in profile_components: private_key = ECPrivateKey(parent_private_key) public_key = private_key.public_key() subject = { "publicKey": public_key.to_hex() } token = sign_token(profile_component, private_key.to_hex(), subject, signing_algorithm=signing_algorithm) token_record = wrap_token(token) token_record["parentPublicKey"] = public_key.to_hex() token_records.append(token_record) return token_records
def load_signing_key(signing_key, crypto_backend=default_backend()): """ Optional: crypto backend object from the "cryptography" python library """ if not isinstance(crypto_backend, (Backend, MultiBackend)): raise ValueError('backend must be a valid Backend object') if isinstance(signing_key, EllipticCurvePrivateKey): return signing_key elif isinstance(signing_key, (str, unicode)): invalid_strings = [b'-----BEGIN PUBLIC KEY-----'] invalid_string_matches = [ string_value in signing_key for string_value in invalid_strings ] if any(invalid_string_matches): raise ValueError( 'Signing key must be a private key, not a public key.') if is_hex(signing_key): try: private_key_pem = ECPrivateKey(signing_key).to_pem() except: pass else: try: return load_pem_private_key(private_key_pem, password=None, backend=crypto_backend) except: raise InvalidPrivateKeyError() try: return load_der_private_key(signing_key, password=None, backend=crypto_backend) except Exception as e: traceback.print_exc() raise InvalidPrivateKeyError() else: try: return load_pem_private_key(signing_key, password=None, backend=crypto_backend) except: raise InvalidPrivateKeyError() else: raise ValueError('Signing key must be in string or unicode format.')
def setUp(self): self.private_key_hex = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b22901' self.public_key_hex = '027d28f9951ce46538951e3697c62588a87f1f1f295de4a14fdd4c780fc52cfe69' self.sample_payload = {"issuedAt": "1440713414.19"} self.multiple_private_keys = [ '99eca4792e019686f2b115d65224c72431d1dc361a1bacbf46daf0ed194ea07c01', '43baf5d14516a295f8883425bb0b35de7e08ab126965c5775cf7a5956d2eb6b801' ] self.multiple_public_keys = [ ECPrivateKey(pk).public_key().to_hex() for pk in self.multiple_private_keys ] self.multiple_invalid_public_keys_1 = [ self.public_key_hex, self.multiple_public_keys[0] ] self.multiple_invalid_public_keys_2 = [ self.public_key_hex, self.multiple_public_keys[1], self.multiple_public_keys[0] ]
def encrypt_wallet(wallet, password, test_legacy=False): """ Encrypt the wallet. Return the encrypted dict on success Return {'error': ...} on error """ if test_legacy: assert BLOCKSTACK_TEST, 'test_legacy only works in test mode' # must be conformant to the current schema if not test_legacy: jsonschema.validate(wallet, WALLET_SCHEMA_CURRENT) payment_privkey_info = wallet.get('payment_privkey', None) owner_privkey_info = wallet.get('owner_privkey', None) data_privkey_info = wallet.get('data_privkey', None) if not is_singlesig(data_privkey_info): log.error('Invalid data private key') return {'error': 'Invalid data private key'} if not is_singlesig_hex(data_privkey_info): data_privkey_info = ECPrivateKey(data_privkey_info).to_hex() encrypted_wallet = _make_encrypted_wallet_data(password, payment_privkey_info, owner_privkey_info, data_privkey_info, test_legacy=test_legacy) if 'error' in encrypted_wallet: return encrypted_wallet # sanity check if not test_legacy: jsonschema.validate(encrypted_wallet, ENCRYPTED_WALLET_SCHEMA_CURRENT) return encrypted_wallet
def _make_encrypted_wallet_data(password, payment_privkey_info, owner_privkey_info, data_privkey_info, test_legacy=False): """ Lowlevel method to make the encrypted wallet's data, given the decrypted data. """ data = {} enc_payment_info = None enc_owner_info = None enc_data_info = None if not test_legacy: # legacy wallets (which we test for) may omit these. # when running in production, this is prohibited. assert payment_privkey_info assert owner_privkey_info assert data_privkey_info if payment_privkey_info is not None: enc_payment_info = encrypt_private_key_info(payment_privkey_info, password) if 'error' in enc_payment_info: log.error('failed to encrypt payment private key info') return {'error': enc_payment_info['error']} if owner_privkey_info is not None: enc_owner_info = encrypt_private_key_info(owner_privkey_info, password) if 'error' in enc_owner_info: log.error('failed to encrypt owner private key info') return {'error': enc_owner_info['error']} if data_privkey_info is not None: enc_data_info = encrypt_private_key_info(data_privkey_info, password) if 'error' in enc_data_info: log.error('failed to encrypt data private key info') return {'error': enc_data_info['error']} if enc_payment_info is not None: payment_addr = enc_payment_info['encrypted_private_key_info'][ 'address'] enc_payment_info = enc_payment_info['encrypted_private_key_info'][ 'private_key_info'] data['encrypted_payment_privkey'] = enc_payment_info data['payment_addresses'] = [payment_addr] if enc_owner_info is not None: owner_addr = enc_owner_info['encrypted_private_key_info']['address'] enc_owner_info = enc_owner_info['encrypted_private_key_info'][ 'private_key_info'] data['encrypted_owner_privkey'] = enc_owner_info data['owner_addresses'] = [owner_addr] if enc_data_info is not None: enc_data_info = enc_data_info['encrypted_private_key_info'][ 'private_key_info'] data['encrypted_data_privkey'] = enc_data_info data['data_pubkeys'] = [ ECPrivateKey(data_privkey_info).public_key().to_hex() ] data['data_pubkey'] = data['data_pubkeys'][0] data['version'] = SERIES_VERSION return data
def setUp(self): self.private_key = ECPrivateKey( self.ref['hex_private_key'], compressed=True)
def test_private_key_to_public_key_conversion(self): priv = ECPrivateKey(self.reference['hex_private_key'], compressed=False) pub = priv.public_key() self.assertEqual(pub.to_hex(), self.reference['hex_public_key']) self.assertEqual(pub.address(), self.reference['address'])
def setUp(self): self.master_private_key = ECPrivateKey(compressed=True) self.profile_components = [ {"name": "Naval Ravikant"}, {"birthDate": "1980-01-01"} ]
def setUp(self): self.private_key = ECPrivateKey(self.reference['hex_private_key'], compressed=False)
def test_private_key_from_wif(self): self.private_key_from_wif = ECPrivateKey( self.reference['wif_private_key'], compressed=False) self.assertEqual( self.private_key.to_hex(), self.private_key_from_wif.to_hex())
def test_private_key_from_wif(self): self.private_key_from_wif = ECPrivateKey( self.reference['wif_private_key'], compressed=False) self.assertEqual(self.private_key.to_hex(), self.private_key_from_wif.to_hex())