Esempio n. 1
0
def sign_raw_data(raw_data, privatekey):
    """
    Sign a string of data.
    Returns signature as a base64 string
    """
    data_hash = get_data_hash(raw_data)

    pk = ECPrivateKey(privatekey)
    pk_hex = pk.to_hex()

    # force uncompressed
    if len(pk_hex) > 64:
        pk = ECPrivateKey(privkey[:64])
    
    priv = pk.to_hex()
    pub = pk.public_key().to_hex()

    assert len(pub[2:].decode('hex')) == ecdsa.SECP256k1.verifying_key_length, "BUG: Invalid key decoding"
 
    sk = ecdsa.SigningKey.from_string(priv.decode('hex'), curve=ecdsa.SECP256k1)
    sig_bin = sk.sign_digest(data_hash.decode('hex'), sigencode=ecdsa.util.sigencode_der)
    
    # enforce low-s
    sig_r, sig_s = ecdsa.util.sigdecode_der( sig_bin, ecdsa.SECP256k1.order )
    if sig_s * 2 >= ecdsa.SECP256k1.order:
        log.debug("High-S to low-S")
        sig_s = ecdsa.SECP256k1.order - sig_s

    sig_bin = ecdsa.util.sigencode_der( sig_r, sig_s, ecdsa.SECP256k1.order )

    # sanity check 
    vk = ecdsa.VerifyingKey.from_string(pub[2:].decode('hex'), curve=ecdsa.SECP256k1)
    assert vk.verify_digest(sig_bin, data_hash.decode('hex'), sigdecode=ecdsa.util.sigdecode_der), "Failed to verify signature ({}, {})".format(sig_r, sig_s)

    return base64.b64encode( bitcoin.encode_sig( None, sig_r, sig_s ).decode('hex') )
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
 def setUp(self):
     self.master_private_key = ECPrivateKey(compressed=True)
     self.profile_components = [{
         "name": "Naval Ravikant"
     }, {
         "birthDate": "1980-01-01"
     }]
def scenario( wallets, **kw ):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

    empty_key = ECPrivateKey().to_hex()

    wallet_keys = testlib.ysi_client_initialize_wallet(
        "0123456789abcdef", wallets[1].privkey, wallets[2].privkey, wallets[0].privkey)
    test_proxy = testlib.TestAPIProxy()
    ysi_client.set_default_proxy( test_proxy )

    testlib.ysi_namespace_preorder( "test", wallets[1].addr, wallets[0].privkey )
    testlib.next_block( **kw )

    testlib.ysi_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0], 10, 10, wallets[0].privkey )
    testlib.next_block( **kw )

    testlib.ysi_namespace_ready( "test", wallets[1].privkey )
    testlib.next_block( **kw )

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()

    testlib.next_block( **kw )

    config_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG", None)

    config_dir = os.path.dirname(config_path)
    conf = ysi_client.get_config(config_path)
    assert conf

    api_pass = conf['api_password']

    # let's do a withdraw of all
    res = testlib.ysi_REST_call('POST', '/v1/wallet/balance', None, api_pass=api_pass, data= {
        'address' : virtualchain.get_privkey_address(empty_key),
        })
    if 'error' in res['response']:
        res['test'] = 'Failed to perform withdraw'
        print json.dumps(res)
        error = True
        return False
    for i in xrange (0, 1):
        testlib.next_block( **kw )
    print 'Waiting for the withdraw to go through'
    res = testlib.ysi_REST_call('GET', '/v1/wallet/balance/0', None, api_pass=api_pass)
    if 'error' in res['response']:
        res['test'] = 'Failed to get wallet balance'
        print json.dumps(res)
        error = True
        return False

    res = testlib.ysi_REST_call('GET', '/v1/wallet/balance/0', None, api_pass=api_pass)
    if 'error' in res['response']:
        res['test'] = 'Failed to get wallet balance'
        print json.dumps(res)
        error = True
        return False
