{ "info": { "author": "Hans-Peter Jansen", "author_email": "hpj@urpla.net", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7" ], "description": "Summary\n-------\n\nEncrypted plain file keyring backend for use with the\n[keyring](https://pypi.python.org/pypi/keyring) package.\n\nDescription\n-----------\nThe project is mainly targeted on a sufficiently secure storage for plain text\npasswords (keyring) in a simple portable file, where the default keyring storage\nimplementation of a usual desktop environment doesn't fit.\n\nCryptography\n------------\nThe keyring is secured with a keyring password. A raw\n`Argon2($argon2id$v=19$m=65536,t=15,p=2)` hash is generated from the keyring\npassword, which is used as a key for encryption of plaintext passwords in one of\nthe supported authenticated AES encryption schemes (CCM, EAX, GCM, OCB), where\nGCM is the default. The resulting encrypted data is persisted, together with the\nArgon2 salt, nonce and MAC. This value is stored with a service/userid reference\nin a text file (.ini format). The service/userid is taken into account as\nassociated data for MAC calculation.\n\nInitially, a static reference value, treated as a password is stored as well,\nand this value is used for verification of the keyring password in subsequent\naccesses.\n\nAttack surface\n--------------\nThe static reference value allow some form of attack, as it encrypts a well\nknown value. Hopefully, the Argon2 hash, combined with the authenticated AES\nencryption scheme raises the effort to break the key sufficiently high.\n\nThe Argon2 parameterization is chosen in a way, that usual desktop and server\nsystems as of today (2017) have to process a significant CPU and Memory load\nin order to calculate the hashes, which renders brute force attacks impractical.\n\nThe authenticated AES encryption scheme prevents tampering with the encrypted\ndata as well as its reference (service/userid).\n\nQuick start guide\n-----------------\n\nIn order to get you started, you will need to have a `python3` environment\nand `git` available (preferably on a linux system).\n\nYou might want to provide the python packages [argon2-cffi](https://pypi.python.org/pypi/argon2_cffi), [keyring](https://pypi.python.org/pypi/keyring), [pycryptodome](https://pypi.python.org/pypi/pycryptodome)\nand their dependencies (most notably [SecretStorage](https://pypi.python.org/pypi/SecretStorage) and [cryptography](https://pypi.python.org/pypi/cryptography)) with your\nsystem package management, or use a local venv, but that will depend on a\nproperly working C compiler and some development packages installed\n(`python-devel` and `openssl-devel` at least).\n\nSetup package and environment\n-----------------------------\n\n```\n$ git clone https://github.com/frispete/keyrings.cryptfile\n$ cd keyrings.cryptfile\n$ pyvenv env\n$ . env/bin/activate\n(env) $ pip install -e .\n```\n\nThe last command should succeed without errors, some development packages might\nbe missing otherwise.\n\nExample session\n---------------\n\nCreate an encrypted keyring, and store a test password into it. The process asks\nfor the keyring password itself, that protects your stored keyring values.\n\n```\n(env) $ python3\nPython 3.4.5 (default, Jul 03 2016, 12:57:15) [GCC] on linux\nType \"help\", \"copyright\", \"credits\" or \"license\" for more information.\n>>> from keyrings.cryptfile.cryptfile import CryptFileKeyring\n>>> kr = CryptFileKeyring()\n>>> kr.set_password(\"service\", \"user\", \"secret\")\nPlease set a password for your new keyring: ******\nPlease confirm the password: ******\n>>> ^d\n```\n\nNow retrieve the stored secret from the keyring again:\n\n```\n(env) $ python3\nPython 3.4.5 (default, Jul 03 2016, 12:57:15) [GCC] on linux\nType \"help\", \"copyright\", \"credits\" or \"license\" for more information.\n>>> from keyrings.cryptfile.cryptfile import CryptFileKeyring\n>>> kr = CryptFileKeyring()\n>>> kr.get_password(\"service\", \"user\")\nPlease enter password for encrypted keyring: ******\n'secret'\n>>> ^d\n```\n\nNote, that the KDF delays the `{set,get}_password()` operations for a few seconds\n(~1 sec. on a capable system).\n\nResult\n------\n\nThe resulting file might look similar to:\n```\n(env) $ cat ~/.local/share/python_keyring/cryptfile_pass.cfg\n[keyring_2Dsetting]\npassword_20reference =\n eyJtYWMiOiAiWmVHU2lBalZ5WHd6Vmg3K2Z6TGx2UT09IiwgIm5vbmNlIjogIjB0b2dKa3RYdmdY\n TVpEU1F1QkFOZFE9PSIsICJzYWx0IjogInZ2dFYzN2JvWnVLRTQzVHJ6dGd6YVE9PSIsICJkYXRh\n IjogIk1UdnRzYUZ6OHdSaUZYbFBHOWZmL2dQZ0dmL3ROOG05In0=\nscheme = [Argon2] AES128.GCM\nversion = 1.0\n\n[service]\nuser =\n eyJtYWMiOiAiaTJ4MWhNVGJ1S0pTZExYSXQwR0dqUT09IiwgIm5vbmNlIjogIlJ5YU1DZmkyZ0JE\n NStlNHN6MGpQRWc9PSIsICJzYWx0IjogIjlIM1hJbDVhZmRZaVhkTUZyTWNOV2c9PSIsICJkYXRh\n IjogImhNVC9LaTRYIn0=\n```\n\nThe values can be decoded like this:\n\n```\n(env) $ python3\n>>> import base64\n>>> base64.decodebytes(b\"\"\"\n... eyJtYWMiOiAiaTJ4MWhNVGJ1S0pTZExYSXQwR0dqUT09IiwgIm5vbmNlIjogIlJ5YU1DZmkyZ0JE\n... NStlNHN6MGpQRWc9PSIsICJzYWx0IjogIjlIM1hJbDVhZmRZaVhkTUZyTWNOV2c9PSIsICJkYXRh\n... IjogImhNVC9LaTRYIn0=\"\"\")\nb'{\"mac\": \"i2x1hMTbuKJSdLXIt0GGjQ==\",\n \"nonce\": \"RyaMCfi2gBD5+e4sz0jPEg==\",\n \"salt\": \"9H3XIl5afdYiXdMFrMcNWg==\",\n \"data\": \"hMT/Ki4X\"}'\n```\n\nDiscussion\n----------\n\nThe items of the json dict constitute the encryption parameters and value. In\ntheory, it should be sufficiently **hard** to get back to the plain value of\n**data** without knowledge of the password. Due to the association of the values\nreference (`service` and `user` here) with the authenticated encryption,\nmodifications of values reference are detected/rejected as well.\n\nThe class hierarchy is inherited from the keyrings.alt project, which is not\nexactly easy to follow. The most interesting parts are in\n*keyrings/cryptfile/cryptfile.py*, which is quite concise itself, even if you're\nnot fluent in python.\n\nIn order to control this process any further, you might want to subclass\n`CryptFileKeyring` and/or `PlaintextKeyring`.\n\nYou can avoid the interactive getpass() request for the keyring password by\nsupplying `kr.keyring_key = \"your keyring password\"` before calling any other\nmethods on the keyring.", "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/frispete/keyrings.cryptfile", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "keyrings.cryptfile", "package_url": "https://pypi.org/project/keyrings.cryptfile/", "platform": "", "project_url": "https://pypi.org/project/keyrings.cryptfile/", "project_urls": { "Homepage": "https://github.com/frispete/keyrings.cryptfile" }, "release_url": "https://pypi.org/project/keyrings.cryptfile/1.3.4/", "requires_dist": null, "requires_python": ">=3.5", "summary": "Encrypted file keyring backend", "version": "1.3.4" }, "last_serial": 4984890, "releases": { "1.2": [ { "comment_text": "", "digests": { "md5": "f08c8f213ed638c316f14f848cae742a", "sha256": "94e77611c66619708429d59b9de5dfd787c14e4d4beee9bd45acb0aa88fc7c70" }, "downloads": -1, "filename": "keyrings.cryptfile-1.2.tar.gz", "has_sig": false, "md5_digest": "f08c8f213ed638c316f14f848cae742a", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7", "size": 16153, "upload_time": "2018-05-18T11:58:56", "url": "https://files.pythonhosted.org/packages/12/dd/c2794a16726baed4d21b0d6911cf5b9c6794044d4d751540b4f3d83bb18c/keyrings.cryptfile-1.2.tar.gz" } ], "1.2.1": [ { "comment_text": "", "digests": { "md5": "aaf2167f0334e2d57f2c8e4a421fef42", "sha256": "bb7d05c6420cd6b3fbf0dea27ea61d74ba53c1e2f4cd0d2001555a366a9db488" }, "downloads": -1, "filename": "keyrings.cryptfile-1.2.1.tar.gz", "has_sig": false, "md5_digest": "aaf2167f0334e2d57f2c8e4a421fef42", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7", "size": 16275, "upload_time": "2018-05-19T10:34:25", "url": "https://files.pythonhosted.org/packages/9c/b6/76fcbcbc67d82cd9e6ed1e50df12cd7a07e0d53506f5acb4932ce9578fb8/keyrings.cryptfile-1.2.1.tar.gz" } ], "1.3": [ { "comment_text": "", "digests": { "md5": "e88923b1f62f2cfb06a1069f729721a9", "sha256": "aac8478090e6cb77e668188f3ca825df24a3781d127af44187f07a5f388354fa" }, "downloads": -1, "filename": "keyrings.cryptfile-1.3.tar.gz", "has_sig": false, "md5_digest": "e88923b1f62f2cfb06a1069f729721a9", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7", "size": 17224, "upload_time": "2018-10-09T10:06:11", "url": "https://files.pythonhosted.org/packages/d1/a8/ad688c3e39f531255759860e5f890c452f8c9a46bf38bf73f75b9d623eac/keyrings.cryptfile-1.3.tar.gz" } ], "1.3.1": [ { "comment_text": "", "digests": { "md5": "f5ae498242b976bd16bf01c8d681668d", "sha256": "3afb43c859e6de3f5e39473db51758b8b8cd46f31219794124e9346a83573f02" }, "downloads": -1, "filename": "keyrings.cryptfile-1.3.1.tar.gz", "has_sig": false, "md5_digest": "f5ae498242b976bd16bf01c8d681668d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16732, "upload_time": "2019-01-04T16:08:38", "url": "https://files.pythonhosted.org/packages/cf/4d/ca8bf83dd593f553410b001c1e70f324d555abac06b1a86121ac1a357474/keyrings.cryptfile-1.3.1.tar.gz" } ], "1.3.2": [ { "comment_text": "", "digests": { "md5": "bc42333523f16f3d2077b871d03d0a63", "sha256": "e565c485eb3fc6f92eceaef485cddd88b5d31be7809e4eacce96a1f2bc949bef" }, "downloads": -1, "filename": "keyrings.cryptfile-1.3.2.tar.gz", "has_sig": false, "md5_digest": "bc42333523f16f3d2077b871d03d0a63", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7", "size": 17296, "upload_time": "2019-01-04T17:04:03", "url": "https://files.pythonhosted.org/packages/a0/13/7ae834e5594079d6489c37d07590174bc9c9fa66e87c526dd8bccc767ae7/keyrings.cryptfile-1.3.2.tar.gz" } ], "1.3.3": [ { "comment_text": "", "digests": { "md5": "9e2032251766c86285b2ddd3056e9121", "sha256": "a27c613885b57b7e9c97623dbfaff4cc5a0ebb4add83b292a16bf658b5bfdc45" }, "downloads": -1, "filename": "keyrings.cryptfile-1.3.3.tar.gz", "has_sig": false, "md5_digest": "9e2032251766c86285b2ddd3056e9121", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7", "size": 17340, "upload_time": "2019-01-06T17:41:15", "url": "https://files.pythonhosted.org/packages/82/ef/2a71ad13d9fb77e70394e1d9bf9cf9c2de9939e580b0a5c4c69fabdb0f6b/keyrings.cryptfile-1.3.3.tar.gz" } ], "1.3.4": [ { "comment_text": "", "digests": { "md5": "b891c2e35f24391652beb4d0bab9a8e5", "sha256": "8d6f9c28c9bec5e7fc0be7e5d0219efba4849180470e3157dbf90b099eb68fa7" }, "downloads": -1, "filename": "keyrings.cryptfile-1.3.4.tar.gz", "has_sig": false, "md5_digest": "b891c2e35f24391652beb4d0bab9a8e5", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.5", "size": 17317, "upload_time": "2019-03-25T22:17:21", "url": "https://files.pythonhosted.org/packages/d0/e7/35c4c8321421a5d3525064b508f8576dd3e36e3ba305c9e23a7e2b66c44d/keyrings.cryptfile-1.3.4.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "b891c2e35f24391652beb4d0bab9a8e5", "sha256": "8d6f9c28c9bec5e7fc0be7e5d0219efba4849180470e3157dbf90b099eb68fa7" }, "downloads": -1, "filename": "keyrings.cryptfile-1.3.4.tar.gz", "has_sig": false, "md5_digest": "b891c2e35f24391652beb4d0bab9a8e5", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.5", "size": 17317, "upload_time": "2019-03-25T22:17:21", "url": "https://files.pythonhosted.org/packages/d0/e7/35c4c8321421a5d3525064b508f8576dd3e36e3ba305c9e23a7e2b66c44d/keyrings.cryptfile-1.3.4.tar.gz" } ] }