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
Esempio n. 2
0
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
Esempio n. 3
0
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
Esempio n. 4
0
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)
Esempio n. 7
0
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'])
Esempio n. 8
0
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'])
Esempio n. 9
0
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']
Esempio n. 10
0
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
Esempio n. 12
0
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.')
Esempio n. 13
0
    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]
        ]
Esempio n. 14
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
Esempio n. 15
0
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
Esempio n. 16
0
 def setUp(self):
     self.private_key = ECPrivateKey(
         self.ref['hex_private_key'], compressed=True)
Esempio n. 17
0
 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"}
     ]
Esempio n. 19
0
 def setUp(self):
     self.private_key = ECPrivateKey(self.reference['hex_private_key'],
                                     compressed=False)
Esempio n. 20
0
 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())
Esempio n. 21
0
 def setUp(self):
     self.private_key = ECPrivateKey(self.reference['hex_private_key'], compressed=False)
Esempio n. 22
0
 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())
Esempio n. 23
0
 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'])