From 02f82f403512fb14d33b23c19e9452186b88b491 Mon Sep 17 00:00:00 2001 From: Holger Date: Fri, 1 Mar 2024 16:21:50 +0100 Subject: [PATCH] Improve layout --- .flake8 | 5 +- .github/pytest.ini | 3 + .github/workflows/pre-commit.yml | 15 ++ .github/workflows/tests.yml | 20 ++ .github/workflows/wheels_arm64.yml | 3 +- .github/workflows/wheels_linux.yml | 1 - .github/workflows/wheels_sdist.yml | 2 +- .github/workflows/wheels_win_64.yml | 2 +- .gitignore | 2 +- .pre-commit-config.yaml | 61 ++++++ README.rst | 22 +-- dev-requirements.txt | 2 +- pyproject.toml | 2 +- scrypt-windows-stubs/include/getopt.h | 2 +- scrypt-windows-stubs/include/inttypes.h | 18 +- scrypt-windows-stubs/include/unistd.h | 6 +- scrypt/__init__.py | 4 +- scrypt/scrypt.py | 248 +++++++++++++----------- scrypt/tests/ciphertexts.csv | 2 +- scrypt/tests/hashvectors.csv | 2 +- scrypt/tests/test_scrypt.py | 172 ++++++++-------- scrypt/tests/test_scrypt_c_module.py | 3 +- scrypt/tests/test_scrypt_py2x.py | 42 ---- scrypt/tests/test_scrypt_py3x.py | 20 +- setup.py | 217 +++++++++++---------- util/travis_osx_install.sh | 2 +- 26 files changed, 490 insertions(+), 388 deletions(-) create mode 100644 .github/pytest.ini create mode 100644 .github/workflows/pre-commit.yml create mode 100644 .github/workflows/tests.yml create mode 100644 .pre-commit-config.yaml delete mode 100644 scrypt/tests/test_scrypt_py2x.py diff --git a/.flake8 b/.flake8 index 06d70e9..9d505ae 100644 --- a/.flake8 +++ b/.flake8 @@ -3,6 +3,7 @@ ignore = # indentation is not a multiple of four, E111,E114, # visually indented line with same indent as next logical line, - E129 + E129, + W503 -max-line-length=80 +max-line-length=100 diff --git a/.github/pytest.ini b/.github/pytest.ini new file mode 100644 index 0000000..22004ea --- /dev/null +++ b/.github/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +norecursedirs = .git .* *.egg* old dist build +addopts = -rw diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 0000000..8a813f2 --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,15 @@ +name: pre-commit + +on: + pull_request: + push: + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: "3.9" + - uses: pre-commit/action@v2.0.0 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..abc25c3 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,20 @@ +name: Run tests +on: [push] +jobs: + run: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-2019, windows-latest, macos-latest] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + steps: + - uses: actions/checkout@master + - name: Setup Python + uses: actions/setup-python@master + with: + python-version: ${{ matrix.python-version }} + - name: Install packages + run: | + pip install pytest + pip install -e . + pytest diff --git a/.github/workflows/wheels_arm64.yml b/.github/workflows/wheels_arm64.yml index c3c4a67..c902853 100644 --- a/.github/workflows/wheels_arm64.yml +++ b/.github/workflows/wheels_arm64.yml @@ -35,7 +35,7 @@ jobs: with: name: artifact-${{ matrix.python }} path: wheelhouse/*.whl - + upload_pypi: name: Upload to PyPI (prod) needs: [build_aarch64_wheels] @@ -52,4 +52,3 @@ jobs: with: user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} - diff --git a/.github/workflows/wheels_linux.yml b/.github/workflows/wheels_linux.yml index 5d677d6..a575e5b 100644 --- a/.github/workflows/wheels_linux.yml +++ b/.github/workflows/wheels_linux.yml @@ -42,4 +42,3 @@ jobs: with: user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} - diff --git a/.github/workflows/wheels_sdist.yml b/.github/workflows/wheels_sdist.yml index 1b76918..744bb67 100644 --- a/.github/workflows/wheels_sdist.yml +++ b/.github/workflows/wheels_sdist.yml @@ -21,7 +21,7 @@ jobs: path: dist/*.tar.gz - name: Check metadata run: twine check dist/* - + upload_pypi: name: Upload to PyPI (prod) needs: [make_sdist] diff --git a/.github/workflows/wheels_win_64.yml b/.github/workflows/wheels_win_64.yml index 409b0e5..a42f88e 100644 --- a/.github/workflows/wheels_win_64.yml +++ b/.github/workflows/wheels_win_64.yml @@ -7,7 +7,7 @@ env: CIBW_TEST_REQUIRES: pytest CIBW_TEST_COMMAND: "pytest --pyargs scrypt" jobs: - + build_wheels_for_win: name: Build wheels on Win64 runs-on: windows-latest diff --git a/.gitignore b/.gitignore index 928c2ea..f2eac2a 100644 --- a/.gitignore +++ b/.gitignore @@ -96,4 +96,4 @@ ENV/ # wing *.wpr -*.wpu \ No newline at end of file +*.wpu diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..4d193dd --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,61 @@ + +default_language_version: + python: python3 +repos: + - repo: https://github.com/psf/black + rev: 24.2.0 + hooks: + - id: black + exclude: ^(scrypt-1.2.1/) + args: [--skip-string-normalization] + - repo: https://github.com/myint/autoflake + rev: v2.3.0 + hooks: + - id: autoflake + exclude: ^(scrypt-1.2.1/) + args: + - --in-place + - --ignore-init-module-imports + - --remove-all-unused-imports + - --remove-duplicate-keys + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: check-toml + - id: check-yaml + - id: end-of-file-fixer + exclude: ^(scrypt-1.2.1/) + - id: trailing-whitespace + exclude: ^(scrypt-1.2.1/) + - repo: https://github.com/PyCQA/flake8 + rev: "7.0.0" + hooks: + - id: flake8 + name: flake8 except __init__.py + exclude: (^(scrypt-1.2.1/)|/__init__\.py$) + additional_dependencies: ["flake8-bugbear==23.1.20"] + args: [--config, .flake8] + - id: flake8 + exclude: ^(scrypt-1.2.1/) + name: flake8 only __init__.py + args: [--config, .flake8, "--extend-ignore=F401"] # ignore unused imports in __init__.py + files: /__init__\.py$ + - repo: https://github.com/PyCQA/isort + rev: 5.13.2 + hooks: + - id: isort + args: ["--profile", "black"] + name: isort except __init__.py + exclude: (^(scrypt-1.2.1/)|/__init__\.py$) + - repo: https://github.com/myint/docformatter + rev: v1.7.5 + hooks: + - id: docformatter + exclude: ^(scrypt-1.2.1/) + args: ["--in-place", "--wrap-summaries=88"] + - repo: https://github.com/asottile/pyupgrade + rev: v3.15.1 + hooks: + - id: pyupgrade + exclude: ^(scrypt-1.2.1/) + args: ["--py37-plus"] diff --git a/README.rst b/README.rst index fba154c..0d15e84 100644 --- a/README.rst +++ b/README.rst @@ -8,15 +8,15 @@ function. .. image:: https://img.shields.io/pypi/v/scrypt.svg :target: https://pypi.python.org/pypi/scrypt/ :alt: Latest Version - -.. image:: https://anaconda.org/conda-forge/scrypt/badges/version.svg + +.. image:: https://anaconda.org/conda-forge/scrypt/badges/version.svg :target: https://anaconda.org/conda-forge/scrypt - -.. image:: https://anaconda.org/conda-forge/scrypt/badges/downloads.svg + +.. image:: https://anaconda.org/conda-forge/scrypt/badges/downloads.svg :target: https://anaconda.org/conda-forge/scrypt -.. image:: https://ci.appveyor.com/api/projects/status/h644bjbdawke9vf2?svg=true +.. image:: https://ci.appveyor.com/api/projects/status/h644bjbdawke9vf2?svg=true :target: https://ci.appveyor.com/project/holger80/py-scrypt .. image:: https://www.travis-ci.com/holgern/py-scrypt.svg?branch=master @@ -35,7 +35,7 @@ Installation ============ For Debian and Ubuntu, please ensure that the following packages are installed: - + .. code:: bash $ sudo apt-get install build-essential libssl-dev python-dev @@ -54,8 +54,8 @@ For OSX, please do the following:: For OSX, you can also use the precompiled wheels. They are installed by:: - $ pip install scrypt - + $ pip install scrypt + For Windows, please use the precompiled wheels. They are installed by:: $ pip install scrypt @@ -112,8 +112,8 @@ Changelog 0.8.17 ------ -* add_dll_directory for python 3.8 on windows, as importlib.util.find_spec does not search all paths anymore - +* add_dll_directory for python 3.8 on windows, as importlib.util.find_spec does not search all paths anymore + 0.8.16 ------ @@ -175,7 +175,7 @@ Changelog ----- * MANIFEST.in fixed -* scrypt.py moved into own scrypt directory with __init__.py +* scrypt.py moved into own scrypt directory with __init__.py * openssl library path for osx wheel repaired 0.8.4 diff --git a/dev-requirements.txt b/dev-requirements.txt index cdf4f8d..48ec298 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,3 +1,3 @@ tox nose -pytest \ No newline at end of file +pytest diff --git a/pyproject.toml b/pyproject.toml index 606bb1d..da898d2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,4 +6,4 @@ select = "*-musllinux*" before-all = "apk add openssl-dev" [tool.cibuildwheel.macos] -before-all = "brew install openssl@1.1" \ No newline at end of file +before-all = "brew install openssl@1.1" diff --git a/scrypt-windows-stubs/include/getopt.h b/scrypt-windows-stubs/include/getopt.h index 0b78650..d4c0932 100644 --- a/scrypt-windows-stubs/include/getopt.h +++ b/scrypt-windows-stubs/include/getopt.h @@ -4,7 +4,7 @@ * * Copyright (c)2002-2003 Mark K. Kim * All rights reserved. -* +* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: diff --git a/scrypt-windows-stubs/include/inttypes.h b/scrypt-windows-stubs/include/inttypes.h index 4b3828a..ead903f 100644 --- a/scrypt-windows-stubs/include/inttypes.h +++ b/scrypt-windows-stubs/include/inttypes.h @@ -1,32 +1,32 @@ // ISO C9x compliant inttypes.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// // Copyright (c) 2006 Alexander Chemeris -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: -// +// // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. -// +// // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. -// +// // 3. The name of the author may be used to endorse or promote products // derived from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +// /////////////////////////////////////////////////////////////////////////////// #ifndef _MSC_VER // [ diff --git a/scrypt-windows-stubs/include/unistd.h b/scrypt-windows-stubs/include/unistd.h index 85af152..5987e45 100644 --- a/scrypt-windows-stubs/include/unistd.h +++ b/scrypt-windows-stubs/include/unistd.h @@ -6,9 +6,9 @@ #ifndef _UNISTD_H #define _UNISTD_H 1 -/* This file intended to serve as a drop-in replacement for +/* This file intended to serve as a drop-in replacement for * unistd.h on Windows - * Please add functionality as neeeded + * Please add functionality as neeeded */ #include @@ -37,7 +37,7 @@ #define STDERR_FILENO 2 /* should be in some equivalent to */ typedef __int8 int8_t; -typedef __int16 int16_t; +typedef __int16 int16_t; typedef __int32 int32_t; typedef __int64 int64_t; typedef unsigned __int8 uint8_t; diff --git a/scrypt/__init__.py b/scrypt/__init__.py index c08d17e..17143d9 100644 --- a/scrypt/__init__.py +++ b/scrypt/__init__.py @@ -1 +1,3 @@ -from .scrypt import * +from .scrypt import encrypt, decrypt, hash, error + +__all__ = ['error', 'encrypt', 'decrypt', 'hash'] diff --git a/scrypt/scrypt.py b/scrypt/scrypt.py index 47c8ad5..0832d0e 100644 --- a/scrypt/scrypt.py +++ b/scrypt/scrypt.py @@ -1,85 +1,93 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- import os import sys -from ctypes import (cdll, - POINTER, pointer, - c_char_p, - c_size_t, c_double, c_int, c_uint64, c_uint32, - create_string_buffer) -IS_PY2 = sys.version_info < (3, 0, 0, 'final', 0) -if IS_PY2: - import imp - _scrypt = cdll.LoadLibrary(imp.find_module('_scrypt')[1]) -else: - if sys.version_info >= (3, 8) and sys.platform == 'win32': - lib_path = os.path.join(os.path.normpath(sys.prefix), 'Library', 'bin') - build_dir = os.path.join(os.path.dirname(__file__), '../') - if os.path.exists(lib_path): - os.add_dll_directory(lib_path) - if os.path.exists(build_dir): - os.add_dll_directory(build_dir) - import importlib - import importlib.util - _scrypt = cdll.LoadLibrary(importlib.util.find_spec('_scrypt').origin) +from ctypes import ( + POINTER, + c_char_p, + c_double, + c_int, + c_size_t, + c_uint32, + c_uint64, + cdll, + create_string_buffer, + pointer, +) + +if sys.version_info >= (3, 8) and sys.platform == 'win32': + lib_path = os.path.join(os.path.normpath(sys.prefix), 'Library', 'bin') + build_dir = os.path.join(os.path.dirname(__file__), '../') + if os.path.exists(lib_path): + os.add_dll_directory(lib_path) + if os.path.exists(build_dir): + os.add_dll_directory(build_dir) +import importlib +import importlib.util + +_scrypt = cdll.LoadLibrary(importlib.util.find_spec('_scrypt').origin) __version__ = '0.8.22' _scryptenc_buf = _scrypt.exp_scryptenc_buf -_scryptenc_buf.argtypes = [c_char_p, # const uint_t *inbuf - c_size_t, # size_t inbuflen - c_char_p, # uint8_t *outbuf - c_char_p, # const uint8_t *passwd - c_size_t, # size_t passwdlen - c_size_t, # size_t maxmem - c_double, # double maxmemfrac - c_double, # double maxtime - c_int, # int verbose - ] +_scryptenc_buf.argtypes = [ + c_char_p, # const uint_t *inbuf + c_size_t, # size_t inbuflen + c_char_p, # uint8_t *outbuf + c_char_p, # const uint8_t *passwd + c_size_t, # size_t passwdlen + c_size_t, # size_t maxmem + c_double, # double maxmemfrac + c_double, # double maxtime + c_int, # int verbose +] _scryptenc_buf.restype = c_int _scryptdec_buf = _scrypt.exp_scryptdec_buf -_scryptdec_buf.argtypes = [c_char_p, # const uint8_t *inbuf - c_size_t, # size_t inbuflen - c_char_p, # uint8_t *outbuf - POINTER(c_size_t), # size_t *outlen - c_char_p, # const uint8_t *passwd - c_size_t, # size_t passwdlen - c_size_t, # size_t maxmem - c_double, # double maxmemfrac - c_double, # double maxtime - c_int, # int verbose - c_int, # int force - ] +_scryptdec_buf.argtypes = [ + c_char_p, # const uint8_t *inbuf + c_size_t, # size_t inbuflen + c_char_p, # uint8_t *outbuf + POINTER(c_size_t), # size_t *outlen + c_char_p, # const uint8_t *passwd + c_size_t, # size_t passwdlen + c_size_t, # size_t maxmem + c_double, # double maxmemfrac + c_double, # double maxtime + c_int, # int verbose + c_int, # int force +] _scryptdec_buf.restype = c_int _crypto_scrypt = _scrypt.exp_crypto_scrypt -_crypto_scrypt.argtypes = [c_char_p, # const uint8_t *passwd - c_size_t, # size_t passwdlen - c_char_p, # const uint8_t *salt - c_size_t, # size_t saltlen - c_uint64, # uint64_t N - c_uint32, # uint32_t r - c_uint32, # uint32_t p - c_char_p, # uint8_t *buf - c_size_t, # size_t buflen - ] +_crypto_scrypt.argtypes = [ + c_char_p, # const uint8_t *passwd + c_size_t, # size_t passwdlen + c_char_p, # const uint8_t *salt + c_size_t, # size_t saltlen + c_uint64, # uint64_t N + c_uint32, # uint32_t r + c_uint32, # uint32_t p + c_char_p, # uint8_t *buf + c_size_t, # size_t buflen +] _crypto_scrypt.restype = c_int -ERROR_MESSAGES = ['success', - 'getrlimit or sysctl(hw.usermem) failed', - 'clock_getres or clock_gettime failed', - 'error computing derived key', - 'could not read salt from /dev/urandom', - 'error in OpenSSL', - 'malloc failed', - 'data is not a valid scrypt-encrypted block', - 'unrecognized scrypt format', - 'decrypting file would take too much memory', - 'decrypting file would take too long', - 'password is incorrect', - 'error writing output file', - 'error reading input file'] +ERROR_MESSAGES = [ + 'success', + 'getrlimit or sysctl(hw.usermem) failed', + 'clock_getres or clock_gettime failed', + 'error computing derived key', + 'could not read salt from /dev/urandom', + 'error in OpenSSL', + 'malloc failed', + 'data is not a valid scrypt-encrypted block', + 'unrecognized scrypt format', + 'decrypting file would take too much memory', + 'decrypting file would take too long', + 'password is incorrect', + 'error writing output file', + 'error reading input file', +] MAXMEM_DEFAULT = 0 MAXMEMFRAC_DEFAULT = 0.5 @@ -91,29 +99,29 @@ class error(Exception): def __init__(self, scrypt_code): if isinstance(scrypt_code, int): self._scrypt_code = scrypt_code - super(error, self).__init__(ERROR_MESSAGES[scrypt_code]) + super().__init__(ERROR_MESSAGES[scrypt_code]) else: self._scrypt_code = -1 - super(error, self).__init__(scrypt_code) + super().__init__(scrypt_code) def _ensure_bytes(data): - if IS_PY2 and isinstance(data, unicode): - raise TypeError('can not encrypt/decrypt unicode objects') - - if not IS_PY2 and isinstance(data, str): + if isinstance(data, str): return bytes(data, 'utf-8') return data -def encrypt(input, password, - maxtime=MAXTIME_DEFAULT_ENC, - maxmem=MAXMEM_DEFAULT, - maxmemfrac=MAXMEMFRAC_DEFAULT): - """ - Encrypt a string using a password. The resulting data will have len = - len(input) + 128. +def encrypt( + input, + password, + maxtime=MAXTIME_DEFAULT_ENC, + maxmem=MAXMEM_DEFAULT, + maxmemfrac=MAXMEMFRAC_DEFAULT, +): + """Encrypt a string using a password. + The resulting data will have len = len(input) + + 128. Notes for Python 2: - `input` and `password` must be str instances @@ -137,23 +145,32 @@ def encrypt(input, password, outbuf = create_string_buffer(len(input) + 128) # verbose is set to zero - result = _scryptenc_buf(input, len(input), - outbuf, - password, len(password), - maxmem, maxmemfrac, maxtime, 0) + result = _scryptenc_buf( + input, + len(input), + outbuf, + password, + len(password), + maxmem, + maxmemfrac, + maxtime, + 0, + ) if result: raise error(result) return outbuf.raw -def decrypt(input, password, - maxtime=MAXTIME_DEFAULT, - maxmem=MAXMEM_DEFAULT, - maxmemfrac=MAXMEMFRAC_DEFAULT, - encoding='utf-8'): - """ - Decrypt a string using a password. +def decrypt( + input, + password, + maxtime=MAXTIME_DEFAULT, + maxmem=MAXMEM_DEFAULT, + maxmemfrac=MAXMEMFRAC_DEFAULT, + encoding='utf-8', +): + """Decrypt a string using a password. Notes for Python 2: - `input` and `password` must be str instances @@ -181,38 +198,41 @@ def decrypt(input, password, input = _ensure_bytes(input) password = _ensure_bytes(password) # verbose and force are set to zero - result = _scryptdec_buf(input, len(input), - outbuf, outbuflen, - password, len(password), - maxmem, maxmemfrac, maxtime, 0, 0) + result = _scryptdec_buf( + input, + len(input), + outbuf, + outbuflen, + password, + len(password), + maxmem, + maxmemfrac, + maxtime, + 0, + 0, + ) if result: raise error(result) - out_bytes = outbuf.raw[:outbuflen.contents.value] + out_bytes = outbuf.raw[: outbuflen.contents.value] - if IS_PY2 or encoding is None: + if encoding is None: return out_bytes return str(out_bytes, encoding) def hash(password, salt, N=1 << 14, r=8, p=1, buflen=64): - """ - Compute scrypt(password, salt, N, r, p, buflen). + """Compute scrypt(password, salt, N, r, p, buflen). The parameters r, p, and buflen must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N must be a power of 2 greater than 1. N, r and p must all be positive. - Notes for Python 2: - - `password` and `salt` must be str instances - - The result will be a str instance - - Notes for Python 3: - - `password` and `salt` can be both str and bytes. If they are str - instances, they wil be encoded with utf-8. - - The result will be a bytes instance + - `password` and `salt` can be both str and bytes. If they are str + instances, they wil be encoded with utf-8. + - The result will be a bytes instance Exceptions raised: - TypeError on invalid input @@ -225,12 +245,14 @@ def hash(password, salt, N=1 << 14, r=8, p=1, buflen=64): salt = _ensure_bytes(salt) if r * p >= (1 << 30) or N <= 1 or (N & (N - 1)) != 0 or p < 1 or r < 1: - raise error('hash parameters are wrong (r*p should be < 2**30, and N should be a power of two > 1)') - - result = _crypto_scrypt(password, len(password), - salt, len(salt), - N, r, p, - outbuf, buflen, 0) + raise error( + 'hash parameters are wrong (r*p should be < 2**30, ' + 'and N should be a power of two > 1)' + ) + + result = _crypto_scrypt( + password, len(password), salt, len(salt), N, r, p, outbuf, buflen, 0 + ) if result: raise error('could not compute hash') diff --git a/scrypt/tests/ciphertexts.csv b/scrypt/tests/ciphertexts.csv index fa830c2..2364699 100644 --- a/scrypt/tests/ciphertexts.csv +++ b/scrypt/tests/ciphertexts.csv @@ -3,4 +3,4 @@ message,password,0.01,0,0.0625,736372797074000a00000008000000019f6d3fe5e9423a12d message,password,5.0000,0.0000,0.1250,736372797074000a00000008000000cb974d55992fea307caa3593205c8851cd56b3ddfd241ee7b1c075cfd2e2f871dddcee71b6bc2b6b075caa1699ea58ce32e9fcd802b18069828201692380574e23e84c2d39d6a951c9c2401dea1a0fa44195b01fca9332f7aac223c84251c69a28037788e09cf297a003a62e2e7c5b6f039e3c1d21fa5da6 message,password,0.5000,0.0000,0.0625,736372797074000a00000008000000141429bb22aef840e1dde29564dada8f2a77fc2855fe8c9e27e5bf5df4a0eec330344e8471bf83e2466a28acc9d1813a3e50e64697fb8e9c7c17954950f16a5b78fe114d8b147c5936802fe52b17f83e6da9de884257f2a938aa37c2e92b1c33cd9afd0f5e91baba29be4b1c0709bd2a31a4c52394f9b0d4 message,password,0.5000,0.0000,0.1250,736372797074000a0000000800000014e9baa49b57b2e5b561df54121d870532714f063f295c15ca48e32b677e8e11126ab8da24683951749a19eede36ea3768cb01e8eda6c0f570db7051e07e99d2d687ce28f96aa2e6afa8a0a8c5d902c847e041e14435a22d873c4e676f7a7f5ab9107171b583d02724c056707640931a3c160b9e0ef87bae -message,password,0.5000,10485760.0000,0.1250,736372797074000a0000000800000014e53c55cd89b6e2de639c1621d92e79212e5f4fc793387435486427eb8adeb192382b5b6397f98ac66fa528a13cba01bd611082369fe1e2244a01ba8329ff6fcaa2db5e87fb75683ae6fc636d873c2e004a0209b947c7b8e805174d65ec0ac2cb597baadae6cf092c33a5096590860b51570faa89e39bf0 \ No newline at end of file +message,password,0.5000,10485760.0000,0.1250,736372797074000a0000000800000014e53c55cd89b6e2de639c1621d92e79212e5f4fc793387435486427eb8adeb192382b5b6397f98ac66fa528a13cba01bd611082369fe1e2244a01ba8329ff6fcaa2db5e87fb75683ae6fc636d873c2e004a0209b947c7b8e805174d65ec0ac2cb597baadae6cf092c33a5096590860b51570faa89e39bf0 diff --git a/scrypt/tests/hashvectors.csv b/scrypt/tests/hashvectors.csv index 384f265..1842d90 100644 --- a/scrypt/tests/hashvectors.csv +++ b/scrypt/tests/hashvectors.csv @@ -3,4 +3,4 @@ password,salt,n,r,p,hexhash password,NaCl,1024,8,16,fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640 pleaseletmein,SodiumChloride,16384,8,1,7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887 pleaseletmein,SodiumChloride,32768,16,4,cbc397a9b5f5a53048c5b9f039ee1246d9532c8089fb346a4ab47cd0701febf18652b1ee042e070d1b6c631c43fd05ececd5b165ee1c2ffc1a2e98406fc2cd52 -pleaseletmein,SodiumChloride,1048576,8,1,2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049e8a952fbcbf45c6fa77a41a4 \ No newline at end of file +pleaseletmein,SodiumChloride,1048576,8,1,2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049e8a952fbcbf45c6fa77a41a4 diff --git a/scrypt/tests/test_scrypt.py b/scrypt/tests/test_scrypt.py index 968485f..378b1bd 100644 --- a/scrypt/tests/test_scrypt.py +++ b/scrypt/tests/test_scrypt.py @@ -1,12 +1,10 @@ -# -*- coding: utf-8 -*- - -from os import urandom -from os.path import dirname, abspath, sep -from sys import version_info, exit -from csv import reader +import unittest as testm from binascii import a2b_hex, b2a_hex +from csv import reader +from os import urandom +from os.path import abspath, dirname, sep + import scrypt -import unittest as testm class TestScrypt(testm.TestCase): @@ -21,7 +19,7 @@ def setUp(self): self.one_megabyte = 1024 * 1024 # in Bytes self.ten_megabytes = 10 * self.one_megabyte base_dir = dirname(abspath(__file__)) + sep - cvf = open(base_dir + "ciphertexts.csv", "r") + cvf = open(base_dir + "ciphertexts.csv") ciphertxt_reader = reader(cvf, dialect="excel") self.ciphertexts = [] for row in ciphertxt_reader: @@ -30,25 +28,25 @@ def setUp(self): self.ciphertext = a2b_hex(bytes(self.ciphertexts[1][5].encode('ascii'))) def test_encrypt_decrypt(self): - """Test encrypt for simple encryption and decryption""" + """Test encrypt for simple encryption and decryption.""" s = scrypt.encrypt(self.input, self.password, 0.1) m = scrypt.decrypt(s, self.password) self.assertEqual(m, self.input) def test_encrypt(self): - """Test encrypt takes input and password strings as - positional arguments and produces ciphertext""" + """Test encrypt takes input and password strings as positional arguments and + produces ciphertext.""" s = scrypt.encrypt(self.input, self.password) self.assertEqual(len(s), 128 + len(self.input)) def test_encrypt_input_and_password_as_keywords(self): - """Test encrypt for input and password accepted as keywords""" + """Test encrypt for input and password accepted as keywords.""" s = scrypt.encrypt(password=self.password, input=self.input) m = scrypt.decrypt(s, self.password) self.assertEqual(m, self.input) def test_encrypt_missing_input_keyword_argument(self): - """Test encrypt raises TypeError if keyword argument missing input""" + """Test encrypt raises TypeError if keyword argument missing input.""" self.assertRaises(TypeError, lambda: scrypt.encrypt(password=self.password)) def test_encrypt_missing_password_positional_argument(self): @@ -57,121 +55,125 @@ def test_encrypt_missing_password_positional_argument(self): self.assertRaises(TypeError, lambda: scrypt.encrypt(self.input)) def test_encrypt_missing_both_required_positional_arguments(self): - """Test encrypt raises TypeError if both positional arguments missing - (input and password)""" + """Test encrypt raises TypeError if both positional arguments missing (input and + password)""" self.assertRaises(TypeError, lambda: scrypt.encrypt()) def test_encrypt_maxtime_positional(self): - """Test encrypt maxtime accepts maxtime at position 3""" + """Test encrypt maxtime accepts maxtime at position 3.""" s = scrypt.encrypt(self.input, self.password, 0.01) m = scrypt.decrypt(s, self.password) self.assertEqual(m, self.input) def test_encrypt_maxtime_key(self): - """Test encrypt maxtime accepts maxtime as keyword argument""" + """Test encrypt maxtime accepts maxtime as keyword argument.""" s = scrypt.encrypt(self.input, self.password, maxtime=0.01) m = scrypt.decrypt(s, self.password) self.assertEqual(m, self.input) def test_encrypt_maxmem_positional(self): - """Test encrypt maxmem accepts 4th positional argument and exactly - (1 megabyte) of storage to use for V array""" + """Test encrypt maxmem accepts 4th positional argument and exactly (1 megabyte) + of storage to use for V array.""" s = scrypt.encrypt(self.input, self.password, 0.01, self.one_megabyte) m = scrypt.decrypt(s, self.password) self.assertEqual(m, self.input) def test_encrypt_maxmem_undersized(self): - """Test encrypt maxmem accepts (< 1 megabyte) of storage to use for V array""" + """Test encrypt maxmem accepts (< 1 megabyte) of storage to use for V array.""" s = scrypt.encrypt(self.input, self.password, 0.01, self.one_byte) m = scrypt.decrypt(s, self.password) self.assertEqual(m, self.input) def test_encrypt_maxmem_in_normal_range(self): - """Test encrypt maxmem accepts (> 1 megabyte) of storage to use for V array""" - s = scrypt.encrypt(self.input, - self.password, - 0.01, - self.ten_megabytes) + """Test encrypt maxmem accepts (> 1 megabyte) of storage to use for V array.""" + s = scrypt.encrypt(self.input, self.password, 0.01, self.ten_megabytes) m = scrypt.decrypt(s, self.password) self.assertEqual(m, self.input) def test_encrypt_maxmem_keyword_argument(self): - """Test encrypt maxmem accepts exactly (1 megabyte) of storage to use for - V array""" - s = scrypt.encrypt(self.input, - self.password, - maxmem=self.one_megabyte, - maxtime=0.01) + """Test encrypt maxmem accepts exactly (1 megabyte) of storage to use for V + array.""" + s = scrypt.encrypt( + self.input, self.password, maxmem=self.one_megabyte, maxtime=0.01 + ) m = scrypt.decrypt(s, self.password) self.assertEqual(m, self.input) def test_encrypt_maxmemfrac_positional(self): - """Test encrypt maxmemfrac accepts 5th positional argument of 1/16 total - memory for V array""" + """Test encrypt maxmemfrac accepts 5th positional argument of 1/16 total memory + for V array.""" s = scrypt.encrypt(self.input, self.password, 0.01, 0, 0.0625) m = scrypt.decrypt(s, self.password) self.assertEqual(m, self.input) def test_encrypt_maxmemfrac_keyword_argument(self): - """Test encrypt maxmemfrac accepts keyword argument of 1/16 total memory for - V array""" - s = scrypt.encrypt(self.input, self.password, maxmemfrac=0.0625, - maxtime=0.01) + """Test encrypt maxmemfrac accepts keyword argument of 1/16 total memory for V + array.""" + s = scrypt.encrypt(self.input, self.password, maxmemfrac=0.0625, maxtime=0.01) m = scrypt.decrypt(s, self.password) self.assertEqual(m, self.input) def test_encrypt_long_input(self): - """Test encrypt accepts long input for encryption""" + """Test encrypt accepts long input for encryption.""" s = scrypt.encrypt(self.longinput, self.password, 0.1) self.assertEqual(len(s), 128 + len(self.longinput)) def test_encrypt_raises_error_on_invalid_keyword(self): - """Test encrypt raises TypeError if invalid keyword used in argument""" - self.assertRaises(TypeError, lambda: scrypt.encrypt(self.input, - self.password, nonsense="Raise error")) + """Test encrypt raises TypeError if invalid keyword used in argument.""" + self.assertRaises( + TypeError, + lambda: scrypt.encrypt(self.input, self.password, nonsense="Raise error"), + ) def test_decrypt_from_csv_ciphertexts(self): - """Test decrypt function with precalculated combinations""" + """Test decrypt function with precalculated combinations.""" for row in self.ciphertexts[1:]: h = scrypt.decrypt(a2b_hex(bytes(row[5].encode('ascii'))), row[1]) self.assertEqual(bytes(h.encode("ascii")), row[0].encode("ascii")) def test_decrypt_maxtime_positional(self): - """Test decrypt function accepts third positional argument""" + """Test decrypt function accepts third positional argument.""" m = scrypt.decrypt(self.ciphertext, self.password, self.five_seconds) self.assertEqual(m, self.input) def test_decrypt_maxtime_keyword_argument(self): - """Test decrypt function accepts maxtime keyword argument""" + """Test decrypt function accepts maxtime keyword argument.""" m = scrypt.decrypt(maxtime=1.0, input=self.ciphertext, password=self.password) self.assertEqual(m, self.input) def test_decrypt_maxmem_positional(self): - """Test decrypt function accepts fourth positional argument""" - m = scrypt.decrypt(self.ciphertext, self.password, self.five_minutes, self.ten_megabytes) + """Test decrypt function accepts fourth positional argument.""" + m = scrypt.decrypt( + self.ciphertext, self.password, self.five_minutes, self.ten_megabytes + ) self.assertEqual(m, self.input) def test_decrypt_maxmem_keyword_argument(self): - """Test decrypt function accepts maxmem keyword argument""" - m = scrypt.decrypt(maxmem=self.ten_megabytes, input=self.ciphertext, password=self.password) + """Test decrypt function accepts maxmem keyword argument.""" + m = scrypt.decrypt( + maxmem=self.ten_megabytes, input=self.ciphertext, password=self.password + ) self.assertEqual(m, self.input) def test_decrypt_maxmemfrac_positional(self): - """Test decrypt function accepts maxmem keyword argument""" - m = scrypt.decrypt(self.ciphertext, self.password, self.five_minutes, self.one_megabyte, 0.0625) + """Test decrypt function accepts maxmem keyword argument.""" + m = scrypt.decrypt( + self.ciphertext, self.password, self.five_minutes, self.one_megabyte, 0.0625 + ) self.assertEqual(m, self.input) def test_decrypt_maxmemfrac_keyword_argument(self): - """Test decrypt function accepts maxmem keyword argument""" - m = scrypt.decrypt(maxmemfrac=0.625, input=self.ciphertext, password=self.password) + """Test decrypt function accepts maxmem keyword argument.""" + m = scrypt.decrypt( + maxmemfrac=0.625, input=self.ciphertext, password=self.password + ) self.assertEqual(m, self.input) def test_decrypt_raises_error_on_too_little_time(self): - """Test decrypt function raises scrypt.error raised if insufficient time allowed for - ciphertext decryption""" + """Test decrypt function raises scrypt.error raised if insufficient time allowed + for ciphertext decryption.""" s = scrypt.encrypt(self.input, self.password, 0.1) - self.assertRaises(scrypt.error, - lambda: scrypt.decrypt(s, self.password, .01)) + self.assertRaises(scrypt.error, lambda: scrypt.decrypt(s, self.password, 0.01)) class TestScryptHash(testm.TestCase): @@ -182,92 +184,94 @@ def setUp(self): self.salt = "NaCl" self.hashes = [] base_dir = dirname(abspath(__file__)) + sep - hvf = open(base_dir + "hashvectors.csv", "r") + hvf = open(base_dir + "hashvectors.csv") hash_reader = reader(hvf, dialect="excel") for row in hash_reader: self.hashes.append(row) hvf.close() def test_hash_vectors_from_csv(self): - """Test hash function with precalculated combinations""" + """Test hash function with precalculated combinations.""" for row in self.hashes[1:]: h = scrypt.hash(row[0], row[1], int(row[2]), int(row[3]), int(row[4])) hhex = b2a_hex(h) self.assertEqual(hhex, bytes(row[5].encode("utf-8"))) def test_hash_buflen_keyword(self): - """Test hash takes keyword valid buflen""" + """Test hash takes keyword valid buflen.""" h64 = scrypt.hash(self.input, self.salt, buflen=64) h128 = scrypt.hash(self.input, self.salt, buflen=128) self.assertEqual(len(h64), 64) self.assertEqual(len(h128), 128) def test_hash_n_positional(self): - """Test hash accepts valid N in position 3""" + """Test hash accepts valid N in position 3.""" h = scrypt.hash(self.input, self.salt, 256) self.assertEqual(len(h), 64) def test_hash_n_keyword(self): - """Test hash takes keyword valid N""" + """Test hash takes keyword valid N.""" h = scrypt.hash(N=256, password=self.input, salt=self.salt) self.assertEqual(len(h), 64) def test_hash_r_positional(self): - """Test hash accepts valid r in position 4""" + """Test hash accepts valid r in position 4.""" h = scrypt.hash(self.input, self.salt, 256, 16) self.assertEqual(len(h), 64) def test_hash_r_keyword(self): - """Test hash takes keyword valid r""" + """Test hash takes keyword valid r.""" h = scrypt.hash(r=16, password=self.input, salt=self.salt) self.assertEqual(len(h), 64) def test_hash_p_positional(self): - """Test hash accepts valid p in position 5""" + """Test hash accepts valid p in position 5.""" h = scrypt.hash(self.input, self.salt, 256, 8, 2) self.assertEqual(len(h), 64) def test_hash_p_keyword(self): - """Test hash takes keyword valid p""" + """Test hash takes keyword valid p.""" h = scrypt.hash(p=4, password=self.input, salt=self.salt) self.assertEqual(len(h), 64) def test_hash_raises_error_on_p_equals_zero(self): """Test hash raises scrypt error on illegal parameter value (p = 0)""" - self.assertRaises(scrypt.error, - lambda: scrypt.hash(self.input, self.salt, p=0)) + self.assertRaises(scrypt.error, lambda: scrypt.hash(self.input, self.salt, p=0)) def test_hash_raises_error_on_negative_p(self): """Test hash raises scrypt error on illegal parameter value (p < 0)""" - self.assertRaises(scrypt.error, - lambda: scrypt.hash(self.input, self.salt, p=-1)) + self.assertRaises( + scrypt.error, lambda: scrypt.hash(self.input, self.salt, p=-1) + ) def test_hash_raises_error_on_r_equals_zero(self): """Test hash raises scrypt error on illegal parameter value (r = 0)""" - self.assertRaises(scrypt.error, - lambda: scrypt.hash(self.input, self.salt, r=0)) + self.assertRaises(scrypt.error, lambda: scrypt.hash(self.input, self.salt, r=0)) def test_hash_raises_error_on_negative_r(self): """Test hash raises scrypt error on illegal parameter value (r < 1)""" - self.assertRaises(scrypt.error, - lambda: scrypt.hash(self.input, self.salt, r=-1)) + self.assertRaises( + scrypt.error, lambda: scrypt.hash(self.input, self.salt, r=-1) + ) def test_hash_raises_error_r_p_over_limit(self): - """Test hash raises scrypt error when parameters r multiplied by p over limit 2**30""" - self.assertRaises(scrypt.error, - lambda: scrypt.hash(self.input, self.salt, r=2, p=2 ** 29)) + """Test hash raises scrypt error when parameters r multiplied by p over limit + 2**30.""" + self.assertRaises( + scrypt.error, lambda: scrypt.hash(self.input, self.salt, r=2, p=2**29) + ) def test_hash_raises_error_n_not_power_of_two(self): - """Test hash raises scrypt error when parameter N is not a power of two {2, 4, 8, 16, etc}""" - self.assertRaises(scrypt.error, - lambda: scrypt.hash(self.input, self.salt, N=3)) + """Test hash raises scrypt error when parameter N is not a power of two {2, 4, + 8, 16, etc}""" + self.assertRaises(scrypt.error, lambda: scrypt.hash(self.input, self.salt, N=3)) def test_hash_raises_error_n_under_limit(self): - """Test hash raises scrypt error when parameter N under limit of 1""" - self.assertRaises(scrypt.error, - lambda: scrypt.hash(self.input, self.salt, N=1)) - self.assertRaises(scrypt.error, - lambda: scrypt.hash(self.input, self.salt, N=-1)) + """Test hash raises scrypt error when parameter N under limit of 1.""" + self.assertRaises(scrypt.error, lambda: scrypt.hash(self.input, self.salt, N=1)) + self.assertRaises( + scrypt.error, lambda: scrypt.hash(self.input, self.salt, N=-1) + ) if __name__ == "__main__": diff --git a/scrypt/tests/test_scrypt_c_module.py b/scrypt/tests/test_scrypt_c_module.py index d62ce64..578bbfb 100644 --- a/scrypt/tests/test_scrypt_c_module.py +++ b/scrypt/tests/test_scrypt_c_module.py @@ -1,10 +1,9 @@ -from sys import version_info, exit import unittest as testm class TestScryptCModule(testm.TestCase): def test_import_module(self): - """Test importing the _scrypt module""" + """Test importing the _scrypt module.""" import _scrypt diff --git a/scrypt/tests/test_scrypt_py2x.py b/scrypt/tests/test_scrypt_py2x.py deleted file mode 100644 index c2a9acb..0000000 --- a/scrypt/tests/test_scrypt_py2x.py +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: utf-8 -*- - -from sys import version_info, exit -import scrypt -import unittest as testm - - -@testm.skipIf(version_info > (3, 0, 0, 'final', 0), "Tests for Python 2 only") -class TestScryptForPython2(testm.TestCase): - - def setUp(self): - self.input = "message" - self.password = "password" - self.unicode_text = '\xe1\x93\x84\xe1\x93\x87\xe1\x95\x97\xe1\x92\xbb\xe1\x92\xa5\xe1\x90\x85\xe1\x91\xa6'.decode('utf-8') - - def test_py2_encrypt_fails_on_unicode_input(self): - """Test Py2 encrypt raises TypeError when Unicode input passed""" - self.assertRaises(TypeError, lambda: scrypt.encrypt(self.unicode_text, self.password)) - - def test_py2_encrypt_fails_on_unicode_password(self): - """Test Py2 encrypt raises TypeError when Unicode password passed""" - self.assertRaises(TypeError, lambda: scrypt.encrypt(self.input, self.unicode_text)) - - def test_py2_encrypt_returns_string(self): - """Test Py2 encrypt returns str""" - e = scrypt.encrypt(self.input, self.password, 0.1) - self.assertTrue(isinstance(e, str)) - - def test_py2_decrypt_returns_string(self): - """Test Py2 decrypt returns str""" - s = scrypt.encrypt(self.input, self.password, 0.1) - m = scrypt.decrypt(s, self.password) - self.assertTrue(isinstance(m, str)) - - def test_py2_hash_returns_string(self): - """Test Py2 hash return str""" - h = scrypt.hash(self.input, self.password) - self.assertTrue(isinstance(h, str)) - - -if __name__ == "__main__": - testm.main() diff --git a/scrypt/tests/test_scrypt_py3x.py b/scrypt/tests/test_scrypt_py3x.py index f87373d..47bca9b 100644 --- a/scrypt/tests/test_scrypt_py3x.py +++ b/scrypt/tests/test_scrypt_py3x.py @@ -1,8 +1,7 @@ -# -*- coding: utf-8 -*- +import unittest as testm +from sys import version_info -from sys import version_info, exit import scrypt -import unittest as testm @testm.skipIf(version_info < (3, 0, 0, 'final', 0), "Tests for Python 3 only") @@ -11,34 +10,37 @@ class TestScryptForPy3(testm.TestCase): def setUp(self): self.input = "message" self.password = "password" - self.byte_text = b'\xe1\x93\x84\xe1\x93\x87\xe1\x95\x97\xe1\x92\xbb\xe1\x92\xa5\xe1\x90\x85\xe1\x91\xa6' + self.byte_text = ( + b'\xe1\x93\x84\xe1\x93\x87\xe1\x95\x97' + b'\xe1\x92\xbb\xe1\x92\xa5\xe1\x90\x85\xe1\x91\xa6' + ) self.unicode_text = self.byte_text.decode('utf-8', "strict") def test_py3_encrypt_allows_bytes_input(self): - """Test Py3 encrypt allows unicode input""" + """Test Py3 encrypt allows unicode input.""" s = scrypt.encrypt(self.byte_text, self.password, 0.1) m = scrypt.decrypt(s, self.password) self.assertEqual(bytes(m.encode("utf-8")), self.byte_text) def test_py3_encrypt_allows_bytes_password(self): - """Test Py3 encrypt allows unicode password""" + """Test Py3 encrypt allows unicode password.""" s = scrypt.encrypt(self.input, self.byte_text, 0.1) m = scrypt.decrypt(s, self.byte_text) self.assertEqual(m, self.input) def test_py3_encrypt_returns_bytes(self): - """Test Py3 encrypt return bytes""" + """Test Py3 encrypt return bytes.""" s = scrypt.encrypt(self.input, self.password, 0.1) self.assertTrue(isinstance(s, bytes)) def test_py3_decrypt_returns_unicode_string(self): - """Test Py3 decrypt returns Unicode UTF-8 string""" + """Test Py3 decrypt returns Unicode UTF-8 string.""" s = scrypt.encrypt(self.input, self.password, 0.1) m = scrypt.decrypt(s, self.password) self.assertTrue(isinstance(m, str)) def test_py3_hash_returns_bytes(self): - """Test Py3 hash return bytes""" + """Test Py3 hash return bytes.""" h = scrypt.hash(self.input, self.password) self.assertTrue(isinstance(h, bytes)) diff --git a/setup.py b/setup.py index 9121ea6..c83dc84 100644 --- a/setup.py +++ b/setup.py @@ -1,11 +1,10 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- -from setuptools import setup, Extension - -import sys +import os import platform import struct -import os +import sys + +from setuptools import Extension, setup includes = [] libraries = [] @@ -15,32 +14,38 @@ if sys.platform.startswith('linux'): - define_macros = [('HAVE_CLOCK_GETTIME', '1'), - ('HAVE_LIBRT', '1'), - ('HAVE_POSIX_MEMALIGN', '1'), - ('HAVE_STRUCT_SYSINFO', '1'), - ('HAVE_STRUCT_SYSINFO_MEM_UNIT', '1'), - ('HAVE_STRUCT_SYSINFO_TOTALRAM', '1'), - ('HAVE_SYSINFO', '1'), - ('HAVE_SYS_SYSINFO_H', '1'), - ('_FILE_OFFSET_BITS', '64')] + define_macros = [ + ('HAVE_CLOCK_GETTIME', '1'), + ('HAVE_LIBRT', '1'), + ('HAVE_POSIX_MEMALIGN', '1'), + ('HAVE_STRUCT_SYSINFO', '1'), + ('HAVE_STRUCT_SYSINFO_MEM_UNIT', '1'), + ('HAVE_STRUCT_SYSINFO_TOTALRAM', '1'), + ('HAVE_SYSINFO', '1'), + ('HAVE_SYS_SYSINFO_H', '1'), + ('_FILE_OFFSET_BITS', '64'), + ] libraries = ['crypto', 'rt'] includes = ['/usr/local/include', '/usr/include'] CFLAGS.append('-O2') elif sys.platform.startswith('win32') and os.environ.get('MSYSTEM'): msys2_env = os.getenv('MSYSTEM') - print('Building for MSYS2 {!r} environment'.format(msys2_env)) - if msys2_env not in ('UCRT64','MSYS'): - print('py-scrypt is untested with environment {!r}: you may experience problems'.format(msys2_env)) + print(f'Building for MSYS2 {msys2_env!r} environment') + if msys2_env not in ('UCRT64', 'MSYS'): + print( + 'py-scrypt is untested with environment {!r}: you may experience problems'.format( + msys2_env + ) + ) includes = { - 'UCRT64': [], - 'MSYS': ['/mingw64/include'], - 'MINGW32': ['/mingw32/include'], - 'MINGW64': ['/mingw64/include'], - 'CLANG32': ['/clang32/include'], - 'CLANG64': ['/clang64/include'], + 'UCRT64': [], + 'MSYS': ['/mingw64/include'], + 'MINGW32': ['/mingw32/include'], + 'MINGW64': ['/mingw64/include'], + 'CLANG32': ['/clang32/include'], + 'CLANG64': ['/clang64/include'], 'CLANGARM64': ['/clangarm64/include'], - }.get(msys2_env,[]) + }.get(msys2_env, []) define_macros = [] libraries = ['libcrypto'] CFLAGS.append('-O2') @@ -49,31 +54,35 @@ extra_sources = ['scrypt-windows-stubs/gettimeofday.c'] if struct.calcsize('P') == 8: - if os.path.isdir('c:\OpenSSL-v111-Win64') and sys.version_info[0] >= 3 and sys.version_info[1] > 4: - openssl_dir = 'c:\OpenSSL-v111-Win64' - elif os.path.isdir('c:\Program Files\OpenSSL-Win64'): - openssl_dir = 'c:\Program Files\OpenSSL-Win64' - elif os.path.isdir('c:\Program Files\OpenSSL'): - openssl_dir = 'c:\Program Files\OpenSSL' + if ( + os.path.isdir(r'c:\OpenSSL-v111-Win64') + and sys.version_info[0] >= 3 + and sys.version_info[1] > 4 + ): + openssl_dir = r'c:\OpenSSL-v111-Win64' + elif os.path.isdir(r'c:\Program Files\OpenSSL-Win64'): + openssl_dir = r'c:\Program Files\OpenSSL-Win64' + elif os.path.isdir(r'c:\Program Files\OpenSSL'): + openssl_dir = r'c:\Program Files\OpenSSL' else: - openssl_dir = 'c:\OpenSSL-Win64' - library_dirs = [openssl_dir + '\lib'] - includes = [openssl_dir + '\include', 'scrypt-windows-stubs/include'] + openssl_dir = r'c:\OpenSSL-Win64' + library_dirs = [openssl_dir + r'\lib'] + includes = [openssl_dir + r'\include', 'scrypt-windows-stubs/include'] else: - if os.path.isdir('c:\OpenSSL-v111-Win32'): - openssl_dir = 'c:\OpenSSL-v111-Win32' - elif os.path.isdir('c:\Program Files (x86)\OpenSSL-Win32'): - openssl_dir = 'c:\Program Files (x86)\OpenSSL-Win32' - elif os.path.isdir('c:\Program Files (x86)\OpenSSL'): - openssl_dir = 'c:\Program Files (x86)\OpenSSL' + if os.path.isdir(r'c:\OpenSSL-v111-Win32'): + openssl_dir = r'c:\OpenSSL-v111-Win32' + elif os.path.isdir(r'c:\Program Files (x86)\OpenSSL-Win32'): + openssl_dir = r'c:\Program Files (x86)\OpenSSL-Win32' + elif os.path.isdir(r'c:\Program Files (x86)\OpenSSL'): + openssl_dir = r'c:\Program Files (x86)\OpenSSL' else: - openssl_dir = 'c:\OpenSSL-Win32' - library_dirs = [openssl_dir + '\lib'] - includes = [openssl_dir + '\include', 'scrypt-windows-stubs/include'] + openssl_dir = r'c:\OpenSSL-Win32' + library_dirs = [openssl_dir + r'\lib'] + includes = [openssl_dir + r'\include', 'scrypt-windows-stubs/include'] windows_link_legacy_openssl = os.environ.get( "SCRYPT_WINDOWS_LINK_LEGACY_OPENSSL", None ) - if windows_link_legacy_openssl is None: + if windows_link_legacy_openssl is None: libraries = ['libcrypto_static'] else: libraries = ['libeay32'] @@ -81,72 +90,80 @@ elif sys.platform.startswith('darwin') and platform.mac_ver()[0] < '10.6': define_macros = [('HAVE_SYSCTL_HW_USERMEM', '1')] - # disable for travis + # disable for travis libraries = ['crypto'] elif sys.platform.startswith('darwin'): - define_macros = [('HAVE_POSIX_MEMALIGN', '1'), - ('HAVE_SYSCTL_HW_USERMEM', '1')] - # disable for travis + define_macros = [('HAVE_POSIX_MEMALIGN', '1'), ('HAVE_SYSCTL_HW_USERMEM', '1')] + # disable for travis libraries = ['crypto'] else: - define_macros = [('HAVE_POSIX_MEMALIGN', '1'), - ('HAVE_SYSCTL_HW_USERMEM', '1')] + define_macros = [('HAVE_POSIX_MEMALIGN', '1'), ('HAVE_SYSCTL_HW_USERMEM', '1')] libraries = ['crypto'] scrypt_module = Extension( '_scrypt', - sources=['src/scrypt.c', - 'scrypt-1.2.1/lib/crypto/crypto_scrypt_smix_sse2.c', - 'scrypt-1.2.1/lib/crypto/crypto_scrypt_smix.c', - 'scrypt-1.2.1/lib/crypto/crypto_scrypt.c', - 'scrypt-1.2.1/lib/scryptenc/scryptenc.c', - 'scrypt-1.2.1/lib/scryptenc/scryptenc_cpuperf.c', - 'scrypt-1.2.1/lib/util/memlimit.c', - 'scrypt-1.2.1/libcperciva/alg/sha256.c', - 'scrypt-1.2.1/libcperciva/crypto/crypto_aes_aesni.c', - 'scrypt-1.2.1/libcperciva/crypto/crypto_aes.c', - 'scrypt-1.2.1/libcperciva/crypto/crypto_aesctr.c', - 'scrypt-1.2.1/libcperciva/crypto/crypto_entropy.c', - 'scrypt-1.2.1/libcperciva/util/entropy.c', - 'scrypt-1.2.1/libcperciva/util/insecure_memzero.c', - 'scrypt-1.2.1/libcperciva/util/warnp.c', - 'scrypt-1.2.1/libcperciva/util/humansize.c', - 'scrypt-1.2.1/libcperciva/util/asprintf.c'] + extra_sources, - include_dirs=['scrypt-1.2.1', - 'scrypt-1.2.1/lib', - 'scrypt-1.2.1/lib/scryptenc', - 'scrypt-1.2.1/lib/crypto', - 'scrypt-1.2.1/lib/util', - 'scrypt-1.2.1/libcperciva/cpusupport', - 'scrypt-1.2.1/libcperciva/alg', - 'scrypt-1.2.1/libcperciva/util', - 'scrypt-1.2.1/libcperciva/crypto'] + includes, + sources=[ + 'src/scrypt.c', + 'scrypt-1.2.1/lib/crypto/crypto_scrypt_smix_sse2.c', + 'scrypt-1.2.1/lib/crypto/crypto_scrypt_smix.c', + 'scrypt-1.2.1/lib/crypto/crypto_scrypt.c', + 'scrypt-1.2.1/lib/scryptenc/scryptenc.c', + 'scrypt-1.2.1/lib/scryptenc/scryptenc_cpuperf.c', + 'scrypt-1.2.1/lib/util/memlimit.c', + 'scrypt-1.2.1/libcperciva/alg/sha256.c', + 'scrypt-1.2.1/libcperciva/crypto/crypto_aes_aesni.c', + 'scrypt-1.2.1/libcperciva/crypto/crypto_aes.c', + 'scrypt-1.2.1/libcperciva/crypto/crypto_aesctr.c', + 'scrypt-1.2.1/libcperciva/crypto/crypto_entropy.c', + 'scrypt-1.2.1/libcperciva/util/entropy.c', + 'scrypt-1.2.1/libcperciva/util/insecure_memzero.c', + 'scrypt-1.2.1/libcperciva/util/warnp.c', + 'scrypt-1.2.1/libcperciva/util/humansize.c', + 'scrypt-1.2.1/libcperciva/util/asprintf.c', + ] + + extra_sources, + include_dirs=[ + 'scrypt-1.2.1', + 'scrypt-1.2.1/lib', + 'scrypt-1.2.1/lib/scryptenc', + 'scrypt-1.2.1/lib/crypto', + 'scrypt-1.2.1/lib/util', + 'scrypt-1.2.1/libcperciva/cpusupport', + 'scrypt-1.2.1/libcperciva/alg', + 'scrypt-1.2.1/libcperciva/util', + 'scrypt-1.2.1/libcperciva/crypto', + ] + + includes, define_macros=[('HAVE_CONFIG_H', None)] + define_macros, extra_compile_args=CFLAGS, library_dirs=library_dirs, - libraries=libraries) + libraries=libraries, +) -setup(name='scrypt', - version='0.8.22', - description='Bindings for the scrypt key derivation function library', - author='Magnus Hallin', - author_email='mhallin@gmail.com', - maintainer="Holger Nahrstaedt", - maintainer_email="nahrstaedt@gmail.com", - url='https://github.com/holgern/py-scrypt', - packages=['scrypt', 'scrypt.tests'], - package_data={'scrypt': ['tests/*.csv']}, - ext_modules=[scrypt_module], - classifiers=['Development Status :: 4 - Beta', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: BSD License', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Topic :: Security :: Cryptography', - 'Topic :: Software Development :: Libraries'], - license='2-clause BSD', - long_description=open('README.rst').read()) +setup( + name='scrypt', + version='0.8.21', + description='Bindings for the scrypt key derivation function library', + author='Magnus Hallin', + author_email='mhallin@gmail.com', + maintainer="Holger Nahrstaedt", + maintainer_email="nahrstaedt@gmail.com", + url='https://github.com/holgern/py-scrypt', + packages=['scrypt', 'scrypt.tests'], + package_data={'scrypt': ['tests/*.csv']}, + ext_modules=[scrypt_module], + classifiers=[ + 'Development Status :: 4 - Beta', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: BSD License', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Topic :: Security :: Cryptography', + 'Topic :: Software Development :: Libraries', + ], + license='2-clause BSD', + long_description=open('README.rst').read(), +) diff --git a/util/travis_osx_install.sh b/util/travis_osx_install.sh index 34337f0..38ef5da 100644 --- a/util/travis_osx_install.sh +++ b/util/travis_osx_install.sh @@ -68,4 +68,4 @@ source ~/.venv/bin/activate pip install --upgrade pip pip install --upgrade wheel pip install tox -pip install delocate +pip install delocate