Esempio n. 6
0
def decrypt_multisig_info(enc_multisig_info, password):
    """
    Given an encrypted multisig info dict,
    decrypt the sensitive fields.

    Returns {'private_keys': ..., 'redeem_script': ..., **other_fields}
    Return {'error': ...} on error
    """
    multisig_info = {
        'private_keys': None,
        'redeem_script': None,
    }

    hex_password = hexlify(password)

    assert is_encrypted_multisig(
        enc_multisig_info), 'Invalid encrypted multisig keys'

    multisig_info['private_keys'] = []
    for enc_pk in enc_multisig_info['encrypted_private_keys']:
        pk = None
        try:
            pk = aes_decrypt(enc_pk, hex_password)
            virtualchain.BitcoinPrivateKey(pk)
        except Exception as e:
            if BLOCKSTACK_TEST:
                log.exception(e)

            return {
                'error':
                'Invalid password; failed to decrypt private key in multisig wallet'
            }

        multisig_info['private_keys'].append(ECPrivateKey(pk).to_hex())

    redeem_script = None
    enc_redeem_script = enc_multisig_info['encrypted_redeem_script']
    try:
        redeem_script = aes_decrypt(enc_redeem_script, hex_password)
    except Exception as e:
        if BLOCKSTACK_TEST:
            log.exception(e)

        return {
            'error':
            'Invalid password; failed to decrypt redeem script in multisig wallet'
        }

    multisig_info['redeem_script'] = redeem_script

    # preserve any other information in the multisig info
    for k, v in enc_multisig_info.items():
        if k not in ['encrypted_private_keys', 'encrypted_redeem_script']:
            multisig_info[k] = v

    return multisig_info
Esempio n. 7
0
def load_data_pubkey_for_new_zonefile( wallet_keys={}, config_path=CONFIG_PATH ):
    """
    Find the right public key to use for data when creating a new zonefile.
    If the wallet has a data keypair defined, use that.
    Otherwise, fall back to the owner public key
    """
    data_pubkey = None
    if 'data_privkey' in wallet_keys and wallet_keys['data_privkey'] is not None:
        data_pubkey = ECPrivateKey(wallet_keys['data_privkey']).public_key().to_hex()
    elif 'data_pubkey' in wallet_keys:
        data_pubkey = wallet_keys['data_pubkey']

    return data_pubkey
Esempio n. 8
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. 9
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)
Esempio n. 10
0
def decrypt_private_key_info(privkey_info, password):
    """
    Decrypt a particular private key info bundle.
    It can be either a single-signature private key, or a multisig key bundle.
    Return {'address': ..., 'private_key_info': ...} on success.
    Return {'error': ...} on error.
    """
    hex_password = hexlify(password)

    ret = {}
    if is_encrypted_multisig(privkey_info):
        ret = decrypt_multisig_info(privkey_info, password)

        if 'error' in ret:
            return {
                'error':
                'Failed to decrypt multisig wallet: {}'.format(ret['error'])
            }

        # sanity check
        if 'redeem_script' not in ret:
            return {'error': 'Invalid multisig wallet: missing redeem_script'}

        if 'private_keys' not in ret:
            return {'error': 'Invalid multisig wallet: missing private_keys'}

        return {
            'address': virtualchain.make_p2sh_address(ret['redeem_script']),
            'private_key_info': ret
        }

    if is_encrypted_singlesig(privkey_info):
        try:
            pk = aes_decrypt(privkey_info, hex_password)
            pk = ECPrivateKey(pk).to_hex()
        except Exception as e:
            if BLOCKSTACK_TEST:
                log.exception(e)

            return {'error': 'Invalid password'}

        return {
            'address':
            virtualchain.BitcoinPrivateKey(pk).public_key().address(),
            'private_key_info': pk
        }

    return {'error': 'Invalid encrypted private key info'}
