def clean_settings( backup_json ): clean_settings = {} new_settings = json.loads( backup_json, object_hook=lambda x: Settings.Instance().fix_account_keys(x) ) if 'bip32master' not in new_settings: raise ValueError( "Given JSON doesn't have master key" ) vbytes, depth, fingerprint, i, chaincode, key = bitcoin.bip32_deserialize( new_settings['bip32master'] ) if vbytes != bitcoin.PRIVATE or depth != 0 or i != 0 or fingerprint != '\x00'*4: raise ValueError( "Master key is not at top of tree and private" ) clean_settings['bip32master'] = new_settings['bip32master'] clean_settings['accountNumber'] = new_settings.get( "accountNumber", 1 ) clean_settings['accounts'] = { } for account, account_info in new_settings.get( 'accounts', { } ).items(): if 'accountKey' not in account_info: raise ValueError( "Account %i has no master key" % account ) vbytes, depth, fingerprint, i, chaincode, key = bitcoin.bip32_deserialize( account_info["accountKey"] ) if depth != 2 or vbytes != bitcoin.PRIVATE or i != 0: raise ValueError( "Account %i has invalid master key" % account ) if account_info.get( "numKeys", 0 ) < 0: raise ValueError( "Account %i has invalid key count " % account ) clean_settings['accounts'][account] = { } clean_settings['accounts'][account]['accountKey'] = account_info['accountKey'] clean_settings['accounts'][account]['numKeys'] = account_info.get( "numKeys", 0 ) clean_settings['accounts'][account]['keys'] = [] KeyHelper.regenerate_keys( account_info['accountKey'], range( account_info.get("numKeys", 0 )), clean_settings['accounts'][account]['keys'] ) #FIXME: actually check validity of imported redeemscripts clean_settings['redeemScripts'] = new_settings.get( 'redeemScripts', [] ) return clean_settings
def test_invalid_bip32_key(): #keys with invalid checksum bad_keys = ( 'xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8BrrngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7', 'xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQQKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw' ) for x in bad_keys: with pytest.raises(Exception) as e_info: fake_tuple = btc.bip32_deserialize(x)
def clean_settings(backup_json): clean_settings = {} new_settings = json.loads( backup_json, object_hook=lambda x: Settings.Instance().fix_account_keys(x)) if 'bip32master' not in new_settings: raise ValueError("Given JSON doesn't have master key") vbytes, depth, fingerprint, i, chaincode, key = bitcoin.bip32_deserialize( new_settings['bip32master']) if vbytes != bitcoin.PRIVATE or depth != 0 or i != 0 or fingerprint != '\x00' * 4: raise ValueError("Master key is not at top of tree and private") clean_settings['bip32master'] = new_settings['bip32master'] clean_settings['accountNumber'] = new_settings.get("accountNumber", 1) clean_settings['accounts'] = {} for account, account_info in new_settings.get('accounts', {}).items(): if 'accountKey' not in account_info: raise ValueError("Account %i has no master key" % account) vbytes, depth, fingerprint, i, chaincode, key = bitcoin.bip32_deserialize( account_info["accountKey"]) if depth != 2 or vbytes != bitcoin.PRIVATE or i != 0: raise ValueError("Account %i has invalid master key" % account) if account_info.get("numKeys", 0) < 0: raise ValueError("Account %i has invalid key count " % account) clean_settings['accounts'][account] = {} clean_settings['accounts'][account]['accountKey'] = account_info[ 'accountKey'] clean_settings['accounts'][account]['numKeys'] = account_info.get( "numKeys", 0) clean_settings['accounts'][account]['keys'] = [] KeyHelper.regenerate_keys( account_info['accountKey'], range(account_info.get("numKeys", 0)), clean_settings['accounts'][account]['keys']) #FIXME: actually check validity of imported redeemscripts clean_settings['redeemScripts'] = new_settings.get( 'redeemScripts', []) return clean_settings
def key_address(masterkey, path): """Compute address and private key (hex) for path""" derived_key = descend(masterkey, path) priv_key = btc.bip32_deserialize(derived_key)[-1] pub_key = btc.bip32_extract_key(btc.bip32_privtopub(derived_key)) priv_key_hex = btc.encode_privkey( btc.decode_privkey(priv_key, 'bin_compressed'), 'hex') address = btc.pubkey_to_address(pub_key) return priv_key_hex, address
def make_moderator(self): """ Set self as a moderator in the DHT. """ u = objects.Profile() k = u.PublicKey() k.public_key = bitcoin.bip32_deserialize(KeyChain().bitcoin_master_pubkey)[5] k.signature = self.signing_key.sign(k.public_key)[:64] u.bitcoin_key.MergeFrom(k) u.moderator = True Profile().update(u) proto = self.kserver.node.getProto().SerializeToString() self.kserver.set(digest("moderators"), digest(proto), proto)
def make_moderator(self): """ Set self as a moderator in the DHT. """ u = objects.Profile() k = u.PublicKey() k.public_key = bitcoin.bip32_deserialize(KeyChain(self.db).bitcoin_master_pubkey)[5] k.signature = self.signing_key.sign(k.public_key)[:64] u.bitcoin_key.MergeFrom(k) u.moderator = True Profile(self.db).update(u) proto = self.kserver.node.getProto().SerializeToString() self.kserver.set(digest("moderators"), digest(proto), proto)
def test_child_generation(self): public_keychain = PublicKeychain.from_public_key(self.public_key_hex) public_keychain_child = public_keychain.child(0) keychain_parts = bip32_deserialize(str(public_keychain_child)) self.assertEqual(keychain_parts[4], self.reference_child_0_chaincode)
def is_bip32_pubkey(s): try: key = btc.bip32_deserialize(s) return key[0] in btc.PUBLIC except Exception: return False
def create(self, expiration_date, metadata_category, title, description, currency_code, price, process_time, nsfw, shipping_origin, shipping_regions, est_delivery_domestic=None, est_delivery_international=None, terms_conditions=None, returns=None, keywords=None, category=None, condition=None, sku=None, images=None, free_shipping=None, shipping_currency_code=None, shipping_domestic=None, shipping_international=None, options=None, moderators=None): """ All parameters are strings except: :param expiration_date: `string` (must be formatted UTC datetime) :param keywords: `list` :param nsfw: `boolean` :param images: a `list` of image files :param free_shipping: `boolean` :param shipping_origin: a 'string' formatted `CountryCode` :param shipping_regions: a 'list' of 'string' formatted `CountryCode`s :param options: a 'dict' containing options as keys and 'list' as option values. :param moderators: a 'list' of 'string' guids (hex encoded). """ # TODO: import keys into the contract, import moderator information from db, sign contract. profile = Profile().get() keychain = KeyChain() self.contract = OrderedDict( { "vendor_offer": { "listing": { "metadata": { "version": "0.1", "expiry": expiration_date + " UTC", "category": metadata_category, "category_sub": "fixed price" }, "id": { "guid": keychain.guid.encode("hex"), "pubkeys": { "guid": keychain.guid_signed_pubkey[64:].encode("hex"), "bitcoin": bitcoin.bip32_deserialize( KeyChain().bitcoin_master_pubkey)[5].encode("hex") } }, "item": { "title": title, "description": description, "process_time": process_time, "price_per_unit": {}, "nsfw": nsfw } } } } ) if metadata_category == "physical good" and condition is not None: self.contract["vendor_offer"]["listing"]["item"]["condition"] = condition if currency_code.upper() == "BTC": item = self.contract["vendor_offer"]["listing"]["item"] item["price_per_unit"]["bitcoin"] = price else: item = self.contract["vendor_offer"]["listing"]["item"] item["price_per_unit"]["fiat"] = {} item["price_per_unit"]["fiat"]["price"] = price item["price_per_unit"]["fiat"]["currency_code"] = currency_code if keywords is not None: self.contract["vendor_offer"]["listing"]["item"]["keywords"] = [] self.contract["vendor_offer"]["listing"]["item"]["keywords"].extend(keywords) if category is not None: self.contract["vendor_offer"]["listing"]["item"]["category"] = category if sku is not None: self.contract["vendor_offer"]["listing"]["item"]["sku"] = sku if options is not None: self.contract["vendor_offer"]["listing"]["item"]["options"] = options if metadata_category == "physical good": self.contract["vendor_offer"]["listing"]["shipping"] = {} shipping = self.contract["vendor_offer"]["listing"]["shipping"] shipping["shipping_origin"] = shipping_origin if free_shipping is False: self.contract["vendor_offer"]["listing"]["shipping"]["free"] = False self.contract["vendor_offer"]["listing"]["shipping"]["flat_fee"] = {} if shipping_currency_code == "BTC": self.contract["vendor_offer"]["listing"]["shipping"]["flat_fee"]["bitcoin"] = {} self.contract["vendor_offer"]["listing"]["shipping"]["flat_fee"]["bitcoin"][ "domestic"] = shipping_domestic self.contract["vendor_offer"]["listing"]["shipping"]["flat_fee"]["bitcoin"][ "international"] = shipping_international else: shipping = self.contract["vendor_offer"]["listing"]["shipping"] shipping["flat_fee"]["fiat"] = {} shipping["flat_fee"]["fiat"]["price"] = {} shipping["flat_fee"]["fiat"]["price"][ "domestic"] = shipping_domestic shipping["flat_fee"]["fiat"]["price"][ "international"] = shipping_international shipping["flat_fee"]["fiat"][ "currency_code"] = shipping_currency_code else: self.contract["vendor_offer"]["listing"]["shipping"]["free"] = True self.contract["vendor_offer"]["listing"]["shipping"]["shipping_regions"] = [] for region in shipping_regions: shipping = self.contract["vendor_offer"]["listing"]["shipping"] shipping["shipping_regions"].append(region) listing = self.contract["vendor_offer"]["listing"] listing["shipping"]["est_delivery"] = {} listing["shipping"]["est_delivery"]["domestic"] = est_delivery_domestic listing["shipping"]["est_delivery"][ "international"] = est_delivery_international if profile.HasField("handle"): self.contract["vendor_offer"]["listing"]["id"]["blockchain_id"] = profile.handle if images is not None: self.contract["vendor_offer"]["listing"]["item"]["image_hashes"] = [] for image in images: hash_value = digest(image).encode("hex") self.contract["vendor_offer"]["listing"]["item"]["image_hashes"].append(hash_value) with open(DATA_FOLDER + "store/media/" + hash_value, 'w') as outfile: outfile.write(image) HashMap().insert(digest(image), DATA_FOLDER + "store/media/" + hash_value) if terms_conditions is not None or returns is not None: self.contract["vendor_offer"]["listing"]["policy"] = {} if terms_conditions is not None: self.contract["vendor_offer"]["listing"]["policy"]["terms_conditions"] = terms_conditions if returns is not None: self.contract["vendor_offer"]["listing"]["policy"]["returns"] = returns if moderators is not None: self.contract["vendor_offer"]["listing"]["moderators"] = [] for mod in moderators: mod_info = ModeratorStore().get_moderator(unhexlify(mod)) print mod_info if mod_info is not None: moderator = { "guid": mod, "blockchain_id": mod_info[6], "pubkeys": { "signing": { "key": mod_info[1][64:].encode("hex"), "signature": mod_info[1][:64].encode("hex") }, "encryption": { "key": mod_info[2].encode("hex"), "signature": mod_info[3].encode("hex") }, "bitcoin": { "key": mod_info[4].encode("hex"), "signature": mod_info[5].encode("hex") } } } self.contract["vendor_offer"]["listing"]["moderators"].append(moderator) listing = json.dumps(self.contract["vendor_offer"]["listing"], indent=4) self.contract["vendor_offer"]["signature"] = \ keychain.signing_key.sign(listing, encoder=nacl.encoding.HexEncoder)[:128] self.save()