{ "info": { "author": "Brenden Matthews", "author_email": "brenden@diddyinc.com", "bugtrack_url": null, "classifiers": [ "License :: Public Domain", "Operating System :: OS Independent", "Programming Language :: Python :: 3" ], "description": "[![Build Status](https://travis-ci.org/brndnmtthws/seed-otp.svg?branch=master)](https://travis-ci.org/brndnmtthws/seed-otp) [![Maintainability](https://api.codeclimate.com/v1/badges/679cd32dba7a27f9bb4d/maintainability)](https://codeclimate.com/github/brndnmtthws/seed-otp/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/679cd32dba7a27f9bb4d/test_coverage)](https://codeclimate.com/github/brndnmtthws/seed-otp/test_coverage) [![PyPI version](https://badge.fury.io/py/seed-otp.svg)](https://badge.fury.io/py/seed-otp)\n\n# seed-otp\n\n`seed-otp` is a Python-based one-time pad CLI tool for storing your Bitcoin seed\nmnemonic words securely using multi-factor auth.\n\n## Background\n\n### The Problem\n\nYou have an HD wallet such as a Trezor or Ledger for storing your Bitcoin,\nand you would like to store your seed mnemonic phrase. You may also\nwant to store multiple copies of your seed in different places.\nUnfortunately, if any one of those copies of your seed becomes compromised,\nanyone with access to the seed can now take all your coins, and buy\nthemselves\na lambo.\n\nNormally you would not need access to your seed mnemonic. However, should\nsomething happen to your wallet (perhaps you lose it, or it breaks), you may\nneed to restore the wallet using the seed phrase.\n\n### This Solution\n\nUse a [one-time pad](https://en.wikipedia.org/wiki/One-time_pad) with\n[multi-factor\nauthentication](https://en.wikipedia.org/wiki/Multi-factor_authentication).\n\nBy combining mult-factor auth (something you know plus something you have)\nand one-time pad encryption, you have a simple yet extremely hard to crack\nsolution. Your OTP key and seed mnemonic are stored separately, making it\nonerous to obtain both. If someone _does_ obtain either your mnemonic or OTP\nkey, you would have time to move your funds to a new wallet with a brand new seed and OTP key.\n\nYour auth factors are:\n\n- **Something you know**: A one-time pad key which you have stored securely in\n a password manager, which is locked with a password only you know. The\n password DB is backed up securely.\n- **Something you have**: An encrypted mnemonic seed phrase stored on archival\n paper or another long term physical cold storage device. The phrase itself\n looks like a normal mnenomic phrase, which provides plausible deniability,\n and does not indicate to anyone who might find the phrase _how_ it's\n actually used.\n\n### Caveats, Limitations, Gotchas\n\n- To use this tool, you need to enter the seed words into a computer. If your\n computer is compromised, someone could still use a keylogger or other tool to\n capture the seed mnemonic. Only use this tool if you trust the computer you\n are using.\n\n### Other Solutions\n\nThere are a variety of other solutions to this problem, some of which may be\nmore appropriate for your needs. Let's go over some of the alternatives and\ndiscuss why they might not be appropriate:\n\n1. Custody with a third party, such as Coinbase.\n - The main problem with any third party custody service is that you must\n place complete trust in that third party.\n - Custody providers are not immune to crime, theft, rogue employees,\n mistakes, going out of business, or government intervention. _Rekt_.\n2. The Horcrux design (using a multi-signature scheme).\n - This pattern is based on the idea of storing small pieces of your seed\n phrase in several different places, much like Voldemort did with his soul\n in Harry Potter.\n - While it's not impossible to do this on your own, it's logistically\n tricky and prone to error.\n - There is at least one company which provides this option as a service,\n but at the time of writing they're asking for several thousand dollars\n per year in subscription fees, an amount that is both absurd and out of\n reach for normal people. _Rekt_ because you have no money left.\n3. Storing your seed phrase in a super secret place and hoping nobody finds\n it.\n - This is equivalent to burying a chest full of treasure in your backyard\n and hoping nobody looks there. _Rekt_ when your neighbour buys a metal\n detector.\n4. Store the seed phares itself using a password manager.\n - The main downside is that you do not have multi-factor auth: if someone\n gains access to your password manager, you will be _rekt_.\n\n## Quickstart\n\n### Checklist\n\nBefore using this tool, you should have a few things:\n\n- [x] Get a decent hardware wallet from a reputable vendor. 2 popular options\n are [Trezor](https://trezor.io/) and [Ledger](https://www.ledger.com/).\n- [x] Get a password manager, and learn to use it (if you haven't already). A\n few good options are [KeepPassX](https://www.keepassx.org/),\n [1Password](https://1password.com/), or [BitWarden](https://bitwarden.com/).\n Make sure your passwords are backed up, and test the restore process.\n- [x] Figure out a good way to store your mnemonic seed phrase, such as using\n archival paper or a metal seed storage product (check out [@lopp's stress\n test\n here](https://medium.com/@lopp/metal-bitcoin-seed-storage-stress-test-21f47cf8e6f5)).\n- [x] Have a safe place to store the seed mnemonic, such as in an actual safe,\n or a safe deposit box.\n- [x] Make sure you have a secure computer to run the software. It should be\n running an up-to-date and secure OS. Avoid using any computers which might be\n controlled by third parties (such as a work computer, or your friend's\n computer). If you want to be extra safe, consider using a [privacy OS such as\n Tails](https://tails.boum.org/)\n\n### Install from PyPI\n\n```ShellSession\n$ pip install seed-otp\n```\n\n### Generate an OTP key\n\n```ShellSession\n$ seed-otp generate 12\n{\n \"otp-key\": \"AAwCnwGIAe0EWABWAI4AkAMjAFQBLgZjB1T1PJtz\",\n \"success\": true\n}\n```\n\nStore the key above in your password management tool.\n\n### Encode your seed mnemonic using the OTP\n\n```ShellSession\n$ seed-otp encrypt AAwCnwGIAe0EWABWAI4AkAMjAFQBLgZjB1T1PJtz abandon ability able about above absent absorb abstract absurd abuse access accident\n{\n \"encrypted-words\": [\n \"fault\",\n \"couple\",\n \"digital\",\n \"merge\",\n \"area\",\n \"bar\",\n \"barrel\",\n \"grab\",\n \"argue\",\n \"cheap\",\n \"soap\",\n \"typical\"\n ]\n}\n```\n\nStore the phrase above in your safe place.\n\n### Decode your seed mnemonic using the OTP\n\n```ShellSession\n$ seed-otp decrypt AAwCnwGIAe0EWABWAI4AkAMjAFQBLgZjB1T1PJtz fault couple digital merge area bar barrel grab argue cheap soap typical\n{\n \"decrypted-words\": [\n \"abandon\",\n \"ability\",\n \"able\",\n \"about\",\n \"above\",\n \"absent\",\n \"absorb\",\n \"abstract\",\n \"absurd\",\n \"abuse\",\n \"access\",\n \"accident\"\n ]\n}\n```\n\n## Synopsis\n\n Usage: seed-otp [OPTIONS] COMMAND [ARGS]...\n\n Options:\n -h, --help Show this message and exit.\n\n Commands:\n check-key Check OTP key for encoding or checksum errors.\n decrypt Decrypt seed words using an OTP key.\n encrypt Encrypt seed words using an OTP key.\n generate Generate a secure OTP key for up to NUM_WORDS number of words.\n\n## Implementation Details\n\n### OTP Key\n\nThe OTP key is a URL-safe base64 encoded key (without padding) composed of N\nsubkeys, where N is the number of keys specified at creation time. The values\nare stored as big-endian short unsigned integers (2-bytes each). The last 4\nbytes of the OTP key is the first 4 bytes of the SHA256 digest of the\npreceeding bytes.\n\n 0 1\n 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n | Number of Keys |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n \\ /\n / Keylist (variable length) \\\n \\ /\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n | |\n + Checksum +\n | |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\nBIP-0039 uses 11 bits per word, but in this scheme we're using 16 bits per\nword. This is mainly for simplicity, with the trade-off of using more bytes.\nIt also allows the possibilty of using larger wordlists (of up to 65536\nwords).\n\n### Encrypting/decrypting words\n\nBelow is some pseudocode for encrypting/decrypting. Assume that the words and\nkeys are mapped to integers representing an index position in the wordlist.\n\nTo encrypt a word, the algorithm is as follows:\n\n ciphertext = (word + key) mod 2048\n\nTo decrypt a word, do the following:\n\n word = (ciphertext - key) mod 2048\n\nYou could perform the encryption/decryption using pen and paper if you feel\nthe need to do so. This would prevent the necessity of typing your seed words\ninto a computer. Naturally, you could also generate your own keys and store\nthose offline as well. For practical purposes, however, this is probably\nunnecessary.\n\n## Tip jar\n\n- BTC: 3EEAE1oKEMnmHGU5Qxibv9mBQyNnes8j8N", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/brndnmtthws/seed-otp", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "seed-otp", "package_url": "https://pypi.org/project/seed-otp/", "platform": "", "project_url": "https://pypi.org/project/seed-otp/", "project_urls": { "Homepage": "https://github.com/brndnmtthws/seed-otp" }, "release_url": "https://pypi.org/project/seed-otp/0.1.0/", "requires_dist": null, "requires_python": ">=3.5", "summary": "Python-based Bitcoin seed mnemonic one-time pad tool", "version": "0.1.0" }, "last_serial": 4561650, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "481d274cd25e4697c6858eb5fe5222f6", "sha256": "d1978c283aee97efcb86b47ee0c944d739045bd4bdd4c15875ff0344924560ef" }, "downloads": -1, "filename": "seed-otp-0.1.0.tar.gz", "has_sig": false, "md5_digest": "481d274cd25e4697c6858eb5fe5222f6", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.5", "size": 69942, "upload_time": "2018-12-05T00:13:55", "url": "https://files.pythonhosted.org/packages/58/eb/5a3e9ed6b27f4b1406c69493afed4a4349a7e447109167465e9249b0b05f/seed-otp-0.1.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "481d274cd25e4697c6858eb5fe5222f6", "sha256": "d1978c283aee97efcb86b47ee0c944d739045bd4bdd4c15875ff0344924560ef" }, "downloads": -1, "filename": "seed-otp-0.1.0.tar.gz", "has_sig": false, "md5_digest": "481d274cd25e4697c6858eb5fe5222f6", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.5", "size": 69942, "upload_time": "2018-12-05T00:13:55", "url": "https://files.pythonhosted.org/packages/58/eb/5a3e9ed6b27f4b1406c69493afed4a4349a7e447109167465e9249b0b05f/seed-otp-0.1.0.tar.gz" } ] }