Esempio n. 11
0
def load_data_pubkey_for_new_zonefile(wallet_keys={}, config_path=CONFIG_PATH):
    """
    Find the right public key to use for data when creating a new zonefile.
    If the wallet has a data keypair defined, use that.
    Otherwise, fall back to the owner public key
    """
    data_pubkey = None

    data_privkey = wallet_keys.get('data_privkey', None)
    if data_privkey is not None:
        # force compressed
        data_pubkey = ECPrivateKey(data_privkey, compressed=True).public_key().to_hex()
        return data_pubkey

    data_pubkey = wallet_keys.get('data_pubkey', None)
    return data_pubkey
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 get_data_privkey(user_zonefile, wallet_keys=None, config_path=CONFIG_PATH):
    """
    Get the user's data private key.
    Use the private key that corresponds to the data public key in their zonefile.
    (If the have a designated data public key, use the data private key.  If they don't,
    use the owner private key).

    Return None if not set
    """
    from .wallet import get_wallet
    from .user import user_zonefile_data_pubkey

    try:
        data_pubkey = user_zonefile_data_pubkey(user_zonefile)
    except ValueError:
        log.error("Multiple pubkeys defined")
        return None

    if data_pubkey is None:
        log.error("No data public key defined")
        return None

    wallet = None
    if wallet_keys is not None:
        if not wallet_keys.has_key(
                'data_privkey') or wallet_keys['data_privkey'] is None:
            log.error("No data private key set")
            return None

        wallet = wallet_keys

    else:
        wallet = get_wallet(config_path=CONFIG_PATH)
        assert wallet is not None

    if not wallet.has_key('data_privkey') or ECPrivateKey(
            wallet['data_privkey']).public_key().to_hex() != data_pubkey:
        # data private key doesn't match zonefile
        log.error("Data private key does not match zonefile")
        return None

    else:
        # zonefile matches data privkey
        return wallet['data_privkey']
Esempio n. 14
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. 15
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. 16
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'])
Esempio n. 17
0
 def setUp(self):
     self.private_key = ECPrivateKey(
         self.ref['wif_private_key'], compressed=False)
     self.assertEqual(self.private_key_from_wif.to_hex(), self.ref['hex_private_key'])
Esempio n. 18
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. 19
0
 def setUp(self):
     self.private_key = ECPrivateKey(self.reference['hex_private_key'],
                                     compressed=False)
Esempio n. 20
0
def make_wallet_keys(data_privkey=None,
                     owner_privkey=None,
                     payment_privkey=None):
    """
    For testing.  DO NOT USE
    """

    ret = {
        'owner_privkey': None,
        'data_privkey': None,
        'payment_privkey': None,
    }

    if data_privkey is not None:
        if not is_singlesig(data_privkey):
            raise ValueError('Invalid data key info')

        pk_data = virtualchain.BitcoinPrivateKey(data_privkey).to_hex()
        ret['data_privkey'] = pk_data

    if owner_privkey is not None:
        if is_multisig(owner_privkey):
            pks = [
                virtualchain.BitcoinPrivateKey(pk).to_hex()
                for pk in owner_privkey['private_keys']
            ]
            m, pubs = virtualchain.parse_multisig_redeemscript(
                owner_privkey['redeem_script'])
            ret['owner_privkey'] = virtualchain.make_multisig_info(m, pks)
            ret['owner_addresses'] = [ret['owner_privkey']['address']]

        elif is_singlesig(owner_privkey):
            pk_owner = virtualchain.BitcoinPrivateKey(owner_privkey).to_hex()
            ret['owner_privkey'] = pk_owner
            ret['owner_addresses'] = [
                virtualchain.BitcoinPrivateKey(
                    pk_owner).public_key().address()
            ]

        else:
            raise ValueError('Invalid owner key info')

    if payment_privkey is None:
        return ret

    if is_multisig(payment_privkey):
        pks = [
            virtualchain.BitcoinPrivateKey(pk).to_hex()
            for pk in payment_privkey['private_keys']
        ]
        m, pubs = virtualchain.parse_multisig_redeemscript(
            payment_privkey['redeem_script'])
        ret['payment_privkey'] = virtualchain.make_multisig_info(m, pks)
        ret['payment_addresses'] = [ret['payment_privkey']['address']]

    elif is_singlesig(payment_privkey):
        pk_payment = virtualchain.BitcoinPrivateKey(payment_privkey).to_hex()
        ret['payment_privkey'] = pk_payment
        ret['payment_addresses'] = [
            virtualchain.BitcoinPrivateKey(pk_payment).public_key().address()
        ]

    else:
        raise ValueError('Invalid payment key info')

    ret['data_pubkey'] = ECPrivateKey(
        ret['data_privkey']).public_key().to_hex()
    ret['data_pubkeys'] = [ret['data_pubkey']]

    return ret
