{ "info": { "author": "Steven Buss", "author_email": "steven.buss@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2.5", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.0", "Programming Language :: Python :: 3.1", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4" ], "description": ".. image:: https://travis-ci.org/sbuss/bitmerchant.svg?branch=master\n :target: https://travis-ci.org/sbuss/bitmerchant\n\n.. image:: http://codecov.io/github/sbuss/bitmerchant/coverage.svg?branch=master\n :target: http://codecov.io/github/sbuss/bitmerchant?branch=master\n\nBitmerchant\n===========\n\nBitmerchant is a work-in-progress python library for common bitcoin/altcoin\nmerchant uses.\n\nBitmerchant currently supports:\n\n.. _BIP32: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki\n\n#. Easy to use BIP32_ wallet for linking user payments with their accounts.\n\nThese features are planned (or in development where marked):\n\n#. Regular and M-of-N transactions (under development)\n#. A system that monitors the blockchain and sends out a signal when a\n payment is received at an address you're tracking.\n#. Automatic forwarding transactions\n\n--------------\n\nIf you find this library useful, please consider a small donation. Donations\nwill be used to reward developers for bugfixes.\n\n+--------------------------------------+--------------------------------------+\n| BTC | Doge |\n+======================================+======================================+\n| 19jSqVd8bpevi3qacBedkAdDqEXtGAn5t7 | DQ4b7RJfoniVwFsnrMJr6vi6n6UFeubdiv |\n+--------------------------------------+--------------------------------------+\n| |Donate BTC| | |Donate DOGE| |\n+--------------------------------------+--------------------------------------+\n\nNOTICE\n======\n\n** **BUG NOTICE** **\n\nVersions of ``bitmerchant`` prior to ``0.1.8`` contained a caching bug that may\nhave resulted in calls to ``bip32.Wallet.get_child`` to return incorrect results.\nThe steps to reproduce the bug are unlikely and do not match the typical\nusage patterns of ``bitmerchant``.\n\n**At this time, no users are known to have been affected by this bug.**\n\nIf you have been affected by this bug and need help recovering any lost or\nmisplaced coins, please contact me directly at\nsteven.buss+bitmerchant@gmail.com.\n\nThe affected versions of ``bitmerchant`` have been removed from pypi. They\nhave not been untagged in git.\n\nThe two possible failure scenarios are: misplaced coins and stolen coins\n\nMisplaced Coins\n---------------\n\nThis is still unlikely, but slightly more likely than having your coins stolen.\n\nIn order to have misplaced coins as a result of the bug, all of the below\npoints must be true:\n\n#. Your master private key must be available for your code to load, rather than in a secure offline backup\n#. You call ``get_child`` directly, rather than ``create_new_address_for_user``\n#. You call ``get_child(n, is_prime=False)`` and ``get_child(n, is_prime=True)``\n #. in the same python process\n #. on the same wallet object\n #. you display the public address of the second ``get_child`` call (in whichever order)\n\nIn this case, the bug would have resulted in the first ``get_child``'s address\nbeing shown. You can easily recover these misplaced coins by updating to\n``bitmerchant>=0.1.8``, regenerating the address you accidentally sent coins\nto, and moving them to a corrected destination. The \"deterministic\" part of\n\"hierarchical deterministic wallets\" really works to your advantage here.\n\nStolen Coins\n------------\n\nFirst, it is extremely unlikely that your code met all of the requirements\nto be affected by this bug. If you can answer \"yes\" to every one of the points\nbelow, then you should upgrade to ``bitmerchant>=0.1.8``, generate a new master\nprivate key, and move all coins to the new wallet as soon as possible.\n\nIn order to have coins stolen as a result of the bug, all of the below points\nmust be true:\n\n#. You expose your master public key to the public\n#. Your master private key must be available for your code to load, rather than in a secure offline backup\n#. You call ``get_child`` directly, rather than ``create_new_address_for_user``\n#. You call ``get_child(n, is_prime=False)`` and ``get_child(n, is_prime=True)``\n #. in that order\n #. in the same python process\n #. on the same wallet object\n #. with the intention of only giving the prime child to the user\n#. You give the public and private keys of child wallets to users\n\nInstallation\n============\n\nbitmerchant is on pypi_, so just use pip:\n\n.. _pypi: https://pypi.python.org/pypi/bitmerchant\n\n.. code-block:: bash\n\n pip install bitmerchant\n\nThen to verify it's working:\n\n.. code-block:: python\n\n from bitmerchant.wallet import Wallet\n\n w = Wallet.from_master_secret(\"correct horse battery staple\")\n assert w.to_address() == \"1AJ7EDxyRwyGNcL4scXfUU7XqYkmVcwHqe\"\n\nBIP32 wallets\n=============\n\nBIP32_ wallets are hierarchical deterministic wallets. They allow you to\ngenerate bitcoin/altcoin addresses without exposing your private key to a\npotentially insecure server.\n\nTo link a user with a new bitcoin address, you just need to provide the user's\nID to the ``create_new_address_for_user`` method:\n\nTL;DR\n-----\n\n.. code-block:: python\n\n ## DO THIS ON AN OFFLINE MACHINE, NOT YOUR WEBSERVER\n from bitmerchant.wallet import Wallet\n\n # Create a wallet, and a primary child wallet for your app\n my_wallet = Wallet.new_random_wallet()\n print(my_wallet.serialize_b58(private=True)) # Write this down or print it out and keep in a secure location\n project_0_wallet = my_wallet.get_child(0, is_prime=True)\n project_0_public = project_0_wallet.public_copy()\n print(project_0_public.serialize_b58(private=False)) # Put this in your app's settings file\n\n\n ## THINGS BELOW ARE PUBLIC FOR YOUR WEBSERVER\n\n # In your app's settings file, declare your public wallet:\n WALLET_PUBKEY = \"\"\n\n # Create a payment address for a user as needed:\n from bitmerchant.wallet import Wallet\n from myapp.settings import WALLET_PUBKEY\n\n def get_payment_address_for_user(user):\n user_id = user.id\n assert isinstance(user_id, (int, long))\n wallet = Wallet.deserialize(WALLET_PUBKEY)\n wallet_for_user = wallet.create_new_address_for_user(user.id)\n return wallet_for_user.to_address()\n\n.. _security:\n\nSecurity warning\n----------------\n\n\nBIP32 wallets have a vulnerability/bug that allows an attacker to recover the\nmaster private key when given a master public key and a publicly-derived\nprivate child. In other words:\n\n.. code-block:: python\n\n from bitmerchant.wallet import Wallet\n\n w = Wallet.new_random_wallet()\n child = w.get_child(0, is_prime=False) # public derivation of a private child\n w_pub = w.public_copy()\n master_public_key = w_pub.serialize_b58(private=False)\n private_child_key = child.serialize_b58(private=True)\n\nGiven ``master_public_key`` and ``private_child_key``, the steps to recover the\nsecret master private key (``w``) are as simple as a subtraction on the\nelliptic curve. This has been implemented as ``Wallet.crack_private_key``,\nbecause if it's possible to do this, then anyone should be able to do it so the\nattack is well known:\n\n.. code-block:: python\n\n public_master = Wallet.deserialize(master_public_key)\n private_child = Wallet.deserialize(private_child_key)\n private_master = public_master.crack_private_key(private_child)\n assert private_master == w # :(\n\nThis attack can be mitigated by these simple steps:\n\n#. NEVER give out your root master public key.\n#. When uploading a master public key to a webserver, always use a prime child\n of your master root.\n#. Never give out a private child key unless the user you're giving it to\n already has control of the parent private key (eg, for user-owned wallets).\n\nWhy \"always use a prime child of your master root\" in step 2? Because prime\nchildren use private derivation, which means they cannot be used to recover the\nparent private key (no easier than brute force, anyway).\n\nCreate a new wallet\n-------------------\n\nIf you haven't created a wallet yet, do so like this:\n\n**IMPORTANT** You must back up your wallet's private key, otherwise you won't\nbe able to retrieve the coins sent to your public addresses.\n\n.. code-block:: python\n\n from bitmerchant.wallet import Wallet\n\n my_wallet = Wallet.new_random_wallet()\n\n # Then back up your private key\n\n private_key = my_wallet.serialize()\n print(private_key)\n # Make sure that you can load your wallet successfully from this key\n wallet_test = Wallet.deserialize(private_key)\n assert my_wallet == wallet_test\n # If that assertion fails then open a ticket!\n # NOW WRITE DOWN THE PRIVATE KEY AND STORE IT IN A SECURE LOCATION\n\nNote that it's a good idea to supply some extra entropy to `new_random_wallet`\nin case your PRNG is compromised. You can accomplish this easily by banging on\nthe keyboard. Here's an example, yours should be *much* longer:\n\n.. code-block:: python\n\n from bitmerchant.wallet import Wallet\n\n wallet1 = Wallet.new_random_wallet('asdfasdfasdf')\n wallet2 = Wallet.new_random_wallet('asdfasdfasdf')\n assert(wallet1.get_private_key_hex() != wallet2.get_private_key_hex())\n\n # They're completely different\n\nBIP32 wallets (or hierarchical deterministic wallets) allow you to create child\nwallets which can only generate public keys and don't expose a private key to\nan insecure server. You should create a new prime child wallet for every\nwebsite you run (or a new wallet entirely), and perhaps a new prime child for\neach user (though that requires pre-generating a bunch of prime children\noffline, since you need the private key). Try to use prime children where\npossible (see `security`_).\n\nIt's a good idea to create at least *one* prime child wallet for use on your\nwebsite. The thinking being that if your website's wallet gets compromised\nsomehow, you haven't completely lost control because your master wallet is\nsecured on an offline machine. You can use your master wallet to move any funds\nin compromised child wallets to new child wallets and you'll be ok.\n\nLet's generate a new child wallet for your first website!\n\n.. code-block:: python\n\n # Lets assume you're loading a wallet from your safe private key backup\n my_wallet = Wallet.deserialize(private_key)\n\n # Create a new, public-only prime child wallet. Since you have the master\n # private key, you can recreate this child at any time in the future and don't\n # need to securely store its private key.\n # Remember to generate this as a prime child! See the security notice above.\n child = my_wallet.get_child(0, is_prime=True, as_private=False)\n\n # And lets export this child key\n public_key = child.serialize_b58(private=False)\n print(public_key)\n\nYou can store your public key in your app's source code, as long as you never\nreveal any private keys. See the `security`_ notice above.\n\nBe aware that if someone gets a hold of your public key then they can generate\nall of your subsequent child addresses, which means they'll know exactly how\nmany coins you have. The attacker cannot spend any coins, however, unless they\nare able to recover the private key (see `security`_).\n\nGenerating new public addresses\n-------------------------------\n\nBIP32 wallets allow you to generate public addresses without revealing your\nprivate key. Just pass in the user ID that needs a wallet:\n\n.. code-block:: python\n\n from bitmerchant.wallet import Wallet\n from myapp.settings import WALLET_PUBKEY # Created above\n\n master_wallet = Wallet.deserialize(WALLET_PUBKEY)\n user_wallet = master_wallet.create_new_address_for_user(user_id)\n payment_address = user_wallet.to_address()\n\nThis assumes that ``user_id`` is a unique positive integer and does not change\nfor the life of the user (and is less than 2,147,483,648). Now any payments\nreceived at ``payment_address`` should be credited to the user identified by\n``user_id``.\n\nStaying secure\n==============\n\nPublic Keys\n-----------\n\nPublic keys are mostly safe to keep on a public webserver. However, even though\na public key does not allow an attacker to spend any of your coins, you should\nstill try to protect the public key from hackers or curious eyes. Knowing the\npublic key allows an attacker to generate all possible child wallets and know\nexactly how many coins you have. This isn't terrible, but nobody likes having\ntheir books opened up like this.\n\nAs mentioned earlier, knowledge of a master public key and a non-prime private\nchild of that key is enough to be able to recover the master private key. Never\nreveal private keys to users unless they already own the master private parent.\n\nYour master public key can be used to generate a virtually unlimited number of\nchild public keys. Your users won't pay to your master public key, but instead\nyou'll use your master public key to generate a new wallet for each user.\n\nPrivate Keys\n------------\n\nYou must have the private key to spend any of your coins. If your private key\nis stolen then the hacker also has control of all of your coins. With a BIP32\nWallet, generating a new master wallet is one of the only times that you need\nto be paranoid (and you're not being paranoid if they really *are* out to get\nyou). Paranoia here is good because if anyone gets control of your master\nwallet they can spend all funds in all child wallets.\n\nYou should create your wallet on a computer that is not connected to the\ninternet. Ideally, this computer will *never* be connected to the internet\nafter you generate your private key. The safest way to do this is to run Ubuntu\non a livecd, install python and bitmerchant, and generate a new wallet.\n\nOnce you generate a new wallet you should write down the private key on a piece\nof paper (or print it out ...but can you *really* trust your printer?) and\nstore it in a secure location.\n\n.. code-block:: bash\n\n sudo apt-get install python\n sudo apt-get install pip\n\n pip install bitmerchant\n pip install ipython\n\n # Then launch the ipython shell\n ipython\n\nOnce inside your ipython shell, generate a new wallet:\n\n.. code-block:: python\n\n from bitmerchant.wallet import Wallet\n\n my_wallet = Wallet.new_random_wallet()\n\n # Then back up your private key\n\n private_key = my_wallet.serialize()\n print(private_key)\n # Write down this private key.\n # Double check it.\n # Then shut down the computer without connecting to the internet.\n\nMaster private key\n------------------\n\nYour master private key allows you to spend coins sent to any of your public\naddresses. Guard this with your life, and never put it on a computer that's\nconnected to the internet.\n\nMaster private keys must NEVER be put on the internet. They must NEVER be\nlocated on a computer that is even *connected* to the internet. The only key\nthat should be online is your PUBLIC key. Your private key should be written\ndown (yes, on paper) and stored in a safe location, or on a computer that is\nnever connected to the internet.\n\nSecurity wise, this is the most important part of generating secure public\npayment addresses. A master private key is the only way to retrieve the funds\npaid to a public address. You can use your master private key to generate the\nprivate keys of any child wallets, and then transfer those to a networked\ncomputer as necessary, if you want slightly smaller surface area for attacks.\n\nForthcoming versions of bitmerchant will allow you to generate transactions\noffline that you can safely transfer to a networked computer, allowing you to\nspend your child funds without ever putting a private key on a networked\nmachine.\n\nDevelopment\n===========\n\nI'd love for you to contribute to bitmerchant! If you can't write code, then\nplease open a ticket for feature requests or bugs you find!\n\nIf you can code and you'd like to submit a pull request, please be sure to\ninclude tests. This library is quite well tested and I intend to keep coverage\nabove 95% indefinitely.\n\nRewards may be given out to developers depending on the severity of bugs\nfound/patched. The donation addresses mentioned at the top of this document\nwill be used to fund rewards.\n\nTesting\n-------\n\nI use tox & travis-ci to test against all python versions >= 2.5. Locally,\nyou can use the `make test` target, which will only test against python-2.7.\nYou can, of course, call tox directly:\n\n.. code-block:: bash\n\n make setup\n tox\n tox -e py34\n tox -- tests.test_bip32:TestWallet\n\nNote that the full test suite on py-{2.5..3.4} takes about 5 minutes to run.\npypy and pypy3 are considerably slower at about 25 minutes, due to unoptimized\ncrypto operations.\n\nPackaging\n---------\n\nSee PACKAGING_\n\n.. _PACKAGING: https://raw.github.com/sbuss/bitmerchant/master/PACKAGING.md\n\n.. |Donate BTC| image:: https://raw.github.com/sbuss/bitmerchant/master/media/donation_btc_qr_code.gif\n.. |Donate DOGE| image:: https://raw.github.com/sbuss/bitmerchant/master/media/donation_doge_qr_code.gif", "description_content_type": null, "docs_url": null, "download_url": "https://github.com/sbuss/bitmerchant/tarball/v0.1.8", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/sbuss/bitmerchant", "keywords": null, "license": "MIT License", "maintainer": null, "maintainer_email": null, "name": "bitmerchant", "package_url": "https://pypi.org/project/bitmerchant/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/bitmerchant/", "project_urls": { "Download": "https://github.com/sbuss/bitmerchant/tarball/v0.1.8", "Homepage": "https://github.com/sbuss/bitmerchant" }, "release_url": "https://pypi.org/project/bitmerchant/0.1.8/", "requires_dist": [ "base58 (>=0.2.1)", "ecdsa (>=0.10)", "six (>=1.5.2)", "cachetools (>=1.1.1)" ], "requires_python": null, "summary": "Bitcoin/altcoin merchant tools", "version": "0.1.8" }, "last_serial": 1716730, "releases": { "0.1.8": [ { "comment_text": "", "digests": { "md5": "c2d0cb4a158fd0de1d8e61314d7ece0f", "sha256": "01f5584625e7988ce4d8a32527e1160eaa00265042e6db1f29b04398dafd88e0" }, "downloads": -1, "filename": "bitmerchant-0.1.8-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "c2d0cb4a158fd0de1d8e61314d7ece0f", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 28574, "upload_time": "2015-09-10T06:25:06", "url": "https://files.pythonhosted.org/packages/f0/fd/840712bffaa449023e9665d46c38541de509ae5b25ab865d75877437d3c7/bitmerchant-0.1.8-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "70d175987b137f2728d57ecb277e4786", "sha256": "fba4c2091084ed0b4f9faac0ebbba8d255c5ccd3a18e7f877ce13aab71649ddc" }, "downloads": -1, "filename": "bitmerchant-0.1.8.tar.gz", "has_sig": false, "md5_digest": "70d175987b137f2728d57ecb277e4786", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23420, "upload_time": "2015-09-10T06:25:13", "url": "https://files.pythonhosted.org/packages/a0/3c/3cc4b1f447cf0ea27c21a0e2e55adaf0064a8cd4b3294fb3c27ca27f6dd3/bitmerchant-0.1.8.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "c2d0cb4a158fd0de1d8e61314d7ece0f", "sha256": "01f5584625e7988ce4d8a32527e1160eaa00265042e6db1f29b04398dafd88e0" }, "downloads": -1, "filename": "bitmerchant-0.1.8-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "c2d0cb4a158fd0de1d8e61314d7ece0f", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 28574, "upload_time": "2015-09-10T06:25:06", "url": "https://files.pythonhosted.org/packages/f0/fd/840712bffaa449023e9665d46c38541de509ae5b25ab865d75877437d3c7/bitmerchant-0.1.8-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "70d175987b137f2728d57ecb277e4786", "sha256": "fba4c2091084ed0b4f9faac0ebbba8d255c5ccd3a18e7f877ce13aab71649ddc" }, "downloads": -1, "filename": "bitmerchant-0.1.8.tar.gz", "has_sig": false, "md5_digest": "70d175987b137f2728d57ecb277e4786", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23420, "upload_time": "2015-09-10T06:25:13", "url": "https://files.pythonhosted.org/packages/a0/3c/3cc4b1f447cf0ea27c21a0e2e55adaf0064a8cd4b3294fb3c27ca27f6dd3/bitmerchant-0.1.8.tar.gz" } ] }