{"id":13697960,"url":"https://github.com/mcdallas/cryptotools","last_synced_at":"2025-05-07T15:45:21.611Z","repository":{"id":44341064,"uuid":"119552891","full_name":"mcdallas/cryptotools","owner":"mcdallas","description":null,"archived":false,"fork":false,"pushed_at":"2024-06-29T19:34:37.000Z","size":392,"stargazers_count":206,"open_issues_count":5,"forks_count":80,"subscribers_count":16,"default_branch":"master","last_synced_at":"2024-12-19T02:07:42.764Z","etag":null,"topics":["bitcoin","cryptography","ecdsa","elliptic-curves","rsa"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mcdallas.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-01-30T15:11:38.000Z","updated_at":"2024-12-12T17:04:55.000Z","dependencies_parsed_at":"2024-11-18T07:04:44.923Z","dependency_job_id":null,"html_url":"https://github.com/mcdallas/cryptotools","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcdallas%2Fcryptotools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcdallas%2Fcryptotools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcdallas%2Fcryptotools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcdallas%2Fcryptotools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mcdallas","download_url":"https://codeload.github.com/mcdallas/cryptotools/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231449692,"owners_count":18378431,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bitcoin","cryptography","ecdsa","elliptic-curves","rsa"],"created_at":"2024-08-02T18:01:06.928Z","updated_at":"2024-12-27T07:08:32.522Z","avatar_url":"https://github.com/mcdallas.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"About this repo\n---------------\n\nBarebones Python 3.6+ implementation (no dependencies/standard lib only) of some common cryptographic functions for educational purposes.\nFeel free to fork the repo and play around with it. Performance is ..abysmal but otherwise it works fine. Please do not\nuse this for anything serious because I am not a security expert.\n\n\nInstall\n-------\n\n.. code-block:: bash\n\n    $ pip install git+https://github.com/mcdallas/cryptotools.git@master#egg=cryptotools\n\n\nExamples\n--------\n\nHD Wallets\n\n.. code-block:: Python\n\n    from cryptotools.BTC import Xprv\n\n    \u003e\u003e\u003e m = Xprv.from_mnemonic('impulse prize erode winner pupil fun off addict ...')\n    \u003e\u003e\u003e m.encode()\n    'xprv9s21ZrQH143K38bNJiHY54kkjio8o6aw3bRjCbzi8KgRxNy98avUribz1wk85ToSUV2VwVuc73NJWc2YGwpMtqz7bBFUh9Q77RtJeuh2zvy'\n\n    \u003e\u003e\u003e m/44/0/0/0\n    Xprv(path=m/44/0/0/0, key=L1WKXyMwKnp8wPwAtjwiKWunACY5RSUXAzmS6jDRRHcHnDbeRiKu)\n\n    \u003e\u003e\u003e m/0./123/5.  # Use floats for hardened path, alternative is // e.g m//0/123//5\n    Xprv(path=m/0h/123/5h, key=L3qskbdzgNu4kwjx2QU63q59khpEHVaSbqd2Pc268Jngiha6mbfQ)\n\n    \u003e\u003e\u003e M = m.to_xpub()\n\n    \u003e\u003e\u003e (m/123/456).to_xpub() == M/123/456\n    True\n\n    \u003e\u003e\u003e (m/44./0./0./0/0).address('P2PKH')  # bip44\n    '1BTYXdyrBh1yRCDpqyDhoQG896bnzqtaPz'\n\n    \u003e\u003e\u003e (m/84./0./0./0/0).address('P2WPKH')  # bip84\n    'bc1qjnx8cq32z2t72tsmuwql3wz22lywlpcm3w52lk'\n\n\nBIP39 checksum\n\nSay you lost the first of your 12 mnemonic words and you want to filter out the possible mnemonics from 2048 to 128 by veryfing the checksum\n\n.. code-block:: Python\n\n    from cryptotools.BTC.HD import check, WORDS\n\n    phrase = \"{x} decrease enjoy credit fold prepare school midnight flower wrong false already\"\n\n    for word in WORDS:\n        mnemonic = phrase.format(x=word)\n        if check(mnemonic):\n            print(mnemonic)\n\n\nSign/Verify message:\n\n.. code-block:: Python\n\n    import secrets\n    from cryptotools.ECDSA.secp256k1 import generate_keypair, Message\n\n    private, public = generate_keypair()\n\n    \u003e\u003e\u003e message = Message(secrets.token_bytes(32))\n    \u003e\u003e\u003e sig1 = message.sign(private)          # ECDSA\n    \u003e\u003e\u003e sig2 = message.sign_schnorr(private)  # Schnorr\n    \u003e\u003e\u003e message.verify(sig1, public)\n    True\n    \u003e\u003e\u003e message.verify(sig2, public)\n    True\n\n\nVerify a transaction:\n\n.. code-block:: Python\n\n    from cryptotools.BTC import Transaction\n\n    tx = Transaction.get('454e575aa1ed4427985a9732d753b37dc711675eb7c977637b1eea7f600ed214')\n\n    \u003e\u003e\u003e tx\n    Transaction(inputs=1, outputs=2)\n\n    \u003e\u003e\u003e tx.outputs\n    [Output(type=P2SH, value=0.0266 BTC),\n     Output(type=P2WSH, value=0.00468 BTC)]\n\n    \u003e\u003e\u003e tx.verify()  # this runs the bitcoin script\n    True\n\n\nCreate a transaction and submit it automatically\n\n.. code-block:: Python\n\n    import os\n    os.environ['CRYPTOTOOLS_NETWORK'] = 'test'  # sets network to testnet (before library import)\n\n    from cryptotools.BTC import PrivateKey, send\n\n    key = PrivateKey.from_hex('mysupersecretkey')\n\n    \u003e\u003e\u003e send(source='n4SbPWR6EmQMsWaQVYYFXiJgjweGKE4XnQ', to={'n2NGrooSecJaiD6ssp4YqFoj9eZ7GrCJ66': 0.46}, fee=0.01, private=key)\n    '907b92969cb3a16ddb45591bf2530f177b7f10cef4e62c331596a84f66c3b8c3'  # txid\n\n\nCreate and broadcast manually\n\n.. code-block:: Python\n\n    import os\n    os.environ['CRYPTOTOOLS_NETWORK'] = 'test'\n\n    from cryptotools.BTC import PrivateKey, Address\n\n    private = PrivateKey.from_hex('mysupersecretkey')\n    address = Address('n2NGrooSecJaiD6ssp4YqFoj9eZ7GrCJ66')\n\n    \u003e\u003e\u003e address.balance()\n    0.55\n\n    \u003e\u003e\u003e send_to = {'n4SbPWR6EmQMsWaQVYYFXiJgjweGKE4XnQ': 0.1, 'n2NGrooSecJaiD6ssp4YqFoj9eZ7GrCJ66': 0.4}\n    \u003e\u003e\u003e tx = address.send(to=send_to, fee=0.05, private=private)\n\n    \u003e\u003e\u003e tx\n    Transaction(inputs=1, outputs=2)\n\n    \u003e\u003e\u003e tx.inputs[0].is_signed()\n    True\n\n    \u003e\u003e\u003e tx.verify()  # Make sure transaction is valid before broadcasting\n    True\n\n    \u003e\u003e\u003e tx.broadcast()\n    'Transaction Submitted'\n\nCreate keys/addresses (including segwit)\n\n.. code-block:: Python\n\n    from cryptotools.BTC import generate_keypair, push, script_to_address, OP\n    private, public = generate_keypair()\n\n    \u003e\u003e\u003e private.hex()\n    'de4f177274d29f88a5805333e10525f5dd41634455dfadc8849b977802481ccd'\n\n    \u003e\u003e\u003e private.wif(compressed=False)\n    '5KWCAYLo35uZ9ibPTzTUDXESTE6ne8p1eXviYMHwaoS4tpvYCAp'\n\n    \u003e\u003e\u003e public.hex()\n    '047e30fd478b44869850352daef8f5f7a7b5233044018d465431afdc0b436c973e8df1244189d25ae73d90c90cc0f998eb9784adecaecc46e8c536d7d6845fa26e'\n\n    \u003e\u003e\u003e public.to_address('P2PKH')\n    '19dFXDxiD4KrUTNFfcgeekFpQmUC553GzW'\n\n    # Simple \u003ckey\u003e \u003cOP_CHECKSIG\u003e script\n    \u003e\u003e\u003e script = push(public.encode(compressed=True)) + OP.CHECKSIG.byte\n    \u003e\u003e\u003e script_to_address(script, 'P2WSH')\n    'bc1q8yh8l8ft3220q328hlapqhflpzy6xvkq6u36mctk8gq5pyxm3rwqv5h5dg'\n\n    # nested P2WSH into P2SH -- use with caution\n    \u003e\u003e\u003e script_to_address(script, 'P2WSH-P2SH')\n    '34eBzenHJEdk5PK9ojuuBZvCRtNhvvysYZ'\n\n.. code-block:: Python\n\n    from cryptotools.ECDSA.secp256k1 import CURVE, PrivateKey\n    private = PrivateKey.random()\n\n    \u003e\u003e\u003e private.int()\n    8034465994996476238286561766373949549982328752707977290709076444881813294372\n\n    \u003e\u003e\u003e public = private.to_public()\n    \u003e\u003e\u003e public\n    PublicKey(102868560361119050321154887315228169307787313299675114268359376451780341556078, 83001804479408277471207716276761041184203185393579361784723900699449806360826)\n\n    \u003e\u003e\u003e public.point in CURVE\n    True\n\n    \u003e\u003e\u003e public.to_address('P2WPKH')\n    'bc1qh2egksgfejqpktc3kkdtuqqrukrpzzp9lr0phn'\n\n\nConfiguration\n--------\n\nBy default the library communicates with the bitcoin network (for fetching transactions) via a block \nexplorer but as an alternative you can use a bitcoin node via it's RPC interface. Just set the following \nenviromental variables\n\n.. code-block:: bash\n\n    CRYPTOTOOLS_BACKEND=rpc\n    CRYPTOTOOLS_RPC_HOST=localhost\n    CRYPTOTOOLS_RPC_PORT=8332\n\nand optionally\n\n.. code-block:: bash\n\n    CRYPTOTOOLS_RPC_USER=myuser\n    CRYPTOTOOLS_RPC_PW=mypassword\n\n\nto switch the network to Testnet set\n\n.. code-block:: bash\n\n    CRYPTOTOOLS_NETWORK=test\n\n\nto run tests\n\n.. code-block:: bash\n\n   $ python -m unittest\n\nfrom the project directory\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcdallas%2Fcryptotools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmcdallas%2Fcryptotools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcdallas%2Fcryptotools/lists"}