Esempio n. 21
0
            )

        return ret

    # legacy compat: use the master private key to generate child keys.
    # If the specific key they are purposed for is not defined in the wallet,
    # then they are used in its place.
    # This is because originally, the master private key was used to derive
    # the owner, payment, and data private keys; not all wallets define
    # these keys separately (and have instead relied on us being able to
    # generate them from the master private key).
    child = wallet.get_child_keypairs(count=3, include_privkey=True)
    payment_keypair = child[0]
    owner_keypair = child[1]
    data_keypair = child[2]
    data_pubkey = ECPrivateKey(data_keypair[1]).public_key().to_hex()

    multisig = False
    curr_height = get_block_height(config_path=config_path)
    if curr_height >= config.EPOCH_HEIGHT_MINIMUM:
        # safe to use multisig
        multisig = True

    ret = {}
    keynames = ['payment', 'owner', 'data']
    for i in xrange(0, len(keynames)):

        keyname = keynames[i]
        keyname_privkey = "%s_privkey" % keyname
        keyname_addresses = "%s_addresses" % keyname
Esempio n. 22
0
def unlock_wallet(password=None, config_dir=CONFIG_DIR, wallet_path=None):
    """
    Unlock the wallet.
    Save the wallet to the RPC daemon on success.

    If this wallet is in legacy format, then it will
    be migrated to the latest format and the legacy
    copy backed up.

    Return {'status': True, 'addresses': ...} on success
    return {'error': ...} on error
    """
    config_path = os.path.join(config_dir, CONFIG_FILENAME)
    if wallet_path is None:
        wallet_path = os.path.join(config_dir, WALLET_FILENAME)

    if is_wallet_unlocked(config_dir):
        return {'status': True}

    else:

        try:
            if password is None:
                password = getpass("Enter wallet password: "******"r") as f:
                data = f.read()
                data = json.loads(data)

            wallet = decrypt_wallet(data, password, config_path=config_path)
            if 'error' in wallet:
                log.error("Failed to decrypt wallet: %s" % wallet['error'])
                return wallet

            # may need to migrate data_pubkey into wallet.json
            _, _, onfile_data_pubkey = get_addresses_from_file(
                wallet_path=wallet_path)
            if onfile_data_pubkey is None:

                # make a data keypair (always the third child (index 2) of the HDWallet)
                w = HDWallet(wallet['hex_privkey'])
                child = w.get_child_keypairs(count=3, include_privkey=True)
                data_keypair = child[2]

                wallet['data_privkey'] = data_keypair[1]
                wallet['data_pubkeys'] = [
                    ECPrivateKey(data_keypair[1]).public_key().to_hex()
                ]
                wallet['data_pubkey'] = wallet['data_pubkeys'][0]

                # set addresses
                wallet['payment_addresses'] = [
                    get_privkey_info_address(wallet['payment_privkey'])
                ]
                wallet['owner_addresses'] = [
                    get_privkey_info_address(wallet['owner_privkey'])
                ]

                # save!
                encrypted_wallet = make_wallet(
                    password,
                    hex_privkey=wallet['hex_privkey'],
                    payment_privkey=wallet['payment_privkey'],
                    owner_privkey=wallet['owner_privkey'],
                    data_privkey=wallet['data_privkey'],
                    config_path=config_path)

                if 'error' in encrypted_wallet:
                    log.error("Failed to make wallet: %s" %
                              encrypted_wallet['error'])
                    return encrypted_wallet

                write_wallet(encrypted_wallet, path=wallet_path + ".tmp")
                legacy_path = wallet_path + ".legacy"
                if os.path.exists(wallet_path):
                    if not os.path.exists(legacy_path):
                        shutil.move(wallet_path, legacy_path)
                    else:
                        i = 1
                        while os.path.exists(legacy_path):
                            legacy_path = wallet_path + ".legacy.%s" % i
                            i += 1

                        shutil.move(wallet_path, legacy_path)

                shutil.move(wallet_path + ".tmp", wallet_path)
                log.debug(
                    "Migrated wallet %s (legacy wallet backed up to %s)" %
                    (wallet_path, legacy_path))

            # save!
            try:
                res = save_keys_to_memory([
                    wallet['payment_addresses'][0], wallet['payment_privkey']
                ], [wallet['owner_addresses'][0], wallet['owner_privkey']
                    ], [wallet['data_pubkeys'][0], wallet['data_privkey']],
                                          config_dir=config_dir)

            except KeyError, ke:
                if os.environ.get("BLOCKSACK_DEBUG", None) == "1":
                    log.error(
                        "data: %s\n" %
                        simplejson.dumps(wallet, indent=4, sort_keys=True))
                raise

            if 'error' in res:
                return res

            addresses = {
                "payment_address": wallet['payment_addresses'][0],
                "owner_address": wallet['owner_addresses'][0],
                "data_pubkey": wallet['data_pubkeys'][0]
            }

            return {'status': True, "addresses": addresses}

        except KeyboardInterrupt:
            return {'error': 'Interrupted'}
