{"id":15639986,"url":"https://github.com/ricmoo/pyscrypt","last_synced_at":"2025-05-05T03:26:05.876Z","repository":{"id":14512695,"uuid":"17226379","full_name":"ricmoo/pyscrypt","owner":"ricmoo","description":"Pure-Python implementation of Scrypt PBKDF and scrypt file format library.","archived":false,"fork":false,"pushed_at":"2022-07-02T03:25:26.000Z","size":317,"stargazers_count":81,"open_issues_count":4,"forks_count":22,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-15T11:52:43.623Z","etag":null,"topics":["python","scrypt"],"latest_commit_sha":null,"homepage":"","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/ricmoo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-02-26T21:41:36.000Z","updated_at":"2024-12-01T05:45:38.000Z","dependencies_parsed_at":"2022-07-15T18:00:35.523Z","dependency_job_id":null,"html_url":"https://github.com/ricmoo/pyscrypt","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ricmoo%2Fpyscrypt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ricmoo%2Fpyscrypt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ricmoo%2Fpyscrypt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ricmoo%2Fpyscrypt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ricmoo","download_url":"https://codeload.github.com/ricmoo/pyscrypt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252431517,"owners_count":21746869,"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":["python","scrypt"],"created_at":"2024-10-03T11:29:33.292Z","updated_at":"2025-05-05T03:26:05.845Z","avatar_url":"https://github.com/ricmoo.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"pyscrypt\n========\n\nA very simple, pure-Python implementation of the scrypt password-based key derivation function and scrypt file format libraries.\n\n### Features\n\n\n- Pure Python (no external dependancies)\n- Python 2.x and 3.x support (see below for Python 3 details)\n\n--\n\n**The sample code in this documentation is for Python 2.x. For Python 3.x, see the Python 3 section below.**\n\n\n\n\nAPI\n===\n\n### scrypt PBKDF hash\n\n\nThe scrypt algorithm is a password-based key derivation function, which takes in several parameters to adjust the difficulty and returns a string of bytes. This is useful for transforming passwords into a target length, while at the same time increaing the cost of attempting to brute-froce guess a password.\n\n* `password` - a passowrd\n* `salt` - a cryptographic salt\n* `N` - general work factor\n* `r` - memory cost\n* `p` - computation cost (parallelization factor)\n* `dkLen` - the output length (in bytes) to return\n\n\n```python\nimport pyscrypt\n\nhashed = pyscrypt.hash(password = \"correct horse battery staple\", \n                       salt = \"seasalt\", \n                       N = 1024, \n                       r = 1, \n                       p = 1, \n                       dkLen = 32)\nprint hashed.encode('hex')\n```\n\n### Write a scrypt Encrypted File\n\nWhen writing a file the `N`, `r` and `p` parameters are required. The `salt` parameter is optional, and if omitted will be generated from _urandom_.\n\n```python\nimport pyscrypt\n\nwith pyscrypt.ScryptFile('filename.scrypt', \"password\", N = 1024, r = 1, p = 1) as f:\n    f.write(\"Hello World\")\n```\n\nTo write to a file-like object without the context manager, it is important to either close the ScryptFile manually or to call finalize to ensure the footer gets flushed:\n\n```python\nimport pyscrypt\nimport StringIO\n\noutput = StringIO.StringIO()\nsf = pyscrypt.ScryptFile(output, \"pass123\", 1024, 1, 1)\nsf.write(\"Hello world\")\nsf.finalize()\n\noutput.seek(0)\nencrypted = output.read()\n```\n\n### Read a scrypt Encrypted File\n\n```python\nimport pyscrypt\n\n# Read the entire contents\nwith pyscrypt.ScryptFile('filename.scrypt', password = \"password\") as f:\n    print f.read()\n\n# Iterate over each line\nwith pyscrypt.ScryptFile('filename.scrypt', password = \"password\") as f:\n    for line in f:\n        print line\n\n    # Ensure the integrity of the file after completely read\n    print f.valid\n```\n\n\n\nTest Harness\n============\n\nA handful of test cases are provided for both the hash algorithm and the ScryptFile library. The ScryptFile tests generate tests that can be validated against the command line utility (http://www.tarsnap.com/scrypt.html).\n\n```python\n# python tests/run-tests-hash.py\nVersion: 1.6.0\nTest 1: pass\nTest 2: pass\nTest 3: pass\nTest 4: pass\nTest 5: pass\n\n# python tests/run-tests-file.py \nVersion: 1.6.0\nTest Encrypt/Decrypt: text_length=3 result=pass valid=True\nTest Encrypt/Decrypt: text_length=16 result=pass valid=True\nTest Encrypt/Decrypt: text_length=127 result=pass valid=True\nTest Encrypt/Decrypt: text_length=128 result=pass valid=True\nTest Encrypt/Decrypt: text_length=129 result=pass valid=True\nTest Encrypt/Decrypt: text_length=1500 result=pass valid=True\nCreated /tmp/test-10.scrypt and /tmp/test-10.txt. Check with tarsnap.\nCreated /tmp/test-100.scrypt and /tmp/test-100.txt. Check with tarsnap.\nCreated /tmp/test-1000.scrypt and /tmp/test-1000.txt. Check with tarsnap.\nTest With filename: result=pass\nTest Verify: filename=tests/test1.scrypt result=pass\nTest Decrypt: dec('tests/test1.scrypt') == 'tests/test1.txt' result=pass valid=None\nTest Decrypt: dec('tests/test1.scrypt') == 'tests/test1.txt' result=pass valid=True\nTest Decrypt: dec('tests/test1.scrypt') == 'tests/test1.txt' result=pass valid=True\nTest Verify: filename=tests/test2.scrypt result=pass\nTest Decrypt: dec('tests/test2.scrypt') == 'tests/test2.txt' result=pass valid=None\nTest Decrypt: dec('tests/test2.scrypt') == 'tests/test2.txt' result=pass valid=None\nTest Decrypt: dec('tests/test2.scrypt') == 'tests/test2.txt' result=pass valid=True\n```\n\nNotice that `valid` is sometimes None. The value of `valid` can take on one of three values:\n* **None** - File has not been entirely read, so the checksum cannot be verified\n* **True** - The end-of-file checksum is valid\n* **False** - The end-of-file checksum is invalid (some bytes in the file are corrupt)\n\nPerformance\n===========\n\nThe scrypt algorithm is a CPU and memory intense algorithm, **by design**. For comparison, here are numbers based on my MacBook Air for scrypt hashing with (N = 1024, r = 1, p =1):\n\n**CPython** (what you probably have installed)\n\n6 hashes per second\n\n**Pypy** (a much faster Python implementation, see [pypy.org](http://pypy.org))\n\n250 hashes per second\n\n**C-Wrapper** (See the FAQ below)\n\n2364 hashes per second\n\n\nPython 3\n========\n\nThis library is Python 3 friendly, however, there are a few things to note.\n\n- The parameters `password` and `salt` must be byte objects. e.g. `b\"pass123\"` instead of `\"pass123\"`.\n- ScryptFile's mode must be either `rb` or `wb`. ScryptFile has two constants to help write portable code, `ScryptFile.MODE_READ` and `ScryptFile.MODE_WRITE`.\n\n```python\nimport pyscrypt\n\n# Hash\nhashed = pyscrypt.hash(password = b\"correct horse battery staple\", \n                       salt = b\"seasalt\", \n                       N = 1024, \n                       r = 1, \n                       p = 1, \n                       dkLen = 256)\nprint hashed\n\n# Write a file\nwith pyscrypt.ScryptFile('filename.scrypt', b'password', 1024, 1, 1) as f:\n    f.write(b\"Hello world\")\n\n# Read a file\nwith pyscrypt.ScryptFile('filename.scrypt', b'password') as f:\n    data = f.read()\n    print(data)\n```\n\nFAQ\n===\n\n**Why is this so slow?**\nIt is written in pure Python. It is not meant to be fast, more of a reference solution.\n\n\n**How do I get one of these C wrappers you speak of?**\n\n```python\n\u003e # Download the source\n\u003e curl -L https://github.com/forrestv/p2pool/archive/13.4.tar.gz \u003e p2pool-13.4.tar.gz\n\n\u003e # Untar\n\u003e tar -xzf p2pool-13.4.tar.gz\n\n\u003e # Build and install\n\u003e cd p2pool-13.4/litecoin_scrypt/\n\u003e python setup.py build\n\u003e sudo python setup.py install\n\n\u003e python\n\u003e\u003e\u003e import scrypt\n\u003e\u003e\u003e scrypt.hash(password = \"correct horse staple battery\", \n                salt = \"seasalt\", \n                N = 1024, \n                p = 1, \n                r = 1, \n                buflen = 256)\n```\n    \n**How do I get a question I have added?**\nE-mail me at pyscrypt@ricmoo.com with any questions, suggestions, comments, et cetera.\n\n**Can I give you my money?**\nUmm... Ok? :-)\n\n_Bitcoin_  - `1LNdGsYtZXWeiKjGba7T997qvzrWqLXLma`\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fricmoo%2Fpyscrypt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fricmoo%2Fpyscrypt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fricmoo%2Fpyscrypt/lists"}