diff --git a/.azure-pipelines/wheel-builder.yml b/.azure-pipelines/wheel-builder.yml new file mode 100644 index 0000000000000000000000000000000000000000..0859aefd9f413bca4e8ab7099d26c498ca5d4f25_LmF6dXJlLXBpcGVsaW5lcy93aGVlbC1idWlsZGVyLnltbA== --- /dev/null +++ b/.azure-pipelines/wheel-builder.yml @@ -0,0 +1,160 @@ +trigger: none +pr: none + +jobs: + - job: 'macOS' + pool: + vmImage: 'macOS-10.14' + strategy: + matrix: + Python27: + python.version: '2.7' + PYTHON_DOWNLOAD_URL: "https://www.python.org/ftp/python/2.7.16/python-2.7.16-macosx10.6.pkg" + PYTHON_BIN_PATH: /Library/Frameworks/Python.framework/Versions/2.7/bin/python + Python3: + python.version: '3.4' + PYTHON_DOWNLOAD_URL: "https://www.python.org/ftp/python/3.7.3/python-3.7.3-macosx10.6.pkg" + PYTHON_BIN_PATH: /Library/Frameworks/Python.framework/Versions/3.7/bin/python3 + steps: + - script: | + set -e + set -x + + curl "$PYTHON_DOWNLOAD_URL" -o python.pkg + sudo installer -pkg python.pkg -target / + displayName: Download and install Python + + - script: $PYTHON_BIN_PATH -m pip install -U virtualenv + displayName: Install virtualenv + - script: $PYTHON_BIN_PATH -m virtualenv .venv + displayName: Create virtualenv + - script: .venv/bin/pip install -U wheel + displayName: Update wheel to the latest version + - script: .venv/bin/pip install cffi six + displayName: Install our Python dependencies + + - script: | + set -e + set -x + + REGEX="3\.([0-9])*" + if [[ "$PYTHON_VERSION" =~ $REGEX ]]; then + PY_LIMITED_API="--build-option --py-limited-api=cp3${BASH_REMATCH[1]}" + fi + + .venv/bin/pip wheel bcrypt --no-use-pep517 --wheel-dir=wheelhouse --no-binary bcrypt --no-deps $PY_LIMITED_API + displayName: Build the wheel + - script: .venv/bin/pip install --no-index -f wheelhouse bcrypt + displayName: Test installing the wheel + - script: | + .venv/bin/python -c "import bcrypt;password = b'super secret password';hashed = bcrypt.hashpw(password, bcrypt.gensalt());bcrypt.checkpw(password, hashed)" + displayName: Test the installed wheel + - task: PublishBuildArtifacts@1 + inputs: + pathToPublish: wheelhouse/ + artifactName: bcrypt-macos-python$(python.version) + + - job: 'manylinux1' + pool: + vmImage: 'ubuntu-16.04' + container: 'pyca/cryptography-manylinux1:x86_64' + strategy: + matrix: + Python27m: + PYTHON_VERSION: 'cp27-cp27m' + Python27mu: + PYTHON_VERSION: 'cp27-cp27mu' + Python3m: + PYTHON_VERSION: 'cp34-cp34m' + steps: + - script: /opt/python/$PYTHON_VERSION/bin/python -m virtualenv .venv + displayName: Create virtualenv + - script: .venv/bin/pip install cffi six + displayName: Install our Python dependencies + - script: | + set -e + set -x + + REGEX="cp3([0-9])*" + if [[ "$PYTHON_VERSION" =~ $REGEX ]]; then + PY_LIMITED_API="--build-option --py-limited-api=cp3${BASH_REMATCH[1]}" + fi + .venv/bin/pip wheel bcrypt --no-use-pep517 --no-binary bcrypt --no-deps --wheel-dir=tmpwheelhouse $PY_LIMITED_API + displayName: Build the wheel + - script: auditwheel repair tmpwheelhouse/bcrypt*.whl -w wheelhouse/ + displayName: Run auditwheel + - script: .venv/bin/pip install bcrypt --no-index -f wheelhouse/ + displayName: Test installing the wheel + - script: | + .venv/bin/python -c "import bcrypt;password = b'super secret password';hashed = bcrypt.hashpw(password, bcrypt.gensalt());bcrypt.checkpw(password, hashed)" + displayName: Test the installed wheel + - task: PublishBuildArtifacts@1 + inputs: + pathToPublish: wheelhouse/ + artifactName: bcrypt-manylinux1-$(PYTHON_VERSION) + + - job: 'windows' + pool: + vmImage: 'windows-2019' + container: $[variables.containerImage] + strategy: + matrix: + Python27-x86: + containerImage: 'pyca/cryptography-runner-windows:py27-x86' + PYTHON_VERSION: '27' + WINDOWS_ARCH: 'x86' + Python27-x86-64: + containerImage: 'pyca/cryptography-runner-windows:py27-x86_64' + PYTHON_VERSION: '27' + WINDOWS_ARCH: 'x86_64' + Python34-x86: + containerImage: 'pyca/cryptography-runner-windows:py34-x86' + PYTHON_VERSION: '34' + WINDOWS_ARCH: 'x86' + Python34-x86-64: + containerImage: 'pyca/cryptography-runner-windows:py34-x86_64' + PYTHON_VERSION: '34' + WINDOWS_ARCH: 'x86_64' + Python35-x86: + containerImage: 'pyca/cryptography-runner-windows:py35-x86' + PYTHON_VERSION: '35' + WINDOWS_ARCH: 'x86' + Python35-x86-64: + containerImage: 'pyca/cryptography-runner-windows:py35-x86_64' + PYTHON_VERSION: '35' + WINDOWS_ARCH: 'x86_64' + Python36-x86: + containerImage: 'pyca/cryptography-runner-windows:py3-x86' + PYTHON_VERSION: '36' + WINDOWS_ARCH: 'x86' + Python36-x86-64: + containerImage: 'pyca/cryptography-runner-windows:py3-x86_64' + PYTHON_VERSION: '36' + WINDOWS_ARCH: 'x86_64' + Python37-x86: + containerImage: 'pyca/cryptography-runner-windows:py3-x86' + PYTHON_VERSION: '37' + WINDOWS_ARCH: 'x86' + Python37-x86-64: + containerImage: 'pyca/cryptography-runner-windows:py3-x86_64' + PYTHON_VERSION: '37' + WINDOWS_ARCH: 'x86_64' + steps: + - script: '"C:/Python%PYTHON_VERSION%/Scripts/pip" install wheel cffi six' + displayName: Install wheel and our Python dependencies + - script: | + C:/Python%PYTHON_VERSION%/Scripts/pip wheel bcrypt --no-use-pep517 --wheel-dir=wheelhouse --no-binary bcrypt + displayName: Build the wheel + - script: '"C:/Python%PYTHON_VERSION%/Scripts/pip" install -f wheelhouse bcrypt --no-index' + displayName: Test installing the wheel + - script: | + "C:/Python%PYTHON_VERSION%/python" -c "import bcrypt;password = b'super secret password';hashed = bcrypt.hashpw(password, bcrypt.gensalt());bcrypt.checkpw(password, hashed)" + displayName: Test the installed wheel + - script: mkdir bcrypt-wheelhouse + displayName: Create a directory for placing the final wheel in + - script: move wheelhouse\bcrypt*.whl bcrypt-wheelhouse\ + displayName: Move the bcrypt wheel into the final wheel house + - task: PublishBuildArtifacts@1 + inputs: + pathToPublish: bcrypt-wheelhouse/ + artifactName: bcrypt-windows-$(WINDOWS_ARCH)-python$(PYTHON_VERSION) diff --git a/.jenkins/Jenkinsfile-wheel-builder b/.jenkins/Jenkinsfile-wheel-builder deleted file mode 100644 index 08bdbdd29ce80b0282162360728760f600b7af49_LmplbmtpbnMvSmVua2luc2ZpbGUtd2hlZWwtYnVpbGRlcg==..0000000000000000000000000000000000000000 --- a/.jenkins/Jenkinsfile-wheel-builder +++ /dev/null @@ -1,152 +0,0 @@ -def configs = [ - [ - label: 'windows', - versions: ['py26', 'py27', 'py34', 'py35', 'py36'], - ], - [ - label: 'windows64', - versions: ['py26', 'py27', 'py34', 'py35', 'py36'], - ], - [ - label: 'sierra', - versions: ['py26', 'py27', 'py34', 'py35', 'py36'], - ], - [ - label: 'docker', - imageName: 'quay.io/pypa/manylinux1_x86_64', - versions: [ - 'cp26-cp26m', 'cp26-cp26mu', - 'cp27-cp27m', 'cp27-cp27mu', 'cp33-cp33m', - 'cp34-cp34m', 'cp35-cp35m', 'cp36-cp36m' - ], - ], - [ - label: 'docker', - imageName: 'quay.io/pypa/manylinux1_i686', - versions: [ - 'cp26-cp26m', 'cp26-cp26mu', - 'cp27-cp27m', 'cp27-cp27mu', 'cp33-cp33m', - 'cp34-cp34m', 'cp35-cp35m', 'cp36-cp36m' - ], - ], -] - - -def build(version, label, imageName) { - try { - timeout(time: 30, unit: 'MINUTES') { - if (label.contains("windows")) { - def pythonPath = [ - py26: "C:\\Python26\\python.exe", - py27: "C:\\Python27\\python.exe", - py33: "C:\\Python33\\python.exe", - py34: "C:\\Python34\\python.exe", - py35: "C:\\Python35\\python.exe", - py36: "C:\\Python36\\python.exe" - ] - bat """ - wmic qfe - @set PATH="C:\\Python27";"C:\\Python27\\Scripts";%PATH% - @set PYTHON="${pythonPath[version]}" - - virtualenv -p %PYTHON% .release - call .release\\Scripts\\activate - pip install wheel virtualenv - pip wheel bcrypt --wheel-dir=wheelhouse --no-binary bcrypt - pip install -f wheelhouse bcrypt --no-index - python -c "import bcrypt;password = b'super secret password';hashed = bcrypt.hashpw(password, bcrypt.gensalt());bcrypt.checkpw(password, hashed)" - """ - } else if (label.contains("sierra")) { - def pythonPath = [ - py26: "/usr/bin/python2.6", - py27: "/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7", - py34: "/Library/Frameworks/Python.framework/Versions/3.4/bin/python3.4", - py35: "/Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5", - py36: "/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6", - ] - ansiColor { - sh """#!/usr/bin/env bash - set -xe - # output the list of things we've installed as a point in time check of how up - # to date the builder is - /usr/sbin/system_profiler SPInstallHistoryDataType - - # Jenkins logs in as a non-interactive shell, so we don't even have /usr/local/bin in PATH - export PATH="/usr/local/bin:\${PATH}" - export PATH="/Users/jenkins/.pyenv/shims:\${PATH}" - - printenv - - virtualenv .venv -p ${pythonPath[version]} - source .venv/bin/activate - pip install -U wheel # upgrade wheel to latest before we use it to build the wheel - pip wheel bcrypt --wheel-dir=wheelhouse --no-binary bcrypt - pip install -f wheelhouse bcrypt --no-index - python -c "import bcrypt;password = b'super secret password';hashed = bcrypt.hashpw(password, bcrypt.gensalt());bcrypt.checkpw(password, hashed)" - """ - } - } else if (label.contains("docker")) { - linux32 = "" - if (imageName.contains("i686")) { - linux32 = "linux32" - } - sh """#!/usr/bin/env bash - set -x -e - # Because we are doing this as root in the container, but we write to a mounted dir that is outside the container - # we need to make sure we set these files writable such that the jenkins user can delete them afterwards - mkdir -p tmpwheelhouse - mkdir -p wheelhouse - chmod -R 777 tmpwheelhouse - chmod -R 777 wheelhouse - - $linux32 /opt/python/$version/bin/pip install cffi six - $linux32 /opt/python/$version/bin/pip wheel --no-binary bcrypt --no-deps bcrypt -w tmpwheelhouse/ - $linux32 auditwheel repair tmpwheelhouse/bcrypt*.whl -w wheelhouse/ - $linux32 /opt/python/$version/bin/pip install bcrypt --no-index -f wheelhouse/ - $linux32 /opt/python/$version/bin/python -c "import bcrypt;password = b'super secret password';hashed = bcrypt.hashpw(password, bcrypt.gensalt());bcrypt.checkpw(password, hashed)" - """ - } - archiveArtifacts artifacts: "**/wheelhouse/bcrypt*.whl" - } - } finally { - deleteDir() - } - -} - -def builders = [:] -for (config in configs) { - def label = config["label"] - def versions = config["versions"] - - for (_version in versions) { - def version = _version - - if (label.contains("docker")) { - def imageName = config["imageName"] - def combinedName = "${imageName}-${version}" - builders[combinedName] = { - node(label) { - stage(combinedName) { - def buildImage = docker.image(imageName) - buildImage.pull() - buildImage.inside("-u root") { - build(version, label, imageName) - } - } - } - } - } else { - def combinedName = "${label}-${version}" - builders[combinedName] = { - node(label) { - stage(combinedName) { - build(version, label, "") - } - } - } - } - } -} - -parallel builders diff --git a/.travis.yml b/.travis.yml index 08bdbdd29ce80b0282162360728760f600b7af49_LnRyYXZpcy55bWw=..0859aefd9f413bca4e8ab7099d26c498ca5d4f25_LnRyYXZpcy55bWw= 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,5 @@ matrix: include: - - python: 2.6 - env: TOXENV=py26 CC=gcc - python: 2.7 env: TOXENV=py27 CC=gcc @@ -9,10 +7,8 @@ - python: 2.7 env: TOXENV=py27 CC=gcc - - python: 3.3 - env: TOXENV=py33 CC=gcc - python: 3.4 env: TOXENV=py34 CC=gcc - python: 3.5 env: TOXENV=py35 CC=gcc - python: 3.6 env: TOXENV=py36 CC=gcc @@ -13,8 +9,14 @@ - python: 3.4 env: TOXENV=py34 CC=gcc - python: 3.5 env: TOXENV=py35 CC=gcc - python: 3.6 env: TOXENV=py36 CC=gcc + - python: 3.6 + env: TOXENV=py36 CC=gcc + - python: 3.7 + env: TOXENV=py37 CC=gcc + dist: xenial + sudo: true - python: pypy env: TOXENV=pypy CC=gcc @@ -19,6 +21,4 @@ - python: pypy env: TOXENV=pypy CC=gcc - - python: 2.6 - env: TOXENV=py26 CC=clang - python: 2.7 env: TOXENV=py27 CC=clang @@ -23,10 +23,8 @@ - python: 2.7 env: TOXENV=py27 CC=clang - - python: 3.3 - env: TOXENV=py33 CC=clang - python: 3.4 env: TOXENV=py34 CC=clang - python: 3.5 env: TOXENV=py35 CC=clang - python: 3.6 env: TOXENV=py36 CC=clang @@ -27,9 +25,13 @@ - python: 3.4 env: TOXENV=py34 CC=clang - python: 3.5 env: TOXENV=py35 CC=clang - python: 3.6 env: TOXENV=py36 CC=clang + - python: 3.7 + env: TOXENV=py37 CC=clang + dist: xenial + sudo: true - python: pypy env: TOXENV=pypy CC=clang - python: 2.7 @@ -37,14 +39,6 @@ - env: TOXENV=packaging - python: 3.5 env: TOXENV=py3pep8 - - language: generic - os: osx - osx_image: xcode7.3 - env: TOXENV=py27 - - language: generic - os: osx - osx_image: xcode7.3 - env: TOXENV=py35 install: .travis/install.sh @@ -53,3 +47,17 @@ branches: only: - master + - /\d+\.\d+\.x/ + - /\d+\.\d+(\.\d+)?/ + +notifications: +irc: + channels: + # This is set to a secure variable to prevent forks from notifying the + # IRC channel whenever they fail a build. This can be removed when travis + # implements https://github.com/travis-ci/travis-ci/issues/1094. + # The value encrypted here was created via + # travis encrypt "irc.freenode.org#cryptography-dev" + - secure: "SYCVjMUGx5sJ5iEdgEz1iUG6QC7Ep1CGlAatbW8AmNTCurnJHN1Ezm1ix3mbGDevdeyQC/eC1iOXEEj6jhImUziUAG1YtpgHsJ1H3J5MNU/WUNuj6TGESa9iMq6K2cAAIWGvDR0hx4tO5/p09GevL9GVmc2IelUKuGKNkOVRGrI=" + use_notice: true + skip_join: true diff --git a/.travis/install.sh b/.travis/install.sh index 08bdbdd29ce80b0282162360728760f600b7af49_LnRyYXZpcy9pbnN0YWxsLnNo..0859aefd9f413bca4e8ab7099d26c498ca5d4f25_LnRyYXZpcy9pbnN0YWxsLnNo 100755 --- a/.travis/install.sh +++ b/.travis/install.sh @@ -3,35 +3,7 @@ set -e set -x -install_pyenv () { - git clone https://github.com/yyuu/pyenv.git ~/.pyenv - PYENV_ROOT="$HOME/.pyenv" - PATH="$PYENV_ROOT/bin:$PATH" - eval "$(pyenv init -)" -} - -if [[ "$(uname -s)" == 'Darwin' ]]; then - install_pyenv - case "${TOXENV}" in - py27) - curl -O https://bootstrap.pypa.io/get-pip.py - python get-pip.py --user - ;; - py35) - pyenv install 3.5.1 - pyenv global 3.5.1 - ;; - esac - pyenv rehash - python -m pip install --user virtualenv -else - if [[ "${TOXENV}" == "pypy" ]]; then - install_pyenv - pyenv install pypy-2.6.0 - pyenv global pypy-2.6.0 - fi - pip install virtualenv -fi +pip install virtualenv python -m virtualenv ~/.venv source ~/.venv/bin/activate diff --git a/.travis/run.sh b/.travis/run.sh index 08bdbdd29ce80b0282162360728760f600b7af49_LnRyYXZpcy9ydW4uc2g=..0859aefd9f413bca4e8ab7099d26c498ca5d4f25_LnRyYXZpcy9ydW4uc2g= 100755 --- a/.travis/run.sh +++ b/.travis/run.sh @@ -3,20 +3,5 @@ set -e set -x -init_pyenv () { - PYENV_ROOT="$HOME/.pyenv" - PATH="$PYENV_ROOT/bin:$PATH" - eval "$(pyenv init -)" -} - -if [[ "$(uname -s)" == "Darwin" ]]; then - init_pyenv -else - if [[ "${TOXENV}" == "pypy" ]]; then - init_pyenv - pyenv global pypy-2.6.0 - fi -fi - source ~/.venv/bin/activate tox diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index 08bdbdd29ce80b0282162360728760f600b7af49_SmVua2luc2ZpbGU=..0000000000000000000000000000000000000000 --- a/Jenkinsfile +++ /dev/null @@ -1,61 +0,0 @@ -def configs = [ - [ - label: 'windows', - toxenvs: ['py26', 'py27', 'py33', 'py34', 'py35', 'py36'], - ], - [ - label: 'windows64', - toxenvs: ['py26', 'py27', 'py33', 'py34', 'py35', 'py36'], - ], - [ - label: 'freebsd11', - toxenvs: ['py27'], - ], -] - -def build(label, toxenv) { - try { - timeout(time: 5, unit: 'MINUTES') { - if (label.startsWith("windows")) { - bat """ - @set PATH="C:\\Python27";"C:\\Python27\\Scripts";%PATH% - tox -r -e $toxenv - """ - } else { - ansiColor('xterm') { - sh "tox -r -e $toxenv -- --color=yes" - } - } - } - } finally { - deleteDir() - } - -} - -def builders = [:] -for (config in configs) { - def label = config["label"] - def toxenvs = config["toxenvs"] - - // We need to use a temporary variable here and then - // bind it in the for loop so that it is properly captured - // by the closure - for (_toxenv in toxenvs) { - def toxenv = _toxenv - def combinedName = "${label}-${toxenv}" - - builders[combinedName] = { - node(label) { - stage("Checkout") { - checkout scm - } - stage(combinedName) { - build(label, toxenv) - } - } - } - } -} - -parallel builders diff --git a/MANIFEST.in b/MANIFEST.in index 08bdbdd29ce80b0282162360728760f600b7af49_TUFOSUZFU1QuaW4=..0859aefd9f413bca4e8ab7099d26c498ca5d4f25_TUFOSUZFU1QuaW4= 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,8 +1,10 @@ include LICENSE README.rst +include pyproject.toml + include tox.ini .coveragerc include src/build_bcrypt.py recursive-include src/_csrc * recursive-include tests *.py @@ -3,8 +5,8 @@ include tox.ini .coveragerc include src/build_bcrypt.py recursive-include src/_csrc * recursive-include tests *.py -exclude requirements.txt tasks.py .travis.yml wheel-scripts Jenkinsfile +exclude requirements.txt release.py .travis.yml azure-pipelines.yml @@ -10,7 +12,5 @@ -exclude .jenkins -recursive-exclude .jenkins * - -recursive-exclude wheel-scripts * +exclude .azure-pipelines +recursive-exclude .azure-pipelines * prune .travis diff --git a/README.rst b/README.rst index 08bdbdd29ce80b0282162360728760f600b7af49_UkVBRE1FLnJzdA==..0859aefd9f413bca4e8ab7099d26c498ca5d4f25_UkVBRE1FLnJzdA== 100644 --- a/README.rst +++ b/README.rst @@ -2,9 +2,9 @@ ====== .. image:: https://img.shields.io/pypi/v/bcrypt.svg - :target: https://pypi.python.org/pypi/bcrypt/ + :target: https://pypi.org/project/bcrypt/ :alt: Latest Version .. image:: https://travis-ci.org/pyca/bcrypt.svg?branch=master :target: https://travis-ci.org/pyca/bcrypt @@ -6,9 +6,12 @@ :alt: Latest Version .. image:: https://travis-ci.org/pyca/bcrypt.svg?branch=master :target: https://travis-ci.org/pyca/bcrypt -Modern password hashing for your software and your servers +.. image:: https://dev.azure.com/pyca/bcrypt/_apis/build/status/bcrypt-CI?branchName=master + :target: https://dev.azure.com/pyca/bcrypt/_build/latest?definitionId=8&branchName=master + +Good password hashing for your software and your servers Installation @@ -34,6 +37,11 @@ $ sudo yum install gcc libffi-devel python-devel +Alternatives +============ + +While bcrypt remains a good choice for password storage depending on your specific use case you may also want to consider using scrypt (either via `standard library`_ or `cryptography`_) or argon2id via `argon2_cffi`_. + Changelog ========= @@ -37,6 +45,24 @@ Changelog ========= +3.1.6 +----- + +* Added support for compilation on Haiku. + +3.1.5 +----- + +* Added support for compilation on AIX. +* Dropped Python 2.6 and 3.3 support. +* Switched to using ``abi3`` wheels for Python 3. If you are not getting a + wheel on a compatible platform please upgrade your ``pip`` version. + +3.1.4 +----- + +* Fixed compilation with mingw and on illumos. + 3.1.3 ----- * Fixed a compilation issue on Solaris. @@ -158,7 +184,7 @@ ------------- This library should be compatible with py-bcrypt and it will run on Python -2.6+, 3.3+, and PyPy 2.6+. +2.7, 3.4+, and PyPy 2.6+. C Code ------ @@ -172,3 +198,6 @@ identify a vulnerability, we ask you to contact us privately. .. _`same security policy as cryptography`: https://cryptography.io/en/latest/security/ +.. _`standard library`: https://docs.python.org/3/library/hashlib.html#hashlib.scrypt +.. _`argon2_cffi`: https://argon2-cffi.readthedocs.io +.. _`cryptography`: https://cryptography.io/en/latest/hazmat/primitives/key-derivation-functions/#cryptography.hazmat.primitives.kdf.scrypt.Scrypt diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 0000000000000000000000000000000000000000..0859aefd9f413bca4e8ab7099d26c498ca5d4f25_YXp1cmUtcGlwZWxpbmVzLnltbA== --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,89 @@ +trigger: + branches: + include: + - "master" + tags: + include: + - "*" + +jobs: +- job: 'mac' + pool: + vmImage: 'macOS-10.14' + strategy: + matrix: + Python27: + python.version: '2.7' + TOXENV: py27 + Python34: + python.version: '3.4' + TOXENV: py34 + Python35: + python.version: '3.5' + TOXENV: py35 + Python36: + python.version: '3.6' + TOXENV: py36 + Python37: + python.version: '3.7' + TOXENV: py37 + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '$(python.version)' + architecture: 'x64' + + - script: pip install tox + displayName: 'Install tox' + + - script: tox + displayName: 'Run tests' +- job: 'win' + pool: + vmImage: 'windows-2019' + container: $[variables.containerImage] + strategy: + matrix: + Python27-x86: + TOXENV: py27 + containerImage: 'pyca/cryptography-runner-windows:py27-x86' + PYTHON_DIR: 'Python27' + Python27-x86-64: + TOXENV: py27 + containerImage: 'pyca/cryptography-runner-windows:py27-x86_64' + PYTHON_DIR: 'Python27' + Python34-x86: + TOXENV: py34 + containerImage: 'pyca/cryptography-runner-windows:py34-x86' + PYTHON_DIR: 'Python34' + Python34-x86-64: + TOXENV: py34 + containerImage: 'pyca/cryptography-runner-windows:py34-x86_64' + PYTHON_DIR: 'Python34' + Python35-x86: + TOXENV: py35 + containerImage: 'pyca/cryptography-runner-windows:py35-x86' + PYTHON_DIR: 'Python35' + Python35-x86-64: + TOXENV: py35 + containerImage: 'pyca/cryptography-runner-windows:py35-x86_64' + PYTHON_DIR: 'Python35' + Python36-x86: + TOXENV: py36 + containerImage: 'pyca/cryptography-runner-windows:py3-x86' + PYTHON_DIR: 'Python36' + Python36-x86-64: + TOXENV: py36 + containerImage: 'pyca/cryptography-runner-windows:py3-x86_64' + PYTHON_DIR: 'Python36' + Python37-x86: + TOXENV: py37 + containerImage: 'pyca/cryptography-runner-windows:py3-x86' + PYTHON_DIR: 'Python37' + Python37-x86-64: + TOXENV: py37 + containerImage: 'pyca/cryptography-runner-windows:py3-x86_64' + PYTHON_DIR: 'Python37' + steps: + - script: "C:/%PYTHON_DIR%/Scripts/tox" + displayName: 'Run tests' diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000000000000000000000000000000000..0859aefd9f413bca4e8ab7099d26c498ca5d4f25_cHlwcm9qZWN0LnRvbWw= --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,10 @@ +[build-system] +# Must be kept in sync with `setup_requirements` in `setup.py` +requires = [ + "setuptools>=40.8.0", + "wheel", + "cffi>=1.1; python_implementation != 'PyPy'", +] +# Point to the setuptools' PEP517 build backend explicitly to +# disable Pip's fallback guessing +build-backend = "setuptools.build_meta" diff --git a/release.py b/release.py new file mode 100644 index 0000000000000000000000000000000000000000..0859aefd9f413bca4e8ab7099d26c498ca5d4f25_cmVsZWFzZS5weQ== --- /dev/null +++ b/release.py @@ -0,0 +1,102 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import getpass +import glob +import os +import subprocess +import tempfile +import time +import zipfile + +from azure.devops.connection import Connection +from azure.devops.v5_1.build.models import Build + +import click + +from msrest.authentication import BasicAuthentication + + +def run(*args, **kwargs): + print("[running] {0}".format(list(args))) + subprocess.check_call(list(args), **kwargs) + + +def wait_for_build_completed_azure(build_client, build_id): + while True: + build = build_client.get_build("bcrypt", build_id) + if build.finish_time is not None: + break + time.sleep(3) + + +def download_artifacts_azure(build_client, build_id): + artifacts = build_client.get_artifacts("bcrypt", build_id) + paths = [] + for artifact in artifacts: + contents = build_client.get_artifact_content_zip( + "bcrypt", build_id, artifact.name + ) + with tempfile.NamedTemporaryFile() as f: + for chunk in contents: + f.write(chunk) + f.flush() + with zipfile.ZipFile(f.name) as z: + for name in z.namelist(): + if not name.endswith(".whl"): + continue + p = z.open(name) + out_path = os.path.join( + os.path.dirname(__file__), + "dist", + os.path.basename(name), + ) + with open(out_path, "wb") as f: + f.write(p.read()) + paths.append(out_path) + return paths + + +def build_wheels_azure(version): + token = getpass.getpass("Azure personal access token: ") + credentials = BasicAuthentication("", token) + connection = Connection( + base_url="https://dev.azure.com/pyca", creds=credentials + ) + build_client = connection.clients.get_build_client() + [definition] = build_client.get_definitions( + "bcrypt", "bcrypt-wheel-builder" + ) + build_description = Build( + definition=definition, + ) + build = build_client.queue_build( + project="bcrypt", build=build_description + ) + wait_for_build_completed_azure(build_client, build.id) + return download_artifacts_azure(build_client, build.id) + + +@click.command() +@click.argument("version") +def release(version): + """ + ``version`` should be a string like '0.4' or '1.0'. + """ + run("git", "tag", "-s", version, "-m", "{0} release".format(version)) + run("git", "push", "--tags") + + run("python", "setup.py", "sdist") + + packages = glob.glob("dist/bcrypt-{0}*".format(version)) + run("twine", "upload", "-s", *packages) + + azure_wheel_paths = build_wheels_azure(version) + run("twine", "upload", *azure_wheel_paths) + + +if __name__ == "__main__": + release() diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000000000000000000000000000000000000..0859aefd9f413bca4e8ab7099d26c498ca5d4f25_c2V0dXAuY2Zn --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[metadata] +license_file = LICENSE diff --git a/setup.py b/setup.py index 08bdbdd29ce80b0282162360728760f600b7af49_c2V0dXAucHk=..0859aefd9f413bca4e8ab7099d26c498ca5d4f25_c2V0dXAucHk= 100644 --- a/setup.py +++ b/setup.py @@ -54,6 +54,7 @@ author=__about__["__author__"], author_email=__about__["__email__"], + python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", setup_requires=[CFFI_DEPENDENCY], install_requires=[ CFFI_DEPENDENCY, @@ -61,7 +62,7 @@ ], extras_require={ "tests": [ - "pytest>=3.2.1", + "pytest>=3.2.1,!=3.3.0", ], }, tests_require=[ @@ -65,7 +66,7 @@ ], }, tests_require=[ - "pytest>=3.2.1", + "pytest>=3.2.1,!=3.3.0", ], package_dir={"": "src"}, @@ -76,6 +77,8 @@ zip_safe=False, classifiers=[ + "Development Status :: 5 - Production/Stable", + "License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Programming Language :: Python :: 2", @@ -79,6 +82,5 @@ "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Programming Language :: Python :: 2", - "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", @@ -83,6 +85,5 @@ "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", @@ -86,6 +87,7 @@ "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", ], ext_package="bcrypt", diff --git a/src/_csrc/blf.c b/src/_csrc/blf.c index 08bdbdd29ce80b0282162360728760f600b7af49_c3JjL19jc3JjL2JsZi5j..0859aefd9f413bca4e8ab7099d26c498ca5d4f25_c3JjL19jc3JjL2JsZi5j 100644 --- a/src/_csrc/blf.c +++ b/src/_csrc/blf.c @@ -15,10 +15,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products + * 3. The name of the author may not 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 diff --git a/src/_csrc/blf.h b/src/_csrc/blf.h index 08bdbdd29ce80b0282162360728760f600b7af49_c3JjL19jc3JjL2JsZi5o..0859aefd9f413bca4e8ab7099d26c498ca5d4f25_c3JjL19jc3JjL2JsZi5o 100644 --- a/src/_csrc/blf.h +++ b/src/_csrc/blf.h @@ -14,10 +14,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products + * 3. The name of the author may not 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 diff --git a/src/_csrc/portable_endian.h b/src/_csrc/portable_endian.h index 08bdbdd29ce80b0282162360728760f600b7af49_c3JjL19jc3JjL3BvcnRhYmxlX2VuZGlhbi5o..0859aefd9f413bca4e8ab7099d26c498ca5d4f25_c3JjL19jc3JjL3BvcnRhYmxlX2VuZGlhbi5o 100644 --- a/src/_csrc/portable_endian.h +++ b/src/_csrc/portable_endian.h @@ -94,6 +94,10 @@ # include <sys/endian.h> +#elif defined(__HAIKU__) + +# include <endian.h> + #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) # include <sys/endian.h> @@ -180,6 +184,35 @@ # define be64toh(x) BE_64(x) # define le64toh(x) LE_64(x) +#elif defined _AIX /* AIX is always big endian */ +# define be64toh(x) (x) +# define be32toh(x) (x) +# define be16toh(x) (x) +# define le32toh(x) \ + ((((x) & 0xff) << 24) | \ + (((x) & 0xff00) << 8) | \ + (((x) & 0xff0000) >> 8) | \ + (((x) & 0xff000000) >> 24)) +# define le64toh(x) \ + ((((x) & 0x00000000000000ffL) << 56) | \ + (((x) & 0x000000000000ff00L) << 40) | \ + (((x) & 0x0000000000ff0000L) << 24) | \ + (((x) & 0x00000000ff000000L) << 8) | \ + (((x) & 0x000000ff00000000L) >> 8) | \ + (((x) & 0x0000ff0000000000L) >> 24) | \ + (((x) & 0x00ff000000000000L) >> 40) | \ + (((x) & 0xff00000000000000L) >> 56)) +# ifndef htobe64 +# define htobe64(x) be64toh(x) +# endif +# ifndef htobe32 +# define htobe32(x) be32toh(x) +# endif +# ifndef htobe16 +# define htobe16(x) be16toh(x) +# endif + + #else # error platform not supported diff --git a/src/bcrypt/__about__.py b/src/bcrypt/__about__.py index 08bdbdd29ce80b0282162360728760f600b7af49_c3JjL2JjcnlwdC9fX2Fib3V0X18ucHk=..0859aefd9f413bca4e8ab7099d26c498ca5d4f25_c3JjL2JjcnlwdC9fX2Fib3V0X18ucHk= 100644 --- a/src/bcrypt/__about__.py +++ b/src/bcrypt/__about__.py @@ -26,7 +26,7 @@ __summary__ = "Modern password hashing for your software and your servers" __uri__ = "https://github.com/pyca/bcrypt/" -__version__ = "3.1.3" +__version__ = "3.1.7.dev1" __author__ = "The Python Cryptographic Authority developers" __email__ = "cryptography-dev@python.org" diff --git a/src/bcrypt/__init__.py b/src/bcrypt/__init__.py index 08bdbdd29ce80b0282162360728760f600b7af49_c3JjL2JjcnlwdC9fX2luaXRfXy5weQ==..0859aefd9f413bca4e8ab7099d26c498ca5d4f25_c3JjL2JjcnlwdC9fX2luaXRfXy5weQ== 100644 --- a/src/bcrypt/__init__.py +++ b/src/bcrypt/__init__.py @@ -22,8 +22,7 @@ import six -from bcrypt import _bcrypt - +from . import _bcrypt from .__about__ import ( __author__, __copyright__, __email__, __license__, __summary__, __title__, __uri__, __version__, @@ -134,7 +133,9 @@ "Warning: bcrypt.kdf() called with only {0} round(s). " "This few is not secure: the parameter is linear, like PBKDF2.") .format(rounds), - UserWarning) + UserWarning, + stacklevel=2, + ) key = _bcrypt.ffi.new("uint8_t[]", desired_key_bytes) res = _bcrypt.lib.bcrypt_pbkdf( diff --git a/tasks.py b/tasks.py deleted file mode 100644 index 08bdbdd29ce80b0282162360728760f600b7af49_dGFza3MucHk=..0000000000000000000000000000000000000000 --- a/tasks.py +++ /dev/null @@ -1,120 +0,0 @@ -from __future__ import absolute_import, division, print_function - -import getpass -import io -import os -import time - -from clint.textui.progress import Bar as ProgressBar - -import invoke - -import requests - - -JENKINS_URL = "https://jenkins.cryptography.io/job/bcrypt-wheel-builder" - - -def wait_for_build_completed(session): - # Wait 20 seconds before actually checking if the build is complete, to - # ensure that it had time to really start. - time.sleep(20) - while True: - response = session.get( - "{0}/lastBuild/api/json/".format(JENKINS_URL), - headers={ - "Accept": "application/json", - } - ) - response.raise_for_status() - if not response.json()["building"]: - assert response.json()["result"] == "SUCCESS" - break - time.sleep(0.1) - - -def download_artifacts(session): - response = session.get( - "{0}/lastBuild/api/json/".format(JENKINS_URL), - headers={ - "Accept": "application/json" - } - ) - response.raise_for_status() - assert not response.json()["building"] - assert response.json()["result"] == "SUCCESS" - - paths = [] - - last_build_number = response.json()["number"] - for run in response.json()["runs"]: - if run["number"] != last_build_number: - print( - "Skipping {0} as it is not from the latest build ({1})".format( - run["url"], last_build_number - ) - ) - continue - - response = session.get( - run["url"] + "api/json/", - headers={ - "Accept": "application/json", - } - ) - response.raise_for_status() - for artifact in response.json()["artifacts"]: - response = session.get( - "{0}artifact/{1}".format(run["url"], artifact["relativePath"]), - stream=True - ) - assert response.headers["content-length"] - print("Downloading {0}".format(artifact["fileName"])) - bar = ProgressBar( - expected_size=int(response.headers["content-length"]), - filled_char="=" - ) - content = io.BytesIO() - for data in response.iter_content(chunk_size=8192): - content.write(data) - bar.show(content.tell()) - assert bar.expected_size == content.tell() - bar.done() - out_path = os.path.join( - os.path.dirname(__file__), - "dist", - artifact["fileName"], - ) - with open(out_path, "wb") as f: - f.write(content.getvalue()) - paths.append(out_path) - return paths - - -@invoke.task -def release(version): - """ - ``version`` should be a string like '0.4' or '1.0'. - """ - invoke.run("git tag -s {0} -m '{0} release'".format(version)) - invoke.run("git push --tags") - - invoke.run("python setup.py sdist") - - invoke.run( - "twine upload -s dist/bcrypt-{0}*".format(version) - ) - - session = requests.Session() - - token = getpass.getpass("Input the Jenkins token: ") - response = session.post( - "{0}/build?token={1}".format(JENKINS_URL, token), - params={ - "cause": "Building wheels for {0}".format(version) - } - ) - response.raise_for_status() - wait_for_build_completed(session) - paths = download_artifacts(session) - invoke.run("twine upload {0}".format(" ".join(paths))) diff --git a/tests/test_bcrypt.py b/tests/test_bcrypt.py index 08bdbdd29ce80b0282162360728760f600b7af49_dGVzdHMvdGVzdF9iY3J5cHQucHk=..0859aefd9f413bca4e8ab7099d26c498ca5d4f25_dGVzdHMvdGVzdF9iY3J5cHQucHk= 100644 --- a/tests/test_bcrypt.py +++ b/tests/test_bcrypt.py @@ -400,7 +400,9 @@ b"\x43\x66\x6c\x9b\x09\xef\x33\xed\x8c\x27\xe8\xe8\xf3\xe2\xd8\xe6" ]]) def test_kdf(rounds, password, salt, expected): - derived = bcrypt.kdf(password, salt, len(expected), rounds) + derived = bcrypt.kdf( + password, salt, len(expected), rounds, ignore_few_rounds=True + ) assert derived == expected diff --git a/tox.ini b/tox.ini index 08bdbdd29ce80b0282162360728760f600b7af49_dG94LmluaQ==..0859aefd9f413bca4e8ab7099d26c498ca5d4f25_dG94LmluaQ== 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py26,py27,pypy,py33,py34,py35,py36,pep8,py3pep8,packaging +envlist = py27,pypy,py34,py35,py36,py37,pep8,py3pep8,packaging [testenv] extras = @@ -19,7 +19,7 @@ flake8 . [testenv:py3pep8] -basepython = python3.3 +basepython = python3 deps = flake8 flake8-import-order @@ -37,6 +37,7 @@ [flake8] +ignore = W504 exclude = .tox,*.egg select = E,W,F,N,I application-import-names = bcrypt,tests