diff --git a/.github/requirements/publish-requirements.in b/.github/requirements/publish-requirements.in index 1b92e685d4ab..adfe8ec15086 100644 --- a/.github/requirements/publish-requirements.in +++ b/.github/requirements/publish-requirements.in @@ -1,5 +1,8 @@ twine requests -# WARN: changing the requirements here DOES NOT update the dependencies used for publishing at the github workflow, as the process used publish-requirements.txt -# To update publish-requirements.txt according to the dependencies here, run pip-compile --allow-unsafe --generate-hashes publish-requirements.in \ No newline at end of file +# WARN: changing the requirements here DOES NOT update the dependencies used +# for publishing at the github workflow, as the process uses +# `publish-requirements.txt`. +# To update `publish-requirements.txt`, run the command indicated in the +# header of that file. diff --git a/.github/requirements/publish-requirements.txt b/.github/requirements/publish-requirements.txt index 7f2e95cd5a31..c0b65124b350 100644 --- a/.github/requirements/publish-requirements.txt +++ b/.github/requirements/publish-requirements.txt @@ -1,10 +1,6 @@ -# -# This file is autogenerated by pip-compile with Python 3.11 -# by the following command: -# -# pip-compile --generate-hashes publish-requirements.in -# -backports-tarfile==1.2.0 \ +# This file was autogenerated by uv via the following command: +# uv pip compile --universal -p 3.11 --generate-hashes .github/requirements/publish-requirements.in +backports-tarfile==1.2.0 ; python_full_version < '3.12' \ --hash=sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34 \ --hash=sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991 # via jaraco-context @@ -12,7 +8,7 @@ certifi==2024.8.30 \ --hash=sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8 \ --hash=sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9 # via requests -cffi==1.17.1 \ +cffi==1.17.1 ; platform_python_implementation != 'PyPy' and sys_platform == 'linux' \ --hash=sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8 \ --hash=sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2 \ --hash=sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1 \ @@ -173,7 +169,7 @@ charset-normalizer==3.3.2 \ --hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \ --hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561 # via requests -cryptography==43.0.1 \ +cryptography==43.0.1 ; sys_platform == 'linux' \ --hash=sha256:014f58110f53237ace6a408b5beb6c427b64e084eb451ef25a28308270086494 \ --hash=sha256:1bbcce1a551e262dfbafb6e6252f1ae36a248e615ca44ba302df077a846a8806 \ --hash=sha256:203e92a75716d8cfb491dc47c79e17d0d9207ccffcbcb35f598fbe463ae3444d \ @@ -228,7 +224,7 @@ jaraco-functools==4.0.2 \ --hash=sha256:3460c74cd0d32bf82b9576bbb3527c4364d5b27a21f5158a62aed6c4b42e23f5 \ --hash=sha256:c9d16a3ed4ccb5a889ad8e0b7a343401ee5b2a71cee6ed192d3f68bc351e94e3 # via keyring -jeepney==0.8.0 \ +jeepney==0.8.0 ; sys_platform == 'linux' \ --hash=sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806 \ --hash=sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755 # via @@ -246,9 +242,9 @@ mdurl==0.1.2 \ --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba # via markdown-it-py -more-itertools==10.4.0 \ - --hash=sha256:0f7d9f83a0a8dcfa8a2694a770590d98a67ea943e3d9f5298309a484758c4e27 \ - --hash=sha256:fe0e63c4ab068eac62410ab05cccca2dc71ec44ba8ef29916a0090df061cf923 +more-itertools==10.5.0 \ + --hash=sha256:037b0d3203ce90cca8ab1defbbdac29d5f993fc20131f3664dc8d6acfa872aef \ + --hash=sha256:5482bfef7849c25dc3c6dd53a6173ae4795da2a41a80faea6700d9f5846c5da6 # via # jaraco-classes # jaraco-functools @@ -274,7 +270,7 @@ pkginfo==1.10.0 \ --hash=sha256:5df73835398d10db79f8eecd5cd86b1f6d29317589ea70796994d49399af6297 \ --hash=sha256:889a6da2ed7ffc58ab5b900d888ddce90bce912f2d2de1dc1c26f4cb9fe65097 # via twine -pycparser==2.22 \ +pycparser==2.22 ; platform_python_implementation != 'PyPy' and sys_platform == 'linux' \ --hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \ --hash=sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc # via cffi @@ -284,6 +280,10 @@ pygments==2.18.0 \ # via # readme-renderer # rich +pywin32-ctypes==0.2.3 ; sys_platform == 'win32' \ + --hash=sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8 \ + --hash=sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755 + # via keyring readme-renderer==44.0 \ --hash=sha256:2fbca89b81a08526aadf1357a8c2ae889ec05fb03f5da67f9769c9a592166151 \ --hash=sha256:8712034eabbfa6805cacf1402b4eeb2a73028f72d1166d6f5cb7f9c047c5d1e1 @@ -292,7 +292,7 @@ requests==2.32.3 \ --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \ --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6 # via - # -r publish-requirements.in + # -r .github/requirements/publish-requirements.in # requests-toolbelt # twine requests-toolbelt==1.0.0 \ @@ -307,14 +307,14 @@ rich==13.8.0 \ --hash=sha256:2e85306a063b9492dffc86278197a60cbece75bcb766022f3436f567cae11bdc \ --hash=sha256:a5ac1f1cd448ade0d59cc3356f7db7a7ccda2c8cbae9c7a90c28ff463d3e91f4 # via twine -secretstorage==3.3.3 \ +secretstorage==3.3.3 ; sys_platform == 'linux' \ --hash=sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77 \ --hash=sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99 # via keyring twine==5.1.1 \ --hash=sha256:215dbe7b4b94c2c50a7315c0275d2258399280fbb7d04182c7e55e24b5f93997 \ --hash=sha256:9aa0825139c02b3434d913545c7b847a21c835e11597f5255842d457da2322db - # via -r publish-requirements.in + # via -r .github/requirements/publish-requirements.in urllib3==2.2.2 \ --hash=sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472 \ --hash=sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168 diff --git a/.github/requirements/uv-requirements.txt b/.github/requirements/uv-requirements.txt new file mode 100644 index 000000000000..1c52eda4f7e7 --- /dev/null +++ b/.github/requirements/uv-requirements.txt @@ -0,0 +1,21 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile --universal -p 3.8 --generate-hashes - +uv==0.4.7 \ + --hash=sha256:00aa7299edefcc4069d73b988a7331d590e3fedd29f5695b1680905af1ccba04 \ + --hash=sha256:0fef80011c96dc8e284f4895b7ca92945e450fb517872115a557e72789c0e2c5 \ + --hash=sha256:106fc5449a63137da6b3c4fd25775e3eeda3b11c8cea12439d95201237a95484 \ + --hash=sha256:1357fb27047cff94422bb82cf9a82d7285ce8341a204fc1925b0b89c8d108249 \ + --hash=sha256:23283699e6035ef536b204f9094e7297093a527f958b86d4ce26613c603f564c \ + --hash=sha256:2ab5f6701046b373cdedca7334e20a8dc7726eb4c3e2f6e18297dbbda09afba9 \ + --hash=sha256:319a585f53c0b63b989526206383716e1d7c0f3483425058b94bf47402a81841 \ + --hash=sha256:54c3dde3c01d96fba484c2728e020c7c867e05a88de143ddb6df1091d1ffdfb7 \ + --hash=sha256:63b59e0cfa303a97ce5ba19fa8fc27a6339516561bc4b821cca52ed15721cbdb \ + --hash=sha256:904763380be165f5213dcbacb8d6c17d5cf138ea4bd24b4a37a1b6046b5650a1 \ + --hash=sha256:9356449439d4fa42419d17736d775cd1701b1b4a054ab445faf1477a6920a505 \ + --hash=sha256:a1850d93f78eeb6d0ace3dc0335e1bf141a4b6a26844ab75f00055de2a4817cd \ + --hash=sha256:ab7308c0604268f21b1a5bce4e1b61bcf56831f4aef59bee93c2b5815f4bc6a8 \ + --hash=sha256:bfbd6e28b0543b774db7d97d61963c384c70284e95056004c8f74252e69616c7 \ + --hash=sha256:d6c8e43bbdfa2f7910245335acb93fcb5a4e34995b7ce60de4e814071690b3c5 \ + --hash=sha256:e1f3285bebfeab6e076e651ec47f6adf7a83a4f014dd9d7e73efc034e77d42cd \ + --hash=sha256:e8bc35e30f2bb03f0e1812f1c0dce0e73d8ab01e90392d39f334da9d75e522b0 \ + --hash=sha256:ec49a00317799226d33135bf40e8da44262f44e3980a5bb9e6dae7250523c963 diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 7e34db123a93..f1b92b5b9eca 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -21,6 +21,7 @@ on: env: BUILD_REQUIREMENTS_PATH: .github/requirements/build-requirements.txt + UV_REQUIREMENTS_PATH: .github/requirements/uv-requirements.txt jobs: sdist: @@ -33,7 +34,7 @@ jobs: ref: ${{ github.event.inputs.version || github.ref }} persist-credentials: false - - run: python -m pip install uv + - run: python -m pip install -r $UV_REQUIREMENTS_PATH - name: Make sdist (cryptography) run: uv build --build-constraint=$BUILD_REQUIREMENTS_PATH --require-hashes --sdist @@ -106,9 +107,6 @@ jobs: sparse-checkout: | ${{ env.BUILD_REQUIREMENTS_PATH }} sparse-checkout-cone-mode: false - - run: /opt/python/${{ matrix.PYTHON.VERSION }}/bin/python -m venv .venv - - name: Install Python dependencies - run: .venv/bin/pip install --require-hashes -r ${{ env.BUILD_REQUIREMENTS_PATH }} - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: @@ -117,19 +115,15 @@ jobs: - name: Build the wheel run: | if [ -n "${{ matrix.PYTHON.ABI_VERSION }}" ]; then - PY_LIMITED_API="--config-settings=build-args=--features=pyo3/abi3-${{ matrix.PYTHON.ABI_VERSION }} --no-build-isolation" + PY_LIMITED_API="--config-settings=build-args=--features=pyo3/abi3-${{ matrix.PYTHON.ABI_VERSION }}" fi - # `maturin` has a binary that needs to be on the $PATH, so we - # activate the venv. - source .venv/bin/activate OPENSSL_DIR="/opt/pyca/cryptography/openssl" \ OPENSSL_STATIC=1 \ - .venv/bin/python -m pip wheel -v --no-deps $PY_LIMITED_API cryptograph*.tar.gz -w dist/ - mv dist/cryptography*.whl tmpwheelhouse + uv build --python=/opt/python/${{ matrix.PYTHON.VERSION }}/bin/python --wheel --require-hashes --build-constraint=$BUILD_REQUIREMENTS_PATH $PY_LIMITED_API cryptography*.tar.gz -o tmpwheelhouse/ env: RUSTUP_HOME: /root/.rustup - - run: auditwheel repair --plat ${{ matrix.MANYLINUX.NAME }} tmpwheelhouse/cryptograph*.whl -w wheelhouse/ + - run: auditwheel repair --plat ${{ matrix.MANYLINUX.NAME }} tmpwheelhouse/cryptography*.whl -w wheelhouse/ - run: unzip wheelhouse/*.whl -d execstack.check - run: | results=$(readelf -lW execstack.check/cryptography/hazmat/bindings/*.so) @@ -139,15 +133,17 @@ jobs: else exit 0 fi - - run: .venv/bin/pip install cryptography --no-index -f wheelhouse/ + + - run: uv venv --python=/opt/python/${{ matrix.PYTHON.VERSION }}/bin/python + - run: uv pip install --require-hashes -r $BUILD_REQUIREMENTS_PATH + - run: uv pip install cryptography --no-index -f wheelhouse/ - run: | - .venv/bin/python -c "from cryptography.hazmat.backends.openssl.backend import backend;print('Loaded: ' + backend.openssl_version_text());print('Linked Against: ' + backend._ffi.string(backend._lib.OPENSSL_VERSION_TEXT).decode('ascii'))" - - run: mkdir cryptography-wheelhouse - - run: mv wheelhouse/cryptography*.whl cryptography-wheelhouse/ + echo "from cryptography.hazmat.backends.openssl.backend import backend;print('Loaded: ' + backend.openssl_version_text());print('Linked Against: ' + backend._ffi.string(backend._lib.OPENSSL_VERSION_TEXT).decode('ascii'))" | uv run - + - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 with: name: "cryptography-${{ github.event.inputs.version }}-${{ matrix.MANYLINUX.NAME }}-${{ matrix.PYTHON.VERSION }}-${{ matrix.PYTHON.ABI_VERSION }}" - path: cryptography-wheelhouse/ + path: wheelhouse/ macos: needs: [sdist] @@ -195,6 +191,7 @@ jobs: persist-credentials: false sparse-checkout: | ${{ env.BUILD_REQUIREMENTS_PATH }} + ${{ env.UV_REQUIREMENTS_PATH }} sparse-checkout-cone-mode: false - name: Setup python run: | @@ -222,46 +219,41 @@ jobs: toolchain: stable # Add the arm64 target in addition to the native arch (x86_64) target: aarch64-apple-darwin - - run: ${{ matrix.PYTHON.BIN_PATH }} -m venv venv - - name: Install Python dependencies - run: venv/bin/pip install --require-hashes -r ${{ env.BUILD_REQUIREMENTS_PATH }} - - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: cryptography-sdist + + - run: ${{ matrix.PYTHON.BIN_PATH }} -m pip install -r ${{ env.UV_REQUIREMENTS_PATH }} - run: mkdir wheelhouse - name: Build the wheel run: | if [ -n "${{ matrix.PYTHON.ABI_VERSION }}" ]; then - PY_LIMITED_API="--config-settings=build-args=--features=pyo3/abi3-${{ matrix.PYTHON.ABI_VERSION }} --no-build-isolation" + PY_LIMITED_API="--config-settings=build-args=--features=pyo3/abi3-${{ matrix.PYTHON.ABI_VERSION }}" fi - # `maturin` has a binary that needs to be on the $PATH, so we - # activate the venv. - source venv/bin/activate OPENSSL_DIR="$(readlink -f ../openssl-macos-universal2/)" \ OPENSSL_STATIC=1 \ - venv/bin/python -m pip wheel -v --no-deps $PY_LIMITED_API cryptograph*.tar.gz -w dist/ - mv dist/cryptography*.whl wheelhouse + uv build --wheel --require-hashes --build-constraint=$BUILD_REQUIREMENTS_PATH $PY_LIMITED_API cryptography*.tar.gz -o wheelhouse/ env: MACOSX_DEPLOYMENT_TARGET: ${{ matrix.PYTHON.DEPLOYMENT_TARGET }} ARCHFLAGS: ${{ matrix.PYTHON.ARCHFLAGS }} _PYTHON_HOST_PLATFORM: ${{ matrix.PYTHON._PYTHON_HOST_PLATFORM }} - - run: venv/bin/pip install -f wheelhouse/ --no-index cryptography + + - run: uv venv + - run: uv pip install --require-hashes -r $BUILD_REQUIREMENTS_PATH + - run: uv pip install cryptography --no-index -f wheelhouse/ - name: Show the wheel's minimum macOS SDK and architectures run: | - find venv/lib/*/site-packages/cryptography/hazmat/bindings -name '*.so' -exec vtool -show {} \; + find .venv/lib/*/site-packages/cryptography/hazmat/bindings -name '*.so' -exec vtool -show {} \; - run: | - venv/bin/python -c "from cryptography.hazmat.backends.openssl.backend import backend;print('Loaded: ' + backend.openssl_version_text());print('Linked Against: ' + backend._ffi.string(backend._lib.OPENSSL_VERSION_TEXT).decode('ascii'))" + echo "from cryptography.hazmat.backends.openssl.backend import backend;print('Loaded: ' + backend.openssl_version_text());print('Linked Against: ' + backend._ffi.string(backend._lib.OPENSSL_VERSION_TEXT).decode('ascii'))" | uv run - - - run: mkdir cryptography-wheelhouse - - run: mv wheelhouse/cryptography*.whl cryptography-wheelhouse/ - run: | - echo "CRYPTOGRAPHY_WHEEL_NAME=$(basename $(ls cryptography-wheelhouse/cryptography*.whl))" >> $GITHUB_ENV + echo "CRYPTOGRAPHY_WHEEL_NAME=$(basename $(ls wheelhouse/cryptography*.whl))" >> $GITHUB_ENV - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 with: name: "${{ env.CRYPTOGRAPHY_WHEEL_NAME }}" - path: cryptography-wheelhouse/ + path: wheelhouse/ windows: needs: [sdist] @@ -290,6 +282,7 @@ jobs: persist-credentials: false sparse-checkout: | ${{ env.BUILD_REQUIREMENTS_PATH }} + ${{ env.UV_REQUIREMENTS_PATH }} sparse-checkout-cone-mode: false - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 @@ -320,25 +313,25 @@ jobs: echo "OPENSSL_DIR=C:/openssl-${{ matrix.WINDOWS.WINDOWS }}" >> $GITHUB_ENV echo "OPENSSL_STATIC=1" >> $GITHUB_ENV shell: bash - - name: Install Python dependencies - run: python -m pip install --require-hashes -r ${{ env.BUILD_REQUIREMENTS_PATH }} + + - run: pip install -r ${{ env.UV_REQUIREMENTS_PATH }} - run: mkdir wheelhouse - run: | if [ -n "${{ matrix.PYTHON.ABI_VERSION }}" ]; then - PY_LIMITED_API="--config-settings=build-args=--features=pyo3/abi3-${{ matrix.PYTHON.ABI_VERSION }} --no-build-isolation" + PY_LIMITED_API="--config-settings=build-args=--features=pyo3/abi3-${{ matrix.PYTHON.ABI_VERSION }}" fi - python -m pip wheel -v --no-deps cryptography*.tar.gz $PY_LIMITED_API -w dist/ - mv dist/cryptography*.whl wheelhouse/ + uv build --wheel --require-hashes --build-constraint=$BUILD_REQUIREMENTS_PATH cryptography*.tar.gz $PY_LIMITED_API -o wheelhouse/ shell: bash - - run: pip install -f wheelhouse --no-index cryptography + + - run: uv venv + - run: uv pip install --require-hashes -r ${{ env.BUILD_REQUIREMENTS_PATH }} + - run: uv pip install cryptography --no-index -f wheelhouse/ - name: Print the OpenSSL we built and linked against run: | - python -c "from cryptography.hazmat.backends.openssl.backend import backend;print('Loaded: ' + backend.openssl_version_text());print('Linked Against: ' + backend._ffi.string(backend._lib.OPENSSL_VERSION_TEXT).decode('ascii'))" + echo "from cryptography.hazmat.backends.openssl.backend import backend;print('Loaded: ' + backend.openssl_version_text());print('Linked Against: ' + backend._ffi.string(backend._lib.OPENSSL_VERSION_TEXT).decode('ascii'))" | uv run - - - run: mkdir cryptography-wheelhouse - - run: move wheelhouse\cryptography*.whl cryptography-wheelhouse\ - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 with: name: "cryptography-${{ github.event.inputs.version }}-${{ matrix.WINDOWS.WINDOWS }}-${{ matrix.PYTHON.VERSION }}-${{ matrix.PYTHON.ABI_VERSION }}" - path: cryptography-wheelhouse\ + path: wheelhouse\ diff --git a/ci-constraints-requirements.txt b/ci-constraints-requirements.txt index 04f7993764e1..6e134309b211 100644 --- a/ci-constraints-requirements.txt +++ b/ci-constraints-requirements.txt @@ -1,76 +1,134 @@ -# This is named ambigiously, but it's a pip constraints file, named like a -# requirements file so dependabot will update the pins. -# It was originally generated with; -# pip-compile --extra=docs --extra=docstest --extra=pep8test --extra=test --extra=test-randomorder --extra=nox --extra=sdist --resolver=backtracking --strip-extras --unsafe-package=cffi --unsafe-package=pycparser --unsafe-package=setuptools pyproject.toml -# and then manually massaged to add version specifiers to packages whose -# versions vary by Python version - -alabaster==1.0.0 +# This file was autogenerated by uv via the following command: +# uv pip compile --universal -p 3.7 --extra=docs --extra=docstest --extra=pep8test --extra=test --extra=test-randomorder --extra=nox --extra=sdist --unsafe-package=cffi --unsafe-package=pycparser --unsafe-package=setuptools --unsafe-package=cryptography-vectors pyproject.toml +alabaster==0.7.13 ; python_full_version < '3.10' + # via sphinx +alabaster==1.0.0 ; python_full_version >= '3.10' # via sphinx -argcomplete==3.5.0; python_version >= "3.8" +argcomplete==3.1.2 ; python_full_version < '3.8' + # via nox +argcomplete==3.5.0 ; python_full_version >= '3.8' # via nox -babel==2.16.0 +babel==2.14.0 ; python_full_version < '3.8' # via sphinx -build==1.2.1 +babel==2.16.0 ; python_full_version >= '3.8' + # via sphinx +bleach==6.0.0 ; python_full_version < '3.8' + # via readme-renderer +build==1.1.1 ; python_full_version < '3.8' + # via cryptography (pyproject.toml) +build==1.2.2 ; python_full_version >= '3.8' # via - # check-sdist # cryptography (pyproject.toml) + # check-sdist certifi==2024.8.30 - # via requests + # via + # cryptography (pyproject.toml) + # requests charset-normalizer==3.3.2 # via requests -check-sdist==0.1.3 +check-sdist==0.1.3 ; python_full_version >= '3.8' # via cryptography (pyproject.toml) click==8.1.7 # via cryptography (pyproject.toml) +colorama==0.4.6 ; (platform_system != 'Windows' and sys_platform == 'win32') or platform_system == 'Windows' or os_name == 'nt' + # via + # build + # click + # colorlog + # pytest + # sphinx colorlog==6.8.2 # via nox -coverage==7.6.1; python_version >= "3.8" - # via - # coverage - # pytest-cov +coverage==7.2.7 ; python_full_version < '3.8' + # via pytest-cov +coverage==7.6.1 ; python_full_version >= '3.8' + # via pytest-cov distlib==0.3.8 # via virtualenv -docutils==0.21.2 +docutils==0.19 ; python_full_version < '3.8' + # via + # readme-renderer + # sphinx +docutils==0.20.1 ; python_full_version >= '3.8' and python_full_version < '3.10' # via # readme-renderer # sphinx # sphinx-rtd-theme -exceptiongroup==1.2.2 +docutils==0.21.2 ; python_full_version >= '3.10' + # via + # readme-renderer + # sphinx + # sphinx-rtd-theme +exceptiongroup==1.2.2 ; python_full_version < '3.11' # via pytest -execnet==2.1.1; python_version >= "3.8" +execnet==2.0.2 ; python_full_version < '3.8' # via pytest-xdist -filelock==3.15.4; python_version >= "3.8" +execnet==2.1.1 ; python_full_version >= '3.8' + # via pytest-xdist +filelock==3.12.2 ; python_full_version < '3.8' + # via virtualenv +filelock==3.16.0 ; python_full_version >= '3.8' # via virtualenv idna==3.8 # via requests imagesize==1.4.1 # via sphinx +importlib-metadata==6.7.0 ; python_full_version < '3.8' + # via + # argcomplete + # build + # click + # nox + # pluggy + # pytest + # pytest-randomly + # sphinx + # sphinxcontrib-spelling + # virtualenv +importlib-metadata==8.4.0 ; python_full_version >= '3.8' and python_full_version < '3.10.2' + # via + # build + # pytest-randomly + # sphinx +importlib-resources==6.4.4 ; python_full_version == '3.8.*' + # via check-sdist iniconfig==2.0.0 # via pytest jinja2==3.1.4 # via sphinx markupsafe==2.1.5 # via jinja2 -mypy==1.11.2 +mypy==1.4.1 ; python_full_version < '3.8' + # via cryptography (pyproject.toml) +mypy==1.11.2 ; python_full_version >= '3.8' # via cryptography (pyproject.toml) mypy-extensions==1.0.0 # via mypy -nh3==0.2.18 +nh3==0.2.18 ; python_full_version >= '3.8' # via readme-renderer nox==2024.4.15 # via cryptography (pyproject.toml) -packaging==24.1; python_version >= "3.8" +packaging==24.0 ; python_full_version < '3.8' + # via + # build + # nox + # pytest + # sphinx +packaging==24.1 ; python_full_version >= '3.8' # via # build # nox # pytest # sphinx -pathspec==0.12.1 +pathspec==0.12.1 ; python_full_version >= '3.8' # via check-sdist -platformdirs==4.2.2; python_version >= "3.8" +platformdirs==4.0.0 ; python_full_version < '3.8' + # via virtualenv +platformdirs==4.3.1 ; python_full_version >= '3.8' # via virtualenv -pluggy==1.5.0; python_version >= "3.8" +pluggy==1.2.0 ; python_full_version < '3.8' + # via pytest +pluggy==1.5.0 ; python_full_version >= '3.8' # via pytest pretend==1.0.9 # via cryptography (pyproject.toml) @@ -80,13 +138,24 @@ pyenchant==3.2.2 # via # cryptography (pyproject.toml) # sphinxcontrib-spelling -pygments==2.18.0 +pygments==2.17.2 ; python_full_version < '3.8' + # via + # readme-renderer + # sphinx +pygments==2.18.0 ; python_full_version >= '3.8' # via # readme-renderer # sphinx pyproject-hooks==1.1.0 # via build -pytest==8.3.2; python_version >= "3.8" +pytest==7.4.4 ; python_full_version < '3.8' + # via + # cryptography (pyproject.toml) + # pytest-benchmark + # pytest-cov + # pytest-randomly + # pytest-xdist +pytest==8.3.2 ; python_full_version >= '3.8' # via # cryptography (pyproject.toml) # pytest-benchmark @@ -95,64 +164,119 @@ pytest==8.3.2; python_version >= "3.8" # pytest-xdist pytest-benchmark==4.0.0 # via cryptography (pyproject.toml) -pytest-cov==5.0.0; python_version >= "3.8" +pytest-cov==4.1.0 ; python_full_version < '3.8' + # via cryptography (pyproject.toml) +pytest-cov==5.0.0 ; python_full_version >= '3.8' + # via cryptography (pyproject.toml) +pytest-randomly==3.12.0 ; python_full_version < '3.8' + # via cryptography (pyproject.toml) +pytest-randomly==3.15.0 ; python_full_version >= '3.8' + # via cryptography (pyproject.toml) +pytest-xdist==3.5.0 ; python_full_version < '3.8' # via cryptography (pyproject.toml) -pytest-randomly==3.15.0 +pytest-xdist==3.6.1 ; python_full_version >= '3.8' # via cryptography (pyproject.toml) -pytest-xdist==3.6.1; python_version >= "3.8" +pytz==2024.1 ; python_full_version < '3.9' + # via babel +readme-renderer==37.3 ; python_full_version < '3.8' # via cryptography (pyproject.toml) -readme-renderer==44.0 +readme-renderer==43.0 ; python_full_version >= '3.8' and python_full_version < '3.10' # via cryptography (pyproject.toml) -requests==2.32.3 +readme-renderer==44.0 ; python_full_version >= '3.10' + # via cryptography (pyproject.toml) +requests==2.31.0 ; python_full_version < '3.8' + # via sphinx +requests==2.32.3 ; python_full_version >= '3.8' # via sphinx ruff==0.6.4 # via cryptography (pyproject.toml) +six==1.16.0 ; python_full_version < '3.8' + # via bleach snowballstemmer==2.2.0 # via sphinx -sphinx==8.0.2 +sphinx==5.3.0 ; python_full_version < '3.8' + # via + # cryptography (pyproject.toml) + # sphinxcontrib-spelling +sphinx==7.1.2 ; python_full_version >= '3.8' and python_full_version < '3.10' # via # cryptography (pyproject.toml) # sphinx-rtd-theme - # sphinxcontrib-applehelp - # sphinxcontrib-devhelp - # sphinxcontrib-htmlhelp # sphinxcontrib-jquery - # sphinxcontrib-qthelp - # sphinxcontrib-serializinghtml # sphinxcontrib-spelling -sphinx-rtd-theme==3.0.0rc1 +sphinx==8.0.2 ; python_full_version >= '3.10' + # via + # cryptography (pyproject.toml) + # sphinx-rtd-theme + # sphinxcontrib-jquery + # sphinxcontrib-spelling +sphinx-rtd-theme==3.0.0rc1 ; python_full_version >= '3.8' # via cryptography (pyproject.toml) -sphinxcontrib-applehelp==2.0.0 +sphinxcontrib-applehelp==1.0.2 ; python_full_version < '3.8' + # via sphinx +sphinxcontrib-applehelp==1.0.4 ; python_full_version >= '3.8' and python_full_version < '3.10' # via sphinx -sphinxcontrib-devhelp==2.0.0 +sphinxcontrib-applehelp==2.0.0 ; python_full_version >= '3.10' # via sphinx -sphinxcontrib-htmlhelp==2.1.0 +sphinxcontrib-devhelp==1.0.2 ; python_full_version < '3.10' # via sphinx -sphinxcontrib-jquery==4.1 +sphinxcontrib-devhelp==2.0.0 ; python_full_version >= '3.10' + # via sphinx +sphinxcontrib-htmlhelp==2.0.0 ; python_full_version < '3.8' + # via sphinx +sphinxcontrib-htmlhelp==2.0.1 ; python_full_version >= '3.8' and python_full_version < '3.10' + # via sphinx +sphinxcontrib-htmlhelp==2.1.0 ; python_full_version >= '3.10' + # via sphinx +sphinxcontrib-jquery==4.1 ; python_full_version >= '3.8' # via sphinx-rtd-theme sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==2.0.0 +sphinxcontrib-qthelp==1.0.3 ; python_full_version < '3.10' + # via sphinx +sphinxcontrib-qthelp==2.0.0 ; python_full_version >= '3.10' # via sphinx -sphinxcontrib-serializinghtml==2.0.0 +sphinxcontrib-serializinghtml==1.1.5 ; python_full_version < '3.10' + # via sphinx +sphinxcontrib-serializinghtml==2.0.0 ; python_full_version >= '3.10' # via sphinx sphinxcontrib-spelling==8.0.0 # via cryptography (pyproject.toml) -tomli==2.0.1 +tomli==2.0.1 ; python_full_version <= '3.11' # via # build - # check-manifest + # check-sdist # coverage # mypy - # pyproject-hooks + # nox # pytest -typing-extensions==4.12.2; python_version >= "3.8" + # sphinx +typed-ast==1.5.5 ; python_full_version < '3.8' + # via mypy +typing-extensions==4.7.1 ; python_full_version < '3.8' + # via + # importlib-metadata + # mypy + # nox + # platformdirs +typing-extensions==4.12.2 ; python_full_version >= '3.8' # via mypy -urllib3==2.2.2 +urllib3==2.0.7 ; python_full_version < '3.8' + # via requests +urllib3==2.2.2 ; python_full_version >= '3.8' # via requests virtualenv==20.26.3 # via nox +webencodings==0.5.1 ; python_full_version < '3.8' + # via bleach +zipp==3.15.0 ; python_full_version < '3.8' + # via importlib-metadata +zipp==3.20.1 ; python_full_version >= '3.8' and python_full_version < '3.10.2' + # via + # importlib-metadata + # importlib-resources -# The following packages are considered to be unsafe in a requirements file: +# The following packages were excluded from the output: # cffi # pycparser +# cryptography-vectors diff --git a/pyproject.toml b/pyproject.toml index 44348415061a..4f9fab38d563 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -74,7 +74,7 @@ test = [ "certifi", ] test-randomorder = ["pytest-randomly"] -docs = ["sphinx >=5.3.0", "sphinx-rtd-theme >=3.0.0rc1"] +docs = ["sphinx >=5.3.0", "sphinx-rtd-theme >=3.0.0rc1; python_version >= '3.8'"] docstest = ["pyenchant >=1.6.11", "readme-renderer", "sphinxcontrib-spelling >=4.0.1"] sdist = ["build"] # `click` included because its needed to type check `release.py` @@ -184,3 +184,8 @@ git-only = [ ".gitattributes", ".gitignore", ] + +[tool.uv] +# These cover all Python versions, but by expressing multiple environments we +# force uv's resolver to pick the latest versions of packages for each version. +environments = ["python_version >= '3.10'", "python_version >= '3.8' and python_version < '3.10'", "python_version < '3.8'"] diff --git a/src/cryptography/hazmat/bindings/_rust/__init__.pyi b/src/cryptography/hazmat/bindings/_rust/__init__.pyi index c0ea0a5405ca..30b67d85597e 100644 --- a/src/cryptography/hazmat/bindings/_rust/__init__.pyi +++ b/src/cryptography/hazmat/bindings/_rust/__init__.pyi @@ -6,7 +6,6 @@ import typing from cryptography.hazmat.primitives import padding -def check_pkcs7_padding(data: bytes) -> bool: ... def check_ansix923_padding(data: bytes) -> bool: ... class PKCS7PaddingContext(padding.PaddingContext): @@ -14,6 +13,11 @@ class PKCS7PaddingContext(padding.PaddingContext): def update(self, data: bytes) -> bytes: ... def finalize(self) -> bytes: ... +class PKCS7UnpaddingContext(padding.PaddingContext): + def __init__(self, block_size: int) -> None: ... + def update(self, data: bytes) -> bytes: ... + def finalize(self) -> bytes: ... + class ObjectIdentifier: def __init__(self, val: str) -> None: ... @property diff --git a/src/cryptography/hazmat/primitives/padding.py b/src/cryptography/hazmat/primitives/padding.py index d1ca775f33d0..b2a3f1cfffaa 100644 --- a/src/cryptography/hazmat/primitives/padding.py +++ b/src/cryptography/hazmat/primitives/padding.py @@ -11,8 +11,8 @@ from cryptography.exceptions import AlreadyFinalized from cryptography.hazmat.bindings._rust import ( PKCS7PaddingContext, + PKCS7UnpaddingContext, check_ansix923_padding, - check_pkcs7_padding, ) @@ -115,32 +115,11 @@ def padder(self) -> PaddingContext: return PKCS7PaddingContext(self.block_size) def unpadder(self) -> PaddingContext: - return _PKCS7UnpaddingContext(self.block_size) - - -class _PKCS7UnpaddingContext(PaddingContext): - _buffer: bytes | None - - def __init__(self, block_size: int): - self.block_size = block_size - # TODO: more copies than necessary, we should use zero-buffer (#193) - self._buffer = b"" - - def update(self, data: bytes) -> bytes: - self._buffer, result = _byte_unpadding_update( - self._buffer, data, self.block_size - ) - return result - - def finalize(self) -> bytes: - result = _byte_unpadding_check( - self._buffer, self.block_size, check_pkcs7_padding - ) - self._buffer = None - return result + return PKCS7UnpaddingContext(self.block_size) PaddingContext.register(PKCS7PaddingContext) +PaddingContext.register(PKCS7UnpaddingContext) class ANSIX923: diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs index cd7b99f1570a..e15fffa6d32e 100644 --- a/src/rust/src/lib.rs +++ b/src/rust/src/lib.rs @@ -102,7 +102,7 @@ mod _rust { #[pymodule_export] use crate::oid::ObjectIdentifier; #[pymodule_export] - use crate::padding::{check_ansix923_padding, check_pkcs7_padding, PKCS7PaddingContext}; + use crate::padding::{check_ansix923_padding, PKCS7PaddingContext, PKCS7UnpaddingContext}; #[pymodule_export] use crate::pkcs12::pkcs12; #[pymodule_export] diff --git a/src/rust/src/padding.rs b/src/rust/src/padding.rs index 3a55039d3385..0031f148ea15 100644 --- a/src/rust/src/padding.rs +++ b/src/rust/src/padding.rs @@ -20,7 +20,6 @@ fn constant_time_lt(a: u8, b: u8) -> u8 { duplicate_msb_to_all(a ^ ((a ^ b) | (a.wrapping_sub(b) ^ b))) } -#[pyo3::pyfunction] pub(crate) fn check_pkcs7_padding(data: &[u8]) -> bool { let mut mismatch = 0; let pad_size = *data.last().unwrap(); @@ -111,6 +110,65 @@ impl PKCS7PaddingContext { } } +#[pyo3::pyclass] +pub(crate) struct PKCS7UnpaddingContext { + block_size: usize, + buffer: Option>, +} + +#[pyo3::pymethods] +impl PKCS7UnpaddingContext { + #[new] + pub(crate) fn new(block_size: usize) -> PKCS7UnpaddingContext { + PKCS7UnpaddingContext { + block_size: block_size / 8, + buffer: Some(Vec::new()), + } + } + + pub(crate) fn update<'a>( + &mut self, + py: pyo3::Python<'a>, + buf: CffiBuf<'a>, + ) -> CryptographyResult> { + match self.buffer.as_mut() { + Some(v) => { + v.extend_from_slice(buf.as_bytes()); + let finished_blocks = (v.len() / self.block_size).saturating_sub(1); + let result_size = finished_blocks * self.block_size; + let result = v.drain(..result_size); + Ok(pyo3::types::PyBytes::new_bound(py, result.as_slice())) + } + None => Err(exceptions::already_finalized_error()), + } + } + + pub(crate) fn finalize<'p>( + &mut self, + py: pyo3::Python<'p>, + ) -> CryptographyResult> { + match self.buffer.take() { + Some(v) => { + if v.len() != self.block_size { + return Err( + pyo3::exceptions::PyValueError::new_err("Invalid padding bytes.").into(), + ); + } + if !check_pkcs7_padding(&v) { + return Err( + pyo3::exceptions::PyValueError::new_err("Invalid padding bytes.").into(), + ); + } + + let pad_size = *v.last().unwrap(); + let result = &v[..v.len() - pad_size as usize]; + Ok(pyo3::types::PyBytes::new_bound(py, result)) + } + None => Err(exceptions::already_finalized_error()), + } + } +} + #[cfg(test)] mod tests { use super::constant_time_lt; diff --git a/tests/hazmat/primitives/test_padding.py b/tests/hazmat/primitives/test_padding.py index 0ab1125f5bfb..df1ee4ec1131 100644 --- a/tests/hazmat/primitives/test_padding.py +++ b/tests/hazmat/primitives/test_padding.py @@ -80,6 +80,8 @@ def test_pad(self, size, unpadded, padded): b"111111111111111122222222222222", b"111111111111111122222222222222\x02\x02", ), + (128, b"1" * 16, b"1" * 16 + b"\x10" * 16), + (128, b"1" * 17, b"1" * 17 + b"\x0f" * 15), ], ) def test_unpad(self, size, unpadded, padded):