Esempio n. 23
0
 def test_random_private_key(self):
     private_key = ECPrivateKey()
     self.assertTrue(isinstance(private_key, ECPrivateKey))
Esempio n. 24
0
def scenario(wallets, **kw):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

    empty_key = ECPrivateKey().to_hex()

    wallet_keys = testlib.ysi_client_initialize_wallet("0123456789abcdef",
                                                       empty_key, empty_key,
                                                       empty_key)
    test_proxy = testlib.TestAPIProxy()
    ysi_client.set_default_proxy(test_proxy)

    testlib.ysi_namespace_preorder("test", wallets[1].addr, wallets[0].privkey)
    testlib.next_block(**kw)

    testlib.ysi_namespace_reveal(
        "test", wallets[1].addr, 52595, 250, 4,
        [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10,
        wallets[0].privkey)
    testlib.next_block(**kw)

    testlib.ysi_namespace_ready("test", wallets[1].privkey)
    testlib.next_block(**kw)

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()

    testlib.next_block(**kw)

    config_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG", None)

    config_dir = os.path.dirname(config_path)
    conf = ysi_client.get_config(config_path)
    assert conf

    api_pass = conf['api_password']

    payment_key = wallets[1].privkey

    # make zonefile for recipient
    driver_urls = ysi_client.storage.make_mutable_data_urls(
        'bar.test', use_only=['dht', 'disk'])
    zonefile = ysi_client.zonefile.make_empty_zonefile('bar.test',
                                                       wallets[4].pubkey_hex,
                                                       urls=driver_urls)
    zonefile_txt = ysi_zones.make_zone_file(zonefile,
                                            origin='bar.test',
                                            ttl=3600)

    no_key_postage = {'name': 'bar.test', 'zonefile': zonefile_txt}
    key_postage = dict(no_key_postage)
    key_postage['payment_key'] = payment_key
    key_postage['owner_key'] = new_key

    res = testlib.ysi_REST_call('POST',
                                '/v1/names',
                                None,
                                api_pass=api_pass,
                                data=no_key_postage)
    if 'error' not in res['response']:
        print "Successfully registered user with should-have-been-bad keys"
        print res
        return False

    # let's do a small withdraw
    res = testlib.ysi_REST_call(
        'POST',
        '/v1/wallet/balance',
        None,
        api_pass=api_pass,
        data={
            'address': virtualchain.get_privkey_address(empty_key),
            'amount': int(1e4),
            'payment_key': payment_key
        })
    if 'error' in res['response']:
        res['test'] = 'Failed to perform withdraw'
        print json.dumps(res)
        error = True
        return False
    for i in xrange(0, 1):
        testlib.next_block(**kw)
    print 'Waiting for the withdraw to go through'
    res = testlib.ysi_REST_call('GET',
                                '/v1/wallet/balance/0',
                                None,
                                api_pass=api_pass)
    if 'error' in res['response']:
        res['test'] = 'Failed to get wallet balance'
        print json.dumps(res)
        error = True
        return False

    if int(res['response']['balance']['satoshis']) <= 0:
        res['test'] = 'Wallet balance did not increment!'
        print json.dumps(res)
        error = True
        return False

    res = testlib.ysi_REST_call('POST',
                                '/v1/names',
                                None,
                                api_pass=api_pass,
                                data=key_postage)
    if 'error' in res['response']:
        res['test'] = 'Failed to register user'
        print json.dumps(res)
        error = True
        return False

    print "Registering bar.test"
    for i in xrange(0, 6):
        testlib.next_block(**kw)
    if not res:
        return False
    # wait for the preorder to get confirmed
    for i in xrange(0, 4):
        testlib.next_block(**kw)
    # wait for register to go through
    print 'Wait for register to be submitted'
    time.sleep(10)

    # wait for the register to get confirmed
    for i in xrange(0, 6):
        testlib.next_block(**kw)

    res = testlib.verify_in_queue(None,
                                  'bar.test',
                                  'register',
                                  None,
                                  api_pass=api_pass)
    if not res:
        return False

    for i in xrange(0, 4):
        testlib.next_block(**kw)

    print 'Wait for update to be submitted'
    time.sleep(10)

    # wait for update to get confirmed
    for i in xrange(0, 6):
        testlib.next_block(**kw)

    res = testlib.verify_in_queue(None,
                                  'bar.test',
                                  'update',
                                  None,
                                  api_pass=api_pass)
    if not res:
        print res
        print "update error in first update"
        return False

    for i in xrange(0, 4):
        testlib.next_block(**kw)

    print 'Wait for zonefile to be sent'
    time.sleep(10)

    res = testlib.ysi_REST_call("GET",
                                "/v1/names/bar.test",
                                None,
                                api_pass=api_pass)
    if 'error' in res or res['http_status'] != 200:
        res['test'] = 'Failed to get name bar.test'
        print json.dumps(res)
        return False

    print res['response']

    zonefile_hash = res['response']['zonefile_hash']

    # should still be registered
    if res['response']['status'] != 'registered':
        print "register not complete"
        print json.dumps(res)
        return False

    # do we have the history for the name?
    res = testlib.ysi_REST_call("GET",
                                "/v1/names/bar.test/history",
                                None,
                                api_pass=api_pass)
    if 'error' in res or res['http_status'] != 200:
        res['test'] = "Failed to get name history for foo.test"
        print json.dumps(res)
        return False

    # valid history?
    hist = res['response']
    if len(hist.keys()) != 3:
        res['test'] = 'Failed to get update history'
        res['history'] = hist
        print json.dumps(res, indent=4, sort_keys=True)
        return False

    # get the zonefile
    res = testlib.ysi_REST_call(
        "GET",
        "/v1/names/bar.test/zonefile/{}".format(zonefile_hash),
        None,
        api_pass=api_pass)
    if 'error' in res or res['http_status'] != 200:
        res['test'] = 'Failed to get name zonefile'
        print json.dumps(res)
        return False

    # same zonefile we put?
    if res['response']['zonefile'] != zonefile_txt:
        res['test'] = 'mismatched zonefile, expected\n{}\n'.format(
            zonefile_txt)
        print json.dumps(res)
        return False

    # okay, now let's try to do an update.
    # make zonefile for recipient
    driver_urls = ysi_client.storage.make_mutable_data_urls(
        'bar.test', use_only=['http', 'disk'])
    zonefile = ysi_client.zonefile.make_empty_zonefile('bar.test',
                                                       wallets[3].pubkey_hex,
                                                       urls=driver_urls)
    zonefile_txt = ysi_zones.make_zone_file(zonefile,
                                            origin='bar.test',
                                            ttl=3600)

    # let's do this update.
    res = testlib.ysi_REST_call('PUT',
                                '/v1/names/bar.test/zonefile',
                                None,
                                api_pass=api_pass,
                                data={
                                    'zonefile': zonefile_txt,
                                    'owner_key': new_key,
                                    'payment_key': payment_key
                                })
    if 'error' in res or res['http_status'] != 202:
        res['test'] = 'Failed to register user'
        print json.dumps(res)
        error = True
        return False
    else:
        print "Submitted update!"
        print res

    print 'Wait for update to be submitted'
    time.sleep(10)

    # wait for update to get confirmed
    for i in xrange(0, 6):
        testlib.next_block(**kw)

    res = testlib.verify_in_queue(None,
                                  'bar.test',
                                  'update',
                                  None,
                                  api_pass=api_pass)
    if not res:
        print "update error in second update"
        print res
        return False

    for i in xrange(0, 4):
        testlib.next_block(**kw)

    # wait for zonefile to propagate
    time.sleep(10)

    res = testlib.ysi_REST_call("GET",
                                "/v1/names/bar.test",
                                None,
                                api_pass=api_pass)
    if 'error' in res or res['http_status'] != 200:
        res['test'] = 'Failed to get name bar.test'
        print json.dumps(res)
        return False

    zonefile_hash = res['response']['zonefile_hash']
    # get the zonefile
    res = testlib.ysi_REST_call(
        "GET",
        "/v1/names/bar.test/zonefile/{}".format(zonefile_hash),
        None,
        api_pass=api_pass)
    if 'error' in res or res['http_status'] != 200:
        res['test'] = 'Failed to get name zonefile'
        print json.dumps(res)
        return False

    # same zonefile we put?
    if res['response']['zonefile'] != zonefile_txt:
        res['test'] = 'mismatched zonefile, expected\n{}\n'.format(
            zonefile_txt)
        print json.dumps(res)
        return False
Esempio n. 25
0
 def setUp(self):
     self.private_key = ECPrivateKey(
         self.ref['hex_private_key'], compressed=True)
Esempio n. 26
0
def singlesig_privkey_to_string(privkey_info):
    """
    Convert private key to string
    """
    return ECPrivateKey(privkey_info).to_hex()
Esempio n. 27
0
            assert is_legacy
            assert keyname in key_defaults, 'BUG: no legacy private key for {}'.format(
                keyname)

            default_privkey = key_defaults[keyname]
            new_wallet[keyname_privkey] = default_privkey
            new_wallet[keyname_addresses] = [
                virtualchain.BitcoinPrivateKey(
                    default_privkey).public_key().address()
            ]

            migrated = True

    # add data keys. Make sure it's *uncompressed*
    assert new_wallet.has_key('data_privkey')
    data_pubkey = ECPrivateKey(str(
        new_wallet['data_privkey'])).public_key().to_hex()
    if keylib.key_formatting.get_pubkey_format(
            data_pubkey) == 'hex_compressed':
        data_pubkey = keylib.key_formatting.decompress(data_pubkey)

    data_pubkey = str(data_pubkey)

    new_wallet['data_pubkeys'] = [data_pubkey]
    new_wallet['data_pubkey'] = data_pubkey

    new_wallet['version'] = SERIES_VERSION

    # sanity check--must be decrypted properly
    try:
        jsonschema.validate(new_wallet, WALLET_SCHEMA_CURRENT)
    except ValidationError as e:
Esempio n. 28
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