From d63473112119993bc5d556e0c37b03d5e5b560f0 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 8 Dec 2020 21:01:11 -0500 Subject: [PATCH 0001/2380] Reopen master for 3.4 (#5605) --- CHANGELOG.rst | 7 +++++-- src/cryptography/__about__.py | 2 +- vectors/cryptography_vectors/__about__.py | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index caa8e20c525b..d392c47cdfa5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,13 +1,16 @@ Changelog ========= +3.4 - `master`_ +~~~~~~~~~~~~~~~ + +.. note:: This version is not yet released and is under active development. + .. _v3-3: 3.3 - 2020-12-08 ~~~~~~~~~~~~~~~~ -.. note:: This version is not yet released and is under active development. - * **BACKWARDS INCOMPATIBLE:** Support for Python 3.5 has been removed due to low usage and maintenance burden. * **BACKWARDS INCOMPATIBLE:** The diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py index d7a3c1e6de87..18efbab0714a 100644 --- a/src/cryptography/__about__.py +++ b/src/cryptography/__about__.py @@ -22,7 +22,7 @@ ) __uri__ = "https://github.com/pyca/cryptography" -__version__ = "3.3" +__version__ = "3.4.dev1" __author__ = "The cryptography developers" __email__ = "cryptography-dev@python.org" diff --git a/vectors/cryptography_vectors/__about__.py b/vectors/cryptography_vectors/__about__.py index 5cb6768fa234..82a389b024a4 100644 --- a/vectors/cryptography_vectors/__about__.py +++ b/vectors/cryptography_vectors/__about__.py @@ -20,7 +20,7 @@ __uri__ = "https://github.com/pyca/cryptography" -__version__ = "3.3" +__version__ = "3.4.dev1" __author__ = "The cryptography developers" __email__ = "cryptography-dev@python.org" From ff12a375521e5b702d9d58c8a04604c65496eb54 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 9 Dec 2020 00:10:10 -0500 Subject: [PATCH 0002/2380] Remove Python2 from CI and code that branched on it (#5607) * Remove Python2 from CI and code that branched on it * Update setup.py Co-authored-by: Hugo van Kemenade * remove * review feedback Co-authored-by: Hugo van Kemenade --- .github/workflows/ci.yml | 16 - .github/workflows/wheel-builder.yml | 28 +- .zuul.d/jobs.yaml | 11 - .zuul.d/project.yaml | 1 - CHANGELOG.rst | 2 + README.rst | 2 +- docs/development/getting-started.rst | 1 - docs/installation.rst | 15 +- setup.py | 8 +- src/cryptography/__init__.py | 13 - .../hazmat/backends/openssl/backend.py | 50 +-- .../hazmat/primitives/asymmetric/rsa.py | 7 +- src/cryptography/hazmat/primitives/padding.py | 10 +- .../hazmat/primitives/serialization/ssh.py | 6 +- src/cryptography/utils.py | 42 +- src/cryptography/x509/name.py | 6 +- tests/hazmat/primitives/test_serialization.py | 77 ++-- tests/x509/test_x509.py | 16 +- tests/x509/test_x509_ext.py | 377 +++++------------- tox.ini | 10 +- 20 files changed, 189 insertions(+), 509 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1e03eaede894..b48cb3a95e7b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,12 +16,8 @@ jobs: matrix: PYTHON: - {VERSION: "3.9", TOXENV: "pep8,packaging,docs", COVERAGE: "false"} - - {VERSION: "pypy2", TOXENV: "pypy-nocoverage", COVERAGE: "false"} - {VERSION: "pypy3", TOXENV: "pypy3-nocoverage", COVERAGE: "false"} - - {VERSION: "2.7", TOXENV: "py27", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} - - {VERSION: "2.7", TOXENV: "py27-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} - - {VERSION: "2.7", TOXENV: "py27", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1h"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1h"}} - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1h"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1h", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct"}} @@ -86,16 +82,13 @@ jobs: strategy: matrix: IMAGE: - - {IMAGE: "pyca/cryptography-runner-centos8", TOXENV: "py27"} - {IMAGE: "pyca/cryptography-runner-centos8", TOXENV: "py36"} - {IMAGE: "pyca/cryptography-runner-centos8-fips", TOXENV: "py36", FIPS: true} - - {IMAGE: "pyca/cryptography-runner-stretch", TOXENV: "py27"} - {IMAGE: "pyca/cryptography-runner-buster", TOXENV: "py37"} - {IMAGE: "pyca/cryptography-runner-bullseye", TOXENV: "py38"} - {IMAGE: "pyca/cryptography-runner-sid", TOXENV: "py39"} - {IMAGE: "pyca/cryptography-runner-ubuntu-bionic", TOXENV: "py36"} - {IMAGE: "pyca/cryptography-runner-ubuntu-focal", TOXENV: "py38"} - - {IMAGE: "pyca/cryptography-runner-ubuntu-rolling", TOXENV: "py27"} - {IMAGE: "pyca/cryptography-runner-ubuntu-rolling", TOXENV: "py38"} - {IMAGE: "pyca/cryptography-runner-ubuntu-rolling", TOXENV: "py38-randomorder"} - {IMAGE: "pyca/cryptography-runner-fedora", TOXENV: "py39"} @@ -120,7 +113,6 @@ jobs: strategy: matrix: PYTHON: - - {VERSION: "2.7", TOXENV: "py27", EXTRA_CFLAGS: ""} - {VERSION: "3.6", TOXENV: "py36", EXTRA_CFLAGS: ""} - {VERSION: "3.9", TOXENV: "py39", EXTRA_CFLAGS: "-DUSE_OSRANDOM_RNG_FOR_TESTING"} name: "Python ${{ matrix.PYTHON.VERSION }} on macOS" @@ -162,7 +154,6 @@ jobs: - {ARCH: 'x86', WINDOWS: 'win32'} - {ARCH: 'x64', WINDOWS: 'win64'} PYTHON: - - {VERSION: "2.7", TOXENV: "py27", MSVC_VERSION: "2010", CL_FLAGS: ""} - {VERSION: "3.6", TOXENV: "py36", MSVC_VERSION: "2019", CL_FLAGS: ""} - {VERSION: "3.7", TOXENV: "py37", MSVC_VERSION: "2019", CL_FLAGS: ""} - {VERSION: "3.8", TOXENV: "py38", MSVC_VERSION: "2019", CL_FLAGS: ""} @@ -176,13 +167,6 @@ jobs: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} - - name: Install MSVC for Python 2.7 - run: | - Invoke-WebRequest -Uri https://download.microsoft.com/download/7/9/6/796EF2E4-801B-4FC4-AB28-B59FBF6D907B/VCForPython27.msi -OutFile VCForPython27.msi - Start-Process msiexec -Wait -ArgumentList @('/i', 'VCForPython27.msi', '/qn', 'ALLUSERS=1') - Remove-Item VCForPython27.msi -Force - shell: powershell - if: matrix.PYTHON.VERSION == '2.7' - run: python -m pip install tox requests coverage - name: Download OpenSSL run: | diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index b74edc2da5a4..4365174c80c8 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -11,7 +11,7 @@ jobs: container: ${{ matrix.MANYLINUX.CONTAINER }} strategy: matrix: - PYTHON: ["cp27-cp27m", "cp27-cp27mu", "cp36-cp36m"] + PYTHON: ["cp36-cp36m"] MANYLINUX: - NAME: manylinux1_x86_64 CONTAINER: "pyca/cryptography-manylinux1:x86_64" @@ -57,12 +57,8 @@ jobs: strategy: matrix: PYTHON: - - VERSION: '2.7' - ABI_VERSION: '2.7' - DOWNLOAD_URL: 'https://www.python.org/ftp/python/2.7.17/python-2.7.17-macosx10.9.pkg' - BIN_PATH: '/Library/Frameworks/Python.framework/Versions/2.7/bin/python' - VERSION: '3.8' - ABI_VERSION: '3.6' + ABI_VERSION: 'cp36' DOWNLOAD_URL: 'https://www.python.org/ftp/python/3.8.2/python-3.8.2-macosx10.9.pkg' BIN_PATH: '/Library/Frameworks/Python.framework/Versions/3.8/bin/python3' name: "${{ matrix.PYTHON.VERSION }} ABI ${{ matrix.PYTHON.ABI_VERSION }} macOS" @@ -85,16 +81,11 @@ jobs: - run: venv/bin/pip download cryptography==${{ github.event.inputs.version }} --no-deps --no-binary cryptography && tar zxvf cryptography*.tar.gz && mkdir wheelhouse - name: Build the wheel run: | - REGEX="3\.([0-9])*" - if [[ "${{ matrix.PYTHON.ABI_VERSION }}" =~ $REGEX ]]; then - PY_LIMITED_API="--py-limited-api=cp3${BASH_REMATCH[1]}" - fi - cd cryptography* CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS="1" \ LDFLAGS="${HOME}/openssl-macos-x86-64/lib/libcrypto.a ${HOME}/openssl-macos-x86-64/lib/libssl.a" \ CFLAGS="-I${HOME}/openssl-macos-x86-64/include -mmacosx-version-min=10.10 -march=core2" \ - ../venv/bin/python setup.py bdist_wheel $PY_LIMITED_API && mv dist/cryptography*.whl ../wheelhouse + ../venv/bin/python setup.py bdist_wheel --py-limited-api=${{ matrix.PYTHON.ABI_VERSION }} && mv dist/cryptography*.whl ../wheelhouse - run: venv/bin/pip install -f wheelhouse --no-index cryptography - 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'))" @@ -114,8 +105,7 @@ jobs: - {ARCH: 'x86', WINDOWS: 'win32'} - {ARCH: 'x64', WINDOWS: 'win64'} PYTHON: - - {VERSION: "2.7", MSVC_VERSION: "2010"} - - {VERSION: "3.8", MSVC_VERSION: "2019", "USE_ABI3": "true", "ABI_VERSION": "cp36"} + - {VERSION: "3.8", MSVC_VERSION: "2019", "ABI_VERSION": "cp36"} name: "${{ matrix.PYTHON.VERSION }} ${{ matrix.WINDOWS.WINDOWS }} ${{ matrix.PYTHON.ABI_VERSION }}" steps: - uses: actions/checkout@v2 @@ -124,13 +114,6 @@ jobs: with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} - - name: Install MSVC for Python 2.7 - run: | - Invoke-WebRequest -Uri https://download.microsoft.com/download/7/9/6/796EF2E4-801B-4FC4-AB28-B59FBF6D907B/VCForPython27.msi -OutFile VCForPython27.msi - Start-Process msiexec -Wait -ArgumentList @('/i', 'VCForPython27.msi', '/qn', 'ALLUSERS=1') - Remove-Item VCForPython27.msi -Force - shell: powershell - if: matrix.PYTHON.VERSION == '2.7' - run: pip install requests - name: Download OpenSSL run: | @@ -144,10 +127,7 @@ jobs: - run: python -m pip install -U pip wheel cffi six ipaddress "enum34; python_version < '3'" - run: pip download cryptography==${{ github.event.inputs.version }} --no-deps --no-binary cryptography && tar zxvf cryptography*.tar.gz && mkdir wheelhouse shell: bash - - run: cd cryptography* && python setup.py bdist_wheel && mv dist/cryptography*.whl ../wheelhouse - if: matrix.PYTHON.USE_ABI3 != 'true' - run: cd cryptography* && python setup.py bdist_wheel --py-limited-api=${{ matrix.PYTHON.ABI_VERSION }} && mv dist/cryptography*.whl ../wheelhouse - if: matrix.PYTHON.USE_ABI3 == 'true' - run: pip install -f wheelhouse --no-index cryptography - name: Print the OpenSSL we built and linked against run: | diff --git a/.zuul.d/jobs.yaml b/.zuul.d/jobs.yaml index 38cab295060f..bf542b0c96c2 100644 --- a/.zuul.d/jobs.yaml +++ b/.zuul.d/jobs.yaml @@ -25,13 +25,6 @@ vars: tox_envlist: py36 -- job: - name: pyca-cryptography-centos-8-py27-arm64 - parent: pyca-cryptography-base - nodeset: centos-8-arm64 - vars: - tox_envlist: py27 - - job: name: pyca-cryptography-build-wheel abstract: true @@ -57,12 +50,8 @@ - platform: manylinux1_x86_64 image: pyca/cryptography-manylinux1:x86_64 pythons: - - cp27-cp27m - - cp27-cp27mu - cp36-cp36m - platform: manylinux2010_x86_64 image: pyca/cryptography-manylinux2010:x86_64 pythons: - - cp27-cp27m - - cp27-cp27mu - cp36-cp36m diff --git a/.zuul.d/project.yaml b/.zuul.d/project.yaml index 3cda2ff87d00..b05d6b56f164 100644 --- a/.zuul.d/project.yaml +++ b/.zuul.d/project.yaml @@ -6,7 +6,6 @@ - pyca-cryptography-ubuntu-focal-py38-arm64 - pyca-cryptography-ubuntu-bionic-py36-arm64 - pyca-cryptography-centos-8-py36-arm64 - - pyca-cryptography-centos-8-py27-arm64 release: jobs: - pyca-cryptography-build-wheel-arm64 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d392c47cdfa5..a5e699ddba08 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,8 @@ Changelog .. note:: This version is not yet released and is under active development. +* **BACKWARDS INCOMPATIBLE:** Support for Python 2 has been removed. + .. _v3-3: 3.3 - 2020-12-08 diff --git a/README.rst b/README.rst index 10de198b8af4..06bdbbec1f65 100644 --- a/README.rst +++ b/README.rst @@ -18,7 +18,7 @@ pyca/cryptography ``cryptography`` is a package which provides cryptographic recipes and primitives to Python developers. Our goal is for it to be your "cryptographic -standard library". It supports Python 2.7, Python 3.6+, and PyPy 5.4+. +standard library". It supports Python 3.6+ and PyPy3 7.2+. ``cryptography`` includes both high level recipes and low level interfaces to common cryptographic algorithms such as symmetric ciphers, message digests, and diff --git a/docs/development/getting-started.rst b/docs/development/getting-started.rst index 1d939a9c3786..e230fc30d405 100644 --- a/docs/development/getting-started.rst +++ b/docs/development/getting-started.rst @@ -79,7 +79,6 @@ each supported Python version and run the tests. For example: $ tox ... - py27: commands succeeded ERROR: pypy: InterpreterNotFound: pypy py38: commands succeeded docs: commands succeeded diff --git a/docs/installation.rst b/docs/installation.rst index ea4625582a87..9696f7d3915b 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -10,10 +10,9 @@ You can install ``cryptography`` with ``pip``: Supported platforms ------------------- -Currently we test ``cryptography`` on Python 2.7, 3.6+, -PyPy 7.3.1, and PyPy3 7.3.1 on these operating systems. +Currently we test ``cryptography`` on Python 3.6+ and PyPy3 7.3.1 on these +operating systems. -* x86-64 CentOS 7.x * x86-64 & AArch64 CentOS 8.x * x86-64 Fedora (latest) * x86-64 macOS 10.15 Catalina @@ -45,9 +44,9 @@ just run If you prefer to compile it yourself you'll need to have OpenSSL installed. You can compile OpenSSL yourself as well or use `a binary distribution`_. Be sure to download the proper version for your architecture and Python -(VC2010 works for Python 2.7 while VC2015 is required for 3.6 and above). -Wherever you place your copy of OpenSSL you'll need to set the ``LIB`` and ``INCLUDE`` -environment variables to include the proper locations. For example: +(VC2015 is required for 3.6 and above). Wherever you place your copy of OpenSSL +you'll need to set the ``LIB`` and ``INCLUDE`` environment variables to include +the proper locations. For example: .. code-block:: console @@ -87,8 +86,6 @@ available on your system. Alpine ~~~~~~ -Replace ``python3-dev`` with ``python-dev`` if you're using Python 2. - .. code-block:: console $ sudo apk add gcc musl-dev python3-dev libffi-dev openssl-dev @@ -98,8 +95,6 @@ If you get an error with ``openssl-dev`` you may have to use ``libressl-dev``. Debian/Ubuntu ~~~~~~~~~~~~~ -Replace ``python3-dev`` with ``python-dev`` if you're using Python 2. - .. code-block:: console $ sudo apt-get install build-essential libssl-dev libffi-dev python3-dev diff --git a/setup.py b/setup.py index 4ebbc1b50203..230affec5571 100644 --- a/setup.py +++ b/setup.py @@ -63,9 +63,8 @@ "Operating System :: POSIX :: Linux", "Operating System :: Microsoft :: Windows", "Programming Language :: Python", - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", @@ -79,13 +78,10 @@ where="src", exclude=["_cffi_src", "_cffi_src.*"] ), include_package_data=True, - python_requires=( - ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*" - ), + python_requires=">=3.6", install_requires=["six >= 1.4.1"] + setup_requirements, setup_requires=setup_requirements, extras_require={ - ":python_version < '3'": ["enum34", "ipaddress"], "test": [ "pytest>=3.6.0,!=3.9.0,!=3.9.1,!=3.9.2", "pretend", diff --git a/src/cryptography/__init__.py b/src/cryptography/__init__.py index 465671eec826..7b6ae2860c3a 100644 --- a/src/cryptography/__init__.py +++ b/src/cryptography/__init__.py @@ -4,9 +4,6 @@ from __future__ import absolute_import, division, print_function -import sys -import warnings - from cryptography.__about__ import ( __author__, __copyright__, @@ -17,7 +14,6 @@ __uri__, __version__, ) -from cryptography.utils import CryptographyDeprecationWarning __all__ = [ @@ -30,12 +26,3 @@ "__license__", "__copyright__", ] - -if sys.version_info[0] == 2: - warnings.warn( - "Python 2 is no longer supported by the Python core team. Support for " - "it is now deprecated in cryptography, and will be removed in the " - "next release.", - CryptographyDeprecationWarning, - stacklevel=2, - ) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 45d4a1a1eec9..f6193287746c 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -10,7 +10,6 @@ import warnings from contextlib import contextmanager -import six from six.moves import range from cryptography import utils, x509 @@ -521,24 +520,15 @@ def _consume_errors_with_text(self): def _bn_to_int(self, bn): assert bn != self._ffi.NULL - if not six.PY2: - # Python 3 has constant time from_bytes, so use that. - bn_num_bytes = self._lib.BN_num_bytes(bn) - bin_ptr = self._ffi.new("unsigned char[]", bn_num_bytes) - bin_len = self._lib.BN_bn2bin(bn, bin_ptr) - # A zero length means the BN has value 0 - self.openssl_assert(bin_len >= 0) - val = int.from_bytes(self._ffi.buffer(bin_ptr)[:bin_len], "big") - if self._lib.BN_is_negative(bn): - val = -val - return val - else: - # Under Python 2 the best we can do is hex() - hex_cdata = self._lib.BN_bn2hex(bn) - self.openssl_assert(hex_cdata != self._ffi.NULL) - hex_str = self._ffi.string(hex_cdata) - self._lib.OPENSSL_free(hex_cdata) - return int(hex_str, 16) + bn_num_bytes = self._lib.BN_num_bytes(bn) + bin_ptr = self._ffi.new("unsigned char[]", bn_num_bytes) + bin_len = self._lib.BN_bn2bin(bn, bin_ptr) + # A zero length means the BN has value 0 + self.openssl_assert(bin_len >= 0) + val = int.from_bytes(self._ffi.buffer(bin_ptr)[:bin_len], "big") + if self._lib.BN_is_negative(bn): + val = -val + return val def _int_to_bn(self, num, bn=None): """ @@ -552,24 +542,10 @@ def _int_to_bn(self, num, bn=None): if bn is None: bn = self._ffi.NULL - if not six.PY2: - # Python 3 has constant time to_bytes, so use that. - - binary = num.to_bytes(int(num.bit_length() / 8.0 + 1), "big") - bn_ptr = self._lib.BN_bin2bn(binary, len(binary), bn) - self.openssl_assert(bn_ptr != self._ffi.NULL) - return bn_ptr - - else: - # Under Python 2 the best we can do is hex(), [2:] removes the 0x - # prefix. - hex_num = hex(num).rstrip("L")[2:].encode("ascii") - bn_ptr = self._ffi.new("BIGNUM **") - bn_ptr[0] = bn - res = self._lib.BN_hex2bn(bn_ptr, hex_num) - self.openssl_assert(res != 0) - self.openssl_assert(bn_ptr[0] != self._ffi.NULL) - return bn_ptr[0] + binary = num.to_bytes(int(num.bit_length() / 8.0 + 1), "big") + bn_ptr = self._lib.BN_bin2bn(binary, len(binary), bn) + self.openssl_assert(bn_ptr != self._ffi.NULL) + return bn_ptr def generate_rsa_private_key(self, public_exponent, key_size): rsa._verify_rsa_parameters(public_exponent, key_size) diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py index ea16bbf66e66..28c3072bd2e8 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py @@ -5,12 +5,7 @@ from __future__ import absolute_import, division, print_function import abc - -try: - # Only available in math in 3.5+ - from math import gcd -except ImportError: - from fractions import gcd +from math import gcd import six diff --git a/src/cryptography/hazmat/primitives/padding.py b/src/cryptography/hazmat/primitives/padding.py index 98abffbc08be..d3dc7093ae51 100644 --- a/src/cryptography/hazmat/primitives/padding.py +++ b/src/cryptography/hazmat/primitives/padding.py @@ -42,10 +42,7 @@ def _byte_padding_update(buffer_, data, block_size): utils._check_byteslike("data", data) - # six.PY2: Only coerce non-bytes objects to avoid triggering bad behavior - # of future's newbytes type. Unconditionally call bytes() after Python 2 - # support is gone. - buffer_ += data if isinstance(data, bytes) else bytes(data) + buffer_ += bytes(data) finished_blocks = len(buffer_) // (block_size // 8) @@ -69,10 +66,7 @@ def _byte_unpadding_update(buffer_, data, block_size): utils._check_byteslike("data", data) - # six.PY2: Only coerce non-bytes objects to avoid triggering bad behavior - # of future's newbytes type. Unconditionally call bytes() after Python 2 - # support is gone. - buffer_ += data if isinstance(data, bytes) else bytes(data) + buffer_ += bytes(data) finished_blocks = max(len(buffer_) // (block_size // 8) - 1, 0) diff --git a/src/cryptography/hazmat/primitives/serialization/ssh.py b/src/cryptography/hazmat/primitives/serialization/ssh.py index 5ecae59f8aa6..783586cb4366 100644 --- a/src/cryptography/hazmat/primitives/serialization/ssh.py +++ b/src/cryptography/hazmat/primitives/serialization/ssh.py @@ -8,6 +8,7 @@ import os import re import struct +from base64 import encodebytes as _base64_encode import six @@ -34,11 +35,6 @@ def _bcrypt_kdf(*args, **kwargs): raise UnsupportedAlgorithm("Need bcrypt module") -try: - from base64 import encodebytes as _base64_encode -except ImportError: - from base64 import encodestring as _base64_encode - _SSH_ED25519 = b"ssh-ed25519" _SSH_RSA = b"ssh-rsa" _SSH_DSA = b"ssh-dss" diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index bdb3dbf4776f..025f61623e54 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -5,7 +5,6 @@ from __future__ import absolute_import, division, print_function import abc -import binascii import inspect import sys import warnings @@ -59,46 +58,19 @@ def register_decorator(klass): return register_decorator -if hasattr(int, "from_bytes"): - int_from_bytes = int.from_bytes -else: +int_from_bytes = int.from_bytes - def int_from_bytes(data, byteorder, signed=False): - assert byteorder == "big" - assert not signed - return int(binascii.hexlify(data), 16) - - -if hasattr(int, "to_bytes"): - - def int_to_bytes(integer, length=None): - return integer.to_bytes( - length or (integer.bit_length() + 7) // 8 or 1, "big" - ) - - -else: - - def int_to_bytes(integer, length=None): - hex_string = "%x" % integer - if length is None: - n = len(hex_string) - else: - n = length * 2 - return binascii.unhexlify(hex_string.zfill(n + (n & 1))) +def int_to_bytes(integer, length=None): + return integer.to_bytes( + length or (integer.bit_length() + 7) // 8 or 1, "big" + ) class InterfaceNotImplemented(Exception): pass -if hasattr(inspect, "signature"): - signature = inspect.signature -else: - signature = inspect.getargspec - - def verify_interface(iface, klass): for method in iface.__abstractmethods__: if not hasattr(klass, method): @@ -108,8 +80,8 @@ def verify_interface(iface, klass): if isinstance(getattr(iface, method), abc.abstractproperty): # Can't properly verify these yet. continue - sig = signature(getattr(iface, method)) - actual = signature(getattr(klass, method)) + sig = inspect.signature(getattr(iface, method)) + actual = inspect.signature(getattr(klass, method)) if sig != actual: raise InterfaceNotImplemented( "{}.{}'s signature differs from the expected. Expected: " diff --git a/src/cryptography/x509/name.py b/src/cryptography/x509/name.py index 0be876a0ed6c..caf536f60381 100644 --- a/src/cryptography/x509/name.py +++ b/src/cryptography/x509/name.py @@ -254,8 +254,4 @@ def __len__(self): def __repr__(self): rdns = ",".join(attr.rfc4514_string() for attr in self._attributes) - - if six.PY2: - return "".format(rdns.encode("utf8")) - else: - return "".format(rdns) + return "".format(rdns) diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index 32debd46c7d2..4b125c1e09fb 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -11,8 +11,6 @@ import pytest -import six - from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.backends.interfaces import ( DERSerializationBackend, @@ -1238,9 +1236,8 @@ def test_load_ssh_public_key_byteslike(self, backend): b"teIg1TO03/FD9hbpBFgBeix3NrCFPls= root@cloud-server-01" ) assert load_ssh_public_key(bytearray(ssh_key), backend) - if six.PY3: - assert load_ssh_public_key(memoryview(ssh_key), backend) - assert load_ssh_public_key(memoryview(bytearray(ssh_key)), backend) + assert load_ssh_public_key(memoryview(ssh_key), backend) + assert load_ssh_public_key(memoryview(bytearray(ssh_key)), backend) def test_load_ssh_public_key_ecdsa_nist_p384(self, backend): _skip_curve_unsupported(backend, ec.SECP384R1()) @@ -1942,28 +1939,27 @@ def test_load_ssh_private_key(self, key_file, backend): == nocomment_data ) - if six.PY3: - # memoryview(bytes) - private_key = load_ssh_private_key( - memoryview(priv_data), password, backend - ) - assert ( - private_key.public_key().public_bytes( - Encoding.OpenSSH, PublicFormat.OpenSSH - ) - == nocomment_data + # memoryview(bytes) + private_key = load_ssh_private_key( + memoryview(priv_data), password, backend + ) + assert ( + private_key.public_key().public_bytes( + Encoding.OpenSSH, PublicFormat.OpenSSH ) + == nocomment_data + ) - # memoryview(bytearray) - private_key = load_ssh_private_key( - memoryview(bytearray(priv_data)), password, backend - ) - assert ( - private_key.public_key().public_bytes( - Encoding.OpenSSH, PublicFormat.OpenSSH - ) - == nocomment_data + # memoryview(bytearray) + private_key = load_ssh_private_key( + memoryview(bytearray(priv_data)), password, backend + ) + assert ( + private_key.public_key().public_bytes( + Encoding.OpenSSH, PublicFormat.OpenSSH ) + == nocomment_data + ) # serialize with own code and reload encryption = NoEncryption() @@ -2022,24 +2018,23 @@ def test_bcrypt_encryption(self, backend): ) assert pub1 == pub2 - if six.PY3: - # memoryview(bytes) - decoded_key2 = load_ssh_private_key( - memoryview(encdata), psw, backend - ) - pub2 = decoded_key2.public_key().public_bytes( - Encoding.OpenSSH, PublicFormat.OpenSSH - ) - assert pub1 == pub2 + # memoryview(bytes) + decoded_key2 = load_ssh_private_key( + memoryview(encdata), psw, backend + ) + pub2 = decoded_key2.public_key().public_bytes( + Encoding.OpenSSH, PublicFormat.OpenSSH + ) + assert pub1 == pub2 - # memoryview(bytearray) - decoded_key2 = load_ssh_private_key( - memoryview(bytearray(encdata)), psw, backend - ) - pub2 = decoded_key2.public_key().public_bytes( - Encoding.OpenSSH, PublicFormat.OpenSSH - ) - assert pub1 == pub2 + # memoryview(bytearray) + decoded_key2 = load_ssh_private_key( + memoryview(bytearray(encdata)), psw, backend + ) + pub2 = decoded_key2.public_key().public_bytes( + Encoding.OpenSSH, PublicFormat.OpenSSH + ) + assert pub1 == pub2 with pytest.raises(ValueError): decoded_key = load_ssh_private_key(encdata, None, backend) diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 146619b9a84b..2e5656d8aa34 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -16,8 +16,6 @@ import pytz -import six - from cryptography import utils, x509 from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat._der import ( @@ -4810,16 +4808,10 @@ def test_ne(self): def test_repr(self): na = x509.NameAttribute(x509.ObjectIdentifier("2.5.4.3"), u"value") - if not six.PY2: - assert repr(na) == ( - ", value='value')>" - ) - else: - assert repr(na) == ( - ", value=u'value')>" - ) + assert repr(na) == ( + ", value='value')>" + ) def test_distinugished_name(self): # Escaping diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index 8e2b402712ff..0e231069f84c 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -13,8 +13,6 @@ import pytest -import six - from cryptography import x509 from cryptography.hazmat.backends.interfaces import ( DSABackend, @@ -213,16 +211,10 @@ def test_repr(self): ext1 = x509.UnrecognizedExtension( x509.ObjectIdentifier("1.2.3.4"), b"\x03\x02\x01" ) - if not six.PY2: - assert repr(ext1) == ( - ", value=b'\\x03\\x02\\x01')>" - ) - else: - assert repr(ext1) == ( - ", value='\\x03\\x02\\x01')>" - ) + assert repr(ext1) == ( + ", value=b'\\x03\\x02\\x01')>" + ) def test_hash(self): ext1 = x509.UnrecognizedExtension( @@ -275,16 +267,10 @@ def test_ne(self): def test_repr(self): ci = x509.CertificateIssuer([x509.DNSName(u"cryptography.io")]) - if not six.PY2: - assert repr(ci) == ( - "])>)>" - ) - else: - assert repr(ci) == ( - "])>)>" - ) + assert repr(ci) == ( + "])>)>" + ) def test_get_values_for_type(self): ci = x509.CertificateIssuer([x509.DNSName(u"cryptography.io")]) @@ -405,16 +391,10 @@ def test_iter_input(self): def test_repr(self): nr = x509.NoticeReference(u"org", [1, 3, 4]) - if not six.PY2: - assert repr(nr) == ( - "" - ) - else: - assert repr(nr) == ( - "" - ) + assert repr(nr) == ( + "" + ) def test_eq(self): nr = x509.NoticeReference("org", [1, 2]) @@ -449,16 +429,10 @@ def test_notice_reference_none(self): def test_repr(self): un = x509.UserNotice(x509.NoticeReference(u"org", [1]), u"text") - if not six.PY2: - assert repr(un) == ( - ", explicit_text='text')>" - ) - else: - assert repr(un) == ( - ", explicit_text=u'text')>" - ) + assert repr(un) == ( + ", explicit_text='text')>" + ) def test_eq(self): nr = x509.NoticeReference("org", [1, 2]) @@ -515,18 +489,11 @@ def test_iter_input(self): def test_repr(self): pq = [u"string", x509.UserNotice(None, u"hi")] pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), pq) - if not six.PY2: - assert repr(pi) == ( - ", policy_qualifiers=['string', ])>" - ) - else: - assert repr(pi) == ( - ", policy_qualifiers=[u'string', ])>" - ) + assert repr(pi) == ( + ", policy_qualifiers=['string', ])>" + ) def test_eq(self): pi = x509.PolicyInformation( @@ -594,18 +561,11 @@ def test_repr(self): pq = [u"string"] pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), pq) cp = x509.CertificatePolicies([pi]) - if not six.PY2: - assert repr(cp) == ( - ", policy_qualifi" - "ers=['string'])>])>" - ) - else: - assert repr(cp) == ( - ", policy_qualifi" - "ers=[u'string'])>])>" - ) + assert repr(cp) == ( + ", policy_qualifi" + "ers=['string'])>])>" + ) def test_eq(self): pi = x509.PolicyInformation( @@ -1011,20 +971,12 @@ def test_repr(self): binascii.unhexlify(b"092384932230498bc980aa8098456f6ff7ff3ac9") ) ext = x509.Extension(ExtensionOID.SUBJECT_KEY_IDENTIFIER, False, ski) - if not six.PY2: - assert repr(ext) == ( - ", critical=False, value=)>" - ) - else: - assert repr(ext) == ( - ", critical=False, value=)>" - ) + assert repr(ext) == ( + ", critical=False, value=)>" + ) def test_eq(self): ski = x509.SubjectKeyIdentifier( @@ -1128,18 +1080,11 @@ def test_repr(self): ) aki = x509.AuthorityKeyIdentifier(b"digest", [dirname], 1234) - if not six.PY2: - assert repr(aki) == ( - ")>], author" - "ity_cert_serial_number=1234)>" - ) - else: - assert repr(aki) == ( - ")>], author" - "ity_cert_serial_number=1234)>" - ) + assert repr(aki) == ( + ")>], author" + "ity_cert_serial_number=1234)>" + ) def test_eq(self): dirname = x509.DirectoryName( @@ -1806,10 +1751,7 @@ def test_hash(self): class TestRFC822Name(object): def test_repr(self): gn = x509.RFC822Name(u"string") - if not six.PY2: - assert repr(gn) == "" - else: - assert repr(gn) == "" + assert repr(gn) == "" def test_equality(self): gn = x509.RFC822Name(u"string") @@ -1891,10 +1833,7 @@ def test_hash(self): def test_repr(self): gn = x509.UniformResourceIdentifier(u"string") - if not six.PY2: - assert repr(gn) == ("") - else: - assert repr(gn) == ("") + assert repr(gn) == ("") class TestRegisteredID(object): @@ -1981,28 +1920,16 @@ def test_invalid_args(self): def test_repr(self): gn = x509.OtherName(x509.ObjectIdentifier("1.2.3.4"), b"derdata") - if not six.PY2: - assert repr(gn) == ( - ", value=b'derdata')>" - ) - else: - assert repr(gn) == ( - ", value='derdata')>" - ) + assert repr(gn) == ( + ", value=b'derdata')>" + ) gn = x509.OtherName(x509.ObjectIdentifier("2.5.4.65"), b"derdata") - if not six.PY2: - assert repr(gn) == ( - ", value=b'derdata')>" - ) - else: - assert repr(gn) == ( - ", value='derdata')>" - ) + assert repr(gn) == ( + ", value=b'derdata')>" + ) def test_eq(self): gn = x509.OtherName(x509.ObjectIdentifier("1.2.3.4"), b"derdata") @@ -2070,14 +1997,9 @@ def test_invalid_general_names(self): def test_repr(self): gns = x509.GeneralNames([x509.DNSName(u"cryptography.io")]) - if not six.PY2: - assert repr(gns) == ( - "])>" - ) - else: - assert repr(gns) == ( - "])>" - ) + assert repr(gns) == ( + "])>" + ) def test_eq(self): gns = x509.GeneralNames([x509.DNSName(u"cryptography.io")]) @@ -2135,16 +2057,10 @@ def test_invalid_general_names(self): def test_repr(self): san = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")]) - if not six.PY2: - assert repr(san) == ( - "])>)>" - ) - else: - assert repr(san) == ( - "])>)>" - ) + assert repr(san) == ( + "])>)>" + ) def test_eq(self): san = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")]) @@ -2249,16 +2165,10 @@ def test_invalid_general_names(self): def test_repr(self): san = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]) - if not six.PY2: - assert repr(san) == ( - "])>)>" - ) - else: - assert repr(san) == ( - "])>)>" - ) + assert repr(san) == ( + "])>)>" + ) def test_eq(self): san = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]) @@ -2634,18 +2544,11 @@ def test_repr(self): AuthorityInformationAccessOID.OCSP, x509.UniformResourceIdentifier(u"http://ocsp.domain.com"), ) - if not six.PY2: - assert repr(ad) == ( - ", access_location=)>" - ) - else: - assert repr(ad) == ( - ", access_location=)>" - ) + assert repr(ad) == ( + ", access_location=)>" + ) def test_eq(self): ad = x509.AccessDescription( @@ -2826,26 +2729,15 @@ def test_repr(self): ), ] ) - if not six.PY2: - assert repr(aia) == ( - ", acces" - "s_location=)>, , access_lo" - "cation=)>])>" - ) - else: - assert repr(aia) == ( - ", acces" - "s_location=)>, , access_lo" - "cation=)>])>" - ) + assert repr(aia) == ( + ", acces" + "s_location=)>, , access_lo" + "cation=)>])>" + ) def test_eq(self): aia = x509.AuthorityInformationAccess( @@ -3031,20 +2923,12 @@ def test_repr(self): ) ] ) - if not six.PY2: - assert repr(sia) == ( - ", access_location=)>])>" - ) - else: - assert repr(sia) == ( - ", access_location=)>])>" - ) + assert repr(sia) == ( + ", access_location=)>])>" + ) def test_eq(self): sia = x509.SubjectInformationAccess( @@ -3509,18 +3393,11 @@ def test_repr(self): nc = x509.NameConstraints( permitted_subtrees=permitted, excluded_subtrees=None ) - if not six.PY2: - assert repr(nc) == ( - ", ], excluded_subtrees=None)>" - ) - else: - assert repr(nc) == ( - ", ], excluded_subtrees=None)>" - ) + assert repr(nc) == ( + ", ], excluded_subtrees=None)>" + ) def test_eq(self): nc = x509.NameConstraints( @@ -3874,20 +3751,12 @@ def test_repr(self): ) ], ) - if not six.PY2: - assert repr(dp) == ( - ", reasons=frozenset({}), crl_issuer=[)>])>" - ) - else: - assert repr(dp) == ( - ", reasons=frozenset([]), crl_issuer=[)>])>" - ) + assert repr(dp) == ( + ", reasons=frozenset({}), crl_issuer=[)>])>" + ) def test_hash(self): dp = x509.DistributionPoint( @@ -3983,20 +3852,12 @@ def test_repr(self): ), ] ) - if not six.PY2: - assert repr(fcrl) == ( - "], relative" - "_name=None, reasons=frozenset({}), crl_issuer=None)>])>" - ) - else: - assert repr(fcrl) == ( - "], relative" - "_name=None, reasons=frozenset([]), crl_issuer=None)>])>" - ) + assert repr(fcrl) == ( + "], relative" + "_name=None, reasons=frozenset({}), crl_issuer=None)>])>" + ) def test_eq(self): fcrl = x509.FreshestCRL( @@ -4246,20 +4107,12 @@ def test_repr(self): ), ] ) - if not six.PY2: - assert repr(cdp) == ( - "], relative" - "_name=None, reasons=frozenset({}), crl_issuer=None)>])>" - ) - else: - assert repr(cdp) == ( - "], relative" - "_name=None, reasons=frozenset([]), crl_issuer=None)>])>" - ) + assert repr(cdp) == ( + "], relative" + "_name=None, reasons=frozenset({}), crl_issuer=None)>])>" + ) def test_eq(self): cdp = x509.CRLDistributionPoints( @@ -5116,22 +4969,13 @@ def test_repr(self): False, False, ) - if not six.PY2: - assert repr(idp) == ( - "}), indirect_crl=False, only_contains_attribut" - "e_certs=False)>" - ) - else: - assert repr(idp) == ( - "]), indirect_crl=False, only_contains_attribut" - "e_certs=False)>" - ) + assert repr(idp) == ( + "}), indirect_crl=False, only_contains_attribut" + "e_certs=False)>" + ) def test_eq(self): idp1 = x509.IssuingDistributionPoint( @@ -5758,10 +5602,7 @@ def test_ne(self): def test_repr(self): nonce1 = x509.OCSPNonce(b"nonce") - if not six.PY2: - assert repr(nonce1) == "" - else: - assert repr(nonce1) == "" + assert repr(nonce1) == "" def test_hash(self): nonce1 = x509.OCSPNonce(b"0" * 5) diff --git a/tox.ini b/tox.ini index e6e04575bbc6..a420dceaf04f 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 2.4 -envlist = py27,pypy,py36,py37,py38,py39,docs,pep8,packaging +envlist = pypy3,py36,py37,py38,py39,docs,pep8,packaging isolated_build = True [testenv] @@ -22,14 +22,6 @@ commands = coverage combine coverage report -m -# This target disables coverage on pypy because of performance problems with -# coverage.py on pypy. -[testenv:pypy-nocoverage] -basepython = pypy -commands = - pip list - pytest --capture=no --strict {posargs} - # This target disables coverage on pypy because of performance problems with # coverage.py on pypy. [testenv:pypy3-nocoverage] From 7d4e567e16521288197aed23506f9370beadef66 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 9 Dec 2020 00:40:21 -0500 Subject: [PATCH 0003/2380] Switch black to py36 as the minimum version (#5608) --- docs/conf.py | 2 +- pyproject.toml | 2 +- setup.py | 2 +- src/_cffi_src/utils.py | 2 +- .../hazmat/backends/openssl/backend.py | 2 +- .../hazmat/backends/openssl/decode_asn1.py | 2 +- src/cryptography/x509/extensions.py | 10 +- tests/hazmat/backends/test_openssl.py | 6 +- tests/hazmat/primitives/test_chacha20.py | 2 +- tests/hazmat/primitives/test_ciphers.py | 16 +- tests/hazmat/primitives/test_cmac.py | 4 +- tests/hazmat/primitives/test_concatkdf.py | 18 +- tests/hazmat/primitives/test_constant_time.py | 6 +- tests/hazmat/primitives/test_hashes.py | 2 +- tests/hazmat/primitives/test_hkdf.py | 12 +- tests/hazmat/primitives/test_hmac.py | 4 +- tests/hazmat/primitives/test_kbkdf.py | 6 +- tests/hazmat/primitives/test_padding.py | 8 +- tests/hazmat/primitives/test_pbkdf2hmac.py | 4 +- tests/hazmat/primitives/test_pkcs7.py | 10 +- tests/hazmat/primitives/test_poly1305.py | 8 +- tests/hazmat/primitives/test_serialization.py | 4 +- tests/hazmat/primitives/test_x963kdf.py | 8 +- tests/test_fernet.py | 4 +- tests/x509/test_ocsp.py | 4 +- tests/x509/test_x509.py | 916 ++++++++--------- tests/x509/test_x509_crlbuilder.py | 62 +- tests/x509/test_x509_ext.py | 922 +++++++++--------- tests/x509/test_x509_revokedcertbuilder.py | 4 +- vectors/setup.py | 2 +- 30 files changed, 988 insertions(+), 1066 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 33240d8de1a3..fe8c38c2a59d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -81,7 +81,7 @@ base_dir = os.path.join(os.path.dirname(__file__), os.pardir) about = {} with open(os.path.join(base_dir, "src", "cryptography", "__about__.py")) as f: - exec (f.read(), about) + exec(f.read(), about) version = release = about["__version__"] diff --git a/pyproject.toml b/pyproject.toml index 667f29e23ff2..c829506945cf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,4 +11,4 @@ build-backend = "setuptools.build_meta" [tool.black] line-length = 79 -target-version = ["py27"] +target-version = ["py36"] diff --git a/setup.py b/setup.py index 230affec5571..ea0df349e48e 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ about = {} with open(os.path.join(src_dir, "cryptography", "__about__.py")) as f: - exec (f.read(), about) + exec(f.read(), about) # `setup_requirements` must be kept in sync with `pyproject.toml` diff --git a/src/_cffi_src/utils.py b/src/_cffi_src/utils.py index 56745a3e5b2e..93659ffc33bd 100644 --- a/src/_cffi_src/utils.py +++ b/src/_cffi_src/utils.py @@ -16,7 +16,7 @@ base_src = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) about = {} with open(os.path.join(base_src, "cryptography", "__about__.py")) as f: - exec (f.read(), about) + exec(f.read(), about) def build_ffi_for_binding( diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index f6193287746c..976209f71902 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1167,7 +1167,7 @@ def _create_x509_extension(self, handlers, extension): *[ encode_der(INTEGER, encode_der_integer(x.value)) for x in extension.value - ] + ], ) value = _encode_asn1_str_gc(self, asn1) return self._create_raw_x509_extension(extension, value) diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index cc9b8c0e34d9..f29057e98b2d 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -132,7 +132,7 @@ def _decode_general_name(backend, gn): if "1" in bits[prefix:]: raise ValueError("Invalid netmask") - ip = ipaddress.ip_network(base.exploded + u"/{}".format(prefix)) + ip = ipaddress.ip_network(base.exploded + "/{}".format(prefix)) else: ip = ipaddress.ip_address(data) diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index 130ba69b8769..d1981704eef1 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -671,9 +671,9 @@ def __init__(self, require_explicit_policy, inhibit_policy_mapping): def __repr__(self): return ( - u"".format(self) + "".format(self) ) def __eq__(self, other): @@ -1180,8 +1180,8 @@ def _validate_ip_name(self, tree): def __repr__(self): return ( - u"".format(self) + "".format(self) ) def __hash__(self): diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index eab868fad3a6..2808a003fda8 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -39,17 +39,17 @@ def skip_if_libre_ssl(openssl_version): - if u"LibreSSL" in openssl_version: + if "LibreSSL" in openssl_version: pytest.skip("LibreSSL hard-codes RAND_bytes to use arc4random.") class TestLibreSkip(object): def test_skip_no(self): - assert skip_if_libre_ssl(u"OpenSSL 1.0.2h 3 May 2016") is None + assert skip_if_libre_ssl("OpenSSL 1.0.2h 3 May 2016") is None def test_skip_yes(self): with pytest.raises(pytest.skip.Exception): - skip_if_libre_ssl(u"LibreSSL 2.1.6") + skip_if_libre_ssl("LibreSSL 2.1.6") class DummyMGF(object): diff --git a/tests/hazmat/primitives/test_chacha20.py b/tests/hazmat/primitives/test_chacha20.py index cb12d3c91ae2..eda4906ad4fe 100644 --- a/tests/hazmat/primitives/test_chacha20.py +++ b/tests/hazmat/primitives/test_chacha20.py @@ -71,4 +71,4 @@ def test_invalid_nonce(self): def test_invalid_key_type(self): with pytest.raises(TypeError, match="key must be bytes"): - algorithms.ChaCha20(u"0" * 32, b"0" * 16) + algorithms.ChaCha20("0" * 32, b"0" * 16) diff --git a/tests/hazmat/primitives/test_ciphers.py b/tests/hazmat/primitives/test_ciphers.py index a9219fe99c15..4d951a136c79 100644 --- a/tests/hazmat/primitives/test_ciphers.py +++ b/tests/hazmat/primitives/test_ciphers.py @@ -46,7 +46,7 @@ def test_invalid_key_size(self): def test_invalid_key_type(self): with pytest.raises(TypeError, match="key must be bytes"): - AES(u"0" * 32) + AES("0" * 32) class TestAESXTS(object): @@ -94,7 +94,7 @@ def test_invalid_key_size(self): def test_invalid_key_type(self): with pytest.raises(TypeError, match="key must be bytes"): - Camellia(u"0" * 32) + Camellia("0" * 32) class TestTripleDES(object): @@ -109,7 +109,7 @@ def test_invalid_key_size(self): def test_invalid_key_type(self): with pytest.raises(TypeError, match="key must be bytes"): - TripleDES(u"0" * 16) + TripleDES("0" * 16) class TestBlowfish(object): @@ -127,7 +127,7 @@ def test_invalid_key_size(self): def test_invalid_key_type(self): with pytest.raises(TypeError, match="key must be bytes"): - Blowfish(u"0" * 8) + Blowfish("0" * 8) class TestCAST5(object): @@ -145,7 +145,7 @@ def test_invalid_key_size(self): def test_invalid_key_type(self): with pytest.raises(TypeError, match="key must be bytes"): - CAST5(u"0" * 10) + CAST5("0" * 10) class TestARC4(object): @@ -171,7 +171,7 @@ def test_invalid_key_size(self): def test_invalid_key_type(self): with pytest.raises(TypeError, match="key must be bytes"): - ARC4(u"0" * 10) + ARC4("0" * 10) class TestIDEA(object): @@ -185,7 +185,7 @@ def test_invalid_key_size(self): def test_invalid_key_type(self): with pytest.raises(TypeError, match="key must be bytes"): - IDEA(u"0" * 16) + IDEA("0" * 16) class TestSEED(object): @@ -199,7 +199,7 @@ def test_invalid_key_size(self): def test_invalid_key_type(self): with pytest.raises(TypeError, match="key must be bytes"): - SEED(u"0" * 16) + SEED("0" * 16) def test_invalid_backend(): diff --git a/tests/hazmat/primitives/test_cmac.py b/tests/hazmat/primitives/test_cmac.py index e4a35df621fd..4ed92e7e4149 100644 --- a/tests/hazmat/primitives/test_cmac.py +++ b/tests/hazmat/primitives/test_cmac.py @@ -182,10 +182,10 @@ def test_verify_reject_unicode(self, backend): cmac = CMAC(AES(key), backend) with pytest.raises(TypeError): - cmac.update(u"") + cmac.update("") with pytest.raises(TypeError): - cmac.verify(u"") + cmac.verify("") @pytest.mark.supported( only_if=lambda backend: backend.cmac_algorithm_supported( diff --git a/tests/hazmat/primitives/test_concatkdf.py b/tests/hazmat/primitives/test_concatkdf.py index 271e01175d30..f49e4cdcd98c 100644 --- a/tests/hazmat/primitives/test_concatkdf.py +++ b/tests/hazmat/primitives/test_concatkdf.py @@ -100,7 +100,7 @@ def test_invalid_verify(self, backend): def test_unicode_typeerror(self, backend): with pytest.raises(TypeError): ConcatKDFHash( - hashes.SHA256(), 16, otherinfo=u"foo", backend=backend + hashes.SHA256(), 16, otherinfo="foo", backend=backend ) with pytest.raises(TypeError): @@ -108,21 +108,21 @@ def test_unicode_typeerror(self, backend): hashes.SHA256(), 16, otherinfo=None, backend=backend ) - ckdf.derive(u"foo") + ckdf.derive("foo") with pytest.raises(TypeError): ckdf = ConcatKDFHash( hashes.SHA256(), 16, otherinfo=None, backend=backend ) - ckdf.verify(u"foo", b"bar") + ckdf.verify("foo", b"bar") with pytest.raises(TypeError): ckdf = ConcatKDFHash( hashes.SHA256(), 16, otherinfo=None, backend=backend ) - ckdf.verify(b"foo", u"bar") + ckdf.verify(b"foo", "bar") @pytest.mark.requires_backend_interface(interface=HMACBackend) @@ -249,7 +249,7 @@ def test_unicode_typeerror(self, backend): ConcatKDFHMAC( hashes.SHA256(), 16, - salt=u"foo", + salt="foo", otherinfo=None, backend=backend, ) @@ -259,7 +259,7 @@ def test_unicode_typeerror(self, backend): hashes.SHA256(), 16, salt=None, - otherinfo=u"foo", + otherinfo="foo", backend=backend, ) @@ -268,21 +268,21 @@ def test_unicode_typeerror(self, backend): hashes.SHA256(), 16, salt=None, otherinfo=None, backend=backend ) - ckdf.derive(u"foo") + ckdf.derive("foo") with pytest.raises(TypeError): ckdf = ConcatKDFHMAC( hashes.SHA256(), 16, salt=None, otherinfo=None, backend=backend ) - ckdf.verify(u"foo", b"bar") + ckdf.verify("foo", b"bar") with pytest.raises(TypeError): ckdf = ConcatKDFHMAC( hashes.SHA256(), 16, salt=None, otherinfo=None, backend=backend ) - ckdf.verify(b"foo", u"bar") + ckdf.verify(b"foo", "bar") def test_invalid_backend(): diff --git a/tests/hazmat/primitives/test_constant_time.py b/tests/hazmat/primitives/test_constant_time.py index e8e85a840afc..f681bd1f85f0 100644 --- a/tests/hazmat/primitives/test_constant_time.py +++ b/tests/hazmat/primitives/test_constant_time.py @@ -12,13 +12,13 @@ class TestConstantTimeBytesEq(object): def test_reject_unicode(self): with pytest.raises(TypeError): - constant_time.bytes_eq(b"foo", u"foo") + constant_time.bytes_eq(b"foo", "foo") with pytest.raises(TypeError): - constant_time.bytes_eq(u"foo", b"foo") + constant_time.bytes_eq("foo", b"foo") with pytest.raises(TypeError): - constant_time.bytes_eq(u"foo", u"foo") + constant_time.bytes_eq("foo", "foo") def test_compares(self): assert constant_time.bytes_eq(b"foo", b"foo") is True diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py index eadd0febf25f..06637f21d3ac 100644 --- a/tests/hazmat/primitives/test_hashes.py +++ b/tests/hazmat/primitives/test_hashes.py @@ -22,7 +22,7 @@ class TestHashContext(object): def test_hash_reject_unicode(self, backend): m = hashes.Hash(hashes.SHA1(), backend=backend) with pytest.raises(TypeError): - m.update(u"\u00FC") + m.update("\u00FC") def test_hash_algorithm_instance(self, backend): with pytest.raises(TypeError): diff --git a/tests/hazmat/primitives/test_hkdf.py b/tests/hazmat/primitives/test_hkdf.py index 1d7de6c472ee..fa20f3a631e1 100644 --- a/tests/hazmat/primitives/test_hkdf.py +++ b/tests/hazmat/primitives/test_hkdf.py @@ -65,31 +65,31 @@ def test_verify_invalid(self, backend): def test_unicode_typeerror(self, backend): with pytest.raises(TypeError): - HKDF(hashes.SHA256(), 16, salt=u"foo", info=None, backend=backend) + HKDF(hashes.SHA256(), 16, salt="foo", info=None, backend=backend) with pytest.raises(TypeError): - HKDF(hashes.SHA256(), 16, salt=None, info=u"foo", backend=backend) + HKDF(hashes.SHA256(), 16, salt=None, info="foo", backend=backend) with pytest.raises(TypeError): hkdf = HKDF( hashes.SHA256(), 16, salt=None, info=None, backend=backend ) - hkdf.derive(u"foo") + hkdf.derive("foo") with pytest.raises(TypeError): hkdf = HKDF( hashes.SHA256(), 16, salt=None, info=None, backend=backend ) - hkdf.verify(u"foo", b"bar") + hkdf.verify("foo", b"bar") with pytest.raises(TypeError): hkdf = HKDF( hashes.SHA256(), 16, salt=None, info=None, backend=backend ) - hkdf.verify(b"foo", u"bar") + hkdf.verify(b"foo", "bar") def test_derive_short_output(self, backend): hkdf = HKDF(hashes.SHA256(), 4, salt=None, info=None, backend=backend) @@ -202,7 +202,7 @@ def test_unicode_error(self, backend): hkdf = HKDFExpand(hashes.SHA256(), 42, info, backend) with pytest.raises(TypeError): - hkdf.derive(u"first") + hkdf.derive("first") def test_invalid_backend(): diff --git a/tests/hazmat/primitives/test_hmac.py b/tests/hazmat/primitives/test_hmac.py index 7ea931aca4db..70db4d5d4e33 100644 --- a/tests/hazmat/primitives/test_hmac.py +++ b/tests/hazmat/primitives/test_hmac.py @@ -37,7 +37,7 @@ class TestHMAC(object): def test_hmac_reject_unicode(self, backend): h = hmac.HMAC(b"mykey", hashes.SHA1(), backend=backend) with pytest.raises(TypeError): - h.update(u"\u00FC") + h.update("\u00FC") def test_hmac_algorithm_instance(self, backend): with pytest.raises(TypeError): @@ -77,7 +77,7 @@ def test_invalid_verify(self, backend): def test_verify_reject_unicode(self, backend): h = hmac.HMAC(b"", hashes.SHA1(), backend=backend) with pytest.raises(TypeError): - h.verify(u"") + h.verify("") def test_unsupported_hash(self, backend): with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_HASH): diff --git a/tests/hazmat/primitives/test_kbkdf.py b/tests/hazmat/primitives/test_kbkdf.py index 5ff5d74ea871..bba9f5e72a2c 100644 --- a/tests/hazmat/primitives/test_kbkdf.py +++ b/tests/hazmat/primitives/test_kbkdf.py @@ -283,7 +283,7 @@ def test_unicode_error_label(self, backend): 4, 4, CounterLocation.BeforeFixed, - u"label", + "label", b"context", backend=backend, ) @@ -298,7 +298,7 @@ def test_unicode_error_context(self, backend): 4, CounterLocation.BeforeFixed, b"label", - u"context", + "context", None, backend=backend, ) @@ -317,7 +317,7 @@ def test_unicode_error_key_material(self, backend): None, backend=backend, ) - kdf.derive(u"material") + kdf.derive("material") def test_buffer_protocol(self, backend): kdf = KBKDFHMAC( diff --git a/tests/hazmat/primitives/test_padding.py b/tests/hazmat/primitives/test_padding.py index b15eb37539c5..b06c8339ce4a 100644 --- a/tests/hazmat/primitives/test_padding.py +++ b/tests/hazmat/primitives/test_padding.py @@ -38,10 +38,10 @@ def test_invalid_padding(self, size, padded): def test_non_bytes(self): padder = padding.PKCS7(128).padder() with pytest.raises(TypeError): - padder.update(u"abc") + padder.update("abc") unpadder = padding.PKCS7(128).unpadder() with pytest.raises(TypeError): - unpadder.update(u"abc") + unpadder.update("abc") def test_zany_py2_bytes_subclass(self): class mybytes(bytes): # noqa: N801 @@ -161,10 +161,10 @@ def test_invalid_padding(self, size, padded): def test_non_bytes(self): padder = padding.ANSIX923(128).padder() with pytest.raises(TypeError): - padder.update(u"abc") + padder.update("abc") unpadder = padding.ANSIX923(128).unpadder() with pytest.raises(TypeError): - unpadder.update(u"abc") + unpadder.update("abc") def test_zany_py2_bytes_subclass(self): class mybytes(bytes): # noqa: N801 diff --git a/tests/hazmat/primitives/test_pbkdf2hmac.py b/tests/hazmat/primitives/test_pbkdf2hmac.py index 34fd25cf47e5..ec7ac799ca12 100644 --- a/tests/hazmat/primitives/test_pbkdf2hmac.py +++ b/tests/hazmat/primitives/test_pbkdf2hmac.py @@ -45,12 +45,12 @@ def test_invalid_key(self, backend): def test_unicode_error_with_salt(self, backend): with pytest.raises(TypeError): - PBKDF2HMAC(hashes.SHA1(), 20, u"salt", 10, backend) + PBKDF2HMAC(hashes.SHA1(), 20, "salt", 10, backend) def test_unicode_error_with_key_material(self, backend): kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, backend) with pytest.raises(TypeError): - kdf.derive(u"unicode here") + kdf.derive("unicode here") def test_buffer_protocol(self, backend): kdf = PBKDF2HMAC(hashes.SHA1(), 10, b"salt", 10, backend) diff --git a/tests/hazmat/primitives/test_pkcs7.py b/tests/hazmat/primitives/test_pkcs7.py index 8b93cb6334ba..3aeda299583a 100644 --- a/tests/hazmat/primitives/test_pkcs7.py +++ b/tests/hazmat/primitives/test_pkcs7.py @@ -44,9 +44,7 @@ def test_load_pkcs7_pem(self): assert len(certs) == 1 assert certs[0].subject.get_attributes_for_oid( x509.oid.NameOID.COMMON_NAME - ) == [ - x509.NameAttribute(x509.oid.NameOID.COMMON_NAME, u"ISRG Root X1") - ] + ) == [x509.NameAttribute(x509.oid.NameOID.COMMON_NAME, "ISRG Root X1")] def test_load_pkcs7_der(self): certs = load_vectors_from_file( @@ -59,14 +57,14 @@ def test_load_pkcs7_der(self): x509.oid.NameOID.COMMON_NAME ) == [ x509.NameAttribute( - x509.oid.NameOID.COMMON_NAME, u"Amazon Root CA 3" + x509.oid.NameOID.COMMON_NAME, "Amazon Root CA 3" ) ] assert certs[1].subject.get_attributes_for_oid( x509.oid.NameOID.COMMON_NAME ) == [ x509.NameAttribute( - x509.oid.NameOID.COMMON_NAME, u"Amazon Root CA 2" + x509.oid.NameOID.COMMON_NAME, "Amazon Root CA 2" ) ] @@ -146,7 +144,7 @@ class TestPKCS7Builder(object): def test_invalid_data(self): builder = pkcs7.PKCS7SignatureBuilder() with pytest.raises(TypeError): - builder.set_data(u"not bytes") + builder.set_data("not bytes") def test_set_data_twice(self): builder = pkcs7.PKCS7SignatureBuilder().set_data(b"test") diff --git a/tests/hazmat/primitives/test_poly1305.py b/tests/hazmat/primitives/test_poly1305.py index 8779484ac9aa..dd84b14aabf9 100644 --- a/tests/hazmat/primitives/test_poly1305.py +++ b/tests/hazmat/primitives/test_poly1305.py @@ -71,10 +71,10 @@ def test_raises_after_finalize(self, backend): def test_reject_unicode(self, backend): poly = Poly1305(b"0" * 32) with pytest.raises(TypeError): - poly.update(u"") + poly.update("") with pytest.raises(TypeError): - Poly1305.generate_tag(b"0" * 32, u"") + Poly1305.generate_tag(b"0" * 32, "") def test_verify(self, backend): poly = Poly1305(b"0" * 32) @@ -107,10 +107,10 @@ def test_invalid_verify(self, backend): def test_verify_reject_unicode(self, backend): poly = Poly1305(b"0" * 32) with pytest.raises(TypeError): - poly.verify(u"") + poly.verify("") with pytest.raises(TypeError): - Poly1305.verify_tag(b"0" * 32, b"msg", u"") + Poly1305.verify_tag(b"0" * 32, b"msg", "") def test_invalid_key_type(self, backend): with pytest.raises(TypeError): diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index 4b125c1e09fb..549c86d5551b 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -167,7 +167,7 @@ def test_load_der_dsa_private_key(self, key_path, password, backend): @pytest.mark.requires_backend_interface(interface=RSABackend) def test_password_not_bytes(self, key_path, backend): key_file = os.path.join("asymmetric", *key_path) - password = u"this password is not bytes" + password = "this password is not bytes" with pytest.raises(TypeError): load_vectors_from_file( @@ -625,7 +625,7 @@ def test_invalid_encoding_with_traditional(self, backend): ) def test_password_not_bytes(self, key_path, backend): key_file = os.path.join("asymmetric", *key_path) - password = u"this password is not bytes" + password = "this password is not bytes" with pytest.raises(TypeError): load_vectors_from_file( diff --git a/tests/hazmat/primitives/test_x963kdf.py b/tests/hazmat/primitives/test_x963kdf.py index 5040ae41ebbf..af1c927e1331 100644 --- a/tests/hazmat/primitives/test_x963kdf.py +++ b/tests/hazmat/primitives/test_x963kdf.py @@ -86,28 +86,28 @@ def test_invalid_verify(self, backend): def test_unicode_typeerror(self, backend): with pytest.raises(TypeError): - X963KDF(hashes.SHA256(), 16, sharedinfo=u"foo", backend=backend) + X963KDF(hashes.SHA256(), 16, sharedinfo="foo", backend=backend) with pytest.raises(TypeError): xkdf = X963KDF( hashes.SHA256(), 16, sharedinfo=None, backend=backend ) - xkdf.derive(u"foo") + xkdf.derive("foo") with pytest.raises(TypeError): xkdf = X963KDF( hashes.SHA256(), 16, sharedinfo=None, backend=backend ) - xkdf.verify(u"foo", b"bar") + xkdf.verify("foo", b"bar") with pytest.raises(TypeError): xkdf = X963KDF( hashes.SHA256(), 16, sharedinfo=None, backend=backend ) - xkdf.verify(b"foo", u"bar") + xkdf.verify(b"foo", "bar") def test_invalid_backend(): diff --git a/tests/test_fernet.py b/tests/test_fernet.py index 38409b03e888..5c5ed46f3930 100644 --- a/tests/test_fernet.py +++ b/tests/test_fernet.py @@ -113,9 +113,9 @@ def test_non_base64_token(self, backend): def test_unicode(self, backend): f = Fernet(base64.urlsafe_b64encode(b"\x00" * 32), backend=backend) with pytest.raises(TypeError): - f.encrypt(u"") + f.encrypt("") with pytest.raises(TypeError): - f.decrypt(u"") + f.decrypt("") def test_timestamp_ignored_no_ttl(self, monkeypatch, backend): f = Fernet(base64.urlsafe_b64encode(b"\x00" * 32), backend=backend) diff --git a/tests/x509/test_ocsp.py b/tests/x509/test_ocsp.py index b64940242905..10dac033db29 100644 --- a/tests/x509/test_ocsp.py +++ b/tests/x509/test_ocsp.py @@ -52,8 +52,8 @@ def _generate_root(private_key=None, algorithm=hashes.SHA256()): subject = x509.Name( [ - x509.NameAttribute(x509.NameOID.COUNTRY_NAME, u"US"), - x509.NameAttribute(x509.NameOID.COMMON_NAME, u"Cryptography CA"), + x509.NameAttribute(x509.NameOID.COUNTRY_NAME, "US"), + x509.NameAttribute(x509.NameOID.COMMON_NAME, "Cryptography CA"), ] ) diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 2e5656d8aa34..f2acf9559405 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -195,14 +195,14 @@ def test_issuer(self, backend): assert isinstance(crl.issuer, x509.Name) assert list(crl.issuer) == [ - x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US"), + x509.NameAttribute(x509.OID_COUNTRY_NAME, "US"), x509.NameAttribute( - x509.OID_ORGANIZATION_NAME, u"Test Certificates 2011" + x509.OID_ORGANIZATION_NAME, "Test Certificates 2011" ), - x509.NameAttribute(x509.OID_COMMON_NAME, u"Good CA"), + x509.NameAttribute(x509.OID_COMMON_NAME, "Good CA"), ] assert crl.issuer.get_attributes_for_oid(x509.OID_COMMON_NAME) == [ - x509.NameAttribute(x509.OID_COMMON_NAME, u"Good CA") + x509.NameAttribute(x509.OID_COMMON_NAME, "Good CA") ] def test_equality(self, backend): @@ -311,12 +311,12 @@ def test_extensions(self, backend): [ x509.AccessDescription( AuthorityInformationAccessOID.CA_ISSUERS, - x509.DNSName(u"cryptography.io"), + x509.DNSName("cryptography.io"), ) ] ) assert ian.value == x509.IssuerAlternativeName( - [x509.UniformResourceIdentifier(u"https://cryptography.io")] + [x509.UniformResourceIdentifier("https://cryptography.io")] ) def test_delta_crl_indicator(self, backend): @@ -515,9 +515,9 @@ def test_revoked_extensions(self, backend): x509.DirectoryName( x509.Name( [ - x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US"), + x509.NameAttribute(x509.OID_COUNTRY_NAME, "US"), x509.NameAttribute( - x509.OID_COMMON_NAME, u"cryptography.io" + x509.OID_COMMON_NAME, "cryptography.io" ), ] ) @@ -648,7 +648,7 @@ def test_get_revoked_certificate_doesnt_reorder(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) @@ -796,14 +796,14 @@ def test_issuer(self, backend): issuer = cert.issuer assert isinstance(issuer, x509.Name) assert list(issuer) == [ - x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), x509.NameAttribute( - NameOID.ORGANIZATION_NAME, u"Test Certificates 2011" + NameOID.ORGANIZATION_NAME, "Test Certificates 2011" ), - x509.NameAttribute(NameOID.COMMON_NAME, u"Good CA"), + x509.NameAttribute(NameOID.COMMON_NAME, "Good CA"), ] assert issuer.get_attributes_for_oid(NameOID.COMMON_NAME) == [ - x509.NameAttribute(NameOID.COMMON_NAME, u"Good CA") + x509.NameAttribute(NameOID.COMMON_NAME, "Good CA") ] def test_all_issuer_name_types(self, backend): @@ -816,36 +816,36 @@ def test_all_issuer_name_types(self, backend): assert isinstance(issuer, x509.Name) assert list(issuer) == [ - x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), - x509.NameAttribute(NameOID.COUNTRY_NAME, u"CA"), - x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"), - x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Illinois"), - x509.NameAttribute(NameOID.LOCALITY_NAME, u"Chicago"), - x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"), - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Zero, LLC"), - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"One, LLC"), - x509.NameAttribute(NameOID.COMMON_NAME, u"common name 0"), - x509.NameAttribute(NameOID.COMMON_NAME, u"common name 1"), - x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"OU 0"), - x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"OU 1"), - x509.NameAttribute(NameOID.DN_QUALIFIER, u"dnQualifier0"), - x509.NameAttribute(NameOID.DN_QUALIFIER, u"dnQualifier1"), - x509.NameAttribute(NameOID.SERIAL_NUMBER, u"123"), - x509.NameAttribute(NameOID.SERIAL_NUMBER, u"456"), - x509.NameAttribute(NameOID.TITLE, u"Title 0"), - x509.NameAttribute(NameOID.TITLE, u"Title 1"), - x509.NameAttribute(NameOID.SURNAME, u"Surname 0"), - x509.NameAttribute(NameOID.SURNAME, u"Surname 1"), - x509.NameAttribute(NameOID.GIVEN_NAME, u"Given Name 0"), - x509.NameAttribute(NameOID.GIVEN_NAME, u"Given Name 1"), - x509.NameAttribute(NameOID.PSEUDONYM, u"Incognito 0"), - x509.NameAttribute(NameOID.PSEUDONYM, u"Incognito 1"), - x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u"Last Gen"), - x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u"Next Gen"), - x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"dc0"), - x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"dc1"), - x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"test0@test.local"), - x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"test1@test.local"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "CA"), + x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Texas"), + x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Illinois"), + x509.NameAttribute(NameOID.LOCALITY_NAME, "Chicago"), + x509.NameAttribute(NameOID.LOCALITY_NAME, "Austin"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Zero, LLC"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "One, LLC"), + x509.NameAttribute(NameOID.COMMON_NAME, "common name 0"), + x509.NameAttribute(NameOID.COMMON_NAME, "common name 1"), + x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, "OU 0"), + x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, "OU 1"), + x509.NameAttribute(NameOID.DN_QUALIFIER, "dnQualifier0"), + x509.NameAttribute(NameOID.DN_QUALIFIER, "dnQualifier1"), + x509.NameAttribute(NameOID.SERIAL_NUMBER, "123"), + x509.NameAttribute(NameOID.SERIAL_NUMBER, "456"), + x509.NameAttribute(NameOID.TITLE, "Title 0"), + x509.NameAttribute(NameOID.TITLE, "Title 1"), + x509.NameAttribute(NameOID.SURNAME, "Surname 0"), + x509.NameAttribute(NameOID.SURNAME, "Surname 1"), + x509.NameAttribute(NameOID.GIVEN_NAME, "Given Name 0"), + x509.NameAttribute(NameOID.GIVEN_NAME, "Given Name 1"), + x509.NameAttribute(NameOID.PSEUDONYM, "Incognito 0"), + x509.NameAttribute(NameOID.PSEUDONYM, "Incognito 1"), + x509.NameAttribute(NameOID.GENERATION_QUALIFIER, "Last Gen"), + x509.NameAttribute(NameOID.GENERATION_QUALIFIER, "Next Gen"), + x509.NameAttribute(NameOID.DOMAIN_COMPONENT, "dc0"), + x509.NameAttribute(NameOID.DOMAIN_COMPONENT, "dc1"), + x509.NameAttribute(NameOID.EMAIL_ADDRESS, "test0@test.local"), + x509.NameAttribute(NameOID.EMAIL_ADDRESS, "test1@test.local"), ] def test_subject(self, backend): @@ -862,19 +862,19 @@ def test_subject(self, backend): subject = cert.subject assert isinstance(subject, x509.Name) assert list(subject) == [ - x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), x509.NameAttribute( - NameOID.ORGANIZATION_NAME, u"Test Certificates 2011" + NameOID.ORGANIZATION_NAME, "Test Certificates 2011" ), x509.NameAttribute( NameOID.COMMON_NAME, - u"Valid pre2000 UTC notBefore Date EE Certificate Test3", + "Valid pre2000 UTC notBefore Date EE Certificate Test3", ), ] assert subject.get_attributes_for_oid(NameOID.COMMON_NAME) == [ x509.NameAttribute( NameOID.COMMON_NAME, - u"Valid pre2000 UTC notBefore Date EE Certificate Test3", + "Valid pre2000 UTC notBefore Date EE Certificate Test3", ) ] @@ -885,10 +885,10 @@ def test_unicode_name(self, backend): backend, ) assert cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME) == [ - x509.NameAttribute(NameOID.COMMON_NAME, u"We heart UTF8!\u2122") + x509.NameAttribute(NameOID.COMMON_NAME, "We heart UTF8!\u2122") ] assert cert.issuer.get_attributes_for_oid(NameOID.COMMON_NAME) == [ - x509.NameAttribute(NameOID.COMMON_NAME, u"We heart UTF8!\u2122") + x509.NameAttribute(NameOID.COMMON_NAME, "We heart UTF8!\u2122") ] def test_non_ascii_dns_name(self, backend): @@ -904,13 +904,13 @@ def test_non_ascii_dns_name(self, backend): names = san.get_values_for_type(x509.DNSName) assert names == [ - u"partner.biztositas.hu", - u"biztositas.hu", - u"*.biztositas.hu", - u"biztos\xedt\xe1s.hu", - u"*.biztos\xedt\xe1s.hu", - u"xn--biztosts-fza2j.hu", - u"*.xn--biztosts-fza2j.hu", + "partner.biztositas.hu", + "biztositas.hu", + "*.biztositas.hu", + "biztos\xedt\xe1s.hu", + "*.biztos\xedt\xe1s.hu", + "xn--biztosts-fza2j.hu", + "*.xn--biztosts-fza2j.hu", ] def test_all_subject_name_types(self, backend): @@ -922,40 +922,40 @@ def test_all_subject_name_types(self, backend): subject = cert.subject assert isinstance(subject, x509.Name) assert list(subject) == [ - x509.NameAttribute(NameOID.COUNTRY_NAME, u"AU"), - x509.NameAttribute(NameOID.COUNTRY_NAME, u"DE"), - x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"California"), - x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"New York"), - x509.NameAttribute(NameOID.LOCALITY_NAME, u"San Francisco"), - x509.NameAttribute(NameOID.LOCALITY_NAME, u"Ithaca"), - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Org Zero, LLC"), - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Org One, LLC"), - x509.NameAttribute(NameOID.COMMON_NAME, u"CN 0"), - x509.NameAttribute(NameOID.COMMON_NAME, u"CN 1"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "AU"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "DE"), + x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "California"), + x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "New York"), + x509.NameAttribute(NameOID.LOCALITY_NAME, "San Francisco"), + x509.NameAttribute(NameOID.LOCALITY_NAME, "Ithaca"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Org Zero, LLC"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Org One, LLC"), + x509.NameAttribute(NameOID.COMMON_NAME, "CN 0"), + x509.NameAttribute(NameOID.COMMON_NAME, "CN 1"), x509.NameAttribute( - NameOID.ORGANIZATIONAL_UNIT_NAME, u"Engineering 0" + NameOID.ORGANIZATIONAL_UNIT_NAME, "Engineering 0" ), x509.NameAttribute( - NameOID.ORGANIZATIONAL_UNIT_NAME, u"Engineering 1" + NameOID.ORGANIZATIONAL_UNIT_NAME, "Engineering 1" ), - x509.NameAttribute(NameOID.DN_QUALIFIER, u"qualified0"), - x509.NameAttribute(NameOID.DN_QUALIFIER, u"qualified1"), - x509.NameAttribute(NameOID.SERIAL_NUMBER, u"789"), - x509.NameAttribute(NameOID.SERIAL_NUMBER, u"012"), - x509.NameAttribute(NameOID.TITLE, u"Title IX"), - x509.NameAttribute(NameOID.TITLE, u"Title X"), - x509.NameAttribute(NameOID.SURNAME, u"Last 0"), - x509.NameAttribute(NameOID.SURNAME, u"Last 1"), - x509.NameAttribute(NameOID.GIVEN_NAME, u"First 0"), - x509.NameAttribute(NameOID.GIVEN_NAME, u"First 1"), - x509.NameAttribute(NameOID.PSEUDONYM, u"Guy Incognito 0"), - x509.NameAttribute(NameOID.PSEUDONYM, u"Guy Incognito 1"), - x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u"32X"), - x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u"Dreamcast"), - x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"dc2"), - x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"dc3"), - x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"test2@test.local"), - x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"test3@test.local"), + x509.NameAttribute(NameOID.DN_QUALIFIER, "qualified0"), + x509.NameAttribute(NameOID.DN_QUALIFIER, "qualified1"), + x509.NameAttribute(NameOID.SERIAL_NUMBER, "789"), + x509.NameAttribute(NameOID.SERIAL_NUMBER, "012"), + x509.NameAttribute(NameOID.TITLE, "Title IX"), + x509.NameAttribute(NameOID.TITLE, "Title X"), + x509.NameAttribute(NameOID.SURNAME, "Last 0"), + x509.NameAttribute(NameOID.SURNAME, "Last 1"), + x509.NameAttribute(NameOID.GIVEN_NAME, "First 0"), + x509.NameAttribute(NameOID.GIVEN_NAME, "First 1"), + x509.NameAttribute(NameOID.PSEUDONYM, "Guy Incognito 0"), + x509.NameAttribute(NameOID.PSEUDONYM, "Guy Incognito 1"), + x509.NameAttribute(NameOID.GENERATION_QUALIFIER, "32X"), + x509.NameAttribute(NameOID.GENERATION_QUALIFIER, "Dreamcast"), + x509.NameAttribute(NameOID.DOMAIN_COMPONENT, "dc2"), + x509.NameAttribute(NameOID.DOMAIN_COMPONENT, "dc3"), + x509.NameAttribute(NameOID.EMAIL_ADDRESS, "test2@test.local"), + x509.NameAttribute(NameOID.EMAIL_ADDRESS, "test3@test.local"), ] def test_load_good_ca_cert(self, backend): @@ -1277,11 +1277,11 @@ def test_load_rsa_certificate_request(self, path, loader_func, backend): subject = request.subject assert isinstance(subject, x509.Name) assert list(subject) == [ - x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), - x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"), - x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"), - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"), - x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), + x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Texas"), + x509.NameAttribute(NameOID.LOCALITY_NAME, "Austin"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA"), + x509.NameAttribute(NameOID.COMMON_NAME, "cryptography.io"), ] extensions = request.extensions assert isinstance(extensions, x509.Extensions) @@ -1427,8 +1427,8 @@ def test_subject_alt_name(self, backend): ExtensionOID.SUBJECT_ALTERNATIVE_NAME ) assert list(ext.value) == [ - x509.DNSName(u"cryptography.io"), - x509.DNSName(u"sub.cryptography.io"), + x509.DNSName("cryptography.io"), + x509.DNSName("sub.cryptography.io"), ] def test_public_bytes_pem(self, backend): @@ -1454,11 +1454,11 @@ def test_public_bytes_pem(self, backend): subject = request.subject assert isinstance(subject, x509.Name) assert list(subject) == [ - x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), - x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"), - x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"), - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"), - x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), + x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Texas"), + x509.NameAttribute(NameOID.LOCALITY_NAME, "Austin"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA"), + x509.NameAttribute(NameOID.COMMON_NAME, "cryptography.io"), ] def test_public_bytes_der(self, backend): @@ -1484,11 +1484,11 @@ def test_public_bytes_der(self, backend): subject = request.subject assert isinstance(subject, x509.Name) assert list(subject) == [ - x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), - x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"), - x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"), - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"), - x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), + x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Texas"), + x509.NameAttribute(NameOID.LOCALITY_NAME, "Austin"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA"), + x509.NameAttribute(NameOID.COMMON_NAME, "cryptography.io"), ] def test_signature(self, backend): @@ -1649,14 +1649,14 @@ def test_build_cert(self, backend): .issuer_name( x509.Name( [ - x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), x509.NameAttribute( - NameOID.STATE_OR_PROVINCE_NAME, u"Texas" + NameOID.STATE_OR_PROVINCE_NAME, "Texas" ), - x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"), - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"), + x509.NameAttribute(NameOID.LOCALITY_NAME, "Austin"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA"), x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io" + NameOID.COMMON_NAME, "cryptography.io" ), ] ) @@ -1664,14 +1664,14 @@ def test_build_cert(self, backend): .subject_name( x509.Name( [ - x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), x509.NameAttribute( - NameOID.STATE_OR_PROVINCE_NAME, u"Texas" + NameOID.STATE_OR_PROVINCE_NAME, "Texas" ), - x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"), - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"), + x509.NameAttribute(NameOID.LOCALITY_NAME, "Austin"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA"), x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io" + NameOID.COMMON_NAME, "cryptography.io" ), ] ) @@ -1682,9 +1682,7 @@ def test_build_cert(self, backend): True, ) .add_extension( - x509.SubjectAlternativeName( - [x509.DNSName(u"cryptography.io")] - ), + x509.SubjectAlternativeName([x509.DNSName("cryptography.io")]), critical=False, ) .not_valid_before(not_valid_before) @@ -1705,7 +1703,7 @@ def test_build_cert(self, backend): ExtensionOID.SUBJECT_ALTERNATIVE_NAME ) assert list(subject_alternative_name.value) == [ - x509.DNSName(u"cryptography.io"), + x509.DNSName("cryptography.io"), ] def test_build_cert_private_type_encoding(self, backend): @@ -1717,13 +1715,13 @@ def test_build_cert_private_type_encoding(self, backend): [ x509.NameAttribute( NameOID.STATE_OR_PROVINCE_NAME, - u"Texas", + "Texas", _ASN1Type.PrintableString, ), - x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"), + x509.NameAttribute(NameOID.LOCALITY_NAME, "Austin"), x509.NameAttribute( NameOID.COMMON_NAME, - u"cryptography.io", + "cryptography.io", _ASN1Type.IA5String, ), ] @@ -1770,12 +1768,12 @@ def test_build_cert_printable_string_country_name(self, backend): .issuer_name( x509.Name( [ - x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), x509.NameAttribute( - NameOID.JURISDICTION_COUNTRY_NAME, u"US" + NameOID.JURISDICTION_COUNTRY_NAME, "US" ), x509.NameAttribute( - NameOID.STATE_OR_PROVINCE_NAME, u"Texas" + NameOID.STATE_OR_PROVINCE_NAME, "Texas" ), ] ) @@ -1783,12 +1781,12 @@ def test_build_cert_printable_string_country_name(self, backend): .subject_name( x509.Name( [ - x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), x509.NameAttribute( - NameOID.JURISDICTION_COUNTRY_NAME, u"US" + NameOID.JURISDICTION_COUNTRY_NAME, "US" ), x509.NameAttribute( - NameOID.STATE_OR_PROVINCE_NAME, u"Texas" + NameOID.STATE_OR_PROVINCE_NAME, "Texas" ), ] ) @@ -1833,10 +1831,10 @@ def test_checks_for_unsupported_extensions(self, backend): builder = ( x509.CertificateBuilder() .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(private_key.public_key()) .serial_number(777) @@ -1857,7 +1855,7 @@ def test_encode_nonstandard_aia(self, backend): [ x509.AccessDescription( x509.ObjectIdentifier("2.999.7"), - x509.UniformResourceIdentifier(u"http://example.com"), + x509.UniformResourceIdentifier("http://example.com"), ), ] ) @@ -1865,10 +1863,10 @@ def test_encode_nonstandard_aia(self, backend): builder = ( x509.CertificateBuilder() .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(private_key.public_key()) .serial_number(777) @@ -1888,7 +1886,7 @@ def test_encode_nonstandard_sia(self, backend): [ x509.AccessDescription( x509.ObjectIdentifier("2.999.7"), - x509.UniformResourceIdentifier(u"http://example.com"), + x509.UniformResourceIdentifier("http://example.com"), ), ] ) @@ -1896,10 +1894,10 @@ def test_encode_nonstandard_sia(self, backend): builder = ( x509.CertificateBuilder() .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(private_key.public_key()) .serial_number(777) @@ -1921,34 +1919,34 @@ def test_subject_dn_asn1_types(self, backend): name = x509.Name( [ - x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"), - x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), - x509.NameAttribute(NameOID.LOCALITY_NAME, u"value"), - x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"value"), - x509.NameAttribute(NameOID.STREET_ADDRESS, u"value"), - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"value"), - x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"value"), - x509.NameAttribute(NameOID.SERIAL_NUMBER, u"value"), - x509.NameAttribute(NameOID.SURNAME, u"value"), - x509.NameAttribute(NameOID.GIVEN_NAME, u"value"), - x509.NameAttribute(NameOID.TITLE, u"value"), - x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u"value"), - x509.NameAttribute(NameOID.X500_UNIQUE_IDENTIFIER, u"value"), - x509.NameAttribute(NameOID.DN_QUALIFIER, u"value"), - x509.NameAttribute(NameOID.PSEUDONYM, u"value"), - x509.NameAttribute(NameOID.USER_ID, u"value"), - x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"value"), - x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"value"), - x509.NameAttribute(NameOID.JURISDICTION_COUNTRY_NAME, u"US"), + x509.NameAttribute(NameOID.COMMON_NAME, "mysite.com"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), + x509.NameAttribute(NameOID.LOCALITY_NAME, "value"), + x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "value"), + x509.NameAttribute(NameOID.STREET_ADDRESS, "value"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "value"), + x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, "value"), + x509.NameAttribute(NameOID.SERIAL_NUMBER, "value"), + x509.NameAttribute(NameOID.SURNAME, "value"), + x509.NameAttribute(NameOID.GIVEN_NAME, "value"), + x509.NameAttribute(NameOID.TITLE, "value"), + x509.NameAttribute(NameOID.GENERATION_QUALIFIER, "value"), + x509.NameAttribute(NameOID.X500_UNIQUE_IDENTIFIER, "value"), + x509.NameAttribute(NameOID.DN_QUALIFIER, "value"), + x509.NameAttribute(NameOID.PSEUDONYM, "value"), + x509.NameAttribute(NameOID.USER_ID, "value"), + x509.NameAttribute(NameOID.DOMAIN_COMPONENT, "value"), + x509.NameAttribute(NameOID.EMAIL_ADDRESS, "value"), + x509.NameAttribute(NameOID.JURISDICTION_COUNTRY_NAME, "US"), x509.NameAttribute( - NameOID.JURISDICTION_LOCALITY_NAME, u"value" + NameOID.JURISDICTION_LOCALITY_NAME, "value" ), x509.NameAttribute( - NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME, u"value" + NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME, "value" ), - x509.NameAttribute(NameOID.BUSINESS_CATEGORY, u"value"), - x509.NameAttribute(NameOID.POSTAL_ADDRESS, u"value"), - x509.NameAttribute(NameOID.POSTAL_CODE, u"value"), + x509.NameAttribute(NameOID.BUSINESS_CATEGORY, "value"), + x509.NameAttribute(NameOID.POSTAL_ADDRESS, "value"), + x509.NameAttribute(NameOID.POSTAL_CODE, "value"), ] ) cert = ( @@ -1980,10 +1978,10 @@ def test_extreme_times(self, not_valid_before, not_valid_after, backend): builder = ( x509.CertificateBuilder() .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(private_key.public_key()) .serial_number(777) @@ -2005,7 +2003,7 @@ def test_no_subject_name(self, backend): x509.CertificateBuilder() .serial_number(777) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(subject_private_key.public_key()) .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1)) @@ -2022,7 +2020,7 @@ def test_no_issuer_name(self, backend): x509.CertificateBuilder() .serial_number(777) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(subject_private_key.public_key()) .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1)) @@ -2039,10 +2037,10 @@ def test_no_public_key(self, backend): x509.CertificateBuilder() .serial_number(777) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1)) .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30)) @@ -2058,10 +2056,10 @@ def test_no_not_valid_before(self, backend): x509.CertificateBuilder() .serial_number(777) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(subject_private_key.public_key()) .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30)) @@ -2077,10 +2075,10 @@ def test_no_not_valid_after(self, backend): x509.CertificateBuilder() .serial_number(777) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(subject_private_key.public_key()) .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1)) @@ -2095,10 +2093,10 @@ def test_no_serial_number(self, backend): builder = ( x509.CertificateBuilder() .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(subject_private_key.public_key()) .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1)) @@ -2117,7 +2115,7 @@ def test_issuer_name_must_be_a_name_type(self): builder.issuer_name(object) def test_issuer_name_may_only_be_set_once(self): - name = x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + name = x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) builder = x509.CertificateBuilder().issuer_name(name) with pytest.raises(ValueError): @@ -2133,7 +2131,7 @@ def test_subject_name_must_be_a_name_type(self): builder.subject_name(object) def test_subject_name_may_only_be_set_once(self): - name = x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + name = x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) builder = x509.CertificateBuilder().subject_name(name) with pytest.raises(ValueError): @@ -2194,10 +2192,10 @@ def test_minimal_serial_number(self, backend): x509.CertificateBuilder() .serial_number(1) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"RU")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "RU")]) ) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"RU")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "RU")]) ) .public_key(subject_private_key.public_key()) .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1)) @@ -2214,10 +2212,10 @@ def test_biggest_serial_number(self, backend): x509.CertificateBuilder() .serial_number((1 << 159) - 1) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"RU")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "RU")]) ) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"RU")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "RU")]) ) .public_key(subject_private_key.public_key()) .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1)) @@ -2247,10 +2245,10 @@ def test_aware_not_valid_after(self, backend): cert_builder = x509.CertificateBuilder().not_valid_after(time) cert_builder = ( cert_builder.subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .serial_number(1) .public_key(private_key.public_key()) @@ -2268,10 +2266,10 @@ def test_earliest_time(self, backend): cert_builder = ( x509.CertificateBuilder() .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .serial_number(1) .public_key(private_key.public_key()) @@ -2316,10 +2314,10 @@ def test_aware_not_valid_before(self, backend): cert_builder = x509.CertificateBuilder().not_valid_before(time) cert_builder = ( cert_builder.subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .serial_number(1) .public_key(private_key.public_key()) @@ -2375,10 +2373,10 @@ def test_sign_with_unsupported_hash(self, algorithm, backend): builder = x509.CertificateBuilder() builder = ( builder.subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .serial_number(1) .public_key(private_key.public_key()) @@ -2399,10 +2397,10 @@ def test_sign_with_unsupported_hash_ed25519(self, backend): builder = ( x509.CertificateBuilder() .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .serial_number(1) .public_key(private_key.public_key()) @@ -2423,10 +2421,10 @@ def test_sign_with_unsupported_hash_ed448(self, backend): builder = ( x509.CertificateBuilder() .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .serial_number(1) .public_key(private_key.public_key()) @@ -2448,10 +2446,10 @@ def test_sign_rsa_with_md5(self, backend): builder = x509.CertificateBuilder() builder = ( builder.subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .serial_number(1) .public_key(private_key.public_key()) @@ -2472,10 +2470,10 @@ def test_sign_dsa_with_md5(self, backend): builder = x509.CertificateBuilder() builder = ( builder.subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .serial_number(1) .public_key(private_key.public_key()) @@ -2497,10 +2495,10 @@ def test_sign_ec_with_md5(self, backend): builder = x509.CertificateBuilder() builder = ( builder.subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .serial_number(1) .public_key(private_key.public_key()) @@ -2523,10 +2521,10 @@ def test_build_cert_with_dsa_private_key(self, backend): x509.CertificateBuilder() .serial_number(777) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(subject_private_key.public_key()) .add_extension( @@ -2534,9 +2532,7 @@ def test_build_cert_with_dsa_private_key(self, backend): True, ) .add_extension( - x509.SubjectAlternativeName( - [x509.DNSName(u"cryptography.io")] - ), + x509.SubjectAlternativeName([x509.DNSName("cryptography.io")]), critical=False, ) .not_valid_before(not_valid_before) @@ -2557,7 +2553,7 @@ def test_build_cert_with_dsa_private_key(self, backend): ExtensionOID.SUBJECT_ALTERNATIVE_NAME ) assert list(subject_alternative_name.value) == [ - x509.DNSName(u"cryptography.io"), + x509.DNSName("cryptography.io"), ] @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) @@ -2574,10 +2570,10 @@ def test_build_cert_with_ec_private_key(self, backend): x509.CertificateBuilder() .serial_number(777) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(subject_private_key.public_key()) .add_extension( @@ -2585,9 +2581,7 @@ def test_build_cert_with_ec_private_key(self, backend): True, ) .add_extension( - x509.SubjectAlternativeName( - [x509.DNSName(u"cryptography.io")] - ), + x509.SubjectAlternativeName([x509.DNSName("cryptography.io")]), critical=False, ) .not_valid_before(not_valid_before) @@ -2608,7 +2602,7 @@ def test_build_cert_with_ec_private_key(self, backend): ExtensionOID.SUBJECT_ALTERNATIVE_NAME ) assert list(subject_alternative_name.value) == [ - x509.DNSName(u"cryptography.io"), + x509.DNSName("cryptography.io"), ] @pytest.mark.supported( @@ -2627,10 +2621,10 @@ def test_build_cert_with_ed25519(self, backend): x509.CertificateBuilder() .serial_number(777) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(subject_private_key.public_key()) .add_extension( @@ -2638,9 +2632,7 @@ def test_build_cert_with_ed25519(self, backend): True, ) .add_extension( - x509.SubjectAlternativeName( - [x509.DNSName(u"cryptography.io")] - ), + x509.SubjectAlternativeName([x509.DNSName("cryptography.io")]), critical=False, ) .not_valid_before(not_valid_before) @@ -2666,7 +2658,7 @@ def test_build_cert_with_ed25519(self, backend): ExtensionOID.SUBJECT_ALTERNATIVE_NAME ) assert list(subject_alternative_name.value) == [ - x509.DNSName(u"cryptography.io"), + x509.DNSName("cryptography.io"), ] @pytest.mark.supported( @@ -2686,10 +2678,10 @@ def test_build_cert_with_public_ed25519_rsa_sig(self, backend): x509.CertificateBuilder() .serial_number(777) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(subject_private_key.public_key()) .not_valid_before(not_valid_before) @@ -2725,10 +2717,10 @@ def test_build_cert_with_ed448(self, backend): x509.CertificateBuilder() .serial_number(777) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(subject_private_key.public_key()) .add_extension( @@ -2736,9 +2728,7 @@ def test_build_cert_with_ed448(self, backend): True, ) .add_extension( - x509.SubjectAlternativeName( - [x509.DNSName(u"cryptography.io")] - ), + x509.SubjectAlternativeName([x509.DNSName("cryptography.io")]), critical=False, ) .not_valid_before(not_valid_before) @@ -2764,7 +2754,7 @@ def test_build_cert_with_ed448(self, backend): ExtensionOID.SUBJECT_ALTERNATIVE_NAME ) assert list(subject_alternative_name.value) == [ - x509.DNSName(u"cryptography.io"), + x509.DNSName("cryptography.io"), ] @pytest.mark.supported( @@ -2784,10 +2774,10 @@ def test_build_cert_with_public_ed448_rsa_sig(self, backend): x509.CertificateBuilder() .serial_number(777) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(subject_private_key.public_key()) .not_valid_before(not_valid_before) @@ -2820,10 +2810,10 @@ def test_build_cert_with_rsa_key_too_small(self, backend): x509.CertificateBuilder() .serial_number(777) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(subject_private_key.public_key()) .not_valid_before(not_valid_before) @@ -2842,12 +2832,12 @@ def test_build_cert_with_rsa_key_too_small(self, backend): [ # These examples exist to verify compatibility with # certificates that have utf8 encoded data in the ia5string - x509.DNSName._init_without_validation(u"a\xedt\xe1s.test"), + x509.DNSName._init_without_validation("a\xedt\xe1s.test"), x509.RFC822Name._init_without_validation( - u"test@a\xedt\xe1s.test" + "test@a\xedt\xe1s.test" ), x509.UniformResourceIdentifier._init_without_validation( - u"http://a\xedt\xe1s.test" + "http://a\xedt\xe1s.test" ), ] ), @@ -2855,7 +2845,7 @@ def test_build_cert_with_rsa_key_too_small(self, backend): [ x509.PolicyInformation( x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"), - [u"http://other.com/cps"], + ["http://other.com/cps"], ) ] ), @@ -2872,11 +2862,11 @@ def test_build_cert_with_rsa_key_too_small(self, backend): x509.PolicyInformation( x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"), [ - u"http://example.com/cps", - u"http://other.com/cps", + "http://example.com/cps", + "http://other.com/cps", x509.UserNotice( - x509.NoticeReference(u"my org", [1, 2, 3, 4]), - u"thing", + x509.NoticeReference("my org", [1, 2, 3, 4]), + "thing", ), ], ) @@ -2887,12 +2877,12 @@ def test_build_cert_with_rsa_key_too_small(self, backend): x509.PolicyInformation( x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"), [ - u"http://example.com/cps", + "http://example.com/cps", x509.UserNotice( x509.NoticeReference( - u"UTF8\u2122'", [1, 2, 3, 4] + "UTF8\u2122'", [1, 2, 3, 4] ), - u"We heart UTF8!\u2122", + "We heart UTF8!\u2122", ), ], ) @@ -2902,7 +2892,7 @@ def test_build_cert_with_rsa_key_too_small(self, backend): [ x509.PolicyInformation( x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"), - [x509.UserNotice(None, u"thing")], + [x509.UserNotice(None, "thing")], ) ] ), @@ -2912,7 +2902,7 @@ def test_build_cert_with_rsa_key_too_small(self, backend): x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"), [ x509.UserNotice( - x509.NoticeReference(u"my org", [1, 2, 3, 4]), + x509.NoticeReference("my org", [1, 2, 3, 4]), None, ) ], @@ -2921,8 +2911,8 @@ def test_build_cert_with_rsa_key_too_small(self, backend): ), x509.IssuerAlternativeName( [ - x509.DNSName(u"myissuer"), - x509.RFC822Name(u"email@domain.com"), + x509.DNSName("myissuer"), + x509.RFC822Name("email@domain.com"), ] ), x509.ExtendedKeyUsage( @@ -2943,29 +2933,29 @@ def test_build_cert_with_rsa_key_too_small(self, backend): ), x509.NameConstraints( permitted_subtrees=[ - x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.0/24")), - x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.0/29")), - x509.IPAddress(ipaddress.IPv4Network(u"127.0.0.1/32")), - x509.IPAddress(ipaddress.IPv4Network(u"8.0.0.0/8")), - x509.IPAddress(ipaddress.IPv4Network(u"0.0.0.0/0")), + x509.IPAddress(ipaddress.IPv4Network("192.168.0.0/24")), + x509.IPAddress(ipaddress.IPv4Network("192.168.0.0/29")), + x509.IPAddress(ipaddress.IPv4Network("127.0.0.1/32")), + x509.IPAddress(ipaddress.IPv4Network("8.0.0.0/8")), + x509.IPAddress(ipaddress.IPv4Network("0.0.0.0/0")), x509.IPAddress( - ipaddress.IPv6Network(u"FF:0:0:0:0:0:0:0/96") + ipaddress.IPv6Network("FF:0:0:0:0:0:0:0/96") ), x509.IPAddress( - ipaddress.IPv6Network(u"FF:FF:0:0:0:0:0:0/128") + ipaddress.IPv6Network("FF:FF:0:0:0:0:0:0/128") ), ], - excluded_subtrees=[x509.DNSName(u"name.local")], + excluded_subtrees=[x509.DNSName("name.local")], ), x509.NameConstraints( permitted_subtrees=[ - x509.IPAddress(ipaddress.IPv4Network(u"0.0.0.0/0")), + x509.IPAddress(ipaddress.IPv4Network("0.0.0.0/0")), ], excluded_subtrees=None, ), x509.NameConstraints( permitted_subtrees=None, - excluded_subtrees=[x509.DNSName(u"name.local")], + excluded_subtrees=[x509.DNSName("name.local")], ), x509.PolicyConstraints( require_explicit_policy=None, inhibit_policy_mapping=1 @@ -2984,7 +2974,7 @@ def test_build_cert_with_rsa_key_too_small(self, backend): [ x509.NameAttribute( NameOID.COMMON_NAME, - u"indirect CRL for indirectCRL CA3", + "indirect CRL for indirectCRL CA3", ), ] ), @@ -2994,15 +2984,15 @@ def test_build_cert_with_rsa_key_too_small(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COUNTRY_NAME, u"US" + NameOID.COUNTRY_NAME, "US" ), x509.NameAttribute( NameOID.ORGANIZATION_NAME, - u"Test Certificates 2011", + "Test Certificates 2011", ), x509.NameAttribute( NameOID.ORGANIZATIONAL_UNIT_NAME, - u"indirectCRL CA3 cRLIssuer", + "indirectCRL CA3 cRLIssuer", ), ] ) @@ -3019,7 +3009,7 @@ def test_build_cert_with_rsa_key_too_small(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COUNTRY_NAME, u"US" + NameOID.COUNTRY_NAME, "US" ), ] ) @@ -3033,7 +3023,7 @@ def test_build_cert_with_rsa_key_too_small(self, backend): [ x509.NameAttribute( NameOID.ORGANIZATION_NAME, - u"cryptography Testing", + "cryptography Testing", ), ] ) @@ -3047,10 +3037,10 @@ def test_build_cert_with_rsa_key_too_small(self, backend): x509.DistributionPoint( full_name=[ x509.UniformResourceIdentifier( - u"http://myhost.com/myca.crl" + "http://myhost.com/myca.crl" ), x509.UniformResourceIdentifier( - u"http://backup.myhost.com/myca.crl" + "http://backup.myhost.com/myca.crl" ), ], relative_name=None, @@ -3065,11 +3055,11 @@ def test_build_cert_with_rsa_key_too_small(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COUNTRY_NAME, u"US" + NameOID.COUNTRY_NAME, "US" ), x509.NameAttribute( NameOID.COMMON_NAME, - u"cryptography CA", + "cryptography CA", ), ] ) @@ -3083,7 +3073,7 @@ def test_build_cert_with_rsa_key_too_small(self, backend): x509.DistributionPoint( full_name=[ x509.UniformResourceIdentifier( - u"http://domain.com/some.crl" + "http://domain.com/some.crl" ) ], relative_name=None, @@ -3115,7 +3105,7 @@ def test_build_cert_with_rsa_key_too_small(self, backend): [ x509.NameAttribute( NameOID.COMMON_NAME, - u"cryptography CA", + "cryptography CA", ), ] ) @@ -3129,7 +3119,7 @@ def test_build_cert_with_rsa_key_too_small(self, backend): x509.DistributionPoint( full_name=[ x509.UniformResourceIdentifier( - u"http://domain.com/some.crl" + "http://domain.com/some.crl" ) ], relative_name=None, @@ -3143,7 +3133,7 @@ def test_build_cert_with_rsa_key_too_small(self, backend): x509.DistributionPoint( full_name=[ x509.UniformResourceIdentifier( - u"http://domain.com/some.crl" + "http://domain.com/some.crl" ) ], relative_name=None, @@ -3171,7 +3161,7 @@ def test_build_cert_with_rsa_key_too_small(self, backend): [ x509.NameAttribute( NameOID.COMMON_NAME, - u"indirect CRL for indirectCRL CA3", + "indirect CRL for indirectCRL CA3", ), ] ), @@ -3188,11 +3178,9 @@ def test_build_cert_with_rsa_key_too_small(self, backend): [ x509.NameAttribute( NameOID.COMMON_NAME, - u"indirect CRL for indirectCRL CA3", - ), - x509.NameAttribute( - NameOID.COUNTRY_NAME, u"US" + "indirect CRL for indirectCRL CA3", ), + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), ] ), reasons=None, @@ -3212,10 +3200,10 @@ def test_ext(self, add_ext, backend): cert = ( x509.CertificateBuilder() .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .not_valid_before(not_valid_before) .not_valid_after(not_valid_after) @@ -3241,10 +3229,10 @@ def test_key_usage(self, backend): cert = ( x509.CertificateBuilder() .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .not_valid_before(not_valid_before) .not_valid_after(not_valid_after) @@ -3290,7 +3278,7 @@ def test_build_ca_request_with_path_length_none(self, backend): x509.CertificateSigningRequestBuilder() .subject_name( x509.Name( - [x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")] + [x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA")] ) ) .add_extension( @@ -3326,10 +3314,10 @@ def test_unrecognized_extension(self, backend, unrecognized): cert = ( x509.CertificateBuilder() .subject_name( - x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, "US")]) ) .issuer_name( - x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, "US")]) ) .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1)) .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30)) @@ -3364,7 +3352,7 @@ def test_sign_invalid_hash_algorithm(self, backend): def test_request_with_unsupported_hash_ed25519(self, backend): private_key = ed25519.Ed25519PrivateKey.generate() builder = x509.CertificateSigningRequestBuilder().subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) with pytest.raises(ValueError): @@ -3378,7 +3366,7 @@ def test_request_with_unsupported_hash_ed25519(self, backend): def test_request_with_unsupported_hash_ed448(self, backend): private_key = ed448.Ed448PrivateKey.generate() builder = x509.CertificateSigningRequestBuilder().subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) with pytest.raises(ValueError): @@ -3393,7 +3381,7 @@ def test_sign_rsa_with_md5(self, backend): private_key = RSA_KEY_2048.private_key(backend) builder = x509.CertificateSigningRequestBuilder().subject_name( - x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")]) + x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA")]) ) request = builder.sign(private_key, hashes.MD5(), backend) assert isinstance(request.signature_hash_algorithm, hashes.MD5) @@ -3406,7 +3394,7 @@ def test_sign_rsa_with_md5(self, backend): def test_sign_dsa_with_md5(self, backend): private_key = DSA_KEY_2048.private_key(backend) builder = x509.CertificateSigningRequestBuilder().subject_name( - x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")]) + x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA")]) ) with pytest.raises(ValueError): builder.sign(private_key, hashes.MD5(), backend) @@ -3420,7 +3408,7 @@ def test_sign_ec_with_md5(self, backend): _skip_curve_unsupported(backend, ec.SECP256R1()) private_key = EC_KEY_SECP256R1.private_key(backend) builder = x509.CertificateSigningRequestBuilder().subject_name( - x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")]) + x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA")]) ) with pytest.raises(ValueError): builder.sign(private_key, hashes.MD5(), backend) @@ -3441,7 +3429,7 @@ def test_build_ca_request_with_rsa(self, backend): x509.CertificateSigningRequestBuilder() .subject_name( x509.Name( - [x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")] + [x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA")] ) ) .add_extension( @@ -3456,7 +3444,7 @@ def test_build_ca_request_with_rsa(self, backend): subject = request.subject assert isinstance(subject, x509.Name) assert list(subject) == [ - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA"), ] basic_constraints = request.extensions.get_extension_for_oid( ExtensionOID.BASIC_CONSTRAINTS @@ -3474,7 +3462,7 @@ def test_build_ca_request_with_unicode(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.ORGANIZATION_NAME, u"PyCA\U0001f37a" + NameOID.ORGANIZATION_NAME, "PyCA\U0001f37a" ), ] ) @@ -3491,7 +3479,7 @@ def test_build_ca_request_with_unicode(self, backend): subject = loaded_request.subject assert isinstance(subject, x509.Name) assert list(subject) == [ - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA\U0001f37a"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA\U0001f37a"), ] @pytest.mark.requires_backend_interface(interface=RSABackend) @@ -3503,49 +3491,45 @@ def test_subject_dn_asn1_types(self, backend): .subject_name( x509.Name( [ - x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"), - x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), - x509.NameAttribute(NameOID.LOCALITY_NAME, u"value"), + x509.NameAttribute(NameOID.COMMON_NAME, "mysite.com"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), + x509.NameAttribute(NameOID.LOCALITY_NAME, "value"), x509.NameAttribute( - NameOID.STATE_OR_PROVINCE_NAME, u"value" + NameOID.STATE_OR_PROVINCE_NAME, "value" ), - x509.NameAttribute(NameOID.STREET_ADDRESS, u"value"), + x509.NameAttribute(NameOID.STREET_ADDRESS, "value"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "value"), x509.NameAttribute( - NameOID.ORGANIZATION_NAME, u"value" + NameOID.ORGANIZATIONAL_UNIT_NAME, "value" ), + x509.NameAttribute(NameOID.SERIAL_NUMBER, "value"), + x509.NameAttribute(NameOID.SURNAME, "value"), + x509.NameAttribute(NameOID.GIVEN_NAME, "value"), + x509.NameAttribute(NameOID.TITLE, "value"), x509.NameAttribute( - NameOID.ORGANIZATIONAL_UNIT_NAME, u"value" + NameOID.GENERATION_QUALIFIER, "value" ), - x509.NameAttribute(NameOID.SERIAL_NUMBER, u"value"), - x509.NameAttribute(NameOID.SURNAME, u"value"), - x509.NameAttribute(NameOID.GIVEN_NAME, u"value"), - x509.NameAttribute(NameOID.TITLE, u"value"), x509.NameAttribute( - NameOID.GENERATION_QUALIFIER, u"value" + NameOID.X500_UNIQUE_IDENTIFIER, "value" ), + x509.NameAttribute(NameOID.DN_QUALIFIER, "value"), + x509.NameAttribute(NameOID.PSEUDONYM, "value"), + x509.NameAttribute(NameOID.USER_ID, "value"), + x509.NameAttribute(NameOID.DOMAIN_COMPONENT, "value"), + x509.NameAttribute(NameOID.EMAIL_ADDRESS, "value"), x509.NameAttribute( - NameOID.X500_UNIQUE_IDENTIFIER, u"value" + NameOID.JURISDICTION_COUNTRY_NAME, "US" ), - x509.NameAttribute(NameOID.DN_QUALIFIER, u"value"), - x509.NameAttribute(NameOID.PSEUDONYM, u"value"), - x509.NameAttribute(NameOID.USER_ID, u"value"), - x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"value"), - x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"value"), x509.NameAttribute( - NameOID.JURISDICTION_COUNTRY_NAME, u"US" - ), - x509.NameAttribute( - NameOID.JURISDICTION_LOCALITY_NAME, u"value" + NameOID.JURISDICTION_LOCALITY_NAME, "value" ), x509.NameAttribute( NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME, - u"value", - ), - x509.NameAttribute( - NameOID.BUSINESS_CATEGORY, u"value" + "value", ), - x509.NameAttribute(NameOID.POSTAL_ADDRESS, u"value"), - x509.NameAttribute(NameOID.POSTAL_CODE, u"value"), + x509.NameAttribute(NameOID.BUSINESS_CATEGORY, "value"), + x509.NameAttribute(NameOID.POSTAL_ADDRESS, "value"), + x509.NameAttribute(NameOID.POSTAL_CODE, "value"), ] ) ) @@ -3564,13 +3548,13 @@ def test_build_ca_request_with_multivalue_rdns(self, backend): [ x509.RelativeDistinguishedName( [ - x509.NameAttribute(NameOID.TITLE, u"Test"), - x509.NameAttribute(NameOID.COMMON_NAME, u"Multivalue"), - x509.NameAttribute(NameOID.SURNAME, u"RDNs"), + x509.NameAttribute(NameOID.TITLE, "Test"), + x509.NameAttribute(NameOID.COMMON_NAME, "Multivalue"), + x509.NameAttribute(NameOID.SURNAME, "RDNs"), ] ), x509.RelativeDistinguishedName( - [x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")] + [x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA")] ), ] ) @@ -3594,7 +3578,7 @@ def test_build_nonca_request_with_rsa(self, backend): request = ( x509.CertificateSigningRequestBuilder() .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .add_extension( x509.BasicConstraints(ca=False, path_length=None), @@ -3609,7 +3593,7 @@ def test_build_nonca_request_with_rsa(self, backend): subject = request.subject assert isinstance(subject, x509.Name) assert list(subject) == [ - x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), ] basic_constraints = request.extensions.get_extension_for_oid( ExtensionOID.BASIC_CONSTRAINTS @@ -3628,7 +3612,7 @@ def test_build_ca_request_with_ec(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.STATE_OR_PROVINCE_NAME, u"Texas" + NameOID.STATE_OR_PROVINCE_NAME, "Texas" ), ] ) @@ -3645,7 +3629,7 @@ def test_build_ca_request_with_ec(self, backend): subject = request.subject assert isinstance(subject, x509.Name) assert list(subject) == [ - x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"), + x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Texas"), ] basic_constraints = request.extensions.get_extension_for_oid( ExtensionOID.BASIC_CONSTRAINTS @@ -3667,7 +3651,7 @@ def test_build_ca_request_with_ed25519(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.STATE_OR_PROVINCE_NAME, u"Texas" + NameOID.STATE_OR_PROVINCE_NAME, "Texas" ), ] ) @@ -3684,7 +3668,7 @@ def test_build_ca_request_with_ed25519(self, backend): subject = request.subject assert isinstance(subject, x509.Name) assert list(subject) == [ - x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"), + x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Texas"), ] basic_constraints = request.extensions.get_extension_for_oid( ExtensionOID.BASIC_CONSTRAINTS @@ -3706,7 +3690,7 @@ def test_build_ca_request_with_ed448(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.STATE_OR_PROVINCE_NAME, u"Texas" + NameOID.STATE_OR_PROVINCE_NAME, "Texas" ), ] ) @@ -3723,7 +3707,7 @@ def test_build_ca_request_with_ed448(self, backend): subject = request.subject assert isinstance(subject, x509.Name) assert list(subject) == [ - x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"), + x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Texas"), ] basic_constraints = request.extensions.get_extension_for_oid( ExtensionOID.BASIC_CONSTRAINTS @@ -3738,7 +3722,7 @@ def test_build_ca_request_with_dsa(self, backend): request = ( x509.CertificateSigningRequestBuilder() .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .add_extension( x509.BasicConstraints(ca=True, path_length=2), critical=True @@ -3752,7 +3736,7 @@ def test_build_ca_request_with_dsa(self, backend): subject = request.subject assert isinstance(subject, x509.Name) assert list(subject) == [ - x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), ] basic_constraints = request.extensions.get_extension_for_oid( ExtensionOID.BASIC_CONSTRAINTS @@ -3787,12 +3771,10 @@ def test_add_unsupported_extension(self, backend): builder = x509.CertificateSigningRequestBuilder() builder = ( builder.subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .add_extension( - x509.SubjectAlternativeName( - [x509.DNSName(u"cryptography.io")] - ), + x509.SubjectAlternativeName([x509.DNSName("cryptography.io")]), critical=False, ) .add_extension(DummyExtension(), False) @@ -3805,7 +3787,7 @@ def test_key_usage(self, backend): builder = x509.CertificateSigningRequestBuilder() request = ( builder.subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .add_extension( x509.KeyUsage( @@ -3843,7 +3825,7 @@ def test_key_usage_key_agreement_bit(self, backend): builder = x509.CertificateSigningRequestBuilder() request = ( builder.subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .add_extension( x509.KeyUsage( @@ -3881,12 +3863,10 @@ def test_add_two_extensions(self, backend): builder = x509.CertificateSigningRequestBuilder() request = ( builder.subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .add_extension( - x509.SubjectAlternativeName( - [x509.DNSName(u"cryptography.io")] - ), + x509.SubjectAlternativeName([x509.DNSName("cryptography.io")]), critical=False, ) .add_extension( @@ -3906,7 +3886,7 @@ def test_add_two_extensions(self, backend): ext = request.extensions.get_extension_for_oid( ExtensionOID.SUBJECT_ALTERNATIVE_NAME ) - assert list(ext.value) == [x509.DNSName(u"cryptography.io")] + assert list(ext.value) == [x509.DNSName("cryptography.io")] @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) def test_add_attributes(self, backend): @@ -3922,7 +3902,7 @@ def test_add_attributes(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.STATE_OR_PROVINCE_NAME, u"Texas" + NameOID.STATE_OR_PROVINCE_NAME, "Texas" ), ] ) @@ -3976,11 +3956,11 @@ def test_duplicate_attribute(self, backend): def test_set_subject_twice(self): builder = x509.CertificateSigningRequestBuilder() builder = builder.subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) with pytest.raises(ValueError): builder.subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) def test_subject_alt_names(self, backend): @@ -3988,34 +3968,34 @@ def test_subject_alt_names(self, backend): san = x509.SubjectAlternativeName( [ - x509.DNSName(u"example.com"), - x509.DNSName(u"*.example.com"), + x509.DNSName("example.com"), + x509.DNSName("*.example.com"), x509.RegisteredID(x509.ObjectIdentifier("1.2.3.4.5.6.7")), x509.DirectoryName( x509.Name( [ - x509.NameAttribute(NameOID.COMMON_NAME, u"PyCA"), + x509.NameAttribute(NameOID.COMMON_NAME, "PyCA"), x509.NameAttribute( NameOID.ORGANIZATION_NAME, - u"We heart UTF8!\u2122", + "We heart UTF8!\u2122", ), ] ) ), - x509.IPAddress(ipaddress.ip_address(u"127.0.0.1")), - x509.IPAddress(ipaddress.ip_address(u"ff::")), + x509.IPAddress(ipaddress.ip_address("127.0.0.1")), + x509.IPAddress(ipaddress.ip_address("ff::")), x509.OtherName( type_id=x509.ObjectIdentifier("1.2.3.3.3.3"), value=b"0\x03\x02\x01\x05", ), - x509.RFC822Name(u"test@example.com"), - x509.RFC822Name(u"email"), - x509.RFC822Name(u"email@xn--eml-vla4c.com"), + x509.RFC822Name("test@example.com"), + x509.RFC822Name("email"), + x509.RFC822Name("email@xn--eml-vla4c.com"), x509.UniformResourceIdentifier( - u"https://xn--80ato2c.cryptography" + "https://xn--80ato2c.cryptography" ), x509.UniformResourceIdentifier( - u"gopher://cryptography:70/some/path" + "gopher://cryptography:70/some/path" ), ] ) @@ -4023,7 +4003,7 @@ def test_subject_alt_names(self, backend): csr = ( x509.CertificateSigningRequestBuilder() .subject_name( - x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"SAN")]) + x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, "SAN")]) ) .add_extension( san, @@ -4046,7 +4026,7 @@ def test_invalid_asn1_othername(self, backend): builder = ( x509.CertificateSigningRequestBuilder() .subject_name( - x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"SAN")]) + x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, "SAN")]) ) .add_extension( x509.SubjectAlternativeName( @@ -4069,7 +4049,7 @@ def test_subject_alt_name_unsupported_general_name(self, backend): builder = ( x509.CertificateSigningRequestBuilder() .subject_name( - x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"SAN")]) + x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, "SAN")]) ) .add_extension( x509.SubjectAlternativeName([FakeGeneralName("")]), @@ -4092,7 +4072,7 @@ def test_extended_key_usage(self, backend): builder = x509.CertificateSigningRequestBuilder() request = ( builder.subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .add_extension(eku, critical=False) .sign(private_key, hashes.SHA256(), backend) @@ -4109,7 +4089,7 @@ def test_rsa_key_too_small(self, backend): private_key = RSA_KEY_512.private_key(backend) builder = x509.CertificateSigningRequestBuilder() builder = builder.subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) with pytest.raises(ValueError): @@ -4128,13 +4108,11 @@ def test_build_cert_with_aia(self, backend): [ x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp.domain.com"), + x509.UniformResourceIdentifier("http://ocsp.domain.com"), ), x509.AccessDescription( AuthorityInformationAccessOID.CA_ISSUERS, - x509.UniformResourceIdentifier( - u"http://domain.com/ca.crt" - ), + x509.UniformResourceIdentifier("http://domain.com/ca.crt"), ), ] ) @@ -4143,10 +4121,10 @@ def test_build_cert_with_aia(self, backend): x509.CertificateBuilder() .serial_number(777) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(subject_private_key.public_key()) .add_extension(aia, critical=False) @@ -4174,7 +4152,7 @@ def test_build_cert_with_sia(self, backend): [ x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca.domain.com"), + x509.UniformResourceIdentifier("http://ca.domain.com"), ), ] ) @@ -4183,10 +4161,10 @@ def test_build_cert_with_sia(self, backend): x509.CertificateBuilder() .serial_number(777) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(subject_private_key.public_key()) .add_extension(sia, critical=False) @@ -4218,10 +4196,10 @@ def test_build_cert_with_ski(self, backend): x509.CertificateBuilder() .serial_number(777) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(subject_private_key.public_key()) .add_extension(ski, critical=False) @@ -4253,10 +4231,10 @@ def test_build_cert_with_ski(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.ORGANIZATION_NAME, u"PyCA" + NameOID.ORGANIZATION_NAME, "PyCA" ), x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography CA" + NameOID.COMMON_NAME, "cryptography CA" ), ] ) @@ -4271,10 +4249,10 @@ def test_build_cert_with_ski(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.ORGANIZATION_NAME, u"PyCA" + NameOID.ORGANIZATION_NAME, "PyCA" ), x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography CA" + NameOID.COMMON_NAME, "cryptography CA" ), ] ) @@ -4297,10 +4275,10 @@ def test_build_cert_with_aki(self, aki, backend): x509.CertificateBuilder() .serial_number(777) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(subject_private_key.public_key()) .add_extension(aki, critical=False) @@ -4326,10 +4304,10 @@ def test_ocsp_nocheck(self, backend): x509.CertificateBuilder() .serial_number(777) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(subject_private_key.public_key()) .add_extension(x509.OCSPNoCheck(), critical=False) @@ -4491,11 +4469,11 @@ def test_load_dsa_request(self, path, loader_func, backend): subject = request.subject assert isinstance(subject, x509.Name) assert list(subject) == [ - x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"), - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"), - x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), - x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"), - x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"), + x509.NameAttribute(NameOID.COMMON_NAME, "cryptography.io"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), + x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Texas"), + x509.NameAttribute(NameOID.LOCALITY_NAME, "Austin"), ] def test_signature(self, backend): @@ -4657,11 +4635,11 @@ def test_load_ecdsa_certificate_request(self, path, loader_func, backend): subject = request.subject assert isinstance(subject, x509.Name) assert list(subject) == [ - x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"), - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"), - x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), - x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"), - x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"), + x509.NameAttribute(NameOID.COMMON_NAME, "cryptography.io"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), + x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Texas"), + x509.NameAttribute(NameOID.LOCALITY_NAME, "Austin"), ] def test_signature(self, backend): @@ -4756,18 +4734,18 @@ class TestNameAttribute(object): def test_default_types(self): for oid, asn1_type in TestNameAttribute.EXPECTED_TYPES: - na = x509.NameAttribute(oid, u"US") + na = x509.NameAttribute(oid, "US") assert na._type == asn1_type def test_alternate_type(self): na2 = x509.NameAttribute( - NameOID.COMMON_NAME, u"common", _ASN1Type.IA5String + NameOID.COMMON_NAME, "common", _ASN1Type.IA5String ) assert na2._type == _ASN1Type.IA5String def test_init_bad_oid(self): with pytest.raises(TypeError): - x509.NameAttribute(None, u"value") + x509.NameAttribute(None, "value") def test_init_bad_value(self): with pytest.raises(TypeError): @@ -4779,35 +4757,35 @@ def test_init_none_value(self): def test_init_bad_country_code_value(self): with pytest.raises(ValueError): - x509.NameAttribute(NameOID.COUNTRY_NAME, u"United States") + x509.NameAttribute(NameOID.COUNTRY_NAME, "United States") # unicode string of length 2, but > 2 bytes with pytest.raises(ValueError): - x509.NameAttribute(NameOID.COUNTRY_NAME, u"\U0001F37A\U0001F37A") + x509.NameAttribute(NameOID.COUNTRY_NAME, "\U0001F37A\U0001F37A") def test_invalid_type(self): with pytest.raises(TypeError): - x509.NameAttribute(NameOID.COMMON_NAME, u"common", "notanenum") + x509.NameAttribute(NameOID.COMMON_NAME, "common", "notanenum") def test_eq(self): assert x509.NameAttribute( - x509.ObjectIdentifier("2.999.1"), u"value" - ) == x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value") + x509.ObjectIdentifier("2.999.1"), "value" + ) == x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value") def test_ne(self): assert x509.NameAttribute( - x509.ObjectIdentifier("2.5.4.3"), u"value" - ) != x509.NameAttribute(x509.ObjectIdentifier("2.5.4.5"), u"value") + x509.ObjectIdentifier("2.5.4.3"), "value" + ) != x509.NameAttribute(x509.ObjectIdentifier("2.5.4.5"), "value") assert x509.NameAttribute( - x509.ObjectIdentifier("2.999.1"), u"value" - ) != x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value2") + x509.ObjectIdentifier("2.999.1"), "value" + ) != x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value2") assert ( - x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value") + x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), "value") != object() ) def test_repr(self): - na = x509.NameAttribute(x509.ObjectIdentifier("2.5.4.3"), u"value") + na = x509.NameAttribute(x509.ObjectIdentifier("2.5.4.3"), "value") assert repr(na) == ( ", value='value')>" @@ -4815,19 +4793,19 @@ def test_repr(self): def test_distinugished_name(self): # Escaping - na = x509.NameAttribute(NameOID.COMMON_NAME, u'James "Jim" Smith, III') + na = x509.NameAttribute(NameOID.COMMON_NAME, 'James "Jim" Smith, III') assert na.rfc4514_string() == r"CN=James \"Jim\" Smith\, III" - na = x509.NameAttribute(NameOID.USER_ID, u"# escape+,;\0this ") + na = x509.NameAttribute(NameOID.USER_ID, "# escape+,;\0this ") assert na.rfc4514_string() == r"UID=\# escape\+\,\;\00this\ " # Nonstandard attribute OID - na = x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"somebody@example.com") + na = x509.NameAttribute(NameOID.EMAIL_ADDRESS, "somebody@example.com") assert ( na.rfc4514_string() == "1.2.840.113549.1.9.1=somebody@example.com" ) def test_empty_value(self): - na = x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"") + na = x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "") assert na.rfc4514_string() == r"ST=" @@ -4845,10 +4823,10 @@ def test_init_duplicate_attribute(self): x509.RelativeDistinguishedName( [ x509.NameAttribute( - x509.ObjectIdentifier("2.999.1"), u"val1" + x509.ObjectIdentifier("2.999.1"), "val1" ), x509.NameAttribute( - x509.ObjectIdentifier("2.999.1"), u"val1" + x509.ObjectIdentifier("2.999.1"), "val1" ), ] ) @@ -4856,32 +4834,20 @@ def test_init_duplicate_attribute(self): def test_hash(self): rdn1 = x509.RelativeDistinguishedName( [ - x509.NameAttribute( - x509.ObjectIdentifier("2.999.1"), u"value1" - ), - x509.NameAttribute( - x509.ObjectIdentifier("2.999.2"), u"value2" - ), + x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value1"), + x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), "value2"), ] ) rdn2 = x509.RelativeDistinguishedName( [ - x509.NameAttribute( - x509.ObjectIdentifier("2.999.2"), u"value2" - ), - x509.NameAttribute( - x509.ObjectIdentifier("2.999.1"), u"value1" - ), + x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), "value2"), + x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value1"), ] ) rdn3 = x509.RelativeDistinguishedName( [ - x509.NameAttribute( - x509.ObjectIdentifier("2.999.1"), u"value1" - ), - x509.NameAttribute( - x509.ObjectIdentifier("2.999.2"), u"value3" - ), + x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value1"), + x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), "value3"), ] ) assert hash(rdn1) == hash(rdn2) @@ -4890,22 +4856,14 @@ def test_hash(self): def test_eq(self): rdn1 = x509.RelativeDistinguishedName( [ - x509.NameAttribute( - x509.ObjectIdentifier("2.999.1"), u"value1" - ), - x509.NameAttribute( - x509.ObjectIdentifier("2.999.2"), u"value2" - ), + x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value1"), + x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), "value2"), ] ) rdn2 = x509.RelativeDistinguishedName( [ - x509.NameAttribute( - x509.ObjectIdentifier("2.999.2"), u"value2" - ), - x509.NameAttribute( - x509.ObjectIdentifier("2.999.1"), u"value1" - ), + x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), "value2"), + x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value1"), ] ) assert rdn1 == rdn2 @@ -4913,22 +4871,14 @@ def test_eq(self): def test_ne(self): rdn1 = x509.RelativeDistinguishedName( [ - x509.NameAttribute( - x509.ObjectIdentifier("2.999.1"), u"value1" - ), - x509.NameAttribute( - x509.ObjectIdentifier("2.999.2"), u"value2" - ), + x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value1"), + x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), "value2"), ] ) rdn2 = x509.RelativeDistinguishedName( [ - x509.NameAttribute( - x509.ObjectIdentifier("2.999.1"), u"value1" - ), - x509.NameAttribute( - x509.ObjectIdentifier("2.999.2"), u"value3" - ), + x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value1"), + x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), "value3"), ] ) assert rdn1 != rdn2 @@ -4937,9 +4887,9 @@ def test_ne(self): def test_iter_input(self): # Order must be preserved too attrs = [ - x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1"), - x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value2"), - x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value3"), + x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value1"), + x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value2"), + x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value3"), ] rdn = x509.RelativeDistinguishedName(iter(attrs)) assert list(rdn) == attrs @@ -4947,7 +4897,7 @@ def test_iter_input(self): def test_get_attributes_for_oid(self): oid = x509.ObjectIdentifier("2.999.1") - attr = x509.NameAttribute(oid, u"value1") + attr = x509.NameAttribute(oid, "value1") rdn = x509.RelativeDistinguishedName([attr]) assert rdn.get_attributes_for_oid(oid) == [attr] assert rdn.get_attributes_for_oid(x509.ObjectIdentifier("1.2.3")) == [] @@ -5002,8 +4952,8 @@ def test_valid(self): class TestName(object): def test_eq(self): - ava1 = x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1") - ava2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2") + ava1 = x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value1") + ava2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), "value2") name1 = x509.Name([ava1, ava2]) name2 = x509.Name( [ @@ -5017,8 +4967,8 @@ def test_eq(self): assert name3 == name4 def test_ne(self): - ava1 = x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1") - ava2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2") + ava1 = x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value1") + ava2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), "value2") name1 = x509.Name([ava1, ava2]) name2 = x509.Name([ava2, ava1]) name3 = x509.Name([x509.RelativeDistinguishedName([ava1, ava2])]) @@ -5027,8 +4977,8 @@ def test_ne(self): assert name1 != object() def test_hash(self): - ava1 = x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1") - ava2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2") + ava1 = x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value1") + ava2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), "value2") name1 = x509.Name([ava1, ava2]) name2 = x509.Name( [ @@ -5046,15 +4996,15 @@ def test_hash(self): def test_iter_input(self): attrs = [ - x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1") + x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value1") ] name = x509.Name(iter(attrs)) assert list(name) == attrs assert list(name) == attrs def test_rdns(self): - rdn1 = x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1") - rdn2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2") + rdn1 = x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value1") + rdn2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), "value2") name1 = x509.Name([rdn1, rdn2]) assert name1.rdns == [ x509.RelativeDistinguishedName([rdn1]), @@ -5067,13 +5017,13 @@ def test_rdns(self): ("common_name", "org_name", "expected_repr"), [ ( - u"cryptography.io", - u"PyCA", + "cryptography.io", + "PyCA", "", ), ( - u"Certificación", - u"Certificación", + "Certificación", + "Certificación", "", ), ], @@ -5092,17 +5042,17 @@ def test_rfc4514_string(self): n = x509.Name( [ x509.RelativeDistinguishedName( - [x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"net")] + [x509.NameAttribute(NameOID.DOMAIN_COMPONENT, "net")] ), x509.RelativeDistinguishedName( - [x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"example")] + [x509.NameAttribute(NameOID.DOMAIN_COMPONENT, "example")] ), x509.RelativeDistinguishedName( [ x509.NameAttribute( - NameOID.ORGANIZATIONAL_UNIT_NAME, u"Sales" + NameOID.ORGANIZATIONAL_UNIT_NAME, "Sales" ), - x509.NameAttribute(NameOID.COMMON_NAME, u"J. Smith"), + x509.NameAttribute(NameOID.COMMON_NAME, "J. Smith"), ] ), ] @@ -5112,11 +5062,11 @@ def test_rfc4514_string(self): def test_rfc4514_string_empty_values(self): n = x509.Name( [ - x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), - x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u""), - x509.NameAttribute(NameOID.LOCALITY_NAME, u""), - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"), - x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"), + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), + x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, ""), + x509.NameAttribute(NameOID.LOCALITY_NAME, ""), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA"), + x509.NameAttribute(NameOID.COMMON_NAME, "cryptography.io"), ] ) assert n.rfc4514_string() == "CN=cryptography.io,O=PyCA,L=,ST=,C=US" @@ -5129,8 +5079,8 @@ def test_not_nameattribute(self): def test_bytes(self, backend): name = x509.Name( [ - x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"), - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"), + x509.NameAttribute(NameOID.COMMON_NAME, "cryptography.io"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA"), ] ) assert name.public_bytes(backend) == binascii.unhexlify( @@ -5147,10 +5097,10 @@ def test_bmpstring_bytes(self, backend): [ x509.NameAttribute( NameOID.COMMON_NAME, - u"cryptography.io", + "cryptography.io", _ASN1Type.BMPString, ), - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA"), ] ) assert name.public_bytes(backend) == binascii.unhexlify( @@ -5165,10 +5115,10 @@ def test_universalstring_bytes(self, backend): [ x509.NameAttribute( NameOID.COMMON_NAME, - u"cryptography.io", + "cryptography.io", _ASN1Type.UniversalString, ), - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA"), ] ) assert name.public_bytes(backend) == binascii.unhexlify( @@ -5249,10 +5199,10 @@ def test_crt_signing_check(self, backend): x509.CertificateBuilder() .serial_number(777) .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .public_key(public_key) .not_valid_before(not_valid_before) @@ -5265,7 +5215,7 @@ def test_crt_signing_check(self, backend): def test_csr_signing_check(self, backend): private_key = self.load_key(backend) builder = x509.CertificateSigningRequestBuilder().subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) with pytest.raises(TypeError): @@ -5278,7 +5228,7 @@ def test_crl_signing_check(self, backend): builder = ( x509.CertificateRevocationListBuilder() .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"CA")]) + x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, "CA")]) ) .last_update(last_time) .next_update(next_time) diff --git a/tests/x509/test_x509_crlbuilder.py b/tests/x509/test_x509_crlbuilder.py index 922d24917979..a044c2f288fd 100644 --- a/tests/x509/test_x509_crlbuilder.py +++ b/tests/x509/test_x509_crlbuilder.py @@ -39,11 +39,11 @@ def test_issuer_name_invalid(self): def test_set_issuer_name_twice(self): builder = x509.CertificateRevocationListBuilder().issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) with pytest.raises(ValueError): builder.issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) @pytest.mark.requires_backend_interface(interface=RSABackend) @@ -61,7 +61,7 @@ def test_aware_last_update(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) @@ -105,7 +105,7 @@ def test_aware_next_update(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) @@ -188,7 +188,7 @@ def test_no_last_update(self, backend): builder = ( x509.CertificateRevocationListBuilder() .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .next_update(datetime.datetime(2030, 1, 1, 12, 1)) ) @@ -203,7 +203,7 @@ def test_no_next_update(self, backend): builder = ( x509.CertificateRevocationListBuilder() .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")]) + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) .last_update(datetime.datetime(2030, 1, 1, 12, 1)) ) @@ -223,7 +223,7 @@ def test_sign_empty_list(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) @@ -252,12 +252,12 @@ def test_sign_empty_list(self, backend): [ x509.AccessDescription( AuthorityInformationAccessOID.CA_ISSUERS, - x509.DNSName(u"cryptography.io"), + x509.DNSName("cryptography.io"), ) ] ), x509.IssuerAlternativeName( - [x509.UniformResourceIdentifier(u"https://cryptography.io")] + [x509.UniformResourceIdentifier("https://cryptography.io")] ), ], ) @@ -273,7 +273,7 @@ def test_sign_extensions(self, backend, extension): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) @@ -297,7 +297,7 @@ def test_sign_multiple_extensions_critical(self, backend): last_update = datetime.datetime(2002, 1, 1, 12, 1) next_update = datetime.datetime(2030, 1, 1, 12, 1) ian = x509.IssuerAlternativeName( - [x509.UniformResourceIdentifier(u"https://cryptography.io")] + [x509.UniformResourceIdentifier("https://cryptography.io")] ) crl_number = x509.CRLNumber(13) builder = ( @@ -306,7 +306,7 @@ def test_sign_multiple_extensions_critical(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) @@ -338,7 +338,7 @@ def test_freshestcrl_extension(self, backend): freshest = x509.FreshestCRL( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"http://d.om/delta")], + [x509.UniformResourceIdentifier("http://d.om/delta")], None, None, None, @@ -351,7 +351,7 @@ def test_freshestcrl_extension(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) @@ -369,7 +369,7 @@ def test_freshestcrl_extension(self, backend): assert isinstance(ext1.value[0], x509.DistributionPoint) uri = ext1.value[0].full_name[0] assert isinstance(uri, x509.UniformResourceIdentifier) - assert uri.value == u"http://d.om/delta" + assert uri.value == "http://d.om/delta" @pytest.mark.requires_backend_interface(interface=RSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) @@ -383,7 +383,7 @@ def test_add_unsupported_extension(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) @@ -407,7 +407,7 @@ def test_sign_rsa_key_too_small(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) @@ -431,7 +431,7 @@ def test_sign_with_invalid_hash(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) @@ -458,7 +458,7 @@ def test_sign_with_invalid_hash_ed25519(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) @@ -487,7 +487,7 @@ def test_sign_with_invalid_hash_ed448(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) @@ -509,7 +509,7 @@ def test_sign_dsa_key(self, backend): datetime.datetime(2002, 1, 1, 0, 0) ) ian = x509.IssuerAlternativeName( - [x509.UniformResourceIdentifier(u"https://cryptography.io")] + [x509.UniformResourceIdentifier("https://cryptography.io")] ) revoked_cert0 = ( x509.RevokedCertificateBuilder() @@ -526,7 +526,7 @@ def test_sign_dsa_key(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) @@ -560,7 +560,7 @@ def test_sign_ec_key(self, backend): datetime.datetime(2002, 1, 1, 0, 0) ) ian = x509.IssuerAlternativeName( - [x509.UniformResourceIdentifier(u"https://cryptography.io")] + [x509.UniformResourceIdentifier("https://cryptography.io")] ) revoked_cert0 = ( x509.RevokedCertificateBuilder() @@ -577,7 +577,7 @@ def test_sign_ec_key(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) @@ -613,7 +613,7 @@ def test_sign_ed25519_key(self, backend): datetime.datetime(2002, 1, 1, 0, 0) ) ian = x509.IssuerAlternativeName( - [x509.UniformResourceIdentifier(u"https://cryptography.io")] + [x509.UniformResourceIdentifier("https://cryptography.io")] ) revoked_cert0 = ( x509.RevokedCertificateBuilder() @@ -630,7 +630,7 @@ def test_sign_ed25519_key(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) @@ -668,7 +668,7 @@ def test_sign_ed448_key(self, backend): datetime.datetime(2002, 1, 1, 0, 0) ) ian = x509.IssuerAlternativeName( - [x509.UniformResourceIdentifier(u"https://cryptography.io")] + [x509.UniformResourceIdentifier("https://cryptography.io")] ) revoked_cert0 = ( x509.RevokedCertificateBuilder() @@ -685,7 +685,7 @@ def test_sign_ed448_key(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) @@ -724,7 +724,7 @@ def test_dsa_key_sign_md5(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) @@ -749,7 +749,7 @@ def test_ec_key_sign_md5(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) @@ -789,7 +789,7 @@ def test_sign_with_revoked_certificates(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index 0e231069f84c..fcde4ca49c78 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -41,7 +41,7 @@ def _make_certbuilder(private_key): - name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"example.org")]) + name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, "example.org")]) return ( x509.CertificateBuilder() .subject_name(name) @@ -233,55 +233,55 @@ def test_hash(self): class TestCertificateIssuer(object): def test_iter_names(self): ci = x509.CertificateIssuer( - [x509.DNSName(u"cryptography.io"), x509.DNSName(u"crypto.local")] + [x509.DNSName("cryptography.io"), x509.DNSName("crypto.local")] ) assert len(ci) == 2 assert list(ci) == [ - x509.DNSName(u"cryptography.io"), - x509.DNSName(u"crypto.local"), + x509.DNSName("cryptography.io"), + x509.DNSName("crypto.local"), ] def test_indexing(self): ci = x509.CertificateIssuer( [ - x509.DNSName(u"cryptography.io"), - x509.DNSName(u"crypto.local"), - x509.DNSName(u"another.local"), - x509.RFC822Name(u"email@another.local"), - x509.UniformResourceIdentifier(u"http://another.local"), + x509.DNSName("cryptography.io"), + x509.DNSName("crypto.local"), + x509.DNSName("another.local"), + x509.RFC822Name("email@another.local"), + x509.UniformResourceIdentifier("http://another.local"), ] ) assert ci[-1] == ci[4] assert ci[2:6:2] == [ci[2], ci[4]] def test_eq(self): - ci1 = x509.CertificateIssuer([x509.DNSName(u"cryptography.io")]) - ci2 = x509.CertificateIssuer([x509.DNSName(u"cryptography.io")]) + ci1 = x509.CertificateIssuer([x509.DNSName("cryptography.io")]) + ci2 = x509.CertificateIssuer([x509.DNSName("cryptography.io")]) assert ci1 == ci2 def test_ne(self): - ci1 = x509.CertificateIssuer([x509.DNSName(u"cryptography.io")]) - ci2 = x509.CertificateIssuer([x509.DNSName(u"somethingelse.tld")]) + ci1 = x509.CertificateIssuer([x509.DNSName("cryptography.io")]) + ci2 = x509.CertificateIssuer([x509.DNSName("somethingelse.tld")]) assert ci1 != ci2 assert ci1 != object() def test_repr(self): - ci = x509.CertificateIssuer([x509.DNSName(u"cryptography.io")]) + ci = x509.CertificateIssuer([x509.DNSName("cryptography.io")]) assert repr(ci) == ( "])>)>" ) def test_get_values_for_type(self): - ci = x509.CertificateIssuer([x509.DNSName(u"cryptography.io")]) + ci = x509.CertificateIssuer([x509.DNSName("cryptography.io")]) names = ci.get_values_for_type(x509.DNSName) - assert names == [u"cryptography.io"] + assert names == ["cryptography.io"] def test_hash(self): - ci1 = x509.CertificateIssuer([x509.DNSName(u"cryptography.io")]) - ci2 = x509.CertificateIssuer([x509.DNSName(u"cryptography.io")]) + ci1 = x509.CertificateIssuer([x509.DNSName("cryptography.io")]) + ci2 = x509.CertificateIssuer([x509.DNSName("cryptography.io")]) ci3 = x509.CertificateIssuer( - [x509.UniformResourceIdentifier(u"http://something")] + [x509.UniformResourceIdentifier("http://something")] ) assert hash(ci1) == hash(ci2) assert hash(ci1) != hash(ci3) @@ -385,11 +385,11 @@ def test_notice_numbers_none(self): def test_iter_input(self): numbers = [1, 3, 4] - nr = x509.NoticeReference(u"org", iter(numbers)) + nr = x509.NoticeReference("org", iter(numbers)) assert list(nr.notice_numbers) == numbers def test_repr(self): - nr = x509.NoticeReference(u"org", [1, 3, 4]) + nr = x509.NoticeReference("org", [1, 3, 4]) assert repr(nr) == ( ", explicit_text='text')>" @@ -472,7 +472,7 @@ def test_none_policy_qualifiers(self): assert pi.policy_qualifiers is None def test_policy_qualifiers(self): - pq = [u"string"] + pq = ["string"] pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), pq) assert pi.policy_identifier == x509.ObjectIdentifier("1.2.3") assert pi.policy_qualifiers == pq @@ -482,12 +482,12 @@ def test_invalid_policy_identifiers(self): x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), [1, 2]) def test_iter_input(self): - qual = [u"foo", u"bar"] + qual = ["foo", "bar"] pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), iter(qual)) assert list(pi.policy_qualifiers) == qual def test_repr(self): - pq = [u"string", x509.UserNotice(None, u"hi")] + pq = ["string", x509.UserNotice(None, "hi")] pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), pq) assert repr(pi) == ( ")>" def test_eq(self): name = x509.Name( - [x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")] + [x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value1")] ) name2 = x509.Name( - [x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")] + [x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value1")] ) gn = x509.DirectoryName(name) gn2 = x509.DirectoryName(name2) @@ -1724,10 +1716,10 @@ def test_eq(self): def test_ne(self): name = x509.Name( - [x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")] + [x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value1")] ) name2 = x509.Name( - [x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2")] + [x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), "value2")] ) gn = x509.DirectoryName(name) gn2 = x509.DirectoryName(name2) @@ -1736,10 +1728,10 @@ def test_ne(self): def test_hash(self): name = x509.Name( - [x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")] + [x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), "value1")] ) name2 = x509.Name( - [x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2")] + [x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), "value2")] ) gn = x509.DirectoryName(name) gn2 = x509.DirectoryName(name) @@ -1750,13 +1742,13 @@ def test_hash(self): class TestRFC822Name(object): def test_repr(self): - gn = x509.RFC822Name(u"string") + gn = x509.RFC822Name("string") assert repr(gn) == "" def test_equality(self): - gn = x509.RFC822Name(u"string") - gn2 = x509.RFC822Name(u"string2") - gn3 = x509.RFC822Name(u"string") + gn = x509.RFC822Name("string") + gn2 = x509.RFC822Name("string2") + gn3 = x509.RFC822Name("string") assert gn != gn2 assert gn != object() assert gn == gn3 @@ -1770,23 +1762,23 @@ def test_not_text(self): def test_invalid_email(self): with pytest.raises(ValueError): - x509.RFC822Name(u"Name ") + x509.RFC822Name("Name ") with pytest.raises(ValueError): - x509.RFC822Name(u"") + x509.RFC822Name("") def test_single_label(self): - gn = x509.RFC822Name(u"administrator") - assert gn.value == u"administrator" + gn = x509.RFC822Name("administrator") + assert gn.value == "administrator" def test_non_a_label(self): with pytest.raises(ValueError): - x509.RFC822Name(u"email@em\xe5\xefl.com") + x509.RFC822Name("email@em\xe5\xefl.com") def test_hash(self): - g1 = x509.RFC822Name(u"email@host.com") - g2 = x509.RFC822Name(u"email@host.com") - g3 = x509.RFC822Name(u"admin@host.com") + g1 = x509.RFC822Name("email@host.com") + g2 = x509.RFC822Name("email@host.com") + g3 = x509.RFC822Name("admin@host.com") assert hash(g1) == hash(g2) assert hash(g1) != hash(g3) @@ -1794,9 +1786,9 @@ def test_hash(self): class TestUniformResourceIdentifier(object): def test_equality(self): - gn = x509.UniformResourceIdentifier(u"string") - gn2 = x509.UniformResourceIdentifier(u"string2") - gn3 = x509.UniformResourceIdentifier(u"string") + gn = x509.UniformResourceIdentifier("string") + gn2 = x509.UniformResourceIdentifier("string2") + gn3 = x509.UniformResourceIdentifier("string") assert gn != gn2 assert gn != object() assert gn == gn3 @@ -1806,33 +1798,33 @@ def test_not_text(self): x509.UniformResourceIdentifier(1.3) def test_no_parsed_hostname(self): - gn = x509.UniformResourceIdentifier(u"singlelabel") - assert gn.value == u"singlelabel" + gn = x509.UniformResourceIdentifier("singlelabel") + assert gn.value == "singlelabel" def test_with_port(self): - gn = x509.UniformResourceIdentifier(u"singlelabel:443/test") - assert gn.value == u"singlelabel:443/test" + gn = x509.UniformResourceIdentifier("singlelabel:443/test") + assert gn.value == "singlelabel:443/test" def test_non_a_label(self): with pytest.raises(ValueError): x509.UniformResourceIdentifier( - u"http://\u043f\u044b\u043a\u0430.cryptography" + "http://\u043f\u044b\u043a\u0430.cryptography" ) def test_empty_hostname(self): - gn = x509.UniformResourceIdentifier(u"ldap:///some-nonsense") + gn = x509.UniformResourceIdentifier("ldap:///some-nonsense") assert gn.value == "ldap:///some-nonsense" def test_hash(self): - g1 = x509.UniformResourceIdentifier(u"http://host.com") - g2 = x509.UniformResourceIdentifier(u"http://host.com") - g3 = x509.UniformResourceIdentifier(u"http://other.com") + g1 = x509.UniformResourceIdentifier("http://host.com") + g2 = x509.UniformResourceIdentifier("http://host.com") + g3 = x509.UniformResourceIdentifier("http://other.com") assert hash(g1) == hash(g2) assert hash(g1) != hash(g3) def test_repr(self): - gn = x509.UniformResourceIdentifier(u"string") + gn = x509.UniformResourceIdentifier("string") assert repr(gn) == ("") @@ -1879,33 +1871,33 @@ def test_not_ipaddress(self): x509.IPAddress(1.3) def test_repr(self): - gn = x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1")) + gn = x509.IPAddress(ipaddress.IPv4Address("127.0.0.1")) assert repr(gn) == "" - gn2 = x509.IPAddress(ipaddress.IPv6Address(u"ff::")) + gn2 = x509.IPAddress(ipaddress.IPv6Address("ff::")) assert repr(gn2) == "" - gn3 = x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.0/24")) + gn3 = x509.IPAddress(ipaddress.IPv4Network("192.168.0.0/24")) assert repr(gn3) == "" - gn4 = x509.IPAddress(ipaddress.IPv6Network(u"ff::/96")) + gn4 = x509.IPAddress(ipaddress.IPv6Network("ff::/96")) assert repr(gn4) == "" def test_eq(self): - gn = x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1")) - gn2 = x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1")) + gn = x509.IPAddress(ipaddress.IPv4Address("127.0.0.1")) + gn2 = x509.IPAddress(ipaddress.IPv4Address("127.0.0.1")) assert gn == gn2 def test_ne(self): - gn = x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1")) - gn2 = x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.2")) + gn = x509.IPAddress(ipaddress.IPv4Address("127.0.0.1")) + gn2 = x509.IPAddress(ipaddress.IPv4Address("127.0.0.2")) assert gn != gn2 assert gn != object() def test_hash(self): - gn = x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1")) - gn2 = x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1")) - gn3 = x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.2")) + gn = x509.IPAddress(ipaddress.IPv4Address("127.0.0.1")) + gn2 = x509.IPAddress(ipaddress.IPv4Address("127.0.0.1")) + gn3 = x509.IPAddress(ipaddress.IPv4Address("127.0.0.2")) assert hash(gn) == hash(gn2) assert hash(gn) != hash(gn3) @@ -1916,7 +1908,7 @@ def test_invalid_args(self): x509.OtherName(b"notanobjectidentifier", b"derdata") with pytest.raises(TypeError): - x509.OtherName(x509.ObjectIdentifier("1.2.3.4"), u"notderdata") + x509.OtherName(x509.ObjectIdentifier("1.2.3.4"), "notderdata") def test_repr(self): gn = x509.OtherName(x509.ObjectIdentifier("1.2.3.4"), b"derdata") @@ -1956,24 +1948,24 @@ def test_hash(self): class TestGeneralNames(object): def test_get_values_for_type(self): - gns = x509.GeneralNames([x509.DNSName(u"cryptography.io")]) + gns = x509.GeneralNames([x509.DNSName("cryptography.io")]) names = gns.get_values_for_type(x509.DNSName) - assert names == [u"cryptography.io"] + assert names == ["cryptography.io"] def test_iter_names(self): gns = x509.GeneralNames( - [x509.DNSName(u"cryptography.io"), x509.DNSName(u"crypto.local")] + [x509.DNSName("cryptography.io"), x509.DNSName("crypto.local")] ) assert len(gns) == 2 assert list(gns) == [ - x509.DNSName(u"cryptography.io"), - x509.DNSName(u"crypto.local"), + x509.DNSName("cryptography.io"), + x509.DNSName("crypto.local"), ] def test_iter_input(self): names = [ - x509.DNSName(u"cryptography.io"), - x509.DNSName(u"crypto.local"), + x509.DNSName("cryptography.io"), + x509.DNSName("crypto.local"), ] gns = x509.GeneralNames(iter(names)) assert list(gns) == names @@ -1981,11 +1973,11 @@ def test_iter_input(self): def test_indexing(self): gn = x509.GeneralNames( [ - x509.DNSName(u"cryptography.io"), - x509.DNSName(u"crypto.local"), - x509.DNSName(u"another.local"), - x509.RFC822Name(u"email@another.local"), - x509.UniformResourceIdentifier(u"http://another.local"), + x509.DNSName("cryptography.io"), + x509.DNSName("crypto.local"), + x509.DNSName("another.local"), + x509.RFC822Name("email@another.local"), + x509.UniformResourceIdentifier("http://another.local"), ] ) assert gn[-1] == gn[4] @@ -1993,57 +1985,57 @@ def test_indexing(self): def test_invalid_general_names(self): with pytest.raises(TypeError): - x509.GeneralNames([x509.DNSName(u"cryptography.io"), "invalid"]) + x509.GeneralNames([x509.DNSName("cryptography.io"), "invalid"]) def test_repr(self): - gns = x509.GeneralNames([x509.DNSName(u"cryptography.io")]) + gns = x509.GeneralNames([x509.DNSName("cryptography.io")]) assert repr(gns) == ( "])>" ) def test_eq(self): - gns = x509.GeneralNames([x509.DNSName(u"cryptography.io")]) - gns2 = x509.GeneralNames([x509.DNSName(u"cryptography.io")]) + gns = x509.GeneralNames([x509.DNSName("cryptography.io")]) + gns2 = x509.GeneralNames([x509.DNSName("cryptography.io")]) assert gns == gns2 def test_ne(self): - gns = x509.GeneralNames([x509.DNSName(u"cryptography.io")]) - gns2 = x509.GeneralNames([x509.RFC822Name(u"admin@cryptography.io")]) + gns = x509.GeneralNames([x509.DNSName("cryptography.io")]) + gns2 = x509.GeneralNames([x509.RFC822Name("admin@cryptography.io")]) assert gns != gns2 assert gns != object() def test_hash(self): - gns = x509.GeneralNames([x509.DNSName(u"cryptography.io")]) - gns2 = x509.GeneralNames([x509.DNSName(u"cryptography.io")]) - gns3 = x509.GeneralNames([x509.RFC822Name(u"admin@cryptography.io")]) + gns = x509.GeneralNames([x509.DNSName("cryptography.io")]) + gns2 = x509.GeneralNames([x509.DNSName("cryptography.io")]) + gns3 = x509.GeneralNames([x509.RFC822Name("admin@cryptography.io")]) assert hash(gns) == hash(gns2) assert hash(gns) != hash(gns3) class TestIssuerAlternativeName(object): def test_get_values_for_type(self): - san = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")]) + san = x509.IssuerAlternativeName([x509.DNSName("cryptography.io")]) names = san.get_values_for_type(x509.DNSName) - assert names == [u"cryptography.io"] + assert names == ["cryptography.io"] def test_iter_names(self): san = x509.IssuerAlternativeName( - [x509.DNSName(u"cryptography.io"), x509.DNSName(u"crypto.local")] + [x509.DNSName("cryptography.io"), x509.DNSName("crypto.local")] ) assert len(san) == 2 assert list(san) == [ - x509.DNSName(u"cryptography.io"), - x509.DNSName(u"crypto.local"), + x509.DNSName("cryptography.io"), + x509.DNSName("crypto.local"), ] def test_indexing(self): ian = x509.IssuerAlternativeName( [ - x509.DNSName(u"cryptography.io"), - x509.DNSName(u"crypto.local"), - x509.DNSName(u"another.local"), - x509.RFC822Name(u"email@another.local"), - x509.UniformResourceIdentifier(u"http://another.local"), + x509.DNSName("cryptography.io"), + x509.DNSName("crypto.local"), + x509.DNSName("another.local"), + x509.RFC822Name("email@another.local"), + x509.UniformResourceIdentifier("http://another.local"), ] ) assert ian[-1] == ian[4] @@ -2052,34 +2044,34 @@ def test_indexing(self): def test_invalid_general_names(self): with pytest.raises(TypeError): x509.IssuerAlternativeName( - [x509.DNSName(u"cryptography.io"), "invalid"] + [x509.DNSName("cryptography.io"), "invalid"] ) def test_repr(self): - san = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")]) + san = x509.IssuerAlternativeName([x509.DNSName("cryptography.io")]) assert repr(san) == ( "])>)>" ) def test_eq(self): - san = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")]) - san2 = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")]) + san = x509.IssuerAlternativeName([x509.DNSName("cryptography.io")]) + san2 = x509.IssuerAlternativeName([x509.DNSName("cryptography.io")]) assert san == san2 def test_ne(self): - san = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")]) + san = x509.IssuerAlternativeName([x509.DNSName("cryptography.io")]) san2 = x509.IssuerAlternativeName( - [x509.RFC822Name(u"admin@cryptography.io")] + [x509.RFC822Name("admin@cryptography.io")] ) assert san != san2 assert san != object() def test_hash(self): - ian = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")]) - ian2 = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")]) + ian = x509.IssuerAlternativeName([x509.DNSName("cryptography.io")]) + ian2 = x509.IssuerAlternativeName([x509.DNSName("cryptography.io")]) ian3 = x509.IssuerAlternativeName( - [x509.RFC822Name(u"admin@cryptography.io")] + [x509.RFC822Name("admin@cryptography.io")] ) assert hash(ian) == hash(ian2) assert hash(ian) != hash(ian3) @@ -2098,7 +2090,7 @@ def test_uri(self, backend): ExtensionOID.ISSUER_ALTERNATIVE_NAME ) assert list(ext.value) == [ - x509.UniformResourceIdentifier(u"http://path.to.root/root.crt"), + x509.UniformResourceIdentifier("http://path.to.root/root.crt"), ] @@ -2130,28 +2122,28 @@ def test_hash(self): class TestSubjectAlternativeName(object): def test_get_values_for_type(self): - san = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]) + san = x509.SubjectAlternativeName([x509.DNSName("cryptography.io")]) names = san.get_values_for_type(x509.DNSName) - assert names == [u"cryptography.io"] + assert names == ["cryptography.io"] def test_iter_names(self): san = x509.SubjectAlternativeName( - [x509.DNSName(u"cryptography.io"), x509.DNSName(u"crypto.local")] + [x509.DNSName("cryptography.io"), x509.DNSName("crypto.local")] ) assert len(san) == 2 assert list(san) == [ - x509.DNSName(u"cryptography.io"), - x509.DNSName(u"crypto.local"), + x509.DNSName("cryptography.io"), + x509.DNSName("crypto.local"), ] def test_indexing(self): san = x509.SubjectAlternativeName( [ - x509.DNSName(u"cryptography.io"), - x509.DNSName(u"crypto.local"), - x509.DNSName(u"another.local"), - x509.RFC822Name(u"email@another.local"), - x509.UniformResourceIdentifier(u"http://another.local"), + x509.DNSName("cryptography.io"), + x509.DNSName("crypto.local"), + x509.DNSName("another.local"), + x509.RFC822Name("email@another.local"), + x509.UniformResourceIdentifier("http://another.local"), ] ) assert san[-1] == san[4] @@ -2160,34 +2152,34 @@ def test_indexing(self): def test_invalid_general_names(self): with pytest.raises(TypeError): x509.SubjectAlternativeName( - [x509.DNSName(u"cryptography.io"), "invalid"] + [x509.DNSName("cryptography.io"), "invalid"] ) def test_repr(self): - san = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]) + san = x509.SubjectAlternativeName([x509.DNSName("cryptography.io")]) assert repr(san) == ( "])>)>" ) def test_eq(self): - san = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]) - san2 = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]) + san = x509.SubjectAlternativeName([x509.DNSName("cryptography.io")]) + san2 = x509.SubjectAlternativeName([x509.DNSName("cryptography.io")]) assert san == san2 def test_ne(self): - san = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]) + san = x509.SubjectAlternativeName([x509.DNSName("cryptography.io")]) san2 = x509.SubjectAlternativeName( - [x509.RFC822Name(u"admin@cryptography.io")] + [x509.RFC822Name("admin@cryptography.io")] ) assert san != san2 assert san != object() def test_hash(self): - san = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]) - san2 = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]) + san = x509.SubjectAlternativeName([x509.DNSName("cryptography.io")]) + san2 = x509.SubjectAlternativeName([x509.DNSName("cryptography.io")]) san3 = x509.SubjectAlternativeName( - [x509.RFC822Name(u"admin@cryptography.io")] + [x509.RFC822Name("admin@cryptography.io")] ) assert hash(san) == hash(san2) assert hash(san) != hash(san3) @@ -2211,7 +2203,7 @@ def test_dns_name(self, backend): san = ext.value dns = san.get_values_for_type(x509.DNSName) - assert dns == [u"www.cryptography.io", u"cryptography.io"] + assert dns == ["www.cryptography.io", "cryptography.io"] def test_wildcard_dns_name(self, backend): cert = _load_cert( @@ -2225,10 +2217,10 @@ def test_wildcard_dns_name(self, backend): dns = ext.value.get_values_for_type(x509.DNSName) assert dns == [ - u"*.langui.sh", - u"langui.sh", - u"*.saseliminator.com", - u"saseliminator.com", + "*.langui.sh", + "langui.sh", + "*.saseliminator.com", + "saseliminator.com", ] def test_san_empty_hostname(self, backend): @@ -2242,7 +2234,7 @@ def test_san_empty_hostname(self, backend): ) dns = san.value.get_values_for_type(x509.DNSName) - assert dns == [u""] + assert dns == [""] def test_san_wildcard_idna_dns_name(self, backend): cert = _load_cert( @@ -2255,7 +2247,7 @@ def test_san_wildcard_idna_dns_name(self, backend): ) dns = ext.value.get_values_for_type(x509.DNSName) - assert dns == [u"*.xn--80ato2c.cryptography"] + assert dns == ["*.xn--80ato2c.cryptography"] def test_unsupported_gn(self, backend): cert = _load_cert( @@ -2296,8 +2288,8 @@ def test_uri(self, backend): assert ext is not None uri = ext.value.get_values_for_type(x509.UniformResourceIdentifier) assert uri == [ - u"gopher://xn--80ato2c.cryptography:70/path?q=s#hel" u"lo", - u"http://someregulardomain.com", + "gopher://xn--80ato2c.cryptography:70/path?q=s#hel" "lo", + "http://someregulardomain.com", ] def test_ipaddress(self, backend): @@ -2316,8 +2308,8 @@ def test_ipaddress(self, backend): ip = san.get_values_for_type(x509.IPAddress) assert [ - ipaddress.ip_address(u"127.0.0.1"), - ipaddress.ip_address(u"ff::"), + ipaddress.ip_address("127.0.0.1"), + ipaddress.ip_address("ff::"), ] == ip def test_dirname(self, backend): @@ -2338,10 +2330,10 @@ def test_dirname(self, backend): assert [ x509.Name( [ - x509.NameAttribute(NameOID.COMMON_NAME, u"test"), - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Org"), + x509.NameAttribute(NameOID.COMMON_NAME, "test"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Org"), x509.NameAttribute( - NameOID.STATE_OR_PROVINCE_NAME, u"Texas" + NameOID.STATE_OR_PROVINCE_NAME, "Texas" ), ] ) @@ -2362,7 +2354,7 @@ def test_rfc822name(self, backend): san = ext.value rfc822name = san.get_values_for_type(x509.RFC822Name) - assert [u"email@xn--eml-vla4c.com"] == rfc822name + assert ["email@xn--eml-vla4c.com"] == rfc822name def test_idna2003_invalid(self, backend): cert = _load_cert( @@ -2376,7 +2368,7 @@ def test_idna2003_invalid(self, backend): assert len(san) == 1 [name] = san - assert name.value == u"xn--k4h.ws" + assert name.value == "xn--k4h.ws" def test_unicode_rfc822_name_dns_name_uri(self, backend): cert = _load_cert( @@ -2391,9 +2383,9 @@ def test_unicode_rfc822_name_dns_name_uri(self, backend): rfc822_name = ext.value.get_values_for_type(x509.RFC822Name) dns_name = ext.value.get_values_for_type(x509.DNSName) uri = ext.value.get_values_for_type(x509.UniformResourceIdentifier) - assert rfc822_name == [u"email@xn--80ato2c.cryptography"] - assert dns_name == [u"xn--80ato2c.cryptography"] - assert uri == [u"https://www.xn--80ato2c.cryptography"] + assert rfc822_name == ["email@xn--80ato2c.cryptography"] + assert dns_name == ["xn--80ato2c.cryptography"] + assert uri == ["https://www.xn--80ato2c.cryptography"] def test_rfc822name_dnsname_ipaddress_directoryname_uri(self, backend): cert = _load_cert( @@ -2414,22 +2406,22 @@ def test_rfc822name_dnsname_ipaddress_directoryname_uri(self, backend): dns = san.get_values_for_type(x509.DNSName) ip = san.get_values_for_type(x509.IPAddress) dirname = san.get_values_for_type(x509.DirectoryName) - assert [u"user@cryptography.io"] == rfc822_name - assert [u"https://cryptography.io"] == uri - assert [u"cryptography.io"] == dns + assert ["user@cryptography.io"] == rfc822_name + assert ["https://cryptography.io"] == uri + assert ["cryptography.io"] == dns assert [ x509.Name( [ - x509.NameAttribute(NameOID.COMMON_NAME, u"dirCN"), + x509.NameAttribute(NameOID.COMMON_NAME, "dirCN"), x509.NameAttribute( - NameOID.ORGANIZATION_NAME, u"Cryptographic Authority" + NameOID.ORGANIZATION_NAME, "Cryptographic Authority" ), ] ) ] == dirname assert [ - ipaddress.ip_address(u"127.0.0.1"), - ipaddress.ip_address(u"ff::"), + ipaddress.ip_address("127.0.0.1"), + ipaddress.ip_address("ff::"), ] == ip def test_invalid_rfc822name(self, backend): @@ -2443,11 +2435,11 @@ def test_invalid_rfc822name(self, backend): ).value values = san.get_values_for_type(x509.RFC822Name) assert values == [ - u"email", - u"email ", - u"email ", - u"email ", - u"myemail:", + "email", + "email ", + "email ", + "email ", + "myemail:", ] def test_other_name(self, backend): @@ -2474,9 +2466,9 @@ def test_other_name(self, backend): def test_certbuilder(self, backend): sans = [ - u"*.example.org", - u"*.xn--4ca7aey.example.com", - u"foobar.example.net", + "*.example.org", + "*.xn--4ca7aey.example.com", + "foobar.example.net", ] private_key = RSA_KEY_2048.private_key(backend) builder = _make_certbuilder(private_key) @@ -2524,7 +2516,7 @@ def test_eku(self, backend): class TestAccessDescription(object): def test_invalid_access_method(self): with pytest.raises(TypeError): - x509.AccessDescription("notanoid", x509.DNSName(u"test")) + x509.AccessDescription("notanoid", x509.DNSName("test")) def test_invalid_access_location(self): with pytest.raises(TypeError): @@ -2535,14 +2527,14 @@ def test_invalid_access_location(self): def test_valid_nonstandard_method(self): ad = x509.AccessDescription( ObjectIdentifier("2.999.1"), - x509.UniformResourceIdentifier(u"http://example.com"), + x509.UniformResourceIdentifier("http://example.com"), ) assert ad is not None def test_repr(self): ad = x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp.domain.com"), + x509.UniformResourceIdentifier("http://ocsp.domain.com"), ) assert repr(ad) == ( "" + "" ) def test_eq(self): @@ -2682,13 +2674,11 @@ def test_iter_len(self): [ x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp.domain.com"), + x509.UniformResourceIdentifier("http://ocsp.domain.com"), ), x509.AccessDescription( AuthorityInformationAccessOID.CA_ISSUERS, - x509.UniformResourceIdentifier( - u"http://domain.com/ca.crt" - ), + x509.UniformResourceIdentifier("http://domain.com/ca.crt"), ), ] ) @@ -2696,11 +2686,11 @@ def test_iter_len(self): assert list(aia) == [ x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp.domain.com"), + x509.UniformResourceIdentifier("http://ocsp.domain.com"), ), x509.AccessDescription( AuthorityInformationAccessOID.CA_ISSUERS, - x509.UniformResourceIdentifier(u"http://domain.com/ca.crt"), + x509.UniformResourceIdentifier("http://domain.com/ca.crt"), ), ] @@ -2708,7 +2698,7 @@ def test_iter_input(self): desc = [ x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp.domain.com"), + x509.UniformResourceIdentifier("http://ocsp.domain.com"), ) ] aia = x509.AuthorityInformationAccess(iter(desc)) @@ -2719,13 +2709,11 @@ def test_repr(self): [ x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp.domain.com"), + x509.UniformResourceIdentifier("http://ocsp.domain.com"), ), x509.AccessDescription( AuthorityInformationAccessOID.CA_ISSUERS, - x509.UniformResourceIdentifier( - u"http://domain.com/ca.crt" - ), + x509.UniformResourceIdentifier("http://domain.com/ca.crt"), ), ] ) @@ -2744,13 +2732,11 @@ def test_eq(self): [ x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp.domain.com"), + x509.UniformResourceIdentifier("http://ocsp.domain.com"), ), x509.AccessDescription( AuthorityInformationAccessOID.CA_ISSUERS, - x509.UniformResourceIdentifier( - u"http://domain.com/ca.crt" - ), + x509.UniformResourceIdentifier("http://domain.com/ca.crt"), ), ] ) @@ -2758,13 +2744,11 @@ def test_eq(self): [ x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp.domain.com"), + x509.UniformResourceIdentifier("http://ocsp.domain.com"), ), x509.AccessDescription( AuthorityInformationAccessOID.CA_ISSUERS, - x509.UniformResourceIdentifier( - u"http://domain.com/ca.crt" - ), + x509.UniformResourceIdentifier("http://domain.com/ca.crt"), ), ] ) @@ -2775,13 +2759,11 @@ def test_ne(self): [ x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp.domain.com"), + x509.UniformResourceIdentifier("http://ocsp.domain.com"), ), x509.AccessDescription( AuthorityInformationAccessOID.CA_ISSUERS, - x509.UniformResourceIdentifier( - u"http://domain.com/ca.crt" - ), + x509.UniformResourceIdentifier("http://domain.com/ca.crt"), ), ] ) @@ -2789,7 +2771,7 @@ def test_ne(self): [ x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp.domain.com"), + x509.UniformResourceIdentifier("http://ocsp.domain.com"), ), ] ) @@ -2802,25 +2784,23 @@ def test_indexing(self): [ x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp.domain.com"), + x509.UniformResourceIdentifier("http://ocsp.domain.com"), ), x509.AccessDescription( AuthorityInformationAccessOID.CA_ISSUERS, - x509.UniformResourceIdentifier( - u"http://domain.com/ca.crt" - ), + x509.UniformResourceIdentifier("http://domain.com/ca.crt"), ), x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp2.domain.com"), + x509.UniformResourceIdentifier("http://ocsp2.domain.com"), ), x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp3.domain.com"), + x509.UniformResourceIdentifier("http://ocsp3.domain.com"), ), x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp4.domain.com"), + x509.UniformResourceIdentifier("http://ocsp4.domain.com"), ), ] ) @@ -2832,13 +2812,11 @@ def test_hash(self): [ x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp.domain.com"), + x509.UniformResourceIdentifier("http://ocsp.domain.com"), ), x509.AccessDescription( AuthorityInformationAccessOID.CA_ISSUERS, - x509.UniformResourceIdentifier( - u"http://domain.com/ca.crt" - ), + x509.UniformResourceIdentifier("http://domain.com/ca.crt"), ), ] ) @@ -2846,13 +2824,11 @@ def test_hash(self): [ x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp.domain.com"), + x509.UniformResourceIdentifier("http://ocsp.domain.com"), ), x509.AccessDescription( AuthorityInformationAccessOID.CA_ISSUERS, - x509.UniformResourceIdentifier( - u"http://domain.com/ca.crt" - ), + x509.UniformResourceIdentifier("http://domain.com/ca.crt"), ), ] ) @@ -2860,13 +2836,11 @@ def test_hash(self): [ x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp.other.com"), + x509.UniformResourceIdentifier("http://ocsp.other.com"), ), x509.AccessDescription( AuthorityInformationAccessOID.CA_ISSUERS, - x509.UniformResourceIdentifier( - u"http://domain.com/ca.crt" - ), + x509.UniformResourceIdentifier("http://domain.com/ca.crt"), ), ] ) @@ -2884,11 +2858,11 @@ def test_iter_len(self): [ x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca.domain.com"), + x509.UniformResourceIdentifier("http://ca.domain.com"), ), x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca2.domain.com"), + x509.UniformResourceIdentifier("http://ca2.domain.com"), ), ] ) @@ -2896,11 +2870,11 @@ def test_iter_len(self): assert list(sia) == [ x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca.domain.com"), + x509.UniformResourceIdentifier("http://ca.domain.com"), ), x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca2.domain.com"), + x509.UniformResourceIdentifier("http://ca2.domain.com"), ), ] @@ -2908,7 +2882,7 @@ def test_iter_input(self): desc = [ x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca.domain.com"), + x509.UniformResourceIdentifier("http://ca.domain.com"), ) ] sia = x509.SubjectInformationAccess(iter(desc)) @@ -2919,7 +2893,7 @@ def test_repr(self): [ x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca.domain.com"), + x509.UniformResourceIdentifier("http://ca.domain.com"), ) ] ) @@ -2935,11 +2909,11 @@ def test_eq(self): [ x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca.domain.com"), + x509.UniformResourceIdentifier("http://ca.domain.com"), ), x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca2.domain.com"), + x509.UniformResourceIdentifier("http://ca2.domain.com"), ), ] ) @@ -2947,11 +2921,11 @@ def test_eq(self): [ x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca.domain.com"), + x509.UniformResourceIdentifier("http://ca.domain.com"), ), x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca2.domain.com"), + x509.UniformResourceIdentifier("http://ca2.domain.com"), ), ] ) @@ -2962,11 +2936,11 @@ def test_ne(self): [ x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca.domain.com"), + x509.UniformResourceIdentifier("http://ca.domain.com"), ), x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca2.domain.com"), + x509.UniformResourceIdentifier("http://ca2.domain.com"), ), ] ) @@ -2974,7 +2948,7 @@ def test_ne(self): [ x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca.domain.com"), + x509.UniformResourceIdentifier("http://ca.domain.com"), ), ] ) @@ -2987,23 +2961,23 @@ def test_indexing(self): [ x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca.domain.com"), + x509.UniformResourceIdentifier("http://ca.domain.com"), ), x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca2.domain.com"), + x509.UniformResourceIdentifier("http://ca2.domain.com"), ), x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca3.domain.com"), + x509.UniformResourceIdentifier("http://ca3.domain.com"), ), x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca4.domain.com"), + x509.UniformResourceIdentifier("http://ca4.domain.com"), ), x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca5.domain.com"), + x509.UniformResourceIdentifier("http://ca5.domain.com"), ), ] ) @@ -3015,11 +2989,11 @@ def test_hash(self): [ x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca.domain.com"), + x509.UniformResourceIdentifier("http://ca.domain.com"), ), x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca2.domain.com"), + x509.UniformResourceIdentifier("http://ca2.domain.com"), ), ] ) @@ -3027,11 +3001,11 @@ def test_hash(self): [ x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca.domain.com"), + x509.UniformResourceIdentifier("http://ca.domain.com"), ), x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca2.domain.com"), + x509.UniformResourceIdentifier("http://ca2.domain.com"), ), ] ) @@ -3039,11 +3013,11 @@ def test_hash(self): [ x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca.domain.com"), + x509.UniformResourceIdentifier("http://ca.domain.com"), ), x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"http://ca3.domain.com"), + x509.UniformResourceIdentifier("http://ca3.domain.com"), ), ] ) @@ -3070,12 +3044,12 @@ def test_sia(self, backend): [ x509.AccessDescription( SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier(u"https://my.ca.issuer/"), + x509.UniformResourceIdentifier("https://my.ca.issuer/"), ), x509.AccessDescription( x509.ObjectIdentifier("2.999.7"), x509.UniformResourceIdentifier( - u"gopher://info-mac-archive" + "gopher://info-mac-archive" ), ), ] @@ -3101,12 +3075,12 @@ def test_aia_ocsp_ca_issuers(self, backend): [ x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://gv.symcd.com"), + x509.UniformResourceIdentifier("http://gv.symcd.com"), ), x509.AccessDescription( AuthorityInformationAccessOID.CA_ISSUERS, x509.UniformResourceIdentifier( - u"http://gv.symcb.com/gv.crt" + "http://gv.symcb.com/gv.crt" ), ), ] @@ -3128,11 +3102,11 @@ def test_aia_multiple_ocsp_ca_issuers(self, backend): [ x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp.domain.com"), + x509.UniformResourceIdentifier("http://ocsp.domain.com"), ), x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp2.domain.com"), + x509.UniformResourceIdentifier("http://ocsp2.domain.com"), ), x509.AccessDescription( AuthorityInformationAccessOID.CA_ISSUERS, @@ -3140,10 +3114,10 @@ def test_aia_multiple_ocsp_ca_issuers(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"myCN" + NameOID.COMMON_NAME, "myCN" ), x509.NameAttribute( - NameOID.ORGANIZATION_NAME, u"some Org" + NameOID.ORGANIZATION_NAME, "some Org" ), ] ) @@ -3168,7 +3142,7 @@ def test_aia_ocsp_only(self, backend): [ x509.AccessDescription( AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier(u"http://ocsp.domain.com"), + x509.UniformResourceIdentifier("http://ocsp.domain.com"), ), ] ) @@ -3193,10 +3167,10 @@ def test_aia_ca_issuers_only(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"myCN" + NameOID.COMMON_NAME, "myCN" ), x509.NameAttribute( - NameOID.ORGANIZATION_NAME, u"some Org" + NameOID.ORGANIZATION_NAME, "some Org" ), ] ) @@ -3246,9 +3220,9 @@ def test_aki_all_fields(self, backend): x509.DirectoryName( x509.Name( [ - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA"), x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io" + NameOID.COMMON_NAME, "cryptography.io" ), ] ) @@ -3275,9 +3249,9 @@ def test_aki_no_keyid(self, backend): x509.DirectoryName( x509.Name( [ - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA"), x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io" + NameOID.COMMON_NAME, "cryptography.io" ), ] ) @@ -3332,7 +3306,7 @@ def test_ipaddress_wrong_type(self): with pytest.raises(TypeError): x509.NameConstraints( permitted_subtrees=[ - x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1")) + x509.IPAddress(ipaddress.IPv4Address("127.0.0.1")) ], excluded_subtrees=None, ) @@ -3341,13 +3315,13 @@ def test_ipaddress_wrong_type(self): x509.NameConstraints( permitted_subtrees=None, excluded_subtrees=[ - x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1")) + x509.IPAddress(ipaddress.IPv4Address("127.0.0.1")) ], ) def test_ipaddress_allowed_type(self): - permitted = [x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.0/29"))] - excluded = [x509.IPAddress(ipaddress.IPv4Network(u"10.10.0.0/24"))] + permitted = [x509.IPAddress(ipaddress.IPv4Network("192.168.0.0/29"))] + excluded = [x509.IPAddress(ipaddress.IPv4Network("10.10.0.0/24"))] nc = x509.NameConstraints( permitted_subtrees=permitted, excluded_subtrees=excluded ) @@ -3367,7 +3341,7 @@ def test_no_subtrees(self): x509.NameConstraints(None, None) def test_permitted_none(self): - excluded = [x509.DNSName(u"name.local")] + excluded = [x509.DNSName("name.local")] nc = x509.NameConstraints( permitted_subtrees=None, excluded_subtrees=excluded ) @@ -3375,7 +3349,7 @@ def test_permitted_none(self): assert nc.excluded_subtrees is not None def test_excluded_none(self): - permitted = [x509.DNSName(u"name.local")] + permitted = [x509.DNSName("name.local")] nc = x509.NameConstraints( permitted_subtrees=permitted, excluded_subtrees=None ) @@ -3383,13 +3357,13 @@ def test_excluded_none(self): assert nc.excluded_subtrees is None def test_iter_input(self): - subtrees = [x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.0/24"))] + subtrees = [x509.IPAddress(ipaddress.IPv4Network("192.168.0.0/24"))] nc = x509.NameConstraints(iter(subtrees), iter(subtrees)) assert list(nc.permitted_subtrees) == subtrees assert list(nc.excluded_subtrees) == subtrees def test_repr(self): - permitted = [x509.DNSName(u"name.local"), x509.DNSName(u"name2.local")] + permitted = [x509.DNSName("name.local"), x509.DNSName("name2.local")] nc = x509.NameConstraints( permitted_subtrees=permitted, excluded_subtrees=None ) @@ -3401,27 +3375,27 @@ def test_repr(self): def test_eq(self): nc = x509.NameConstraints( - permitted_subtrees=[x509.DNSName(u"name.local")], - excluded_subtrees=[x509.DNSName(u"name2.local")], + permitted_subtrees=[x509.DNSName("name.local")], + excluded_subtrees=[x509.DNSName("name2.local")], ) nc2 = x509.NameConstraints( - permitted_subtrees=[x509.DNSName(u"name.local")], - excluded_subtrees=[x509.DNSName(u"name2.local")], + permitted_subtrees=[x509.DNSName("name.local")], + excluded_subtrees=[x509.DNSName("name2.local")], ) assert nc == nc2 def test_ne(self): nc = x509.NameConstraints( - permitted_subtrees=[x509.DNSName(u"name.local")], - excluded_subtrees=[x509.DNSName(u"name2.local")], + permitted_subtrees=[x509.DNSName("name.local")], + excluded_subtrees=[x509.DNSName("name2.local")], ) nc2 = x509.NameConstraints( - permitted_subtrees=[x509.DNSName(u"name.local")], + permitted_subtrees=[x509.DNSName("name.local")], excluded_subtrees=None, ) nc3 = x509.NameConstraints( permitted_subtrees=None, - excluded_subtrees=[x509.DNSName(u"name2.local")], + excluded_subtrees=[x509.DNSName("name2.local")], ) assert nc != nc2 @@ -3430,20 +3404,20 @@ def test_ne(self): def test_hash(self): nc = x509.NameConstraints( - permitted_subtrees=[x509.DNSName(u"name.local")], - excluded_subtrees=[x509.DNSName(u"name2.local")], + permitted_subtrees=[x509.DNSName("name.local")], + excluded_subtrees=[x509.DNSName("name2.local")], ) nc2 = x509.NameConstraints( - permitted_subtrees=[x509.DNSName(u"name.local")], - excluded_subtrees=[x509.DNSName(u"name2.local")], + permitted_subtrees=[x509.DNSName("name.local")], + excluded_subtrees=[x509.DNSName("name2.local")], ) nc3 = x509.NameConstraints( - permitted_subtrees=[x509.DNSName(u"name.local")], + permitted_subtrees=[x509.DNSName("name.local")], excluded_subtrees=None, ) nc4 = x509.NameConstraints( permitted_subtrees=None, - excluded_subtrees=[x509.DNSName(u"name.local")], + excluded_subtrees=[x509.DNSName("name.local")], ) assert hash(nc) == hash(nc2) assert hash(nc) != hash(nc3) @@ -3463,11 +3437,11 @@ def test_permitted_excluded(self, backend): ExtensionOID.NAME_CONSTRAINTS ).value assert nc == x509.NameConstraints( - permitted_subtrees=[x509.DNSName(u"zombo.local")], + permitted_subtrees=[x509.DNSName("zombo.local")], excluded_subtrees=[ x509.DirectoryName( x509.Name( - [x509.NameAttribute(NameOID.COMMON_NAME, u"zombo")] + [x509.NameAttribute(NameOID.COMMON_NAME, "zombo")] ) ) ], @@ -3483,7 +3457,7 @@ def test_permitted(self, backend): ExtensionOID.NAME_CONSTRAINTS ).value assert nc == x509.NameConstraints( - permitted_subtrees=[x509.DNSName(u"zombo.local")], + permitted_subtrees=[x509.DNSName("zombo.local")], excluded_subtrees=None, ) @@ -3498,8 +3472,8 @@ def test_permitted_with_leading_period(self, backend): ).value assert nc == x509.NameConstraints( permitted_subtrees=[ - x509.DNSName(u".cryptography.io"), - x509.UniformResourceIdentifier(u"ftp://cryptography.test"), + x509.DNSName(".cryptography.io"), + x509.UniformResourceIdentifier("ftp://cryptography.test"), ], excluded_subtrees=None, ) @@ -3516,8 +3490,8 @@ def test_excluded_with_leading_period(self, backend): assert nc == x509.NameConstraints( permitted_subtrees=None, excluded_subtrees=[ - x509.DNSName(u".cryptography.io"), - x509.UniformResourceIdentifier(u"gopher://cryptography.test"), + x509.DNSName(".cryptography.io"), + x509.UniformResourceIdentifier("gopher://cryptography.test"), ], ) @@ -3532,12 +3506,12 @@ def test_permitted_excluded_with_ips(self, backend): ).value assert nc == x509.NameConstraints( permitted_subtrees=[ - x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.0/24")), - x509.IPAddress(ipaddress.IPv6Network(u"FF:0:0:0:0:0:0:0/96")), + x509.IPAddress(ipaddress.IPv4Network("192.168.0.0/24")), + x509.IPAddress(ipaddress.IPv6Network("FF:0:0:0:0:0:0:0/96")), ], excluded_subtrees=[ - x509.DNSName(u".domain.com"), - x509.UniformResourceIdentifier(u"http://test.local"), + x509.DNSName(".domain.com"), + x509.UniformResourceIdentifier("http://test.local"), ], ) @@ -3552,8 +3526,8 @@ def test_single_ip_netmask(self, backend): ).value assert nc == x509.NameConstraints( permitted_subtrees=[ - x509.IPAddress(ipaddress.IPv6Network(u"FF:0:0:0:0:0:0:0/128")), - x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.1/32")), + x509.IPAddress(ipaddress.IPv6Network("FF:0:0:0:0:0:0:0/128")), + x509.IPAddress(ipaddress.IPv4Network("192.168.0.1/32")), ], excluded_subtrees=None, ) @@ -3571,9 +3545,9 @@ def test_invalid_netmask(self, backend): def test_certbuilder(self, backend): permitted = [ - u".example.org", - u".xn--4ca7aey.example.com", - u"foobar.example.net", + ".example.org", + ".xn--4ca7aey.example.com", + "foobar.example.net", ] private_key = RSA_KEY_2048.private_key(backend) builder = _make_certbuilder(private_key) @@ -3615,7 +3589,7 @@ def test_crl_issuer_not_general_names(self): def test_reason_not_reasonflags(self): with pytest.raises(TypeError): x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"http://crypt.og/crl")], + [x509.UniformResourceIdentifier("http://crypt.og/crl")], None, frozenset(["notreasonflags"]), None, @@ -3624,7 +3598,7 @@ def test_reason_not_reasonflags(self): def test_reason_not_frozenset(self): with pytest.raises(TypeError): x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"http://crypt.og/crl")], + [x509.UniformResourceIdentifier("http://crypt.og/crl")], None, [x509.ReasonFlags.ca_compromise], None, @@ -3633,7 +3607,7 @@ def test_reason_not_frozenset(self): def test_disallowed_reasons(self): with pytest.raises(ValueError): x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"http://crypt.og/crl")], + [x509.UniformResourceIdentifier("http://crypt.og/crl")], None, frozenset([x509.ReasonFlags.unspecified]), None, @@ -3641,7 +3615,7 @@ def test_disallowed_reasons(self): with pytest.raises(ValueError): x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"http://crypt.og/crl")], + [x509.UniformResourceIdentifier("http://crypt.og/crl")], None, frozenset([x509.ReasonFlags.remove_from_crl]), None, @@ -3655,7 +3629,7 @@ def test_reason_only(self): def test_eq(self): dp = x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"http://crypt.og/crl")], + [x509.UniformResourceIdentifier("http://crypt.og/crl")], None, frozenset([x509.ReasonFlags.superseded]), [ @@ -3663,7 +3637,7 @@ def test_eq(self): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"Important CA" + NameOID.COMMON_NAME, "Important CA" ) ] ) @@ -3671,7 +3645,7 @@ def test_eq(self): ], ) dp2 = x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"http://crypt.og/crl")], + [x509.UniformResourceIdentifier("http://crypt.og/crl")], None, frozenset([x509.ReasonFlags.superseded]), [ @@ -3679,7 +3653,7 @@ def test_eq(self): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"Important CA" + NameOID.COMMON_NAME, "Important CA" ) ] ) @@ -3690,7 +3664,7 @@ def test_eq(self): def test_ne(self): dp = x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"http://crypt.og/crl")], + [x509.UniformResourceIdentifier("http://crypt.og/crl")], None, frozenset([x509.ReasonFlags.superseded]), [ @@ -3698,7 +3672,7 @@ def test_ne(self): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"Important CA" + NameOID.COMMON_NAME, "Important CA" ) ] ) @@ -3706,7 +3680,7 @@ def test_ne(self): ], ) dp2 = x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"http://crypt.og/crl")], + [x509.UniformResourceIdentifier("http://crypt.og/crl")], None, None, None, @@ -3715,11 +3689,11 @@ def test_ne(self): assert dp != object() def test_iter_input(self): - name = [x509.UniformResourceIdentifier(u"http://crypt.og/crl")] + name = [x509.UniformResourceIdentifier("http://crypt.og/crl")] issuer = [ x509.DirectoryName( x509.Name( - [x509.NameAttribute(NameOID.COMMON_NAME, u"Important CA")] + [x509.NameAttribute(NameOID.COMMON_NAME, "Important CA")] ) ) ] @@ -3736,7 +3710,7 @@ def test_repr(self): dp = x509.DistributionPoint( None, x509.RelativeDistinguishedName( - [x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")] + [x509.NameAttribute(NameOID.COMMON_NAME, "myCN")] ), frozenset([x509.ReasonFlags.ca_compromise]), [ @@ -3744,7 +3718,7 @@ def test_repr(self): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"Important CA" + NameOID.COMMON_NAME, "Important CA" ) ] ) @@ -3760,7 +3734,7 @@ def test_repr(self): def test_hash(self): dp = x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"http://crypt.og/crl")], + [x509.UniformResourceIdentifier("http://crypt.og/crl")], None, frozenset([x509.ReasonFlags.superseded]), [ @@ -3768,7 +3742,7 @@ def test_hash(self): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"Important CA" + NameOID.COMMON_NAME, "Important CA" ) ] ) @@ -3776,7 +3750,7 @@ def test_hash(self): ], ) dp2 = x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"http://crypt.og/crl")], + [x509.UniformResourceIdentifier("http://crypt.og/crl")], None, frozenset([x509.ReasonFlags.superseded]), [ @@ -3784,7 +3758,7 @@ def test_hash(self): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"Important CA" + NameOID.COMMON_NAME, "Important CA" ) ] ) @@ -3794,7 +3768,7 @@ def test_hash(self): dp3 = x509.DistributionPoint( None, x509.RelativeDistinguishedName( - [x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")] + [x509.NameAttribute(NameOID.COMMON_NAME, "myCN")] ), None, None, @@ -3812,7 +3786,7 @@ def test_iter_len(self): fcrl = x509.FreshestCRL( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"http://domain")], + [x509.UniformResourceIdentifier("http://domain")], None, None, None, @@ -3822,7 +3796,7 @@ def test_iter_len(self): assert len(fcrl) == 1 assert list(fcrl) == [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"http://domain")], + [x509.UniformResourceIdentifier("http://domain")], None, None, None, @@ -3832,7 +3806,7 @@ def test_iter_len(self): def test_iter_input(self): points = [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"http://domain")], + [x509.UniformResourceIdentifier("http://domain")], None, None, None, @@ -3845,7 +3819,7 @@ def test_repr(self): fcrl = x509.FreshestCRL( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset([x509.ReasonFlags.key_compromise]), None, @@ -3863,7 +3837,7 @@ def test_eq(self): fcrl = x509.FreshestCRL( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset( [ @@ -3871,14 +3845,14 @@ def test_eq(self): x509.ReasonFlags.ca_compromise, ] ), - [x509.UniformResourceIdentifier(u"uri://thing")], + [x509.UniformResourceIdentifier("uri://thing")], ), ] ) fcrl2 = x509.FreshestCRL( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset( [ @@ -3886,7 +3860,7 @@ def test_eq(self): x509.ReasonFlags.ca_compromise, ] ), - [x509.UniformResourceIdentifier(u"uri://thing")], + [x509.UniformResourceIdentifier("uri://thing")], ), ] ) @@ -3896,7 +3870,7 @@ def test_ne(self): fcrl = x509.FreshestCRL( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset( [ @@ -3904,14 +3878,14 @@ def test_ne(self): x509.ReasonFlags.ca_compromise, ] ), - [x509.UniformResourceIdentifier(u"uri://thing")], + [x509.UniformResourceIdentifier("uri://thing")], ), ] ) fcrl2 = x509.FreshestCRL( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain2")], + [x509.UniformResourceIdentifier("ftp://domain2")], None, frozenset( [ @@ -3919,24 +3893,24 @@ def test_ne(self): x509.ReasonFlags.ca_compromise, ] ), - [x509.UniformResourceIdentifier(u"uri://thing")], + [x509.UniformResourceIdentifier("uri://thing")], ), ] ) fcrl3 = x509.FreshestCRL( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset([x509.ReasonFlags.key_compromise]), - [x509.UniformResourceIdentifier(u"uri://thing")], + [x509.UniformResourceIdentifier("uri://thing")], ), ] ) fcrl4 = x509.FreshestCRL( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset( [ @@ -3944,7 +3918,7 @@ def test_ne(self): x509.ReasonFlags.ca_compromise, ] ), - [x509.UniformResourceIdentifier(u"uri://thing2")], + [x509.UniformResourceIdentifier("uri://thing2")], ), ] ) @@ -3957,7 +3931,7 @@ def test_hash(self): fcrl = x509.FreshestCRL( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset( [ @@ -3965,14 +3939,14 @@ def test_hash(self): x509.ReasonFlags.ca_compromise, ] ), - [x509.UniformResourceIdentifier(u"uri://thing")], + [x509.UniformResourceIdentifier("uri://thing")], ), ] ) fcrl2 = x509.FreshestCRL( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset( [ @@ -3980,17 +3954,17 @@ def test_hash(self): x509.ReasonFlags.ca_compromise, ] ), - [x509.UniformResourceIdentifier(u"uri://thing")], + [x509.UniformResourceIdentifier("uri://thing")], ), ] ) fcrl3 = x509.FreshestCRL( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset([x509.ReasonFlags.key_compromise]), - [x509.UniformResourceIdentifier(u"uri://thing")], + [x509.UniformResourceIdentifier("uri://thing")], ), ] ) @@ -4004,31 +3978,31 @@ def test_indexing(self): None, None, None, - [x509.UniformResourceIdentifier(u"uri://thing")], + [x509.UniformResourceIdentifier("uri://thing")], ), x509.DistributionPoint( None, None, None, - [x509.UniformResourceIdentifier(u"uri://thing2")], + [x509.UniformResourceIdentifier("uri://thing2")], ), x509.DistributionPoint( None, None, None, - [x509.UniformResourceIdentifier(u"uri://thing3")], + [x509.UniformResourceIdentifier("uri://thing3")], ), x509.DistributionPoint( None, None, None, - [x509.UniformResourceIdentifier(u"uri://thing4")], + [x509.UniformResourceIdentifier("uri://thing4")], ), x509.DistributionPoint( None, None, None, - [x509.UniformResourceIdentifier(u"uri://thing5")], + [x509.UniformResourceIdentifier("uri://thing5")], ), ] ) @@ -4045,13 +4019,13 @@ def test_iter_len(self): cdp = x509.CRLDistributionPoints( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"http://domain")], + [x509.UniformResourceIdentifier("http://domain")], None, None, None, ), x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset( [ @@ -4066,13 +4040,13 @@ def test_iter_len(self): assert len(cdp) == 2 assert list(cdp) == [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"http://domain")], + [x509.UniformResourceIdentifier("http://domain")], None, None, None, ), x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset( [ @@ -4087,7 +4061,7 @@ def test_iter_len(self): def test_iter_input(self): points = [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"http://domain")], + [x509.UniformResourceIdentifier("http://domain")], None, None, None, @@ -4100,7 +4074,7 @@ def test_repr(self): cdp = x509.CRLDistributionPoints( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset([x509.ReasonFlags.key_compromise]), None, @@ -4118,7 +4092,7 @@ def test_eq(self): cdp = x509.CRLDistributionPoints( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset( [ @@ -4126,14 +4100,14 @@ def test_eq(self): x509.ReasonFlags.ca_compromise, ] ), - [x509.UniformResourceIdentifier(u"uri://thing")], + [x509.UniformResourceIdentifier("uri://thing")], ), ] ) cdp2 = x509.CRLDistributionPoints( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset( [ @@ -4141,7 +4115,7 @@ def test_eq(self): x509.ReasonFlags.ca_compromise, ] ), - [x509.UniformResourceIdentifier(u"uri://thing")], + [x509.UniformResourceIdentifier("uri://thing")], ), ] ) @@ -4151,7 +4125,7 @@ def test_ne(self): cdp = x509.CRLDistributionPoints( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset( [ @@ -4159,14 +4133,14 @@ def test_ne(self): x509.ReasonFlags.ca_compromise, ] ), - [x509.UniformResourceIdentifier(u"uri://thing")], + [x509.UniformResourceIdentifier("uri://thing")], ), ] ) cdp2 = x509.CRLDistributionPoints( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain2")], + [x509.UniformResourceIdentifier("ftp://domain2")], None, frozenset( [ @@ -4174,24 +4148,24 @@ def test_ne(self): x509.ReasonFlags.ca_compromise, ] ), - [x509.UniformResourceIdentifier(u"uri://thing")], + [x509.UniformResourceIdentifier("uri://thing")], ), ] ) cdp3 = x509.CRLDistributionPoints( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset([x509.ReasonFlags.key_compromise]), - [x509.UniformResourceIdentifier(u"uri://thing")], + [x509.UniformResourceIdentifier("uri://thing")], ), ] ) cdp4 = x509.CRLDistributionPoints( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset( [ @@ -4199,7 +4173,7 @@ def test_ne(self): x509.ReasonFlags.ca_compromise, ] ), - [x509.UniformResourceIdentifier(u"uri://thing2")], + [x509.UniformResourceIdentifier("uri://thing2")], ), ] ) @@ -4212,7 +4186,7 @@ def test_hash(self): cdp = x509.CRLDistributionPoints( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset( [ @@ -4220,14 +4194,14 @@ def test_hash(self): x509.ReasonFlags.ca_compromise, ] ), - [x509.UniformResourceIdentifier(u"uri://thing")], + [x509.UniformResourceIdentifier("uri://thing")], ), ] ) cdp2 = x509.CRLDistributionPoints( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset( [ @@ -4235,17 +4209,17 @@ def test_hash(self): x509.ReasonFlags.ca_compromise, ] ), - [x509.UniformResourceIdentifier(u"uri://thing")], + [x509.UniformResourceIdentifier("uri://thing")], ), ] ) cdp3 = x509.CRLDistributionPoints( [ x509.DistributionPoint( - [x509.UniformResourceIdentifier(u"ftp://domain")], + [x509.UniformResourceIdentifier("ftp://domain")], None, frozenset([x509.ReasonFlags.key_compromise]), - [x509.UniformResourceIdentifier(u"uri://thing")], + [x509.UniformResourceIdentifier("uri://thing")], ), ] ) @@ -4259,31 +4233,31 @@ def test_indexing(self): None, None, None, - [x509.UniformResourceIdentifier(u"uri://thing")], + [x509.UniformResourceIdentifier("uri://thing")], ), x509.DistributionPoint( None, None, None, - [x509.UniformResourceIdentifier(u"uri://thing2")], + [x509.UniformResourceIdentifier("uri://thing2")], ), x509.DistributionPoint( None, None, None, - [x509.UniformResourceIdentifier(u"uri://thing3")], + [x509.UniformResourceIdentifier("uri://thing3")], ), x509.DistributionPoint( None, None, None, - [x509.UniformResourceIdentifier(u"uri://thing4")], + [x509.UniformResourceIdentifier("uri://thing4")], ), x509.DistributionPoint( None, None, None, - [x509.UniformResourceIdentifier(u"uri://thing5")], + [x509.UniformResourceIdentifier("uri://thing5")], ), ] ) @@ -4315,19 +4289,19 @@ def test_fullname_and_crl_issuer(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COUNTRY_NAME, u"US" + NameOID.COUNTRY_NAME, "US" ), x509.NameAttribute( NameOID.ORGANIZATION_NAME, - u"Test Certificates 2011", + "Test Certificates 2011", ), x509.NameAttribute( NameOID.ORGANIZATIONAL_UNIT_NAME, - u"indirectCRL CA3 cRLIssuer", + "indirectCRL CA3 cRLIssuer", ), x509.NameAttribute( NameOID.COMMON_NAME, - u"indirect CRL for indirectCRL CA3", + "indirect CRL for indirectCRL CA3", ), ] ) @@ -4340,15 +4314,15 @@ def test_fullname_and_crl_issuer(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COUNTRY_NAME, u"US" + NameOID.COUNTRY_NAME, "US" ), x509.NameAttribute( NameOID.ORGANIZATION_NAME, - u"Test Certificates 2011", + "Test Certificates 2011", ), x509.NameAttribute( NameOID.ORGANIZATIONAL_UNIT_NAME, - u"indirectCRL CA3 cRLIssuer", + "indirectCRL CA3 cRLIssuer", ), ] ) @@ -4379,7 +4353,7 @@ def test_relativename_and_crl_issuer(self, backend): [ x509.NameAttribute( NameOID.COMMON_NAME, - u"indirect CRL for indirectCRL CA3", + "indirect CRL for indirectCRL CA3", ), ] ), @@ -4389,15 +4363,15 @@ def test_relativename_and_crl_issuer(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COUNTRY_NAME, u"US" + NameOID.COUNTRY_NAME, "US" ), x509.NameAttribute( NameOID.ORGANIZATION_NAME, - u"Test Certificates 2011", + "Test Certificates 2011", ), x509.NameAttribute( NameOID.ORGANIZATIONAL_UNIT_NAME, - u"indirectCRL CA3 cRLIssuer", + "indirectCRL CA3 cRLIssuer", ), ] ) @@ -4425,7 +4399,7 @@ def test_fullname_crl_issuer_reasons(self, backend): x509.DistributionPoint( full_name=[ x509.UniformResourceIdentifier( - u"http://myhost.com/myca.crl" + "http://myhost.com/myca.crl" ) ], relative_name=None, @@ -4440,13 +4414,13 @@ def test_fullname_crl_issuer_reasons(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COUNTRY_NAME, u"US" + NameOID.COUNTRY_NAME, "US" ), x509.NameAttribute( - NameOID.ORGANIZATION_NAME, u"PyCA" + NameOID.ORGANIZATION_NAME, "PyCA" ), x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography CA" + NameOID.COMMON_NAME, "cryptography CA" ), ] ) @@ -4472,7 +4446,7 @@ def test_all_reasons(self, backend): x509.DistributionPoint( full_name=[ x509.UniformResourceIdentifier( - u"http://domain.com/some.crl" + "http://domain.com/some.crl" ) ], relative_name=None, @@ -4509,7 +4483,7 @@ def test_single_reason(self, backend): x509.DistributionPoint( full_name=[ x509.UniformResourceIdentifier( - u"http://domain.com/some.crl" + "http://domain.com/some.crl" ) ], relative_name=None, @@ -4541,7 +4515,7 @@ def test_crl_issuer_only(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography CA" + NameOID.COMMON_NAME, "cryptography CA" ), ] ) @@ -4567,7 +4541,7 @@ def test_crl_empty_hostname(self, backend): x509.DistributionPoint( full_name=[ x509.UniformResourceIdentifier( - u"ldap:///CN=A,OU=B,dc=C,DC=D?E?F?G?H=I" + "ldap:///CN=A,OU=B,dc=C,DC=D?E?F?G?H=I" ) ], relative_name=None, @@ -4594,10 +4568,10 @@ def test_vector(self, backend): x509.DistributionPoint( full_name=[ x509.UniformResourceIdentifier( - u"http://myhost.com/myca.crl" + "http://myhost.com/myca.crl" ), x509.UniformResourceIdentifier( - u"http://backup.myhost.com/myca.crl" + "http://backup.myhost.com/myca.crl" ), ], relative_name=None, @@ -4612,10 +4586,10 @@ def test_vector(self, backend): x509.Name( [ x509.NameAttribute( - NameOID.COUNTRY_NAME, u"US" + NameOID.COUNTRY_NAME, "US" ), x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography CA" + NameOID.COMMON_NAME, "cryptography CA" ), ] ) @@ -4720,7 +4694,7 @@ class TestIssuingDistributionPointExtension(object): x509.IssuingDistributionPoint( full_name=[ x509.UniformResourceIdentifier( - u"http://myhost.com/myca.crl" + "http://myhost.com/myca.crl" ) ], relative_name=None, @@ -4736,7 +4710,7 @@ class TestIssuingDistributionPointExtension(object): x509.IssuingDistributionPoint( full_name=[ x509.UniformResourceIdentifier( - u"http://myhost.com/myca.crl" + "http://myhost.com/myca.crl" ) ], relative_name=None, @@ -4752,7 +4726,7 @@ class TestIssuingDistributionPointExtension(object): x509.IssuingDistributionPoint( full_name=[ x509.UniformResourceIdentifier( - u"http://myhost.com/myca.crl" + "http://myhost.com/myca.crl" ) ], relative_name=None, @@ -4768,7 +4742,7 @@ class TestIssuingDistributionPointExtension(object): x509.IssuingDistributionPoint( full_name=[ x509.UniformResourceIdentifier( - u"http://myhost.com/myca.crl" + "http://myhost.com/myca.crl" ) ], relative_name=None, @@ -4787,7 +4761,7 @@ class TestIssuingDistributionPointExtension(object): [ x509.NameAttribute( oid=x509.NameOID.ORGANIZATION_NAME, - value=u"PyCA", + value="PyCA", ) ] ), @@ -4820,7 +4794,7 @@ class TestIssuingDistributionPointExtension(object): [ x509.NameAttribute( oid=x509.NameOID.ORGANIZATION_NAME, - value=u"PyCA", + value="PyCA", ) ] ), @@ -4850,7 +4824,7 @@ class TestIssuingDistributionPointExtension(object): [ x509.NameAttribute( oid=x509.NameOID.ORGANIZATION_NAME, - value=u"PyCA", + value="PyCA", ) ] ), @@ -4988,7 +4962,7 @@ def test_eq(self): relative_name=x509.RelativeDistinguishedName( [ x509.NameAttribute( - oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA" + oid=x509.NameOID.ORGANIZATION_NAME, value="PyCA" ) ] ), @@ -5003,7 +4977,7 @@ def test_eq(self): relative_name=x509.RelativeDistinguishedName( [ x509.NameAttribute( - oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA" + oid=x509.NameOID.ORGANIZATION_NAME, value="PyCA" ) ] ), @@ -5021,7 +4995,7 @@ def test_ne(self): relative_name=x509.RelativeDistinguishedName( [ x509.NameAttribute( - oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA" + oid=x509.NameOID.ORGANIZATION_NAME, value="PyCA" ) ] ), @@ -5036,7 +5010,7 @@ def test_ne(self): relative_name=x509.RelativeDistinguishedName( [ x509.NameAttribute( - oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA" + oid=x509.NameOID.ORGANIZATION_NAME, value="PyCA" ) ] ), @@ -5056,7 +5030,7 @@ def test_hash(self): x509.RelativeDistinguishedName( [ x509.NameAttribute( - oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA" + oid=x509.NameOID.ORGANIZATION_NAME, value="PyCA" ) ] ), @@ -5077,7 +5051,7 @@ def test_hash(self): x509.IssuingDistributionPoint( full_name=[ x509.UniformResourceIdentifier( - u"http://myhost.com/myca.crl" + "http://myhost.com/myca.crl" ) ], relative_name=None, @@ -5090,7 +5064,7 @@ def test_hash(self): x509.IssuingDistributionPoint( full_name=[ x509.UniformResourceIdentifier( - u"http://myhost.com/myca.crl" + "http://myhost.com/myca.crl" ) ], relative_name=None, @@ -5103,7 +5077,7 @@ def test_hash(self): x509.IssuingDistributionPoint( full_name=[ x509.UniformResourceIdentifier( - u"http://myhost.com/myca.crl" + "http://myhost.com/myca.crl" ) ], relative_name=None, @@ -5116,7 +5090,7 @@ def test_hash(self): x509.IssuingDistributionPoint( full_name=[ x509.UniformResourceIdentifier( - u"http://myhost.com/myca.crl" + "http://myhost.com/myca.crl" ) ], relative_name=None, @@ -5131,7 +5105,7 @@ def test_hash(self): relative_name=x509.RelativeDistinguishedName( [ x509.NameAttribute( - oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA" + oid=x509.NameOID.ORGANIZATION_NAME, value="PyCA" ) ] ), @@ -5155,10 +5129,10 @@ def test_hash(self): relative_name=x509.RelativeDistinguishedName( [ x509.NameAttribute( - oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA" + oid=x509.NameOID.ORGANIZATION_NAME, value="PyCA" ), x509.NameAttribute( - oid=x509.NameOID.COMMON_NAME, value=u"cryptography" + oid=x509.NameOID.COMMON_NAME, value="cryptography" ), ] ), @@ -5181,7 +5155,7 @@ def test_hash(self): relative_name=x509.RelativeDistinguishedName( [ x509.NameAttribute( - oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA" + oid=x509.NameOID.ORGANIZATION_NAME, value="PyCA" ) ] ), @@ -5203,7 +5177,7 @@ def test_generate(self, idp, backend): x509.Name( [ x509.NameAttribute( - NameOID.COMMON_NAME, u"cryptography.io CA" + NameOID.COMMON_NAME, "cryptography.io CA" ) ] ) diff --git a/tests/x509/test_x509_revokedcertbuilder.py b/tests/x509/test_x509_revokedcertbuilder.py index 0db6d2a6f7de..301788ca5920 100644 --- a/tests/x509/test_x509_revokedcertbuilder.py +++ b/tests/x509/test_x509_revokedcertbuilder.py @@ -145,7 +145,7 @@ def test_create_revoked(self, backend): [ x509.InvalidityDate(datetime.datetime(2015, 1, 1, 0, 0)), x509.CRLReason(x509.ReasonFlags.ca_compromise), - x509.CertificateIssuer([x509.DNSName(u"cryptography.io")]), + x509.CertificateIssuer([x509.DNSName("cryptography.io")]), ], ) @pytest.mark.requires_backend_interface(interface=X509Backend) @@ -177,7 +177,7 @@ def test_add_multiple_extensions(self, backend): datetime.datetime(2015, 1, 1, 0, 0) ) certificate_issuer = x509.CertificateIssuer( - [x509.DNSName(u"cryptography.io")] + [x509.DNSName("cryptography.io")] ) crl_reason = x509.CRLReason(x509.ReasonFlags.aa_compromise) builder = ( diff --git a/vectors/setup.py b/vectors/setup.py index 482c01b35a8f..884148286fe7 100644 --- a/vectors/setup.py +++ b/vectors/setup.py @@ -15,7 +15,7 @@ about = {} with open(os.path.join(base_dir, "cryptography_vectors", "__about__.py")) as f: - exec (f.read(), about) + exec(f.read(), about) setup( From b3540ec4a33d4a902bfab00c2817eea8176dc298 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 9 Dec 2020 01:20:32 -0500 Subject: [PATCH 0004/2380] Write a bunch of primitives tests as subtests for performance (#5246) --- setup.py | 3 +- tests/hazmat/primitives/utils.py | 72 ++++++++++++++++++-------------- 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/setup.py b/setup.py index ea0df349e48e..82b84ccf50ea 100644 --- a/setup.py +++ b/setup.py @@ -83,7 +83,8 @@ setup_requires=setup_requirements, extras_require={ "test": [ - "pytest>=3.6.0,!=3.9.0,!=3.9.1,!=3.9.2", + "pytest>=4.4.0", + "pytest-subtests", "pretend", "iso8601", "pytz", diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py index 3f1eff66e00f..118b55951709 100644 --- a/tests/hazmat/primitives/utils.py +++ b/tests/hazmat/primitives/utils.py @@ -5,7 +5,6 @@ from __future__ import absolute_import, division, print_function import binascii -import itertools import os import pytest @@ -46,9 +45,10 @@ def generate_encrypt_test( ): all_params = _load_all_params(path, file_names, param_loader) - @pytest.mark.parametrize("params", all_params) - def test_encryption(self, backend, params): - encrypt_test(backend, cipher_factory, mode_factory, params) + def test_encryption(self, backend, subtests): + for params in all_params: + with subtests.test(): + encrypt_test(backend, cipher_factory, mode_factory, params) return test_encryption @@ -78,9 +78,10 @@ def generate_aead_test( ): all_params = _load_all_params(path, file_names, param_loader) - @pytest.mark.parametrize("params", all_params) - def test_aead(self, backend, params): - aead_test(backend, cipher_factory, mode_factory, params) + def test_aead(self, backend, subtests): + for params in all_params: + with subtests.test(): + aead_test(backend, cipher_factory, mode_factory, params) return test_aead @@ -152,9 +153,10 @@ def generate_stream_encryption_test( ): all_params = _load_all_params(path, file_names, param_loader) - @pytest.mark.parametrize("params", all_params) - def test_stream_encryption(self, backend, params): - stream_encryption_test(backend, cipher_factory, params) + def test_stream_encryption(self, backend, subtests): + for params in all_params: + with subtests.test(): + stream_encryption_test(backend, cipher_factory, params) return test_stream_encryption @@ -180,9 +182,10 @@ def stream_encryption_test(backend, cipher_factory, params): def generate_hash_test(param_loader, path, file_names, hash_cls): all_params = _load_all_params(path, file_names, param_loader) - @pytest.mark.parametrize("params", all_params) - def test_hash(self, backend, params): - hash_test(backend, hash_cls, params) + def test_hash(self, backend, subtests): + for params in all_params: + with subtests.test(): + hash_test(backend, hash_cls, params) return test_hash @@ -234,9 +237,10 @@ def base_hmac_test(backend, algorithm): def generate_hmac_test(param_loader, path, file_names, algorithm): all_params = _load_all_params(path, file_names, param_loader) - @pytest.mark.parametrize("params", all_params) - def test_hmac(self, backend, params): - hmac_test(backend, algorithm, params) + def test_hmac(self, backend, subtests): + for params in all_params: + with subtests.test(): + hmac_test(backend, algorithm, params) return test_hmac @@ -251,9 +255,10 @@ def hmac_test(backend, algorithm, params): def generate_pbkdf2_test(param_loader, path, file_names, algorithm): all_params = _load_all_params(path, file_names, param_loader) - @pytest.mark.parametrize("params", all_params) - def test_pbkdf2(self, backend, params): - pbkdf2_test(backend, algorithm, params) + def test_pbkdf2(self, backend, subtests): + for params in all_params: + with subtests.test(): + pbkdf2_test(backend, algorithm, params) return test_pbkdf2 @@ -383,13 +388,14 @@ def hkdf_expand_test(backend, algorithm, params): def generate_hkdf_test(param_loader, path, file_names, algorithm): all_params = _load_all_params(path, file_names, param_loader) - all_tests = [hkdf_extract_test, hkdf_expand_test, hkdf_derive_test] - - @pytest.mark.parametrize( - ("params", "hkdf_test"), itertools.product(all_params, all_tests) - ) - def test_hkdf(self, backend, params, hkdf_test): - hkdf_test(backend, algorithm, params) + def test_hkdf(self, backend, subtests): + for params in all_params: + with subtests.test(): + hkdf_extract_test(backend, algorithm, params) + with subtests.test(): + hkdf_expand_test(backend, algorithm, params) + with subtests.test(): + hkdf_derive_test(backend, algorithm, params) return test_hkdf @@ -397,9 +403,10 @@ def test_hkdf(self, backend, params, hkdf_test): def generate_kbkdf_counter_mode_test(param_loader, path, file_names): all_params = _load_all_params(path, file_names, param_loader) - @pytest.mark.parametrize("params", all_params) - def test_kbkdf(self, backend, params): - kbkdf_counter_mode_test(backend, params) + def test_kbkdf(self, backend, subtests): + for params in all_params: + with subtests.test(): + kbkdf_counter_mode_test(backend, params) return test_kbkdf @@ -457,9 +464,10 @@ def generate_rsa_verification_test( i for i in all_params if i["algorithm"] == hash_alg.name.upper() ] - @pytest.mark.parametrize("params", all_params) - def test_rsa_verification(self, backend, params): - rsa_verification_test(backend, params, hash_alg, pad_factory) + def test_rsa_verification(self, backend, subtests): + for params in all_params: + with subtests.test(): + rsa_verification_test(backend, params, hash_alg, pad_factory) return test_rsa_verification From e0477596f7117845aa2d8768bf1b75162b3d915b Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 9 Dec 2020 01:35:11 -0500 Subject: [PATCH 0005/2380] Remove __future__ import from our code (#5610) --- docs/conf.py | 2 -- docs/cryptography-docs.py | 2 -- docs/development/custom-vectors/arc4/generate_arc4.py | 2 -- docs/development/custom-vectors/cast5/generate_cast5.py | 2 -- docs/development/custom-vectors/hkdf/generate_hkdf.py | 2 -- .../custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py | 2 -- .../custom-vectors/secp256k1/generate_secp256k1.py | 2 -- .../custom-vectors/secp256k1/verify_secp256k1.py | 2 -- docs/development/submitting-patches.rst | 6 ------ release.py | 2 -- setup.py | 2 -- src/_cffi_src/build_openssl.py | 1 - src/_cffi_src/build_padding.py | 1 - src/_cffi_src/openssl/__init__.py | 2 -- src/_cffi_src/openssl/aes.py | 1 - src/_cffi_src/openssl/asn1.py | 1 - src/_cffi_src/openssl/bignum.py | 1 - src/_cffi_src/openssl/bio.py | 1 - src/_cffi_src/openssl/callbacks.py | 1 - src/_cffi_src/openssl/cmac.py | 1 - src/_cffi_src/openssl/conf.py | 1 - src/_cffi_src/openssl/crypto.py | 1 - src/_cffi_src/openssl/cryptography.py | 1 - src/_cffi_src/openssl/ct.py | 1 - src/_cffi_src/openssl/dh.py | 1 - src/_cffi_src/openssl/dsa.py | 1 - src/_cffi_src/openssl/ec.py | 1 - src/_cffi_src/openssl/ecdh.py | 1 - src/_cffi_src/openssl/ecdsa.py | 1 - src/_cffi_src/openssl/engine.py | 1 - src/_cffi_src/openssl/err.py | 1 - src/_cffi_src/openssl/evp.py | 1 - src/_cffi_src/openssl/fips.py | 1 - src/_cffi_src/openssl/hmac.py | 1 - src/_cffi_src/openssl/nid.py | 1 - src/_cffi_src/openssl/objects.py | 1 - src/_cffi_src/openssl/ocsp.py | 1 - src/_cffi_src/openssl/opensslv.py | 1 - src/_cffi_src/openssl/osrandom_engine.py | 1 - src/_cffi_src/openssl/pem.py | 1 - src/_cffi_src/openssl/pkcs12.py | 1 - src/_cffi_src/openssl/pkcs7.py | 1 - src/_cffi_src/openssl/rand.py | 1 - src/_cffi_src/openssl/rsa.py | 1 - src/_cffi_src/openssl/ssl.py | 1 - src/_cffi_src/openssl/x509.py | 1 - src/_cffi_src/openssl/x509_vfy.py | 1 - src/_cffi_src/openssl/x509name.py | 1 - src/_cffi_src/openssl/x509v3.py | 1 - src/_cffi_src/utils.py | 1 - src/cryptography/__about__.py | 1 - src/cryptography/__init__.py | 1 - src/cryptography/exceptions.py | 1 - src/cryptography/fernet.py | 1 - src/cryptography/hazmat/__init__.py | 1 - src/cryptography/hazmat/_der.py | 1 - src/cryptography/hazmat/_oid.py | 1 - src/cryptography/hazmat/backends/__init__.py | 2 -- src/cryptography/hazmat/backends/interfaces.py | 1 - src/cryptography/hazmat/backends/openssl/__init__.py | 1 - src/cryptography/hazmat/backends/openssl/aead.py | 1 - src/cryptography/hazmat/backends/openssl/backend.py | 1 - src/cryptography/hazmat/backends/openssl/ciphers.py | 1 - src/cryptography/hazmat/backends/openssl/cmac.py | 2 -- src/cryptography/hazmat/backends/openssl/decode_asn1.py | 1 - src/cryptography/hazmat/backends/openssl/dh.py | 1 - src/cryptography/hazmat/backends/openssl/dsa.py | 1 - src/cryptography/hazmat/backends/openssl/ec.py | 1 - src/cryptography/hazmat/backends/openssl/ed25519.py | 1 - src/cryptography/hazmat/backends/openssl/ed448.py | 1 - src/cryptography/hazmat/backends/openssl/encode_asn1.py | 1 - src/cryptography/hazmat/backends/openssl/hashes.py | 2 -- src/cryptography/hazmat/backends/openssl/hmac.py | 2 -- src/cryptography/hazmat/backends/openssl/ocsp.py | 1 - src/cryptography/hazmat/backends/openssl/poly1305.py | 2 -- src/cryptography/hazmat/backends/openssl/rsa.py | 1 - src/cryptography/hazmat/backends/openssl/utils.py | 1 - src/cryptography/hazmat/backends/openssl/x25519.py | 1 - src/cryptography/hazmat/backends/openssl/x448.py | 1 - src/cryptography/hazmat/backends/openssl/x509.py | 1 - src/cryptography/hazmat/bindings/__init__.py | 2 -- src/cryptography/hazmat/bindings/openssl/__init__.py | 2 -- src/cryptography/hazmat/bindings/openssl/_conditional.py | 2 -- src/cryptography/hazmat/bindings/openssl/binding.py | 1 - src/cryptography/hazmat/primitives/__init__.py | 2 -- src/cryptography/hazmat/primitives/asymmetric/__init__.py | 1 - src/cryptography/hazmat/primitives/asymmetric/dh.py | 1 - src/cryptography/hazmat/primitives/asymmetric/dsa.py | 1 - src/cryptography/hazmat/primitives/asymmetric/ec.py | 1 - src/cryptography/hazmat/primitives/asymmetric/ed25519.py | 1 - src/cryptography/hazmat/primitives/asymmetric/ed448.py | 1 - src/cryptography/hazmat/primitives/asymmetric/padding.py | 1 - src/cryptography/hazmat/primitives/asymmetric/rsa.py | 1 - src/cryptography/hazmat/primitives/asymmetric/utils.py | 1 - src/cryptography/hazmat/primitives/asymmetric/x25519.py | 1 - src/cryptography/hazmat/primitives/asymmetric/x448.py | 1 - src/cryptography/hazmat/primitives/ciphers/__init__.py | 1 - src/cryptography/hazmat/primitives/ciphers/aead.py | 1 - src/cryptography/hazmat/primitives/ciphers/algorithms.py | 1 - src/cryptography/hazmat/primitives/ciphers/base.py | 1 - src/cryptography/hazmat/primitives/ciphers/modes.py | 1 - src/cryptography/hazmat/primitives/cmac.py | 1 - src/cryptography/hazmat/primitives/constant_time.py | 1 - src/cryptography/hazmat/primitives/hashes.py | 1 - src/cryptography/hazmat/primitives/hmac.py | 1 - src/cryptography/hazmat/primitives/kdf/__init__.py | 1 - src/cryptography/hazmat/primitives/kdf/concatkdf.py | 1 - src/cryptography/hazmat/primitives/kdf/hkdf.py | 1 - src/cryptography/hazmat/primitives/kdf/kbkdf.py | 1 - src/cryptography/hazmat/primitives/kdf/pbkdf2.py | 1 - src/cryptography/hazmat/primitives/kdf/scrypt.py | 1 - src/cryptography/hazmat/primitives/kdf/x963kdf.py | 1 - src/cryptography/hazmat/primitives/keywrap.py | 1 - src/cryptography/hazmat/primitives/padding.py | 1 - src/cryptography/hazmat/primitives/poly1305.py | 2 -- .../hazmat/primitives/serialization/__init__.py | 1 - src/cryptography/hazmat/primitives/serialization/base.py | 1 - src/cryptography/hazmat/primitives/serialization/pkcs12.py | 1 - src/cryptography/hazmat/primitives/serialization/pkcs7.py | 1 - src/cryptography/hazmat/primitives/serialization/ssh.py | 1 - src/cryptography/hazmat/primitives/twofactor/__init__.py | 2 -- src/cryptography/hazmat/primitives/twofactor/hotp.py | 1 - src/cryptography/hazmat/primitives/twofactor/totp.py | 1 - src/cryptography/hazmat/primitives/twofactor/utils.py | 1 - src/cryptography/utils.py | 1 - src/cryptography/x509/__init__.py | 1 - src/cryptography/x509/base.py | 1 - src/cryptography/x509/certificate_transparency.py | 1 - src/cryptography/x509/extensions.py | 1 - src/cryptography/x509/general_name.py | 1 - src/cryptography/x509/name.py | 1 - src/cryptography/x509/ocsp.py | 1 - src/cryptography/x509/oid.py | 1 - tests/__init__.py | 2 -- tests/conftest.py | 1 - tests/doubles.py | 1 - tests/hazmat/__init__.py | 2 -- tests/hazmat/backends/__init__.py | 2 -- tests/hazmat/backends/test_no_backend.py | 1 - tests/hazmat/backends/test_openssl.py | 1 - tests/hazmat/backends/test_openssl_memleak.py | 1 - tests/hazmat/bindings/test_openssl.py | 1 - tests/hazmat/primitives/__init__.py | 2 -- tests/hazmat/primitives/fixtures_dh.py | 1 - tests/hazmat/primitives/fixtures_dsa.py | 1 - tests/hazmat/primitives/fixtures_ec.py | 1 - tests/hazmat/primitives/fixtures_rsa.py | 1 - tests/hazmat/primitives/test_3des.py | 1 - tests/hazmat/primitives/test_aead.py | 1 - tests/hazmat/primitives/test_aes.py | 1 - tests/hazmat/primitives/test_aes_gcm.py | 1 - tests/hazmat/primitives/test_arc4.py | 1 - tests/hazmat/primitives/test_asym_utils.py | 1 - tests/hazmat/primitives/test_block.py | 1 - tests/hazmat/primitives/test_blowfish.py | 1 - tests/hazmat/primitives/test_camellia.py | 1 - tests/hazmat/primitives/test_cast5.py | 1 - tests/hazmat/primitives/test_chacha20.py | 1 - tests/hazmat/primitives/test_ciphers.py | 1 - tests/hazmat/primitives/test_cmac.py | 1 - tests/hazmat/primitives/test_concatkdf.py | 1 - tests/hazmat/primitives/test_constant_time.py | 1 - tests/hazmat/primitives/test_dh.py | 1 - tests/hazmat/primitives/test_dsa.py | 1 - tests/hazmat/primitives/test_ec.py | 1 - tests/hazmat/primitives/test_ed25519.py | 1 - tests/hazmat/primitives/test_ed448.py | 1 - tests/hazmat/primitives/test_hash_vectors.py | 1 - tests/hazmat/primitives/test_hashes.py | 1 - tests/hazmat/primitives/test_hkdf.py | 1 - tests/hazmat/primitives/test_hkdf_vectors.py | 1 - tests/hazmat/primitives/test_hmac.py | 1 - tests/hazmat/primitives/test_hmac_vectors.py | 1 - tests/hazmat/primitives/test_idea.py | 1 - tests/hazmat/primitives/test_kbkdf.py | 1 - tests/hazmat/primitives/test_kbkdf_vectors.py | 1 - tests/hazmat/primitives/test_keywrap.py | 1 - tests/hazmat/primitives/test_padding.py | 1 - tests/hazmat/primitives/test_pbkdf2hmac.py | 1 - tests/hazmat/primitives/test_pbkdf2hmac_vectors.py | 1 - tests/hazmat/primitives/test_pkcs12.py | 1 - tests/hazmat/primitives/test_pkcs7.py | 1 - tests/hazmat/primitives/test_poly1305.py | 1 - tests/hazmat/primitives/test_rsa.py | 1 - tests/hazmat/primitives/test_scrypt.py | 1 - tests/hazmat/primitives/test_seed.py | 1 - tests/hazmat/primitives/test_serialization.py | 1 - tests/hazmat/primitives/test_x25519.py | 1 - tests/hazmat/primitives/test_x448.py | 1 - tests/hazmat/primitives/test_x963_vectors.py | 1 - tests/hazmat/primitives/test_x963kdf.py | 1 - tests/hazmat/primitives/twofactor/__init__.py | 2 -- tests/hazmat/primitives/twofactor/test_hotp.py | 1 - tests/hazmat/primitives/twofactor/test_totp.py | 1 - tests/hazmat/primitives/utils.py | 1 - tests/hazmat/test_der.py | 1 - tests/hazmat/test_oid.py | 1 - tests/hypothesis/__init__.py | 2 -- tests/test_cryptography_utils.py | 1 - tests/test_fernet.py | 1 - tests/test_utils.py | 1 - tests/test_warnings.py | 1 - tests/utils.py | 1 - tests/wycheproof/test_aes.py | 1 - tests/wycheproof/test_chacha20poly1305.py | 1 - tests/wycheproof/test_cmac.py | 1 - tests/wycheproof/test_dsa.py | 1 - tests/wycheproof/test_ecdh.py | 1 - tests/wycheproof/test_ecdsa.py | 1 - tests/wycheproof/test_eddsa.py | 1 - tests/wycheproof/test_hkdf.py | 1 - tests/wycheproof/test_hmac.py | 1 - tests/wycheproof/test_keywrap.py | 1 - tests/wycheproof/test_rsa.py | 1 - tests/wycheproof/test_utils.py | 1 - tests/wycheproof/test_x25519.py | 1 - tests/wycheproof/test_x448.py | 1 - tests/x509/test_ocsp.py | 1 - tests/x509/test_x509.py | 1 - tests/x509/test_x509_crlbuilder.py | 1 - tests/x509/test_x509_ext.py | 1 - tests/x509/test_x509_revokedcertbuilder.py | 1 - vectors/cryptography_vectors/__about__.py | 2 -- vectors/cryptography_vectors/__init__.py | 2 -- vectors/setup.py | 2 -- 225 files changed, 261 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index fe8c38c2a59d..2a307573563b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -16,8 +16,6 @@ # All configuration values have a default; values that are commented out # serve to show the default. -from __future__ import absolute_import, division, print_function - import os import sys diff --git a/docs/cryptography-docs.py b/docs/cryptography-docs.py index 923ec6f5b2c3..1131f6a0e279 100644 --- a/docs/cryptography-docs.py +++ b/docs/cryptography-docs.py @@ -2,8 +2,6 @@ # 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 - from docutils import nodes from docutils.parsers.rst import Directive diff --git a/docs/development/custom-vectors/arc4/generate_arc4.py b/docs/development/custom-vectors/arc4/generate_arc4.py index 2ca85c98dbe7..3359b949edc0 100644 --- a/docs/development/custom-vectors/arc4/generate_arc4.py +++ b/docs/development/custom-vectors/arc4/generate_arc4.py @@ -2,8 +2,6 @@ # 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 binascii from cryptography.hazmat.backends import default_backend diff --git a/docs/development/custom-vectors/cast5/generate_cast5.py b/docs/development/custom-vectors/cast5/generate_cast5.py index 5208b90d8440..c8a83c1de449 100644 --- a/docs/development/custom-vectors/cast5/generate_cast5.py +++ b/docs/development/custom-vectors/cast5/generate_cast5.py @@ -2,8 +2,6 @@ # 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 binascii from cryptography.hazmat.backends import default_backend diff --git a/docs/development/custom-vectors/hkdf/generate_hkdf.py b/docs/development/custom-vectors/hkdf/generate_hkdf.py index aa2fc274f9ae..36c7dceed3a9 100644 --- a/docs/development/custom-vectors/hkdf/generate_hkdf.py +++ b/docs/development/custom-vectors/hkdf/generate_hkdf.py @@ -2,8 +2,6 @@ # 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 binascii from cryptography.hazmat.backends import default_backend diff --git a/docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py b/docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py index a43e1506d53d..000467327538 100644 --- a/docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py +++ b/docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py @@ -2,8 +2,6 @@ # 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 binascii import itertools import os diff --git a/docs/development/custom-vectors/secp256k1/generate_secp256k1.py b/docs/development/custom-vectors/secp256k1/generate_secp256k1.py index bfb150ba6fcc..ef4ab2f88d78 100644 --- a/docs/development/custom-vectors/secp256k1/generate_secp256k1.py +++ b/docs/development/custom-vectors/secp256k1/generate_secp256k1.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import hashlib import os from binascii import hexlify diff --git a/docs/development/custom-vectors/secp256k1/verify_secp256k1.py b/docs/development/custom-vectors/secp256k1/verify_secp256k1.py index f721b0001213..2c8ad1dc80e5 100644 --- a/docs/development/custom-vectors/secp256k1/verify_secp256k1.py +++ b/docs/development/custom-vectors/secp256k1/verify_secp256k1.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, print_function - import os from cryptography.hazmat.backends import default_backend diff --git a/docs/development/submitting-patches.rst b/docs/development/submitting-patches.rst index b4ed175e6adb..e6f8abc65ce2 100644 --- a/docs/development/submitting-patches.rst +++ b/docs/development/submitting-patches.rst @@ -37,12 +37,6 @@ Every code file must start with the boilerplate licensing notice: # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. -Additionally, every Python code file must contain - -.. code-block:: python - - from __future__ import absolute_import, division, print_function - API considerations ~~~~~~~~~~~~~~~~~~ diff --git a/release.py b/release.py index 5f3f251d17bd..3416c8c56340 100644 --- a/release.py +++ b/release.py @@ -2,8 +2,6 @@ # 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 io diff --git a/setup.py b/setup.py index 82b84ccf50ea..1d04eeaee6d2 100644 --- a/setup.py +++ b/setup.py @@ -4,8 +4,6 @@ # 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 os import platform import sys diff --git a/src/_cffi_src/build_openssl.py b/src/_cffi_src/build_openssl.py index 4380c3396909..08499d66f629 100644 --- a/src/_cffi_src/build_openssl.py +++ b/src/_cffi_src/build_openssl.py @@ -2,7 +2,6 @@ # 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 os import sys diff --git a/src/_cffi_src/build_padding.py b/src/_cffi_src/build_padding.py index 207f4a658ea2..61f36ef69109 100644 --- a/src/_cffi_src/build_padding.py +++ b/src/_cffi_src/build_padding.py @@ -2,7 +2,6 @@ # 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 os diff --git a/src/_cffi_src/openssl/__init__.py b/src/_cffi_src/openssl/__init__.py index 4b540884df72..b509336233c2 100644 --- a/src/_cffi_src/openssl/__init__.py +++ b/src/_cffi_src/openssl/__init__.py @@ -1,5 +1,3 @@ # 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 diff --git a/src/_cffi_src/openssl/aes.py b/src/_cffi_src/openssl/aes.py index 25ef3ec0e3cb..55f19fd567f0 100644 --- a/src/_cffi_src/openssl/aes.py +++ b/src/_cffi_src/openssl/aes.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/asn1.py b/src/_cffi_src/openssl/asn1.py index da55b670e041..3e646239d474 100644 --- a/src/_cffi_src/openssl/asn1.py +++ b/src/_cffi_src/openssl/asn1.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/bignum.py b/src/_cffi_src/openssl/bignum.py index 751018391d94..fdfd835e3d18 100644 --- a/src/_cffi_src/openssl/bignum.py +++ b/src/_cffi_src/openssl/bignum.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/bio.py b/src/_cffi_src/openssl/bio.py index 52d57c6228d1..9310c1beb0f9 100644 --- a/src/_cffi_src/openssl/bio.py +++ b/src/_cffi_src/openssl/bio.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/callbacks.py b/src/_cffi_src/openssl/callbacks.py index 19301b973a28..79d4f24bcee9 100644 --- a/src/_cffi_src/openssl/callbacks.py +++ b/src/_cffi_src/openssl/callbacks.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/cmac.py b/src/_cffi_src/openssl/cmac.py index 557abd1ca8f9..a25426305131 100644 --- a/src/_cffi_src/openssl/cmac.py +++ b/src/_cffi_src/openssl/cmac.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #if !defined(OPENSSL_NO_CMAC) diff --git a/src/_cffi_src/openssl/conf.py b/src/_cffi_src/openssl/conf.py index 9db0162a633f..883c474ebdb1 100644 --- a/src/_cffi_src/openssl/conf.py +++ b/src/_cffi_src/openssl/conf.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/crypto.py b/src/_cffi_src/openssl/crypto.py index 6064a4eeea99..340cc8b73801 100644 --- a/src/_cffi_src/openssl/crypto.py +++ b/src/_cffi_src/openssl/crypto.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/cryptography.py b/src/_cffi_src/openssl/cryptography.py index f24bee5a4f82..e2b5a13235ae 100644 --- a/src/_cffi_src/openssl/cryptography.py +++ b/src/_cffi_src/openssl/cryptography.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ /* define our OpenSSL API compatibility level to 1.0.1. Any symbols older than diff --git a/src/_cffi_src/openssl/ct.py b/src/_cffi_src/openssl/ct.py index 5f0670635fa2..6271497625db 100644 --- a/src/_cffi_src/openssl/ct.py +++ b/src/_cffi_src/openssl/ct.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #if CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER && !defined(OPENSSL_NO_CT) diff --git a/src/_cffi_src/openssl/dh.py b/src/_cffi_src/openssl/dh.py index 947a5a8ee02e..979dafa94253 100644 --- a/src/_cffi_src/openssl/dh.py +++ b/src/_cffi_src/openssl/dh.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/dsa.py b/src/_cffi_src/openssl/dsa.py index 3a290067bc5b..7f3f452eb019 100644 --- a/src/_cffi_src/openssl/dsa.py +++ b/src/_cffi_src/openssl/dsa.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/ec.py b/src/_cffi_src/openssl/ec.py index 6432fc22e9e0..32d9b5843197 100644 --- a/src/_cffi_src/openssl/ec.py +++ b/src/_cffi_src/openssl/ec.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/ecdh.py b/src/_cffi_src/openssl/ecdh.py index c73cc9f36fdd..522642aafabc 100644 --- a/src/_cffi_src/openssl/ecdh.py +++ b/src/_cffi_src/openssl/ecdh.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/ecdsa.py b/src/_cffi_src/openssl/ecdsa.py index 3134e24b61d4..99a93515cf2e 100644 --- a/src/_cffi_src/openssl/ecdsa.py +++ b/src/_cffi_src/openssl/ecdsa.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/engine.py b/src/_cffi_src/openssl/engine.py index 24cdd42a8393..9b3ccf1a382d 100644 --- a/src/_cffi_src/openssl/engine.py +++ b/src/_cffi_src/openssl/engine.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/err.py b/src/_cffi_src/openssl/err.py index 0dd7414674fe..0634b656c0f4 100644 --- a/src/_cffi_src/openssl/err.py +++ b/src/_cffi_src/openssl/err.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py index ab7cfeb39511..c9575dc47b71 100644 --- a/src/_cffi_src/openssl/evp.py +++ b/src/_cffi_src/openssl/evp.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/fips.py b/src/_cffi_src/openssl/fips.py index c92bca494be0..b9d0d64d84fb 100644 --- a/src/_cffi_src/openssl/fips.py +++ b/src/_cffi_src/openssl/fips.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/hmac.py b/src/_cffi_src/openssl/hmac.py index 2e0e33ffe3b0..8b1915361be3 100644 --- a/src/_cffi_src/openssl/hmac.py +++ b/src/_cffi_src/openssl/hmac.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/nid.py b/src/_cffi_src/openssl/nid.py index 9ef88cdbbd41..57a9a8d317b1 100644 --- a/src/_cffi_src/openssl/nid.py +++ b/src/_cffi_src/openssl/nid.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/objects.py b/src/_cffi_src/openssl/objects.py index 236903d986a9..bddaa84284ea 100644 --- a/src/_cffi_src/openssl/objects.py +++ b/src/_cffi_src/openssl/objects.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/ocsp.py b/src/_cffi_src/openssl/ocsp.py index c3d034c2c48d..9b939f0f85f9 100644 --- a/src/_cffi_src/openssl/ocsp.py +++ b/src/_cffi_src/openssl/ocsp.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/opensslv.py b/src/_cffi_src/openssl/opensslv.py index 9b0c68933860..630ebd7a1b91 100644 --- a/src/_cffi_src/openssl/opensslv.py +++ b/src/_cffi_src/openssl/opensslv.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/osrandom_engine.py b/src/_cffi_src/openssl/osrandom_engine.py index ed1068ef8aa4..dbc304b399c7 100644 --- a/src/_cffi_src/openssl/osrandom_engine.py +++ b/src/_cffi_src/openssl/osrandom_engine.py @@ -2,7 +2,6 @@ # 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 os diff --git a/src/_cffi_src/openssl/pem.py b/src/_cffi_src/openssl/pem.py index 3f279c4fffa9..2ebcdf6b0eec 100644 --- a/src/_cffi_src/openssl/pem.py +++ b/src/_cffi_src/openssl/pem.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/pkcs12.py b/src/_cffi_src/openssl/pkcs12.py index 21a8481faa30..f08139ed25f3 100644 --- a/src/_cffi_src/openssl/pkcs12.py +++ b/src/_cffi_src/openssl/pkcs12.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/pkcs7.py b/src/_cffi_src/openssl/pkcs7.py index c22263dfe6c1..052bd050819f 100644 --- a/src/_cffi_src/openssl/pkcs7.py +++ b/src/_cffi_src/openssl/pkcs7.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/rand.py b/src/_cffi_src/openssl/rand.py index 1bc2ec0bc386..bb4bce07e239 100644 --- a/src/_cffi_src/openssl/rand.py +++ b/src/_cffi_src/openssl/rand.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/rsa.py b/src/_cffi_src/openssl/rsa.py index 92b8fa4600d8..5d1e163b16c0 100644 --- a/src/_cffi_src/openssl/rsa.py +++ b/src/_cffi_src/openssl/rsa.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index f3511e454c98..61813a3c038a 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/x509.py b/src/_cffi_src/openssl/x509.py index 24946ea48d07..e7f1368cf2e7 100644 --- a/src/_cffi_src/openssl/x509.py +++ b/src/_cffi_src/openssl/x509.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/x509_vfy.py b/src/_cffi_src/openssl/x509_vfy.py index ba3d3dbb1421..57de6d0ec80e 100644 --- a/src/_cffi_src/openssl/x509_vfy.py +++ b/src/_cffi_src/openssl/x509_vfy.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/x509name.py b/src/_cffi_src/openssl/x509name.py index 1fbe26aa7432..e4fe80d9a007 100644 --- a/src/_cffi_src/openssl/x509name.py +++ b/src/_cffi_src/openssl/x509name.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/openssl/x509v3.py b/src/_cffi_src/openssl/x509v3.py index 59681206524b..2cfb8308f3d5 100644 --- a/src/_cffi_src/openssl/x509v3.py +++ b/src/_cffi_src/openssl/x509v3.py @@ -2,7 +2,6 @@ # 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 INCLUDES = """ #include diff --git a/src/_cffi_src/utils.py b/src/_cffi_src/utils.py index 93659ffc33bd..1754e04f398e 100644 --- a/src/_cffi_src/utils.py +++ b/src/_cffi_src/utils.py @@ -2,7 +2,6 @@ # 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 os import sys diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py index 18efbab0714a..7094f7992a2d 100644 --- a/src/cryptography/__about__.py +++ b/src/cryptography/__about__.py @@ -2,7 +2,6 @@ # 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 __all__ = [ "__title__", diff --git a/src/cryptography/__init__.py b/src/cryptography/__init__.py index 7b6ae2860c3a..15e7835e1d2f 100644 --- a/src/cryptography/__init__.py +++ b/src/cryptography/__init__.py @@ -2,7 +2,6 @@ # 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 from cryptography.__about__ import ( __author__, diff --git a/src/cryptography/exceptions.py b/src/cryptography/exceptions.py index 1d52d7dcfc5e..f5860590571b 100644 --- a/src/cryptography/exceptions.py +++ b/src/cryptography/exceptions.py @@ -2,7 +2,6 @@ # 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 from enum import Enum diff --git a/src/cryptography/fernet.py b/src/cryptography/fernet.py index 00c25286715a..f01ba4f40871 100644 --- a/src/cryptography/fernet.py +++ b/src/cryptography/fernet.py @@ -2,7 +2,6 @@ # 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 base64 import binascii diff --git a/src/cryptography/hazmat/__init__.py b/src/cryptography/hazmat/__init__.py index 9f06a9949a31..007694bc5060 100644 --- a/src/cryptography/hazmat/__init__.py +++ b/src/cryptography/hazmat/__init__.py @@ -8,4 +8,3 @@ 100% absolutely sure that you know what you're doing because this module is full of land mines, dragons, and dinosaurs with laser guns. """ -from __future__ import absolute_import, division, print_function diff --git a/src/cryptography/hazmat/_der.py b/src/cryptography/hazmat/_der.py index 462b911b4532..11bfe1bf172d 100644 --- a/src/cryptography/hazmat/_der.py +++ b/src/cryptography/hazmat/_der.py @@ -2,7 +2,6 @@ # 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 six diff --git a/src/cryptography/hazmat/_oid.py b/src/cryptography/hazmat/_oid.py index de2771a7379a..baf2d535c904 100644 --- a/src/cryptography/hazmat/_oid.py +++ b/src/cryptography/hazmat/_oid.py @@ -2,7 +2,6 @@ # 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 from cryptography import utils diff --git a/src/cryptography/hazmat/backends/__init__.py b/src/cryptography/hazmat/backends/__init__.py index 1563936dde6e..aabde5b7e132 100644 --- a/src/cryptography/hazmat/backends/__init__.py +++ b/src/cryptography/hazmat/backends/__init__.py @@ -2,8 +2,6 @@ # 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 - _default_backend = None diff --git a/src/cryptography/hazmat/backends/interfaces.py b/src/cryptography/hazmat/backends/interfaces.py index 418980a34e0d..d5105030d92c 100644 --- a/src/cryptography/hazmat/backends/interfaces.py +++ b/src/cryptography/hazmat/backends/interfaces.py @@ -2,7 +2,6 @@ # 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 abc diff --git a/src/cryptography/hazmat/backends/openssl/__init__.py b/src/cryptography/hazmat/backends/openssl/__init__.py index 8eadeb6e1867..31fd17c3b7fe 100644 --- a/src/cryptography/hazmat/backends/openssl/__init__.py +++ b/src/cryptography/hazmat/backends/openssl/__init__.py @@ -2,7 +2,6 @@ # 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 from cryptography.hazmat.backends.openssl.backend import backend diff --git a/src/cryptography/hazmat/backends/openssl/aead.py b/src/cryptography/hazmat/backends/openssl/aead.py index 4494916852ae..7923831f10af 100644 --- a/src/cryptography/hazmat/backends/openssl/aead.py +++ b/src/cryptography/hazmat/backends/openssl/aead.py @@ -2,7 +2,6 @@ # 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 from cryptography.exceptions import InvalidTag diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 976209f71902..8d6412d46cc7 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -2,7 +2,6 @@ # 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 collections import contextlib diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py index 1e805d235aa2..36871d066ec7 100644 --- a/src/cryptography/hazmat/backends/openssl/ciphers.py +++ b/src/cryptography/hazmat/backends/openssl/ciphers.py @@ -2,7 +2,6 @@ # 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 from cryptography import utils from cryptography.exceptions import InvalidTag, UnsupportedAlgorithm, _Reasons diff --git a/src/cryptography/hazmat/backends/openssl/cmac.py b/src/cryptography/hazmat/backends/openssl/cmac.py index 195fc230f2b2..9be316757414 100644 --- a/src/cryptography/hazmat/backends/openssl/cmac.py +++ b/src/cryptography/hazmat/backends/openssl/cmac.py @@ -2,8 +2,6 @@ # 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 - from cryptography import utils from cryptography.exceptions import ( diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index f29057e98b2d..f5f5c6a4a55f 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -2,7 +2,6 @@ # 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 datetime import ipaddress diff --git a/src/cryptography/hazmat/backends/openssl/dh.py b/src/cryptography/hazmat/backends/openssl/dh.py index 2862676c65ea..3bf138f24fd5 100644 --- a/src/cryptography/hazmat/backends/openssl/dh.py +++ b/src/cryptography/hazmat/backends/openssl/dh.py @@ -2,7 +2,6 @@ # 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 from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm, _Reasons diff --git a/src/cryptography/hazmat/backends/openssl/dsa.py b/src/cryptography/hazmat/backends/openssl/dsa.py index 0c5faba18ac9..c172e40d0968 100644 --- a/src/cryptography/hazmat/backends/openssl/dsa.py +++ b/src/cryptography/hazmat/backends/openssl/dsa.py @@ -2,7 +2,6 @@ # 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 from cryptography import utils from cryptography.exceptions import InvalidSignature diff --git a/src/cryptography/hazmat/backends/openssl/ec.py b/src/cryptography/hazmat/backends/openssl/ec.py index 05d32baba662..c0b479758ca1 100644 --- a/src/cryptography/hazmat/backends/openssl/ec.py +++ b/src/cryptography/hazmat/backends/openssl/ec.py @@ -2,7 +2,6 @@ # 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 from cryptography import utils from cryptography.exceptions import ( diff --git a/src/cryptography/hazmat/backends/openssl/ed25519.py b/src/cryptography/hazmat/backends/openssl/ed25519.py index 13bec3af1094..7c57c8bd2a7b 100644 --- a/src/cryptography/hazmat/backends/openssl/ed25519.py +++ b/src/cryptography/hazmat/backends/openssl/ed25519.py @@ -2,7 +2,6 @@ # 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 from cryptography import exceptions, utils from cryptography.hazmat.primitives import serialization diff --git a/src/cryptography/hazmat/backends/openssl/ed448.py b/src/cryptography/hazmat/backends/openssl/ed448.py index 6512770e5b76..0738c44e2f24 100644 --- a/src/cryptography/hazmat/backends/openssl/ed448.py +++ b/src/cryptography/hazmat/backends/openssl/ed448.py @@ -2,7 +2,6 @@ # 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 from cryptography import exceptions, utils from cryptography.hazmat.primitives import serialization diff --git a/src/cryptography/hazmat/backends/openssl/encode_asn1.py b/src/cryptography/hazmat/backends/openssl/encode_asn1.py index 0a33200bbcc2..1a24a4516222 100644 --- a/src/cryptography/hazmat/backends/openssl/encode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/encode_asn1.py @@ -2,7 +2,6 @@ # 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 calendar import ipaddress diff --git a/src/cryptography/hazmat/backends/openssl/hashes.py b/src/cryptography/hazmat/backends/openssl/hashes.py index 764dce0ede60..b14dffc7571c 100644 --- a/src/cryptography/hazmat/backends/openssl/hashes.py +++ b/src/cryptography/hazmat/backends/openssl/hashes.py @@ -2,8 +2,6 @@ # 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 - from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm, _Reasons diff --git a/src/cryptography/hazmat/backends/openssl/hmac.py b/src/cryptography/hazmat/backends/openssl/hmac.py index 1cc9d99fec7b..ea954c68c85b 100644 --- a/src/cryptography/hazmat/backends/openssl/hmac.py +++ b/src/cryptography/hazmat/backends/openssl/hmac.py @@ -2,8 +2,6 @@ # 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 - from cryptography import utils from cryptography.exceptions import ( diff --git a/src/cryptography/hazmat/backends/openssl/ocsp.py b/src/cryptography/hazmat/backends/openssl/ocsp.py index 50c02e7a8018..9a6b9b418fd7 100644 --- a/src/cryptography/hazmat/backends/openssl/ocsp.py +++ b/src/cryptography/hazmat/backends/openssl/ocsp.py @@ -2,7 +2,6 @@ # 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 functools diff --git a/src/cryptography/hazmat/backends/openssl/poly1305.py b/src/cryptography/hazmat/backends/openssl/poly1305.py index 5699918b1726..35f6819ce87e 100644 --- a/src/cryptography/hazmat/backends/openssl/poly1305.py +++ b/src/cryptography/hazmat/backends/openssl/poly1305.py @@ -2,8 +2,6 @@ # 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 - from cryptography.exceptions import InvalidSignature from cryptography.hazmat.primitives import constant_time diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py index 82cd49c960ab..bbdd73525f75 100644 --- a/src/cryptography/hazmat/backends/openssl/rsa.py +++ b/src/cryptography/hazmat/backends/openssl/rsa.py @@ -2,7 +2,6 @@ # 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 from cryptography import utils from cryptography.exceptions import ( diff --git a/src/cryptography/hazmat/backends/openssl/utils.py b/src/cryptography/hazmat/backends/openssl/utils.py index 3d697d1fb56f..03e36f5b05f6 100644 --- a/src/cryptography/hazmat/backends/openssl/utils.py +++ b/src/cryptography/hazmat/backends/openssl/utils.py @@ -2,7 +2,6 @@ # 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 warnings diff --git a/src/cryptography/hazmat/backends/openssl/x25519.py b/src/cryptography/hazmat/backends/openssl/x25519.py index 4971c5481402..d0f60a075393 100644 --- a/src/cryptography/hazmat/backends/openssl/x25519.py +++ b/src/cryptography/hazmat/backends/openssl/x25519.py @@ -2,7 +2,6 @@ # 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 from cryptography import utils from cryptography.hazmat.backends.openssl.utils import _evp_pkey_derive diff --git a/src/cryptography/hazmat/backends/openssl/x448.py b/src/cryptography/hazmat/backends/openssl/x448.py index 7ebcdf84bcc2..7d836204ce60 100644 --- a/src/cryptography/hazmat/backends/openssl/x448.py +++ b/src/cryptography/hazmat/backends/openssl/x448.py @@ -2,7 +2,6 @@ # 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 from cryptography import utils from cryptography.hazmat.backends.openssl.utils import _evp_pkey_derive diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index 4d0dac7649a6..d7497a3e51c2 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -2,7 +2,6 @@ # 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 datetime import operator diff --git a/src/cryptography/hazmat/bindings/__init__.py b/src/cryptography/hazmat/bindings/__init__.py index 4b540884df72..b509336233c2 100644 --- a/src/cryptography/hazmat/bindings/__init__.py +++ b/src/cryptography/hazmat/bindings/__init__.py @@ -1,5 +1,3 @@ # 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 diff --git a/src/cryptography/hazmat/bindings/openssl/__init__.py b/src/cryptography/hazmat/bindings/openssl/__init__.py index 4b540884df72..b509336233c2 100644 --- a/src/cryptography/hazmat/bindings/openssl/__init__.py +++ b/src/cryptography/hazmat/bindings/openssl/__init__.py @@ -1,5 +1,3 @@ # 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 diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index ca50fed13414..6105093c626b 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -2,8 +2,6 @@ # 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 - def cryptography_has_ec2m(): return [ diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py index 7a84a340e43b..d65abc5adad9 100644 --- a/src/cryptography/hazmat/bindings/openssl/binding.py +++ b/src/cryptography/hazmat/bindings/openssl/binding.py @@ -2,7 +2,6 @@ # 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 collections import threading diff --git a/src/cryptography/hazmat/primitives/__init__.py b/src/cryptography/hazmat/primitives/__init__.py index 4b540884df72..b509336233c2 100644 --- a/src/cryptography/hazmat/primitives/__init__.py +++ b/src/cryptography/hazmat/primitives/__init__.py @@ -1,5 +1,3 @@ # 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 diff --git a/src/cryptography/hazmat/primitives/asymmetric/__init__.py b/src/cryptography/hazmat/primitives/asymmetric/__init__.py index 494a7a13504b..67a46c225288 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/__init__.py +++ b/src/cryptography/hazmat/primitives/asymmetric/__init__.py @@ -2,7 +2,6 @@ # 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 abc diff --git a/src/cryptography/hazmat/primitives/asymmetric/dh.py b/src/cryptography/hazmat/primitives/asymmetric/dh.py index 74a311d5015a..1441877c30c9 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dh.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dh.py @@ -2,7 +2,6 @@ # 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 abc diff --git a/src/cryptography/hazmat/primitives/asymmetric/dsa.py b/src/cryptography/hazmat/primitives/asymmetric/dsa.py index 8ccc66665f36..655319a40e71 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dsa.py @@ -2,7 +2,6 @@ # 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 abc diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index c7e694fc5615..fe62a07fee5b 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -2,7 +2,6 @@ # 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 abc import warnings diff --git a/src/cryptography/hazmat/primitives/asymmetric/ed25519.py b/src/cryptography/hazmat/primitives/asymmetric/ed25519.py index 2d07a029bc73..900b4c5108ca 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ed25519.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ed25519.py @@ -2,7 +2,6 @@ # 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 abc diff --git a/src/cryptography/hazmat/primitives/asymmetric/ed448.py b/src/cryptography/hazmat/primitives/asymmetric/ed448.py index 520ffcbcbcb6..2c8496d9accb 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ed448.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ed448.py @@ -2,7 +2,6 @@ # 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 abc diff --git a/src/cryptography/hazmat/primitives/asymmetric/padding.py b/src/cryptography/hazmat/primitives/asymmetric/padding.py index fc8f6e26a917..785ae2405f97 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/padding.py +++ b/src/cryptography/hazmat/primitives/asymmetric/padding.py @@ -2,7 +2,6 @@ # 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 abc diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py index 28c3072bd2e8..f6fc75409674 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py @@ -2,7 +2,6 @@ # 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 abc from math import gcd diff --git a/src/cryptography/hazmat/primitives/asymmetric/utils.py b/src/cryptography/hazmat/primitives/asymmetric/utils.py index 5f9b677868db..ecc68c3bce2e 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/utils.py +++ b/src/cryptography/hazmat/primitives/asymmetric/utils.py @@ -2,7 +2,6 @@ # 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 from cryptography import utils from cryptography.hazmat._der import ( diff --git a/src/cryptography/hazmat/primitives/asymmetric/x25519.py b/src/cryptography/hazmat/primitives/asymmetric/x25519.py index fc63691536e9..3d17e727a717 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/x25519.py +++ b/src/cryptography/hazmat/primitives/asymmetric/x25519.py @@ -2,7 +2,6 @@ # 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 abc diff --git a/src/cryptography/hazmat/primitives/asymmetric/x448.py b/src/cryptography/hazmat/primitives/asymmetric/x448.py index 3ac067bfd5e0..acff892a1571 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/x448.py +++ b/src/cryptography/hazmat/primitives/asymmetric/x448.py @@ -2,7 +2,6 @@ # 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 abc diff --git a/src/cryptography/hazmat/primitives/ciphers/__init__.py b/src/cryptography/hazmat/primitives/ciphers/__init__.py index 4380f72b2e2e..7d3a2dcc65f8 100644 --- a/src/cryptography/hazmat/primitives/ciphers/__init__.py +++ b/src/cryptography/hazmat/primitives/ciphers/__init__.py @@ -2,7 +2,6 @@ # 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 from cryptography.hazmat.primitives.ciphers.base import ( AEADCipherContext, diff --git a/src/cryptography/hazmat/primitives/ciphers/aead.py b/src/cryptography/hazmat/primitives/ciphers/aead.py index c8c93955ce01..e26909eefcea 100644 --- a/src/cryptography/hazmat/primitives/ciphers/aead.py +++ b/src/cryptography/hazmat/primitives/ciphers/aead.py @@ -2,7 +2,6 @@ # 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 os diff --git a/src/cryptography/hazmat/primitives/ciphers/algorithms.py b/src/cryptography/hazmat/primitives/ciphers/algorithms.py index 8072cedd1714..2ddd9b1075a6 100644 --- a/src/cryptography/hazmat/primitives/ciphers/algorithms.py +++ b/src/cryptography/hazmat/primitives/ciphers/algorithms.py @@ -2,7 +2,6 @@ # 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 from cryptography import utils from cryptography.hazmat.primitives.ciphers import ( diff --git a/src/cryptography/hazmat/primitives/ciphers/base.py b/src/cryptography/hazmat/primitives/ciphers/base.py index dae425a2993d..a1270926e778 100644 --- a/src/cryptography/hazmat/primitives/ciphers/base.py +++ b/src/cryptography/hazmat/primitives/ciphers/base.py @@ -2,7 +2,6 @@ # 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 abc diff --git a/src/cryptography/hazmat/primitives/ciphers/modes.py b/src/cryptography/hazmat/primitives/ciphers/modes.py index 0ba0f2b5a176..75009b907f3c 100644 --- a/src/cryptography/hazmat/primitives/ciphers/modes.py +++ b/src/cryptography/hazmat/primitives/ciphers/modes.py @@ -2,7 +2,6 @@ # 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 abc diff --git a/src/cryptography/hazmat/primitives/cmac.py b/src/cryptography/hazmat/primitives/cmac.py index bf962c906908..48f8e331b235 100644 --- a/src/cryptography/hazmat/primitives/cmac.py +++ b/src/cryptography/hazmat/primitives/cmac.py @@ -2,7 +2,6 @@ # 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 from cryptography import utils from cryptography.exceptions import ( diff --git a/src/cryptography/hazmat/primitives/constant_time.py b/src/cryptography/hazmat/primitives/constant_time.py index 7f41b9efa5f7..49b0a642e500 100644 --- a/src/cryptography/hazmat/primitives/constant_time.py +++ b/src/cryptography/hazmat/primitives/constant_time.py @@ -2,7 +2,6 @@ # 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 hmac diff --git a/src/cryptography/hazmat/primitives/hashes.py b/src/cryptography/hazmat/primitives/hashes.py index 18e2bab36340..41998fd92bf5 100644 --- a/src/cryptography/hazmat/primitives/hashes.py +++ b/src/cryptography/hazmat/primitives/hashes.py @@ -2,7 +2,6 @@ # 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 abc diff --git a/src/cryptography/hazmat/primitives/hmac.py b/src/cryptography/hazmat/primitives/hmac.py index 8c421dc68df9..c417a42941b8 100644 --- a/src/cryptography/hazmat/primitives/hmac.py +++ b/src/cryptography/hazmat/primitives/hmac.py @@ -2,7 +2,6 @@ # 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 from cryptography import utils from cryptography.exceptions import ( diff --git a/src/cryptography/hazmat/primitives/kdf/__init__.py b/src/cryptography/hazmat/primitives/kdf/__init__.py index 2d0724e5daa4..a0e65b95ad3a 100644 --- a/src/cryptography/hazmat/primitives/kdf/__init__.py +++ b/src/cryptography/hazmat/primitives/kdf/__init__.py @@ -2,7 +2,6 @@ # 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 abc diff --git a/src/cryptography/hazmat/primitives/kdf/concatkdf.py b/src/cryptography/hazmat/primitives/kdf/concatkdf.py index 7cc0324fc4f5..85970fa574bd 100644 --- a/src/cryptography/hazmat/primitives/kdf/concatkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/concatkdf.py @@ -2,7 +2,6 @@ # 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 struct diff --git a/src/cryptography/hazmat/primitives/kdf/hkdf.py b/src/cryptography/hazmat/primitives/kdf/hkdf.py index 9bb6bc213253..4c2b149f37f4 100644 --- a/src/cryptography/hazmat/primitives/kdf/hkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/hkdf.py @@ -2,7 +2,6 @@ # 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 six diff --git a/src/cryptography/hazmat/primitives/kdf/kbkdf.py b/src/cryptography/hazmat/primitives/kdf/kbkdf.py index 864337001c89..aa9a5926fd22 100644 --- a/src/cryptography/hazmat/primitives/kdf/kbkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/kbkdf.py @@ -2,7 +2,6 @@ # 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 from enum import Enum diff --git a/src/cryptography/hazmat/primitives/kdf/pbkdf2.py b/src/cryptography/hazmat/primitives/kdf/pbkdf2.py index 5b67d48bbab6..00cc0955ae5c 100644 --- a/src/cryptography/hazmat/primitives/kdf/pbkdf2.py +++ b/src/cryptography/hazmat/primitives/kdf/pbkdf2.py @@ -2,7 +2,6 @@ # 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 from cryptography import utils from cryptography.exceptions import ( diff --git a/src/cryptography/hazmat/primitives/kdf/scrypt.py b/src/cryptography/hazmat/primitives/kdf/scrypt.py index f028646aa02d..7d25e79cef59 100644 --- a/src/cryptography/hazmat/primitives/kdf/scrypt.py +++ b/src/cryptography/hazmat/primitives/kdf/scrypt.py @@ -2,7 +2,6 @@ # 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 sys diff --git a/src/cryptography/hazmat/primitives/kdf/x963kdf.py b/src/cryptography/hazmat/primitives/kdf/x963kdf.py index 1898d526a48f..1d9aae17f13e 100644 --- a/src/cryptography/hazmat/primitives/kdf/x963kdf.py +++ b/src/cryptography/hazmat/primitives/kdf/x963kdf.py @@ -2,7 +2,6 @@ # 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 struct diff --git a/src/cryptography/hazmat/primitives/keywrap.py b/src/cryptography/hazmat/primitives/keywrap.py index 2439cafe6d59..230cc2e6a983 100644 --- a/src/cryptography/hazmat/primitives/keywrap.py +++ b/src/cryptography/hazmat/primitives/keywrap.py @@ -2,7 +2,6 @@ # 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 struct diff --git a/src/cryptography/hazmat/primitives/padding.py b/src/cryptography/hazmat/primitives/padding.py index d3dc7093ae51..43017ffd8b87 100644 --- a/src/cryptography/hazmat/primitives/padding.py +++ b/src/cryptography/hazmat/primitives/padding.py @@ -2,7 +2,6 @@ # 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 abc diff --git a/src/cryptography/hazmat/primitives/poly1305.py b/src/cryptography/hazmat/primitives/poly1305.py index 6439686202de..9243d51a654f 100644 --- a/src/cryptography/hazmat/primitives/poly1305.py +++ b/src/cryptography/hazmat/primitives/poly1305.py @@ -2,8 +2,6 @@ # 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 - from cryptography import utils from cryptography.exceptions import ( diff --git a/src/cryptography/hazmat/primitives/serialization/__init__.py b/src/cryptography/hazmat/primitives/serialization/__init__.py index c2f9b014a62d..0e2a952764d2 100644 --- a/src/cryptography/hazmat/primitives/serialization/__init__.py +++ b/src/cryptography/hazmat/primitives/serialization/__init__.py @@ -2,7 +2,6 @@ # 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 from cryptography.hazmat.primitives.serialization.base import ( BestAvailableEncryption, diff --git a/src/cryptography/hazmat/primitives/serialization/base.py b/src/cryptography/hazmat/primitives/serialization/base.py index fc27235c5cf2..bac610e23376 100644 --- a/src/cryptography/hazmat/primitives/serialization/base.py +++ b/src/cryptography/hazmat/primitives/serialization/base.py @@ -2,7 +2,6 @@ # 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 abc from enum import Enum diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs12.py b/src/cryptography/hazmat/primitives/serialization/pkcs12.py index 201f32941c1f..76f713a21c85 100644 --- a/src/cryptography/hazmat/primitives/serialization/pkcs12.py +++ b/src/cryptography/hazmat/primitives/serialization/pkcs12.py @@ -2,7 +2,6 @@ # 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 from cryptography import x509 from cryptography.hazmat.backends import _get_backend diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs7.py b/src/cryptography/hazmat/primitives/serialization/pkcs7.py index 1e11e28ef5b3..ed82b8be461a 100644 --- a/src/cryptography/hazmat/primitives/serialization/pkcs7.py +++ b/src/cryptography/hazmat/primitives/serialization/pkcs7.py @@ -2,7 +2,6 @@ # 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 from enum import Enum diff --git a/src/cryptography/hazmat/primitives/serialization/ssh.py b/src/cryptography/hazmat/primitives/serialization/ssh.py index 783586cb4366..d75ecb4aa55a 100644 --- a/src/cryptography/hazmat/primitives/serialization/ssh.py +++ b/src/cryptography/hazmat/primitives/serialization/ssh.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/src/cryptography/hazmat/primitives/twofactor/__init__.py b/src/cryptography/hazmat/primitives/twofactor/__init__.py index e71f9e67a334..8a8b30f2aa8f 100644 --- a/src/cryptography/hazmat/primitives/twofactor/__init__.py +++ b/src/cryptography/hazmat/primitives/twofactor/__init__.py @@ -2,8 +2,6 @@ # 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 - class InvalidToken(Exception): pass diff --git a/src/cryptography/hazmat/primitives/twofactor/hotp.py b/src/cryptography/hazmat/primitives/twofactor/hotp.py index c00eec0e548b..93c2f46a6929 100644 --- a/src/cryptography/hazmat/primitives/twofactor/hotp.py +++ b/src/cryptography/hazmat/primitives/twofactor/hotp.py @@ -2,7 +2,6 @@ # 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 struct diff --git a/src/cryptography/hazmat/primitives/twofactor/totp.py b/src/cryptography/hazmat/primitives/twofactor/totp.py index d59539b3f9db..649ccd4662c9 100644 --- a/src/cryptography/hazmat/primitives/twofactor/totp.py +++ b/src/cryptography/hazmat/primitives/twofactor/totp.py @@ -2,7 +2,6 @@ # 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 from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.backends import _get_backend diff --git a/src/cryptography/hazmat/primitives/twofactor/utils.py b/src/cryptography/hazmat/primitives/twofactor/utils.py index 0afa1ccc04b0..a96fb1eea029 100644 --- a/src/cryptography/hazmat/primitives/twofactor/utils.py +++ b/src/cryptography/hazmat/primitives/twofactor/utils.py @@ -2,7 +2,6 @@ # 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 base64 diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index 025f61623e54..c8a59871cc93 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -2,7 +2,6 @@ # 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 abc import inspect diff --git a/src/cryptography/x509/__init__.py b/src/cryptography/x509/__init__.py index 69630e4cba8b..793714693040 100644 --- a/src/cryptography/x509/__init__.py +++ b/src/cryptography/x509/__init__.py @@ -2,7 +2,6 @@ # 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 from cryptography.x509 import certificate_transparency from cryptography.x509.base import ( diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index f3bc872b9456..e841fbb804e9 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -2,7 +2,6 @@ # 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 abc import datetime diff --git a/src/cryptography/x509/certificate_transparency.py b/src/cryptography/x509/certificate_transparency.py index d00fe8126925..cbef28c75f8d 100644 --- a/src/cryptography/x509/certificate_transparency.py +++ b/src/cryptography/x509/certificate_transparency.py @@ -2,7 +2,6 @@ # 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 abc from enum import Enum diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index d1981704eef1..5bee5035e0c1 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -2,7 +2,6 @@ # 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 abc import datetime diff --git a/src/cryptography/x509/general_name.py b/src/cryptography/x509/general_name.py index 9be9d8c991e1..02b8e5eef112 100644 --- a/src/cryptography/x509/general_name.py +++ b/src/cryptography/x509/general_name.py @@ -2,7 +2,6 @@ # 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 abc import ipaddress diff --git a/src/cryptography/x509/name.py b/src/cryptography/x509/name.py index caf536f60381..8672f2618f7b 100644 --- a/src/cryptography/x509/name.py +++ b/src/cryptography/x509/name.py @@ -2,7 +2,6 @@ # 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 from enum import Enum diff --git a/src/cryptography/x509/ocsp.py b/src/cryptography/x509/ocsp.py index f8e27224ecaf..c6d3524aae19 100644 --- a/src/cryptography/x509/ocsp.py +++ b/src/cryptography/x509/ocsp.py @@ -2,7 +2,6 @@ # 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 abc import datetime diff --git a/src/cryptography/x509/oid.py b/src/cryptography/x509/oid.py index 2bf606e50d6b..2e3e60093b52 100644 --- a/src/cryptography/x509/oid.py +++ b/src/cryptography/x509/oid.py @@ -2,7 +2,6 @@ # 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 from cryptography.hazmat._oid import ObjectIdentifier from cryptography.hazmat.primitives import hashes diff --git a/tests/__init__.py b/tests/__init__.py index 4b540884df72..b509336233c2 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,5 +1,3 @@ # 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 diff --git a/tests/conftest.py b/tests/conftest.py index ece7a11e716a..77691c2d1491 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,7 +2,6 @@ # 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 pytest diff --git a/tests/doubles.py b/tests/doubles.py index 2ff1942f5b98..0a64606dde9a 100644 --- a/tests/doubles.py +++ b/tests/doubles.py @@ -2,7 +2,6 @@ # 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 from cryptography import utils from cryptography.hazmat.primitives import hashes, serialization diff --git a/tests/hazmat/__init__.py b/tests/hazmat/__init__.py index 4b540884df72..b509336233c2 100644 --- a/tests/hazmat/__init__.py +++ b/tests/hazmat/__init__.py @@ -1,5 +1,3 @@ # 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 diff --git a/tests/hazmat/backends/__init__.py b/tests/hazmat/backends/__init__.py index 4b540884df72..b509336233c2 100644 --- a/tests/hazmat/backends/__init__.py +++ b/tests/hazmat/backends/__init__.py @@ -1,5 +1,3 @@ # 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 diff --git a/tests/hazmat/backends/test_no_backend.py b/tests/hazmat/backends/test_no_backend.py index 67866929e71d..9c01d1368227 100644 --- a/tests/hazmat/backends/test_no_backend.py +++ b/tests/hazmat/backends/test_no_backend.py @@ -2,7 +2,6 @@ # 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 from cryptography.hazmat.backends import _get_backend, default_backend diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index 2808a003fda8..ff112c61cd7a 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -2,7 +2,6 @@ # 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 itertools import os diff --git a/tests/hazmat/backends/test_openssl_memleak.py b/tests/hazmat/backends/test_openssl_memleak.py index d8bc8660a830..4f64fcb8a5b0 100644 --- a/tests/hazmat/backends/test_openssl_memleak.py +++ b/tests/hazmat/backends/test_openssl_memleak.py @@ -2,7 +2,6 @@ # 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 json import os diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py index 4bc046b80fe4..fb9a1e363742 100644 --- a/tests/hazmat/bindings/test_openssl.py +++ b/tests/hazmat/bindings/test_openssl.py @@ -2,7 +2,6 @@ # 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 pytest diff --git a/tests/hazmat/primitives/__init__.py b/tests/hazmat/primitives/__init__.py index 4b540884df72..b509336233c2 100644 --- a/tests/hazmat/primitives/__init__.py +++ b/tests/hazmat/primitives/__init__.py @@ -1,5 +1,3 @@ # 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 diff --git a/tests/hazmat/primitives/fixtures_dh.py b/tests/hazmat/primitives/fixtures_dh.py index b766c4265837..3ed52d14d40c 100644 --- a/tests/hazmat/primitives/fixtures_dh.py +++ b/tests/hazmat/primitives/fixtures_dh.py @@ -2,7 +2,6 @@ # 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 from cryptography.hazmat.primitives.asymmetric import dh diff --git a/tests/hazmat/primitives/fixtures_dsa.py b/tests/hazmat/primitives/fixtures_dsa.py index d4568ead7306..eca0ec43168b 100644 --- a/tests/hazmat/primitives/fixtures_dsa.py +++ b/tests/hazmat/primitives/fixtures_dsa.py @@ -2,7 +2,6 @@ # 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 from cryptography.hazmat.primitives.asymmetric.dsa import ( DSAParameterNumbers, diff --git a/tests/hazmat/primitives/fixtures_ec.py b/tests/hazmat/primitives/fixtures_ec.py index d1d0a46ffe25..317c2ab243ef 100644 --- a/tests/hazmat/primitives/fixtures_ec.py +++ b/tests/hazmat/primitives/fixtures_ec.py @@ -2,7 +2,6 @@ # 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 from cryptography.hazmat.primitives.asymmetric import ec diff --git a/tests/hazmat/primitives/fixtures_rsa.py b/tests/hazmat/primitives/fixtures_rsa.py index 2c0627282130..bfb11bc8710a 100644 --- a/tests/hazmat/primitives/fixtures_rsa.py +++ b/tests/hazmat/primitives/fixtures_rsa.py @@ -2,7 +2,6 @@ # 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 from cryptography.hazmat.primitives.asymmetric.rsa import ( RSAPrivateNumbers, diff --git a/tests/hazmat/primitives/test_3des.py b/tests/hazmat/primitives/test_3des.py index d14dcad9f71f..f1bca78c0454 100644 --- a/tests/hazmat/primitives/test_3des.py +++ b/tests/hazmat/primitives/test_3des.py @@ -6,7 +6,6 @@ Test using the NIST Test Vectors """ -from __future__ import absolute_import, division, print_function import binascii import os diff --git a/tests/hazmat/primitives/test_aead.py b/tests/hazmat/primitives/test_aead.py index 270693182ed2..bc7f5ab114bf 100644 --- a/tests/hazmat/primitives/test_aead.py +++ b/tests/hazmat/primitives/test_aead.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_aes.py b/tests/hazmat/primitives/test_aes.py index f98ba6fddff8..099717801e0a 100644 --- a/tests/hazmat/primitives/test_aes.py +++ b/tests/hazmat/primitives/test_aes.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_aes_gcm.py b/tests/hazmat/primitives/test_aes_gcm.py index 8b71d12300c9..77f9c6f2757c 100644 --- a/tests/hazmat/primitives/test_aes_gcm.py +++ b/tests/hazmat/primitives/test_aes_gcm.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_arc4.py b/tests/hazmat/primitives/test_arc4.py index de20b7098ae7..be40b578c398 100644 --- a/tests/hazmat/primitives/test_arc4.py +++ b/tests/hazmat/primitives/test_arc4.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_asym_utils.py b/tests/hazmat/primitives/test_asym_utils.py index 70bff012fbcb..dd837af7f09f 100644 --- a/tests/hazmat/primitives/test_asym_utils.py +++ b/tests/hazmat/primitives/test_asym_utils.py @@ -2,7 +2,6 @@ # 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 pytest diff --git a/tests/hazmat/primitives/test_block.py b/tests/hazmat/primitives/test_block.py index 593199315a06..24df0e637935 100644 --- a/tests/hazmat/primitives/test_block.py +++ b/tests/hazmat/primitives/test_block.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/hazmat/primitives/test_blowfish.py b/tests/hazmat/primitives/test_blowfish.py index 5f7480ec9234..ca0aaaa7848f 100644 --- a/tests/hazmat/primitives/test_blowfish.py +++ b/tests/hazmat/primitives/test_blowfish.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_camellia.py b/tests/hazmat/primitives/test_camellia.py index b752345d3e44..f903c8156625 100644 --- a/tests/hazmat/primitives/test_camellia.py +++ b/tests/hazmat/primitives/test_camellia.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_cast5.py b/tests/hazmat/primitives/test_cast5.py index eff5d252f594..9b720594795a 100644 --- a/tests/hazmat/primitives/test_cast5.py +++ b/tests/hazmat/primitives/test_cast5.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_chacha20.py b/tests/hazmat/primitives/test_chacha20.py index eda4906ad4fe..48733911148e 100644 --- a/tests/hazmat/primitives/test_chacha20.py +++ b/tests/hazmat/primitives/test_chacha20.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_ciphers.py b/tests/hazmat/primitives/test_ciphers.py index 4d951a136c79..5fb6a916e117 100644 --- a/tests/hazmat/primitives/test_ciphers.py +++ b/tests/hazmat/primitives/test_ciphers.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_cmac.py b/tests/hazmat/primitives/test_cmac.py index 4ed92e7e4149..03c4cd8a6ca0 100644 --- a/tests/hazmat/primitives/test_cmac.py +++ b/tests/hazmat/primitives/test_cmac.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/hazmat/primitives/test_concatkdf.py b/tests/hazmat/primitives/test_concatkdf.py index f49e4cdcd98c..bb90bb15353d 100644 --- a/tests/hazmat/primitives/test_concatkdf.py +++ b/tests/hazmat/primitives/test_concatkdf.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/hazmat/primitives/test_constant_time.py b/tests/hazmat/primitives/test_constant_time.py index f681bd1f85f0..39e51b4052a7 100644 --- a/tests/hazmat/primitives/test_constant_time.py +++ b/tests/hazmat/primitives/test_constant_time.py @@ -2,7 +2,6 @@ # 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 pytest diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index bc5ed8fb0035..333ee56b08b5 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -2,7 +2,6 @@ # 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 binascii import itertools diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py index bda275064ea2..474da5df5682 100644 --- a/tests/hazmat/primitives/test_dsa.py +++ b/tests/hazmat/primitives/test_dsa.py @@ -2,7 +2,6 @@ # 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 itertools import os diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index 8361306f719b..354bab3462bd 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -2,7 +2,6 @@ # 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 binascii import itertools diff --git a/tests/hazmat/primitives/test_ed25519.py b/tests/hazmat/primitives/test_ed25519.py index 5b003d1e411e..be239026aa1c 100644 --- a/tests/hazmat/primitives/test_ed25519.py +++ b/tests/hazmat/primitives/test_ed25519.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_ed448.py b/tests/hazmat/primitives/test_ed448.py index 9a1f9056993c..6065ae8e4c3d 100644 --- a/tests/hazmat/primitives/test_ed448.py +++ b/tests/hazmat/primitives/test_ed448.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_hash_vectors.py b/tests/hazmat/primitives/test_hash_vectors.py index 9301b6217101..99adcf92300f 100644 --- a/tests/hazmat/primitives/test_hash_vectors.py +++ b/tests/hazmat/primitives/test_hash_vectors.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py index 06637f21d3ac..105f862d8619 100644 --- a/tests/hazmat/primitives/test_hashes.py +++ b/tests/hazmat/primitives/test_hashes.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/hazmat/primitives/test_hkdf.py b/tests/hazmat/primitives/test_hkdf.py index fa20f3a631e1..640dd60a76f1 100644 --- a/tests/hazmat/primitives/test_hkdf.py +++ b/tests/hazmat/primitives/test_hkdf.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_hkdf_vectors.py b/tests/hazmat/primitives/test_hkdf_vectors.py index 97385e203c19..7561369436ad 100644 --- a/tests/hazmat/primitives/test_hkdf_vectors.py +++ b/tests/hazmat/primitives/test_hkdf_vectors.py @@ -2,7 +2,6 @@ # 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 os diff --git a/tests/hazmat/primitives/test_hmac.py b/tests/hazmat/primitives/test_hmac.py index 70db4d5d4e33..618f47322cde 100644 --- a/tests/hazmat/primitives/test_hmac.py +++ b/tests/hazmat/primitives/test_hmac.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/hazmat/primitives/test_hmac_vectors.py b/tests/hazmat/primitives/test_hmac_vectors.py index b39df1a75e7c..fd2a4041dae1 100644 --- a/tests/hazmat/primitives/test_hmac_vectors.py +++ b/tests/hazmat/primitives/test_hmac_vectors.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/hazmat/primitives/test_idea.py b/tests/hazmat/primitives/test_idea.py index 1f766def082a..ea5dbb2f4188 100644 --- a/tests/hazmat/primitives/test_idea.py +++ b/tests/hazmat/primitives/test_idea.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_kbkdf.py b/tests/hazmat/primitives/test_kbkdf.py index bba9f5e72a2c..3f13a0c7c774 100644 --- a/tests/hazmat/primitives/test_kbkdf.py +++ b/tests/hazmat/primitives/test_kbkdf.py @@ -2,7 +2,6 @@ # 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 pytest diff --git a/tests/hazmat/primitives/test_kbkdf_vectors.py b/tests/hazmat/primitives/test_kbkdf_vectors.py index 462e04ec5a87..7545a85da7be 100644 --- a/tests/hazmat/primitives/test_kbkdf_vectors.py +++ b/tests/hazmat/primitives/test_kbkdf_vectors.py @@ -2,7 +2,6 @@ # 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 os diff --git a/tests/hazmat/primitives/test_keywrap.py b/tests/hazmat/primitives/test_keywrap.py index 9b91ccf36b33..947afb3e308a 100644 --- a/tests/hazmat/primitives/test_keywrap.py +++ b/tests/hazmat/primitives/test_keywrap.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_padding.py b/tests/hazmat/primitives/test_padding.py index b06c8339ce4a..b29d5a42e2f8 100644 --- a/tests/hazmat/primitives/test_padding.py +++ b/tests/hazmat/primitives/test_padding.py @@ -2,7 +2,6 @@ # 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 pytest diff --git a/tests/hazmat/primitives/test_pbkdf2hmac.py b/tests/hazmat/primitives/test_pbkdf2hmac.py index ec7ac799ca12..e8ee805edd32 100644 --- a/tests/hazmat/primitives/test_pbkdf2hmac.py +++ b/tests/hazmat/primitives/test_pbkdf2hmac.py @@ -2,7 +2,6 @@ # 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 pytest diff --git a/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py b/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py index 4b97b0d13a97..6b02540284ff 100644 --- a/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py +++ b/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py @@ -2,7 +2,6 @@ # 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 pytest diff --git a/tests/hazmat/primitives/test_pkcs12.py b/tests/hazmat/primitives/test_pkcs12.py index 297483e2f99d..9880666bbb1d 100644 --- a/tests/hazmat/primitives/test_pkcs12.py +++ b/tests/hazmat/primitives/test_pkcs12.py @@ -2,7 +2,6 @@ # 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 os diff --git a/tests/hazmat/primitives/test_pkcs7.py b/tests/hazmat/primitives/test_pkcs7.py index 3aeda299583a..5985863c6404 100644 --- a/tests/hazmat/primitives/test_pkcs7.py +++ b/tests/hazmat/primitives/test_pkcs7.py @@ -2,7 +2,6 @@ # 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 os diff --git a/tests/hazmat/primitives/test_poly1305.py b/tests/hazmat/primitives/test_poly1305.py index dd84b14aabf9..8cb40b3b13b1 100644 --- a/tests/hazmat/primitives/test_poly1305.py +++ b/tests/hazmat/primitives/test_poly1305.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 61c481504ecc..1e32b7f168a4 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -2,7 +2,6 @@ # 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 binascii import itertools diff --git a/tests/hazmat/primitives/test_scrypt.py b/tests/hazmat/primitives/test_scrypt.py index 52e7e153802a..6d68769705af 100644 --- a/tests/hazmat/primitives/test_scrypt.py +++ b/tests/hazmat/primitives/test_scrypt.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_seed.py b/tests/hazmat/primitives/test_seed.py index 66da97836a0a..e01aa0d8b45a 100644 --- a/tests/hazmat/primitives/test_seed.py +++ b/tests/hazmat/primitives/test_seed.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index 549c86d5551b..06e427acd21c 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -2,7 +2,6 @@ # 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 base64 import itertools diff --git a/tests/hazmat/primitives/test_x25519.py b/tests/hazmat/primitives/test_x25519.py index fd1137d9da48..a572e7bf0d69 100644 --- a/tests/hazmat/primitives/test_x25519.py +++ b/tests/hazmat/primitives/test_x25519.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_x448.py b/tests/hazmat/primitives/test_x448.py index 7b19b65ee97f..89423b67cc21 100644 --- a/tests/hazmat/primitives/test_x448.py +++ b/tests/hazmat/primitives/test_x448.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_x963_vectors.py b/tests/hazmat/primitives/test_x963_vectors.py index e3b54fc15516..846093b6b1f0 100644 --- a/tests/hazmat/primitives/test_x963_vectors.py +++ b/tests/hazmat/primitives/test_x963_vectors.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/primitives/test_x963kdf.py b/tests/hazmat/primitives/test_x963kdf.py index af1c927e1331..a02ea11dd0a7 100644 --- a/tests/hazmat/primitives/test_x963kdf.py +++ b/tests/hazmat/primitives/test_x963kdf.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/hazmat/primitives/twofactor/__init__.py b/tests/hazmat/primitives/twofactor/__init__.py index 4b540884df72..b509336233c2 100644 --- a/tests/hazmat/primitives/twofactor/__init__.py +++ b/tests/hazmat/primitives/twofactor/__init__.py @@ -1,5 +1,3 @@ # 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 diff --git a/tests/hazmat/primitives/twofactor/test_hotp.py b/tests/hazmat/primitives/twofactor/test_hotp.py index 08bfd7ebebd0..2b65cde963de 100644 --- a/tests/hazmat/primitives/twofactor/test_hotp.py +++ b/tests/hazmat/primitives/twofactor/test_hotp.py @@ -2,7 +2,6 @@ # 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 os diff --git a/tests/hazmat/primitives/twofactor/test_totp.py b/tests/hazmat/primitives/twofactor/test_totp.py index 06d86008af3e..f590896801ea 100644 --- a/tests/hazmat/primitives/twofactor/test_totp.py +++ b/tests/hazmat/primitives/twofactor/test_totp.py @@ -2,7 +2,6 @@ # 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 pytest diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py index 118b55951709..46ca52dcb5b1 100644 --- a/tests/hazmat/primitives/utils.py +++ b/tests/hazmat/primitives/utils.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/hazmat/test_der.py b/tests/hazmat/test_der.py index ef2052f50026..8820ac1865a4 100644 --- a/tests/hazmat/test_der.py +++ b/tests/hazmat/test_der.py @@ -2,7 +2,6 @@ # 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 pytest diff --git a/tests/hazmat/test_oid.py b/tests/hazmat/test_oid.py index 5589ed976c0c..8fa7d2b063f6 100644 --- a/tests/hazmat/test_oid.py +++ b/tests/hazmat/test_oid.py @@ -2,7 +2,6 @@ # 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 pytest diff --git a/tests/hypothesis/__init__.py b/tests/hypothesis/__init__.py index 4b540884df72..b509336233c2 100644 --- a/tests/hypothesis/__init__.py +++ b/tests/hypothesis/__init__.py @@ -1,5 +1,3 @@ # 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 diff --git a/tests/test_cryptography_utils.py b/tests/test_cryptography_utils.py index 0158ef351fe0..510537d52e9f 100644 --- a/tests/test_cryptography_utils.py +++ b/tests/test_cryptography_utils.py @@ -2,7 +2,6 @@ # 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 pytest diff --git a/tests/test_fernet.py b/tests/test_fernet.py index 5c5ed46f3930..8390ea6e450e 100644 --- a/tests/test_fernet.py +++ b/tests/test_fernet.py @@ -2,7 +2,6 @@ # 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 base64 import calendar diff --git a/tests/test_utils.py b/tests/test_utils.py index d6afa3b34902..389638f151a8 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -2,7 +2,6 @@ # 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 binascii import os diff --git a/tests/test_warnings.py b/tests/test_warnings.py index 073c699bc084..d08f31e3a5a7 100644 --- a/tests/test_warnings.py +++ b/tests/test_warnings.py @@ -2,7 +2,6 @@ # 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 sys import types diff --git a/tests/utils.py b/tests/utils.py index 497fde83f0a5..4fb7a684540f 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -2,7 +2,6 @@ # 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 binascii import collections diff --git a/tests/wycheproof/test_aes.py b/tests/wycheproof/test_aes.py index 9992095ae8c3..43e7164cee56 100644 --- a/tests/wycheproof/test_aes.py +++ b/tests/wycheproof/test_aes.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/wycheproof/test_chacha20poly1305.py b/tests/wycheproof/test_chacha20poly1305.py index 48023ca63d70..936fa8dc020a 100644 --- a/tests/wycheproof/test_chacha20poly1305.py +++ b/tests/wycheproof/test_chacha20poly1305.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/wycheproof/test_cmac.py b/tests/wycheproof/test_cmac.py index bef858395c9c..11a1d34b76df 100644 --- a/tests/wycheproof/test_cmac.py +++ b/tests/wycheproof/test_cmac.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/wycheproof/test_dsa.py b/tests/wycheproof/test_dsa.py index 9185b3e2f4e0..19d2ce486844 100644 --- a/tests/wycheproof/test_dsa.py +++ b/tests/wycheproof/test_dsa.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/wycheproof/test_ecdh.py b/tests/wycheproof/test_ecdh.py index b89dc68ce7fc..a25337de1de9 100644 --- a/tests/wycheproof/test_ecdh.py +++ b/tests/wycheproof/test_ecdh.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/wycheproof/test_ecdsa.py b/tests/wycheproof/test_ecdsa.py index 802bb9f00b3e..b1a98253d089 100644 --- a/tests/wycheproof/test_ecdsa.py +++ b/tests/wycheproof/test_ecdsa.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/wycheproof/test_eddsa.py b/tests/wycheproof/test_eddsa.py index 42c1498afff1..13501a7babcd 100644 --- a/tests/wycheproof/test_eddsa.py +++ b/tests/wycheproof/test_eddsa.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/wycheproof/test_hkdf.py b/tests/wycheproof/test_hkdf.py index 3e1687ea3105..0f553a919394 100644 --- a/tests/wycheproof/test_hkdf.py +++ b/tests/wycheproof/test_hkdf.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/wycheproof/test_hmac.py b/tests/wycheproof/test_hmac.py index 0cf908fe90c1..93433c1c1658 100644 --- a/tests/wycheproof/test_hmac.py +++ b/tests/wycheproof/test_hmac.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/wycheproof/test_keywrap.py b/tests/wycheproof/test_keywrap.py index 9c7d522e61e0..c04ac4907b39 100644 --- a/tests/wycheproof/test_keywrap.py +++ b/tests/wycheproof/test_keywrap.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/wycheproof/test_rsa.py b/tests/wycheproof/test_rsa.py index 926bb44e999f..a3712cc755ab 100644 --- a/tests/wycheproof/test_rsa.py +++ b/tests/wycheproof/test_rsa.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/wycheproof/test_utils.py b/tests/wycheproof/test_utils.py index 593d26bdec91..b0c36d4797d8 100644 --- a/tests/wycheproof/test_utils.py +++ b/tests/wycheproof/test_utils.py @@ -2,7 +2,6 @@ # 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 from ..utils import WycheproofTest diff --git a/tests/wycheproof/test_x25519.py b/tests/wycheproof/test_x25519.py index ce2a965e3a42..926a5e898ff2 100644 --- a/tests/wycheproof/test_x25519.py +++ b/tests/wycheproof/test_x25519.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/wycheproof/test_x448.py b/tests/wycheproof/test_x448.py index fcac80996f74..6c77457a71ef 100644 --- a/tests/wycheproof/test_x448.py +++ b/tests/wycheproof/test_x448.py @@ -2,7 +2,6 @@ # 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 binascii diff --git a/tests/x509/test_ocsp.py b/tests/x509/test_ocsp.py index 10dac033db29..38e1ca5b0873 100644 --- a/tests/x509/test_ocsp.py +++ b/tests/x509/test_ocsp.py @@ -2,7 +2,6 @@ # 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 base64 import datetime diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index f2acf9559405..60d02a1ce092 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -3,7 +3,6 @@ # 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 binascii import collections diff --git a/tests/x509/test_x509_crlbuilder.py b/tests/x509/test_x509_crlbuilder.py index a044c2f288fd..036769e972cc 100644 --- a/tests/x509/test_x509_crlbuilder.py +++ b/tests/x509/test_x509_crlbuilder.py @@ -2,7 +2,6 @@ # 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 datetime diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index fcde4ca49c78..b41e11eee1cb 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -2,7 +2,6 @@ # 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 binascii import datetime diff --git a/tests/x509/test_x509_revokedcertbuilder.py b/tests/x509/test_x509_revokedcertbuilder.py index 301788ca5920..0d24f53792f8 100644 --- a/tests/x509/test_x509_revokedcertbuilder.py +++ b/tests/x509/test_x509_revokedcertbuilder.py @@ -2,7 +2,6 @@ # 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 datetime diff --git a/vectors/cryptography_vectors/__about__.py b/vectors/cryptography_vectors/__about__.py index 82a389b024a4..55e68f44ee40 100644 --- a/vectors/cryptography_vectors/__about__.py +++ b/vectors/cryptography_vectors/__about__.py @@ -2,8 +2,6 @@ # 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 - __all__ = [ "__title__", "__summary__", diff --git a/vectors/cryptography_vectors/__init__.py b/vectors/cryptography_vectors/__init__.py index f39ffe03ab0c..fce9abadc118 100644 --- a/vectors/cryptography_vectors/__init__.py +++ b/vectors/cryptography_vectors/__init__.py @@ -2,8 +2,6 @@ # 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 os from cryptography_vectors.__about__ import ( diff --git a/vectors/setup.py b/vectors/setup.py index 884148286fe7..5aaa62101978 100644 --- a/vectors/setup.py +++ b/vectors/setup.py @@ -4,8 +4,6 @@ # 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 os from setuptools import find_packages, setup From 5528a3182fdd6ed1c44c126d451a87bcf39e79de Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 9 Dec 2020 02:16:01 -0500 Subject: [PATCH 0006/2380] Remove utils.int_from_bytes (#5609) --- src/cryptography/hazmat/_der.py | 4 ++-- src/cryptography/hazmat/primitives/asymmetric/ec.py | 4 ++-- .../hazmat/primitives/serialization/ssh.py | 2 +- src/cryptography/utils.py | 12 +++++++++--- src/cryptography/x509/base.py | 3 +-- tests/hazmat/primitives/test_dh.py | 11 +++++------ tests/test_cryptography_utils.py | 6 ------ tests/x509/test_x509.py | 5 ++--- 8 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/cryptography/hazmat/_der.py b/src/cryptography/hazmat/_der.py index 11bfe1bf172d..299a67fa1ac3 100644 --- a/src/cryptography/hazmat/_der.py +++ b/src/cryptography/hazmat/_der.py @@ -5,7 +5,7 @@ import six -from cryptography.utils import int_from_bytes, int_to_bytes +from cryptography.utils import int_to_bytes # This module contains a lightweight DER encoder and decoder. See X.690 for the @@ -128,7 +128,7 @@ def as_integer(self): raise ValueError( "Invalid DER input: integer not minimally-encoded" ) - return int_from_bytes(self.data, "big") + return int.from_bytes(self.data, "big") def encode_der_integer(x): diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index fe62a07fee5b..f2a91c3fd995 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -391,8 +391,8 @@ def from_encoded_point(cls, curve, data): # key_size is in bits. Convert to bytes and round up byte_length = (curve.key_size + 7) // 8 if len(data) == 2 * byte_length + 1: - x = utils.int_from_bytes(data[1 : byte_length + 1], "big") - y = utils.int_from_bytes(data[byte_length + 1 :], "big") + x = int.from_bytes(data[1 : byte_length + 1], "big") + y = int.from_bytes(data[byte_length + 1 :], "big") return cls(x, y, curve) else: raise ValueError("Invalid elliptic curve point data length") diff --git a/src/cryptography/hazmat/primitives/serialization/ssh.py b/src/cryptography/hazmat/primitives/serialization/ssh.py index d75ecb4aa55a..6328c06e780b 100644 --- a/src/cryptography/hazmat/primitives/serialization/ssh.py +++ b/src/cryptography/hazmat/primitives/serialization/ssh.py @@ -138,7 +138,7 @@ def _get_mpint(data): val, data = _get_sshstr(data) if val and six.indexbytes(val, 0) > 0x7F: raise ValueError("Invalid data") - return utils.int_from_bytes(val, "big"), data + return int.from_bytes(val, "big"), data def _to_mpint(val): diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index c8a59871cc93..2c76f9ffc3f7 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -20,6 +20,7 @@ class CryptographyDeprecationWarning(UserWarning): # cycle ends. PersistentlyDeprecated2017 = CryptographyDeprecationWarning PersistentlyDeprecated2019 = CryptographyDeprecationWarning +DeprecatedIn34 = CryptographyDeprecationWarning def _check_bytes(name, value): @@ -57,9 +58,6 @@ def register_decorator(klass): return register_decorator -int_from_bytes = int.from_bytes - - def int_to_bytes(integer, length=None): return integer.to_bytes( length or (integer.bit_length() + 7) // 8 or 1, "big" @@ -140,3 +138,11 @@ def inner(instance): return result return property(inner) + + +int_from_bytes = deprecated( + int.from_bytes, + __name__, + "int_from_bytes is deprecated, use int.from_bytes instead", + DeprecatedIn34, +) diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index e841fbb804e9..6fad3358a33e 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -10,7 +10,6 @@ import six -from cryptography import utils from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.primitives.asymmetric import ( dsa, @@ -888,4 +887,4 @@ def build(self, backend=None): def random_serial_number(): - return utils.int_from_bytes(os.urandom(20), "big") >> 1 + return int.from_bytes(os.urandom(20), "big") >> 1 diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index 333ee56b08b5..8a670a914300 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -16,7 +16,6 @@ ) from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import dh -from cryptography.utils import int_from_bytes from .fixtures_dh import FFDH3072_P from ...doubles import DummyKeySerializationEncryption @@ -170,7 +169,7 @@ def test_dh_parameters_supported(self, backend): ), ) def test_dh_parameters_allows_rfc3526_groups(self, backend, vector): - p = int_from_bytes(binascii.unhexlify(vector["p"]), "big") + p = int.from_bytes(binascii.unhexlify(vector["p"]), "big") if ( backend._fips_enabled and p.bit_length() < backend._fips_dh_min_modulus @@ -308,7 +307,7 @@ def test_exchange_algorithm(self, backend): key2 = parameters.generate_private_key() shared_key_bytes = key2.exchange(key1.public_key()) - symkey = int_from_bytes(shared_key_bytes, "big") + symkey = int.from_bytes(shared_key_bytes, "big") symkey_manual = pow( key1.public_key().public_numbers().y, @@ -421,7 +420,7 @@ def test_dh_vectors(self, backend, vector): key = private.private_key(backend) symkey = key.exchange(public.public_key(backend)) - assert int_from_bytes(symkey, "big") == int(vector["k"], 16) + assert int.from_bytes(symkey, "big") == int(vector["k"], 16) @pytest.mark.skip_fips(reason="non-FIPS parameters") @pytest.mark.parametrize( @@ -443,8 +442,8 @@ def test_dh_vectors_with_q(self, backend, vector): symkey1 = key1.exchange(public2.public_key(backend)) symkey2 = key2.exchange(public1.public_key(backend)) - assert int_from_bytes(symkey1, "big") == int(vector["z"], 16) - assert int_from_bytes(symkey2, "big") == int(vector["z"], 16) + assert int.from_bytes(symkey1, "big") == int(vector["z"], 16) + assert int.from_bytes(symkey2, "big") == int(vector["z"], 16) @pytest.mark.requires_backend_interface(interface=DHBackend) diff --git a/tests/test_cryptography_utils.py b/tests/test_cryptography_utils.py index 510537d52e9f..ba6da5c50a05 100644 --- a/tests/test_cryptography_utils.py +++ b/tests/test_cryptography_utils.py @@ -8,12 +8,6 @@ from cryptography import utils -def test_int_from_bytes_bytearray(): - assert utils.int_from_bytes(bytearray(b"\x02\x10"), "big") == 528 - with pytest.raises(TypeError): - utils.int_from_bytes(["list", "is", "not", "bytes"], "big") - - class TestCachedProperty(object): def test_simple(self): accesses = [] diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 60d02a1ce092..78f591b1ee74 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -49,7 +49,6 @@ from cryptography.hazmat.primitives.asymmetric.utils import ( decode_dss_signature, ) -from cryptography.utils import int_from_bytes from cryptography.x509.name import _ASN1Type from cryptography.x509.oid import ( AuthorityInformationAccessOID, @@ -5184,7 +5183,7 @@ def load_key(self, backend): os.path.join("asymmetric", "DH", "rfc3526.txt"), load_nist_vectors, )[1] - p = int_from_bytes(binascii.unhexlify(vector["p"]), "big") + p = int.from_bytes(binascii.unhexlify(vector["p"]), "big") params = dh.DHParameterNumbers(p, int(vector["g"])) param = params.parameters(backend) return param.generate_private_key() @@ -5248,5 +5247,5 @@ def notrandom(size): serial_number = x509.random_serial_number() - assert serial_number == utils.int_from_bytes(sample_data, "big") >> 1 + assert serial_number == int.from_bytes(sample_data, "big") >> 1 assert serial_number.bit_length() < 160 From 08afd16f28d22c4530b36a42a7504b0a03a594e3 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 9 Dec 2020 09:04:20 -0600 Subject: [PATCH 0007/2380] we didn't actually commit the final doc fixes for the recover PR (#5614) --- docs/hazmat/primitives/asymmetric/rsa.rst | 18 +++++++++--------- .../hazmat/backends/openssl/rsa.py | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst index 33f402b65a43..09b8f76d708a 100644 --- a/docs/hazmat/primitives/asymmetric/rsa.rst +++ b/docs/hazmat/primitives/asymmetric/rsa.rst @@ -718,8 +718,8 @@ Key interfaces .. versionadded:: 3.3 - Recovers the signed data from the signature. The data contains the - digest of the original message string. The ``padding`` and + Recovers the signed data from the signature. The data typically contains + the digest of the original message string. The ``padding`` and ``algorithm`` parameters must match the ones used when the signature was created for the recovery to succeed. @@ -729,20 +729,20 @@ Key interfaces For :class:`~cryptography.hazmat.primitives.asymmetric.padding.PKCS1v15` - padding, this returns the data after removing the padding layer. For - standard signatures the data contains the full ``DigestInfo`` structure. - For non-standard signatures, any data can be returned, including zero- - length data. + padding, this method returns the data after removing the padding layer. + For standard signatures the data contains the full ``DigestInfo`` + structure. For non-standard signatures, any data can be returned, + including zero-length data. Normally you should use the :meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey.verify` function to validate the signature. But for some non-standard signature formats you may need to explicitly recover and validate the signed - data. Following are some examples: + data. The following are some examples: - Some old Thawte and Verisign timestamp certificates without ``DigestInfo``. - - Signed MD5/SHA1 hashes in TLS 1.1 or earlier (RFC 4346, section 4.7). - - IKE version 1 signatures without ``DigestInfo`` (RFC 2409, section 5.1). + - Signed MD5/SHA1 hashes in TLS 1.1 or earlier (:rfc:`4346`, section 4.7). + - IKE version 1 signatures without ``DigestInfo`` (:rfc:`2409`, section 5.1). :param bytes signature: The signature. diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py index bbdd73525f75..15d2f4f39da5 100644 --- a/src/cryptography/hazmat/backends/openssl/rsa.py +++ b/src/cryptography/hazmat/backends/openssl/rsa.py @@ -275,7 +275,7 @@ def _rsa_sig_recover(backend, padding, algorithm, public_key, signature): # Attempt to keep the rest of the code in this function as constant/time # as possible. See the comment in _enc_dec_rsa_pkey_ctx. Note that the - # outlen parameter is used even though its value may be undefined in the + # buflen parameter is used even though its value may be undefined in the # error case. Due to the tolerant nature of Python slicing this does not # trigger any exceptions. maxlen = backend._lib.EVP_PKEY_size(public_key._evp_pkey) From e66db8079d3fbd0110e87ece1fd48f4bfd9e48b9 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 9 Dec 2020 10:13:48 -0500 Subject: [PATCH 0008/2380] Complete removal of py2 (#5533) * Drop Python 2 * Black everything --- setup.py | 2 +- src/cryptography/fernet.py | 4 +- src/cryptography/hazmat/_der.py | 18 ++++---- .../hazmat/backends/interfaces.py | 41 ++++++------------- .../hazmat/backends/openssl/backend.py | 2 - .../hazmat/backends/openssl/decode_asn1.py | 4 +- .../hazmat/backends/openssl/encode_asn1.py | 4 +- .../hazmat/primitives/asymmetric/__init__.py | 8 +--- .../hazmat/primitives/asymmetric/dh.py | 24 ++++------- .../hazmat/primitives/asymmetric/dsa.py | 27 +++++------- .../hazmat/primitives/asymmetric/ec.py | 29 +++++-------- .../hazmat/primitives/asymmetric/ed25519.py | 8 +--- .../hazmat/primitives/asymmetric/ed448.py | 8 +--- .../hazmat/primitives/asymmetric/padding.py | 7 +--- .../hazmat/primitives/asymmetric/rsa.py | 27 +++++------- .../hazmat/primitives/asymmetric/x25519.py | 8 +--- .../hazmat/primitives/asymmetric/x448.py | 8 +--- .../hazmat/primitives/ciphers/base.py | 20 +++------ .../hazmat/primitives/ciphers/modes.py | 17 +++----- src/cryptography/hazmat/primitives/hashes.py | 15 +++---- .../hazmat/primitives/kdf/__init__.py | 5 +-- .../hazmat/primitives/kdf/hkdf.py | 4 +- .../hazmat/primitives/kdf/kbkdf.py | 2 - src/cryptography/hazmat/primitives/padding.py | 11 ++--- .../hazmat/primitives/serialization/base.py | 5 +-- .../hazmat/primitives/serialization/ssh.py | 6 +-- .../hazmat/primitives/twofactor/hotp.py | 6 +-- .../hazmat/primitives/twofactor/utils.py | 3 +- src/cryptography/x509/base.py | 18 +++----- .../x509/certificate_transparency.py | 5 +-- src/cryptography/x509/extensions.py | 22 ++++------ src/cryptography/x509/general_name.py | 11 ++--- src/cryptography/x509/name.py | 4 +- src/cryptography/x509/ocsp.py | 8 +--- tests/hazmat/primitives/test_padding.py | 4 +- tests/test_fernet.py | 4 +- tests/test_interfaces.py | 17 +++----- tests/utils.py | 10 ++--- 38 files changed, 138 insertions(+), 288 deletions(-) diff --git a/setup.py b/setup.py index 1d04eeaee6d2..1348e9be5797 100644 --- a/setup.py +++ b/setup.py @@ -77,7 +77,7 @@ ), include_package_data=True, python_requires=">=3.6", - install_requires=["six >= 1.4.1"] + setup_requirements, + install_requires=setup_requirements, setup_requires=setup_requirements, extras_require={ "test": [ diff --git a/src/cryptography/fernet.py b/src/cryptography/fernet.py index f01ba4f40871..e47df71ce937 100644 --- a/src/cryptography/fernet.py +++ b/src/cryptography/fernet.py @@ -9,8 +9,6 @@ import struct import time -import six - from cryptography import utils from cryptography.exceptions import InvalidSignature from cryptography.hazmat.backends import _get_backend @@ -96,7 +94,7 @@ def _get_unverified_token_data(token): except (TypeError, binascii.Error): raise InvalidToken - if not data or six.indexbytes(data, 0) != 0x80: + if not data or data[0] != 0x80: raise InvalidToken try: diff --git a/src/cryptography/hazmat/_der.py b/src/cryptography/hazmat/_der.py index 299a67fa1ac3..e00e97e9f5a5 100644 --- a/src/cryptography/hazmat/_der.py +++ b/src/cryptography/hazmat/_der.py @@ -3,8 +3,6 @@ # for complete details. -import six - from cryptography.utils import int_to_bytes @@ -52,7 +50,7 @@ def check_empty(self): def read_byte(self): if len(self.data) < 1: raise ValueError("Invalid DER input: insufficient data") - ret = six.indexbytes(self.data, 0) + ret = self.data[0] self.data = self.data[1:] return ret @@ -110,20 +108,20 @@ def read_single_element(self, expected_tag): return self.read_element(expected_tag) def read_optional_element(self, expected_tag): - if len(self.data) > 0 and six.indexbytes(self.data, 0) == expected_tag: + if len(self.data) > 0 and self.data[0] == expected_tag: return self.read_element(expected_tag) return None def as_integer(self): if len(self.data) == 0: raise ValueError("Invalid DER input: empty integer contents") - first = six.indexbytes(self.data, 0) + first = self.data[0] if first & 0x80 == 0x80: raise ValueError("Negative DER integers are not supported") # The first 9 bits must not all be zero or all be ones. Otherwise, the # encoding should have been one byte shorter. if len(self.data) > 1: - second = six.indexbytes(self.data, 1) + second = self.data[1] if first == 0 and second & 0x80 == 0: raise ValueError( "Invalid DER input: integer not minimally-encoded" @@ -132,7 +130,7 @@ def as_integer(self): def encode_der_integer(x): - if not isinstance(x, six.integer_types): + if not isinstance(x, int): raise ValueError("Value must be an integer") if x < 0: raise ValueError("Negative integers are not supported") @@ -144,12 +142,12 @@ def encode_der(tag, *children): length = 0 for child in children: length += len(child) - chunks = [six.int2byte(tag)] + chunks = [bytes([tag])] if length < 0x80: - chunks.append(six.int2byte(length)) + chunks.append(bytes([length])) else: length_bytes = int_to_bytes(length) - chunks.append(six.int2byte(0x80 | len(length_bytes))) + chunks.append(bytes([0x80 | len(length_bytes)])) chunks.append(length_bytes) chunks.extend(children) return b"".join(chunks) diff --git a/src/cryptography/hazmat/backends/interfaces.py b/src/cryptography/hazmat/backends/interfaces.py index d5105030d92c..c5dfed3114c6 100644 --- a/src/cryptography/hazmat/backends/interfaces.py +++ b/src/cryptography/hazmat/backends/interfaces.py @@ -5,11 +5,8 @@ import abc -import six - -@six.add_metaclass(abc.ABCMeta) -class CipherBackend(object): +class CipherBackend(metaclass=abc.ABCMeta): @abc.abstractmethod def cipher_supported(self, cipher, mode): """ @@ -29,8 +26,7 @@ def create_symmetric_decryption_ctx(self, cipher, mode): """ -@six.add_metaclass(abc.ABCMeta) -class HashBackend(object): +class HashBackend(metaclass=abc.ABCMeta): @abc.abstractmethod def hash_supported(self, algorithm): """ @@ -44,8 +40,7 @@ def create_hash_ctx(self, algorithm): """ -@six.add_metaclass(abc.ABCMeta) -class HMACBackend(object): +class HMACBackend(metaclass=abc.ABCMeta): @abc.abstractmethod def hmac_supported(self, algorithm): """ @@ -60,8 +55,7 @@ def create_hmac_ctx(self, key, algorithm): """ -@six.add_metaclass(abc.ABCMeta) -class CMACBackend(object): +class CMACBackend(metaclass=abc.ABCMeta): @abc.abstractmethod def cmac_algorithm_supported(self, algorithm): """ @@ -75,8 +69,7 @@ def create_cmac_ctx(self, algorithm): """ -@six.add_metaclass(abc.ABCMeta) -class PBKDF2HMACBackend(object): +class PBKDF2HMACBackend(metaclass=abc.ABCMeta): @abc.abstractmethod def pbkdf2_hmac_supported(self, algorithm): """ @@ -93,8 +86,7 @@ def derive_pbkdf2_hmac( """ -@six.add_metaclass(abc.ABCMeta) -class RSABackend(object): +class RSABackend(metaclass=abc.ABCMeta): @abc.abstractmethod def generate_rsa_private_key(self, public_exponent, key_size): """ @@ -128,8 +120,7 @@ def load_rsa_public_numbers(self, numbers): """ -@six.add_metaclass(abc.ABCMeta) -class DSABackend(object): +class DSABackend(metaclass=abc.ABCMeta): @abc.abstractmethod def generate_dsa_parameters(self, key_size): """ @@ -180,8 +171,7 @@ def load_dsa_parameter_numbers(self, numbers): """ -@six.add_metaclass(abc.ABCMeta) -class EllipticCurveBackend(object): +class EllipticCurveBackend(metaclass=abc.ABCMeta): @abc.abstractmethod def elliptic_curve_signature_algorithm_supported( self, signature_algorithm, curve @@ -228,8 +218,7 @@ def derive_elliptic_curve_private_key(self, private_value, curve): """ -@six.add_metaclass(abc.ABCMeta) -class PEMSerializationBackend(object): +class PEMSerializationBackend(metaclass=abc.ABCMeta): @abc.abstractmethod def load_pem_private_key(self, data, password): """ @@ -250,8 +239,7 @@ def load_pem_parameters(self, data): """ -@six.add_metaclass(abc.ABCMeta) -class DERSerializationBackend(object): +class DERSerializationBackend(metaclass=abc.ABCMeta): @abc.abstractmethod def load_der_private_key(self, data, password): """ @@ -272,8 +260,7 @@ def load_der_parameters(self, data): """ -@six.add_metaclass(abc.ABCMeta) -class X509Backend(object): +class X509Backend(metaclass=abc.ABCMeta): @abc.abstractmethod def load_pem_x509_certificate(self, data): """ @@ -331,8 +318,7 @@ def x509_name_bytes(self, name): """ -@six.add_metaclass(abc.ABCMeta) -class DHBackend(object): +class DHBackend(metaclass=abc.ABCMeta): @abc.abstractmethod def generate_dh_parameters(self, generator, key_size): """ @@ -386,8 +372,7 @@ def dh_x942_serialization_supported(self): """ -@six.add_metaclass(abc.ABCMeta) -class ScryptBackend(object): +class ScryptBackend(metaclass=abc.ABCMeta): @abc.abstractmethod def derive_scrypt(self, key_material, salt, length, n, r, p): """ diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 8d6412d46cc7..76fe79f73615 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -9,8 +9,6 @@ import warnings from contextlib import contextmanager -from six.moves import range - from cryptography import utils, x509 from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat._der import ( diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index f5f5c6a4a55f..96ba4cdbc42c 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -6,8 +6,6 @@ import datetime import ipaddress -import six - from cryptography import x509 from cryptography.hazmat._der import DERReader, INTEGER, NULL, SEQUENCE from cryptography.x509.extensions import _TLS_FEATURE_TYPE_TO_ENUM @@ -594,7 +592,7 @@ def _decode_dist_points(backend, cdps): def _decode_reasons(backend, reasons): # We will check each bit from RFC 5280 enum_reasons = [] - for bit_position, reason in six.iteritems(_REASON_BIT_MAPPING): + for bit_position, reason in _REASON_BIT_MAPPING.items(): if backend._lib.ASN1_BIT_STRING_get_bit(reasons, bit_position): enum_reasons.append(reason) diff --git a/src/cryptography/hazmat/backends/openssl/encode_asn1.py b/src/cryptography/hazmat/backends/openssl/encode_asn1.py index 1a24a4516222..0daae661367a 100644 --- a/src/cryptography/hazmat/backends/openssl/encode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/encode_asn1.py @@ -6,8 +6,6 @@ import calendar import ipaddress -import six - from cryptography import utils, x509 from cryptography.hazmat.backends.openssl.decode_asn1 import ( _CRL_ENTRY_REASON_ENUM_TO_CODE, @@ -205,7 +203,7 @@ def _encode_certificate_policies(backend, certificate_policies): backend.openssl_assert(pqi != backend._ffi.NULL) res = backend._lib.sk_POLICYQUALINFO_push(pqis, pqi) backend.openssl_assert(res >= 1) - if isinstance(qualifier, six.text_type): + if isinstance(qualifier, str): pqi.pqualid = _txt2obj( backend, x509.OID_CPS_QUALIFIER.dotted_string ) diff --git a/src/cryptography/hazmat/primitives/asymmetric/__init__.py b/src/cryptography/hazmat/primitives/asymmetric/__init__.py index 67a46c225288..efa23a6e8cd7 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/__init__.py +++ b/src/cryptography/hazmat/primitives/asymmetric/__init__.py @@ -5,11 +5,8 @@ import abc -import six - -@six.add_metaclass(abc.ABCMeta) -class AsymmetricSignatureContext(object): +class AsymmetricSignatureContext(metaclass=abc.ABCMeta): @abc.abstractmethod def update(self, data): """ @@ -23,8 +20,7 @@ def finalize(self): """ -@six.add_metaclass(abc.ABCMeta) -class AsymmetricVerificationContext(object): +class AsymmetricVerificationContext(metaclass=abc.ABCMeta): @abc.abstractmethod def update(self, data): """ diff --git a/src/cryptography/hazmat/primitives/asymmetric/dh.py b/src/cryptography/hazmat/primitives/asymmetric/dh.py index 1441877c30c9..f954afbbbd03 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dh.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dh.py @@ -5,8 +5,6 @@ import abc -import six - from cryptography import utils from cryptography.hazmat.backends import _get_backend @@ -21,7 +19,7 @@ def generate_parameters(generator, key_size, backend=None): class DHPrivateNumbers(object): def __init__(self, x, public_numbers): - if not isinstance(x, six.integer_types): + if not isinstance(x, int): raise TypeError("x must be an integer.") if not isinstance(public_numbers, DHPublicNumbers): @@ -54,7 +52,7 @@ def private_key(self, backend=None): class DHPublicNumbers(object): def __init__(self, y, parameter_numbers): - if not isinstance(y, six.integer_types): + if not isinstance(y, int): raise TypeError("y must be an integer.") if not isinstance(parameter_numbers, DHParameterNumbers): @@ -87,11 +85,9 @@ def public_key(self, backend=None): class DHParameterNumbers(object): def __init__(self, p, g, q=None): - if not isinstance(p, six.integer_types) or not isinstance( - g, six.integer_types - ): + if not isinstance(p, int) or not isinstance(g, int): raise TypeError("p and g must be integers") - if q is not None and not isinstance(q, six.integer_types): + if q is not None and not isinstance(q, int): raise TypeError("q must be integer or None") if g < 2: @@ -126,8 +122,7 @@ def parameters(self, backend=None): q = utils.read_only_property("_q") -@six.add_metaclass(abc.ABCMeta) -class DHParameters(object): +class DHParameters(metaclass=abc.ABCMeta): @abc.abstractmethod def generate_private_key(self): """ @@ -150,8 +145,7 @@ def parameter_numbers(self): DHParametersWithSerialization = DHParameters -@six.add_metaclass(abc.ABCMeta) -class DHPrivateKey(object): +class DHPrivateKey(metaclass=abc.ABCMeta): @abc.abstractproperty def key_size(self): """ @@ -178,8 +172,7 @@ def exchange(self, peer_public_key): """ -@six.add_metaclass(abc.ABCMeta) -class DHPrivateKeyWithSerialization(DHPrivateKey): +class DHPrivateKeyWithSerialization(DHPrivateKey, metaclass=abc.ABCMeta): @abc.abstractmethod def private_numbers(self): """ @@ -193,8 +186,7 @@ def private_bytes(self, encoding, format, encryption_algorithm): """ -@six.add_metaclass(abc.ABCMeta) -class DHPublicKey(object): +class DHPublicKey(metaclass=abc.ABCMeta): @abc.abstractproperty def key_size(self): """ diff --git a/src/cryptography/hazmat/primitives/asymmetric/dsa.py b/src/cryptography/hazmat/primitives/asymmetric/dsa.py index 655319a40e71..6f5443e687b5 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dsa.py @@ -5,14 +5,11 @@ import abc -import six - from cryptography import utils from cryptography.hazmat.backends import _get_backend -@six.add_metaclass(abc.ABCMeta) -class DSAParameters(object): +class DSAParameters(metaclass=abc.ABCMeta): @abc.abstractmethod def generate_private_key(self): """ @@ -20,8 +17,7 @@ def generate_private_key(self): """ -@six.add_metaclass(abc.ABCMeta) -class DSAParametersWithNumbers(DSAParameters): +class DSAParametersWithNumbers(DSAParameters, metaclass=abc.ABCMeta): @abc.abstractmethod def parameter_numbers(self): """ @@ -29,8 +25,7 @@ def parameter_numbers(self): """ -@six.add_metaclass(abc.ABCMeta) -class DSAPrivateKey(object): +class DSAPrivateKey(metaclass=abc.ABCMeta): @abc.abstractproperty def key_size(self): """ @@ -62,8 +57,7 @@ def sign(self, data, algorithm): """ -@six.add_metaclass(abc.ABCMeta) -class DSAPrivateKeyWithSerialization(DSAPrivateKey): +class DSAPrivateKeyWithSerialization(DSAPrivateKey, metaclass=abc.ABCMeta): @abc.abstractmethod def private_numbers(self): """ @@ -77,8 +71,7 @@ def private_bytes(self, encoding, format, encryption_algorithm): """ -@six.add_metaclass(abc.ABCMeta) -class DSAPublicKey(object): +class DSAPublicKey(metaclass=abc.ABCMeta): @abc.abstractproperty def key_size(self): """ @@ -154,9 +147,9 @@ def _check_dsa_private_numbers(numbers): class DSAParameterNumbers(object): def __init__(self, p, q, g): if ( - not isinstance(p, six.integer_types) - or not isinstance(q, six.integer_types) - or not isinstance(g, six.integer_types) + not isinstance(p, int) + or not isinstance(q, int) + or not isinstance(g, int) ): raise TypeError( "DSAParameterNumbers p, q, and g arguments must be integers." @@ -192,7 +185,7 @@ def __repr__(self): class DSAPublicNumbers(object): def __init__(self, y, parameter_numbers): - if not isinstance(y, six.integer_types): + if not isinstance(y, int): raise TypeError("DSAPublicNumbers y argument must be an integer.") if not isinstance(parameter_numbers, DSAParameterNumbers): @@ -231,7 +224,7 @@ def __repr__(self): class DSAPrivateNumbers(object): def __init__(self, x, public_numbers): - if not isinstance(x, six.integer_types): + if not isinstance(x, int): raise TypeError("DSAPrivateNumbers x argument must be an integer.") if not isinstance(public_numbers, DSAPublicNumbers): diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index f2a91c3fd995..29e389550766 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -6,8 +6,6 @@ import abc import warnings -import six - from cryptography import utils from cryptography.hazmat._oid import ObjectIdentifier from cryptography.hazmat.backends import _get_backend @@ -35,8 +33,7 @@ class EllipticCurveOID(object): SECT571R1 = ObjectIdentifier("1.3.132.0.39") -@six.add_metaclass(abc.ABCMeta) -class EllipticCurve(object): +class EllipticCurve(metaclass=abc.ABCMeta): @abc.abstractproperty def name(self): """ @@ -50,8 +47,7 @@ def key_size(self): """ -@six.add_metaclass(abc.ABCMeta) -class EllipticCurveSignatureAlgorithm(object): +class EllipticCurveSignatureAlgorithm(metaclass=abc.ABCMeta): @abc.abstractproperty def algorithm(self): """ @@ -59,8 +55,7 @@ def algorithm(self): """ -@six.add_metaclass(abc.ABCMeta) -class EllipticCurvePrivateKey(object): +class EllipticCurvePrivateKey(metaclass=abc.ABCMeta): @abc.abstractmethod def signer(self, signature_algorithm): """ @@ -99,8 +94,9 @@ def sign(self, data, signature_algorithm): """ -@six.add_metaclass(abc.ABCMeta) -class EllipticCurvePrivateKeyWithSerialization(EllipticCurvePrivateKey): +class EllipticCurvePrivateKeyWithSerialization( + EllipticCurvePrivateKey, metaclass=abc.ABCMeta +): @abc.abstractmethod def private_numbers(self): """ @@ -114,8 +110,7 @@ def private_bytes(self, encoding, format, encryption_algorithm): """ -@six.add_metaclass(abc.ABCMeta) -class EllipticCurvePublicKey(object): +class EllipticCurvePublicKey(metaclass=abc.ABCMeta): @abc.abstractmethod def verifier(self, signature, signature_algorithm): """ @@ -162,7 +157,7 @@ def from_encoded_point(cls, curve, data): if len(data) == 0: raise ValueError("data must not be an empty byte string") - if six.indexbytes(data, 0) not in [0x02, 0x03, 0x04]: + if data[0] not in [0x02, 0x03, 0x04]: raise ValueError("Unsupported elliptic curve point type") from cryptography.hazmat.backends.openssl.backend import backend @@ -327,7 +322,7 @@ def generate_private_key(curve, backend=None): def derive_private_key(private_value, curve, backend=None): backend = _get_backend(backend) - if not isinstance(private_value, six.integer_types): + if not isinstance(private_value, int): raise TypeError("private_value must be an integer type.") if private_value <= 0: @@ -341,9 +336,7 @@ def derive_private_key(private_value, curve, backend=None): class EllipticCurvePublicNumbers(object): def __init__(self, x, y, curve): - if not isinstance(x, six.integer_types) or not isinstance( - y, six.integer_types - ): + if not isinstance(x, int) or not isinstance(y, int): raise TypeError("x and y must be integers.") if not isinstance(curve, EllipticCurve): @@ -429,7 +422,7 @@ def __repr__(self): class EllipticCurvePrivateNumbers(object): def __init__(self, private_value, public_numbers): - if not isinstance(private_value, six.integer_types): + if not isinstance(private_value, int): raise TypeError("private_value must be an integer.") if not isinstance(public_numbers, EllipticCurvePublicNumbers): diff --git a/src/cryptography/hazmat/primitives/asymmetric/ed25519.py b/src/cryptography/hazmat/primitives/asymmetric/ed25519.py index 900b4c5108ca..3b82a7e37588 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ed25519.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ed25519.py @@ -5,8 +5,6 @@ import abc -import six - from cryptography.exceptions import UnsupportedAlgorithm, _Reasons @@ -14,8 +12,7 @@ _ED25519_SIG_SIZE = 64 -@six.add_metaclass(abc.ABCMeta) -class Ed25519PublicKey(object): +class Ed25519PublicKey(metaclass=abc.ABCMeta): @classmethod def from_public_bytes(cls, data): from cryptography.hazmat.backends.openssl.backend import backend @@ -41,8 +38,7 @@ def verify(self, signature, data): """ -@six.add_metaclass(abc.ABCMeta) -class Ed25519PrivateKey(object): +class Ed25519PrivateKey(metaclass=abc.ABCMeta): @classmethod def generate(cls): from cryptography.hazmat.backends.openssl.backend import backend diff --git a/src/cryptography/hazmat/primitives/asymmetric/ed448.py b/src/cryptography/hazmat/primitives/asymmetric/ed448.py index 2c8496d9accb..3550e81e8aaf 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ed448.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ed448.py @@ -5,13 +5,10 @@ import abc -import six - from cryptography.exceptions import UnsupportedAlgorithm, _Reasons -@six.add_metaclass(abc.ABCMeta) -class Ed448PublicKey(object): +class Ed448PublicKey(metaclass=abc.ABCMeta): @classmethod def from_public_bytes(cls, data): from cryptography.hazmat.backends.openssl.backend import backend @@ -37,8 +34,7 @@ def verify(self, signature, data): """ -@six.add_metaclass(abc.ABCMeta) -class Ed448PrivateKey(object): +class Ed448PrivateKey(metaclass=abc.ABCMeta): @classmethod def generate(cls): from cryptography.hazmat.backends.openssl.backend import backend diff --git a/src/cryptography/hazmat/primitives/asymmetric/padding.py b/src/cryptography/hazmat/primitives/asymmetric/padding.py index 785ae2405f97..8515614728af 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/padding.py +++ b/src/cryptography/hazmat/primitives/asymmetric/padding.py @@ -5,15 +5,12 @@ import abc -import six - from cryptography import utils from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import rsa -@six.add_metaclass(abc.ABCMeta) -class AsymmetricPadding(object): +class AsymmetricPadding(metaclass=abc.ABCMeta): @abc.abstractproperty def name(self): """ @@ -35,7 +32,7 @@ def __init__(self, mgf, salt_length): self._mgf = mgf if ( - not isinstance(salt_length, six.integer_types) + not isinstance(salt_length, int) and salt_length is not self.MAX_LENGTH ): raise TypeError("salt_length must be an integer.") diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py index f6fc75409674..da2fcdc14298 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py @@ -6,16 +6,13 @@ import abc from math import gcd -import six - from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.backends.interfaces import RSABackend -@six.add_metaclass(abc.ABCMeta) -class RSAPrivateKey(object): +class RSAPrivateKey(metaclass=abc.ABCMeta): @abc.abstractmethod def signer(self, padding, algorithm): """ @@ -47,8 +44,7 @@ def sign(self, data, padding, algorithm): """ -@six.add_metaclass(abc.ABCMeta) -class RSAPrivateKeyWithSerialization(RSAPrivateKey): +class RSAPrivateKeyWithSerialization(RSAPrivateKey, metaclass=abc.ABCMeta): @abc.abstractmethod def private_numbers(self): """ @@ -62,8 +58,7 @@ def private_bytes(self, encoding, format, encryption_algorithm): """ -@six.add_metaclass(abc.ABCMeta) -class RSAPublicKey(object): +class RSAPublicKey(metaclass=abc.ABCMeta): @abc.abstractmethod def verifier(self, signature, padding, algorithm): """ @@ -272,12 +267,12 @@ def rsa_recover_prime_factors(n, e, d): class RSAPrivateNumbers(object): def __init__(self, p, q, d, dmp1, dmq1, iqmp, public_numbers): if ( - not isinstance(p, six.integer_types) - or not isinstance(q, six.integer_types) - or not isinstance(d, six.integer_types) - or not isinstance(dmp1, six.integer_types) - or not isinstance(dmq1, six.integer_types) - or not isinstance(iqmp, six.integer_types) + not isinstance(p, int) + or not isinstance(q, int) + or not isinstance(d, int) + or not isinstance(dmp1, int) + or not isinstance(dmq1, int) + or not isinstance(iqmp, int) ): raise TypeError( "RSAPrivateNumbers p, q, d, dmp1, dmq1, iqmp arguments must" @@ -343,9 +338,7 @@ def __hash__(self): class RSAPublicNumbers(object): def __init__(self, e, n): - if not isinstance(e, six.integer_types) or not isinstance( - n, six.integer_types - ): + if not isinstance(e, int) or not isinstance(n, int): raise TypeError("RSAPublicNumbers arguments must be integers.") self._e = e diff --git a/src/cryptography/hazmat/primitives/asymmetric/x25519.py b/src/cryptography/hazmat/primitives/asymmetric/x25519.py index 3d17e727a717..ac7ebdf0d12c 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/x25519.py +++ b/src/cryptography/hazmat/primitives/asymmetric/x25519.py @@ -5,13 +5,10 @@ import abc -import six - from cryptography.exceptions import UnsupportedAlgorithm, _Reasons -@six.add_metaclass(abc.ABCMeta) -class X25519PublicKey(object): +class X25519PublicKey(metaclass=abc.ABCMeta): @classmethod def from_public_bytes(cls, data): from cryptography.hazmat.backends.openssl.backend import backend @@ -31,8 +28,7 @@ def public_bytes(self, encoding, format): """ -@six.add_metaclass(abc.ABCMeta) -class X25519PrivateKey(object): +class X25519PrivateKey(metaclass=abc.ABCMeta): @classmethod def generate(cls): from cryptography.hazmat.backends.openssl.backend import backend diff --git a/src/cryptography/hazmat/primitives/asymmetric/x448.py b/src/cryptography/hazmat/primitives/asymmetric/x448.py index acff892a1571..46ad3f0e2515 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/x448.py +++ b/src/cryptography/hazmat/primitives/asymmetric/x448.py @@ -5,13 +5,10 @@ import abc -import six - from cryptography.exceptions import UnsupportedAlgorithm, _Reasons -@six.add_metaclass(abc.ABCMeta) -class X448PublicKey(object): +class X448PublicKey(metaclass=abc.ABCMeta): @classmethod def from_public_bytes(cls, data): from cryptography.hazmat.backends.openssl.backend import backend @@ -31,8 +28,7 @@ def public_bytes(self, encoding, format): """ -@six.add_metaclass(abc.ABCMeta) -class X448PrivateKey(object): +class X448PrivateKey(metaclass=abc.ABCMeta): @classmethod def generate(cls): from cryptography.hazmat.backends.openssl.backend import backend diff --git a/src/cryptography/hazmat/primitives/ciphers/base.py b/src/cryptography/hazmat/primitives/ciphers/base.py index a1270926e778..42cda7858ca8 100644 --- a/src/cryptography/hazmat/primitives/ciphers/base.py +++ b/src/cryptography/hazmat/primitives/ciphers/base.py @@ -5,8 +5,6 @@ import abc -import six - from cryptography import utils from cryptography.exceptions import ( AlreadyFinalized, @@ -20,8 +18,7 @@ from cryptography.hazmat.primitives.ciphers import modes -@six.add_metaclass(abc.ABCMeta) -class CipherAlgorithm(object): +class CipherAlgorithm(metaclass=abc.ABCMeta): @abc.abstractproperty def name(self): """ @@ -35,8 +32,7 @@ def key_size(self): """ -@six.add_metaclass(abc.ABCMeta) -class BlockCipherAlgorithm(object): +class BlockCipherAlgorithm(metaclass=abc.ABCMeta): @abc.abstractproperty def block_size(self): """ @@ -44,8 +40,7 @@ def block_size(self): """ -@six.add_metaclass(abc.ABCMeta) -class CipherContext(object): +class CipherContext(metaclass=abc.ABCMeta): @abc.abstractmethod def update(self, data): """ @@ -67,8 +62,7 @@ def finalize(self): """ -@six.add_metaclass(abc.ABCMeta) -class AEADCipherContext(object): +class AEADCipherContext(metaclass=abc.ABCMeta): @abc.abstractmethod def authenticate_additional_data(self, data): """ @@ -76,8 +70,7 @@ def authenticate_additional_data(self, data): """ -@six.add_metaclass(abc.ABCMeta) -class AEADDecryptionContext(object): +class AEADDecryptionContext(metaclass=abc.ABCMeta): @abc.abstractmethod def finalize_with_tag(self, tag): """ @@ -86,8 +79,7 @@ def finalize_with_tag(self, tag): """ -@six.add_metaclass(abc.ABCMeta) -class AEADEncryptionContext(object): +class AEADEncryptionContext(metaclass=abc.ABCMeta): @abc.abstractproperty def tag(self): """ diff --git a/src/cryptography/hazmat/primitives/ciphers/modes.py b/src/cryptography/hazmat/primitives/ciphers/modes.py index 75009b907f3c..bebbe261c2bb 100644 --- a/src/cryptography/hazmat/primitives/ciphers/modes.py +++ b/src/cryptography/hazmat/primitives/ciphers/modes.py @@ -5,13 +5,10 @@ import abc -import six - from cryptography import utils -@six.add_metaclass(abc.ABCMeta) -class Mode(object): +class Mode(metaclass=abc.ABCMeta): @abc.abstractproperty def name(self): """ @@ -26,8 +23,7 @@ def validate_for_algorithm(self, algorithm): """ -@six.add_metaclass(abc.ABCMeta) -class ModeWithInitializationVector(object): +class ModeWithInitializationVector(metaclass=abc.ABCMeta): @abc.abstractproperty def initialization_vector(self): """ @@ -35,8 +31,7 @@ def initialization_vector(self): """ -@six.add_metaclass(abc.ABCMeta) -class ModeWithTweak(object): +class ModeWithTweak(metaclass=abc.ABCMeta): @abc.abstractproperty def tweak(self): """ @@ -44,8 +39,7 @@ def tweak(self): """ -@six.add_metaclass(abc.ABCMeta) -class ModeWithNonce(object): +class ModeWithNonce(metaclass=abc.ABCMeta): @abc.abstractproperty def nonce(self): """ @@ -53,8 +47,7 @@ def nonce(self): """ -@six.add_metaclass(abc.ABCMeta) -class ModeWithAuthenticationTag(object): +class ModeWithAuthenticationTag(metaclass=abc.ABCMeta): @abc.abstractproperty def tag(self): """ diff --git a/src/cryptography/hazmat/primitives/hashes.py b/src/cryptography/hazmat/primitives/hashes.py index 41998fd92bf5..c0aec11eb28a 100644 --- a/src/cryptography/hazmat/primitives/hashes.py +++ b/src/cryptography/hazmat/primitives/hashes.py @@ -5,8 +5,6 @@ import abc -import six - from cryptography import utils from cryptography.exceptions import ( AlreadyFinalized, @@ -17,8 +15,7 @@ from cryptography.hazmat.backends.interfaces import HashBackend -@six.add_metaclass(abc.ABCMeta) -class HashAlgorithm(object): +class HashAlgorithm(metaclass=abc.ABCMeta): @abc.abstractproperty def name(self): """ @@ -32,8 +29,7 @@ def digest_size(self): """ -@six.add_metaclass(abc.ABCMeta) -class HashContext(object): +class HashContext(metaclass=abc.ABCMeta): @abc.abstractproperty def algorithm(self): """ @@ -59,8 +55,7 @@ def copy(self): """ -@six.add_metaclass(abc.ABCMeta) -class ExtendableOutputFunction(object): +class ExtendableOutputFunction(metaclass=abc.ABCMeta): """ An interface for extendable output functions. """ @@ -189,7 +184,7 @@ class SHAKE128(object): name = "shake128" def __init__(self, digest_size): - if not isinstance(digest_size, six.integer_types): + if not isinstance(digest_size, int): raise TypeError("digest_size must be an integer") if digest_size < 1: @@ -206,7 +201,7 @@ class SHAKE256(object): name = "shake256" def __init__(self, digest_size): - if not isinstance(digest_size, six.integer_types): + if not isinstance(digest_size, int): raise TypeError("digest_size must be an integer") if digest_size < 1: diff --git a/src/cryptography/hazmat/primitives/kdf/__init__.py b/src/cryptography/hazmat/primitives/kdf/__init__.py index a0e65b95ad3a..883bd1fd3cdb 100644 --- a/src/cryptography/hazmat/primitives/kdf/__init__.py +++ b/src/cryptography/hazmat/primitives/kdf/__init__.py @@ -5,11 +5,8 @@ import abc -import six - -@six.add_metaclass(abc.ABCMeta) -class KeyDerivationFunction(object): +class KeyDerivationFunction(metaclass=abc.ABCMeta): @abc.abstractmethod def derive(self, key_material): """ diff --git a/src/cryptography/hazmat/primitives/kdf/hkdf.py b/src/cryptography/hazmat/primitives/kdf/hkdf.py index 4c2b149f37f4..17191a2d42fb 100644 --- a/src/cryptography/hazmat/primitives/kdf/hkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/hkdf.py @@ -3,8 +3,6 @@ # for complete details. -import six - from cryptography import utils from cryptography.exceptions import ( AlreadyFinalized, @@ -95,7 +93,7 @@ def _expand(self, key_material): h = hmac.HMAC(key_material, self._algorithm, backend=self._backend) h.update(output[-1]) h.update(self._info) - h.update(six.int2byte(counter)) + h.update(bytes([counter])) output.append(h.finalize()) counter += 1 diff --git a/src/cryptography/hazmat/primitives/kdf/kbkdf.py b/src/cryptography/hazmat/primitives/kdf/kbkdf.py index aa9a5926fd22..cc092533172f 100644 --- a/src/cryptography/hazmat/primitives/kdf/kbkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/kbkdf.py @@ -5,8 +5,6 @@ from enum import Enum -from six.moves import range - from cryptography import utils from cryptography.exceptions import ( AlreadyFinalized, diff --git a/src/cryptography/hazmat/primitives/padding.py b/src/cryptography/hazmat/primitives/padding.py index 43017ffd8b87..cded31925c05 100644 --- a/src/cryptography/hazmat/primitives/padding.py +++ b/src/cryptography/hazmat/primitives/padding.py @@ -5,15 +5,12 @@ import abc -import six - from cryptography import utils from cryptography.exceptions import AlreadyFinalized from cryptography.hazmat.bindings._padding import lib -@six.add_metaclass(abc.ABCMeta) -class PaddingContext(object): +class PaddingContext(metaclass=abc.ABCMeta): @abc.abstractmethod def update(self, data): """ @@ -87,7 +84,7 @@ def _byte_unpadding_check(buffer_, block_size, checkfn): if not valid: raise ValueError("Invalid padding bytes.") - pad_size = six.indexbytes(buffer_, -1) + pad_size = buffer_[-1] return buffer_[:-pad_size] @@ -117,7 +114,7 @@ def update(self, data): return result def _padding(self, size): - return six.int2byte(size) * size + return bytes([size]) * size def finalize(self): result = _byte_padding_pad( @@ -174,7 +171,7 @@ def update(self, data): return result def _padding(self, size): - return six.int2byte(0) * (size - 1) + six.int2byte(size) + return bytes([0]) * (size - 1) + bytes([size]) def finalize(self): result = _byte_padding_pad( diff --git a/src/cryptography/hazmat/primitives/serialization/base.py b/src/cryptography/hazmat/primitives/serialization/base.py index bac610e23376..9c6ae423e76c 100644 --- a/src/cryptography/hazmat/primitives/serialization/base.py +++ b/src/cryptography/hazmat/primitives/serialization/base.py @@ -6,8 +6,6 @@ import abc from enum import Enum -import six - from cryptography import utils from cryptography.hazmat.backends import _get_backend @@ -71,8 +69,7 @@ class ParameterFormat(Enum): PKCS3 = "PKCS3" -@six.add_metaclass(abc.ABCMeta) -class KeySerializationEncryption(object): +class KeySerializationEncryption(metaclass=abc.ABCMeta): pass diff --git a/src/cryptography/hazmat/primitives/serialization/ssh.py b/src/cryptography/hazmat/primitives/serialization/ssh.py index 6328c06e780b..97a3fb21f2bd 100644 --- a/src/cryptography/hazmat/primitives/serialization/ssh.py +++ b/src/cryptography/hazmat/primitives/serialization/ssh.py @@ -9,8 +9,6 @@ import struct from base64 import encodebytes as _base64_encode -import six - from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.backends import _get_backend @@ -136,7 +134,7 @@ def _get_sshstr(data): def _get_mpint(data): """Big integer.""" val, data = _get_sshstr(data) - if val and six.indexbytes(val, 0) > 0x7F: + if val and val[0] > 0x7F: raise ValueError("Invalid data") return int.from_bytes(val, "big"), data @@ -345,7 +343,7 @@ def get_public(self, data): point, data = _get_sshstr(data) if curve != self.ssh_curve_name: raise ValueError("Curve name mismatch") - if six.indexbytes(point, 0) != 4: + if point[0] != 4: raise NotImplementedError("Need uncompressed point") return (curve, point), data diff --git a/src/cryptography/hazmat/primitives/twofactor/hotp.py b/src/cryptography/hazmat/primitives/twofactor/hotp.py index 93c2f46a6929..be0bf681198c 100644 --- a/src/cryptography/hazmat/primitives/twofactor/hotp.py +++ b/src/cryptography/hazmat/primitives/twofactor/hotp.py @@ -5,8 +5,6 @@ import struct -import six - from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.backends.interfaces import HMACBackend @@ -30,7 +28,7 @@ def __init__( if len(key) < 16 and enforce_key_length is True: raise ValueError("Key length has to be at least 128 bits.") - if not isinstance(length, six.integer_types): + if not isinstance(length, int): raise TypeError("Length parameter must be an integer type.") if length < 6 or length > 8: @@ -58,7 +56,7 @@ def _dynamic_truncate(self, counter): ctx.update(struct.pack(">Q", counter)) hmac_value = ctx.finalize() - offset = six.indexbytes(hmac_value, len(hmac_value) - 1) & 0b1111 + offset = hmac_value[len(hmac_value) - 1] & 0b1111 p = hmac_value[offset : offset + 4] return struct.unpack(">I", p)[0] & 0x7FFFFFFF diff --git a/src/cryptography/hazmat/primitives/twofactor/utils.py b/src/cryptography/hazmat/primitives/twofactor/utils.py index a96fb1eea029..d0facda7d4e3 100644 --- a/src/cryptography/hazmat/primitives/twofactor/utils.py +++ b/src/cryptography/hazmat/primitives/twofactor/utils.py @@ -4,8 +4,7 @@ import base64 - -from six.moves.urllib.parse import quote, urlencode +from urllib.parse import quote, urlencode def _generate_uri(hotp, type_name, account_name, issuer, extra_parameters): diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index 6fad3358a33e..028311dca1a7 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -8,8 +8,6 @@ import os from enum import Enum -import six - from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.primitives.asymmetric import ( dsa, @@ -101,8 +99,7 @@ def __init__(self, msg, parsed_version): self.parsed_version = parsed_version -@six.add_metaclass(abc.ABCMeta) -class Certificate(object): +class Certificate(metaclass=abc.ABCMeta): @abc.abstractmethod def fingerprint(self, algorithm): """ @@ -207,8 +204,7 @@ def public_bytes(self, encoding): """ -@six.add_metaclass(abc.ABCMeta) -class CertificateRevocationList(object): +class CertificateRevocationList(metaclass=abc.ABCMeta): @abc.abstractmethod def public_bytes(self, encoding): """ @@ -314,8 +310,7 @@ def is_signature_valid(self, public_key): """ -@six.add_metaclass(abc.ABCMeta) -class CertificateSigningRequest(object): +class CertificateSigningRequest(metaclass=abc.ABCMeta): @abc.abstractmethod def __eq__(self, other): """ @@ -397,8 +392,7 @@ def get_attribute_for_oid(self): """ -@six.add_metaclass(abc.ABCMeta) -class RevokedCertificate(object): +class RevokedCertificate(metaclass=abc.ABCMeta): @abc.abstractproperty def serial_number(self): """ @@ -574,7 +568,7 @@ def serial_number(self, number): """ Sets the certificate serial number. """ - if not isinstance(number, six.integer_types): + if not isinstance(number, int): raise TypeError("Serial number must be of integral type.") if self._serial_number is not None: raise ValueError("The serial number may only be set once.") @@ -831,7 +825,7 @@ def __init__( self._extensions = extensions def serial_number(self, number): - if not isinstance(number, six.integer_types): + if not isinstance(number, int): raise TypeError("Serial number must be of integral type.") if self._serial_number is not None: raise ValueError("The serial number may only be set once.") diff --git a/src/cryptography/x509/certificate_transparency.py b/src/cryptography/x509/certificate_transparency.py index cbef28c75f8d..44e18803d9d6 100644 --- a/src/cryptography/x509/certificate_transparency.py +++ b/src/cryptography/x509/certificate_transparency.py @@ -6,8 +6,6 @@ import abc from enum import Enum -import six - class LogEntryType(Enum): X509_CERTIFICATE = 0 @@ -18,8 +16,7 @@ class Version(Enum): v1 = 0 -@six.add_metaclass(abc.ABCMeta) -class SignedCertificateTimestamp(object): +class SignedCertificateTimestamp(metaclass=abc.ABCMeta): @abc.abstractproperty def version(self): """ diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index 5bee5035e0c1..dfad69770a0c 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -9,8 +9,6 @@ import ipaddress from enum import Enum -import six - from cryptography import utils from cryptography.hazmat._der import ( BIT_STRING, @@ -99,8 +97,7 @@ def __init__(self, msg, oid): self.oid = oid -@six.add_metaclass(abc.ABCMeta) -class ExtensionType(object): +class ExtensionType(metaclass=abc.ABCMeta): @abc.abstractproperty def oid(self): """ @@ -146,7 +143,7 @@ class CRLNumber(object): oid = ExtensionOID.CRL_NUMBER def __init__(self, crl_number): - if not isinstance(crl_number, six.integer_types): + if not isinstance(crl_number, int): raise TypeError("crl_number must be an integer") self._crl_number = crl_number @@ -198,7 +195,7 @@ def __init__( ) if authority_cert_serial_number is not None and not isinstance( - authority_cert_serial_number, six.integer_types + authority_cert_serial_number, int ): raise TypeError("authority_cert_serial_number must be an integer") @@ -402,7 +399,7 @@ def __init__(self, ca, path_length): raise ValueError("path_length must be None when ca is False") if path_length is not None and ( - not isinstance(path_length, six.integer_types) or path_length < 0 + not isinstance(path_length, int) or path_length < 0 ): raise TypeError( "path_length must be a non-negative integer or None" @@ -437,7 +434,7 @@ class DeltaCRLIndicator(object): oid = ExtensionOID.DELTA_CRL_INDICATOR def __init__(self, crl_number): - if not isinstance(crl_number, six.integer_types): + if not isinstance(crl_number, int): raise TypeError("crl_number must be an integer") self._crl_number = crl_number @@ -645,7 +642,7 @@ class PolicyConstraints(object): def __init__(self, require_explicit_policy, inhibit_policy_mapping): if require_explicit_policy is not None and not isinstance( - require_explicit_policy, six.integer_types + require_explicit_policy, int ): raise TypeError( "require_explicit_policy must be a non-negative integer or " @@ -653,7 +650,7 @@ def __init__(self, require_explicit_policy, inhibit_policy_mapping): ) if inhibit_policy_mapping is not None and not isinstance( - inhibit_policy_mapping, six.integer_types + inhibit_policy_mapping, int ): raise TypeError( "inhibit_policy_mapping must be a non-negative integer or None" @@ -742,8 +739,7 @@ def __init__(self, policy_identifier, policy_qualifiers): if policy_qualifiers: policy_qualifiers = list(policy_qualifiers) if not all( - isinstance(x, (six.text_type, UserNotice)) - for x in policy_qualifiers + isinstance(x, (str, UserNotice)) for x in policy_qualifiers ): raise TypeError( "policy_qualifiers must be a list of strings and/or " @@ -978,7 +974,7 @@ class InhibitAnyPolicy(object): oid = ExtensionOID.INHIBIT_ANY_POLICY def __init__(self, skip_certs): - if not isinstance(skip_certs, six.integer_types): + if not isinstance(skip_certs, int): raise TypeError("skip_certs must be an integer") if skip_certs < 0: diff --git a/src/cryptography/x509/general_name.py b/src/cryptography/x509/general_name.py index 02b8e5eef112..7c1306e2665c 100644 --- a/src/cryptography/x509/general_name.py +++ b/src/cryptography/x509/general_name.py @@ -7,8 +7,6 @@ import ipaddress from email.utils import parseaddr -import six - from cryptography import utils from cryptography.x509.name import Name from cryptography.x509.oid import ObjectIdentifier @@ -33,8 +31,7 @@ def __init__(self, msg, type): self.type = type -@six.add_metaclass(abc.ABCMeta) -class GeneralName(object): +class GeneralName(metaclass=abc.ABCMeta): @abc.abstractproperty def value(self): """ @@ -45,7 +42,7 @@ def value(self): @utils.register_interface(GeneralName) class RFC822Name(object): def __init__(self, value): - if isinstance(value, six.text_type): + if isinstance(value, str): try: value.encode("ascii") except UnicodeEncodeError: @@ -92,7 +89,7 @@ def __hash__(self): @utils.register_interface(GeneralName) class DNSName(object): def __init__(self, value): - if isinstance(value, six.text_type): + if isinstance(value, str): try: value.encode("ascii") except UnicodeEncodeError: @@ -133,7 +130,7 @@ def __hash__(self): @utils.register_interface(GeneralName) class UniformResourceIdentifier(object): def __init__(self, value): - if isinstance(value, six.text_type): + if isinstance(value, str): try: value.encode("ascii") except UnicodeEncodeError: diff --git a/src/cryptography/x509/name.py b/src/cryptography/x509/name.py index 8672f2618f7b..54439ed41516 100644 --- a/src/cryptography/x509/name.py +++ b/src/cryptography/x509/name.py @@ -5,8 +5,6 @@ from enum import Enum -import six - from cryptography import utils from cryptography.hazmat.backends import _get_backend from cryptography.x509.oid import NameOID, ObjectIdentifier @@ -82,7 +80,7 @@ def __init__(self, oid, value, _type=_SENTINEL): "oid argument must be an ObjectIdentifier instance." ) - if not isinstance(value, six.text_type): + if not isinstance(value, str): raise TypeError("value argument must be a text type.") if ( diff --git a/src/cryptography/x509/ocsp.py b/src/cryptography/x509/ocsp.py index c6d3524aae19..5d137d697226 100644 --- a/src/cryptography/x509/ocsp.py +++ b/src/cryptography/x509/ocsp.py @@ -7,8 +7,6 @@ import datetime from enum import Enum -import six - from cryptography import x509 from cryptography.hazmat.primitives import hashes from cryptography.x509.base import ( @@ -298,8 +296,7 @@ def build_unsuccessful(cls, response_status): return backend.create_ocsp_response(response_status, None, None, None) -@six.add_metaclass(abc.ABCMeta) -class OCSPRequest(object): +class OCSPRequest(metaclass=abc.ABCMeta): @abc.abstractproperty def issuer_key_hash(self): """ @@ -337,8 +334,7 @@ def extensions(self): """ -@six.add_metaclass(abc.ABCMeta) -class OCSPResponse(object): +class OCSPResponse(metaclass=abc.ABCMeta): @abc.abstractproperty def response_status(self): """ diff --git a/tests/hazmat/primitives/test_padding.py b/tests/hazmat/primitives/test_padding.py index b29d5a42e2f8..2a526401f117 100644 --- a/tests/hazmat/primitives/test_padding.py +++ b/tests/hazmat/primitives/test_padding.py @@ -5,8 +5,6 @@ import pytest -import six - from cryptography.exceptions import AlreadyFinalized from cryptography.hazmat.primitives import padding @@ -111,7 +109,7 @@ def test_large_padding(self): padded_data = padder.update(b"") padded_data += padder.finalize() - for i in six.iterbytes(padded_data): + for i in padded_data: assert i == 255 unpadder = padding.PKCS7(2040).unpadder() diff --git a/tests/test_fernet.py b/tests/test_fernet.py index 8390ea6e450e..a3f45f7553c2 100644 --- a/tests/test_fernet.py +++ b/tests/test_fernet.py @@ -13,8 +13,6 @@ import pytest -import six - from cryptography.fernet import Fernet, InvalidToken, MultiFernet from cryptography.hazmat.backends import default_backend from cryptography.hazmat.backends.interfaces import CipherBackend, HMACBackend @@ -57,7 +55,7 @@ def test_generate(self, secret, now, iv, src, token, backend): actual_token = f._encrypt_from_parts( src.encode("ascii"), calendar.timegm(iso8601.parse_date(now).utctimetuple()), - b"".join(map(six.int2byte, iv)), + bytes(iv), ) assert actual_token == token.encode("ascii") diff --git a/tests/test_interfaces.py b/tests/test_interfaces.py index 042245f97706..c5c579da0ca7 100644 --- a/tests/test_interfaces.py +++ b/tests/test_interfaces.py @@ -6,8 +6,6 @@ import pytest -import six - from cryptography.utils import ( InterfaceNotImplemented, register_interface_if, @@ -16,8 +14,7 @@ def test_register_interface_if_true(): - @six.add_metaclass(abc.ABCMeta) - class SimpleInterface(object): + class SimpleInterface(metaclass=abc.ABCMeta): pass @register_interface_if(1 == 1, SimpleInterface) @@ -28,8 +25,7 @@ class SimpleClass(object): def test_register_interface_if_false(): - @six.add_metaclass(abc.ABCMeta) - class SimpleInterface(object): + class SimpleInterface(metaclass=abc.ABCMeta): pass @register_interface_if(1 == 2, SimpleInterface) @@ -41,8 +37,7 @@ class SimpleClass(object): class TestVerifyInterface(object): def test_verify_missing_method(self): - @six.add_metaclass(abc.ABCMeta) - class SimpleInterface(object): + class SimpleInterface(metaclass=abc.ABCMeta): @abc.abstractmethod def method(self): """A simple method""" @@ -54,8 +49,7 @@ class NonImplementer(object): verify_interface(SimpleInterface, NonImplementer) def test_different_arguments(self): - @six.add_metaclass(abc.ABCMeta) - class SimpleInterface(object): + class SimpleInterface(metaclass=abc.ABCMeta): @abc.abstractmethod def method(self, a): """Method with one argument""" @@ -70,8 +64,7 @@ def method(self): verify_interface(SimpleInterface, NonImplementer) def test_handles_abstract_property(self): - @six.add_metaclass(abc.ABCMeta) - class SimpleInterface(object): + class SimpleInterface(metaclass=abc.ABCMeta): @abc.abstractproperty def property(self): """An abstract property""" diff --git a/tests/utils.py b/tests/utils.py index 4fb7a684540f..4ec85d776648 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -12,8 +12,6 @@ import pytest -import six - from cryptography.exceptions import UnsupportedAlgorithm import cryptography_vectors @@ -166,7 +164,7 @@ def load_pkcs1_vectors(vector_data): or line.startswith("# PKCS#1 v1.5") ): if example_vector: - for key, value in six.iteritems(example_vector): + for key, value in example_vector.items(): hex_str = "".join(value).replace(" ", "").encode("ascii") example_vector[key] = hex_str examples.append(example_vector) @@ -192,7 +190,7 @@ def load_pkcs1_vectors(vector_data): elif example_vector and line.startswith( "# =============================================" ): - for key, value in six.iteritems(example_vector): + for key, value in example_vector.items(): hex_str = "".join(value).replace(" ", "").encode("ascii") example_vector[key] = hex_str examples.append(example_vector) @@ -212,11 +210,11 @@ def load_pkcs1_vectors(vector_data): assert private_key_vector assert public_key_vector - for key, value in six.iteritems(public_key_vector): + for key, value in public_key_vector.items(): hex_str = "".join(value).replace(" ", "") public_key_vector[key] = int(hex_str, 16) - for key, value in six.iteritems(private_key_vector): + for key, value in private_key_vector.items(): hex_str = "".join(value).replace(" ", "") private_key_vector[key] = int(hex_str, 16) From 057a9fcf3444c0edf2b7589902d976c44030b2e1 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 9 Dec 2020 11:04:47 -0500 Subject: [PATCH 0009/2380] fixes #5611 -- use subtests for wycheproof tests for speed (#5616) --- tests/conftest.py | 16 +--------------- tests/wycheproof/test_aes.py | 9 +++++---- tests/wycheproof/test_chacha20poly1305.py | 5 +++-- tests/wycheproof/test_cmac.py | 4 +++- tests/wycheproof/test_dsa.py | 4 +++- tests/wycheproof/test_ecdh.py | 5 +++-- tests/wycheproof/test_ecdsa.py | 4 +++- tests/wycheproof/test_eddsa.py | 6 ++++-- tests/wycheproof/test_hkdf.py | 4 +++- tests/wycheproof/test_hmac.py | 4 +++- tests/wycheproof/test_keywrap.py | 6 ++++-- tests/wycheproof/test_rsa.py | 12 +++++++----- tests/wycheproof/test_x25519.py | 4 +++- tests/wycheproof/test_x448.py | 4 +++- tests/wycheproof/utils.py | 17 +++++++++++++++++ 15 files changed, 65 insertions(+), 39 deletions(-) create mode 100644 tests/wycheproof/utils.py diff --git a/tests/conftest.py b/tests/conftest.py index 77691c2d1491..43debdd61a85 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -7,10 +7,7 @@ from cryptography.hazmat.backends.openssl import backend as openssl_backend -from .utils import ( - check_backend_support, - load_wycheproof_tests, -) +from .utils import check_backend_support def pytest_report_header(config): @@ -26,17 +23,6 @@ def pytest_addoption(parser): parser.addoption("--wycheproof-root", default=None) -def pytest_generate_tests(metafunc): - if "wycheproof" in metafunc.fixturenames: - wycheproof = metafunc.config.getoption("--wycheproof-root", skip=True) - - testcases = [] - marker = metafunc.definition.get_closest_marker("wycheproof_tests") - for path in marker.args: - testcases.extend(load_wycheproof_tests(wycheproof, path)) - metafunc.parametrize("wycheproof", testcases) - - def pytest_runtest_setup(item): if openssl_backend._fips_enabled: for marker in item.iter_markers(name="skip_fips"): diff --git a/tests/wycheproof/test_aes.py b/tests/wycheproof/test_aes.py index 43e7164cee56..c041b47e15c4 100644 --- a/tests/wycheproof/test_aes.py +++ b/tests/wycheproof/test_aes.py @@ -13,11 +13,12 @@ from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives.ciphers.aead import AESCCM, AESGCM +from .utils import wycheproof_tests from ..hazmat.primitives.test_aead import _aead_supported @pytest.mark.requires_backend_interface(interface=CipherBackend) -@pytest.mark.wycheproof_tests("aes_cbc_pkcs5_test.json") +@wycheproof_tests("aes_cbc_pkcs5_test.json") def test_aes_cbc_pkcs5(backend, wycheproof): key = binascii.unhexlify(wycheproof.testcase["key"]) iv = binascii.unhexlify(wycheproof.testcase["iv"]) @@ -45,7 +46,7 @@ def test_aes_cbc_pkcs5(backend, wycheproof): @pytest.mark.requires_backend_interface(interface=CipherBackend) -@pytest.mark.wycheproof_tests("aes_gcm_test.json") +@wycheproof_tests("aes_gcm_test.json") def test_aes_gcm(backend, wycheproof): key = binascii.unhexlify(wycheproof.testcase["key"]) iv = binascii.unhexlify(wycheproof.testcase["iv"]) @@ -90,7 +91,7 @@ def test_aes_gcm(backend, wycheproof): @pytest.mark.requires_backend_interface(interface=CipherBackend) -@pytest.mark.wycheproof_tests("aes_gcm_test.json") +@wycheproof_tests("aes_gcm_test.json") def test_aes_gcm_aead_api(backend, wycheproof): key = binascii.unhexlify(wycheproof.testcase["key"]) iv = binascii.unhexlify(wycheproof.testcase["iv"]) @@ -124,7 +125,7 @@ def test_aes_gcm_aead_api(backend, wycheproof): reason="Requires OpenSSL with AES-CCM support", ) @pytest.mark.requires_backend_interface(interface=CipherBackend) -@pytest.mark.wycheproof_tests("aes_ccm_test.json") +@wycheproof_tests("aes_ccm_test.json") def test_aes_ccm_aead_api(backend, wycheproof): key = binascii.unhexlify(wycheproof.testcase["key"]) iv = binascii.unhexlify(wycheproof.testcase["iv"]) diff --git a/tests/wycheproof/test_chacha20poly1305.py b/tests/wycheproof/test_chacha20poly1305.py index 936fa8dc020a..9c94c58f74d9 100644 --- a/tests/wycheproof/test_chacha20poly1305.py +++ b/tests/wycheproof/test_chacha20poly1305.py @@ -11,6 +11,7 @@ from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305 +from .utils import wycheproof_tests from ..hazmat.primitives.test_aead import _aead_supported @@ -19,8 +20,8 @@ reason="Requires OpenSSL with ChaCha20Poly1305 support", ) @pytest.mark.requires_backend_interface(interface=CipherBackend) -@pytest.mark.wycheproof_tests("chacha20_poly1305_test.json") -def test_chacha2poly1305(wycheproof): +@wycheproof_tests("chacha20_poly1305_test.json") +def test_chacha2poly1305(backend, wycheproof): key = binascii.unhexlify(wycheproof.testcase["key"]) iv = binascii.unhexlify(wycheproof.testcase["iv"]) aad = binascii.unhexlify(wycheproof.testcase["aad"]) diff --git a/tests/wycheproof/test_cmac.py b/tests/wycheproof/test_cmac.py index 11a1d34b76df..21ce9af888f8 100644 --- a/tests/wycheproof/test_cmac.py +++ b/tests/wycheproof/test_cmac.py @@ -12,9 +12,11 @@ from cryptography.hazmat.primitives.ciphers.algorithms import AES from cryptography.hazmat.primitives.cmac import CMAC +from .utils import wycheproof_tests + @pytest.mark.requires_backend_interface(interface=CMACBackend) -@pytest.mark.wycheproof_tests("aes_cmac_test.json") +@wycheproof_tests("aes_cmac_test.json") def test_aes_cmac(backend, wycheproof): key = binascii.unhexlify(wycheproof.testcase["key"]) msg = binascii.unhexlify(wycheproof.testcase["msg"]) diff --git a/tests/wycheproof/test_dsa.py b/tests/wycheproof/test_dsa.py index 19d2ce486844..1bcf31f024b2 100644 --- a/tests/wycheproof/test_dsa.py +++ b/tests/wycheproof/test_dsa.py @@ -11,6 +11,8 @@ from cryptography.hazmat.backends.interfaces import DSABackend from cryptography.hazmat.primitives import hashes, serialization +from .utils import wycheproof_tests + _DIGESTS = { "SHA-1": hashes.SHA1(), @@ -20,7 +22,7 @@ @pytest.mark.requires_backend_interface(interface=DSABackend) -@pytest.mark.wycheproof_tests( +@wycheproof_tests( "dsa_test.json", "dsa_2048_224_sha224_test.json", "dsa_2048_224_sha256_test.json", diff --git a/tests/wycheproof/test_ecdh.py b/tests/wycheproof/test_ecdh.py index a25337de1de9..a1a90c141b78 100644 --- a/tests/wycheproof/test_ecdh.py +++ b/tests/wycheproof/test_ecdh.py @@ -12,6 +12,7 @@ from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import ec +from .utils import wycheproof_tests from ..hazmat.primitives.test_ec import _skip_exchange_algorithm_unsupported @@ -36,7 +37,7 @@ @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) -@pytest.mark.wycheproof_tests( +@wycheproof_tests( "ecdh_test.json", "ecdh_brainpoolP224r1_test.json", "ecdh_brainpoolP256r1_test.json", @@ -84,7 +85,7 @@ def test_ecdh(backend, wycheproof): @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) -@pytest.mark.wycheproof_tests( +@wycheproof_tests( "ecdh_secp224r1_ecpoint_test.json", "ecdh_secp256r1_ecpoint_test.json", "ecdh_secp384r1_ecpoint_test.json", diff --git a/tests/wycheproof/test_ecdsa.py b/tests/wycheproof/test_ecdsa.py index b1a98253d089..e1bdbace66fe 100644 --- a/tests/wycheproof/test_ecdsa.py +++ b/tests/wycheproof/test_ecdsa.py @@ -12,6 +12,8 @@ from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ec +from .utils import wycheproof_tests + _DIGESTS = { "SHA-1": hashes.SHA1(), @@ -27,7 +29,7 @@ @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) -@pytest.mark.wycheproof_tests( +@wycheproof_tests( "ecdsa_test.json", "ecdsa_brainpoolP224r1_sha224_test.json", "ecdsa_brainpoolP256r1_sha256_test.json", diff --git a/tests/wycheproof/test_eddsa.py b/tests/wycheproof/test_eddsa.py index 13501a7babcd..2de695f57f0a 100644 --- a/tests/wycheproof/test_eddsa.py +++ b/tests/wycheproof/test_eddsa.py @@ -11,12 +11,14 @@ from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey from cryptography.hazmat.primitives.asymmetric.ed448 import Ed448PublicKey +from .utils import wycheproof_tests + @pytest.mark.supported( only_if=lambda backend: backend.ed25519_supported(), skip_message="Requires OpenSSL with Ed25519 support", ) -@pytest.mark.wycheproof_tests("eddsa_test.json") +@wycheproof_tests("eddsa_test.json") def test_ed25519_signature(backend, wycheproof): # We want to fail if/when wycheproof adds more edwards curve tests # so we can add them as well. @@ -43,7 +45,7 @@ def test_ed25519_signature(backend, wycheproof): only_if=lambda backend: backend.ed448_supported(), skip_message="Requires OpenSSL with Ed448 support", ) -@pytest.mark.wycheproof_tests("ed448_test.json") +@wycheproof_tests("ed448_test.json") def test_ed448_signature(backend, wycheproof): key = Ed448PublicKey.from_public_bytes( binascii.unhexlify(wycheproof.testgroup["key"]["pk"]) diff --git a/tests/wycheproof/test_hkdf.py b/tests/wycheproof/test_hkdf.py index 0f553a919394..4886be0fe8cc 100644 --- a/tests/wycheproof/test_hkdf.py +++ b/tests/wycheproof/test_hkdf.py @@ -10,6 +10,8 @@ from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.hkdf import HKDF +from .utils import wycheproof_tests + _HASH_ALGORITHMS = { "HKDF-SHA-1": hashes.SHA1(), @@ -19,7 +21,7 @@ } -@pytest.mark.wycheproof_tests( +@wycheproof_tests( "hkdf_sha1_test.json", "hkdf_sha256_test.json", "hkdf_sha384_test.json", diff --git a/tests/wycheproof/test_hmac.py b/tests/wycheproof/test_hmac.py index 93433c1c1658..bfc690795122 100644 --- a/tests/wycheproof/test_hmac.py +++ b/tests/wycheproof/test_hmac.py @@ -10,6 +10,8 @@ from cryptography.exceptions import InvalidSignature from cryptography.hazmat.primitives import hashes, hmac +from .utils import wycheproof_tests + _HMAC_ALGORITHMS = { "HMACSHA1": hashes.SHA1(), @@ -24,7 +26,7 @@ } -@pytest.mark.wycheproof_tests( +@wycheproof_tests( "hmac_sha1_test.json", "hmac_sha224_test.json", "hmac_sha256_test.json", diff --git a/tests/wycheproof/test_keywrap.py b/tests/wycheproof/test_keywrap.py index c04ac4907b39..6a8cfd08bc69 100644 --- a/tests/wycheproof/test_keywrap.py +++ b/tests/wycheproof/test_keywrap.py @@ -10,9 +10,11 @@ from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives import keywrap +from .utils import wycheproof_tests + @pytest.mark.requires_backend_interface(interface=CipherBackend) -@pytest.mark.wycheproof_tests("kwp_test.json") +@wycheproof_tests("kwp_test.json") def test_keywrap_with_padding(backend, wycheproof): wrapping_key = binascii.unhexlify(wycheproof.testcase["key"]) key_to_wrap = binascii.unhexlify(wycheproof.testcase["msg"]) @@ -37,7 +39,7 @@ def test_keywrap_with_padding(backend, wycheproof): @pytest.mark.requires_backend_interface(interface=CipherBackend) -@pytest.mark.wycheproof_tests("kw_test.json") +@wycheproof_tests("kw_test.json") def test_keywrap(backend, wycheproof): wrapping_key = binascii.unhexlify(wycheproof.testcase["key"]) key_to_wrap = binascii.unhexlify(wycheproof.testcase["msg"]) diff --git a/tests/wycheproof/test_rsa.py b/tests/wycheproof/test_rsa.py index a3712cc755ab..5df466c50538 100644 --- a/tests/wycheproof/test_rsa.py +++ b/tests/wycheproof/test_rsa.py @@ -12,6 +12,8 @@ from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import padding +from .utils import wycheproof_tests + _DIGESTS = { "SHA-1": hashes.SHA1(), @@ -40,7 +42,7 @@ def should_verify(backend, wycheproof): @pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.wycheproof_tests( +@wycheproof_tests( "rsa_signature_test.json", "rsa_signature_2048_sha224_test.json", "rsa_signature_2048_sha256_test.json", @@ -91,7 +93,7 @@ def test_rsa_pkcs1v15_signature(backend, wycheproof): ) -@pytest.mark.wycheproof_tests("rsa_sig_gen_misc_test.json") +@wycheproof_tests("rsa_sig_gen_misc_test.json") def test_rsa_pkcs1v15_signature_generation(backend, wycheproof): key = serialization.load_pem_private_key( wycheproof.testgroup["privateKeyPem"].encode(), @@ -109,7 +111,7 @@ def test_rsa_pkcs1v15_signature_generation(backend, wycheproof): @pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.wycheproof_tests( +@wycheproof_tests( "rsa_pss_2048_sha1_mgf1_20_test.json", "rsa_pss_2048_sha256_mgf1_0_test.json", "rsa_pss_2048_sha256_mgf1_32_test.json", @@ -159,7 +161,7 @@ def test_rsa_pss_signature(backend, wycheproof): @pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.wycheproof_tests( +@wycheproof_tests( "rsa_oaep_2048_sha1_mgf1sha1_test.json", "rsa_oaep_2048_sha224_mgf1sha1_test.json", "rsa_oaep_2048_sha224_mgf1sha224_test.json", @@ -214,7 +216,7 @@ def test_rsa_oaep_encryption(backend, wycheproof): ) -@pytest.mark.wycheproof_tests( +@wycheproof_tests( "rsa_pkcs1_2048_test.json", "rsa_pkcs1_3072_test.json", "rsa_pkcs1_4096_test.json", diff --git a/tests/wycheproof/test_x25519.py b/tests/wycheproof/test_x25519.py index 926a5e898ff2..17aef36fe2e1 100644 --- a/tests/wycheproof/test_x25519.py +++ b/tests/wycheproof/test_x25519.py @@ -12,12 +12,14 @@ X25519PublicKey, ) +from .utils import wycheproof_tests + @pytest.mark.supported( only_if=lambda backend: backend.x25519_supported(), skip_message="Requires OpenSSL with X25519 support", ) -@pytest.mark.wycheproof_tests("x25519_test.json") +@wycheproof_tests("x25519_test.json") def test_x25519(backend, wycheproof): assert set(wycheproof.testgroup.items()) == { ("curve", "curve25519"), diff --git a/tests/wycheproof/test_x448.py b/tests/wycheproof/test_x448.py index 6c77457a71ef..8e7b321484c3 100644 --- a/tests/wycheproof/test_x448.py +++ b/tests/wycheproof/test_x448.py @@ -12,12 +12,14 @@ X448PublicKey, ) +from .utils import wycheproof_tests + @pytest.mark.supported( only_if=lambda backend: backend.x448_supported(), skip_message="Requires OpenSSL with X448 support", ) -@pytest.mark.wycheproof_tests("x448_test.json") +@wycheproof_tests("x448_test.json") def test_x448(backend, wycheproof): assert set(wycheproof.testgroup.items()) == { ("curve", "curve448"), diff --git a/tests/wycheproof/utils.py b/tests/wycheproof/utils.py new file mode 100644 index 000000000000..eebbe7ce3bf6 --- /dev/null +++ b/tests/wycheproof/utils.py @@ -0,0 +1,17 @@ +from ..utils import load_wycheproof_tests + + +def wycheproof_tests(*paths): + def wrapper(func): + def run_wycheproof(backend, subtests, pytestconfig): + wycheproof_root = pytestconfig.getoption( + "--wycheproof-root", skip=True + ) + for path in paths: + for test in load_wycheproof_tests(wycheproof_root, path): + with subtests.test(): + func(backend, test) + + return run_wycheproof + + return wrapper From faa8736164b5f977ae87d2e5941ee91324fbe95f Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 9 Dec 2020 10:58:29 -0600 Subject: [PATCH 0010/2380] use subtests in aead (#5618) --- tests/hazmat/primitives/test_aead.py | 180 +++++++++++++-------------- 1 file changed, 88 insertions(+), 92 deletions(-) diff --git a/tests/hazmat/primitives/test_aead.py b/tests/hazmat/primitives/test_aead.py index bc7f5ab114bf..6787cb503e73 100644 --- a/tests/hazmat/primitives/test_aead.py +++ b/tests/hazmat/primitives/test_aead.py @@ -121,55 +121,53 @@ def test_associated_data_none_equal_to_empty_bytestring(self, backend): pt2 = chacha.decrypt(nonce, ct2, b"") assert pt1 == pt2 - @pytest.mark.parametrize( - "vector", - load_vectors_from_file( + def test_openssl_vectors(self, subtests, backend): + vectors = load_vectors_from_file( os.path.join("ciphers", "ChaCha20Poly1305", "openssl.txt"), load_nist_vectors, - ), - ) - def test_openssl_vectors(self, vector, backend): - key = binascii.unhexlify(vector["key"]) - nonce = binascii.unhexlify(vector["iv"]) - aad = binascii.unhexlify(vector["aad"]) - tag = binascii.unhexlify(vector["tag"]) - pt = binascii.unhexlify(vector["plaintext"]) - ct = binascii.unhexlify(vector["ciphertext"]) - chacha = ChaCha20Poly1305(key) - if vector.get("result") == b"CIPHERFINAL_ERROR": - with pytest.raises(InvalidTag): - chacha.decrypt(nonce, ct + tag, aad) - else: - computed_pt = chacha.decrypt(nonce, ct + tag, aad) - assert computed_pt == pt - computed_ct = chacha.encrypt(nonce, pt, aad) - assert computed_ct == ct + tag - - @pytest.mark.parametrize( - "vector", - load_vectors_from_file( + ) + for vector in vectors: + with subtests.test(): + key = binascii.unhexlify(vector["key"]) + nonce = binascii.unhexlify(vector["iv"]) + aad = binascii.unhexlify(vector["aad"]) + tag = binascii.unhexlify(vector["tag"]) + pt = binascii.unhexlify(vector["plaintext"]) + ct = binascii.unhexlify(vector["ciphertext"]) + chacha = ChaCha20Poly1305(key) + if vector.get("result") == b"CIPHERFINAL_ERROR": + with pytest.raises(InvalidTag): + chacha.decrypt(nonce, ct + tag, aad) + else: + computed_pt = chacha.decrypt(nonce, ct + tag, aad) + assert computed_pt == pt + computed_ct = chacha.encrypt(nonce, pt, aad) + assert computed_ct == ct + tag + + def test_boringssl_vectors(self, subtests, backend): + vectors = load_vectors_from_file( os.path.join("ciphers", "ChaCha20Poly1305", "boringssl.txt"), load_nist_vectors, - ), - ) - def test_boringssl_vectors(self, vector, backend): - key = binascii.unhexlify(vector["key"]) - nonce = binascii.unhexlify(vector["nonce"]) - if vector["ad"].startswith(b'"'): - aad = vector["ad"][1:-1] - else: - aad = binascii.unhexlify(vector["ad"]) - tag = binascii.unhexlify(vector["tag"]) - if vector["in"].startswith(b'"'): - pt = vector["in"][1:-1] - else: - pt = binascii.unhexlify(vector["in"]) - ct = binascii.unhexlify(vector["ct"].strip(b'"')) - chacha = ChaCha20Poly1305(key) - computed_pt = chacha.decrypt(nonce, ct + tag, aad) - assert computed_pt == pt - computed_ct = chacha.encrypt(nonce, pt, aad) - assert computed_ct == ct + tag + ) + for vector in vectors: + with subtests.test(): + key = binascii.unhexlify(vector["key"]) + nonce = binascii.unhexlify(vector["nonce"]) + if vector["ad"].startswith(b'"'): + aad = vector["ad"][1:-1] + else: + aad = binascii.unhexlify(vector["ad"]) + tag = binascii.unhexlify(vector["tag"]) + if vector["in"].startswith(b'"'): + pt = vector["in"][1:-1] + else: + pt = binascii.unhexlify(vector["in"]) + ct = binascii.unhexlify(vector["ct"].strip(b'"')) + chacha = ChaCha20Poly1305(key) + computed_pt = chacha.decrypt(nonce, ct + tag, aad) + assert computed_pt == pt + computed_ct = chacha.encrypt(nonce, pt, aad) + assert computed_ct == ct + tag def test_buffer_protocol(self, backend): key = ChaCha20Poly1305.generate_key() @@ -230,9 +228,8 @@ def test_invalid_nonce_length(self, backend): with pytest.raises(ValueError): aesccm.encrypt(nonce[:6], pt, None) - @pytest.mark.parametrize( - "vector", - _load_all_params( + def test_vectors(self, subtests, backend): + vectors = _load_all_params( os.path.join("ciphers", "AES", "CCM"), [ "DVPT128.rsp", @@ -249,22 +246,22 @@ def test_invalid_nonce_length(self, backend): "VPT256.rsp", ], load_nist_ccm_vectors, - ), - ) - def test_vectors(self, vector, backend): - key = binascii.unhexlify(vector["key"]) - nonce = binascii.unhexlify(vector["nonce"]) - adata = binascii.unhexlify(vector["adata"])[: vector["alen"]] - ct = binascii.unhexlify(vector["ct"]) - pt = binascii.unhexlify(vector["payload"])[: vector["plen"]] - aesccm = AESCCM(key, vector["tlen"]) - if vector.get("fail"): - with pytest.raises(InvalidTag): - aesccm.decrypt(nonce, ct, adata) - else: - computed_pt = aesccm.decrypt(nonce, ct, adata) - assert computed_pt == pt - assert aesccm.encrypt(nonce, pt, adata) == ct + ) + for vector in vectors: + with subtests.test(): + key = binascii.unhexlify(vector["key"]) + nonce = binascii.unhexlify(vector["nonce"]) + adata = binascii.unhexlify(vector["adata"])[: vector["alen"]] + ct = binascii.unhexlify(vector["ct"]) + pt = binascii.unhexlify(vector["payload"])[: vector["plen"]] + aesccm = AESCCM(key, vector["tlen"]) + if vector.get("fail"): + with pytest.raises(InvalidTag): + aesccm.decrypt(nonce, ct, adata) + else: + computed_pt = aesccm.decrypt(nonce, ct, adata) + assert computed_pt == pt + assert aesccm.encrypt(nonce, pt, adata) == ct def test_roundtrip(self, backend): key = AESCCM.generate_key(128) @@ -359,7 +356,7 @@ def _load_gcm_vectors(): ], load_nist_vectors, ) - return [x for x in vectors if len(x["tag"]) == 32] + return [x for x in vectors if len(x["tag"]) == 32 and len(x["iv"]) >= 16] @pytest.mark.requires_backend_interface(interface=CipherBackend) @@ -375,33 +372,32 @@ def test_data_too_large(self): with pytest.raises(OverflowError): aesgcm.encrypt(nonce, b"", FakeData()) - @pytest.mark.parametrize("vector", _load_gcm_vectors()) - def test_vectors(self, backend, vector): - nonce = binascii.unhexlify(vector["iv"]) - - if len(nonce) < 8: - pytest.skip("GCM does not support less than 64-bit IVs") - - if backend._fips_enabled and len(nonce) != 12: - # Red Hat disables non-96-bit IV support as part of its FIPS - # patches. - pytest.skip("Non-96-bit IVs unsupported in FIPS mode.") - - key = binascii.unhexlify(vector["key"]) - aad = binascii.unhexlify(vector["aad"]) - ct = binascii.unhexlify(vector["ct"]) - pt = binascii.unhexlify(vector.get("pt", b"")) - tag = binascii.unhexlify(vector["tag"]) - aesgcm = AESGCM(key) - if vector.get("fail") is True: - with pytest.raises(InvalidTag): - aesgcm.decrypt(nonce, ct + tag, aad) - else: - computed_ct = aesgcm.encrypt(nonce, pt, aad) - assert computed_ct[:-16] == ct - assert computed_ct[-16:] == tag - computed_pt = aesgcm.decrypt(nonce, ct + tag, aad) - assert computed_pt == pt + def test_vectors(self, backend, subtests): + vectors = _load_gcm_vectors() + for vector in vectors: + with subtests.test(): + nonce = binascii.unhexlify(vector["iv"]) + + if backend._fips_enabled and len(nonce) != 12: + # Red Hat disables non-96-bit IV support as part of its + # FIPS patches. + pytest.skip("Non-96-bit IVs unsupported in FIPS mode.") + + key = binascii.unhexlify(vector["key"]) + aad = binascii.unhexlify(vector["aad"]) + ct = binascii.unhexlify(vector["ct"]) + pt = binascii.unhexlify(vector.get("pt", b"")) + tag = binascii.unhexlify(vector["tag"]) + aesgcm = AESGCM(key) + if vector.get("fail") is True: + with pytest.raises(InvalidTag): + aesgcm.decrypt(nonce, ct + tag, aad) + else: + computed_ct = aesgcm.encrypt(nonce, pt, aad) + assert computed_ct[:-16] == ct + assert computed_ct[-16:] == tag + computed_pt = aesgcm.decrypt(nonce, ct + tag, aad) + assert computed_pt == pt @pytest.mark.parametrize( ("nonce", "data", "associated_data"), From 09c867fc4d6e8039d6cd130a1649ca5086d6b008 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 9 Dec 2020 11:03:12 -0600 Subject: [PATCH 0011/2380] subtest-ify keywrap (#5619) --- tests/hazmat/primitives/test_keywrap.py | 162 ++++++++++++------------ 1 file changed, 82 insertions(+), 80 deletions(-) diff --git a/tests/hazmat/primitives/test_keywrap.py b/tests/hazmat/primitives/test_keywrap.py index 947afb3e308a..c5486fe1ee1c 100644 --- a/tests/hazmat/primitives/test_keywrap.py +++ b/tests/hazmat/primitives/test_keywrap.py @@ -18,14 +18,6 @@ @pytest.mark.requires_backend_interface(interface=CipherBackend) class TestAESKeyWrap(object): - @pytest.mark.parametrize( - "params", - _load_all_params( - os.path.join("keywrap", "kwtestvectors"), - ["KW_AE_128.txt", "KW_AE_192.txt", "KW_AE_256.txt"], - load_nist_vectors, - ), - ) @pytest.mark.supported( only_if=lambda backend: backend.cipher_supported( algorithms.AES(b"\x00" * 16), modes.ECB() @@ -33,20 +25,21 @@ class TestAESKeyWrap(object): skip_message="Does not support AES key wrap (RFC 3394) because AES-ECB" " is unsupported", ) - def test_wrap(self, backend, params): - wrapping_key = binascii.unhexlify(params["k"]) - key_to_wrap = binascii.unhexlify(params["p"]) - wrapped_key = keywrap.aes_key_wrap(wrapping_key, key_to_wrap, backend) - assert params["c"] == binascii.hexlify(wrapped_key) - - @pytest.mark.parametrize( - "params", - _load_all_params( + def test_wrap(self, backend, subtests): + params = _load_all_params( os.path.join("keywrap", "kwtestvectors"), - ["KW_AD_128.txt", "KW_AD_192.txt", "KW_AD_256.txt"], + ["KW_AE_128.txt", "KW_AE_192.txt", "KW_AE_256.txt"], load_nist_vectors, - ), - ) + ) + for param in params: + with subtests.test(): + wrapping_key = binascii.unhexlify(param["k"]) + key_to_wrap = binascii.unhexlify(param["p"]) + wrapped_key = keywrap.aes_key_wrap( + wrapping_key, key_to_wrap, backend + ) + assert param["c"] == binascii.hexlify(wrapped_key) + @pytest.mark.supported( only_if=lambda backend: backend.cipher_supported( algorithms.AES(b"\x00" * 16), modes.ECB() @@ -54,17 +47,26 @@ def test_wrap(self, backend, params): skip_message="Does not support AES key wrap (RFC 3394) because AES-ECB" " is unsupported", ) - def test_unwrap(self, backend, params): - wrapping_key = binascii.unhexlify(params["k"]) - wrapped_key = binascii.unhexlify(params["c"]) - if params.get("fail") is True: - with pytest.raises(keywrap.InvalidUnwrap): - keywrap.aes_key_unwrap(wrapping_key, wrapped_key, backend) - else: - unwrapped_key = keywrap.aes_key_unwrap( - wrapping_key, wrapped_key, backend - ) - assert params["p"] == binascii.hexlify(unwrapped_key) + def test_unwrap(self, backend, subtests): + params = _load_all_params( + os.path.join("keywrap", "kwtestvectors"), + ["KW_AD_128.txt", "KW_AD_192.txt", "KW_AD_256.txt"], + load_nist_vectors, + ) + for param in params: + with subtests.test(): + wrapping_key = binascii.unhexlify(param["k"]) + wrapped_key = binascii.unhexlify(param["c"]) + if param.get("fail") is True: + with pytest.raises(keywrap.InvalidUnwrap): + keywrap.aes_key_unwrap( + wrapping_key, wrapped_key, backend + ) + else: + unwrapped_key = keywrap.aes_key_unwrap( + wrapping_key, wrapped_key, backend + ) + assert param["p"] == binascii.hexlify(unwrapped_key) @pytest.mark.supported( only_if=lambda backend: backend.cipher_supported( @@ -124,67 +126,67 @@ def test_unwrap_invalid_wrapped_key_length(self, backend): ) @pytest.mark.requires_backend_interface(interface=CipherBackend) class TestAESKeyWrapWithPadding(object): - @pytest.mark.parametrize( - "params", - _load_all_params( + def test_wrap(self, backend, subtests): + params = _load_all_params( os.path.join("keywrap", "kwtestvectors"), ["KWP_AE_128.txt", "KWP_AE_192.txt", "KWP_AE_256.txt"], load_nist_vectors, - ), - ) - def test_wrap(self, backend, params): - wrapping_key = binascii.unhexlify(params["k"]) - key_to_wrap = binascii.unhexlify(params["p"]) - wrapped_key = keywrap.aes_key_wrap_with_padding( - wrapping_key, key_to_wrap, backend ) - assert params["c"] == binascii.hexlify(wrapped_key) + for param in params: + with subtests.test(): + wrapping_key = binascii.unhexlify(param["k"]) + key_to_wrap = binascii.unhexlify(param["p"]) + wrapped_key = keywrap.aes_key_wrap_with_padding( + wrapping_key, key_to_wrap, backend + ) + assert param["c"] == binascii.hexlify(wrapped_key) - @pytest.mark.parametrize( - "params", - _load_all_params("keywrap", ["kwp_botan.txt"], load_nist_vectors), - ) - def test_wrap_additional_vectors(self, backend, params): - wrapping_key = binascii.unhexlify(params["key"]) - key_to_wrap = binascii.unhexlify(params["input"]) - wrapped_key = keywrap.aes_key_wrap_with_padding( - wrapping_key, key_to_wrap, backend + def test_wrap_additional_vectors(self, backend, subtests): + params = _load_all_params( + "keywrap", ["kwp_botan.txt"], load_nist_vectors ) - assert wrapped_key == binascii.unhexlify(params["output"]) + for param in params: + with subtests.test(): + wrapping_key = binascii.unhexlify(param["key"]) + key_to_wrap = binascii.unhexlify(param["input"]) + wrapped_key = keywrap.aes_key_wrap_with_padding( + wrapping_key, key_to_wrap, backend + ) + assert wrapped_key == binascii.unhexlify(param["output"]) - @pytest.mark.parametrize( - "params", - _load_all_params( + def test_unwrap(self, backend, subtests): + params = _load_all_params( os.path.join("keywrap", "kwtestvectors"), ["KWP_AD_128.txt", "KWP_AD_192.txt", "KWP_AD_256.txt"], load_nist_vectors, - ), - ) - def test_unwrap(self, backend, params): - wrapping_key = binascii.unhexlify(params["k"]) - wrapped_key = binascii.unhexlify(params["c"]) - if params.get("fail") is True: - with pytest.raises(keywrap.InvalidUnwrap): - keywrap.aes_key_unwrap_with_padding( + ) + for param in params: + with subtests.test(): + wrapping_key = binascii.unhexlify(param["k"]) + wrapped_key = binascii.unhexlify(param["c"]) + if param.get("fail") is True: + with pytest.raises(keywrap.InvalidUnwrap): + keywrap.aes_key_unwrap_with_padding( + wrapping_key, wrapped_key, backend + ) + else: + unwrapped_key = keywrap.aes_key_unwrap_with_padding( + wrapping_key, wrapped_key, backend + ) + assert param["p"] == binascii.hexlify(unwrapped_key) + + def test_unwrap_additional_vectors(self, backend, subtests): + params = _load_all_params( + "keywrap", ["kwp_botan.txt"], load_nist_vectors + ) + for param in params: + with subtests.test(): + wrapping_key = binascii.unhexlify(param["key"]) + wrapped_key = binascii.unhexlify(param["output"]) + unwrapped_key = keywrap.aes_key_unwrap_with_padding( wrapping_key, wrapped_key, backend ) - else: - unwrapped_key = keywrap.aes_key_unwrap_with_padding( - wrapping_key, wrapped_key, backend - ) - assert params["p"] == binascii.hexlify(unwrapped_key) - - @pytest.mark.parametrize( - "params", - _load_all_params("keywrap", ["kwp_botan.txt"], load_nist_vectors), - ) - def test_unwrap_additional_vectors(self, backend, params): - wrapping_key = binascii.unhexlify(params["key"]) - wrapped_key = binascii.unhexlify(params["output"]) - unwrapped_key = keywrap.aes_key_unwrap_with_padding( - wrapping_key, wrapped_key, backend - ) - assert unwrapped_key == binascii.unhexlify(params["input"]) + assert unwrapped_key == binascii.unhexlify(param["input"]) def test_unwrap_invalid_wrapped_key_length(self, backend): # Keys to unwrap must be at least 16 bytes From c6c329f60d7bc2c4630951a20da9ee9422642127 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 9 Dec 2020 11:45:31 -0600 Subject: [PATCH 0012/2380] Remove AES GCM < 64-bit IV tests instead of skipping (#5620) * remove AES tests we will always skip * constrain <64-bit IV vector removal to just GCM * apparently this is only used by GCM --- tests/hazmat/primitives/utils.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py index 46ca52dcb5b1..8bee115e23ea 100644 --- a/tests/hazmat/primitives/utils.py +++ b/tests/hazmat/primitives/utils.py @@ -77,6 +77,10 @@ def generate_aead_test( ): all_params = _load_all_params(path, file_names, param_loader) + assert mode_factory is GCM + # We don't support IVs < 64-bit in GCM mode so just strip them out + all_params = [i for i in all_params if len(i["iv"]) >= 16] + def test_aead(self, backend, subtests): for params in all_params: with subtests.test(): @@ -86,10 +90,6 @@ def test_aead(self, backend, subtests): def aead_test(backend, cipher_factory, mode_factory, params): - if mode_factory is GCM and len(params["iv"]) < 16: - # 16 because this is hex encoded data - pytest.skip("Less than 64-bit IVs are no longer supported") - if ( mode_factory is GCM and backend._fips_enabled From d6274d695e01de7c6ce073ce1d0899992090621e Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 9 Dec 2020 14:34:33 -0600 Subject: [PATCH 0013/2380] More test speedups via subtest + removal rather than skipping (#5617) * subtests ec * continue instead of return * indentation --- tests/hazmat/primitives/test_ec.py | 285 ++++++++++++++--------------- 1 file changed, 140 insertions(+), 145 deletions(-) diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index 354bab3462bd..f6569ec6056a 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -278,81 +278,75 @@ def test_ec_key_key_size(backend): @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) class TestECWithNumbers(object): - @pytest.mark.parametrize( - ("vector", "hash_type"), - list( - itertools.product( - load_vectors_from_file( - os.path.join( - "asymmetric", "ECDSA", "FIPS_186-3", "KeyPair.rsp" - ), - load_fips_ecdsa_key_pair_vectors, + def test_with_numbers(self, backend, subtests): + vectors = itertools.product( + load_vectors_from_file( + os.path.join( + "asymmetric", "ECDSA", "FIPS_186-3", "KeyPair.rsp" ), - _HASH_TYPES.values(), - ) - ), - ) - def test_with_numbers(self, backend, vector, hash_type): - curve_type = ec._CURVE_TYPES[vector["curve"]] + load_fips_ecdsa_key_pair_vectors, + ), + _HASH_TYPES.values(), + ) + for vector, hash_type in vectors: + with subtests.test(): + curve_type = ec._CURVE_TYPES[vector["curve"]] - _skip_ecdsa_vector(backend, curve_type, hash_type) + _skip_ecdsa_vector(backend, curve_type, hash_type) - key = ec.EllipticCurvePrivateNumbers( - vector["d"], - ec.EllipticCurvePublicNumbers( - vector["x"], vector["y"], curve_type() - ), - ).private_key(backend) - assert key + key = ec.EllipticCurvePrivateNumbers( + vector["d"], + ec.EllipticCurvePublicNumbers( + vector["x"], vector["y"], curve_type() + ), + ).private_key(backend) + assert key - priv_num = key.private_numbers() - assert priv_num.private_value == vector["d"] - assert priv_num.public_numbers.x == vector["x"] - assert priv_num.public_numbers.y == vector["y"] - assert curve_type().name == priv_num.public_numbers.curve.name + priv_num = key.private_numbers() + assert priv_num.private_value == vector["d"] + assert priv_num.public_numbers.x == vector["x"] + assert priv_num.public_numbers.y == vector["y"] + assert curve_type().name == priv_num.public_numbers.curve.name @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) class TestECDSAVectors(object): - @pytest.mark.parametrize( - ("vector", "hash_type"), - list( - itertools.product( - load_vectors_from_file( - os.path.join( - "asymmetric", "ECDSA", "FIPS_186-3", "KeyPair.rsp" - ), - load_fips_ecdsa_key_pair_vectors, + def test_signing_with_example_keys(self, backend, subtests): + vectors = itertools.product( + load_vectors_from_file( + os.path.join( + "asymmetric", "ECDSA", "FIPS_186-3", "KeyPair.rsp" ), - _HASH_TYPES.values(), - ) - ), - ) - def test_signing_with_example_keys(self, backend, vector, hash_type): - curve_type = ec._CURVE_TYPES[vector["curve"]] + load_fips_ecdsa_key_pair_vectors, + ), + _HASH_TYPES.values(), + ) + for vector, hash_type in vectors: + with subtests.test(): + curve_type = ec._CURVE_TYPES[vector["curve"]] - _skip_ecdsa_vector(backend, curve_type, hash_type) + _skip_ecdsa_vector(backend, curve_type, hash_type) - key = ec.EllipticCurvePrivateNumbers( - vector["d"], - ec.EllipticCurvePublicNumbers( - vector["x"], vector["y"], curve_type() - ), - ).private_key(backend) - assert key + key = ec.EllipticCurvePrivateNumbers( + vector["d"], + ec.EllipticCurvePublicNumbers( + vector["x"], vector["y"], curve_type() + ), + ).private_key(backend) + assert key - pkey = key.public_key() - assert pkey + pkey = key.public_key() + assert pkey - with pytest.warns(CryptographyDeprecationWarning): - signer = key.signer(ec.ECDSA(hash_type())) - signer.update(b"YELLOW SUBMARINE") - signature = signer.finalize() + with pytest.warns(CryptographyDeprecationWarning): + signer = key.signer(ec.ECDSA(hash_type())) + signer.update(b"YELLOW SUBMARINE") + signature = signer.finalize() - with pytest.warns(CryptographyDeprecationWarning): - verifier = pkey.verifier(signature, ec.ECDSA(hash_type())) - verifier.update(b"YELLOW SUBMARINE") - verifier.verify() + with pytest.warns(CryptographyDeprecationWarning): + verifier = pkey.verifier(signature, ec.ECDSA(hash_type())) + verifier.update(b"YELLOW SUBMARINE") + verifier.verify() @pytest.mark.parametrize("curve", ec._CURVE_TYPES.values()) def test_generate_vector_curves(self, backend, curve): @@ -492,9 +486,8 @@ def test_load_invalid_public_ec_key_from_numbers(self, backend): with pytest.raises(ValueError): numbers.public_key(backend) - @pytest.mark.parametrize( - "vector", - itertools.chain( + def test_signatures(self, backend, subtests): + vectors = itertools.chain( load_vectors_from_file( os.path.join( "asymmetric", "ECDSA", "FIPS_186-3", "SigGen.txt" @@ -505,46 +498,49 @@ def test_load_invalid_public_ec_key_from_numbers(self, backend): os.path.join("asymmetric", "ECDSA", "SECP256K1", "SigGen.txt"), load_fips_ecdsa_signing_vectors, ), - ), - ) - def test_signatures(self, backend, vector): - hash_type = _HASH_TYPES[vector["digest_algorithm"]] - curve_type = ec._CURVE_TYPES[vector["curve"]] + ) + for vector in vectors: + with subtests.test(): + hash_type = _HASH_TYPES[vector["digest_algorithm"]] + curve_type = ec._CURVE_TYPES[vector["curve"]] - _skip_ecdsa_vector(backend, curve_type, hash_type) + _skip_ecdsa_vector(backend, curve_type, hash_type) - key = ec.EllipticCurvePublicNumbers( - vector["x"], vector["y"], curve_type() - ).public_key(backend) + key = ec.EllipticCurvePublicNumbers( + vector["x"], vector["y"], curve_type() + ).public_key(backend) - signature = encode_dss_signature(vector["r"], vector["s"]) + signature = encode_dss_signature(vector["r"], vector["s"]) - key.verify(signature, vector["message"], ec.ECDSA(hash_type())) + key.verify(signature, vector["message"], ec.ECDSA(hash_type())) - @pytest.mark.parametrize( - "vector", - load_vectors_from_file( + def test_signature_failures(self, backend, subtests): + vectors = load_vectors_from_file( os.path.join("asymmetric", "ECDSA", "FIPS_186-3", "SigVer.rsp"), load_fips_ecdsa_signing_vectors, - ), - ) - def test_signature_failures(self, backend, vector): - hash_type = _HASH_TYPES[vector["digest_algorithm"]] - curve_type = ec._CURVE_TYPES[vector["curve"]] + ) + for vector in vectors: + with subtests.test(): + hash_type = _HASH_TYPES[vector["digest_algorithm"]] + curve_type = ec._CURVE_TYPES[vector["curve"]] - _skip_ecdsa_vector(backend, curve_type, hash_type) + _skip_ecdsa_vector(backend, curve_type, hash_type) - key = ec.EllipticCurvePublicNumbers( - vector["x"], vector["y"], curve_type() - ).public_key(backend) + key = ec.EllipticCurvePublicNumbers( + vector["x"], vector["y"], curve_type() + ).public_key(backend) - signature = encode_dss_signature(vector["r"], vector["s"]) + signature = encode_dss_signature(vector["r"], vector["s"]) - if vector["fail"] is True: - with pytest.raises(exceptions.InvalidSignature): - key.verify(signature, vector["message"], ec.ECDSA(hash_type())) - else: - key.verify(signature, vector["message"], ec.ECDSA(hash_type())) + if vector["fail"] is True: + with pytest.raises(exceptions.InvalidSignature): + key.verify( + signature, vector["message"], ec.ECDSA(hash_type()) + ) + else: + key.verify( + signature, vector["message"], ec.ECDSA(hash_type()) + ) def test_sign(self, backend): _skip_curve_unsupported(backend, ec.SECP256R1()) @@ -1187,65 +1183,64 @@ def test_signature_not_bytes(self, backend): @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) class TestECDH(object): - @pytest.mark.parametrize( - "vector", - load_vectors_from_file( + def test_key_exchange_with_vectors(self, backend, subtests): + vectors = load_vectors_from_file( os.path.join( "asymmetric", "ECDH", "KASValidityTest_ECCStaticUnified_NOKC_ZZOnly_init.fax", ), load_kasvs_ecdh_vectors, - ), - ) - def test_key_exchange_with_vectors(self, backend, vector): - _skip_exchange_algorithm_unsupported( - backend, ec.ECDH(), ec._CURVE_TYPES[vector["curve"]] ) - - key_numbers = vector["IUT"] - private_numbers = ec.EllipticCurvePrivateNumbers( - key_numbers["d"], - ec.EllipticCurvePublicNumbers( - key_numbers["x"], - key_numbers["y"], - ec._CURVE_TYPES[vector["curve"]](), - ), - ) - # Errno 5-7 indicates a bad public or private key, this doesn't test - # the ECDH code at all - if vector["fail"] and vector["errno"] in [5, 6, 7]: - with pytest.raises(ValueError): - private_numbers.private_key(backend) - return - else: - private_key = private_numbers.private_key(backend) - - peer_numbers = vector["CAVS"] - public_numbers = ec.EllipticCurvePublicNumbers( - peer_numbers["x"], - peer_numbers["y"], - ec._CURVE_TYPES[vector["curve"]](), - ) - # Errno 1 and 2 indicates a bad public key, this doesn't test the ECDH - # code at all - if vector["fail"] and vector["errno"] in [1, 2]: - with pytest.raises(ValueError): - public_numbers.public_key(backend) - return - else: - peer_pubkey = public_numbers.public_key(backend) - - z = private_key.exchange(ec.ECDH(), peer_pubkey) - z = int(hexlify(z).decode("ascii"), 16) - # At this point fail indicates that one of the underlying keys was - # changed. This results in a non-matching derived key. - if vector["fail"]: - # Errno 8 indicates Z should be changed. - assert vector["errno"] == 8 - assert z != vector["Z"] - else: - assert z == vector["Z"] + for vector in vectors: + with subtests.test(): + _skip_exchange_algorithm_unsupported( + backend, ec.ECDH(), ec._CURVE_TYPES[vector["curve"]] + ) + + key_numbers = vector["IUT"] + private_numbers = ec.EllipticCurvePrivateNumbers( + key_numbers["d"], + ec.EllipticCurvePublicNumbers( + key_numbers["x"], + key_numbers["y"], + ec._CURVE_TYPES[vector["curve"]](), + ), + ) + # Errno 5-7 indicates a bad public or private key, this + # doesn't test the ECDH code at all + if vector["fail"] and vector["errno"] in [5, 6, 7]: + with pytest.raises(ValueError): + private_numbers.private_key(backend) + continue + else: + private_key = private_numbers.private_key(backend) + + peer_numbers = vector["CAVS"] + public_numbers = ec.EllipticCurvePublicNumbers( + peer_numbers["x"], + peer_numbers["y"], + ec._CURVE_TYPES[vector["curve"]](), + ) + # Errno 1 and 2 indicates a bad public key, this doesn't test + # the ECDH code at all + if vector["fail"] and vector["errno"] in [1, 2]: + with pytest.raises(ValueError): + public_numbers.public_key(backend) + continue + else: + peer_pubkey = public_numbers.public_key(backend) + + z = private_key.exchange(ec.ECDH(), peer_pubkey) + z = int(hexlify(z).decode("ascii"), 16) + # At this point fail indicates that one of the underlying keys + # was changed. This results in a non-matching derived key. + if vector["fail"]: + # Errno 8 indicates Z should be changed. + assert vector["errno"] == 8 + assert z != vector["Z"] + else: + assert z == vector["Z"] @pytest.mark.parametrize( "vector", From b450df1d09cad3018abd51065d5dbba9064ca67c Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 9 Dec 2020 17:39:57 -0500 Subject: [PATCH 0014/2380] print 10 slowest tests to help us keep runtimes down (#5622) --- tox.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index a420dceaf04f..ac199e328fc8 100644 --- a/tox.ini +++ b/tox.ini @@ -18,7 +18,7 @@ commands = # We use parallel mode and then combine here so that coverage.py will take # the paths like .tox/py38/lib/python3.8/site-packages/cryptography/__init__.py # and collapse them into src/cryptography/__init__.py. - coverage run --parallel-mode -m pytest --capture=no --strict {posargs} + coverage run --parallel-mode -m pytest --capture=no --strict --durations=10 {posargs} coverage combine coverage report -m @@ -28,7 +28,7 @@ commands = basepython = pypy3 commands = pip list - pytest --capture=no --strict {posargs} + pytest --capture=no --strict --durations=10 {posargs} [testenv:docs] extras = From 7d34b55c3a3798d83819a3a845e590d234ad0728 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 9 Dec 2020 18:01:48 -0600 Subject: [PATCH 0015/2380] we already do this check in other places (#5624) * we already do this check in other places This test is *incredibly* expensive and we already do roundtrips like this on other DH groups. To make this test less expensive and also more accurate to its name we now verify that the parameters on the generated key match * empty commit the most important CI feature --- tests/hazmat/primitives/test_dh.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index 8a670a914300..f5db45dc8d3d 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -179,11 +179,7 @@ def test_dh_parameters_allows_rfc3526_groups(self, backend, vector): params = dh.DHParameterNumbers(p, int(vector["g"])) param = params.parameters(backend) key = param.generate_private_key() - # This confirms that a key generated with this group - # will pass DH_check when we serialize and de-serialize it via - # the Numbers path. - roundtripped_key = key.private_numbers().private_key(backend) - assert key.private_numbers() == roundtripped_key.private_numbers() + assert key.private_numbers().public_numbers.parameter_numbers == params @pytest.mark.skip_fips(reason="non-FIPS parameters") @pytest.mark.parametrize( From 657b75a01de302c34bbd8890b9803a8821662227 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 9 Dec 2020 21:30:44 -0600 Subject: [PATCH 0016/2380] re-add Cryptography_HAS_TLSEXT_HOSTNAME and port 3.3.1 changelog (#5627) --- CHANGELOG.rst | 7 +++++++ src/_cffi_src/openssl/ssl.py | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a5e699ddba08..7ff0f05d9cac 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,13 @@ Changelog * **BACKWARDS INCOMPATIBLE:** Support for Python 2 has been removed. +.. _v3-3-1: + +3.3.1 - 2020-12-09 +~~~~~~~~~~~~~~~~~~ + +* Re-added a legacy symbol causing problems for older ``pyOpenSSL`` users. + .. _v3-3: 3.3 - 2020-12-08 diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index 61813a3c038a..1977d4c16e7a 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -24,6 +24,7 @@ static const long Cryptography_HAS_VERIFIED_CHAIN; static const long Cryptography_HAS_KEYLOG; static const long Cryptography_HAS_GET_PROTO_VERSION; +static const long Cryptography_HAS_TLSEXT_HOSTNAME; /* Internally invented symbol to tell us if SSL_MODE_RELEASE_BUFFERS is * supported @@ -503,6 +504,11 @@ """ CUSTOMIZATIONS = """ +// This symbol is being preserved because removing it will break users with +// pyOpenSSL < 19.1 and pip < 20.x. We need to leave this in place until those +// users have upgraded. PersistentlyDeprecated2020 +static const long Cryptography_HAS_TLSEXT_HOSTNAME = 1; + #if CRYPTOGRAPHY_IS_LIBRESSL static const long Cryptography_HAS_VERIFIED_CHAIN = 0; Cryptography_STACK_OF_X509 *(*SSL_get0_verified_chain)(const SSL *) = NULL; From da2879d387b029ae32d33f24e4ee2eb282d3681e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 9 Dec 2020 22:33:57 -0500 Subject: [PATCH 0017/2380] remove check from setup.py that's not needed anymore (#5626) pypy 7.2 is the oldest pypy that supports py3.6 --- setup.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/setup.py b/setup.py index 1348e9be5797..9fe7c8ba7907 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,6 @@ # for complete details. import os -import platform import sys from setuptools import find_packages, setup @@ -26,14 +25,6 @@ # `setup_requirements` must be kept in sync with `pyproject.toml` setup_requirements = ["cffi>=1.12"] -if platform.python_implementation() == "PyPy": - if sys.pypy_version_info < (5, 4): - raise RuntimeError( - "cryptography is not compatible with PyPy < 5.4. Please upgrade " - "PyPy to use this library." - ) - - with open(os.path.join(base_dir, "README.rst")) as f: long_description = f.read() From 705cdb11fb263af4d9e819f96caaafba3ba71aec Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 9 Dec 2020 23:34:16 -0500 Subject: [PATCH 0018/2380] bump libressl versions (#5628) --- .github/workflows/ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b48cb3a95e7b..db2da2b912ee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,8 +23,9 @@ jobs: - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1h", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "2.9.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.0.2"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.1.4"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.2.2"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.1.5"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.2.3"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.3.1"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" steps: - uses: actions/checkout@v2 From 6e50cf3f93f7da02ea981da4efcc977057e2920f Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 10 Dec 2020 15:12:40 -0500 Subject: [PATCH 0019/2380] Convert a few more high cardinality tests to use subtests (#5632) --- tests/hazmat/primitives/test_aes.py | 35 +++---- tests/hazmat/primitives/test_dsa.py | 100 +++++++++---------- tests/hazmat/primitives/test_ed25519.py | 40 ++++---- tests/hazmat/primitives/test_hash_vectors.py | 46 ++++----- tests/hazmat/primitives/test_rsa.py | 47 ++++----- 5 files changed, 134 insertions(+), 134 deletions(-) diff --git a/tests/hazmat/primitives/test_aes.py b/tests/hazmat/primitives/test_aes.py index 099717801e0a..c9cb980037f8 100644 --- a/tests/hazmat/primitives/test_aes.py +++ b/tests/hazmat/primitives/test_aes.py @@ -24,13 +24,12 @@ ) @pytest.mark.requires_backend_interface(interface=CipherBackend) class TestAESModeXTS(object): - @pytest.mark.parametrize( - "vector", + def test_xts_vectors(self, backend, subtests): # This list comprehension excludes any vector that does not have a # data unit length that is divisible by 8. The NIST vectors include # tests for implementations that support encryption of data that is # not divisible modulo 8, but OpenSSL is not such an implementation. - [ + vectors = [ x for x in _load_all_params( os.path.join("ciphers", "AES", "XTS", "tweak-128hexstr"), @@ -38,20 +37,22 @@ class TestAESModeXTS(object): load_nist_vectors, ) if int(x["dataunitlen"]) / 8.0 == int(x["dataunitlen"]) // 8 - ], - ) - def test_xts_vectors(self, vector, backend): - key = binascii.unhexlify(vector["key"]) - tweak = binascii.unhexlify(vector["i"]) - pt = binascii.unhexlify(vector["pt"]) - ct = binascii.unhexlify(vector["ct"]) - cipher = base.Cipher(algorithms.AES(key), modes.XTS(tweak), backend) - enc = cipher.encryptor() - computed_ct = enc.update(pt) + enc.finalize() - assert computed_ct == ct - dec = cipher.decryptor() - computed_pt = dec.update(ct) + dec.finalize() - assert computed_pt == pt + ] + for vector in vectors: + with subtests.test(): + key = binascii.unhexlify(vector["key"]) + tweak = binascii.unhexlify(vector["i"]) + pt = binascii.unhexlify(vector["pt"]) + ct = binascii.unhexlify(vector["ct"]) + cipher = base.Cipher( + algorithms.AES(key), modes.XTS(tweak), backend + ) + enc = cipher.encryptor() + computed_ct = enc.update(pt) + enc.finalize() + assert computed_ct == ct + dec = cipher.decryptor() + computed_pt = dec.update(ct) + dec.finalize() + assert computed_pt == pt @pytest.mark.supported( diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py index 474da5df5682..b247247dd947 100644 --- a/tests/hazmat/primitives/test_dsa.py +++ b/tests/hazmat/primitives/test_dsa.py @@ -386,34 +386,33 @@ class TestDSAVerification(object): "SHA512": hashes.SHA512, } - @pytest.mark.parametrize( - "vector", - load_vectors_from_file( + def test_dsa_verification(self, backend, subtests): + vectors = load_vectors_from_file( os.path.join("asymmetric", "DSA", "FIPS_186-3", "SigVer.rsp"), load_fips_dsa_sig_vectors, - ), - ) - def test_dsa_verification(self, vector, backend): - digest_algorithm = vector["digest_algorithm"].replace("-", "") - algorithm = self._algorithms_dict[digest_algorithm] - - _skip_if_dsa_not_supported( - backend, algorithm, vector["p"], vector["q"], vector["g"] ) - - public_key = dsa.DSAPublicNumbers( - parameter_numbers=dsa.DSAParameterNumbers( - vector["p"], vector["q"], vector["g"] - ), - y=vector["y"], - ).public_key(backend) - sig = encode_dss_signature(vector["r"], vector["s"]) - - if vector["result"] == "F": - with pytest.raises(InvalidSignature): - public_key.verify(sig, vector["msg"], algorithm()) - else: - public_key.verify(sig, vector["msg"], algorithm()) + for vector in vectors: + with subtests.test(): + digest_algorithm = vector["digest_algorithm"].replace("-", "") + algorithm = self._algorithms_dict[digest_algorithm] + + _skip_if_dsa_not_supported( + backend, algorithm, vector["p"], vector["q"], vector["g"] + ) + + public_key = dsa.DSAPublicNumbers( + parameter_numbers=dsa.DSAParameterNumbers( + vector["p"], vector["q"], vector["g"] + ), + y=vector["y"], + ).public_key(backend) + sig = encode_dss_signature(vector["r"], vector["s"]) + + if vector["result"] == "F": + with pytest.raises(InvalidSignature): + public_key.verify(sig, vector["msg"], algorithm()) + else: + public_key.verify(sig, vector["msg"], algorithm()) def test_dsa_verify_invalid_asn1(self, backend): public_key = DSA_KEY_1024.public_numbers.public_key(backend) @@ -494,34 +493,35 @@ class TestDSASignature(object): "SHA512": hashes.SHA512, } - @pytest.mark.parametrize( - "vector", - load_vectors_from_file( + def test_dsa_signing(self, backend, subtests): + vectors = load_vectors_from_file( os.path.join("asymmetric", "DSA", "FIPS_186-3", "SigGen.txt"), load_fips_dsa_sig_vectors, - ), - ) - def test_dsa_signing(self, vector, backend): - digest_algorithm = vector["digest_algorithm"].replace("-", "") - algorithm = self._algorithms_dict[digest_algorithm] - - _skip_if_dsa_not_supported( - backend, algorithm, vector["p"], vector["q"], vector["g"] ) - - private_key = dsa.DSAPrivateNumbers( - public_numbers=dsa.DSAPublicNumbers( - parameter_numbers=dsa.DSAParameterNumbers( - vector["p"], vector["q"], vector["g"] - ), - y=vector["y"], - ), - x=vector["x"], - ).private_key(backend) - signature = private_key.sign(vector["msg"], algorithm()) - assert signature - - private_key.public_key().verify(signature, vector["msg"], algorithm()) + for vector in vectors: + with subtests.test(): + digest_algorithm = vector["digest_algorithm"].replace("-", "") + algorithm = self._algorithms_dict[digest_algorithm] + + _skip_if_dsa_not_supported( + backend, algorithm, vector["p"], vector["q"], vector["g"] + ) + + private_key = dsa.DSAPrivateNumbers( + public_numbers=dsa.DSAPublicNumbers( + parameter_numbers=dsa.DSAParameterNumbers( + vector["p"], vector["q"], vector["g"] + ), + y=vector["y"], + ), + x=vector["x"], + ).private_key(backend) + signature = private_key.sign(vector["msg"], algorithm()) + assert signature + + private_key.public_key().verify( + signature, vector["msg"], algorithm() + ) def test_use_after_finalize(self, backend): private_key = DSA_KEY_1024.private_key(backend) diff --git a/tests/hazmat/primitives/test_ed25519.py b/tests/hazmat/primitives/test_ed25519.py index be239026aa1c..ce74ee8f2d00 100644 --- a/tests/hazmat/primitives/test_ed25519.py +++ b/tests/hazmat/primitives/test_ed25519.py @@ -68,29 +68,29 @@ def test_ed25519_unsupported(backend): skip_message="Requires OpenSSL with Ed25519 support", ) class TestEd25519Signing(object): - @pytest.mark.parametrize( - "vector", - load_vectors_from_file( + def test_sign_verify_input(self, backend, subtests): + vectors = load_vectors_from_file( os.path.join("asymmetric", "Ed25519", "sign.input"), load_ed25519_vectors, - ), - ) - def test_sign_verify_input(self, vector, backend): - sk = binascii.unhexlify(vector["secret_key"]) - pk = binascii.unhexlify(vector["public_key"]) - message = binascii.unhexlify(vector["message"]) - signature = binascii.unhexlify(vector["signature"]) - private_key = Ed25519PrivateKey.from_private_bytes(sk) - computed_sig = private_key.sign(message) - assert computed_sig == signature - public_key = private_key.public_key() - assert ( - public_key.public_bytes( - serialization.Encoding.Raw, serialization.PublicFormat.Raw - ) - == pk ) - public_key.verify(signature, message) + for vector in vectors: + with subtests.test(): + sk = binascii.unhexlify(vector["secret_key"]) + pk = binascii.unhexlify(vector["public_key"]) + message = binascii.unhexlify(vector["message"]) + signature = binascii.unhexlify(vector["signature"]) + private_key = Ed25519PrivateKey.from_private_bytes(sk) + computed_sig = private_key.sign(message) + assert computed_sig == signature + public_key = private_key.public_key() + assert ( + public_key.public_bytes( + serialization.Encoding.Raw, + serialization.PublicFormat.Raw, + ) + == pk + ) + public_key.verify(signature, message) def test_invalid_signature(self, backend): key = Ed25519PrivateKey.generate() diff --git a/tests/hazmat/primitives/test_hash_vectors.py b/tests/hazmat/primitives/test_hash_vectors.py index 99adcf92300f..553eee37599f 100644 --- a/tests/hazmat/primitives/test_hash_vectors.py +++ b/tests/hazmat/primitives/test_hash_vectors.py @@ -230,21 +230,20 @@ class TestSHAKE128(object): hashes.SHAKE128(digest_size=16), ) - @pytest.mark.parametrize( - "vector", - _load_all_params( + def test_shake128_variable(self, backend, subtests): + vectors = _load_all_params( os.path.join("hashes", "SHAKE"), ["SHAKE128VariableOut.rsp"], load_nist_vectors, - ), - ) - def test_shake128_variable(self, vector, backend): - output_length = int(vector["outputlen"]) // 8 - msg = binascii.unhexlify(vector["msg"]) - shake = hashes.SHAKE128(digest_size=output_length) - m = hashes.Hash(shake, backend=backend) - m.update(msg) - assert m.finalize() == binascii.unhexlify(vector["output"]) + ) + for vector in vectors: + with subtests.test(): + output_length = int(vector["outputlen"]) // 8 + msg = binascii.unhexlify(vector["msg"]) + shake = hashes.SHAKE128(digest_size=output_length) + m = hashes.Hash(shake, backend=backend) + m.update(msg) + assert m.finalize() == binascii.unhexlify(vector["output"]) @pytest.mark.supported( @@ -262,18 +261,17 @@ class TestSHAKE256(object): hashes.SHAKE256(digest_size=32), ) - @pytest.mark.parametrize( - "vector", - _load_all_params( + def test_shake256_variable(self, backend, subtests): + vectors = _load_all_params( os.path.join("hashes", "SHAKE"), ["SHAKE256VariableOut.rsp"], load_nist_vectors, - ), - ) - def test_shake256_variable(self, vector, backend): - output_length = int(vector["outputlen"]) // 8 - msg = binascii.unhexlify(vector["msg"]) - shake = hashes.SHAKE256(digest_size=output_length) - m = hashes.Hash(shake, backend=backend) - m.update(msg) - assert m.finalize() == binascii.unhexlify(vector["output"]) + ) + for vector in vectors: + with subtests.test(): + output_length = int(vector["outputlen"]) // 8 + msg = binascii.unhexlify(vector["msg"]) + shake = hashes.SHAKE256(digest_size=output_length) + m = hashes.Hash(shake, backend=backend) + m.update(msg) + assert m.finalize() == binascii.unhexlify(vector["output"]) diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 1e32b7f168a4..d10eb93f4063 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -1623,29 +1623,30 @@ def test_decrypt_oaep_vectors(self, vector, backend): "Does not support OAEP using SHA224 MGF1 and SHA224 hash." ), ) - @pytest.mark.parametrize("vector", _build_oaep_sha2_vectors()) - def test_decrypt_oaep_sha2_vectors(self, vector, backend): - private, public, example, mgf1_alg, hash_alg = vector - skey = rsa.RSAPrivateNumbers( - p=private["p"], - q=private["q"], - d=private["private_exponent"], - dmp1=private["dmp1"], - dmq1=private["dmq1"], - iqmp=private["iqmp"], - public_numbers=rsa.RSAPublicNumbers( - e=private["public_exponent"], n=private["modulus"] - ), - ).private_key(backend) - message = skey.decrypt( - binascii.unhexlify(example["encryption"]), - padding.OAEP( - mgf=padding.MGF1(algorithm=mgf1_alg), - algorithm=hash_alg, - label=None, - ), - ) - assert message == binascii.unhexlify(example["message"]) + def test_decrypt_oaep_sha2_vectors(self, backend, subtests): + vectors = _build_oaep_sha2_vectors() + for private, public, example, mgf1_alg, hash_alg in vectors: + with subtests.test(): + skey = rsa.RSAPrivateNumbers( + p=private["p"], + q=private["q"], + d=private["private_exponent"], + dmp1=private["dmp1"], + dmq1=private["dmq1"], + iqmp=private["iqmp"], + public_numbers=rsa.RSAPublicNumbers( + e=private["public_exponent"], n=private["modulus"] + ), + ).private_key(backend) + message = skey.decrypt( + binascii.unhexlify(example["encryption"]), + padding.OAEP( + mgf=padding.MGF1(algorithm=mgf1_alg), + algorithm=hash_alg, + label=None, + ), + ) + assert message == binascii.unhexlify(example["message"]) @pytest.mark.supported( only_if=lambda backend: backend.rsa_padding_supported( From 137b432da0b47c308b238926f2495c893cbb08b7 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 10 Dec 2020 15:51:05 -0600 Subject: [PATCH 0020/2380] xdist experiment (#5621) * switch to xdist in tox for faster runs * not using auto to avoid too many processes on local laptops * we need to use pytest-cov to generate coverage properly now * these env vars aren't present on no coverage builds * tox changes --- setup.py | 2 ++ tests/hazmat/backends/test_openssl_memleak.py | 8 ++++++++ tox.ini | 10 ++-------- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/setup.py b/setup.py index 9fe7c8ba7907..7ee1f29845b0 100644 --- a/setup.py +++ b/setup.py @@ -73,7 +73,9 @@ extras_require={ "test": [ "pytest>=4.4.0", + "pytest-cov", "pytest-subtests", + "pytest-xdist", "pretend", "iso8601", "pytz", diff --git a/tests/hazmat/backends/test_openssl_memleak.py b/tests/hazmat/backends/test_openssl_memleak.py index 4f64fcb8a5b0..950a41ac9ed0 100644 --- a/tests/hazmat/backends/test_openssl_memleak.py +++ b/tests/hazmat/backends/test_openssl_memleak.py @@ -126,6 +126,14 @@ def free(ptr, path, line): def assert_no_memory_leaks(s, argv=[]): env = os.environ.copy() env["PYTHONPATH"] = os.pathsep.join(sys.path) + + # When using pytest-cov it attempts to instrument subprocesses. This + # causes the memleak tests to raise exceptions. + # we don't need coverage so we remove the env vars. + env.pop("COV_CORE_CONFIG", None) + env.pop("COV_CORE_DATAFILE", None) + env.pop("COV_CORE_SOURCE", None) + argv = [ sys.executable, "-c", diff --git a/tox.ini b/tox.ini index ac199e328fc8..d945bef356bc 100644 --- a/tox.ini +++ b/tox.ini @@ -9,18 +9,12 @@ extras = ssh: ssh deps = # This must be kept in sync with .github/workflows/ci.yml - coverage ./vectors randomorder: pytest-randomly passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH USERNAME PYTHONIOENCODING OPENSSL_FORCE_FIPS_MODE commands = pip list - # We use parallel mode and then combine here so that coverage.py will take - # the paths like .tox/py38/lib/python3.8/site-packages/cryptography/__init__.py - # and collapse them into src/cryptography/__init__.py. - coverage run --parallel-mode -m pytest --capture=no --strict --durations=10 {posargs} - coverage combine - coverage report -m + pytest -n auto --cov=cryptography --cov=tests --capture=no --strict --durations=10 {posargs} # This target disables coverage on pypy because of performance problems with # coverage.py on pypy. @@ -28,7 +22,7 @@ commands = basepython = pypy3 commands = pip list - pytest --capture=no --strict --durations=10 {posargs} + pytest -n auto --capture=no --strict --durations=10 {posargs} [testenv:docs] extras = From 4a19a43c3ba98922e7a130bbf1888c57a378dda0 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 10 Dec 2020 21:01:15 -0500 Subject: [PATCH 0021/2380] debian bullseye has 3.9 now (#5634) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index db2da2b912ee..5bf147959da1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -86,7 +86,7 @@ jobs: - {IMAGE: "pyca/cryptography-runner-centos8", TOXENV: "py36"} - {IMAGE: "pyca/cryptography-runner-centos8-fips", TOXENV: "py36", FIPS: true} - {IMAGE: "pyca/cryptography-runner-buster", TOXENV: "py37"} - - {IMAGE: "pyca/cryptography-runner-bullseye", TOXENV: "py38"} + - {IMAGE: "pyca/cryptography-runner-bullseye", TOXENV: "py39"} - {IMAGE: "pyca/cryptography-runner-sid", TOXENV: "py39"} - {IMAGE: "pyca/cryptography-runner-ubuntu-bionic", TOXENV: "py36"} - {IMAGE: "pyca/cryptography-runner-ubuntu-focal", TOXENV: "py38"} From d8c6c1eef3c277ff02ec6f3a57ae4a07b0d4e34c Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 10 Dec 2020 21:56:08 -0500 Subject: [PATCH 0022/2380] Update APIs to use non-deprecated OpenSSL ones where possible (#5633) cherry picked from #4920 --- src/_cffi_src/openssl/asn1.py | 1 + src/_cffi_src/openssl/evp.py | 1 + src/_cffi_src/openssl/x509.py | 15 +++++++++++---- src/_cffi_src/openssl/x509_vfy.py | 4 ++++ .../hazmat/backends/openssl/backend.py | 4 ++-- .../hazmat/backends/openssl/ciphers.py | 2 +- src/cryptography/hazmat/backends/openssl/x509.py | 8 ++++---- 7 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/_cffi_src/openssl/asn1.py b/src/_cffi_src/openssl/asn1.py index 3e646239d474..0841a115d82a 100644 --- a/src/_cffi_src/openssl/asn1.py +++ b/src/_cffi_src/openssl/asn1.py @@ -44,6 +44,7 @@ /* ASN1 STRING */ unsigned char *ASN1_STRING_data(ASN1_STRING *); +const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *); int ASN1_STRING_set(ASN1_STRING *, const void *, int); /* ASN1 OCTET STRING */ diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py index c9575dc47b71..2b2f995e389f 100644 --- a/src/_cffi_src/openssl/evp.py +++ b/src/_cffi_src/openssl/evp.py @@ -47,6 +47,7 @@ const unsigned char *, int); int EVP_CipherFinal_ex(EVP_CIPHER_CTX *, unsigned char *, int *); int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *); +int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *); EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void); void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *); int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *, int); diff --git a/src/_cffi_src/openssl/x509.py b/src/_cffi_src/openssl/x509.py index e7f1368cf2e7..778b5da31611 100644 --- a/src/_cffi_src/openssl/x509.py +++ b/src/_cffi_src/openssl/x509.py @@ -201,8 +201,10 @@ ASN1_TIME *X509_get_notBefore(X509 *); ASN1_TIME *X509_get_notAfter(X509 *); -ASN1_TIME *X509_getm_notBefore(X509 *); -ASN1_TIME *X509_getm_notAfter(X509 *); +ASN1_TIME *X509_getm_notBefore(const X509 *); +ASN1_TIME *X509_getm_notAfter(const X509 *); +const ASN1_TIME *X509_get0_notBefore(const X509 *); +const ASN1_TIME *X509_get0_notAfter(const X509 *); long X509_REQ_get_version(X509_REQ *); X509_NAME *X509_REQ_get_subject_name(X509_REQ *); @@ -234,6 +236,8 @@ long X509_CRL_get_version(X509_CRL *); ASN1_TIME *X509_CRL_get_lastUpdate(X509_CRL *); ASN1_TIME *X509_CRL_get_nextUpdate(X509_CRL *); +const ASN1_TIME *X509_CRL_get0_lastUpdate(const X509_CRL *); +const ASN1_TIME *X509_CRL_get0_nextUpdate(const X509_CRL *); X509_NAME *X509_CRL_get_issuer(X509_CRL *); Cryptography_STACK_OF_X509_REVOKED *X509_CRL_get_REVOKED(X509_CRL *); @@ -242,8 +246,11 @@ int X509_CRL_set_nextUpdate(X509_CRL *, ASN1_TIME *); int X509_set_notBefore(X509 *, ASN1_TIME *); int X509_set_notAfter(X509 *, ASN1_TIME *); -int X509_set1_notBefore(X509 *, ASN1_TIME *); -int X509_set1_notAfter(X509 *, ASN1_TIME *); + +int X509_CRL_set1_lastUpdate(X509_CRL *, const ASN1_TIME *); +int X509_CRL_set1_nextUpdate(X509_CRL *, const ASN1_TIME *); +int X509_set1_notBefore(X509 *, const ASN1_TIME *); +int X509_set1_notAfter(X509 *, const ASN1_TIME *); EC_KEY *d2i_EC_PUBKEY_bio(BIO *, EC_KEY **); int i2d_EC_PUBKEY_bio(BIO *, EC_KEY *); diff --git a/src/_cffi_src/openssl/x509_vfy.py b/src/_cffi_src/openssl/x509_vfy.py index 57de6d0ec80e..dc4895f4ecbb 100644 --- a/src/_cffi_src/openssl/x509_vfy.py +++ b/src/_cffi_src/openssl/x509_vfy.py @@ -155,8 +155,12 @@ Cryptography_STACK_OF_X509 *); void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *, Cryptography_STACK_OF_X509 *); +void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *, + Cryptography_STACK_OF_X509 *); void X509_STORE_CTX_set_cert(X509_STORE_CTX *, X509 *); void X509_STORE_CTX_set_chain(X509_STORE_CTX *,Cryptography_STACK_OF_X509 *); +void X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *, + Cryptography_STACK_OF_X509 *); X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *); void X509_STORE_CTX_set0_param(X509_STORE_CTX *, X509_VERIFY_PARAM *); int X509_STORE_CTX_set_default(X509_STORE_CTX *, const char *); diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 76fe79f73615..271873d92ad2 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1101,12 +1101,12 @@ def create_x509_crl(self, builder, private_key, algorithm): # Set the last update time. last_update = self._create_asn1_time(builder._last_update) - res = self._lib.X509_CRL_set_lastUpdate(x509_crl, last_update) + res = self._lib.X509_CRL_set1_lastUpdate(x509_crl, last_update) self.openssl_assert(res == 1) # Set the next update time. next_update = self._create_asn1_time(builder._next_update) - res = self._lib.X509_CRL_set_nextUpdate(x509_crl, next_update) + res = self._lib.X509_CRL_set1_nextUpdate(x509_crl, next_update) self.openssl_assert(res == 1) # Add extensions. diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py index 36871d066ec7..760774079766 100644 --- a/src/cryptography/hazmat/backends/openssl/ciphers.py +++ b/src/cryptography/hazmat/backends/openssl/ciphers.py @@ -198,7 +198,7 @@ def finalize(self): self._backend.openssl_assert(res != 0) self._tag = self._backend._ffi.buffer(tag_buf)[:] - res = self._backend._lib.EVP_CIPHER_CTX_cleanup(self._ctx) + res = self._backend._lib.EVP_CIPHER_CTX_reset(self._ctx) self._backend.openssl_assert(res == 1) return self._backend._ffi.buffer(buf)[: outlen[0]] diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index d7497a3e51c2..cb71e645c4f5 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -85,12 +85,12 @@ def public_key(self): @property def not_valid_before(self): - asn1_time = self._backend._lib.X509_getm_notBefore(self._x509) + asn1_time = self._backend._lib.X509_get0_notBefore(self._x509) return _parse_asn1_time(self._backend, asn1_time) @property def not_valid_after(self): - asn1_time = self._backend._lib.X509_getm_notAfter(self._x509) + asn1_time = self._backend._lib.X509_get0_notAfter(self._x509) return _parse_asn1_time(self._backend, asn1_time) @property @@ -276,13 +276,13 @@ def issuer(self): @property def next_update(self): - nu = self._backend._lib.X509_CRL_get_nextUpdate(self._x509_crl) + nu = self._backend._lib.X509_CRL_get0_nextUpdate(self._x509_crl) self._backend.openssl_assert(nu != self._backend._ffi.NULL) return _parse_asn1_time(self._backend, nu) @property def last_update(self): - lu = self._backend._lib.X509_CRL_get_lastUpdate(self._x509_crl) + lu = self._backend._lib.X509_CRL_get0_lastUpdate(self._x509_crl) self._backend.openssl_assert(lu != self._backend._ffi.NULL) return _parse_asn1_time(self._backend, lu) From 6d8bb261eb89b865472bc40204b1a3c22906b490 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 10 Dec 2020 23:07:28 -0600 Subject: [PATCH 0023/2380] bump openssl to latest in CI and change some job names (#5636) * bump openssl to latest in CI and change some job names * change more * missed one last entry --- .github/workflows/ci.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5bf147959da1..869ffa092723 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,9 +18,9 @@ jobs: - {VERSION: "3.9", TOXENV: "pep8,packaging,docs", COVERAGE: "false"} - {VERSION: "pypy3", TOXENV: "pypy3-nocoverage", COVERAGE: "false"} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1h"}} - - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1h"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1h", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1i"}} + - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1i"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1i", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "2.9.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.0.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.1.5"}} @@ -94,7 +94,7 @@ jobs: - {IMAGE: "pyca/cryptography-runner-ubuntu-rolling", TOXENV: "py38-randomorder"} - {IMAGE: "pyca/cryptography-runner-fedora", TOXENV: "py39"} - {IMAGE: "pyca/cryptography-runner-alpine", TOXENV: "py38"} - name: "tox -e ${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" + name: "${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" steps: - uses: actions/checkout@v2 - run: 'git clone --depth=1 https://github.com/google/wycheproof "$HOME/wycheproof"' @@ -107,7 +107,7 @@ jobs: TOXENV: ${{ matrix.IMAGE.TOXENV }} - uses: ./.github/actions/upload-coverage with: - name: "tox -e ${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" + name: "${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" macos: runs-on: macos-latest @@ -116,7 +116,7 @@ jobs: PYTHON: - {VERSION: "3.6", TOXENV: "py36", EXTRA_CFLAGS: ""} - {VERSION: "3.9", TOXENV: "py39", EXTRA_CFLAGS: "-DUSE_OSRANDOM_RNG_FOR_TESTING"} - name: "Python ${{ matrix.PYTHON.VERSION }} on macOS" + name: "${{ matrix.PYTHON.TOXENV }} on macOS" steps: - uses: actions/checkout@v2 - name: Setup python @@ -145,7 +145,7 @@ jobs: - uses: ./.github/actions/upload-coverage with: - name: "Python ${{ matrix.PYTHON.VERSION }} on macOS" + name: "${{ matrix.PYTHON.TOXENV }} on macOS" windows: runs-on: windows-latest @@ -159,7 +159,7 @@ jobs: - {VERSION: "3.7", TOXENV: "py37", MSVC_VERSION: "2019", CL_FLAGS: ""} - {VERSION: "3.8", TOXENV: "py38", MSVC_VERSION: "2019", CL_FLAGS: ""} - {VERSION: "3.9", TOXENV: "py39", MSVC_VERSION: "2019", CL_FLAGS: "/D USE_OSRANDOM_RNG_FOR_TESTING"} - name: "Python ${{ matrix.PYTHON.VERSION }} on ${{ matrix.WINDOWS.WINDOWS }}" + name: "${{ matrix.PYTHON.TOXENV }} on ${{ matrix.WINDOWS.WINDOWS }}" steps: - uses: actions/checkout@v2 - name: Setup python @@ -186,7 +186,7 @@ jobs: - uses: ./.github/actions/upload-coverage with: - name: "Python ${{ matrix.PYTHON.VERSION }} on ${{ matrix.WINDOWS.WINDOWS }}" + name: "${{ matrix.PYTHON.TOXENV }} on ${{ matrix.WINDOWS.WINDOWS }}" linux-downstream: runs-on: ubuntu-latest From bb0db002c38ad96fa6502ac3b42ced836d2e12e4 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 10 Dec 2020 23:21:10 -0600 Subject: [PATCH 0024/2380] remove windows builds and only test lowest/highest (#5635) same policy as our macOS builders --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 869ffa092723..08c9d496e9e4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -156,8 +156,6 @@ jobs: - {ARCH: 'x64', WINDOWS: 'win64'} PYTHON: - {VERSION: "3.6", TOXENV: "py36", MSVC_VERSION: "2019", CL_FLAGS: ""} - - {VERSION: "3.7", TOXENV: "py37", MSVC_VERSION: "2019", CL_FLAGS: ""} - - {VERSION: "3.8", TOXENV: "py38", MSVC_VERSION: "2019", CL_FLAGS: ""} - {VERSION: "3.9", TOXENV: "py39", MSVC_VERSION: "2019", CL_FLAGS: "/D USE_OSRANDOM_RNG_FOR_TESTING"} name: "${{ matrix.PYTHON.TOXENV }} on ${{ matrix.WINDOWS.WINDOWS }}" steps: From ebd9d4daa1e2f6613608513b500e968ef258bfe7 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 11 Dec 2020 00:39:18 -0500 Subject: [PATCH 0025/2380] add a timeout to builds (#5637) this way if they hang, they only hang for a little bit --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 08c9d496e9e4..273fa36b2997 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,6 +27,7 @@ jobs: - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.2.3"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.3.1"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" + timeout-minutes: 30 steps: - uses: actions/checkout@v2 - name: Setup python @@ -95,6 +96,7 @@ jobs: - {IMAGE: "pyca/cryptography-runner-fedora", TOXENV: "py39"} - {IMAGE: "pyca/cryptography-runner-alpine", TOXENV: "py38"} name: "${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" + timeout-minutes: 30 steps: - uses: actions/checkout@v2 - run: 'git clone --depth=1 https://github.com/google/wycheproof "$HOME/wycheproof"' @@ -117,6 +119,7 @@ jobs: - {VERSION: "3.6", TOXENV: "py36", EXTRA_CFLAGS: ""} - {VERSION: "3.9", TOXENV: "py39", EXTRA_CFLAGS: "-DUSE_OSRANDOM_RNG_FOR_TESTING"} name: "${{ matrix.PYTHON.TOXENV }} on macOS" + timeout-minutes: 30 steps: - uses: actions/checkout@v2 - name: Setup python @@ -158,6 +161,7 @@ jobs: - {VERSION: "3.6", TOXENV: "py36", MSVC_VERSION: "2019", CL_FLAGS: ""} - {VERSION: "3.9", TOXENV: "py39", MSVC_VERSION: "2019", CL_FLAGS: "/D USE_OSRANDOM_RNG_FOR_TESTING"} name: "${{ matrix.PYTHON.TOXENV }} on ${{ matrix.WINDOWS.WINDOWS }}" + timeout-minutes: 30 steps: - uses: actions/checkout@v2 - name: Setup python @@ -199,6 +203,7 @@ jobs: - certbot - certbot-josepy name: "Downstream tests for ${{ matrix.DOWNSTREAM }}" + timeout-minutes: 30 steps: - uses: actions/checkout@v2 - name: Setup python @@ -215,6 +220,7 @@ jobs: if: github.event_name == 'push' && github.ref == 'refs/heads/master' runs-on: ubuntu-latest name: "linkcheck" + timeout-minutes: 30 steps: - uses: actions/checkout@v2 - name: Setup python From f85e0684a1ea1c0f0b8bf7f9ba958c0335caa0fc Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 11 Dec 2020 11:18:46 -0600 Subject: [PATCH 0026/2380] make the container build names more readable (#5638) * make the container build names more readable * nope --- .github/workflows/ci.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 273fa36b2997..f68af112c29f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,21 +80,21 @@ jobs: linux-distros: runs-on: ubuntu-latest - container: ${{ matrix.IMAGE.IMAGE }} + container: pyca/cryptography-runner-${{ matrix.IMAGE.IMAGE }} strategy: matrix: IMAGE: - - {IMAGE: "pyca/cryptography-runner-centos8", TOXENV: "py36"} - - {IMAGE: "pyca/cryptography-runner-centos8-fips", TOXENV: "py36", FIPS: true} - - {IMAGE: "pyca/cryptography-runner-buster", TOXENV: "py37"} - - {IMAGE: "pyca/cryptography-runner-bullseye", TOXENV: "py39"} - - {IMAGE: "pyca/cryptography-runner-sid", TOXENV: "py39"} - - {IMAGE: "pyca/cryptography-runner-ubuntu-bionic", TOXENV: "py36"} - - {IMAGE: "pyca/cryptography-runner-ubuntu-focal", TOXENV: "py38"} - - {IMAGE: "pyca/cryptography-runner-ubuntu-rolling", TOXENV: "py38"} - - {IMAGE: "pyca/cryptography-runner-ubuntu-rolling", TOXENV: "py38-randomorder"} - - {IMAGE: "pyca/cryptography-runner-fedora", TOXENV: "py39"} - - {IMAGE: "pyca/cryptography-runner-alpine", TOXENV: "py38"} + - {IMAGE: "centos8", TOXENV: "py36"} + - {IMAGE: "centos8-fips", TOXENV: "py36", FIPS: true} + - {IMAGE: "buster", TOXENV: "py37"} + - {IMAGE: "bullseye", TOXENV: "py39"} + - {IMAGE: "sid", TOXENV: "py39"} + - {IMAGE: "ubuntu-bionic", TOXENV: "py36"} + - {IMAGE: "ubuntu-focal", TOXENV: "py38"} + - {IMAGE: "ubuntu-rolling", TOXENV: "py38"} + - {IMAGE: "ubuntu-rolling", TOXENV: "py38-randomorder"} + - {IMAGE: "fedora", TOXENV: "py39"} + - {IMAGE: "alpine", TOXENV: "py38"} name: "${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" timeout-minutes: 30 steps: From 35ad3129656b558ea45010468391ac3b9e93f314 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 12 Dec 2020 01:58:15 -0500 Subject: [PATCH 0027/2380] Point at ghcr for repos (#5640) * Point at ghcr for repos * poke GHA --- .github/workflows/ci.yml | 2 +- .github/workflows/wheel-builder.yml | 6 +++--- .zuul.d/jobs.yaml | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f68af112c29f..6a933eaeb4cb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,7 +80,7 @@ jobs: linux-distros: runs-on: ubuntu-latest - container: pyca/cryptography-runner-${{ matrix.IMAGE.IMAGE }} + container: ghcr.io/pyca/cryptography-runner-${{ matrix.IMAGE.IMAGE }} strategy: matrix: IMAGE: diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 4365174c80c8..8a4a083bf8d4 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -8,15 +8,15 @@ on: jobs: manylinux: runs-on: ubuntu-latest - container: ${{ matrix.MANYLINUX.CONTAINER }} + container: ghcr.io/pyca/${{ matrix.MANYLINUX.CONTAINER }} strategy: matrix: PYTHON: ["cp36-cp36m"] MANYLINUX: - NAME: manylinux1_x86_64 - CONTAINER: "pyca/cryptography-manylinux1:x86_64" + CONTAINER: "cryptography-manylinux1:x86_64" - NAME: manylinux2010_x86_64 - CONTAINER: "pyca/cryptography-manylinux2010:x86_64" + CONTAINER: "cryptography-manylinux2010:x86_64" name: "${{ matrix.PYTHON }} for ${{ matrix.MANYLINUX.NAME }}" steps: - run: /opt/python/${{ matrix.PYTHON }}/bin/python -m virtualenv .venv diff --git a/.zuul.d/jobs.yaml b/.zuul.d/jobs.yaml index bf542b0c96c2..12f5104caed9 100644 --- a/.zuul.d/jobs.yaml +++ b/.zuul.d/jobs.yaml @@ -37,7 +37,7 @@ vars: wheel_builds: - platform: manylinux2014_aarch64 - image: pyca/cryptography-manylinux2014_aarch64 + image: ghcr.io/pyca/cryptography-manylinux2014_aarch64 pythons: - cp36-cp36m @@ -48,10 +48,10 @@ vars: wheel_builds: - platform: manylinux1_x86_64 - image: pyca/cryptography-manylinux1:x86_64 + image: ghcr.io/pyca/cryptography-manylinux1:x86_64 pythons: - cp36-cp36m - platform: manylinux2010_x86_64 - image: pyca/cryptography-manylinux2010:x86_64 + image: ghcr.io/pyca/cryptography-manylinux2010:x86_64 pythons: - cp36-cp36m From 031044cab2daddad2c6b0325aa3606848a1607c0 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 12 Dec 2020 02:12:21 -0500 Subject: [PATCH 0028/2380] Attempt to split windows tests over multiple jobs (#5639) --- .github/workflows/ci.yml | 7 ++++--- tox.ini | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6a933eaeb4cb..c3967d1e9036 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -160,7 +160,8 @@ jobs: PYTHON: - {VERSION: "3.6", TOXENV: "py36", MSVC_VERSION: "2019", CL_FLAGS: ""} - {VERSION: "3.9", TOXENV: "py39", MSVC_VERSION: "2019", CL_FLAGS: "/D USE_OSRANDOM_RNG_FOR_TESTING"} - name: "${{ matrix.PYTHON.TOXENV }} on ${{ matrix.WINDOWS.WINDOWS }}" + JOB_NUMBER: [0, 1, 2, 3] + name: "${{ matrix.PYTHON.TOXENV }} on ${{ matrix.WINDOWS.WINDOWS }} (part ${{ matrix.JOB_NUMBER }})" timeout-minutes: 30 steps: - uses: actions/checkout@v2 @@ -182,13 +183,13 @@ jobs: shell: bash - run: git clone https://github.com/google/wycheproof - - run: tox -r -- --color=yes --wycheproof-root=wycheproof + - run: tox -r -- --color=yes --wycheproof-root=wycheproof --num-shards=4 --shard-id=${{ matrix.JOB_NUMBER }} env: TOXENV: ${{ matrix.PYTHON.TOXENV }} - uses: ./.github/actions/upload-coverage with: - name: "${{ matrix.PYTHON.TOXENV }} on ${{ matrix.WINDOWS.WINDOWS }}" + name: "${{ matrix.PYTHON.TOXENV }} on ${{ matrix.WINDOWS.WINDOWS }} (part ${{ matrix.JOB_NUMBER }})" linux-downstream: runs-on: ubuntu-latest diff --git a/tox.ini b/tox.ini index d945bef356bc..4c97763ec363 100644 --- a/tox.ini +++ b/tox.ini @@ -8,8 +8,8 @@ extras = test ssh: ssh deps = - # This must be kept in sync with .github/workflows/ci.yml ./vectors + pytest-shard>=0.1.2 randomorder: pytest-randomly passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH USERNAME PYTHONIOENCODING OPENSSL_FORCE_FIPS_MODE commands = From 3e53910e90aaaa7652ff8952c512132481b3de1e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 12 Dec 2020 13:45:20 -0500 Subject: [PATCH 0029/2380] Build manylinux2014 wheels (#5642) --- .github/workflows/wheel-builder.yml | 2 ++ .zuul.d/jobs.yaml | 4 ++++ CHANGELOG.rst | 2 ++ docs/doing-a-release.rst | 7 +++---- docs/installation.rst | 6 +++--- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 8a4a083bf8d4..3e46e6300fad 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -17,6 +17,8 @@ jobs: CONTAINER: "cryptography-manylinux1:x86_64" - NAME: manylinux2010_x86_64 CONTAINER: "cryptography-manylinux2010:x86_64" + - NAME: manylinux2014_x86_64 + CONTAINER: "cryptography-manylinux2014:x86_64" name: "${{ matrix.PYTHON }} for ${{ matrix.MANYLINUX.NAME }}" steps: - run: /opt/python/${{ matrix.PYTHON }}/bin/python -m virtualenv .venv diff --git a/.zuul.d/jobs.yaml b/.zuul.d/jobs.yaml index 12f5104caed9..5a66eece9b5b 100644 --- a/.zuul.d/jobs.yaml +++ b/.zuul.d/jobs.yaml @@ -55,3 +55,7 @@ image: ghcr.io/pyca/cryptography-manylinux2010:x86_64 pythons: - cp36-cp36m + - platform: manylinux2014_x86_64 + image: ghcr.io/pyca/cryptography-manylinux2014:x86_64 + pythons: + - cp36-cp36m diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7ff0f05d9cac..3272591a2e3e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,6 +7,8 @@ Changelog .. note:: This version is not yet released and is under active development. * **BACKWARDS INCOMPATIBLE:** Support for Python 2 has been removed. +* We now ship ``manylinux2014`` wheels in addition to our ``manylinux1`` and + ``manylinux2010`` wheels. .. _v3-3-1: diff --git a/docs/doing-a-release.rst b/docs/doing-a-release.rst index 043d52d28da6..5583ac4c2692 100644 --- a/docs/doing-a-release.rst +++ b/docs/doing-a-release.rst @@ -21,10 +21,9 @@ Verifying OpenSSL version ------------------------- The release process creates wheels bundling OpenSSL for Windows, macOS, and -Linux. Check that the Windows, macOS, and Linux builders (both -``pyca/cryptography-manylinux1`` and ``pyca/cryptography-manylinux2010``) have -the latest OpenSSL. If anything is out of date follow the instructions for -upgrading OpenSSL. +Linux. Check that the Windows, macOS, and Linux builders (the ``manylinux`` +containers) have the latest OpenSSL. If anything is out of date follow the +instructions for upgrading OpenSSL. Upgrading OpenSSL ----------------- diff --git a/docs/installation.rst b/docs/installation.rst index 9696f7d3915b..5d214793b625 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -70,9 +70,9 @@ Building cryptography on Linux ------------------------------ ``cryptography`` ships ``manylinux`` wheels (as of 2.0) so all dependencies -are included. For users on pip 8.1 or above running on a ``manylinux1`` or -``manylinux2010`` compatible distribution (almost everything except Alpine) -all you should need to do is: +are included. For users on pip 8.1 or above running on a ``manylinux1`` (or +greater) compatible distribution (almost everything except Alpine) all you +should need to do is: .. code-block:: console From 9b4a19ed0e9378f6c89150f25dc8eb0debef5e51 Mon Sep 17 00:00:00 2001 From: Eduard Iskandarov Date: Sun, 13 Dec 2020 21:43:30 +0500 Subject: [PATCH 0030/2380] add missing verification parameter flags (#5643) --- src/_cffi_src/openssl/x509_vfy.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/_cffi_src/openssl/x509_vfy.py b/src/_cffi_src/openssl/x509_vfy.py index dc4895f4ecbb..66cc0176115d 100644 --- a/src/_cffi_src/openssl/x509_vfy.py +++ b/src/_cffi_src/openssl/x509_vfy.py @@ -122,6 +122,8 @@ static const long X509_V_FLAG_SUITEB_192_LOS; static const long X509_V_FLAG_SUITEB_128_LOS; static const long X509_V_FLAG_PARTIAL_CHAIN; +static const long X509_V_FLAG_NO_ALT_CHAINS; +static const long X509_V_FLAG_NO_CHECK_TIME; static const long X509_LU_X509; static const long X509_LU_CRL; From 206300d1e4179d2e40b9d2be02eac98aa2ceb13f Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 13 Dec 2020 12:58:48 -0500 Subject: [PATCH 0031/2380] Clone wycheproof in a pre-run task (#5644) this lets zuul automatically retry it, which will help during network flakiness, I hope --- .zuul.d/jobs.yaml | 1 + .zuul.playbooks/playbooks/clone-wycheproof/main.yaml | 7 +++++++ .zuul.playbooks/playbooks/tox/main.yaml | 7 ------- 3 files changed, 8 insertions(+), 7 deletions(-) create mode 100644 .zuul.playbooks/playbooks/clone-wycheproof/main.yaml diff --git a/.zuul.d/jobs.yaml b/.zuul.d/jobs.yaml index 5a66eece9b5b..213bc5d8574e 100644 --- a/.zuul.d/jobs.yaml +++ b/.zuul.d/jobs.yaml @@ -2,6 +2,7 @@ name: pyca-cryptography-base abstract: true description: Run pyca/cryptography unit testing + pre-run: .zuul.playbooks/playbooks/clone-wycheproof/main.yaml run: .zuul.playbooks/playbooks/tox/main.yaml - job: diff --git a/.zuul.playbooks/playbooks/clone-wycheproof/main.yaml b/.zuul.playbooks/playbooks/clone-wycheproof/main.yaml new file mode 100644 index 000000000000..6f8ffb031c83 --- /dev/null +++ b/.zuul.playbooks/playbooks/clone-wycheproof/main.yaml @@ -0,0 +1,7 @@ +- hosts: all + tasks: + - name: Clone wycheproof + git: + repo: https://github.com/google/wycheproof + dest: "{{ ansible_facts.env['HOME'] }}/wycheproof" + depth: 1 diff --git a/.zuul.playbooks/playbooks/tox/main.yaml b/.zuul.playbooks/playbooks/tox/main.yaml index fc92398ffa62..9ad2a78d0515 100644 --- a/.zuul.playbooks/playbooks/tox/main.yaml +++ b/.zuul.playbooks/playbooks/tox/main.yaml @@ -27,15 +27,8 @@ become: yes when: ansible_distribution == 'CentOS' - - name: Clone wycheproof - git: - repo: https://github.com/google/wycheproof - dest: "{{ ansible_facts.env['HOME'] }}/wycheproof" - depth: 1 - - name: Run tox include_role: name: tox vars: tox_extra_args: "-- --wycheproof-root={{ ansible_facts.env['HOME'] }}/wycheproof/" - From a8bb7b03bfad00876ceea728a86cd6f54c50ca3e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 13 Dec 2020 14:59:34 -0500 Subject: [PATCH 0032/2380] Move docker image pulling for wheel buidler to pre-run (#5645) --- .zuul.d/jobs.yaml | 1 + .zuul.playbooks/playbooks/wheel/pre.yaml | 42 +++++++++++++++++++ .../build-wheel-manylinux/tasks/main.yaml | 36 ---------------- 3 files changed, 43 insertions(+), 36 deletions(-) create mode 100644 .zuul.playbooks/playbooks/wheel/pre.yaml diff --git a/.zuul.d/jobs.yaml b/.zuul.d/jobs.yaml index 213bc5d8574e..62f302ae8fd5 100644 --- a/.zuul.d/jobs.yaml +++ b/.zuul.d/jobs.yaml @@ -29,6 +29,7 @@ - job: name: pyca-cryptography-build-wheel abstract: true + pre-run: .zuul.playbooks/playbooks/wheel/pre.yaml run: .zuul.playbooks/playbooks/wheel/main.yaml - job: diff --git a/.zuul.playbooks/playbooks/wheel/pre.yaml b/.zuul.playbooks/playbooks/wheel/pre.yaml new file mode 100644 index 000000000000..fd428334653c --- /dev/null +++ b/.zuul.playbooks/playbooks/wheel/pre.yaml @@ -0,0 +1,42 @@ +- hosts: all + tasks: + - name: Sanity check build list + assert: + that: wheel_builds is defined + + - name: Run ensure-docker + include_role: + name: ensure-docker + + - name: Workaround Linaro aarch64 cloud MTU issues + # NOTE(ianw) : Docker default networking, the Linaro NAT setup and + # *insert random things here* cause PMTU issues, resulting in hung + # connections, particularly to fastly CDN (particularly annoying + # because pypi and pythonhosted live behind that). Can remove after + # upstream changes merge, or we otherwise find a solution in the + # upstream cloud. + # https://review.opendev.org/747062 + # https://review.opendev.org/746833 + # https://review.opendev.org/747064 + when: ansible_architecture == 'aarch64' + block: + - name: Install jq + package: + name: jq + state: present + become: yes + + - name: Reset docker MTU + shell: | + jq --arg mtu 1400 '. + {mtu: $mtu|tonumber}' /etc/docker/daemon.json > /etc/docker/daemon.json.new + cat /etc/docker/daemon.json.new + mv /etc/docker/daemon.json.new /etc/docker/daemon.json + service docker restart + become: yes + + - name: Pre-pull containers + command: >- + docker pull {{ item.image }} + become: yes + loop: '{{ wheel_builds }}' + diff --git a/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/tasks/main.yaml b/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/tasks/main.yaml index aebf7d6b7fbb..553edd899d32 100644 --- a/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/tasks/main.yaml +++ b/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/tasks/main.yaml @@ -11,36 +11,6 @@ include_role: name: ensure-pip -- name: Run ensure-docker - include_role: - name: ensure-docker - -- name: Workaround Linaro aarch64 cloud MTU issues - # NOTE(ianw) : Docker default networking, the Linaro NAT setup and - # *insert random things here* cause PMTU issues, resulting in hung - # connections, particularly to fastly CDN (particularly annoying - # because pypi and pythonhosted live behind that). Can remove after - # upstream changes merge, or we otherwise find a solution in the - # upstream cloud. - # https://review.opendev.org/747062 - # https://review.opendev.org/746833 - # https://review.opendev.org/747064 - when: ansible_architecture == 'aarch64' - block: - - name: Install jq - package: - name: jq - state: present - become: yes - - - name: Reset docker MTU - shell: | - jq --arg mtu 1400 '. + {mtu: $mtu|tonumber}' /etc/docker/daemon.json > /etc/docker/daemon.json.new - cat /etc/docker/daemon.json.new - mv /etc/docker/daemon.json.new /etc/docker/daemon.json - service docker restart - become: yes - # We build an sdist of the checkout, and then build wheels from the # sdist. This ensures that nothing is left out of the sdist. - name: Install sdist required packages @@ -95,12 +65,6 @@ dest: '{{ _build_dir }}' mode: 0755 -- name: Pre-pull containers - command: >- - docker pull {{ item.image }} - become: yes - loop: '{{ wheel_builds }}' - - name: Run builds command: | docker run --rm \ From 149796628ee81644a0ae7e9f049eb6c98aefec41 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 15 Dec 2020 09:42:34 -0500 Subject: [PATCH 0033/2380] put pytest configuration somewhere that goes in the sdist (#5648) fixes #5646 --- pyproject.toml | 9 +++++++++ setup.py | 2 +- tox.ini | 8 -------- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c829506945cf..7d3ad2325abe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,3 +12,12 @@ build-backend = "setuptools.build_meta" [tool.black] line-length = 79 target-version = ["py36"] + +[tool.pytest.ini_options] +addopts = "-r s" +markers = [ + "requires_backend_interface: this test requires a specific backend interface", + "skip_fips: this test is not executed in FIPS mode", + "supported: parametrized test requiring only_if and skip_message", + "wycheproof_tests: this test runs a wycheproof fixture", +] diff --git a/setup.py b/setup.py index 7ee1f29845b0..2eb27e2ce7f5 100644 --- a/setup.py +++ b/setup.py @@ -72,7 +72,7 @@ setup_requires=setup_requirements, extras_require={ "test": [ - "pytest>=4.4.0", + "pytest>=6.0", "pytest-cov", "pytest-subtests", "pytest-xdist", diff --git a/tox.ini b/tox.ini index 4c97763ec363..ecb16f2c75d4 100644 --- a/tox.ini +++ b/tox.ini @@ -67,11 +67,3 @@ application-import-names = cryptography,cryptography_vectors,tests [doc8] extensions = rst - -[pytest] -addopts = -r s -markers = - requires_backend_interface: this test requires a specific backend interface - skip_fips: this test is not executed in FIPS mode - supported: parametrized test requiring only_if and skip_message - wycheproof_tests: this test runs a wycheproof fixture From 41a7f43886565c551c767dc94e803d3fa929fc9e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 15 Dec 2020 10:37:25 -0500 Subject: [PATCH 0034/2380] Remove rtd requirements (#5649) --- MANIFEST.in | 2 +- rtd-requirements.txt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 rtd-requirements.txt diff --git a/MANIFEST.in b/MANIFEST.in index 5c82725a4148..47869c330cff 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -18,7 +18,7 @@ recursive-exclude vectors * recursive-exclude .github * -exclude release.py .coveragerc codecov.yml .readthedocs.yml dev-requirements.txt rtd-requirements.txt tox.ini +exclude release.py .coveragerc codecov.yml .readthedocs.yml dev-requirements.txt tox.ini recursive-exclude .zuul.d * recursive-exclude .zuul.playbooks * diff --git a/rtd-requirements.txt b/rtd-requirements.txt deleted file mode 100644 index 142b6ca357fe..000000000000 --- a/rtd-requirements.txt +++ /dev/null @@ -1 +0,0 @@ --e .[docs] From 971fe8bc09f35644622cb13d62504e96581d436e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 15 Dec 2020 12:33:14 -0500 Subject: [PATCH 0035/2380] Cleanup how we represent authors. (#5650) AUTHORS.rst had not been updated in more than 2 years, it was not a good reference. --- AUTHORS.rst | 44 ----------------------- MANIFEST.in | 1 - src/cryptography/__about__.py | 2 +- vectors/cryptography_vectors/__about__.py | 2 +- 4 files changed, 2 insertions(+), 47 deletions(-) delete mode 100644 AUTHORS.rst diff --git a/AUTHORS.rst b/AUTHORS.rst deleted file mode 100644 index 8ba7e0ed32e9..000000000000 --- a/AUTHORS.rst +++ /dev/null @@ -1,44 +0,0 @@ -AUTHORS -======= - -PGP key fingerprints are enclosed in parentheses. - -* Alex Gaynor (E27D 4AA0 1651 72CB C5D2 AF2B 125F 5C67 DFE9 4084) -* Hynek Schlawack (C2A0 4F86 ACE2 8ADC F817 DBB7 AE25 3622 7F69 F181) -* Donald Stufft -* Laurens Van Houtven <_@lvh.io> (D9DC 4315 772F 8E91 DD22 B153 DFD1 3DF7 A8DD 569B) -* Christian Heimes -* Paul Kehrer (05FD 9FA1 6CF7 5735 0D91 A560 235A E5F1 29F9 ED98) -* Jarret Raim -* Alex Stapleton (A1C7 E50B 66DE 39ED C847 9665 8E3C 20D1 9BD9 5C4C) -* David Reid (0F83 CC87 B32F 482B C726 B58A 9FBF D8F4 DA89 6D74) -* Matthew Lefkowitz (06AB F638 E878 CD29 1264 18AB 7EC2 8125 0FBC 4A07) -* Konstantinos Koukopoulos (D6BD 52B6 8C99 A91C E2C8 934D 3300 566B 3A46 726E) -* Stephen Holsapple -* Terry Chia -* Matthew Iversen (2F04 3DCC D6E6 D5AC D262 2E0B C046 E8A8 7452 2973) -* Mohammed Attia -* Michael Hart -* Mark Adams (A18A 7DD3 283C CF2A B0CE FE0E C7A0 5E3F C972 098C) -* Gregory Haynes (6FB6 44BF 9FD0 EBA2 1CE9 471F B08F 42F9 0DC6 599F) -* Chelsea Winfree -* Steven Buss (1FB9 2EC1 CF93 DFD6 B47F F583 B1A5 6C22 290D A4C3) -* Andre Caron -* Jiangge Zhang (BBEC 782B 015F 71B1 5FF7 EACA 1A8C AA98 255F 5000) -* Major Hayden (1BF9 9264 9596 0033 698C 252B 7370 51E0 C101 1FB1) -* Phoebe Queen (10D4 7741 AB65 50F4 B264 3888 DA40 201A 072B C1FA) -* Google Inc. -* Amaury Forgeot d'Arc -* Dirkjan Ochtman (25BB BAC1 13C1 BFD5 AA59 4A4C 9F96 B929 3038 0381) -* Maximilian Hils -* Simo Sorce -* Thomas Sileo -* Fraser Tweedale -* Ofek Lev (FFB6 B92B 30B1 7848 546E 9912 972F E913 DAD5 A46E) -* Erik Daguerre -* Aviv Palivoda -* Chris Wolfe -* Jeremy Lainé -* Denis Gladkikh -* John Pacific (2CF6 0381 B5EF 29B7 D48C 2020 7BB9 71A0 E891 44D9) -* Marti Raudsepp diff --git a/MANIFEST.in b/MANIFEST.in index 47869c330cff..a4f06cb4b90b 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,3 @@ -include AUTHORS.rst include CHANGELOG.rst include CONTRIBUTING.rst include LICENSE diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py index 7094f7992a2d..dcfcae59cd5d 100644 --- a/src/cryptography/__about__.py +++ b/src/cryptography/__about__.py @@ -23,7 +23,7 @@ __version__ = "3.4.dev1" -__author__ = "The cryptography developers" +__author__ = "The Python Cryptographic Authority and individual contributors" __email__ = "cryptography-dev@python.org" __license__ = "BSD or Apache License, Version 2.0" diff --git a/vectors/cryptography_vectors/__about__.py b/vectors/cryptography_vectors/__about__.py index 55e68f44ee40..a30fbf58fefc 100644 --- a/vectors/cryptography_vectors/__about__.py +++ b/vectors/cryptography_vectors/__about__.py @@ -20,7 +20,7 @@ __version__ = "3.4.dev1" -__author__ = "The cryptography developers" +__author__ = "The Python Cryptographic Authority and individual contributors" __email__ = "cryptography-dev@python.org" __license__ = "BSD or Apache License, Version 2.0" From c4c421ecb23e67d6ba47c3b35dcbdd02a3b9152e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 17 Dec 2020 19:37:21 -0500 Subject: [PATCH 0036/2380] Pin setup-python to fix CI (#5653) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c3967d1e9036..ba4bd4140a89 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Setup python - uses: actions/setup-python@v2 + uses: actions/setup-python@v2.1.4 with: python-version: ${{ matrix.PYTHON.VERSION }} - run: git clone --depth=1 https://github.com/google/wycheproof From 0e9ee795db8d01df69e595e2985884fc1d689784 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 17 Dec 2020 20:06:11 -0500 Subject: [PATCH 0037/2380] Remove last large usage of parametrize with vectors (#5652) --- tests/hazmat/primitives/test_rsa.py | 177 +++++++++---------- tests/hazmat/primitives/test_x963_vectors.py | 41 +++-- 2 files changed, 106 insertions(+), 112 deletions(-) diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index d10eb93f4063..82ba2bf09199 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -397,34 +397,32 @@ class TestRSASignature(object): ), skip_message="Does not support PKCS1v1.5.", ) - @pytest.mark.parametrize( - "pkcs1_example", - _flatten_pkcs1_examples( + def test_pkcs1v15_signing(self, backend, subtests): + vectors = _flatten_pkcs1_examples( load_vectors_from_file( os.path.join("asymmetric", "RSA", "pkcs1v15sign-vectors.txt"), load_pkcs1_vectors, ) - ), - ) - def test_pkcs1v15_signing(self, pkcs1_example, backend): - private, public, example = pkcs1_example - private_key = rsa.RSAPrivateNumbers( - p=private["p"], - q=private["q"], - d=private["private_exponent"], - dmp1=private["dmp1"], - dmq1=private["dmq1"], - iqmp=private["iqmp"], - public_numbers=rsa.RSAPublicNumbers( - e=private["public_exponent"], n=private["modulus"] - ), - ).private_key(backend) - signature = private_key.sign( - binascii.unhexlify(example["message"]), - padding.PKCS1v15(), - hashes.SHA1(), ) - assert binascii.hexlify(signature) == example["signature"] + for private, public, example in vectors: + with subtests.test(): + private_key = rsa.RSAPrivateNumbers( + p=private["p"], + q=private["q"], + d=private["private_exponent"], + dmp1=private["dmp1"], + dmq1=private["dmq1"], + iqmp=private["iqmp"], + public_numbers=rsa.RSAPublicNumbers( + e=private["public_exponent"], n=private["modulus"] + ), + ).private_key(backend) + signature = private_key.sign( + binascii.unhexlify(example["message"]), + padding.PKCS1v15(), + hashes.SHA1(), + ) + assert binascii.hexlify(signature) == example["signature"] @pytest.mark.supported( only_if=lambda backend: backend.rsa_padding_supported( @@ -756,41 +754,40 @@ class TestRSAVerification(object): ), skip_message="Does not support PKCS1v1.5.", ) - @pytest.mark.parametrize( - "pkcs1_example", - _flatten_pkcs1_examples( + def test_pkcs1v15_verification(self, backend, subtests): + vectors = _flatten_pkcs1_examples( load_vectors_from_file( os.path.join("asymmetric", "RSA", "pkcs1v15sign-vectors.txt"), load_pkcs1_vectors, ) - ), - ) - def test_pkcs1v15_verification(self, pkcs1_example, backend): - private, public, example = pkcs1_example - public_key = rsa.RSAPublicNumbers( - e=public["public_exponent"], n=public["modulus"] - ).public_key(backend) - signature = binascii.unhexlify(example["signature"]) - message = binascii.unhexlify(example["message"]) - public_key.verify( - signature, message, padding.PKCS1v15(), hashes.SHA1() ) + for private, public, example in vectors: + with subtests.test(): + public_key = rsa.RSAPublicNumbers( + e=public["public_exponent"], n=public["modulus"] + ).public_key(backend) + signature = binascii.unhexlify(example["signature"]) + message = binascii.unhexlify(example["message"]) + public_key.verify( + signature, message, padding.PKCS1v15(), hashes.SHA1() + ) - # Test digest recovery by providing hash - digest = hashes.Hash(hashes.SHA1()) - digest.update(message) - msg_digest = digest.finalize() - rec_msg_digest = public_key.recover_data_from_signature( - signature, padding.PKCS1v15(), hashes.SHA1() - ) - assert msg_digest == rec_msg_digest + # Test digest recovery by providing hash + digest = hashes.Hash(hashes.SHA1()) + digest.update(message) + msg_digest = digest.finalize() + rec_msg_digest = public_key.recover_data_from_signature( + signature, padding.PKCS1v15(), hashes.SHA1() + ) + assert msg_digest == rec_msg_digest - # Test recovery of all data (full DigestInfo) with hash alg. as None - rec_sig_data = public_key.recover_data_from_signature( - signature, padding.PKCS1v15(), None - ) - assert len(rec_sig_data) > len(msg_digest) - assert msg_digest == rec_sig_data[-len(msg_digest) :] + # Test recovery of all data (full DigestInfo) with hash alg. as + # None + rec_sig_data = public_key.recover_data_from_signature( + signature, padding.PKCS1v15(), None + ) + assert len(rec_sig_data) > len(msg_digest) + assert msg_digest == rec_sig_data[-len(msg_digest) :] @pytest.mark.supported( only_if=lambda backend: backend.rsa_padding_supported( @@ -1498,32 +1495,30 @@ class TestRSADecryption(object): ), skip_message="Does not support PKCS1v1.5.", ) - @pytest.mark.parametrize( - "vector", - _flatten_pkcs1_examples( + def test_decrypt_pkcs1v15_vectors(self, backend, subtests): + vectors = _flatten_pkcs1_examples( load_vectors_from_file( os.path.join("asymmetric", "RSA", "pkcs1v15crypt-vectors.txt"), load_pkcs1_vectors, ) - ), - ) - def test_decrypt_pkcs1v15_vectors(self, vector, backend): - private, public, example = vector - skey = rsa.RSAPrivateNumbers( - p=private["p"], - q=private["q"], - d=private["private_exponent"], - dmp1=private["dmp1"], - dmq1=private["dmq1"], - iqmp=private["iqmp"], - public_numbers=rsa.RSAPublicNumbers( - e=private["public_exponent"], n=private["modulus"] - ), - ).private_key(backend) - ciphertext = binascii.unhexlify(example["encryption"]) - assert len(ciphertext) == (skey.key_size + 7) // 8 - message = skey.decrypt(ciphertext, padding.PKCS1v15()) - assert message == binascii.unhexlify(example["message"]) + ) + for private, public, example in vectors: + with subtests.test(): + skey = rsa.RSAPrivateNumbers( + p=private["p"], + q=private["q"], + d=private["private_exponent"], + dmp1=private["dmp1"], + dmq1=private["dmq1"], + iqmp=private["iqmp"], + public_numbers=rsa.RSAPublicNumbers( + e=private["public_exponent"], n=private["modulus"] + ), + ).private_key(backend) + ciphertext = binascii.unhexlify(example["encryption"]) + assert len(ciphertext) == (skey.key_size + 7) // 8 + message = skey.decrypt(ciphertext, padding.PKCS1v15()) + assert message == binascii.unhexlify(example["message"]) def test_unsupported_padding(self, backend): private_key = RSA_KEY_512.private_key(backend) @@ -2112,28 +2107,28 @@ def test_private_numbers_hash(self): class TestRSAPrimeFactorRecovery(object): - @pytest.mark.parametrize( - "vector", - _flatten_pkcs1_examples( + def test_recover_prime_factors(self, subtests): + vectors = _flatten_pkcs1_examples( load_vectors_from_file( os.path.join("asymmetric", "RSA", "pkcs1v15crypt-vectors.txt"), load_pkcs1_vectors, ) - ), - ) - def test_recover_prime_factors(self, vector): - private, public, example = vector - p, q = rsa.rsa_recover_prime_factors( - private["modulus"], - private["public_exponent"], - private["private_exponent"], - ) - # Unfortunately there is no convention on which prime should be p - # and which one q. The function we use always makes p > q, but the - # NIST vectors are not so consistent. Accordingly, we verify we've - # recovered the proper (p, q) by sorting them and asserting on that. - assert sorted([p, q]) == sorted([private["p"], private["q"]]) - assert p > q + ) + for vector in vectors: + with subtests.test(): + private, public, example = vector + p, q = rsa.rsa_recover_prime_factors( + private["modulus"], + private["public_exponent"], + private["private_exponent"], + ) + # Unfortunately there is no convention on which prime should be + # p and which one q. The function we use always makes p > q, + # but the NIST vectors are not so consistent. Accordingly, we + # verify we've recovered the proper (p, q) by sorting them and + # asserting on that. + assert sorted([p, q]) == sorted([private["p"], private["q"]]) + assert p > q def test_invalid_recover_prime_factors(self): with pytest.raises(ValueError): diff --git a/tests/hazmat/primitives/test_x963_vectors.py b/tests/hazmat/primitives/test_x963_vectors.py index 846093b6b1f0..b374b6e7a5a0 100644 --- a/tests/hazmat/primitives/test_x963_vectors.py +++ b/tests/hazmat/primitives/test_x963_vectors.py @@ -35,30 +35,29 @@ class TestX963(object): "SHA-512": hashes.SHA512, } - @pytest.mark.parametrize( - ("vector"), - load_vectors_from_file( + def test_x963(self, backend, subtests): + vectors = load_vectors_from_file( os.path.join("KDF", "ansx963_2001.txt"), load_x963_vectors - ), - ) - def test_x963(self, backend, vector): - hashfn = self._algorithms_dict[vector["hash"]] - _skip_hashfn_unsupported(backend, hashfn()) + ) + for vector in vectors: + with subtests.test(): + hashfn = self._algorithms_dict[vector["hash"]] + _skip_hashfn_unsupported(backend, hashfn()) - key = binascii.unhexlify(vector["Z"]) - sharedinfo = None - if vector["sharedinfo_length"] != 0: - sharedinfo = binascii.unhexlify(vector["sharedinfo"]) - key_data_len = vector["key_data_length"] // 8 - key_data = binascii.unhexlify(vector["key_data"]) + key = binascii.unhexlify(vector["Z"]) + sharedinfo = None + if vector["sharedinfo_length"] != 0: + sharedinfo = binascii.unhexlify(vector["sharedinfo"]) + key_data_len = vector["key_data_length"] // 8 + key_data = binascii.unhexlify(vector["key_data"]) - xkdf = X963KDF( - algorithm=hashfn(), - length=key_data_len, - sharedinfo=sharedinfo, - backend=backend, - ) - xkdf.verify(key, key_data) + xkdf = X963KDF( + algorithm=hashfn(), + length=key_data_len, + sharedinfo=sharedinfo, + backend=backend, + ) + xkdf.verify(key, key_data) def test_unsupported_hash(self, backend): with pytest.raises(pytest.skip.Exception): From 7b3e266c2f53a6e928dfd2ada9af3df1f67e489c Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 19 Dec 2020 13:42:37 -0500 Subject: [PATCH 0038/2380] Move more stuff to pre-run for resillience (#5658) --- .zuul.d/jobs.yaml | 2 +- .../playbooks/clone-wycheproof/main.yaml | 7 ---- .zuul.playbooks/playbooks/tox/main.yaml | 27 --------------- .zuul.playbooks/playbooks/tox/pre.yaml | 34 +++++++++++++++++++ 4 files changed, 35 insertions(+), 35 deletions(-) delete mode 100644 .zuul.playbooks/playbooks/clone-wycheproof/main.yaml create mode 100644 .zuul.playbooks/playbooks/tox/pre.yaml diff --git a/.zuul.d/jobs.yaml b/.zuul.d/jobs.yaml index 62f302ae8fd5..9d1b2b9f5b62 100644 --- a/.zuul.d/jobs.yaml +++ b/.zuul.d/jobs.yaml @@ -2,7 +2,7 @@ name: pyca-cryptography-base abstract: true description: Run pyca/cryptography unit testing - pre-run: .zuul.playbooks/playbooks/clone-wycheproof/main.yaml + pre-run: .zuul.playbooks/playbooks/tox/pre.yaml run: .zuul.playbooks/playbooks/tox/main.yaml - job: diff --git a/.zuul.playbooks/playbooks/clone-wycheproof/main.yaml b/.zuul.playbooks/playbooks/clone-wycheproof/main.yaml deleted file mode 100644 index 6f8ffb031c83..000000000000 --- a/.zuul.playbooks/playbooks/clone-wycheproof/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ -- hosts: all - tasks: - - name: Clone wycheproof - git: - repo: https://github.com/google/wycheproof - dest: "{{ ansible_facts.env['HOME'] }}/wycheproof" - depth: 1 diff --git a/.zuul.playbooks/playbooks/tox/main.yaml b/.zuul.playbooks/playbooks/tox/main.yaml index 9ad2a78d0515..6243215bc24e 100644 --- a/.zuul.playbooks/playbooks/tox/main.yaml +++ b/.zuul.playbooks/playbooks/tox/main.yaml @@ -1,32 +1,5 @@ - hosts: all tasks: - - - name: Install tox - include_role: - name: ensure-tox - - - name: Install required packages - package: - name: - - build-essential - - libssl-dev - - libffi-dev - - python3-dev - become: yes - when: ansible_distribution in ['Debian', 'Ubuntu'] - - - name: Install required packages - package: - name: - - redhat-rpm-config - - gcc - - libffi-devel - - openssl-devel - - python3-devel - - python2-devel - become: yes - when: ansible_distribution == 'CentOS' - - name: Run tox include_role: name: tox diff --git a/.zuul.playbooks/playbooks/tox/pre.yaml b/.zuul.playbooks/playbooks/tox/pre.yaml new file mode 100644 index 000000000000..b656f327cbf0 --- /dev/null +++ b/.zuul.playbooks/playbooks/tox/pre.yaml @@ -0,0 +1,34 @@ +- hosts: all + tasks: + - name: Clone wycheproof + git: + repo: https://github.com/google/wycheproof + dest: "{{ ansible_facts.env['HOME'] }}/wycheproof" + depth: 1 + + - name: Install tox + include_role: + name: ensure-tox + + - name: Install required packages + package: + name: + - build-essential + - libssl-dev + - libffi-dev + - python3-dev + become: yes + when: ansible_distribution in ['Debian', 'Ubuntu'] + + - name: Install required packages + package: + name: + - redhat-rpm-config + - gcc + - libffi-devel + - openssl-devel + - python3-devel + - python2-devel + become: yes + when: ansible_distribution == 'CentOS' + From e853b4555c393c0e3acfb8420208e106a1a069de Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 19 Dec 2020 17:30:16 -0500 Subject: [PATCH 0039/2380] Attempt to remove the special case for no coverage on pypy3 (#5657) --- .github/workflows/ci.yml | 2 +- tox.ini | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba4bd4140a89..c88de8fe3083 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: matrix: PYTHON: - {VERSION: "3.9", TOXENV: "pep8,packaging,docs", COVERAGE: "false"} - - {VERSION: "pypy3", TOXENV: "pypy3-nocoverage", COVERAGE: "false"} + - {VERSION: "pypy3", TOXENV: "pypy3"} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1i"}} - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1i"}} diff --git a/tox.ini b/tox.ini index ecb16f2c75d4..8a34499cfd81 100644 --- a/tox.ini +++ b/tox.ini @@ -16,14 +16,6 @@ commands = pip list pytest -n auto --cov=cryptography --cov=tests --capture=no --strict --durations=10 {posargs} -# This target disables coverage on pypy because of performance problems with -# coverage.py on pypy. -[testenv:pypy3-nocoverage] -basepython = pypy3 -commands = - pip list - pytest -n auto --capture=no --strict --durations=10 {posargs} - [testenv:docs] extras = docs From b3d82f67ebab7a2f6d5042dbaf41028ef506dd41 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Dec 2020 08:51:06 -0500 Subject: [PATCH 0040/2380] Update actions/setup-python requirement to v2.2.1 (#5661) Updates the requirements on [actions/setup-python](https://github.com/actions/setup-python) to permit the latest version. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/commits/3105fb18c05ddd93efea5f9e0bef7a03a6e9e7df) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 10 +++++----- .github/workflows/wheel-builder.yml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c88de8fe3083..da7f0b3de67a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Setup python - uses: actions/setup-python@v2.1.4 + uses: actions/setup-python@v2.2.1 with: python-version: ${{ matrix.PYTHON.VERSION }} - run: git clone --depth=1 https://github.com/google/wycheproof @@ -123,7 +123,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Setup python - uses: actions/setup-python@v2 + uses: actions/setup-python@v2.2.1 with: python-version: ${{ matrix.PYTHON.VERSION }} @@ -166,7 +166,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Setup python - uses: actions/setup-python@v2 + uses: actions/setup-python@v2.2.1 with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} @@ -208,7 +208,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Setup python - uses: actions/setup-python@v2 + uses: actions/setup-python@v2.2.1 with: python-version: 3.7 - run: python -m pip install -U pip wheel @@ -225,7 +225,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Setup python - uses: actions/setup-python@v2 + uses: actions/setup-python@v2.2.1 with: python-version: 3.9 - run: python -m pip install -U tox diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 3e46e6300fad..d8243e502316 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -112,7 +112,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Setup python - uses: actions/setup-python@v2 + uses: actions/setup-python@v2.2.1 with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} From 9108bb0a69ea850b9943c2b27623cfe50c15d068 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Mon, 21 Dec 2020 15:38:01 +0100 Subject: [PATCH 0041/2380] Add ssl version constants (#5662) * add ssl version constants * try to fix ci * try harder to fix ci * security: if unavailable, set protocol constants to nonexistent version * make linter happy * remove dtls constants * remove superfluous comment --- src/_cffi_src/openssl/ssl.py | 7 +++++++ src/cryptography/hazmat/bindings/openssl/_conditional.py | 1 + 2 files changed, 8 insertions(+) diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index 1977d4c16e7a..11a7d63a961a 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -131,6 +131,12 @@ static const long TLS_ST_BEFORE; static const long TLS_ST_OK; +static const long SSL3_VERSION; +static const long TLS1_VERSION; +static const long TLS1_1_VERSION; +static const long TLS1_2_VERSION; +static const long TLS1_3_VERSION; + typedef ... SSL_METHOD; typedef ... SSL_CTX; @@ -677,6 +683,7 @@ #if CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 static const long Cryptography_HAS_TLSv1_3 = 0; +static const long TLS1_3_VERSION = 0; static const long SSL_OP_NO_TLSv1_3 = 0; static const long SSL_VERIFY_POST_HANDSHAKE = 0; int (*SSL_CTX_set_ciphersuites)(SSL_CTX *, const char *) = NULL; diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index 6105093c626b..8654835796b6 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -198,6 +198,7 @@ def cryptography_has_openssl_cleanup(): def cryptography_has_tlsv13(): return [ + "TLS1_3_VERSION", "SSL_OP_NO_TLSv1_3", "SSL_VERIFY_POST_HANDSHAKE", "SSL_CTX_set_ciphersuites", From c84d6ee0605645a24fd93c436967ee2519aa586a Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 22 Dec 2020 14:33:47 -0500 Subject: [PATCH 0042/2380] Integrate Rust into the build process properly (#5410) --- .github/dependabot.yml | 7 + .github/workflows/ci.yml | 86 ++++++- .github/workflows/wheel-builder.yml | 26 +- .gitignore | 1 + .zuul.d/jobs.yaml | 4 - .zuul.playbooks/playbooks/tox/pre.yaml | 4 + .../files/build-wheels.sh | 2 +- .../build-wheel-manylinux/tasks/main.yaml | 9 + CHANGELOG.rst | 9 +- MANIFEST.in | 1 + docs/conf.py | 3 + docs/faq.rst | 13 + docs/installation.rst | 19 +- docs/spelling_wordlist.txt | 1 + pyproject.toml | 1 + setup.py | 24 +- src/rust/Cargo.lock | 241 ++++++++++++++++++ src/rust/Cargo.toml | 16 ++ src/rust/src/lib.rs | 8 + tox.ini | 11 +- 20 files changed, 465 insertions(+), 21 deletions(-) create mode 100644 src/rust/Cargo.lock create mode 100644 src/rust/Cargo.toml create mode 100644 src/rust/src/lib.rs diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 123014908beb..d4a20bc61049 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,3 +4,10 @@ updates: directory: "/" schedule: interval: "daily" + - package-ecosystem: cargo + directory: "/src/rust/" + schedule: + interval: daily + allow: + # Also update indirect dependencies + - dependency-type: all diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index da7f0b3de67a..5e8f7a24a353 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: PYTHON: - - {VERSION: "3.9", TOXENV: "pep8,packaging,docs", COVERAGE: "false"} + - {VERSION: "3.9", TOXENV: "pep8,rust,packaging,docs", COVERAGE: "false"} - {VERSION: "pypy3", TOXENV: "pypy3"} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1i"}} @@ -26,6 +26,8 @@ jobs: - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.1.5"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.2.3"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.3.1"}} + RUST: + - stable name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 30 steps: @@ -34,6 +36,12 @@ jobs: uses: actions/setup-python@v2.2.1 with: python-version: ${{ matrix.PYTHON.VERSION }} + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.RUST }} + override: true + default: true - run: git clone --depth=1 https://github.com/google/wycheproof - run: python -m pip install tox requests coverage - name: Compute config hash and set config vars @@ -107,10 +115,47 @@ jobs: - run: 'tox -- --wycheproof-root="$HOME/wycheproof"' env: TOXENV: ${{ matrix.IMAGE.TOXENV }} + RUSTUP_HOME: /root/.rustup - uses: ./.github/actions/upload-coverage with: name: "${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" + linux-rust: + runs-on: ubuntu-latest + strategy: + matrix: + PYTHON: + - {VERSION: "3.9", TOXENV: "py39"} + RUST: + # Cover MSRV and in-dev versions + - 1.45.0 + - beta + - nightly + name: "${{ matrix.PYTHON.TOXENV }} with Rust ${{ matrix.RUST }}" + timeout-minutes: 30 + steps: + - uses: actions/checkout@v2 + - name: Setup python + uses: actions/setup-python@v2.2.1 + with: + python-version: ${{ matrix.PYTHON.VERSION }} + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.RUST }} + override: true + default: true + - run: git clone --depth=1 https://github.com/google/wycheproof + - run: python -m pip install tox coverage + - name: Tests + run: | + tox -r -- --color=yes --wycheproof-root=wycheproof + env: + TOXENV: ${{ matrix.PYTHON.TOXENV }} + - uses: ./.github/actions/upload-coverage + with: + name: "${{ matrix.PYTHON.TOXENV }} with Rust ${{ matrix.RUST }}" + macos: runs-on: macos-latest strategy: @@ -118,6 +163,8 @@ jobs: PYTHON: - {VERSION: "3.6", TOXENV: "py36", EXTRA_CFLAGS: ""} - {VERSION: "3.9", TOXENV: "py39", EXTRA_CFLAGS: "-DUSE_OSRANDOM_RNG_FOR_TESTING"} + RUST: + - stable name: "${{ matrix.PYTHON.TOXENV }} on macOS" timeout-minutes: 30 steps: @@ -126,6 +173,12 @@ jobs: uses: actions/setup-python@v2.2.1 with: python-version: ${{ matrix.PYTHON.VERSION }} + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.RUST }} + override: true + default: true - run: python -m pip install tox requests coverage @@ -155,11 +208,13 @@ jobs: strategy: matrix: WINDOWS: - - {ARCH: 'x86', WINDOWS: 'win32'} - - {ARCH: 'x64', WINDOWS: 'win64'} + - {ARCH: 'x86', WINDOWS: 'win32', RUST_TRIPLE: 'i686-pc-windows-msvc'} + - {ARCH: 'x64', WINDOWS: 'win64', RUST_TRIPLE: 'x86_64-pc-windows-msvc'} PYTHON: - {VERSION: "3.6", TOXENV: "py36", MSVC_VERSION: "2019", CL_FLAGS: ""} - {VERSION: "3.9", TOXENV: "py39", MSVC_VERSION: "2019", CL_FLAGS: "/D USE_OSRANDOM_RNG_FOR_TESTING"} + RUST: + - stable JOB_NUMBER: [0, 1, 2, 3] name: "${{ matrix.PYTHON.TOXENV }} on ${{ matrix.WINDOWS.WINDOWS }} (part ${{ matrix.JOB_NUMBER }})" timeout-minutes: 30 @@ -170,6 +225,13 @@ jobs: with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.RUST }} + override: true + default: true + target: ${{ matrix.WINDOWS.RUST_TRIPLE }} - run: python -m pip install tox requests coverage - name: Download OpenSSL @@ -203,6 +265,10 @@ jobs: - dynamodb-encryption-sdk - certbot - certbot-josepy + RUST: + - stable + PYTHON: + - 3.7 name: "Downstream tests for ${{ matrix.DOWNSTREAM }}" timeout-minutes: 30 steps: @@ -210,7 +276,13 @@ jobs: - name: Setup python uses: actions/setup-python@v2.2.1 with: - python-version: 3.7 + python-version: ${{ matrix.PYTHON }} + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.RUST }} + override: true + default: true - run: python -m pip install -U pip wheel - run: ./.github/downstream.d/${{ matrix.DOWNSTREAM }}.sh install - run: pip uninstall -y enum34 @@ -228,6 +300,12 @@ jobs: uses: actions/setup-python@v2.2.1 with: python-version: 3.9 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + default: true - run: python -m pip install -U tox - run: tox -r -- --color=yes env: diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index d8243e502316..c9de0b65b368 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -13,8 +13,6 @@ jobs: matrix: PYTHON: ["cp36-cp36m"] MANYLINUX: - - NAME: manylinux1_x86_64 - CONTAINER: "cryptography-manylinux1:x86_64" - NAME: manylinux2010_x86_64 CONTAINER: "cryptography-manylinux2010:x86_64" - NAME: manylinux2014_x86_64 @@ -23,7 +21,7 @@ jobs: steps: - run: /opt/python/${{ matrix.PYTHON }}/bin/python -m virtualenv .venv - name: Install Python dependencies - run: .venv/bin/pip install -U pip wheel cffi six ipaddress "enum34; python_version < '3'" + run: .venv/bin/pip install -U pip wheel cffi six ipaddress "enum34; python_version < '3' setuptools-rust" - run: .venv/bin/pip download cryptography==${{ github.event.inputs.version }} --no-deps --no-binary cryptography && tar zxvf cryptography*.tar.gz && mkdir tmpwheelhouse - run: | REGEX="cp3([0-9])*" @@ -77,9 +75,15 @@ jobs: ${{ matrix.PYTHON.BIN_PATH }} .github/workflows/download_openssl.py macos openssl-macos-x86-64 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + default: true - run: ${{ matrix.PYTHON.BIN_PATH }} -m virtualenv venv - - run: venv/bin/pip install -U pip wheel cffi six ipaddress "enum34; python_version < '3'" + - run: venv/bin/pip install -U pip wheel cffi six ipaddress "enum34; python_version < '3' setuptools-rust" - run: venv/bin/pip download cryptography==${{ github.event.inputs.version }} --no-deps --no-binary cryptography && tar zxvf cryptography*.tar.gz && mkdir wheelhouse - name: Build the wheel run: | @@ -104,8 +108,8 @@ jobs: strategy: matrix: WINDOWS: - - {ARCH: 'x86', WINDOWS: 'win32'} - - {ARCH: 'x64', WINDOWS: 'win64'} + - {ARCH: 'x86', WINDOWS: 'win32', RUST_TRIPLE: 'i686-pc-windows-msvc'} + - {ARCH: 'x64', WINDOWS: 'win64', RUST_TRIPLE: 'x86_64-pc-windows-msvc'} PYTHON: - {VERSION: "3.8", MSVC_VERSION: "2019", "ABI_VERSION": "cp36"} name: "${{ matrix.PYTHON.VERSION }} ${{ matrix.WINDOWS.WINDOWS }} ${{ matrix.PYTHON.ABI_VERSION }}" @@ -116,6 +120,14 @@ jobs: with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + default: true + target: ${{ matrix.WINDOWS.RUST_TRIPLE }} + - run: pip install requests - name: Download OpenSSL run: | @@ -126,7 +138,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} shell: bash - - run: python -m pip install -U pip wheel cffi six ipaddress "enum34; python_version < '3'" + - run: python -m pip install -U pip wheel cffi six ipaddress "enum34; python_version < '3' setuptools-rust" - run: pip download cryptography==${{ github.event.inputs.version }} --no-deps --no-binary cryptography && tar zxvf cryptography*.tar.gz && mkdir wheelhouse shell: bash - run: cd cryptography* && python setup.py bdist_wheel --py-limited-api=${{ matrix.PYTHON.ABI_VERSION }} && mv dist/cryptography*.whl ../wheelhouse diff --git a/.gitignore b/.gitignore index cdc4b6ad762e..7a00ba471236 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ htmlcov/ .eggs/ *.py[cdo] .hypothesis/ +target/ diff --git a/.zuul.d/jobs.yaml b/.zuul.d/jobs.yaml index 9d1b2b9f5b62..0a0982bab4bd 100644 --- a/.zuul.d/jobs.yaml +++ b/.zuul.d/jobs.yaml @@ -49,10 +49,6 @@ nodeset: ubuntu-bionic vars: wheel_builds: - - platform: manylinux1_x86_64 - image: ghcr.io/pyca/cryptography-manylinux1:x86_64 - pythons: - - cp36-cp36m - platform: manylinux2010_x86_64 image: ghcr.io/pyca/cryptography-manylinux2010:x86_64 pythons: diff --git a/.zuul.playbooks/playbooks/tox/pre.yaml b/.zuul.playbooks/playbooks/tox/pre.yaml index b656f327cbf0..33d3487a22bd 100644 --- a/.zuul.playbooks/playbooks/tox/pre.yaml +++ b/.zuul.playbooks/playbooks/tox/pre.yaml @@ -32,3 +32,7 @@ become: yes when: ansible_distribution == 'CentOS' + - name: Install rust + include_role: + name: ensure-rust + diff --git a/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/files/build-wheels.sh b/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/files/build-wheels.sh index 65a8201823ca..b701c21fa532 100644 --- a/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/files/build-wheels.sh +++ b/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/files/build-wheels.sh @@ -11,7 +11,7 @@ for P in ${PYTHONS}; do "${PYBIN}"/python -m virtualenv .venv - .venv/bin/pip install cffi six ipaddress "enum34; python_version < '3'" + .venv/bin/pip install cffi six ipaddress "enum34; python_version < '3'" setuptools-rust REGEX="cp3([0-9])*" if [[ "${PYBIN}" =~ $REGEX ]]; then diff --git a/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/tasks/main.yaml b/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/tasks/main.yaml index 553edd899d32..dbd2328713b1 100644 --- a/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/tasks/main.yaml +++ b/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/tasks/main.yaml @@ -23,6 +23,15 @@ become: yes when: ansible_distribution in ['Debian', 'Ubuntu'] +- name: Install rust + include_role: + name: ensure-rust + +- name: Install setuptools-rust + pip: + name: setuptools-rust + become: yes + - name: Create sdist command: | python3 setup.py sdist diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3272591a2e3e..2db299378ac0 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,14 +1,19 @@ Changelog ========= +.. _v3-4: + 3.4 - `master`_ ~~~~~~~~~~~~~~~ .. note:: This version is not yet released and is under active development. * **BACKWARDS INCOMPATIBLE:** Support for Python 2 has been removed. -* We now ship ``manylinux2014`` wheels in addition to our ``manylinux1`` and - ``manylinux2010`` wheels. +* We now ship ``manylinux2014`` wheels, and no longer ship ``manylinux1`` + wheels. +* ``cryptography`` now incorporates Rust code. Users building ``cryptography`` + themselves will need to have the Rust toolchain installed, users who use an + officially produced wheel will not need to make any changes. .. _v3-3-1: diff --git a/MANIFEST.in b/MANIFEST.in index a4f06cb4b90b..d564df4961ba 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -10,6 +10,7 @@ include pyproject.toml recursive-include docs * recursive-include src/_cffi_src *.py *.c *.h +recursive-include src/rust Cargo.toml Cargo.lock *.rs prune docs/_build recursive-include tests *.py exclude vectors diff --git a/docs/conf.py b/docs/conf.py index 2a307573563b..90f49463d1b3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -44,6 +44,7 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ "sphinx.ext.autodoc", + "sphinx.ext.autosectionlabel", "sphinx.ext.doctest", "sphinx.ext.intersphinx", "sphinx.ext.viewcode", @@ -198,3 +199,5 @@ # Inconsistent small DH params they seem incapable of fixing r"https://www.secg.org/sec1-v2.pdf", ] + +autosectionlabel_prefix_document = True diff --git a/docs/faq.rst b/docs/faq.rst index d6f4ad336ac7..7eec9c53b427 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -117,6 +117,19 @@ upstream, ``cryptography`` is also dropping support for them. To fix this issue you should upgrade to a newer version of OpenSSL (1.1.0 or later). This may require you to upgrade to a newer operating system. +Installing ``cryptography`` fails with ``error: Can not find Rust compiler`` +---------------------------------------------------------------------------- + +Building ``cryptography`` from source requires you have :ref:`Rust installed +and available` on your ``PATH``. You may be able to fix this +by upgrading to a newer version of ``pip`` which will install a pre-compiled +``cryptography`` wheel. If not, you'll need to install Rust. + +For the current release *only* you can temporarily bypass the requirement to +have Rust installed by setting the ``CRYPTOGRAPHY_DONT_BUILD_RUST`` environment +variable. Note that this option will be removed in the next release and not +having Rust available will be a hard error. + Why are there no wheels for my Python3.x version? ------------------------------------------------- diff --git a/docs/installation.rst b/docs/installation.rst index 5d214793b625..313996233070 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -61,6 +61,9 @@ platforms). ``cryptography`` links against the new 1.1.0 names by default. If you need to compile ``cryptography`` against an older version then you **must** set ``CRYPTOGRAPHY_WINDOWS_LINK_LEGACY_OPENSSL`` or else installation will fail. +You will also need to have :ref:`Rust installed and +available`. + If you need to rebuild ``cryptography`` for any reason be sure to clear the local `wheel cache`_. @@ -70,7 +73,7 @@ Building cryptography on Linux ------------------------------ ``cryptography`` ships ``manylinux`` wheels (as of 2.0) so all dependencies -are included. For users on pip 8.1 or above running on a ``manylinux1`` (or +are included. For users on pip 19.0 or above running on a ``manylinux2010`` (or greater) compatible distribution (almost everything except Alpine) all you should need to do is: @@ -83,6 +86,9 @@ If you are on Alpine or just want to compile it yourself then using ``pypy``), and headers for the OpenSSL and ``libffi`` libraries available on your system. +On all Linux distributions you will need to have :ref:`Rust installed and +available`. + Alpine ~~~~~~ @@ -229,6 +235,9 @@ open a terminal window and run: This will install a compiler (clang) along with (most of) the required development headers. +You will also need to have :ref:`Rust installed and +available`. + You'll also need OpenSSL, which you can obtain from `Homebrew`_ or `MacPorts`_. Cryptography does **not** support Apple's deprecated OpenSSL distribution. @@ -267,6 +276,13 @@ You can also build cryptography statically: If you need to rebuild ``cryptography`` for any reason be sure to clear the local `wheel cache`_. +Rust +---- + +Building ``cryptography`` requires having a working Rust toolchain. The current +minimum supported Rust version is 1.45.0. + +Instructions for installing Rust can be found on `the Rust Project's website`_. .. _`Homebrew`: https://brew.sh .. _`MacPorts`: https://www.macports.org @@ -274,3 +290,4 @@ local `wheel cache`_. .. _virtualenv: https://virtualenv.pypa.io/en/latest/ .. _openssl.org: https://www.openssl.org/source/ .. _`wheel cache`: https://pip.pypa.io/en/stable/reference/pip_install/#caching +.. _`the Rust Project's website`: https://www.rust-lang.org/tools/install diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt index f0486e05f704..f59c3e413506 100644 --- a/docs/spelling_wordlist.txt +++ b/docs/spelling_wordlist.txt @@ -106,6 +106,7 @@ testability Thawte timestamp timestamps +toolchain tunable Ubuntu unencrypted diff --git a/pyproject.toml b/pyproject.toml index 7d3ad2325abe..ecd77063890c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,6 +6,7 @@ requires = [ "wheel", # Must be kept in sync with the `setup_requirements` in `setup.py` "cffi>=1.12; platform_python_implementation != 'PyPy'", + "setuptools-rust>=0.11.4", ] build-backend = "setuptools.build_meta" diff --git a/setup.py b/setup.py index 2eb27e2ce7f5..58de2f4a8c5c 100644 --- a/setup.py +++ b/setup.py @@ -5,10 +5,13 @@ # for complete details. import os +import platform import sys from setuptools import find_packages, setup +from setuptools_rust import RustExtension + base_dir = os.path.dirname(__file__) src_dir = os.path.join(base_dir, "src") @@ -23,7 +26,24 @@ # `setup_requirements` must be kept in sync with `pyproject.toml` -setup_requirements = ["cffi>=1.12"] +setup_requirements = ["cffi>=1.12", "setuptools-rust>=0.11.4"] + +if os.environ.get("CRYPTOGRAPHY_DONT_BUILD_RUST"): + rust_extensions = [] +else: + rust_extensions = [ + RustExtension( + "_rust", + "src/rust/Cargo.toml", + py_limited_api=True, + # Enable abi3 mode if we're not using PyPy. + features=( + [] + if platform.python_implementation() == "PyPy" + else ["pyo3/abi3-py36"] + ), + ) + ] with open(os.path.join(base_dir, "README.rst")) as f: long_description = f.read() @@ -108,6 +128,7 @@ "src/_cffi_src/build_openssl.py:ffi", "src/_cffi_src/build_padding.py:ffi", ], + rust_extensions=rust_extensions, ) except: # noqa: E722 # Note: This is a bare exception that re-raises so that we don't interfere @@ -128,6 +149,7 @@ instructions for your platform. 3) Check our frequently asked questions for more information: https://cryptography.io/en/latest/faq.html + 4) Ensure you have a recent Rust toolchain installed. =============================DEBUG ASSISTANCE============================= """ ) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock new file mode 100644 index 000000000000..259218a5249c --- /dev/null +++ b/src/rust/Cargo.lock @@ -0,0 +1,241 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cryptography-rust" +version = "0.1.0" +dependencies = [ + "pyo3", +] + +[[package]] +name = "ctor" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fbaabec2c953050352311293be5c6aba8e141ba19d6811862b232d6fd020484" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "ghost" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5bcf1bbeab73aa4cf2fde60a846858dc036163c7c33bec309f8d17de785479" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "indoc" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a75aeaaef0ce18b58056d306c27b07436fbb34b8816c53094b76dd81803136" +dependencies = [ + "unindent", +] + +[[package]] +name = "instant" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "inventory" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f0f7efb804ec95e33db9ad49e4252f049e37e8b0a4652e3cd61f7999f2eff7f" +dependencies = [ + "ctor", + "ghost", + "inventory-impl", +] + +[[package]] +name = "inventory-impl" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75c094e94816723ab936484666968f5b58060492e880f3c8d00489a1e244fa51" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "libc" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" + +[[package]] +name = "lock_api" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "parking_lot" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c6d9b8427445284a09c55be860a15855ab580a417ccad9da88f5a06787ced0" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "paste" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5d65c4d95931acda4498f675e332fcbdc9a06705cd07086c510e9b6009cd1c1" + +[[package]] +name = "proc-macro2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "pyo3" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdd01a4c2719dd1f3ceab0875fa1a2c2cd3c619477349d78f43cd716b345436" +dependencies = [ + "cfg-if", + "ctor", + "indoc", + "inventory", + "libc", + "parking_lot", + "paste", + "pyo3-macros", + "unindent", +] + +[[package]] +name = "pyo3-macros" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f8218769d13e354f841d559a19b0cf22cfd55959c7046ef594e5f34dbe46d16" +dependencies = [ + "pyo3-macros-backend", + "quote", + "syn", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4da0bfdf76f0a5971c698f2cb6b3f832a6f80f16dedeeb3f123eb0431ecce2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "smallvec" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae524f056d7d770e174287294f562e95044c68e88dec909a00d2094805db9d75" + +[[package]] +name = "syn" +version = "1.0.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + +[[package]] +name = "unindent" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml new file mode 100644 index 000000000000..1f80ca8a9e1c --- /dev/null +++ b/src/rust/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "cryptography-rust" +version = "0.1.0" +authors = ["The cryptography developers "] +edition = "2018" +publish = false + +[dependencies] +pyo3 = { version = "0.13.0", features = ["extension-module"] } + +[lib] +name = "cryptography_rust" +crate-type = ["cdylib"] + +[profile.release] +lto = "thin" diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs new file mode 100644 index 000000000000..f06ac5f02125 --- /dev/null +++ b/src/rust/src/lib.rs @@ -0,0 +1,8 @@ +// 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. + +#[pyo3::prelude::pymodule] +fn _rust(_py: pyo3::Python<'_>, _m: &pyo3::types::PyModule) -> pyo3::PyResult<()> { + Ok(()) +} diff --git a/tox.ini b/tox.ini index 8a34499cfd81..0d28248a36e6 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 2.4 -envlist = pypy3,py36,py37,py38,py39,docs,pep8,packaging +envlist = pypy3,py36,py37,py38,py39,docs,pep8,rust,packaging isolated_build = True [testenv] @@ -45,6 +45,15 @@ commands = flake8 . black --check . +[testenv:rust] +basepython = python3 +changedir = src/rust/ +allowlist_externals = + cargo +commands = + cargo fmt --all -- --check + cargo clippy -- -D warnings + [testenv:packaging] deps = check-manifest From a7c5e693d4a7552a552a7b9b8d152d811474c8a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Dec 2020 15:29:09 -0500 Subject: [PATCH 0043/2380] Bump parking_lot_core from 0.8.1 to 0.8.2 in /src/rust (#5664) Bumps [parking_lot_core](https://github.com/Amanieu/parking_lot) from 0.8.1 to 0.8.2. - [Release notes](https://github.com/Amanieu/parking_lot/releases) - [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md) - [Commits](https://github.com/Amanieu/parking_lot/compare/0.8.1...core-0.8.2) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 259218a5249c..57668f71d781 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -102,9 +102,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c6d9b8427445284a09c55be860a15855ab580a417ccad9da88f5a06787ced0" +checksum = "9ccb628cad4f84851442432c60ad8e1f607e29752d0bf072cbd0baf28aa34272" dependencies = [ "cfg-if", "instant", From 899400b9a172956ce42dad07ad46e97ccb242a57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Dec 2020 15:48:46 -0500 Subject: [PATCH 0044/2380] Bump syn from 1.0.54 to 1.0.55 in /src/rust (#5663) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.54 to 1.0.55. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.54...1.0.55) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 57668f71d781..bcadc18a1ee7 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -197,9 +197,9 @@ checksum = "ae524f056d7d770e174287294f562e95044c68e88dec909a00d2094805db9d75" [[package]] name = "syn" -version = "1.0.54" +version = "1.0.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44" +checksum = "a571a711dddd09019ccc628e1b17fe87c59b09d513c06c026877aa708334f37a" dependencies = [ "proc-macro2", "quote", From 5cbaad04281dd4e8e32109e64f9ba05f7d13ebd2 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 22 Dec 2020 14:57:41 -0600 Subject: [PATCH 0045/2380] changelog update (#5666) --- CHANGELOG.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2db299378ac0..c0352c5dd744 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -9,11 +9,13 @@ Changelog .. note:: This version is not yet released and is under active development. * **BACKWARDS INCOMPATIBLE:** Support for Python 2 has been removed. -* We now ship ``manylinux2014`` wheels, and no longer ship ``manylinux1`` - wheels. +* We now ship ``manylinux2014`` wheels and no longer ship ``manylinux1`` + wheels. Users should upgrade to the latest ``pip`` to ensure this doesn't + cause issues downloading wheels on their platform. * ``cryptography`` now incorporates Rust code. Users building ``cryptography`` - themselves will need to have the Rust toolchain installed, users who use an - officially produced wheel will not need to make any changes. + themselves will need to have the Rust toolchain installed. Users who use an + officially produced wheel will not need to make any changes. The minimum + supported Rust version is 1.45.0. .. _v3-3-1: From bd0d0fda51ea8e77fef4def5d6322f7cbdf63248 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Dec 2020 16:09:20 -0500 Subject: [PATCH 0046/2380] Bump quote from 1.0.7 to 1.0.8 in /src/rust (#5665) Bumps [quote](https://github.com/dtolnay/quote) from 1.0.7 to 1.0.8. - [Release notes](https://github.com/dtolnay/quote/releases) - [Commits](https://github.com/dtolnay/quote/compare/1.0.7...1.0.8) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index bcadc18a1ee7..8ceebf4264c5 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -170,9 +170,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" dependencies = [ "proc-macro2", ] From c0771754bb29c003ce1e80095ed8c27329d1bc78 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Dec 2020 10:15:28 -0500 Subject: [PATCH 0047/2380] Bump ctor from 0.1.16 to 0.1.17 in /src/rust (#5672) Bumps [ctor](https://github.com/mmastrac/rust-ctor) from 0.1.16 to 0.1.17. - [Release notes](https://github.com/mmastrac/rust-ctor/releases) - [Commits](https://github.com/mmastrac/rust-ctor/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 8ceebf4264c5..4a73a08832b0 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -15,9 +15,9 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbaabec2c953050352311293be5c6aba8e141ba19d6811862b232d6fd020484" +checksum = "373c88d9506e2e9230f6107701b7d8425f4cb3f6df108ec3042a26e936666da5" dependencies = [ "quote", "syn", @@ -197,9 +197,9 @@ checksum = "ae524f056d7d770e174287294f562e95044c68e88dec909a00d2094805db9d75" [[package]] name = "syn" -version = "1.0.55" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a571a711dddd09019ccc628e1b17fe87c59b09d513c06c026877aa708334f37a" +checksum = "a9802ddde94170d186eeee5005b798d9c159fa970403f1be19976d0cfb939b72" dependencies = [ "proc-macro2", "quote", From a9d60e83b76c37713060d472d5ef9062d4cf5ce3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Jan 2021 02:38:03 -0500 Subject: [PATCH 0048/2380] Bump smallvec from 1.5.1 to 1.6.0 in /src/rust (#5678) Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.5.1 to 1.6.0. - [Release notes](https://github.com/servo/rust-smallvec/releases) - [Commits](https://github.com/servo/rust-smallvec/compare/v1.5.1...v1.6.0) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 4a73a08832b0..05f4286e3561 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -191,9 +191,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "smallvec" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae524f056d7d770e174287294f562e95044c68e88dec909a00d2094805db9d75" +checksum = "1a55ca5f3b68e41c979bf8c46a6f1da892ca4db8f94023ce0bd32407573b1ac0" [[package]] name = "syn" From e4c7a3d4833811983e4ae58da51b44c5e26be968 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Jan 2021 09:06:57 -0500 Subject: [PATCH 0049/2380] Bump syn from 1.0.56 to 1.0.57 in /src/rust (#5679) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.56 to 1.0.57. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.56...1.0.57) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 05f4286e3561..e8e120a7ed3c 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -197,9 +197,9 @@ checksum = "1a55ca5f3b68e41c979bf8c46a6f1da892ca4db8f94023ce0bd32407573b1ac0" [[package]] name = "syn" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9802ddde94170d186eeee5005b798d9c159fa970403f1be19976d0cfb939b72" +checksum = "4211ce9909eb971f111059df92c45640aad50a619cf55cd76476be803c4c68e6" dependencies = [ "proc-macro2", "quote", From b892abab9651ccf9256804e22b50fa25366febee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Jan 2021 02:11:37 -0500 Subject: [PATCH 0050/2380] Bump syn from 1.0.57 to 1.0.58 in /src/rust (#5681) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.57 to 1.0.58. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.57...1.0.58) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index e8e120a7ed3c..8cc42ff826c7 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -197,9 +197,9 @@ checksum = "1a55ca5f3b68e41c979bf8c46a6f1da892ca4db8f94023ce0bd32407573b1ac0" [[package]] name = "syn" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4211ce9909eb971f111059df92c45640aad50a619cf55cd76476be803c4c68e6" +checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5" dependencies = [ "proc-macro2", "quote", From 688db7fef94cf75054fc15daab3a2ffb0bd585a8 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 7 Jan 2021 13:11:40 -0500 Subject: [PATCH 0051/2380] fix wheel builder (#5682) don't install enum34, and fix syntax error --- .github/workflows/wheel-builder.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index c9de0b65b368..528c07fd4ac0 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -21,7 +21,7 @@ jobs: steps: - run: /opt/python/${{ matrix.PYTHON }}/bin/python -m virtualenv .venv - name: Install Python dependencies - run: .venv/bin/pip install -U pip wheel cffi six ipaddress "enum34; python_version < '3' setuptools-rust" + run: .venv/bin/pip install -U pip wheel cffi six ipaddress setuptools-rust - run: .venv/bin/pip download cryptography==${{ github.event.inputs.version }} --no-deps --no-binary cryptography && tar zxvf cryptography*.tar.gz && mkdir tmpwheelhouse - run: | REGEX="cp3([0-9])*" @@ -83,7 +83,7 @@ jobs: default: true - run: ${{ matrix.PYTHON.BIN_PATH }} -m virtualenv venv - - run: venv/bin/pip install -U pip wheel cffi six ipaddress "enum34; python_version < '3' setuptools-rust" + - run: venv/bin/pip install -U pip wheel cffi six ipaddress setuptools-rust - run: venv/bin/pip download cryptography==${{ github.event.inputs.version }} --no-deps --no-binary cryptography && tar zxvf cryptography*.tar.gz && mkdir wheelhouse - name: Build the wheel run: | @@ -138,7 +138,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} shell: bash - - run: python -m pip install -U pip wheel cffi six ipaddress "enum34; python_version < '3' setuptools-rust" + - run: python -m pip install -U pip wheel cffi six ipaddress setuptools-rust - run: pip download cryptography==${{ github.event.inputs.version }} --no-deps --no-binary cryptography && tar zxvf cryptography*.tar.gz && mkdir wheelhouse shell: bash - run: cd cryptography* && python setup.py bdist_wheel --py-limited-api=${{ matrix.PYTHON.ABI_VERSION }} && mv dist/cryptography*.whl ../wheelhouse From 0109b0cc7af38ecc3956e887ef5147046a41239c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Jan 2021 07:54:27 -0500 Subject: [PATCH 0052/2380] Bump libc from 0.2.81 to 0.2.82 in /src/rust (#5684) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.81 to 0.2.82. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.81...0.2.82) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 8cc42ff826c7..52233cee88da 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -76,9 +76,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.81" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" +checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929" [[package]] name = "lock_api" From 928262531c3245ae16abea1108c6601490a59ef5 Mon Sep 17 00:00:00 2001 From: Chkoupinator Date: Sat, 9 Jan 2021 18:08:26 +0100 Subject: [PATCH 0053/2380] Added information on what encrypt raises (#5686) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added information on what encrypt raises Added a note on RSA's Encrypt explanation for newcomers such as myself, so that they don't have to waste 4 hours trying to figure out what is causing the ValueError like I did 😅 * Moved the note under the raises ValueError section * Removed whitespaces causing issues * Update rsa.rst * Update docs/hazmat/primitives/asymmetric/rsa.rst Co-authored-by: Paul Kehrer Co-authored-by: Alex Gaynor Co-authored-by: Paul Kehrer --- docs/hazmat/primitives/asymmetric/rsa.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst index 09b8f76d708a..be69c636cbc5 100644 --- a/docs/hazmat/primitives/asymmetric/rsa.rst +++ b/docs/hazmat/primitives/asymmetric/rsa.rst @@ -654,6 +654,10 @@ Key interfaces :return bytes: Encrypted data. + :raises ValueError: The data could not be encrypted. One possible cause + is if ``data`` is too large; RSA keys can only encrypt data that + is smaller than the key size. + .. attribute:: key_size :type: int From 4b7b0af26ee8200e3217edb120520b52a5ff1055 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Jan 2021 09:03:12 -0500 Subject: [PATCH 0054/2380] Bump pyo3 from 0.13.0 to 0.13.1 in /src/rust (#5690) Bumps [pyo3](https://github.com/pyo3/pyo3) from 0.13.0 to 0.13.1. - [Release notes](https://github.com/pyo3/pyo3/releases) - [Changelog](https://github.com/PyO3/pyo3/blob/master/CHANGELOG.md) - [Commits](https://github.com/pyo3/pyo3/compare/v0.13.0...v0.13.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 12 ++++++------ src/rust/Cargo.toml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 52233cee88da..9636ee3a51e9 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -131,9 +131,9 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdd01a4c2719dd1f3ceab0875fa1a2c2cd3c619477349d78f43cd716b345436" +checksum = "00ca634cf3acd58a599b535ed6cb188223298977d471d146121792bfa23b754c" dependencies = [ "cfg-if", "ctor", @@ -148,9 +148,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f8218769d13e354f841d559a19b0cf22cfd55959c7046ef594e5f34dbe46d16" +checksum = "483ac516dbda6789a5b4be0271e7a31b9ad4ec8c0a5955050e8076f72bdbef8f" dependencies = [ "pyo3-macros-backend", "quote", @@ -159,9 +159,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4da0bfdf76f0a5971c698f2cb6b3f832a6f80f16dedeeb3f123eb0431ecce2" +checksum = "15230cabcda008f03565ed8bac40f094cbb5ee1b46e6551f1ec3a0e922cf7df9" dependencies = [ "proc-macro2", "quote", diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 1f80ca8a9e1c..8d154fbbe48d 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" publish = false [dependencies] -pyo3 = { version = "0.13.0", features = ["extension-module"] } +pyo3 = { version = "0.13.1", features = ["extension-module"] } [lib] name = "cryptography_rust" From 7b1d7af45b35d997a08b8e0361d46d176588ed30 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Jan 2021 09:18:35 -0500 Subject: [PATCH 0055/2380] Bump smallvec from 1.6.0 to 1.6.1 in /src/rust (#5689) Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.6.0 to 1.6.1. - [Release notes](https://github.com/servo/rust-smallvec/releases) - [Commits](https://github.com/servo/rust-smallvec/compare/v1.6.0...v1.6.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 9636ee3a51e9..bc715f079ee4 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -191,9 +191,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "smallvec" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a55ca5f3b68e41c979bf8c46a6f1da892ca4db8f94023ce0bd32407573b1ac0" +checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "syn" From 59106907647243359faf69be18175b8bc06afb6f Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Tue, 12 Jan 2021 08:05:47 -0800 Subject: [PATCH 0056/2380] correct types in docs/index.rst doctest (#5692) --- docs/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index ec3913f41d8c..460873ccdacd 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -14,9 +14,9 @@ key derivation functions. For example, to encrypt something with >>> f = Fernet(key) >>> token = f.encrypt(b"A really secret message. Not for prying eyes.") >>> token - '...' + b'...' >>> f.decrypt(token) - 'A really secret message. Not for prying eyes.' + b'A really secret message. Not for prying eyes.' If you are interested in learning more about the field of cryptography, we recommend `Crypto 101, by Laurens Van Houtven`_ and `The Cryptopals Crypto From d6535b68455767be37402ad7ce185d2e459daec8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Jan 2021 12:18:58 -0500 Subject: [PATCH 0057/2380] Bump ctor from 0.1.17 to 0.1.18 in /src/rust (#5693) Bumps [ctor](https://github.com/mmastrac/rust-ctor) from 0.1.17 to 0.1.18. - [Release notes](https://github.com/mmastrac/rust-ctor/releases) - [Commits](https://github.com/mmastrac/rust-ctor/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index bc715f079ee4..61f9952a8203 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -15,9 +15,9 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c88d9506e2e9230f6107701b7d8425f4cb3f6df108ec3042a26e936666da5" +checksum = "10bcb9d7dcbf7002aaffbb53eac22906b64cdcc127971dcc387d8eb7c95d5560" dependencies = [ "quote", "syn", From 8fd6b44969a2175f3968f214368d9c7ba631131a Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 25 Jan 2021 15:12:56 -0500 Subject: [PATCH 0058/2380] It's 2021! (#5701) --- docs/conf.py | 2 +- src/cryptography/__about__.py | 2 +- vectors/cryptography_vectors/__about__.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 90f49463d1b3..0db9dd8b842d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -70,7 +70,7 @@ # General information about the project. project = "Cryptography" -copyright = "2013-2020, Individual Contributors" +copyright = "2013-2021, Individual Contributors" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py index dcfcae59cd5d..ab91153ecfe1 100644 --- a/src/cryptography/__about__.py +++ b/src/cryptography/__about__.py @@ -27,4 +27,4 @@ __email__ = "cryptography-dev@python.org" __license__ = "BSD or Apache License, Version 2.0" -__copyright__ = "Copyright 2013-2020 {}".format(__author__) +__copyright__ = "Copyright 2013-2021 {}".format(__author__) diff --git a/vectors/cryptography_vectors/__about__.py b/vectors/cryptography_vectors/__about__.py index a30fbf58fefc..fe4c6e5f19d9 100644 --- a/vectors/cryptography_vectors/__about__.py +++ b/vectors/cryptography_vectors/__about__.py @@ -24,4 +24,4 @@ __email__ = "cryptography-dev@python.org" __license__ = "BSD or Apache License, Version 2.0" -__copyright__ = "Copyright 2013-2020 %s" % __author__ +__copyright__ = "Copyright 2013-2021 %s" % __author__ From dbe2f0cdd71369a9d2ef47f74b8c9d292a6698cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Jan 2021 21:43:41 -0500 Subject: [PATCH 0059/2380] Bump syn from 1.0.58 to 1.0.60 in /src/rust (#5700) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.58 to 1.0.60. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.58...1.0.60) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 61f9952a8203..257e095b5d42 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -197,9 +197,9 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "syn" -version = "1.0.58" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5" +checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" dependencies = [ "proc-macro2", "quote", From 321e556bc97690dd49518aaf60798ee22ef15dec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Jan 2021 09:15:27 -0500 Subject: [PATCH 0060/2380] Bump libc from 0.2.82 to 0.2.83 in /src/rust (#5705) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.82 to 0.2.83. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.82...0.2.83) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 257e095b5d42..41a30a6a4b56 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -76,9 +76,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929" +checksum = "7eb0c4e9c72ee9d69b767adebc5f4788462a3b45624acd919475c92597bcaf4f" [[package]] name = "lock_api" From 4a6627b4c11f7da99147c4e200eabdf11b5d59c8 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 28 Jan 2021 19:20:02 -0500 Subject: [PATCH 0061/2380] Introduce the most very basic mypy type checking (#5706) Nothing is really annotated, just getting to clean. --- .github/workflows/ci.yml | 2 +- MANIFEST.in | 2 +- mypy.ini | 6 ++ .../hazmat/backends/openssl/ocsp.py | 61 ++++++++----------- .../hazmat/bindings/openssl/binding.py | 3 +- .../hazmat/primitives/serialization/ssh.py | 8 ++- tox.ini | 9 +++ 7 files changed, 52 insertions(+), 39 deletions(-) create mode 100644 mypy.ini diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5e8f7a24a353..14dcfeb378dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: PYTHON: - - {VERSION: "3.9", TOXENV: "pep8,rust,packaging,docs", COVERAGE: "false"} + - {VERSION: "3.9", TOXENV: "pep8,rust,mypy,packaging,docs", COVERAGE: "false"} - {VERSION: "pypy3", TOXENV: "pypy3"} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1i"}} diff --git a/MANIFEST.in b/MANIFEST.in index d564df4961ba..4b4ec2dfc8e5 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -18,7 +18,7 @@ recursive-exclude vectors * recursive-exclude .github * -exclude release.py .coveragerc codecov.yml .readthedocs.yml dev-requirements.txt tox.ini +exclude release.py .coveragerc codecov.yml .readthedocs.yml dev-requirements.txt tox.ini mypy.ini recursive-exclude .zuul.d * recursive-exclude .zuul.playbooks * diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 000000000000..d67587279163 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,6 @@ +[mypy] + +[mypy-cryptography.hazmat.bindings._openssl] +ignore_missing_imports = True +[mypy-cryptography.hazmat.bindings._padding] +ignore_missing_imports = True \ No newline at end of file diff --git a/src/cryptography/hazmat/backends/openssl/ocsp.py b/src/cryptography/hazmat/backends/openssl/ocsp.py index 9a6b9b418fd7..231794c6bd24 100644 --- a/src/cryptography/hazmat/backends/openssl/ocsp.py +++ b/src/cryptography/hazmat/backends/openssl/ocsp.py @@ -3,8 +3,6 @@ # for complete details. -import functools - from cryptography import utils, x509 from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.backends.openssl.decode_asn1 import ( @@ -28,20 +26,6 @@ ) -def _requires_successful_response(func): - @functools.wraps(func) - def wrapper(self, *args): - if self.response_status != OCSPResponseStatus.SUCCESSFUL: - raise ValueError( - "OCSP response status is not successful so the property " - "has no value" - ) - else: - return func(self, *args) - - return wrapper - - def _issuer_key_hash(backend, cert_id): key_hash = backend._ffi.new("ASN1_OCTET_STRING **") res = backend._lib.OCSP_id_get0_info( @@ -136,17 +120,24 @@ def __init__(self, backend, ocsp_response): response_status = utils.read_only_property("_status") + def _requires_successful_response(self): + if self.response_status != OCSPResponseStatus.SUCCESSFUL: + raise ValueError( + "OCSP response status is not successful so the property " + "has no value" + ) + @property - @_requires_successful_response def signature_algorithm_oid(self): + self._requires_successful_response() alg = self._backend._lib.OCSP_resp_get0_tbs_sigalg(self._basic) self._backend.openssl_assert(alg != self._backend._ffi.NULL) oid = _obj2txt(self._backend, alg.algorithm) return x509.ObjectIdentifier(oid) @property - @_requires_successful_response def signature_hash_algorithm(self): + self._requires_successful_response() oid = self.signature_algorithm_oid try: return x509._SIG_OIDS_TO_HASH[oid] @@ -156,15 +147,15 @@ def signature_hash_algorithm(self): ) @property - @_requires_successful_response def signature(self): + self._requires_successful_response() sig = self._backend._lib.OCSP_resp_get0_signature(self._basic) self._backend.openssl_assert(sig != self._backend._ffi.NULL) return _asn1_string_to_bytes(self._backend, sig) @property - @_requires_successful_response def tbs_response_bytes(self): + self._requires_successful_response() respdata = self._backend._lib.OCSP_resp_get0_respdata(self._basic) self._backend.openssl_assert(respdata != self._backend._ffi.NULL) pp = self._backend._ffi.new("unsigned char **") @@ -177,8 +168,8 @@ def tbs_response_bytes(self): return self._backend._ffi.buffer(pp[0], res)[:] @property - @_requires_successful_response def certificates(self): + self._requires_successful_response() sk_x509 = self._backend._lib.OCSP_resp_get0_certs(self._basic) num = self._backend._lib.sk_X509_num(sk_x509) certs = [] @@ -195,8 +186,8 @@ def certificates(self): return certs @property - @_requires_successful_response def responder_key_hash(self): + self._requires_successful_response() _, asn1_string = self._responder_key_name() if asn1_string == self._backend._ffi.NULL: return None @@ -204,8 +195,8 @@ def responder_key_hash(self): return _asn1_string_to_bytes(self._backend, asn1_string) @property - @_requires_successful_response def responder_name(self): + self._requires_successful_response() x509_name, _ = self._responder_key_name() if x509_name == self._backend._ffi.NULL: return None @@ -222,16 +213,16 @@ def _responder_key_name(self): return x509_name[0], asn1_string[0] @property - @_requires_successful_response def produced_at(self): + self._requires_successful_response() produced_at = self._backend._lib.OCSP_resp_get0_produced_at( self._basic ) return _parse_asn1_generalized_time(self._backend, produced_at) @property - @_requires_successful_response def certificate_status(self): + self._requires_successful_response() status = self._backend._lib.OCSP_single_get0_status( self._single, self._backend._ffi.NULL, @@ -243,8 +234,8 @@ def certificate_status(self): return _CERT_STATUS_TO_ENUM[status] @property - @_requires_successful_response def revocation_time(self): + self._requires_successful_response() if self.certificate_status is not OCSPCertStatus.REVOKED: return None @@ -260,8 +251,8 @@ def revocation_time(self): return _parse_asn1_generalized_time(self._backend, asn1_time[0]) @property - @_requires_successful_response def revocation_reason(self): + self._requires_successful_response() if self.certificate_status is not OCSPCertStatus.REVOKED: return None @@ -283,8 +274,8 @@ def revocation_reason(self): return _CRL_ENTRY_REASON_CODE_TO_ENUM[reason_ptr[0]] @property - @_requires_successful_response def this_update(self): + self._requires_successful_response() asn1_time = self._backend._ffi.new("ASN1_GENERALIZEDTIME **") self._backend._lib.OCSP_single_get0_status( self._single, @@ -297,8 +288,8 @@ def this_update(self): return _parse_asn1_generalized_time(self._backend, asn1_time[0]) @property - @_requires_successful_response def next_update(self): + self._requires_successful_response() asn1_time = self._backend._ffi.new("ASN1_GENERALIZEDTIME **") self._backend._lib.OCSP_single_get0_status( self._single, @@ -313,33 +304,33 @@ def next_update(self): return None @property - @_requires_successful_response def issuer_key_hash(self): + self._requires_successful_response() return _issuer_key_hash(self._backend, self._cert_id) @property - @_requires_successful_response def issuer_name_hash(self): + self._requires_successful_response() return _issuer_name_hash(self._backend, self._cert_id) @property - @_requires_successful_response def hash_algorithm(self): + self._requires_successful_response() return _hash_algorithm(self._backend, self._cert_id) @property - @_requires_successful_response def serial_number(self): + self._requires_successful_response() return _serial_number(self._backend, self._cert_id) @utils.cached_property - @_requires_successful_response def extensions(self): + self._requires_successful_response() return self._backend._ocsp_basicresp_ext_parser.parse(self._basic) @utils.cached_property - @_requires_successful_response def single_extensions(self): + self._requires_successful_response() return self._backend._ocsp_singleresp_ext_parser.parse(self._single) def public_bytes(self, encoding): diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py index d65abc5adad9..bd67d97ef366 100644 --- a/src/cryptography/hazmat/bindings/openssl/binding.py +++ b/src/cryptography/hazmat/bindings/openssl/binding.py @@ -6,6 +6,7 @@ import collections import threading import types +import typing import cryptography from cryptography import utils @@ -108,7 +109,7 @@ class Binding(object): OpenSSL API wrapper. """ - lib = None + lib: typing.ClassVar = None ffi = ffi _lib_loaded = False _init_lock = threading.Lock() diff --git a/src/cryptography/hazmat/primitives/serialization/ssh.py b/src/cryptography/hazmat/primitives/serialization/ssh.py index 97a3fb21f2bd..5b98d5140a74 100644 --- a/src/cryptography/hazmat/primitives/serialization/ssh.py +++ b/src/cryptography/hazmat/primitives/serialization/ssh.py @@ -28,7 +28,13 @@ except ImportError: _bcrypt_supported = False - def _bcrypt_kdf(*args, **kwargs): + def _bcrypt_kdf( + password: bytes, + salt: bytes, + desired_key_bytes: int, + rounds: int, + ignore_few_rounds: bool = False, + ) -> bytes: raise UnsupportedAlgorithm("Need bcrypt module") diff --git a/tox.ini b/tox.ini index 0d28248a36e6..b5956629fa5e 100644 --- a/tox.ini +++ b/tox.ini @@ -45,6 +45,15 @@ commands = flake8 . black --check . +[testenv:mypy] +basepython = python3 +extras = + ssh +deps = + mypy +commands = + mypy src/cryptography/ + [testenv:rust] basepython = python3 changedir = src/rust/ From 2adfa8d702b794f4a9bfae9c9234f7a0fbfacb80 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Jan 2021 08:54:51 -0500 Subject: [PATCH 0062/2380] Bump libc from 0.2.83 to 0.2.84 in /src/rust (#5707) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.83 to 0.2.84. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 41a30a6a4b56..f1a6f69eb439 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -76,9 +76,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0c4e9c72ee9d69b767adebc5f4788462a3b45624acd919475c92597bcaf4f" +checksum = "1cca32fa0182e8c0989459524dc356b8f2b5c10f1b9eb521b7d182c03cf8c5ff" [[package]] name = "lock_api" From db9e20a4cefdf8802d89740d54188d9c53975fe4 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 29 Jan 2021 16:39:20 -0500 Subject: [PATCH 0063/2380] Apply type annotations to fernet (#5708) --- src/cryptography/fernet.py | 61 ++++++++++++++++++++++++-------------- tests/test_fernet.py | 6 ++-- 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/src/cryptography/fernet.py b/src/cryptography/fernet.py index e47df71ce937..c9464c5ad436 100644 --- a/src/cryptography/fernet.py +++ b/src/cryptography/fernet.py @@ -8,6 +8,7 @@ import os import struct import time +import typing from cryptography import utils from cryptography.exceptions import InvalidSignature @@ -25,7 +26,7 @@ class InvalidToken(Exception): class Fernet(object): - def __init__(self, key, backend=None): + def __init__(self, key: bytes, backend=None): backend = _get_backend(backend) key = base64.urlsafe_b64decode(key) @@ -39,17 +40,19 @@ def __init__(self, key, backend=None): self._backend = backend @classmethod - def generate_key(cls): + def generate_key(cls) -> bytes: return base64.urlsafe_b64encode(os.urandom(32)) - def encrypt(self, data): + def encrypt(self, data: bytes) -> bytes: return self.encrypt_at_time(data, int(time.time())) - def encrypt_at_time(self, data, current_time): + def encrypt_at_time(self, data: bytes, current_time: int) -> bytes: iv = os.urandom(16) return self._encrypt_from_parts(data, current_time, iv) - def _encrypt_from_parts(self, data, current_time, iv): + def _encrypt_from_parts( + self, data: bytes, current_time: int, iv: bytes + ) -> bytes: utils._check_bytes("data", data) padder = padding.PKCS7(algorithms.AES.block_size).padder() @@ -68,26 +71,32 @@ def _encrypt_from_parts(self, data, current_time, iv): hmac = h.finalize() return base64.urlsafe_b64encode(basic_parts + hmac) - def decrypt(self, token, ttl=None): + def decrypt(self, token: bytes, ttl: typing.Optional[int] = None) -> bytes: timestamp, data = Fernet._get_unverified_token_data(token) - return self._decrypt_data(data, timestamp, ttl, int(time.time())) + if ttl is None: + time_info = None + else: + time_info = (ttl, int(time.time())) + return self._decrypt_data(data, timestamp, time_info) - def decrypt_at_time(self, token, ttl, current_time): + def decrypt_at_time( + self, token: bytes, ttl: int, current_time: int + ) -> bytes: if ttl is None: raise ValueError( "decrypt_at_time() can only be used with a non-None ttl" ) timestamp, data = Fernet._get_unverified_token_data(token) - return self._decrypt_data(data, timestamp, ttl, current_time) + return self._decrypt_data(data, timestamp, (ttl, current_time)) - def extract_timestamp(self, token): + def extract_timestamp(self, token: bytes) -> int: timestamp, data = Fernet._get_unverified_token_data(token) # Verify the token was not tampered with. self._verify_signature(data) return timestamp @staticmethod - def _get_unverified_token_data(token): + def _get_unverified_token_data(token: bytes) -> typing.Tuple[int, bytes]: utils._check_bytes("token", token) try: data = base64.urlsafe_b64decode(token) @@ -103,7 +112,7 @@ def _get_unverified_token_data(token): raise InvalidToken return timestamp, data - def _verify_signature(self, data): + def _verify_signature(self, data: bytes) -> None: h = HMAC(self._signing_key, hashes.SHA256(), backend=self._backend) h.update(data[:-32]) try: @@ -111,8 +120,14 @@ def _verify_signature(self, data): except InvalidSignature: raise InvalidToken - def _decrypt_data(self, data, timestamp, ttl, current_time): - if ttl is not None: + def _decrypt_data( + self, + data: bytes, + timestamp: int, + time_info: typing.Optional[typing.Tuple[int, int]], + ) -> bytes: + if time_info is not None: + ttl, current_time = time_info if timestamp + ttl < current_time: raise InvalidToken @@ -142,25 +157,25 @@ def _decrypt_data(self, data, timestamp, ttl, current_time): class MultiFernet(object): - def __init__(self, fernets): - fernets = list(fernets) + def __init__(self, fernets_it: typing.Iterator[Fernet]): + fernets = list(fernets_it) if not fernets: raise ValueError( "MultiFernet requires at least one Fernet instance" ) self._fernets = fernets - def encrypt(self, msg): + def encrypt(self, msg: bytes) -> bytes: return self.encrypt_at_time(msg, int(time.time())) - def encrypt_at_time(self, msg, current_time): + def encrypt_at_time(self, msg: bytes, current_time: int) -> bytes: return self._fernets[0].encrypt_at_time(msg, current_time) - def rotate(self, msg): + def rotate(self, msg: bytes) -> bytes: timestamp, data = Fernet._get_unverified_token_data(msg) for f in self._fernets: try: - p = f._decrypt_data(data, timestamp, None, None) + p = f._decrypt_data(data, timestamp, None) break except InvalidToken: pass @@ -170,7 +185,7 @@ def rotate(self, msg): iv = os.urandom(16) return self._fernets[0]._encrypt_from_parts(p, timestamp, iv) - def decrypt(self, msg, ttl=None): + def decrypt(self, msg: bytes, ttl: typing.Optional[int] = None) -> bytes: for f in self._fernets: try: return f.decrypt(msg, ttl) @@ -178,7 +193,9 @@ def decrypt(self, msg, ttl=None): pass raise InvalidToken - def decrypt_at_time(self, msg, ttl, current_time): + def decrypt_at_time( + self, msg: bytes, ttl: int, current_time: int + ) -> bytes: for f in self._fernets: try: return f.decrypt_at_time(msg, ttl, current_time) diff --git a/tests/test_fernet.py b/tests/test_fernet.py index a3f45f7553c2..a2afaa596331 100644 --- a/tests/test_fernet.py +++ b/tests/test_fernet.py @@ -11,6 +11,8 @@ import iso8601 +import pretend + import pytest from cryptography.fernet import Fernet, InvalidToken, MultiFernet @@ -118,9 +120,7 @@ def test_timestamp_ignored_no_ttl(self, monkeypatch, backend): f = Fernet(base64.urlsafe_b64encode(b"\x00" * 32), backend=backend) pt = b"encrypt me" token = f.encrypt(pt) - ts = "1985-10-26T01:20:01-07:00" - current_time = calendar.timegm(iso8601.parse_date(ts).utctimetuple()) - monkeypatch.setattr(time, "time", lambda: current_time) + monkeypatch.setattr(time, "time", pretend.raiser(ValueError)) assert f.decrypt(token, ttl=None) == pt def test_ttl_required_in_decrypt_at_time(self, monkeypatch, backend): From b24d67d49d2fcac6aebd9523b989adc379fd0164 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 29 Jan 2021 18:00:00 -0500 Subject: [PATCH 0064/2380] Apply type annotations to x509 builders (#5709) --- docs/x509/reference.rst | 12 ++--- src/cryptography/utils.py | 9 ++-- src/cryptography/x509/base.py | 95 +++++++++++++++++++++++------------ 3 files changed, 75 insertions(+), 41 deletions(-) diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst index a46c5d623238..c6eba06f881e 100644 --- a/docs/x509/reference.rst +++ b/docs/x509/reference.rst @@ -764,11 +764,11 @@ X.509 Certificate Builder expiration time for the certificate. The certificate may not be trusted clients if it is used after this time. - .. method:: add_extension(extension, critical) + .. method:: add_extension(extval, critical) Adds an X.509 extension to the certificate. - :param extension: An extension conforming to the + :param extval: An extension conforming to the :class:`~cryptography.x509.ExtensionType` interface. :param critical: Set to ``True`` if the extension must be understood and @@ -993,11 +993,11 @@ X.509 Certificate Revocation List Builder :param time: The :class:`datetime.datetime` object (in UTC) that marks the next update time for this CRL. - .. method:: add_extension(extension, critical) + .. method:: add_extension(extval, critical) Adds an X.509 extension to this CRL. - :param extension: An extension with the + :param extval: An extension with the :class:`~cryptography.x509.ExtensionType` interface. :param critical: Set to ``True`` if the extension must be understood and @@ -1120,11 +1120,11 @@ X.509 Revoked Certificate Builder :param time: The :class:`datetime.datetime` object (in UTC) that marks the revocation time for the certificate. - .. method:: add_extension(extension, critical) + .. method:: add_extension(extval, critical) Adds an X.509 extension to this revoked certificate. - :param extension: An instance of one of the + :param extval: An instance of one of the :ref:`CRL entry extensions `. :param critical: Set to ``True`` if the extension must be understood and diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index 2c76f9ffc3f7..48d90c64acf3 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -6,6 +6,7 @@ import abc import inspect import sys +import typing import warnings @@ -23,19 +24,19 @@ class CryptographyDeprecationWarning(UserWarning): DeprecatedIn34 = CryptographyDeprecationWarning -def _check_bytes(name, value): +def _check_bytes(name: str, value: bytes): if not isinstance(value, bytes): raise TypeError("{} must be bytes".format(name)) -def _check_byteslike(name, value): +def _check_byteslike(name: str, value: bytes): try: memoryview(value) except TypeError: raise TypeError("{} must be bytes-like".format(name)) -def read_only_property(name): +def read_only_property(name: str): return property(lambda self: getattr(self, name)) @@ -58,7 +59,7 @@ def register_decorator(klass): return register_decorator -def int_to_bytes(integer, length=None): +def int_to_bytes(integer: int, length: typing.Optional[int] = None): return integer.to_bytes( length or (integer.bit_length() + 7) // 8 or 1, "big" ) diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index 028311dca1a7..0d1d6f0ad806 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -6,9 +6,11 @@ import abc import datetime import os +import typing from enum import Enum from cryptography.hazmat.backends import _get_backend +from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import ( dsa, ec, @@ -22,6 +24,13 @@ _EARLIEST_UTC_TIME = datetime.datetime(1950, 1, 1) +_PRIVATE_KEY_TYPES = typing.Union[ + ed25519.Ed25519PrivateKey, + ed448.Ed448PrivateKey, + rsa.RSAPrivateKey, + dsa.DSAPrivateKey, + ec.EllipticCurvePrivateKey, +] class AttributeNotFound(Exception): @@ -421,7 +430,7 @@ def __init__(self, subject_name=None, extensions=[], attributes=[]): self._extensions = extensions self._attributes = attributes - def subject_name(self, name): + def subject_name(self, name: Name): """ Sets the certificate requestor's distinguished name. """ @@ -433,14 +442,14 @@ def subject_name(self, name): name, self._extensions, self._attributes ) - def add_extension(self, extension, critical): + def add_extension(self, extval: ExtensionType, critical: bool): """ Adds an X.509 extension to the certificate request. """ - if not isinstance(extension, ExtensionType): + if not isinstance(extval, ExtensionType): raise TypeError("extension must be an ExtensionType") - extension = Extension(extension.oid, critical, extension) + extension = Extension(extval.oid, critical, extval) _reject_duplicate_extension(extension, self._extensions) return CertificateSigningRequestBuilder( @@ -449,7 +458,7 @@ def add_extension(self, extension, critical): self._attributes, ) - def add_attribute(self, oid, value): + def add_attribute(self, oid: ObjectIdentifier, value: bytes): """ Adds an X.509 attribute with an OID and associated value. """ @@ -467,7 +476,12 @@ def add_attribute(self, oid, value): self._attributes + [(oid, value)], ) - def sign(self, private_key, algorithm, backend=None): + def sign( + self, + private_key: _PRIVATE_KEY_TYPES, + algorithm: hashes.HashAlgorithm, + backend=None, + ) -> CertificateSigningRequest: """ Signs the request using the requestor's private key. """ @@ -497,7 +511,7 @@ def __init__( self._not_valid_after = not_valid_after self._extensions = extensions - def issuer_name(self, name): + def issuer_name(self, name: Name): """ Sets the CA's distinguished name. """ @@ -515,7 +529,7 @@ def issuer_name(self, name): self._extensions, ) - def subject_name(self, name): + def subject_name(self, name: Name): """ Sets the requestor's distinguished name. """ @@ -533,7 +547,16 @@ def subject_name(self, name): self._extensions, ) - def public_key(self, key): + def public_key( + self, + key: typing.Union[ + dsa.DSAPublicKey, + rsa.RSAPublicKey, + ec.EllipticCurvePublicKey, + ed25519.Ed25519PublicKey, + ed448.Ed448PublicKey, + ], + ): """ Sets the requestor's public key (as found in the signing request). """ @@ -564,7 +587,7 @@ def public_key(self, key): self._extensions, ) - def serial_number(self, number): + def serial_number(self, number: int): """ Sets the certificate serial number. """ @@ -591,7 +614,7 @@ def serial_number(self, number): self._extensions, ) - def not_valid_before(self, time): + def not_valid_before(self, time: datetime.datetime): """ Sets the certificate activation time. """ @@ -620,7 +643,7 @@ def not_valid_before(self, time): self._extensions, ) - def not_valid_after(self, time): + def not_valid_after(self, time: datetime.datetime): """ Sets the certificate expiration time. """ @@ -652,14 +675,14 @@ def not_valid_after(self, time): self._extensions, ) - def add_extension(self, extension, critical): + def add_extension(self, extval: ExtensionType, critical: bool): """ Adds an X.509 extension to the certificate. """ - if not isinstance(extension, ExtensionType): + if not isinstance(extval, ExtensionType): raise TypeError("extension must be an ExtensionType") - extension = Extension(extension.oid, critical, extension) + extension = Extension(extval.oid, critical, extval) _reject_duplicate_extension(extension, self._extensions) return CertificateBuilder( @@ -672,7 +695,12 @@ def add_extension(self, extension, critical): self._extensions + [extension], ) - def sign(self, private_key, algorithm, backend=None): + def sign( + self, + private_key: _PRIVATE_KEY_TYPES, + algorithm: hashes.HashAlgorithm, + backend=None, + ) -> Certificate: """ Signs the certificate using the CA's private key. """ @@ -713,7 +741,7 @@ def __init__( self._extensions = extensions self._revoked_certificates = revoked_certificates - def issuer_name(self, issuer_name): + def issuer_name(self, issuer_name: Name): if not isinstance(issuer_name, Name): raise TypeError("Expecting x509.Name object.") if self._issuer_name is not None: @@ -726,7 +754,7 @@ def issuer_name(self, issuer_name): self._revoked_certificates, ) - def last_update(self, last_update): + def last_update(self, last_update: datetime.datetime): if not isinstance(last_update, datetime.datetime): raise TypeError("Expecting datetime object.") if self._last_update is not None: @@ -748,7 +776,7 @@ def last_update(self, last_update): self._revoked_certificates, ) - def next_update(self, next_update): + def next_update(self, next_update: datetime.datetime): if not isinstance(next_update, datetime.datetime): raise TypeError("Expecting datetime object.") if self._next_update is not None: @@ -770,14 +798,14 @@ def next_update(self, next_update): self._revoked_certificates, ) - def add_extension(self, extension, critical): + def add_extension(self, extval: ExtensionType, critical: bool): """ Adds an X.509 extension to the certificate revocation list. """ - if not isinstance(extension, ExtensionType): + if not isinstance(extval, ExtensionType): raise TypeError("extension must be an ExtensionType") - extension = Extension(extension.oid, critical, extension) + extension = Extension(extval.oid, critical, extval) _reject_duplicate_extension(extension, self._extensions) return CertificateRevocationListBuilder( self._issuer_name, @@ -787,7 +815,7 @@ def add_extension(self, extension, critical): self._revoked_certificates, ) - def add_revoked_certificate(self, revoked_certificate): + def add_revoked_certificate(self, revoked_certificate: RevokedCertificate): """ Adds a revoked certificate to the CRL. """ @@ -802,7 +830,12 @@ def add_revoked_certificate(self, revoked_certificate): self._revoked_certificates + [revoked_certificate], ) - def sign(self, private_key, algorithm, backend=None): + def sign( + self, + private_key: _PRIVATE_KEY_TYPES, + algorithm: hashes.HashAlgorithm, + backend=None, + ) -> CertificateRevocationList: backend = _get_backend(backend) if self._issuer_name is None: raise ValueError("A CRL must have an issuer name") @@ -824,7 +857,7 @@ def __init__( self._revocation_date = revocation_date self._extensions = extensions - def serial_number(self, number): + def serial_number(self, number: int): if not isinstance(number, int): raise TypeError("Serial number must be of integral type.") if self._serial_number is not None: @@ -842,7 +875,7 @@ def serial_number(self, number): number, self._revocation_date, self._extensions ) - def revocation_date(self, time): + def revocation_date(self, time: datetime.datetime): if not isinstance(time, datetime.datetime): raise TypeError("Expecting datetime object.") if self._revocation_date is not None: @@ -856,11 +889,11 @@ def revocation_date(self, time): self._serial_number, time, self._extensions ) - def add_extension(self, extension, critical): - if not isinstance(extension, ExtensionType): + def add_extension(self, extval: ExtensionType, critical: bool): + if not isinstance(extval, ExtensionType): raise TypeError("extension must be an ExtensionType") - extension = Extension(extension.oid, critical, extension) + extension = Extension(extval.oid, critical, extval) _reject_duplicate_extension(extension, self._extensions) return RevokedCertificateBuilder( self._serial_number, @@ -868,7 +901,7 @@ def add_extension(self, extension, critical): self._extensions + [extension], ) - def build(self, backend=None): + def build(self, backend=None) -> RevokedCertificate: backend = _get_backend(backend) if self._serial_number is None: raise ValueError("A revoked certificate must have a serial number") @@ -880,5 +913,5 @@ def build(self, backend=None): return backend.create_x509_revoked_certificate(self) -def random_serial_number(): +def random_serial_number() -> int: return int.from_bytes(os.urandom(20), "big") >> 1 From cd2fe87b00e91c1fcc936ea02e4620e84375ff45 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 29 Jan 2021 18:36:00 -0500 Subject: [PATCH 0065/2380] Include type hints in the changelog (#5710) --- CHANGELOG.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c0352c5dd744..053017b05a4a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -16,6 +16,9 @@ Changelog themselves will need to have the Rust toolchain installed. Users who use an officially produced wheel will not need to make any changes. The minimum supported Rust version is 1.45.0. +* ``cryptography`` has begun including :pep:`484` type hints on its APIs. While + they do not yet cover all public APIs, users can begin using them to type + check their code with ``mypy``. .. _v3-3-1: From fbb48ea7998910c812b5c758183ff87868561081 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 30 Jan 2021 12:20:17 -0500 Subject: [PATCH 0066/2380] Apply type annotations to the core x509 types (#5711) --- .../hazmat/backends/openssl/x509.py | 133 ++++++----- src/cryptography/hazmat/primitives/hashes.py | 36 +-- src/cryptography/x509/base.py | 216 +++++++++--------- src/cryptography/x509/oid.py | 5 +- 4 files changed, 201 insertions(+), 189 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index cb71e645c4f5..f460ed2da4cb 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -5,9 +5,11 @@ import datetime import operator +import typing from cryptography import utils, x509 from cryptography.exceptions import UnsupportedAlgorithm +from cryptography.hazmat.backends.openssl import dsa, ec, rsa from cryptography.hazmat.backends.openssl.decode_asn1 import ( _asn1_integer_to_int, _asn1_string_to_bytes, @@ -20,7 +22,7 @@ _txt2obj_gc, ) from cryptography.hazmat.primitives import hashes, serialization -from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa +from cryptography.x509.base import _PUBLIC_KEY_TYPES from cryptography.x509.name import _ASN1Type @@ -43,23 +45,23 @@ def __init__(self, backend, x509_cert): def __repr__(self): return "".format(self.subject) - def __eq__(self, other): - if not isinstance(other, x509.Certificate): + def __eq__(self, other: object) -> bool: + if not isinstance(other, _Certificate): return NotImplemented res = self._backend._lib.X509_cmp(self._x509, other._x509) return res == 0 - def __ne__(self, other): + def __ne__(self, other: object) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(self.public_bytes(serialization.Encoding.DER)) def __deepcopy__(self, memo): return self - def fingerprint(self, algorithm): + def fingerprint(self, algorithm: hashes.HashAlgorithm) -> bytes: h = hashes.Hash(algorithm, self._backend) h.update(self.public_bytes(serialization.Encoding.DER)) return h.finalize() @@ -67,12 +69,12 @@ def fingerprint(self, algorithm): version = utils.read_only_property("_version") @property - def serial_number(self): + def serial_number(self) -> int: asn1_int = self._backend._lib.X509_get_serialNumber(self._x509) self._backend.openssl_assert(asn1_int != self._backend._ffi.NULL) return _asn1_integer_to_int(self._backend, asn1_int) - def public_key(self): + def public_key(self) -> _PUBLIC_KEY_TYPES: pkey = self._backend._lib.X509_get_pubkey(self._x509) if pkey == self._backend._ffi.NULL: # Remove errors from the stack. @@ -84,29 +86,31 @@ def public_key(self): return self._backend._evp_pkey_to_public_key(pkey) @property - def not_valid_before(self): + def not_valid_before(self) -> datetime.datetime: asn1_time = self._backend._lib.X509_get0_notBefore(self._x509) return _parse_asn1_time(self._backend, asn1_time) @property - def not_valid_after(self): + def not_valid_after(self) -> datetime.datetime: asn1_time = self._backend._lib.X509_get0_notAfter(self._x509) return _parse_asn1_time(self._backend, asn1_time) @property - def issuer(self): + def issuer(self) -> x509.Name: issuer = self._backend._lib.X509_get_issuer_name(self._x509) self._backend.openssl_assert(issuer != self._backend._ffi.NULL) return _decode_x509_name(self._backend, issuer) @property - def subject(self): + def subject(self) -> x509.Name: subject = self._backend._lib.X509_get_subject_name(self._x509) self._backend.openssl_assert(subject != self._backend._ffi.NULL) return _decode_x509_name(self._backend, subject) @property - def signature_hash_algorithm(self): + def signature_hash_algorithm( + self, + ) -> typing.Optional[hashes.HashAlgorithm]: oid = self.signature_algorithm_oid try: return x509._SIG_OIDS_TO_HASH[oid] @@ -116,7 +120,7 @@ def signature_hash_algorithm(self): ) @property - def signature_algorithm_oid(self): + def signature_algorithm_oid(self) -> x509.ObjectIdentifier: alg = self._backend._ffi.new("X509_ALGOR **") self._backend._lib.X509_get0_signature( self._backend._ffi.NULL, alg, self._x509 @@ -126,11 +130,11 @@ def signature_algorithm_oid(self): return x509.ObjectIdentifier(oid) @utils.cached_property - def extensions(self): + def extensions(self) -> x509.Extensions: return self._backend._certificate_extension_parser.parse(self._x509) @property - def signature(self): + def signature(self) -> bytes: sig = self._backend._ffi.new("ASN1_BIT_STRING **") self._backend._lib.X509_get0_signature( sig, self._backend._ffi.NULL, self._x509 @@ -139,7 +143,7 @@ def signature(self): return _asn1_string_to_bytes(self._backend, sig[0]) @property - def tbs_certificate_bytes(self): + def tbs_certificate_bytes(self) -> bytes: pp = self._backend._ffi.new("unsigned char **") res = self._backend._lib.i2d_re_X509_tbs(self._x509, pp) self._backend.openssl_assert(res > 0) @@ -148,7 +152,7 @@ def tbs_certificate_bytes(self): ) return self._backend._ffi.buffer(pp[0], res)[:] - def public_bytes(self, encoding): + def public_bytes(self, encoding: serialization.Encoding) -> bytes: bio = self._backend._create_mem_bio_gc() if encoding is serialization.Encoding.PEM: res = self._backend._lib.PEM_write_bio_X509(bio, self._x509) @@ -161,8 +165,7 @@ def public_bytes(self, encoding): return self._backend._read_mem_bio(bio) -@utils.register_interface(x509.RevokedCertificate) -class _RevokedCertificate(object): +class _RevokedCertificate(x509.RevokedCertificate): def __init__(self, backend, crl, x509_revoked): self._backend = backend # The X509_REVOKED_value is a X509_REVOKED * that has @@ -176,7 +179,7 @@ def __init__(self, backend, crl, x509_revoked): self._x509_revoked = x509_revoked @property - def serial_number(self): + def serial_number(self) -> int: asn1_int = self._backend._lib.X509_REVOKED_get0_serialNumber( self._x509_revoked ) @@ -184,7 +187,7 @@ def serial_number(self): return _asn1_integer_to_int(self._backend, asn1_int) @property - def revocation_date(self): + def revocation_date(self) -> datetime.datetime: return _parse_asn1_time( self._backend, self._backend._lib.X509_REVOKED_get0_revocationDate( @@ -193,7 +196,7 @@ def revocation_date(self): ) @utils.cached_property - def extensions(self): + def extensions(self) -> x509.Extensions: return self._backend._revoked_cert_extension_parser.parse( self._x509_revoked ) @@ -205,17 +208,17 @@ def __init__(self, backend, x509_crl): self._backend = backend self._x509_crl = x509_crl - def __eq__(self, other): - if not isinstance(other, x509.CertificateRevocationList): + def __eq__(self, other: object) -> bool: + if not isinstance(other, _CertificateRevocationList): return NotImplemented res = self._backend._lib.X509_CRL_cmp(self._x509_crl, other._x509_crl) return res == 0 - def __ne__(self, other): + def __ne__(self, other: object) -> bool: return not self == other - def fingerprint(self, algorithm): + def fingerprint(self, algorithm: hashes.HashAlgorithm) -> bytes: h = hashes.Hash(algorithm, self._backend) bio = self._backend._create_mem_bio_gc() res = self._backend._lib.i2d_X509_CRL_bio(bio, self._x509_crl) @@ -234,7 +237,9 @@ def _sorted_crl(self): dup = self._backend._ffi.gc(dup, self._backend._lib.X509_CRL_free) return dup - def get_revoked_certificate_by_serial_number(self, serial_number): + def get_revoked_certificate_by_serial_number( + self, serial_number: int + ) -> typing.Optional[x509.RevokedCertificate]: revoked = self._backend._ffi.new("X509_REVOKED **") asn1_int = _encode_asn1_int_gc(self._backend, serial_number) res = self._backend._lib.X509_CRL_get0_by_serial( @@ -249,7 +254,9 @@ def get_revoked_certificate_by_serial_number(self, serial_number): ) @property - def signature_hash_algorithm(self): + def signature_hash_algorithm( + self, + ) -> typing.Optional[hashes.HashAlgorithm]: oid = self.signature_algorithm_oid try: return x509._SIG_OIDS_TO_HASH[oid] @@ -259,7 +266,7 @@ def signature_hash_algorithm(self): ) @property - def signature_algorithm_oid(self): + def signature_algorithm_oid(self) -> x509.ObjectIdentifier: alg = self._backend._ffi.new("X509_ALGOR **") self._backend._lib.X509_CRL_get0_signature( self._x509_crl, self._backend._ffi.NULL, alg @@ -269,25 +276,25 @@ def signature_algorithm_oid(self): return x509.ObjectIdentifier(oid) @property - def issuer(self): + def issuer(self) -> x509.Name: issuer = self._backend._lib.X509_CRL_get_issuer(self._x509_crl) self._backend.openssl_assert(issuer != self._backend._ffi.NULL) return _decode_x509_name(self._backend, issuer) @property - def next_update(self): + def next_update(self) -> datetime.datetime: nu = self._backend._lib.X509_CRL_get0_nextUpdate(self._x509_crl) self._backend.openssl_assert(nu != self._backend._ffi.NULL) return _parse_asn1_time(self._backend, nu) @property - def last_update(self): + def last_update(self) -> datetime.datetime: lu = self._backend._lib.X509_CRL_get0_lastUpdate(self._x509_crl) self._backend.openssl_assert(lu != self._backend._ffi.NULL) return _parse_asn1_time(self._backend, lu) @property - def signature(self): + def signature(self) -> bytes: sig = self._backend._ffi.new("ASN1_BIT_STRING **") self._backend._lib.X509_CRL_get0_signature( self._x509_crl, sig, self._backend._ffi.NULL @@ -296,7 +303,7 @@ def signature(self): return _asn1_string_to_bytes(self._backend, sig[0]) @property - def tbs_certlist_bytes(self): + def tbs_certlist_bytes(self) -> bytes: pp = self._backend._ffi.new("unsigned char **") res = self._backend._lib.i2d_re_X509_CRL_tbs(self._x509_crl, pp) self._backend.openssl_assert(res > 0) @@ -305,7 +312,7 @@ def tbs_certlist_bytes(self): ) return self._backend._ffi.buffer(pp[0], res)[:] - def public_bytes(self, encoding): + def public_bytes(self, encoding: serialization.Encoding) -> bytes: bio = self._backend._create_mem_bio_gc() if encoding is serialization.Encoding.PEM: res = self._backend._lib.PEM_write_bio_X509_CRL( @@ -341,7 +348,7 @@ def __getitem__(self, idx): raise IndexError return self._revoked_cert(idx) - def __len__(self): + def __len__(self) -> int: revoked = self._backend._lib.X509_CRL_get_REVOKED(self._x509_crl) if revoked == self._backend._ffi.NULL: return 0 @@ -349,13 +356,17 @@ def __len__(self): return self._backend._lib.sk_X509_REVOKED_num(revoked) @utils.cached_property - def extensions(self): + def extensions(self) -> x509.Extensions: return self._backend._crl_extension_parser.parse(self._x509_crl) - def is_signature_valid(self, public_key): + def is_signature_valid(self, public_key: _PUBLIC_KEY_TYPES) -> bool: if not isinstance( public_key, - (dsa.DSAPublicKey, rsa.RSAPublicKey, ec.EllipticCurvePublicKey), + ( + dsa._DSAPublicKey, + rsa._RSAPublicKey, + ec._EllipticCurvePublicKey, + ), ): raise TypeError( "Expecting one of DSAPublicKey, RSAPublicKey," @@ -378,7 +389,7 @@ def __init__(self, backend, x509_req): self._backend = backend self._x509_req = x509_req - def __eq__(self, other): + def __eq__(self, other: object) -> bool: if not isinstance(other, _CertificateSigningRequest): return NotImplemented @@ -386,26 +397,28 @@ def __eq__(self, other): other_bytes = other.public_bytes(serialization.Encoding.DER) return self_bytes == other_bytes - def __ne__(self, other): + def __ne__(self, other: object) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(self.public_bytes(serialization.Encoding.DER)) - def public_key(self): + def public_key(self) -> _PUBLIC_KEY_TYPES: pkey = self._backend._lib.X509_REQ_get_pubkey(self._x509_req) self._backend.openssl_assert(pkey != self._backend._ffi.NULL) pkey = self._backend._ffi.gc(pkey, self._backend._lib.EVP_PKEY_free) return self._backend._evp_pkey_to_public_key(pkey) @property - def subject(self): + def subject(self) -> x509.Name: subject = self._backend._lib.X509_REQ_get_subject_name(self._x509_req) self._backend.openssl_assert(subject != self._backend._ffi.NULL) return _decode_x509_name(self._backend, subject) @property - def signature_hash_algorithm(self): + def signature_hash_algorithm( + self, + ) -> typing.Optional[hashes.HashAlgorithm]: oid = self.signature_algorithm_oid try: return x509._SIG_OIDS_TO_HASH[oid] @@ -415,7 +428,7 @@ def signature_hash_algorithm(self): ) @property - def signature_algorithm_oid(self): + def signature_algorithm_oid(self) -> x509.ObjectIdentifier: alg = self._backend._ffi.new("X509_ALGOR **") self._backend._lib.X509_REQ_get0_signature( self._x509_req, self._backend._ffi.NULL, alg @@ -425,7 +438,7 @@ def signature_algorithm_oid(self): return x509.ObjectIdentifier(oid) @utils.cached_property - def extensions(self): + def extensions(self) -> x509.Extensions: x509_exts = self._backend._lib.X509_REQ_get_extensions(self._x509_req) x509_exts = self._backend._ffi.gc( x509_exts, @@ -438,7 +451,7 @@ def extensions(self): ) return self._backend._csr_extension_parser.parse(x509_exts) - def public_bytes(self, encoding): + def public_bytes(self, encoding: serialization.Encoding) -> bytes: bio = self._backend._create_mem_bio_gc() if encoding is serialization.Encoding.PEM: res = self._backend._lib.PEM_write_bio_X509_REQ( @@ -453,7 +466,7 @@ def public_bytes(self, encoding): return self._backend._read_mem_bio(bio) @property - def tbs_certrequest_bytes(self): + def tbs_certrequest_bytes(self) -> bytes: pp = self._backend._ffi.new("unsigned char **") res = self._backend._lib.i2d_re_X509_REQ_tbs(self._x509_req, pp) self._backend.openssl_assert(res > 0) @@ -463,7 +476,7 @@ def tbs_certrequest_bytes(self): return self._backend._ffi.buffer(pp[0], res)[:] @property - def signature(self): + def signature(self) -> bytes: sig = self._backend._ffi.new("ASN1_BIT_STRING **") self._backend._lib.X509_REQ_get0_signature( self._x509_req, sig, self._backend._ffi.NULL @@ -472,7 +485,7 @@ def signature(self): return _asn1_string_to_bytes(self._backend, sig[0]) @property - def is_signature_valid(self): + def is_signature_valid(self) -> bool: pkey = self._backend._lib.X509_REQ_get_pubkey(self._x509_req) self._backend.openssl_assert(pkey != self._backend._ffi.NULL) pkey = self._backend._ffi.gc(pkey, self._backend._lib.EVP_PKEY_free) @@ -484,7 +497,7 @@ def is_signature_valid(self): return True - def get_attribute_for_oid(self, oid): + def get_attribute_for_oid(self, oid: x509.ObjectIdentifier) -> bytes: obj = _txt2obj_gc(self._backend, oid.dotted_string) pos = self._backend._lib.X509_REQ_get_attr_by_OBJ( self._x509_req, obj, -1 @@ -537,20 +550,20 @@ def __init__(self, backend, sct_list, sct): self._sct = sct @property - def version(self): + def version(self) -> x509.certificate_transparency.Version: version = self._backend._lib.SCT_get_version(self._sct) assert version == self._backend._lib.SCT_VERSION_V1 return x509.certificate_transparency.Version.v1 @property - def log_id(self): + def log_id(self) -> bytes: out = self._backend._ffi.new("unsigned char **") log_id_length = self._backend._lib.SCT_get0_log_id(self._sct, out) assert log_id_length >= 0 return self._backend._ffi.buffer(out[0], log_id_length)[:] @property - def timestamp(self): + def timestamp(self) -> datetime.datetime: timestamp = self._backend._lib.SCT_get_timestamp(self._sct) milliseconds = timestamp % 1000 return datetime.datetime.utcfromtimestamp(timestamp // 1000).replace( @@ -558,7 +571,7 @@ def timestamp(self): ) @property - def entry_type(self): + def entry_type(self) -> x509.certificate_transparency.LogEntryType: entry_type = self._backend._lib.SCT_get_log_entry_type(self._sct) # We currently only support loading SCTs from the X.509 extension, so # we only have precerts. @@ -573,14 +586,14 @@ def _signature(self): self._backend.openssl_assert(ptrptr[0] != self._backend._ffi.NULL) return self._backend._ffi.buffer(ptrptr[0], res)[:] - def __hash__(self): + def __hash__(self) -> int: return hash(self._signature) - def __eq__(self, other): + def __eq__(self, other: object) -> bool: if not isinstance(other, _SignedCertificateTimestamp): return NotImplemented return self._signature == other._signature - def __ne__(self, other): + def __ne__(self, other: object) -> bool: return not self == other diff --git a/src/cryptography/hazmat/primitives/hashes.py b/src/cryptography/hazmat/primitives/hashes.py index c0aec11eb28a..3eaa89bd6939 100644 --- a/src/cryptography/hazmat/primitives/hashes.py +++ b/src/cryptography/hazmat/primitives/hashes.py @@ -105,75 +105,64 @@ def finalize(self): return digest -@utils.register_interface(HashAlgorithm) -class SHA1(object): +class SHA1(HashAlgorithm): name = "sha1" digest_size = 20 block_size = 64 -@utils.register_interface(HashAlgorithm) -class SHA512_224(object): # noqa: N801 +class SHA512_224(HashAlgorithm): # noqa: N801 name = "sha512-224" digest_size = 28 block_size = 128 -@utils.register_interface(HashAlgorithm) -class SHA512_256(object): # noqa: N801 +class SHA512_256(HashAlgorithm): # noqa: N801 name = "sha512-256" digest_size = 32 block_size = 128 -@utils.register_interface(HashAlgorithm) -class SHA224(object): +class SHA224(HashAlgorithm): name = "sha224" digest_size = 28 block_size = 64 -@utils.register_interface(HashAlgorithm) -class SHA256(object): +class SHA256(HashAlgorithm): name = "sha256" digest_size = 32 block_size = 64 -@utils.register_interface(HashAlgorithm) -class SHA384(object): +class SHA384(HashAlgorithm): name = "sha384" digest_size = 48 block_size = 128 -@utils.register_interface(HashAlgorithm) -class SHA512(object): +class SHA512(HashAlgorithm): name = "sha512" digest_size = 64 block_size = 128 -@utils.register_interface(HashAlgorithm) -class SHA3_224(object): # noqa: N801 +class SHA3_224(HashAlgorithm): # noqa: N801 name = "sha3-224" digest_size = 28 -@utils.register_interface(HashAlgorithm) -class SHA3_256(object): # noqa: N801 +class SHA3_256(HashAlgorithm): # noqa: N801 name = "sha3-256" digest_size = 32 -@utils.register_interface(HashAlgorithm) -class SHA3_384(object): # noqa: N801 +class SHA3_384(HashAlgorithm): # noqa: N801 name = "sha3-384" digest_size = 48 -@utils.register_interface(HashAlgorithm) -class SHA3_512(object): # noqa: N801 +class SHA3_512(HashAlgorithm): # noqa: N801 name = "sha3-512" digest_size = 64 @@ -212,8 +201,7 @@ def __init__(self, digest_size): digest_size = utils.read_only_property("_digest_size") -@utils.register_interface(HashAlgorithm) -class MD5(object): +class MD5(HashAlgorithm): name = "md5" digest_size = 16 block_size = 64 diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index 0d1d6f0ad806..c17fff8cee01 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -10,7 +10,7 @@ from enum import Enum from cryptography.hazmat.backends import _get_backend -from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ( dsa, ec, @@ -18,12 +18,19 @@ ed448, rsa, ) -from cryptography.x509.extensions import Extension, ExtensionType +from cryptography.x509.extensions import Extension, ExtensionType, Extensions from cryptography.x509.name import Name from cryptography.x509.oid import ObjectIdentifier _EARLIEST_UTC_TIME = datetime.datetime(1950, 1, 1) +_PUBLIC_KEY_TYPES = typing.Union[ + dsa.DSAPublicKey, + rsa.RSAPublicKey, + ec.EllipticCurvePublicKey, + ed25519.Ed25519PublicKey, + ed448.Ed448PublicKey, +] _PRIVATE_KEY_TYPES = typing.Union[ ed25519.Ed25519PrivateKey, ed448.Ed448PrivateKey, @@ -39,21 +46,26 @@ def __init__(self, msg, oid): self.oid = oid -def _reject_duplicate_extension(extension, extensions): +def _reject_duplicate_extension( + extension: Extension, extensions: typing.List[Extension] +): # This is quadratic in the number of extensions for e in extensions: if e.oid == extension.oid: raise ValueError("This extension has already been set.") -def _reject_duplicate_attribute(oid, attributes): +def _reject_duplicate_attribute( + oid: ObjectIdentifier, + attributes: typing.List[typing.Tuple[ObjectIdentifier, bytes]], +): # This is quadratic in the number of attributes for attr_oid, _ in attributes: if attr_oid == oid: raise ValueError("This attribute has already been set.") -def _convert_to_naive_utc_time(time): +def _convert_to_naive_utc_time(time: datetime.datetime) -> datetime.datetime: """Normalizes a datetime to a naive datetime in UTC. time -- datetime to normalize. Assumed to be in UTC if not timezone @@ -72,36 +84,6 @@ class Version(Enum): v3 = 2 -def load_pem_x509_certificate(data, backend=None): - backend = _get_backend(backend) - return backend.load_pem_x509_certificate(data) - - -def load_der_x509_certificate(data, backend=None): - backend = _get_backend(backend) - return backend.load_der_x509_certificate(data) - - -def load_pem_x509_csr(data, backend=None): - backend = _get_backend(backend) - return backend.load_pem_x509_csr(data) - - -def load_der_x509_csr(data, backend=None): - backend = _get_backend(backend) - return backend.load_der_x509_csr(data) - - -def load_pem_x509_crl(data, backend=None): - backend = _get_backend(backend) - return backend.load_pem_x509_crl(data) - - -def load_der_x509_crl(data, backend=None): - backend = _get_backend(backend) - return backend.load_der_x509_crl(data) - - class InvalidVersion(Exception): def __init__(self, msg, parsed_version): super(InvalidVersion, self).__init__(msg) @@ -110,192 +92,214 @@ def __init__(self, msg, parsed_version): class Certificate(metaclass=abc.ABCMeta): @abc.abstractmethod - def fingerprint(self, algorithm): + def fingerprint(self, algorithm: hashes.HashAlgorithm) -> bytes: """ Returns bytes using digest passed. """ @abc.abstractproperty - def serial_number(self): + def serial_number(self) -> int: """ Returns certificate serial number """ @abc.abstractproperty - def version(self): + def version(self) -> Version: """ Returns the certificate version """ @abc.abstractmethod - def public_key(self): + def public_key(self) -> _PUBLIC_KEY_TYPES: """ Returns the public key """ @abc.abstractproperty - def not_valid_before(self): + def not_valid_before(self) -> datetime.datetime: """ Not before time (represented as UTC datetime) """ @abc.abstractproperty - def not_valid_after(self): + def not_valid_after(self) -> datetime.datetime: """ Not after time (represented as UTC datetime) """ @abc.abstractproperty - def issuer(self): + def issuer(self) -> Name: """ Returns the issuer name object. """ @abc.abstractproperty - def subject(self): + def subject(self) -> Name: """ Returns the subject name object. """ @abc.abstractproperty - def signature_hash_algorithm(self): + def signature_hash_algorithm(self) -> hashes.HashAlgorithm: """ Returns a HashAlgorithm corresponding to the type of the digest signed in the certificate. """ @abc.abstractproperty - def signature_algorithm_oid(self): + def signature_algorithm_oid(self) -> ObjectIdentifier: """ Returns the ObjectIdentifier of the signature algorithm. """ @abc.abstractproperty - def extensions(self): + def extensions(self) -> Extensions: """ Returns an Extensions object. """ @abc.abstractproperty - def signature(self): + def signature(self) -> bytes: """ Returns the signature bytes. """ @abc.abstractproperty - def tbs_certificate_bytes(self): + def tbs_certificate_bytes(self) -> bytes: """ Returns the tbsCertificate payload bytes as defined in RFC 5280. """ @abc.abstractmethod - def __eq__(self, other): + def __eq__(self, other: object) -> bool: """ Checks equality. """ @abc.abstractmethod - def __ne__(self, other): + def __ne__(self, other: object) -> bool: """ Checks not equal. """ @abc.abstractmethod - def __hash__(self): + def __hash__(self) -> int: """ Computes a hash. """ @abc.abstractmethod - def public_bytes(self, encoding): + def public_bytes(self, encoding: serialization.Encoding) -> bytes: """ Serializes the certificate to PEM or DER format. """ +class RevokedCertificate(metaclass=abc.ABCMeta): + @abc.abstractproperty + def serial_number(self) -> int: + """ + Returns the serial number of the revoked certificate. + """ + + @abc.abstractproperty + def revocation_date(self) -> datetime.datetime: + """ + Returns the date of when this certificate was revoked. + """ + + @abc.abstractproperty + def extensions(self) -> Extensions: + """ + Returns an Extensions object containing a list of Revoked extensions. + """ + + class CertificateRevocationList(metaclass=abc.ABCMeta): @abc.abstractmethod - def public_bytes(self, encoding): + def public_bytes(self, encoding: serialization.Encoding) -> bytes: """ Serializes the CRL to PEM or DER format. """ @abc.abstractmethod - def fingerprint(self, algorithm): + def fingerprint(self, algorithm: hashes.HashAlgorithm) -> bytes: """ Returns bytes using digest passed. """ @abc.abstractmethod - def get_revoked_certificate_by_serial_number(self, serial_number): + def get_revoked_certificate_by_serial_number( + self, serial_number: int + ) -> typing.Optional[RevokedCertificate]: """ Returns an instance of RevokedCertificate or None if the serial_number is not in the CRL. """ @abc.abstractproperty - def signature_hash_algorithm(self): + def signature_hash_algorithm(self) -> hashes.HashAlgorithm: """ Returns a HashAlgorithm corresponding to the type of the digest signed in the certificate. """ @abc.abstractproperty - def signature_algorithm_oid(self): + def signature_algorithm_oid(self) -> ObjectIdentifier: """ Returns the ObjectIdentifier of the signature algorithm. """ @abc.abstractproperty - def issuer(self): + def issuer(self) -> Name: """ Returns the X509Name with the issuer of this CRL. """ @abc.abstractproperty - def next_update(self): + def next_update(self) -> datetime.datetime: """ Returns the date of next update for this CRL. """ @abc.abstractproperty - def last_update(self): + def last_update(self) -> datetime.datetime: """ Returns the date of last update for this CRL. """ @abc.abstractproperty - def extensions(self): + def extensions(self) -> Extensions: """ Returns an Extensions object containing a list of CRL extensions. """ @abc.abstractproperty - def signature(self): + def signature(self) -> bytes: """ Returns the signature bytes. """ @abc.abstractproperty - def tbs_certlist_bytes(self): + def tbs_certlist_bytes(self) -> bytes: """ Returns the tbsCertList payload bytes as defined in RFC 5280. """ @abc.abstractmethod - def __eq__(self, other): + def __eq__(self, other: object) -> bool: """ Checks equality. """ @abc.abstractmethod - def __ne__(self, other): + def __ne__(self, other: object) -> bool: """ Checks not equal. """ @abc.abstractmethod - def __len__(self): + def __len__(self) -> int: """ Number of revoked certificates in the CRL. """ @@ -313,7 +317,7 @@ def __iter__(self): """ @abc.abstractmethod - def is_signature_valid(self, public_key): + def is_signature_valid(self, public_key: _PUBLIC_KEY_TYPES) -> bool: """ Verifies signature of revocation list against given public key. """ @@ -321,104 +325,114 @@ def is_signature_valid(self, public_key): class CertificateSigningRequest(metaclass=abc.ABCMeta): @abc.abstractmethod - def __eq__(self, other): + def __eq__(self, other: object) -> bool: """ Checks equality. """ @abc.abstractmethod - def __ne__(self, other): + def __ne__(self, other: object) -> bool: """ Checks not equal. """ @abc.abstractmethod - def __hash__(self): + def __hash__(self) -> int: """ Computes a hash. """ @abc.abstractmethod - def public_key(self): + def public_key(self) -> _PUBLIC_KEY_TYPES: """ Returns the public key """ @abc.abstractproperty - def subject(self): + def subject(self) -> Name: """ Returns the subject name object. """ @abc.abstractproperty - def signature_hash_algorithm(self): + def signature_hash_algorithm(self) -> hashes.HashAlgorithm: """ Returns a HashAlgorithm corresponding to the type of the digest signed in the certificate. """ @abc.abstractproperty - def signature_algorithm_oid(self): + def signature_algorithm_oid(self) -> ObjectIdentifier: """ Returns the ObjectIdentifier of the signature algorithm. """ @abc.abstractproperty - def extensions(self): + def extensions(self) -> Extensions: """ Returns the extensions in the signing request. """ @abc.abstractmethod - def public_bytes(self, encoding): + def public_bytes(self, encoding: serialization.Encoding) -> bytes: """ Encodes the request to PEM or DER format. """ @abc.abstractproperty - def signature(self): + def signature(self) -> bytes: """ Returns the signature bytes. """ @abc.abstractproperty - def tbs_certrequest_bytes(self): + def tbs_certrequest_bytes(self) -> bytes: """ Returns the PKCS#10 CertificationRequestInfo bytes as defined in RFC 2986. """ @abc.abstractproperty - def is_signature_valid(self): + def is_signature_valid(self) -> bool: """ Verifies signature of signing request. """ - @abc.abstractproperty - def get_attribute_for_oid(self): + @abc.abstractmethod + def get_attribute_for_oid(self, oid: ObjectIdentifier) -> bytes: """ Get the attribute value for a given OID. """ -class RevokedCertificate(metaclass=abc.ABCMeta): - @abc.abstractproperty - def serial_number(self): - """ - Returns the serial number of the revoked certificate. - """ +def load_pem_x509_certificate(data: bytes, backend=None) -> Certificate: + backend = _get_backend(backend) + return backend.load_pem_x509_certificate(data) - @abc.abstractproperty - def revocation_date(self): - """ - Returns the date of when this certificate was revoked. - """ - @abc.abstractproperty - def extensions(self): - """ - Returns an Extensions object containing a list of Revoked extensions. - """ +def load_der_x509_certificate(data: bytes, backend=None) -> Certificate: + backend = _get_backend(backend) + return backend.load_der_x509_certificate(data) + + +def load_pem_x509_csr(data: bytes, backend=None) -> CertificateSigningRequest: + backend = _get_backend(backend) + return backend.load_pem_x509_csr(data) + + +def load_der_x509_csr(data: bytes, backend=None) -> CertificateSigningRequest: + backend = _get_backend(backend) + return backend.load_der_x509_csr(data) + + +def load_pem_x509_crl(data: bytes, backend=None) -> CertificateRevocationList: + backend = _get_backend(backend) + return backend.load_pem_x509_crl(data) + + +def load_der_x509_crl(data: bytes, backend=None) -> CertificateRevocationList: + backend = _get_backend(backend) + return backend.load_der_x509_crl(data) class CertificateSigningRequestBuilder(object): @@ -549,13 +563,7 @@ def subject_name(self, name: Name): def public_key( self, - key: typing.Union[ - dsa.DSAPublicKey, - rsa.RSAPublicKey, - ec.EllipticCurvePublicKey, - ed25519.Ed25519PublicKey, - ed448.Ed448PublicKey, - ], + key: _PUBLIC_KEY_TYPES, ): """ Sets the requestor's public key (as found in the signing request). diff --git a/src/cryptography/x509/oid.py b/src/cryptography/x509/oid.py index 2e3e60093b52..c7695bdb5397 100644 --- a/src/cryptography/x509/oid.py +++ b/src/cryptography/x509/oid.py @@ -2,6 +2,7 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. +import typing from cryptography.hazmat._oid import ObjectIdentifier from cryptography.hazmat.primitives import hashes @@ -105,7 +106,9 @@ class SignatureAlgorithmOID(object): GOSTR3410_2012_WITH_3411_2012_512 = ObjectIdentifier("1.2.643.7.1.1.3.3") -_SIG_OIDS_TO_HASH = { +_SIG_OIDS_TO_HASH: typing.Dict[ + ObjectIdentifier, typing.Optional[hashes.HashAlgorithm] +] = { SignatureAlgorithmOID.RSA_WITH_MD5: hashes.MD5(), SignatureAlgorithmOID.RSA_WITH_SHA1: hashes.SHA1(), SignatureAlgorithmOID._RSA_WITH_SHA1: hashes.SHA1(), From 1932c45821301945ac06ed0bdc81b081c3a51df9 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 30 Jan 2021 15:06:58 -0600 Subject: [PATCH 0067/2380] type hinting for hashes, hmac, and cmac (#5713) --- .../hazmat/backends/openssl/cmac.py | 8 ++-- .../hazmat/backends/openssl/hashes.py | 13 +++--- .../hazmat/backends/openssl/hmac.py | 15 +++--- src/cryptography/hazmat/primitives/cmac.py | 12 +++-- src/cryptography/hazmat/primitives/hashes.py | 46 ++++++++----------- src/cryptography/hazmat/primitives/hmac.py | 19 +++++--- 6 files changed, 56 insertions(+), 57 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/cmac.py b/src/cryptography/hazmat/backends/openssl/cmac.py index 9be316757414..a00c10cfeb85 100644 --- a/src/cryptography/hazmat/backends/openssl/cmac.py +++ b/src/cryptography/hazmat/backends/openssl/cmac.py @@ -51,11 +51,11 @@ def __init__(self, backend, algorithm, ctx=None): algorithm = utils.read_only_property("_algorithm") - def update(self, data): + def update(self, data: bytes) -> None: res = self._backend._lib.CMAC_Update(self._ctx, data, len(data)) self._backend.openssl_assert(res == 1) - def finalize(self): + def finalize(self) -> bytes: buf = self._backend._ffi.new("unsigned char[]", self._output_length) length = self._backend._ffi.new("size_t *", self._output_length) res = self._backend._lib.CMAC_Final(self._ctx, buf, length) @@ -65,7 +65,7 @@ def finalize(self): return self._backend._ffi.buffer(buf)[:] - def copy(self): + def copy(self) -> "_CMACContext": copied_ctx = self._backend._lib.CMAC_CTX_new() copied_ctx = self._backend._ffi.gc( copied_ctx, self._backend._lib.CMAC_CTX_free @@ -74,7 +74,7 @@ def copy(self): self._backend.openssl_assert(res == 1) return _CMACContext(self._backend, self._algorithm, ctx=copied_ctx) - def verify(self, signature): + def verify(self, signature: bytes) -> None: digest = self.finalize() if not constant_time.bytes_eq(digest, signature): raise InvalidSignature("Signature did not match digest.") diff --git a/src/cryptography/hazmat/backends/openssl/hashes.py b/src/cryptography/hazmat/backends/openssl/hashes.py index b14dffc7571c..823d24f91595 100644 --- a/src/cryptography/hazmat/backends/openssl/hashes.py +++ b/src/cryptography/hazmat/backends/openssl/hashes.py @@ -8,9 +8,8 @@ from cryptography.hazmat.primitives import hashes -@utils.register_interface(hashes.HashContext) -class _HashContext(object): - def __init__(self, backend, algorithm, ctx=None): +class _HashContext(hashes.HashContext): + def __init__(self, backend, algorithm: hashes.HashAlgorithm, ctx=None): self._algorithm = algorithm self._backend = backend @@ -37,7 +36,7 @@ def __init__(self, backend, algorithm, ctx=None): algorithm = utils.read_only_property("_algorithm") - def copy(self): + def copy(self) -> "_HashContext": copied_ctx = self._backend._lib.EVP_MD_CTX_new() copied_ctx = self._backend._ffi.gc( copied_ctx, self._backend._lib.EVP_MD_CTX_free @@ -46,14 +45,14 @@ def copy(self): self._backend.openssl_assert(res != 0) return _HashContext(self._backend, self.algorithm, ctx=copied_ctx) - def update(self, data): + def update(self, data: bytes) -> None: data_ptr = self._backend._ffi.from_buffer(data) res = self._backend._lib.EVP_DigestUpdate( self._ctx, data_ptr, len(data) ) self._backend.openssl_assert(res != 0) - def finalize(self): + def finalize(self) -> bytes: if isinstance(self.algorithm, hashes.ExtendableOutputFunction): # extendable output functions use a different finalize return self._finalize_xof() @@ -69,7 +68,7 @@ def finalize(self): ) return self._backend._ffi.buffer(buf)[: outlen[0]] - def _finalize_xof(self): + def _finalize_xof(self) -> bytes: buf = self._backend._ffi.new( "unsigned char[]", self.algorithm.digest_size ) diff --git a/src/cryptography/hazmat/backends/openssl/hmac.py b/src/cryptography/hazmat/backends/openssl/hmac.py index ea954c68c85b..e9e461300f7a 100644 --- a/src/cryptography/hazmat/backends/openssl/hmac.py +++ b/src/cryptography/hazmat/backends/openssl/hmac.py @@ -12,9 +12,10 @@ from cryptography.hazmat.primitives import constant_time, hashes -@utils.register_interface(hashes.HashContext) -class _HMACContext(object): - def __init__(self, backend, key, algorithm, ctx=None): +class _HMACContext(hashes.HashContext): + def __init__( + self, backend, key: bytes, algorithm: hashes.HashAlgorithm, ctx=None + ): self._algorithm = algorithm self._backend = backend @@ -41,7 +42,7 @@ def __init__(self, backend, key, algorithm, ctx=None): algorithm = utils.read_only_property("_algorithm") - def copy(self): + def copy(self) -> "_HMACContext": copied_ctx = self._backend._lib.HMAC_CTX_new() self._backend.openssl_assert(copied_ctx != self._backend._ffi.NULL) copied_ctx = self._backend._ffi.gc( @@ -53,12 +54,12 @@ def copy(self): self._backend, self._key, self.algorithm, ctx=copied_ctx ) - def update(self, data): + def update(self, data: bytes) -> None: data_ptr = self._backend._ffi.from_buffer(data) res = self._backend._lib.HMAC_Update(self._ctx, data_ptr, len(data)) self._backend.openssl_assert(res != 0) - def finalize(self): + def finalize(self) -> bytes: buf = self._backend._ffi.new( "unsigned char[]", self._backend._lib.EVP_MAX_MD_SIZE ) @@ -68,7 +69,7 @@ def finalize(self): self._backend.openssl_assert(outlen[0] == self.algorithm.digest_size) return self._backend._ffi.buffer(buf)[: outlen[0]] - def verify(self, signature): + def verify(self, signature: bytes) -> None: digest = self.finalize() if not constant_time.bytes_eq(digest, signature): raise InvalidSignature("Signature did not match digest.") diff --git a/src/cryptography/hazmat/primitives/cmac.py b/src/cryptography/hazmat/primitives/cmac.py index 48f8e331b235..1ebdb052c69d 100644 --- a/src/cryptography/hazmat/primitives/cmac.py +++ b/src/cryptography/hazmat/primitives/cmac.py @@ -15,7 +15,9 @@ class CMAC(object): - def __init__(self, algorithm, backend=None, ctx=None): + def __init__( + self, algorithm: ciphers.BlockCipherAlgorithm, backend=None, ctx=None + ): backend = _get_backend(backend) if not isinstance(backend, CMACBackend): raise UnsupportedAlgorithm( @@ -33,21 +35,21 @@ def __init__(self, algorithm, backend=None, ctx=None): else: self._ctx = ctx - def update(self, data): + def update(self, data: bytes) -> None: if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") utils._check_bytes("data", data) self._ctx.update(data) - def finalize(self): + def finalize(self) -> bytes: if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") digest = self._ctx.finalize() self._ctx = None return digest - def verify(self, signature): + def verify(self, signature: bytes) -> None: utils._check_bytes("signature", signature) if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") @@ -55,7 +57,7 @@ def verify(self, signature): ctx, self._ctx = self._ctx, None ctx.verify(signature) - def copy(self): + def copy(self) -> "CMAC": if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") return CMAC( diff --git a/src/cryptography/hazmat/primitives/hashes.py b/src/cryptography/hazmat/primitives/hashes.py index 3eaa89bd6939..b296f15969d4 100644 --- a/src/cryptography/hazmat/primitives/hashes.py +++ b/src/cryptography/hazmat/primitives/hashes.py @@ -2,7 +2,6 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. - import abc from cryptography import utils @@ -17,13 +16,13 @@ class HashAlgorithm(metaclass=abc.ABCMeta): @abc.abstractproperty - def name(self): + def name(self) -> str: """ A string naming this algorithm (e.g. "sha256", "md5"). """ @abc.abstractproperty - def digest_size(self): + def digest_size(self) -> int: """ The size of the resulting digest in bytes. """ @@ -31,25 +30,25 @@ def digest_size(self): class HashContext(metaclass=abc.ABCMeta): @abc.abstractproperty - def algorithm(self): + def algorithm(self) -> HashAlgorithm: """ A HashAlgorithm that will be used by this context. """ @abc.abstractmethod - def update(self, data): + def update(self, data: bytes) -> None: """ Processes the provided bytes through the hash. """ @abc.abstractmethod - def finalize(self): + def finalize(self) -> bytes: """ Finalizes the hash context and returns the hash digest as bytes. """ @abc.abstractmethod - def copy(self): + def copy(self) -> "HashContext": """ Return a HashContext that is a copy of the current context. """ @@ -61,9 +60,8 @@ class ExtendableOutputFunction(metaclass=abc.ABCMeta): """ -@utils.register_interface(HashContext) -class Hash(object): - def __init__(self, algorithm, backend=None, ctx=None): +class Hash(HashContext): + def __init__(self, algorithm: HashAlgorithm, backend=None, ctx=None): backend = _get_backend(backend) if not isinstance(backend, HashBackend): raise UnsupportedAlgorithm( @@ -84,20 +82,20 @@ def __init__(self, algorithm, backend=None, ctx=None): algorithm = utils.read_only_property("_algorithm") - def update(self, data): + def update(self, data: bytes) -> None: if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") utils._check_byteslike("data", data) self._ctx.update(data) - def copy(self): + def copy(self) -> "Hash": if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") return Hash( self.algorithm, backend=self._backend, ctx=self._ctx.copy() ) - def finalize(self): + def finalize(self) -> bytes: if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") digest = self._ctx.finalize() @@ -167,12 +165,10 @@ class SHA3_512(HashAlgorithm): # noqa: N801 digest_size = 64 -@utils.register_interface(HashAlgorithm) -@utils.register_interface(ExtendableOutputFunction) -class SHAKE128(object): +class SHAKE128(HashAlgorithm, ExtendableOutputFunction): name = "shake128" - def __init__(self, digest_size): + def __init__(self, digest_size: int): if not isinstance(digest_size, int): raise TypeError("digest_size must be an integer") @@ -184,12 +180,10 @@ def __init__(self, digest_size): digest_size = utils.read_only_property("_digest_size") -@utils.register_interface(HashAlgorithm) -@utils.register_interface(ExtendableOutputFunction) -class SHAKE256(object): +class SHAKE256(HashAlgorithm, ExtendableOutputFunction): name = "shake256" - def __init__(self, digest_size): + def __init__(self, digest_size: int): if not isinstance(digest_size, int): raise TypeError("digest_size must be an integer") @@ -207,14 +201,13 @@ class MD5(HashAlgorithm): block_size = 64 -@utils.register_interface(HashAlgorithm) -class BLAKE2b(object): +class BLAKE2b(HashAlgorithm): name = "blake2b" _max_digest_size = 64 _min_digest_size = 1 block_size = 128 - def __init__(self, digest_size): + def __init__(self, digest_size: int): if digest_size != 64: raise ValueError("Digest size must be 64") @@ -224,14 +217,13 @@ def __init__(self, digest_size): digest_size = utils.read_only_property("_digest_size") -@utils.register_interface(HashAlgorithm) -class BLAKE2s(object): +class BLAKE2s(HashAlgorithm): name = "blake2s" block_size = 64 _max_digest_size = 32 _min_digest_size = 1 - def __init__(self, digest_size): + def __init__(self, digest_size: int): if digest_size != 32: raise ValueError("Digest size must be 32") diff --git a/src/cryptography/hazmat/primitives/hmac.py b/src/cryptography/hazmat/primitives/hmac.py index c417a42941b8..5911925b8bdc 100644 --- a/src/cryptography/hazmat/primitives/hmac.py +++ b/src/cryptography/hazmat/primitives/hmac.py @@ -14,9 +14,14 @@ from cryptography.hazmat.primitives import hashes -@utils.register_interface(hashes.HashContext) -class HMAC(object): - def __init__(self, key, algorithm, backend=None, ctx=None): +class HMAC(hashes.HashContext): + def __init__( + self, + key: bytes, + algorithm: hashes.HashAlgorithm, + backend=None, + ctx=None, + ): backend = _get_backend(backend) if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( @@ -37,13 +42,13 @@ def __init__(self, key, algorithm, backend=None, ctx=None): algorithm = utils.read_only_property("_algorithm") - def update(self, data): + def update(self, data: bytes) -> None: if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") utils._check_byteslike("data", data) self._ctx.update(data) - def copy(self): + def copy(self) -> "HMAC": if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") return HMAC( @@ -53,14 +58,14 @@ def copy(self): ctx=self._ctx.copy(), ) - def finalize(self): + def finalize(self) -> bytes: if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") digest = self._ctx.finalize() self._ctx = None return digest - def verify(self, signature): + def verify(self, signature: bytes) -> None: utils._check_bytes("signature", signature) if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") From 35606c23b0b556bc19b177b4b5b9662090c57882 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 30 Jan 2021 15:52:56 -0600 Subject: [PATCH 0068/2380] add typing to keywrap (#5715) --- src/cryptography/hazmat/primitives/keywrap.py | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/cryptography/hazmat/primitives/keywrap.py b/src/cryptography/hazmat/primitives/keywrap.py index 230cc2e6a983..52d49d35f2eb 100644 --- a/src/cryptography/hazmat/primitives/keywrap.py +++ b/src/cryptography/hazmat/primitives/keywrap.py @@ -4,6 +4,7 @@ import struct +import typing from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.primitives.ciphers import Cipher @@ -12,7 +13,9 @@ from cryptography.hazmat.primitives.constant_time import bytes_eq -def _wrap_core(wrapping_key, a, r, backend): +def _wrap_core( + wrapping_key: bytes, a: bytes, r: typing.List[bytes], backend +) -> bytes: # RFC 3394 Key Wrap - 2.2.1 (index method) encryptor = Cipher(AES(wrapping_key), ECB(), backend).encryptor() n = len(r) @@ -33,7 +36,9 @@ def _wrap_core(wrapping_key, a, r, backend): return a + b"".join(r) -def aes_key_wrap(wrapping_key, key_to_wrap, backend=None): +def aes_key_wrap( + wrapping_key: bytes, key_to_wrap: bytes, backend=None +) -> bytes: backend = _get_backend(backend) if len(wrapping_key) not in [16, 24, 32]: raise ValueError("The wrapping key must be a valid AES key length") @@ -49,7 +54,9 @@ def aes_key_wrap(wrapping_key, key_to_wrap, backend=None): return _wrap_core(wrapping_key, a, r, backend) -def _unwrap_core(wrapping_key, a, r, backend): +def _unwrap_core( + wrapping_key: bytes, a: bytes, r: typing.List[bytes], backend +) -> typing.Tuple[bytes, typing.List[bytes]]: # Implement RFC 3394 Key Unwrap - 2.2.2 (index method) decryptor = Cipher(AES(wrapping_key), ECB(), backend).decryptor() n = len(r) @@ -72,7 +79,9 @@ def _unwrap_core(wrapping_key, a, r, backend): return a, r -def aes_key_wrap_with_padding(wrapping_key, key_to_wrap, backend=None): +def aes_key_wrap_with_padding( + wrapping_key: bytes, key_to_wrap: bytes, backend=None +) -> bytes: backend = _get_backend(backend) if len(wrapping_key) not in [16, 24, 32]: raise ValueError("The wrapping key must be a valid AES key length") @@ -92,7 +101,9 @@ def aes_key_wrap_with_padding(wrapping_key, key_to_wrap, backend=None): return _wrap_core(wrapping_key, aiv, r, backend) -def aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend=None): +def aes_key_unwrap_with_padding( + wrapping_key: bytes, wrapped_key: bytes, backend=None +) -> bytes: backend = _get_backend(backend) if len(wrapped_key) < 16: raise InvalidUnwrap("Must be at least 16 bytes") @@ -135,7 +146,9 @@ def aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend=None): return data[:-b] -def aes_key_unwrap(wrapping_key, wrapped_key, backend=None): +def aes_key_unwrap( + wrapping_key: bytes, wrapped_key: bytes, backend=None +) -> bytes: backend = _get_backend(backend) if len(wrapped_key) < 24: raise InvalidUnwrap("Must be at least 24 bytes") From 83c598ac3df8b06f4f68b0cc845de1fde0e454a3 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 30 Jan 2021 16:33:12 -0600 Subject: [PATCH 0069/2380] add typing to padding and constant time modules (#5714) --- .../hazmat/primitives/constant_time.py | 2 +- src/cryptography/hazmat/primitives/padding.py | 83 +++++++++++-------- 2 files changed, 51 insertions(+), 34 deletions(-) diff --git a/src/cryptography/hazmat/primitives/constant_time.py b/src/cryptography/hazmat/primitives/constant_time.py index 49b0a642e500..9a773f86d58a 100644 --- a/src/cryptography/hazmat/primitives/constant_time.py +++ b/src/cryptography/hazmat/primitives/constant_time.py @@ -6,7 +6,7 @@ import hmac -def bytes_eq(a, b): +def bytes_eq(a: bytes, b: bytes): if not isinstance(a, bytes) or not isinstance(b, bytes): raise TypeError("a and b must be bytes.") diff --git a/src/cryptography/hazmat/primitives/padding.py b/src/cryptography/hazmat/primitives/padding.py index cded31925c05..afed91341c0a 100644 --- a/src/cryptography/hazmat/primitives/padding.py +++ b/src/cryptography/hazmat/primitives/padding.py @@ -4,6 +4,7 @@ import abc +import typing from cryptography import utils from cryptography.exceptions import AlreadyFinalized @@ -12,19 +13,19 @@ class PaddingContext(metaclass=abc.ABCMeta): @abc.abstractmethod - def update(self, data): + def update(self, data: bytes) -> bytes: """ Pads the provided bytes and returns any available data as bytes. """ @abc.abstractmethod - def finalize(self): + def finalize(self) -> bytes: """ Finalize the padding, returns bytes. """ -def _byte_padding_check(block_size): +def _byte_padding_check(block_size: int) -> None: if not (0 <= block_size <= 2040): raise ValueError("block_size must be in range(0, 2041).") @@ -32,7 +33,9 @@ def _byte_padding_check(block_size): raise ValueError("block_size must be a multiple of 8.") -def _byte_padding_update(buffer_, data, block_size): +def _byte_padding_update( + buffer_: typing.Optional[bytes], data: bytes, block_size: int +): if buffer_ is None: raise AlreadyFinalized("Context was already finalized.") @@ -48,7 +51,11 @@ def _byte_padding_update(buffer_, data, block_size): return buffer_, result -def _byte_padding_pad(buffer_, block_size, paddingfn): +def _byte_padding_pad( + buffer_: typing.Optional[bytes], + block_size: int, + paddingfn: typing.Callable[[int], bytes], +): if buffer_ is None: raise AlreadyFinalized("Context was already finalized.") @@ -56,7 +63,9 @@ def _byte_padding_pad(buffer_, block_size, paddingfn): return buffer_ + paddingfn(pad_size) -def _byte_unpadding_update(buffer_, data, block_size): +def _byte_unpadding_update( + buffer_: typing.Optional[bytes], data: bytes, block_size: int +): if buffer_ is None: raise AlreadyFinalized("Context was already finalized.") @@ -72,7 +81,11 @@ def _byte_unpadding_update(buffer_, data, block_size): return buffer_, result -def _byte_unpadding_check(buffer_, block_size, checkfn): +def _byte_unpadding_check( + buffer_: typing.Optional[bytes], + block_size: int, + checkfn: typing.Callable[[bytes, int], int], +): if buffer_ is None: raise AlreadyFinalized("Context was already finalized.") @@ -89,7 +102,7 @@ def _byte_unpadding_check(buffer_, block_size, checkfn): class PKCS7(object): - def __init__(self, block_size): + def __init__(self, block_size: int): _byte_padding_check(block_size) self.block_size = block_size @@ -100,23 +113,24 @@ def unpadder(self): return _PKCS7UnpaddingContext(self.block_size) -@utils.register_interface(PaddingContext) -class _PKCS7PaddingContext(object): - def __init__(self, block_size): +class _PKCS7PaddingContext(PaddingContext): + _buffer: typing.Optional[bytes] + + 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): + def update(self, data: bytes) -> bytes: self._buffer, result = _byte_padding_update( self._buffer, data, self.block_size ) return result - def _padding(self, size): + def _padding(self, size: int) -> bytes: return bytes([size]) * size - def finalize(self): + def finalize(self) -> bytes: result = _byte_padding_pad( self._buffer, self.block_size, self._padding ) @@ -124,20 +138,21 @@ def finalize(self): return result -@utils.register_interface(PaddingContext) -class _PKCS7UnpaddingContext(object): - def __init__(self, block_size): +class _PKCS7UnpaddingContext(PaddingContext): + _buffer: typing.Optional[bytes] + + 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): + def update(self, data: bytes) -> bytes: self._buffer, result = _byte_unpadding_update( self._buffer, data, self.block_size ) return result - def finalize(self): + def finalize(self) -> bytes: result = _byte_unpadding_check( self._buffer, self.block_size, lib.Cryptography_check_pkcs7_padding ) @@ -146,34 +161,35 @@ def finalize(self): class ANSIX923(object): - def __init__(self, block_size): + def __init__(self, block_size: int): _byte_padding_check(block_size) self.block_size = block_size - def padder(self): + def padder(self) -> PaddingContext: return _ANSIX923PaddingContext(self.block_size) - def unpadder(self): + def unpadder(self) -> PaddingContext: return _ANSIX923UnpaddingContext(self.block_size) -@utils.register_interface(PaddingContext) -class _ANSIX923PaddingContext(object): - def __init__(self, block_size): +class _ANSIX923PaddingContext(PaddingContext): + _buffer: typing.Optional[bytes] + + 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): + def update(self, data: bytes) -> bytes: self._buffer, result = _byte_padding_update( self._buffer, data, self.block_size ) return result - def _padding(self, size): + def _padding(self, size: int) -> bytes: return bytes([0]) * (size - 1) + bytes([size]) - def finalize(self): + def finalize(self) -> bytes: result = _byte_padding_pad( self._buffer, self.block_size, self._padding ) @@ -181,20 +197,21 @@ def finalize(self): return result -@utils.register_interface(PaddingContext) -class _ANSIX923UnpaddingContext(object): - def __init__(self, block_size): +class _ANSIX923UnpaddingContext(PaddingContext): + _buffer: typing.Optional[bytes] + + 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): + def update(self, data: bytes) -> bytes: self._buffer, result = _byte_unpadding_update( self._buffer, data, self.block_size ) return result - def finalize(self): + def finalize(self) -> bytes: result = _byte_unpadding_check( self._buffer, self.block_size, From f16bff2cbd2855f0becb27724334e4bdb0679247 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 30 Jan 2021 17:44:14 -0500 Subject: [PATCH 0070/2380] Apply type annotations to x509 ct and ocsp (#5712) --- docs/x509/ocsp.rst | 8 +- src/cryptography/fernet.py | 4 +- .../hazmat/backends/openssl/ocsp.py | 76 ++-- .../hazmat/backends/openssl/x509.py | 6 +- src/cryptography/x509/base.py | 4 +- .../x509/certificate_transparency.py | 9 +- src/cryptography/x509/extensions.py | 9 +- src/cryptography/x509/general_name.py | 77 ++-- src/cryptography/x509/name.py | 52 +-- src/cryptography/x509/ocsp.py | 395 +++++++++--------- 10 files changed, 338 insertions(+), 302 deletions(-) diff --git a/docs/x509/ocsp.rst b/docs/x509/ocsp.rst index 0c2d07aef852..6a3e1e7064f2 100644 --- a/docs/x509/ocsp.rst +++ b/docs/x509/ocsp.rst @@ -151,11 +151,11 @@ Creating Requests :class:`~cryptography.hazmat.primitives.hashes.SHA384`, and :class:`~cryptography.hazmat.primitives.hashes.SHA512` are allowed. - .. method:: add_extension(extension, critical) + .. method:: add_extension(extval, critical) Adds an extension to the request. - :param extension: An extension conforming to the + :param extval: An extension conforming to the :class:`~cryptography.x509.ExtensionType` interface. :param critical: Set to ``True`` if the extension must be understood and @@ -274,11 +274,11 @@ Creating Responses :attr:`~cryptography.x509.ocsp.OCSPResponderEncoding.HASH` or :attr:`~cryptography.x509.ocsp.OCSPResponderEncoding.NAME`. - .. method:: add_extension(extension, critical) + .. method:: add_extension(extval, critical) Adds an extension to the response. - :param extension: An extension conforming to the + :param extval: An extension conforming to the :class:`~cryptography.x509.ExtensionType` interface. :param critical: Set to ``True`` if the extension must be understood and diff --git a/src/cryptography/fernet.py b/src/cryptography/fernet.py index c9464c5ad436..57772fee424a 100644 --- a/src/cryptography/fernet.py +++ b/src/cryptography/fernet.py @@ -157,8 +157,8 @@ def _decrypt_data( class MultiFernet(object): - def __init__(self, fernets_it: typing.Iterator[Fernet]): - fernets = list(fernets_it) + def __init__(self, fernets: typing.Iterable[Fernet]): + fernets = list(fernets) if not fernets: raise ValueError( "MultiFernet requires at least one Fernet instance" diff --git a/src/cryptography/hazmat/backends/openssl/ocsp.py b/src/cryptography/hazmat/backends/openssl/ocsp.py index 231794c6bd24..9138e78dba62 100644 --- a/src/cryptography/hazmat/backends/openssl/ocsp.py +++ b/src/cryptography/hazmat/backends/openssl/ocsp.py @@ -2,6 +2,8 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. +import datetime +import typing from cryptography import utils, x509 from cryptography.exceptions import UnsupportedAlgorithm @@ -14,7 +16,7 @@ _parse_asn1_generalized_time, ) from cryptography.hazmat.backends.openssl.x509 import _Certificate -from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives import hashes, serialization from cryptography.x509.ocsp import ( OCSPCertStatus, OCSPRequest, @@ -84,8 +86,7 @@ def _hash_algorithm(backend, cert_id): ) -@utils.register_interface(OCSPResponse) -class _OCSPResponse(object): +class _OCSPResponse(OCSPResponse): def __init__(self, backend, ocsp_response): self._backend = backend self._ocsp_response = ocsp_response @@ -120,7 +121,7 @@ def __init__(self, backend, ocsp_response): response_status = utils.read_only_property("_status") - def _requires_successful_response(self): + def _requires_successful_response(self) -> None: if self.response_status != OCSPResponseStatus.SUCCESSFUL: raise ValueError( "OCSP response status is not successful so the property " @@ -128,7 +129,7 @@ def _requires_successful_response(self): ) @property - def signature_algorithm_oid(self): + def signature_algorithm_oid(self) -> x509.ObjectIdentifier: self._requires_successful_response() alg = self._backend._lib.OCSP_resp_get0_tbs_sigalg(self._basic) self._backend.openssl_assert(alg != self._backend._ffi.NULL) @@ -136,7 +137,9 @@ def signature_algorithm_oid(self): return x509.ObjectIdentifier(oid) @property - def signature_hash_algorithm(self): + def signature_hash_algorithm( + self, + ) -> typing.Optional[hashes.HashAlgorithm]: self._requires_successful_response() oid = self.signature_algorithm_oid try: @@ -147,14 +150,14 @@ def signature_hash_algorithm(self): ) @property - def signature(self): + def signature(self) -> bytes: self._requires_successful_response() sig = self._backend._lib.OCSP_resp_get0_signature(self._basic) self._backend.openssl_assert(sig != self._backend._ffi.NULL) return _asn1_string_to_bytes(self._backend, sig) @property - def tbs_response_bytes(self): + def tbs_response_bytes(self) -> bytes: self._requires_successful_response() respdata = self._backend._lib.OCSP_resp_get0_respdata(self._basic) self._backend.openssl_assert(respdata != self._backend._ffi.NULL) @@ -168,25 +171,25 @@ def tbs_response_bytes(self): return self._backend._ffi.buffer(pp[0], res)[:] @property - def certificates(self): + def certificates(self) -> typing.List[x509.Certificate]: self._requires_successful_response() sk_x509 = self._backend._lib.OCSP_resp_get0_certs(self._basic) num = self._backend._lib.sk_X509_num(sk_x509) - certs = [] + certs: typing.List[x509.Certificate] = [] for i in range(num): - x509 = self._backend._lib.sk_X509_value(sk_x509, i) - self._backend.openssl_assert(x509 != self._backend._ffi.NULL) - cert = _Certificate(self._backend, x509) + x509_ptr = self._backend._lib.sk_X509_value(sk_x509, i) + self._backend.openssl_assert(x509_ptr != self._backend._ffi.NULL) + cert = _Certificate(self._backend, x509_ptr) # We need to keep the OCSP response that the certificate came from # alive until the Certificate object itself goes out of scope, so # we give it a private reference. - cert._ocsp_resp = self + cert._ocsp_resp_ref = self certs.append(cert) return certs @property - def responder_key_hash(self): + def responder_key_hash(self) -> typing.Optional[bytes]: self._requires_successful_response() _, asn1_string = self._responder_key_name() if asn1_string == self._backend._ffi.NULL: @@ -195,7 +198,7 @@ def responder_key_hash(self): return _asn1_string_to_bytes(self._backend, asn1_string) @property - def responder_name(self): + def responder_name(self) -> typing.Optional[x509.Name]: self._requires_successful_response() x509_name, _ = self._responder_key_name() if x509_name == self._backend._ffi.NULL: @@ -213,7 +216,7 @@ def _responder_key_name(self): return x509_name[0], asn1_string[0] @property - def produced_at(self): + def produced_at(self) -> datetime.datetime: self._requires_successful_response() produced_at = self._backend._lib.OCSP_resp_get0_produced_at( self._basic @@ -221,7 +224,7 @@ def produced_at(self): return _parse_asn1_generalized_time(self._backend, produced_at) @property - def certificate_status(self): + def certificate_status(self) -> OCSPCertStatus: self._requires_successful_response() status = self._backend._lib.OCSP_single_get0_status( self._single, @@ -234,7 +237,7 @@ def certificate_status(self): return _CERT_STATUS_TO_ENUM[status] @property - def revocation_time(self): + def revocation_time(self) -> typing.Optional[datetime.datetime]: self._requires_successful_response() if self.certificate_status is not OCSPCertStatus.REVOKED: return None @@ -251,7 +254,7 @@ def revocation_time(self): return _parse_asn1_generalized_time(self._backend, asn1_time[0]) @property - def revocation_reason(self): + def revocation_reason(self) -> typing.Optional[x509.ReasonFlags]: self._requires_successful_response() if self.certificate_status is not OCSPCertStatus.REVOKED: return None @@ -274,7 +277,7 @@ def revocation_reason(self): return _CRL_ENTRY_REASON_CODE_TO_ENUM[reason_ptr[0]] @property - def this_update(self): + def this_update(self) -> datetime.datetime: self._requires_successful_response() asn1_time = self._backend._ffi.new("ASN1_GENERALIZEDTIME **") self._backend._lib.OCSP_single_get0_status( @@ -288,7 +291,7 @@ def this_update(self): return _parse_asn1_generalized_time(self._backend, asn1_time[0]) @property - def next_update(self): + def next_update(self) -> typing.Optional[datetime.datetime]: self._requires_successful_response() asn1_time = self._backend._ffi.new("ASN1_GENERALIZEDTIME **") self._backend._lib.OCSP_single_get0_status( @@ -304,36 +307,36 @@ def next_update(self): return None @property - def issuer_key_hash(self): + def issuer_key_hash(self) -> bytes: self._requires_successful_response() return _issuer_key_hash(self._backend, self._cert_id) @property - def issuer_name_hash(self): + def issuer_name_hash(self) -> bytes: self._requires_successful_response() return _issuer_name_hash(self._backend, self._cert_id) @property - def hash_algorithm(self): + def hash_algorithm(self) -> hashes.HashAlgorithm: self._requires_successful_response() return _hash_algorithm(self._backend, self._cert_id) @property - def serial_number(self): + def serial_number(self) -> int: self._requires_successful_response() return _serial_number(self._backend, self._cert_id) @utils.cached_property - def extensions(self): + def extensions(self) -> x509.Extensions: self._requires_successful_response() return self._backend._ocsp_basicresp_ext_parser.parse(self._basic) @utils.cached_property - def single_extensions(self): + def single_extensions(self) -> x509.Extensions: self._requires_successful_response() return self._backend._ocsp_singleresp_ext_parser.parse(self._single) - def public_bytes(self, encoding): + def public_bytes(self, encoding: serialization.Encoding) -> bytes: if encoding is not serialization.Encoding.DER: raise ValueError("The only allowed encoding value is Encoding.DER") @@ -345,8 +348,7 @@ def public_bytes(self, encoding): return self._backend._read_mem_bio(bio) -@utils.register_interface(OCSPRequest) -class _OCSPRequest(object): +class _OCSPRequest(OCSPRequest): def __init__(self, backend, ocsp_request): if backend._lib.OCSP_request_onereq_count(ocsp_request) > 1: raise NotImplementedError( @@ -362,26 +364,26 @@ def __init__(self, backend, ocsp_request): self._backend.openssl_assert(self._cert_id != self._backend._ffi.NULL) @property - def issuer_key_hash(self): + def issuer_key_hash(self) -> bytes: return _issuer_key_hash(self._backend, self._cert_id) @property - def issuer_name_hash(self): + def issuer_name_hash(self) -> bytes: return _issuer_name_hash(self._backend, self._cert_id) @property - def serial_number(self): + def serial_number(self) -> int: return _serial_number(self._backend, self._cert_id) @property - def hash_algorithm(self): + def hash_algorithm(self) -> hashes.HashAlgorithm: return _hash_algorithm(self._backend, self._cert_id) @utils.cached_property - def extensions(self): + def extensions(self) -> x509.Extensions: return self._backend._ocsp_req_ext_parser.parse(self._ocsp_request) - def public_bytes(self, encoding): + def public_bytes(self, encoding: serialization.Encoding) -> bytes: if encoding is not serialization.Encoding.DER: raise ValueError("The only allowed encoding value is Encoding.DER") diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index f460ed2da4cb..07a1dd8a4722 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -26,8 +26,10 @@ from cryptography.x509.name import _ASN1Type -@utils.register_interface(x509.Certificate) -class _Certificate(object): +class _Certificate(x509.Certificate): + # Keep-alive reference used by OCSP + _ocsp_resp_ref: typing.Any + def __init__(self, backend, x509_cert): self._backend = backend self._x509 = x509_cert diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index c17fff8cee01..5c5e6c6daaad 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -140,7 +140,9 @@ def subject(self) -> Name: """ @abc.abstractproperty - def signature_hash_algorithm(self) -> hashes.HashAlgorithm: + def signature_hash_algorithm( + self, + ) -> typing.Optional[hashes.HashAlgorithm]: """ Returns a HashAlgorithm corresponding to the type of the digest signed in the certificate. diff --git a/src/cryptography/x509/certificate_transparency.py b/src/cryptography/x509/certificate_transparency.py index 44e18803d9d6..d51bee92effc 100644 --- a/src/cryptography/x509/certificate_transparency.py +++ b/src/cryptography/x509/certificate_transparency.py @@ -4,6 +4,7 @@ import abc +import datetime from enum import Enum @@ -18,25 +19,25 @@ class Version(Enum): class SignedCertificateTimestamp(metaclass=abc.ABCMeta): @abc.abstractproperty - def version(self): + def version(self) -> Version: """ Returns the SCT version. """ @abc.abstractproperty - def log_id(self): + def log_id(self) -> bytes: """ Returns an identifier indicating which log this SCT is for. """ @abc.abstractproperty - def timestamp(self): + def timestamp(self) -> datetime.datetime: """ Returns the timestamp for this SCT. """ @abc.abstractproperty - def entry_type(self): + def entry_type(self) -> LogEntryType: """ Returns whether this is an SCT for a certificate or pre-certificate. """ diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index dfad69770a0c..0602908e480d 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -7,6 +7,7 @@ import datetime import hashlib import ipaddress +import typing from enum import Enum from cryptography import utils @@ -86,27 +87,27 @@ def getitem_method(self, idx): class DuplicateExtension(Exception): - def __init__(self, msg, oid): + def __init__(self, msg: str, oid: ObjectIdentifier): super(DuplicateExtension, self).__init__(msg) self.oid = oid class ExtensionNotFound(Exception): - def __init__(self, msg, oid): + def __init__(self, msg: str, oid: ObjectIdentifier): super(ExtensionNotFound, self).__init__(msg) self.oid = oid class ExtensionType(metaclass=abc.ABCMeta): @abc.abstractproperty - def oid(self): + def oid(self) -> ObjectIdentifier: """ Returns the oid associated with the given extension type. """ class Extensions(object): - def __init__(self, extensions): + def __init__(self, extensions: typing.List[ExtensionType]): self._extensions = extensions def get_extension_for_oid(self, oid): diff --git a/src/cryptography/x509/general_name.py b/src/cryptography/x509/general_name.py index 7c1306e2665c..6683e9313ce8 100644 --- a/src/cryptography/x509/general_name.py +++ b/src/cryptography/x509/general_name.py @@ -5,6 +5,7 @@ import abc import ipaddress +import typing from email.utils import parseaddr from cryptography import utils @@ -41,7 +42,7 @@ def value(self): @utils.register_interface(GeneralName) class RFC822Name(object): - def __init__(self, value): + def __init__(self, value: str): if isinstance(value, str): try: value.encode("ascii") @@ -70,25 +71,25 @@ def _init_without_validation(cls, value): instance._value = value return instance - def __repr__(self): + def __repr__(self) -> str: return "".format(self.value) - def __eq__(self, other): + def __eq__(self, other: object) -> bool: if not isinstance(other, RFC822Name): return NotImplemented return self.value == other.value - def __ne__(self, other): + def __ne__(self, other: object) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(self.value) @utils.register_interface(GeneralName) class DNSName(object): - def __init__(self, value): + def __init__(self, value: str): if isinstance(value, str): try: value.encode("ascii") @@ -114,22 +115,22 @@ def _init_without_validation(cls, value): def __repr__(self): return "".format(self.value) - def __eq__(self, other): + def __eq__(self, other: object) -> bool: if not isinstance(other, DNSName): return NotImplemented return self.value == other.value - def __ne__(self, other): + def __ne__(self, other: object) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(self.value) @utils.register_interface(GeneralName) class UniformResourceIdentifier(object): - def __init__(self, value): + def __init__(self, value: str): if isinstance(value, str): try: value.encode("ascii") @@ -152,25 +153,25 @@ def _init_without_validation(cls, value): instance._value = value return instance - def __repr__(self): + def __repr__(self) -> str: return "".format(self.value) - def __eq__(self, other): + def __eq__(self, other: object) -> bool: if not isinstance(other, UniformResourceIdentifier): return NotImplemented return self.value == other.value - def __ne__(self, other): + def __ne__(self, other: object) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(self.value) @utils.register_interface(GeneralName) class DirectoryName(object): - def __init__(self, value): + def __init__(self, value: Name): if not isinstance(value, Name): raise TypeError("value must be a Name") @@ -178,25 +179,25 @@ def __init__(self, value): value = utils.read_only_property("_value") - def __repr__(self): + def __repr__(self) -> str: return "".format(self.value) - def __eq__(self, other): + def __eq__(self, other: object) -> bool: if not isinstance(other, DirectoryName): return NotImplemented return self.value == other.value - def __ne__(self, other): + def __ne__(self, other: object) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(self.value) @utils.register_interface(GeneralName) class RegisteredID(object): - def __init__(self, value): + def __init__(self, value: ObjectIdentifier): if not isinstance(value, ObjectIdentifier): raise TypeError("value must be an ObjectIdentifier") @@ -204,25 +205,33 @@ def __init__(self, value): value = utils.read_only_property("_value") - def __repr__(self): + def __repr__(self) -> str: return "".format(self.value) - def __eq__(self, other): + def __eq__(self, other: object) -> bool: if not isinstance(other, RegisteredID): return NotImplemented return self.value == other.value - def __ne__(self, other): + def __ne__(self, other: object) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(self.value) @utils.register_interface(GeneralName) class IPAddress(object): - def __init__(self, value): + def __init__( + self, + value: typing.Union[ + ipaddress.IPv4Address, + ipaddress.IPv6Address, + ipaddress.IPv4Network, + ipaddress.IPv6Network, + ], + ): if not isinstance( value, ( @@ -242,25 +251,25 @@ def __init__(self, value): value = utils.read_only_property("_value") - def __repr__(self): + def __repr__(self) -> str: return "".format(self.value) - def __eq__(self, other): + def __eq__(self, other: object) -> bool: if not isinstance(other, IPAddress): return NotImplemented return self.value == other.value - def __ne__(self, other): + def __ne__(self, other: object) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(self.value) @utils.register_interface(GeneralName) class OtherName(object): - def __init__(self, type_id, value): + def __init__(self, type_id: ObjectIdentifier, value: bytes): if not isinstance(type_id, ObjectIdentifier): raise TypeError("type_id must be an ObjectIdentifier") if not isinstance(value, bytes): @@ -272,19 +281,19 @@ def __init__(self, type_id, value): type_id = utils.read_only_property("_type_id") value = utils.read_only_property("_value") - def __repr__(self): + def __repr__(self) -> str: return "".format( self.type_id, self.value ) - def __eq__(self, other): + def __eq__(self, other: object) -> bool: if not isinstance(other, OtherName): return NotImplemented return self.type_id == other.type_id and self.value == other.value - def __ne__(self, other): + def __ne__(self, other: object) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash((self.type_id, self.value)) diff --git a/src/cryptography/x509/name.py b/src/cryptography/x509/name.py index 54439ed41516..c183160e0aca 100644 --- a/src/cryptography/x509/name.py +++ b/src/cryptography/x509/name.py @@ -2,7 +2,7 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. - +import typing from enum import Enum from cryptography import utils @@ -74,7 +74,7 @@ def _escape_dn_value(val): class NameAttribute(object): - def __init__(self, oid, value, _type=_SENTINEL): + def __init__(self, oid: ObjectIdentifier, value: str, _type=_SENTINEL): if not isinstance(oid, ObjectIdentifier): raise TypeError( "oid argument must be an ObjectIdentifier instance." @@ -111,7 +111,7 @@ def __init__(self, oid, value, _type=_SENTINEL): oid = utils.read_only_property("_oid") value = utils.read_only_property("_value") - def rfc4514_string(self): + def rfc4514_string(self) -> str: """ Format as RFC4514 Distinguished Name string. @@ -121,24 +121,24 @@ def rfc4514_string(self): key = _NAMEOID_TO_NAME.get(self.oid, self.oid.dotted_string) return "%s=%s" % (key, _escape_dn_value(self.value)) - def __eq__(self, other): + def __eq__(self, other: object) -> bool: if not isinstance(other, NameAttribute): return NotImplemented return self.oid == other.oid and self.value == other.value - def __ne__(self, other): + def __ne__(self, other: object) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash((self.oid, self.value)) - def __repr__(self): + def __repr__(self) -> str: return "".format(self) class RelativeDistinguishedName(object): - def __init__(self, attributes): + def __init__(self, attributes: typing.Iterable[NameAttribute]): attributes = list(attributes) if not attributes: raise ValueError("a relative distinguished name cannot be empty") @@ -152,10 +152,10 @@ def __init__(self, attributes): if len(self._attribute_set) != len(attributes): raise ValueError("duplicate attributes are not allowed") - def get_attributes_for_oid(self, oid): + def get_attributes_for_oid(self, oid) -> typing.List[NameAttribute]: return [i for i in self if i.oid == oid] - def rfc4514_string(self): + def rfc4514_string(self) -> str: """ Format as RFC4514 Distinguished Name string. @@ -164,25 +164,25 @@ def rfc4514_string(self): """ return "+".join(attr.rfc4514_string() for attr in self._attributes) - def __eq__(self, other): + def __eq__(self, other: object) -> bool: if not isinstance(other, RelativeDistinguishedName): return NotImplemented return self._attribute_set == other._attribute_set - def __ne__(self, other): + def __ne__(self, other: object) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(self._attribute_set) - def __iter__(self): + def __iter__(self) -> typing.Iterator[NameAttribute]: return iter(self._attributes) - def __len__(self): + def __len__(self) -> int: return len(self._attributes) - def __repr__(self): + def __repr__(self) -> str: return "".format(self.rfc4514_string()) @@ -201,7 +201,7 @@ def __init__(self, attributes): " or a list RelativeDistinguishedName" ) - def rfc4514_string(self): + def rfc4514_string(self) -> str: """ Format as RFC4514 Distinguished Name string. For example 'CN=foobar.com,O=Foo Corp,C=US' @@ -216,39 +216,39 @@ def rfc4514_string(self): attr.rfc4514_string() for attr in reversed(self._attributes) ) - def get_attributes_for_oid(self, oid): + def get_attributes_for_oid(self, oid) -> typing.Iterable[NameAttribute]: return [i for i in self if i.oid == oid] @property - def rdns(self): + def rdns(self) -> typing.Iterable[RelativeDistinguishedName]: return self._attributes - def public_bytes(self, backend=None): + def public_bytes(self, backend=None) -> bytes: backend = _get_backend(backend) return backend.x509_name_bytes(self) - def __eq__(self, other): + def __eq__(self, other: object) -> bool: if not isinstance(other, Name): return NotImplemented return self._attributes == other._attributes - def __ne__(self, other): + def __ne__(self, other: object) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: # TODO: this is relatively expensive, if this looks like a bottleneck # for you, consider optimizing! return hash(tuple(self._attributes)) - def __iter__(self): + def __iter__(self) -> typing.Iterator[NameAttribute]: for rdn in self._attributes: for ava in rdn: yield ava - def __len__(self): + def __len__(self) -> int: return sum(len(rdn) for rdn in self._attributes) - def __repr__(self): + def __repr__(self) -> str: rdns = ",".join(attr.rfc4514_string() for attr in self._attributes) return "".format(rdns) diff --git a/src/cryptography/x509/ocsp.py b/src/cryptography/x509/ocsp.py index 5d137d697226..4d4992060f07 100644 --- a/src/cryptography/x509/ocsp.py +++ b/src/cryptography/x509/ocsp.py @@ -5,12 +5,14 @@ import abc import datetime +import typing from enum import Enum from cryptography import x509 -from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives import hashes, serialization from cryptography.x509.base import ( _EARLIEST_UTC_TIME, + _PRIVATE_KEY_TYPES, _convert_to_naive_utc_time, _reject_duplicate_extension, ) @@ -65,55 +67,6 @@ class OCSPCertStatus(Enum): _CERT_STATUS_TO_ENUM = {x.value: x for x in OCSPCertStatus} -def load_der_ocsp_request(data): - from cryptography.hazmat.backends.openssl.backend import backend - - return backend.load_der_ocsp_request(data) - - -def load_der_ocsp_response(data): - from cryptography.hazmat.backends.openssl.backend import backend - - return backend.load_der_ocsp_response(data) - - -class OCSPRequestBuilder(object): - def __init__(self, request=None, extensions=[]): - self._request = request - self._extensions = extensions - - def add_certificate(self, cert, issuer, algorithm): - if self._request is not None: - raise ValueError("Only one certificate can be added to a request") - - _verify_algorithm(algorithm) - if not isinstance(cert, x509.Certificate) or not isinstance( - issuer, x509.Certificate - ): - raise TypeError("cert and issuer must be a Certificate") - - return OCSPRequestBuilder((cert, issuer, algorithm), self._extensions) - - def add_extension(self, extension, critical): - if not isinstance(extension, x509.ExtensionType): - raise TypeError("extension must be an ExtensionType") - - extension = x509.Extension(extension.oid, critical, extension) - _reject_duplicate_extension(extension, self._extensions) - - return OCSPRequestBuilder( - self._request, self._extensions + [extension] - ) - - def build(self): - from cryptography.hazmat.backends.openssl.backend import backend - - if self._request is None: - raise ValueError("You must add a certificate before building") - - return backend.create_ocsp_request(self) - - class _SingleResponse(object): def __init__( self, @@ -184,151 +137,39 @@ def __init__( self._revocation_reason = revocation_reason -class OCSPResponseBuilder(object): - def __init__( - self, response=None, responder_id=None, certs=None, extensions=[] - ): - self._response = response - self._responder_id = responder_id - self._certs = certs - self._extensions = extensions - - def add_response( - self, - cert, - issuer, - algorithm, - cert_status, - this_update, - next_update, - revocation_time, - revocation_reason, - ): - if self._response is not None: - raise ValueError("Only one response per OCSPResponse.") - - singleresp = _SingleResponse( - cert, - issuer, - algorithm, - cert_status, - this_update, - next_update, - revocation_time, - revocation_reason, - ) - return OCSPResponseBuilder( - singleresp, - self._responder_id, - self._certs, - self._extensions, - ) - - def responder_id(self, encoding, responder_cert): - if self._responder_id is not None: - raise ValueError("responder_id can only be set once") - if not isinstance(responder_cert, x509.Certificate): - raise TypeError("responder_cert must be a Certificate") - if not isinstance(encoding, OCSPResponderEncoding): - raise TypeError( - "encoding must be an element from OCSPResponderEncoding" - ) - - return OCSPResponseBuilder( - self._response, - (responder_cert, encoding), - self._certs, - self._extensions, - ) - - def certificates(self, certs): - if self._certs is not None: - raise ValueError("certificates may only be set once") - certs = list(certs) - if len(certs) == 0: - raise ValueError("certs must not be an empty list") - if not all(isinstance(x, x509.Certificate) for x in certs): - raise TypeError("certs must be a list of Certificates") - return OCSPResponseBuilder( - self._response, - self._responder_id, - certs, - self._extensions, - ) - - def add_extension(self, extension, critical): - if not isinstance(extension, x509.ExtensionType): - raise TypeError("extension must be an ExtensionType") - - extension = x509.Extension(extension.oid, critical, extension) - _reject_duplicate_extension(extension, self._extensions) - - return OCSPResponseBuilder( - self._response, - self._responder_id, - self._certs, - self._extensions + [extension], - ) - - def sign(self, private_key, algorithm): - from cryptography.hazmat.backends.openssl.backend import backend - - if self._response is None: - raise ValueError("You must add a response before signing") - if self._responder_id is None: - raise ValueError("You must add a responder_id before signing") - - return backend.create_ocsp_response( - OCSPResponseStatus.SUCCESSFUL, self, private_key, algorithm - ) - - @classmethod - def build_unsuccessful(cls, response_status): - from cryptography.hazmat.backends.openssl.backend import backend - - if not isinstance(response_status, OCSPResponseStatus): - raise TypeError( - "response_status must be an item from OCSPResponseStatus" - ) - if response_status is OCSPResponseStatus.SUCCESSFUL: - raise ValueError("response_status cannot be SUCCESSFUL") - - return backend.create_ocsp_response(response_status, None, None, None) - - class OCSPRequest(metaclass=abc.ABCMeta): @abc.abstractproperty - def issuer_key_hash(self): + def issuer_key_hash(self) -> bytes: """ The hash of the issuer public key """ @abc.abstractproperty - def issuer_name_hash(self): + def issuer_name_hash(self) -> bytes: """ The hash of the issuer name """ @abc.abstractproperty - def hash_algorithm(self): + def hash_algorithm(self) -> hashes.HashAlgorithm: """ The hash algorithm used in the issuer name and key hashes """ @abc.abstractproperty - def serial_number(self): + def serial_number(self) -> int: """ The serial number of the cert whose status is being checked """ @abc.abstractmethod - def public_bytes(self, encoding): + def public_bytes(self, encoding: serialization.Encoding) -> bytes: """ Serializes the request to DER """ @abc.abstractproperty - def extensions(self): + def extensions(self) -> x509.Extensions: """ The list of request extensions. Not single request extensions. """ @@ -336,38 +177,40 @@ def extensions(self): class OCSPResponse(metaclass=abc.ABCMeta): @abc.abstractproperty - def response_status(self): + def response_status(self) -> OCSPResponseStatus: """ The status of the response. This is a value from the OCSPResponseStatus enumeration """ @abc.abstractproperty - def signature_algorithm_oid(self): + def signature_algorithm_oid(self) -> x509.ObjectIdentifier: """ The ObjectIdentifier of the signature algorithm """ @abc.abstractproperty - def signature_hash_algorithm(self): + def signature_hash_algorithm( + self, + ) -> typing.Optional[hashes.HashAlgorithm]: """ Returns a HashAlgorithm corresponding to the type of the digest signed """ @abc.abstractproperty - def signature(self): + def signature(self) -> bytes: """ The signature bytes """ @abc.abstractproperty - def tbs_response_bytes(self): + def tbs_response_bytes(self) -> bytes: """ The tbsResponseData bytes """ @abc.abstractproperty - def certificates(self): + def certificates(self) -> typing.List[x509.Certificate]: """ A list of certificates used to help build a chain to verify the OCSP response. This situation occurs when the OCSP responder uses a delegate @@ -375,88 +218,264 @@ def certificates(self): """ @abc.abstractproperty - def responder_key_hash(self): + def responder_key_hash(self) -> typing.Optional[bytes]: """ The responder's key hash or None """ @abc.abstractproperty - def responder_name(self): + def responder_name(self) -> typing.Optional[x509.Name]: """ The responder's Name or None """ @abc.abstractproperty - def produced_at(self): + def produced_at(self) -> datetime.datetime: """ The time the response was produced """ @abc.abstractproperty - def certificate_status(self): + def certificate_status(self) -> OCSPCertStatus: """ The status of the certificate (an element from the OCSPCertStatus enum) """ @abc.abstractproperty - def revocation_time(self): + def revocation_time(self) -> typing.Optional[datetime.datetime]: """ The date of when the certificate was revoked or None if not revoked. """ @abc.abstractproperty - def revocation_reason(self): + def revocation_reason(self) -> typing.Optional[x509.ReasonFlags]: """ The reason the certificate was revoked or None if not specified or not revoked. """ @abc.abstractproperty - def this_update(self): + def this_update(self) -> datetime.datetime: """ The most recent time at which the status being indicated is known by the responder to have been correct """ @abc.abstractproperty - def next_update(self): + def next_update(self) -> typing.Optional[datetime.datetime]: """ The time when newer information will be available """ @abc.abstractproperty - def issuer_key_hash(self): + def issuer_key_hash(self) -> bytes: """ The hash of the issuer public key """ @abc.abstractproperty - def issuer_name_hash(self): + def issuer_name_hash(self) -> bytes: """ The hash of the issuer name """ @abc.abstractproperty - def hash_algorithm(self): + def hash_algorithm(self) -> hashes.HashAlgorithm: """ The hash algorithm used in the issuer name and key hashes """ @abc.abstractproperty - def serial_number(self): + def serial_number(self) -> int: """ The serial number of the cert whose status is being checked """ @abc.abstractproperty - def extensions(self): + def extensions(self) -> x509.Extensions: """ The list of response extensions. Not single response extensions. """ @abc.abstractproperty - def single_extensions(self): + def single_extensions(self) -> x509.Extensions: """ The list of single response extensions. Not response extensions. """ + + +class OCSPRequestBuilder(object): + def __init__(self, request=None, extensions=[]): + self._request = request + self._extensions = extensions + + def add_certificate( + self, + cert: x509.Certificate, + issuer: x509.Certificate, + algorithm: hashes.HashAlgorithm, + ) -> "OCSPRequestBuilder": + if self._request is not None: + raise ValueError("Only one certificate can be added to a request") + + _verify_algorithm(algorithm) + if not isinstance(cert, x509.Certificate) or not isinstance( + issuer, x509.Certificate + ): + raise TypeError("cert and issuer must be a Certificate") + + return OCSPRequestBuilder((cert, issuer, algorithm), self._extensions) + + def add_extension( + self, extval: x509.ExtensionType, critical: bool + ) -> "OCSPRequestBuilder": + if not isinstance(extval, x509.ExtensionType): + raise TypeError("extension must be an ExtensionType") + + extension = x509.Extension(extval.oid, critical, extval) + _reject_duplicate_extension(extension, self._extensions) + + return OCSPRequestBuilder( + self._request, self._extensions + [extension] + ) + + def build(self) -> OCSPRequest: + from cryptography.hazmat.backends.openssl.backend import backend + + if self._request is None: + raise ValueError("You must add a certificate before building") + + return backend.create_ocsp_request(self) + + +class OCSPResponseBuilder(object): + def __init__( + self, response=None, responder_id=None, certs=None, extensions=[] + ): + self._response = response + self._responder_id = responder_id + self._certs = certs + self._extensions = extensions + + def add_response( + self, + cert: x509.Certificate, + issuer: x509.Certificate, + algorithm: hashes.HashAlgorithm, + cert_status: OCSPCertStatus, + this_update: datetime.datetime, + next_update: datetime.datetime, + revocation_time: datetime.datetime, + revocation_reason: x509.ReasonFlags, + ) -> "OCSPResponseBuilder": + if self._response is not None: + raise ValueError("Only one response per OCSPResponse.") + + singleresp = _SingleResponse( + cert, + issuer, + algorithm, + cert_status, + this_update, + next_update, + revocation_time, + revocation_reason, + ) + return OCSPResponseBuilder( + singleresp, + self._responder_id, + self._certs, + self._extensions, + ) + + def responder_id( + self, encoding: OCSPResponderEncoding, responder_cert: x509.Certificate + ) -> "OCSPResponseBuilder": + if self._responder_id is not None: + raise ValueError("responder_id can only be set once") + if not isinstance(responder_cert, x509.Certificate): + raise TypeError("responder_cert must be a Certificate") + if not isinstance(encoding, OCSPResponderEncoding): + raise TypeError( + "encoding must be an element from OCSPResponderEncoding" + ) + + return OCSPResponseBuilder( + self._response, + (responder_cert, encoding), + self._certs, + self._extensions, + ) + + def certificates( + self, certs: typing.Iterable[x509.Certificate] + ) -> "OCSPResponseBuilder": + if self._certs is not None: + raise ValueError("certificates may only be set once") + certs = list(certs) + if len(certs) == 0: + raise ValueError("certs must not be an empty list") + if not all(isinstance(x, x509.Certificate) for x in certs): + raise TypeError("certs must be a list of Certificates") + return OCSPResponseBuilder( + self._response, + self._responder_id, + certs, + self._extensions, + ) + + def add_extension( + self, extval: x509.ExtensionType, critical: bool + ) -> "OCSPResponseBuilder": + if not isinstance(extval, x509.ExtensionType): + raise TypeError("extension must be an ExtensionType") + + extension = x509.Extension(extval.oid, critical, extval) + _reject_duplicate_extension(extension, self._extensions) + + return OCSPResponseBuilder( + self._response, + self._responder_id, + self._certs, + self._extensions + [extension], + ) + + def sign( + self, private_key: _PRIVATE_KEY_TYPES, algorithm: hashes.HashAlgorithm + ) -> OCSPResponse: + from cryptography.hazmat.backends.openssl.backend import backend + + if self._response is None: + raise ValueError("You must add a response before signing") + if self._responder_id is None: + raise ValueError("You must add a responder_id before signing") + + return backend.create_ocsp_response( + OCSPResponseStatus.SUCCESSFUL, self, private_key, algorithm + ) + + @classmethod + def build_unsuccessful(cls, response_status: OCSPResponse) -> OCSPResponse: + from cryptography.hazmat.backends.openssl.backend import backend + + if not isinstance(response_status, OCSPResponseStatus): + raise TypeError( + "response_status must be an item from OCSPResponseStatus" + ) + if response_status is OCSPResponseStatus.SUCCESSFUL: + raise ValueError("response_status cannot be SUCCESSFUL") + + return backend.create_ocsp_response(response_status, None, None, None) + + +def load_der_ocsp_request(data: bytes) -> OCSPRequest: + from cryptography.hazmat.backends.openssl.backend import backend + + return backend.load_der_ocsp_request(data) + + +def load_der_ocsp_response(data: bytes) -> OCSPResponse: + from cryptography.hazmat.backends.openssl.backend import backend + + return backend.load_der_ocsp_response(data) From 5e302f93c81f499c21137e2a99d8cfaba93df209 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 30 Jan 2021 19:22:33 -0500 Subject: [PATCH 0071/2380] Attempt to run mypy over tests and vectors (#5716) --- mypy.ini | 7 ++++++- tox.ini | 3 ++- vectors/cryptography_vectors/__init__.py | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/mypy.ini b/mypy.ini index d67587279163..addaace24a35 100644 --- a/mypy.ini +++ b/mypy.ini @@ -3,4 +3,9 @@ [mypy-cryptography.hazmat.bindings._openssl] ignore_missing_imports = True [mypy-cryptography.hazmat.bindings._padding] -ignore_missing_imports = True \ No newline at end of file +ignore_missing_imports = True + +[mypy-iso8601] +ignore_missing_imports = True +[mypy-pretend] +ignore_missing_imports = True diff --git a/tox.ini b/tox.ini index b5956629fa5e..eebe1f79bdd5 100644 --- a/tox.ini +++ b/tox.ini @@ -48,11 +48,12 @@ commands = [testenv:mypy] basepython = python3 extras = + test ssh deps = mypy commands = - mypy src/cryptography/ + mypy src/cryptography/ vectors/cryptography_vectors/ tests/ [testenv:rust] basepython = python3 diff --git a/vectors/cryptography_vectors/__init__.py b/vectors/cryptography_vectors/__init__.py index fce9abadc118..86cddaca382f 100644 --- a/vectors/cryptography_vectors/__init__.py +++ b/vectors/cryptography_vectors/__init__.py @@ -3,6 +3,7 @@ # for complete details. import os +import typing from cryptography_vectors.__about__ import ( __author__, @@ -28,6 +29,6 @@ ] -def open_vector_file(filename, mode): +def open_vector_file(filename: str, mode: str) -> typing.IO: base = os.path.dirname(__file__) return open(os.path.join(base, filename), mode) From 576adfb66abd3df53ed078200e37a69701942830 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 30 Jan 2021 19:18:38 -0600 Subject: [PATCH 0072/2380] add type hints for twofactor (#5717) * add type hints for twofactor * fix import ordering --- .../hazmat/primitives/twofactor/hotp.py | 21 ++++++++++++---- .../hazmat/primitives/twofactor/totp.py | 24 ++++++++++++------- .../hazmat/primitives/twofactor/utils.py | 9 ++++++- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/cryptography/hazmat/primitives/twofactor/hotp.py b/src/cryptography/hazmat/primitives/twofactor/hotp.py index be0bf681198c..ae6769ac7664 100644 --- a/src/cryptography/hazmat/primitives/twofactor/hotp.py +++ b/src/cryptography/hazmat/primitives/twofactor/hotp.py @@ -4,6 +4,7 @@ import struct +import typing from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.backends import _get_backend @@ -14,9 +15,17 @@ from cryptography.hazmat.primitives.twofactor.utils import _generate_uri +_ALLOWED_HASH_TYPES = typing.Union[SHA1, SHA256, SHA512] + + class HOTP(object): def __init__( - self, key, length, algorithm, backend=None, enforce_key_length=True + self, + key: bytes, + length: int, + algorithm: _ALLOWED_HASH_TYPES, + backend=None, + enforce_key_length: bool = True, ): backend = _get_backend(backend) if not isinstance(backend, HMACBackend): @@ -42,16 +51,16 @@ def __init__( self._algorithm = algorithm self._backend = backend - def generate(self, counter): + def generate(self, counter: int): truncated_value = self._dynamic_truncate(counter) hotp = truncated_value % (10 ** self._length) return "{0:0{1}}".format(hotp, self._length).encode() - def verify(self, hotp, counter): + def verify(self, hotp: bytes, counter: int): if not constant_time.bytes_eq(self.generate(counter), hotp): raise InvalidToken("Supplied HOTP value does not match.") - def _dynamic_truncate(self, counter): + def _dynamic_truncate(self, counter: int): ctx = hmac.HMAC(self._key, self._algorithm, self._backend) ctx.update(struct.pack(">Q", counter)) hmac_value = ctx.finalize() @@ -60,7 +69,9 @@ def _dynamic_truncate(self, counter): p = hmac_value[offset : offset + 4] return struct.unpack(">I", p)[0] & 0x7FFFFFFF - def get_provisioning_uri(self, account_name, counter, issuer): + def get_provisioning_uri( + self, account_name: str, counter: int, issuer: typing.Optional[str] + ): return _generate_uri( self, "hotp", account_name, issuer, [("counter", int(counter))] ) diff --git a/src/cryptography/hazmat/primitives/twofactor/totp.py b/src/cryptography/hazmat/primitives/twofactor/totp.py index 649ccd4662c9..ba14e3ba3ca2 100644 --- a/src/cryptography/hazmat/primitives/twofactor/totp.py +++ b/src/cryptography/hazmat/primitives/twofactor/totp.py @@ -2,25 +2,29 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. +import typing from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.backends.interfaces import HMACBackend from cryptography.hazmat.primitives import constant_time from cryptography.hazmat.primitives.twofactor import InvalidToken -from cryptography.hazmat.primitives.twofactor.hotp import HOTP +from cryptography.hazmat.primitives.twofactor.hotp import ( + HOTP, + _ALLOWED_HASH_TYPES, +) from cryptography.hazmat.primitives.twofactor.utils import _generate_uri class TOTP(object): def __init__( self, - key, - length, - algorithm, - time_step, + key: bytes, + length: int, + algorithm: _ALLOWED_HASH_TYPES, + time_step: int, backend=None, - enforce_key_length=True, + enforce_key_length: bool = True, ): backend = _get_backend(backend) if not isinstance(backend, HMACBackend): @@ -32,15 +36,17 @@ def __init__( self._time_step = time_step self._hotp = HOTP(key, length, algorithm, backend, enforce_key_length) - def generate(self, time): + def generate(self, time: int): counter = int(time / self._time_step) return self._hotp.generate(counter) - def verify(self, totp, time): + def verify(self, totp: bytes, time: int): if not constant_time.bytes_eq(self.generate(time), totp): raise InvalidToken("Supplied TOTP value does not match.") - def get_provisioning_uri(self, account_name, issuer): + def get_provisioning_uri( + self, account_name: str, issuer: typing.Optional[str] + ): return _generate_uri( self._hotp, "totp", diff --git a/src/cryptography/hazmat/primitives/twofactor/utils.py b/src/cryptography/hazmat/primitives/twofactor/utils.py index d0facda7d4e3..60b5e928eaec 100644 --- a/src/cryptography/hazmat/primitives/twofactor/utils.py +++ b/src/cryptography/hazmat/primitives/twofactor/utils.py @@ -4,10 +4,17 @@ import base64 +import typing from urllib.parse import quote, urlencode -def _generate_uri(hotp, type_name, account_name, issuer, extra_parameters): +def _generate_uri( + hotp, + type_name: str, + account_name: str, + issuer: typing.Optional[str], + extra_parameters, +): parameters = [ ("digits", hotp._length), ("secret", base64.b32encode(hotp._key)), From 4372d3f2b8f48e90a0ce2aaf01b5686590833738 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 30 Jan 2021 21:40:51 -0600 Subject: [PATCH 0073/2380] type hinting for symmetric ciphers (#5719) * type hinting for symmetric ciphers * make our interface verifier happy --- .../hazmat/primitives/_cipheralgorithm.py | 31 +++++++ .../hazmat/primitives/ciphers/aead.py | 69 ++++++++++++--- .../hazmat/primitives/ciphers/algorithms.py | 70 ++++++--------- .../hazmat/primitives/ciphers/base.py | 15 +--- .../hazmat/primitives/ciphers/modes.py | 85 +++++++++---------- tests/doubles.py | 2 +- 6 files changed, 154 insertions(+), 118 deletions(-) create mode 100644 src/cryptography/hazmat/primitives/_cipheralgorithm.py diff --git a/src/cryptography/hazmat/primitives/_cipheralgorithm.py b/src/cryptography/hazmat/primitives/_cipheralgorithm.py new file mode 100644 index 000000000000..f13d02d2d7e2 --- /dev/null +++ b/src/cryptography/hazmat/primitives/_cipheralgorithm.py @@ -0,0 +1,31 @@ +# 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. + +import abc + + +# This exists to break an import cycle. It is normally accessible from the +# ciphers module. + + +class CipherAlgorithm(metaclass=abc.ABCMeta): + @abc.abstractproperty + def name(self): + """ + A string naming this mode (e.g. "AES", "Camellia"). + """ + + @abc.abstractproperty + def key_size(self): + """ + The size of the key being used as an integer in bits (e.g. 128, 256). + """ + + +class BlockCipherAlgorithm(metaclass=abc.ABCMeta): + @abc.abstractproperty + def block_size(self): + """ + The size of a block as an integer in bits (e.g. 64, 128). + """ diff --git a/src/cryptography/hazmat/primitives/ciphers/aead.py b/src/cryptography/hazmat/primitives/ciphers/aead.py index e26909eefcea..b539c6a46386 100644 --- a/src/cryptography/hazmat/primitives/ciphers/aead.py +++ b/src/cryptography/hazmat/primitives/ciphers/aead.py @@ -4,6 +4,7 @@ import os +import typing from cryptography import exceptions, utils from cryptography.hazmat.backends.openssl import aead @@ -13,7 +14,7 @@ class ChaCha20Poly1305(object): _MAX_SIZE = 2 ** 32 - def __init__(self, key): + def __init__(self, key: bytes): if not backend.aead_cipher_supported(self): raise exceptions.UnsupportedAlgorithm( "ChaCha20Poly1305 is not supported by this version of OpenSSL", @@ -27,10 +28,15 @@ def __init__(self, key): self._key = key @classmethod - def generate_key(cls): + def generate_key(cls) -> bytes: return os.urandom(32) - def encrypt(self, nonce, data, associated_data): + def encrypt( + self, + nonce: bytes, + data: bytes, + associated_data: typing.Optional[bytes], + ) -> bytes: if associated_data is None: associated_data = b"" @@ -43,14 +49,24 @@ def encrypt(self, nonce, data, associated_data): self._check_params(nonce, data, associated_data) return aead._encrypt(backend, self, nonce, data, associated_data, 16) - def decrypt(self, nonce, data, associated_data): + def decrypt( + self, + nonce: bytes, + data: bytes, + associated_data: typing.Optional[bytes], + ) -> bytes: if associated_data is None: associated_data = b"" self._check_params(nonce, data, associated_data) return aead._decrypt(backend, self, nonce, data, associated_data, 16) - def _check_params(self, nonce, data, associated_data): + def _check_params( + self, + nonce: bytes, + data: bytes, + associated_data: bytes, + ) -> None: utils._check_byteslike("nonce", nonce) utils._check_bytes("data", data) utils._check_bytes("associated_data", associated_data) @@ -61,7 +77,7 @@ def _check_params(self, nonce, data, associated_data): class AESCCM(object): _MAX_SIZE = 2 ** 32 - def __init__(self, key, tag_length=16): + def __init__(self, key: bytes, tag_length: int = 16): utils._check_byteslike("key", key) if len(key) not in (16, 24, 32): raise ValueError("AESCCM key must be 128, 192, or 256 bits.") @@ -76,7 +92,7 @@ def __init__(self, key, tag_length=16): self._tag_length = tag_length @classmethod - def generate_key(cls, bit_length): + def generate_key(cls, bit_length: int) -> bytes: if not isinstance(bit_length, int): raise TypeError("bit_length must be an integer") @@ -85,7 +101,12 @@ def generate_key(cls, bit_length): return os.urandom(bit_length // 8) - def encrypt(self, nonce, data, associated_data): + def encrypt( + self, + nonce: bytes, + data: bytes, + associated_data: typing.Optional[bytes], + ) -> bytes: if associated_data is None: associated_data = b"" @@ -101,7 +122,12 @@ def encrypt(self, nonce, data, associated_data): backend, self, nonce, data, associated_data, self._tag_length ) - def decrypt(self, nonce, data, associated_data): + def decrypt( + self, + nonce: bytes, + data: bytes, + associated_data: typing.Optional[bytes], + ) -> bytes: if associated_data is None: associated_data = b"" @@ -128,7 +154,7 @@ def _check_params(self, nonce, data, associated_data): class AESGCM(object): _MAX_SIZE = 2 ** 32 - def __init__(self, key): + def __init__(self, key: bytes): utils._check_byteslike("key", key) if len(key) not in (16, 24, 32): raise ValueError("AESGCM key must be 128, 192, or 256 bits.") @@ -136,7 +162,7 @@ def __init__(self, key): self._key = key @classmethod - def generate_key(cls, bit_length): + def generate_key(cls, bit_length: int) -> bytes: if not isinstance(bit_length, int): raise TypeError("bit_length must be an integer") @@ -145,7 +171,12 @@ def generate_key(cls, bit_length): return os.urandom(bit_length // 8) - def encrypt(self, nonce, data, associated_data): + def encrypt( + self, + nonce: bytes, + data: bytes, + associated_data: typing.Optional[bytes], + ) -> bytes: if associated_data is None: associated_data = b"" @@ -158,14 +189,24 @@ def encrypt(self, nonce, data, associated_data): self._check_params(nonce, data, associated_data) return aead._encrypt(backend, self, nonce, data, associated_data, 16) - def decrypt(self, nonce, data, associated_data): + def decrypt( + self, + nonce: bytes, + data: bytes, + associated_data: typing.Optional[bytes], + ) -> bytes: if associated_data is None: associated_data = b"" self._check_params(nonce, data, associated_data) return aead._decrypt(backend, self, nonce, data, associated_data, 16) - def _check_params(self, nonce, data, associated_data): + def _check_params( + self, + nonce: bytes, + data: bytes, + associated_data: bytes, + ) -> None: utils._check_byteslike("nonce", nonce) utils._check_bytes("data", data) utils._check_bytes("associated_data", associated_data) diff --git a/src/cryptography/hazmat/primitives/ciphers/algorithms.py b/src/cryptography/hazmat/primitives/ciphers/algorithms.py index 2ddd9b1075a6..cb1f252d49f8 100644 --- a/src/cryptography/hazmat/primitives/ciphers/algorithms.py +++ b/src/cryptography/hazmat/primitives/ciphers/algorithms.py @@ -25,45 +25,39 @@ def _verify_key_size(algorithm, key): return key -@utils.register_interface(BlockCipherAlgorithm) -@utils.register_interface(CipherAlgorithm) -class AES(object): +class AES(CipherAlgorithm, BlockCipherAlgorithm): name = "AES" block_size = 128 # 512 added to support AES-256-XTS, which uses 512-bit keys key_sizes = frozenset([128, 192, 256, 512]) - def __init__(self, key): + def __init__(self, key: bytes): self.key = _verify_key_size(self, key) @property - def key_size(self): + def key_size(self) -> int: return len(self.key) * 8 -@utils.register_interface(BlockCipherAlgorithm) -@utils.register_interface(CipherAlgorithm) -class Camellia(object): +class Camellia(CipherAlgorithm, BlockCipherAlgorithm): name = "camellia" block_size = 128 key_sizes = frozenset([128, 192, 256]) - def __init__(self, key): + def __init__(self, key: bytes): self.key = _verify_key_size(self, key) @property - def key_size(self): + def key_size(self) -> int: return len(self.key) * 8 -@utils.register_interface(BlockCipherAlgorithm) -@utils.register_interface(CipherAlgorithm) -class TripleDES(object): +class TripleDES(CipherAlgorithm, BlockCipherAlgorithm): name = "3DES" block_size = 64 key_sizes = frozenset([64, 128, 192]) - def __init__(self, key): + def __init__(self, key: bytes): if len(key) == 8: key += key + key elif len(key) == 16: @@ -71,89 +65,79 @@ def __init__(self, key): self.key = _verify_key_size(self, key) @property - def key_size(self): + def key_size(self) -> int: return len(self.key) * 8 -@utils.register_interface(BlockCipherAlgorithm) -@utils.register_interface(CipherAlgorithm) -class Blowfish(object): +class Blowfish(CipherAlgorithm, BlockCipherAlgorithm): name = "Blowfish" block_size = 64 key_sizes = frozenset(range(32, 449, 8)) - def __init__(self, key): + def __init__(self, key: bytes): self.key = _verify_key_size(self, key) @property - def key_size(self): + def key_size(self) -> int: return len(self.key) * 8 -@utils.register_interface(BlockCipherAlgorithm) -@utils.register_interface(CipherAlgorithm) -class CAST5(object): +class CAST5(CipherAlgorithm, BlockCipherAlgorithm): name = "CAST5" block_size = 64 key_sizes = frozenset(range(40, 129, 8)) - def __init__(self, key): + def __init__(self, key: bytes): self.key = _verify_key_size(self, key) @property - def key_size(self): + def key_size(self) -> int: return len(self.key) * 8 -@utils.register_interface(CipherAlgorithm) -class ARC4(object): +class ARC4(CipherAlgorithm): name = "RC4" key_sizes = frozenset([40, 56, 64, 80, 128, 160, 192, 256]) - def __init__(self, key): + def __init__(self, key: bytes): self.key = _verify_key_size(self, key) @property - def key_size(self): + def key_size(self) -> int: return len(self.key) * 8 -@utils.register_interface(CipherAlgorithm) -class IDEA(object): +class IDEA(CipherAlgorithm): name = "IDEA" block_size = 64 key_sizes = frozenset([128]) - def __init__(self, key): + def __init__(self, key: bytes): self.key = _verify_key_size(self, key) @property - def key_size(self): + def key_size(self) -> int: return len(self.key) * 8 -@utils.register_interface(BlockCipherAlgorithm) -@utils.register_interface(CipherAlgorithm) -class SEED(object): +class SEED(CipherAlgorithm, BlockCipherAlgorithm): name = "SEED" block_size = 128 key_sizes = frozenset([128]) - def __init__(self, key): + def __init__(self, key: bytes): self.key = _verify_key_size(self, key) @property - def key_size(self): + def key_size(self) -> int: return len(self.key) * 8 -@utils.register_interface(CipherAlgorithm) -@utils.register_interface(ModeWithNonce) -class ChaCha20(object): +class ChaCha20(CipherAlgorithm, ModeWithNonce): name = "ChaCha20" key_sizes = frozenset([256]) - def __init__(self, key, nonce): + def __init__(self, key: bytes, nonce: bytes): self.key = _verify_key_size(self, key) utils._check_byteslike("nonce", nonce) @@ -165,5 +149,5 @@ def __init__(self, key, nonce): nonce = utils.read_only_property("_nonce") @property - def key_size(self): + def key_size(self) -> int: return len(self.key) * 8 diff --git a/src/cryptography/hazmat/primitives/ciphers/base.py b/src/cryptography/hazmat/primitives/ciphers/base.py index 42cda7858ca8..1b98637216f7 100644 --- a/src/cryptography/hazmat/primitives/ciphers/base.py +++ b/src/cryptography/hazmat/primitives/ciphers/base.py @@ -15,23 +15,10 @@ ) from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.backends.interfaces import CipherBackend +from cryptography.hazmat.primitives._cipheralgorithm import CipherAlgorithm from cryptography.hazmat.primitives.ciphers import modes -class CipherAlgorithm(metaclass=abc.ABCMeta): - @abc.abstractproperty - def name(self): - """ - A string naming this mode (e.g. "AES", "Camellia"). - """ - - @abc.abstractproperty - def key_size(self): - """ - The size of the key being used as an integer in bits (e.g. 128, 256). - """ - - class BlockCipherAlgorithm(metaclass=abc.ABCMeta): @abc.abstractproperty def block_size(self): diff --git a/src/cryptography/hazmat/primitives/ciphers/modes.py b/src/cryptography/hazmat/primitives/ciphers/modes.py index bebbe261c2bb..5265aad2378a 100644 --- a/src/cryptography/hazmat/primitives/ciphers/modes.py +++ b/src/cryptography/hazmat/primitives/ciphers/modes.py @@ -4,19 +4,21 @@ import abc +import typing from cryptography import utils +from cryptography.hazmat.primitives._cipheralgorithm import CipherAlgorithm class Mode(metaclass=abc.ABCMeta): @abc.abstractproperty - def name(self): + def name(self) -> str: """ A string naming this mode (e.g. "ECB", "CBC"). """ @abc.abstractmethod - def validate_for_algorithm(self, algorithm): + def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: """ Checks that all the necessary invariants of this (mode, algorithm) combination are met. @@ -25,7 +27,7 @@ def validate_for_algorithm(self, algorithm): class ModeWithInitializationVector(metaclass=abc.ABCMeta): @abc.abstractproperty - def initialization_vector(self): + def initialization_vector(self) -> bytes: """ The value of the initialization vector for this mode as bytes. """ @@ -33,7 +35,7 @@ def initialization_vector(self): class ModeWithTweak(metaclass=abc.ABCMeta): @abc.abstractproperty - def tweak(self): + def tweak(self) -> bytes: """ The value of the tweak for this mode as bytes. """ @@ -41,7 +43,7 @@ def tweak(self): class ModeWithNonce(metaclass=abc.ABCMeta): @abc.abstractproperty - def nonce(self): + def nonce(self) -> bytes: """ The value of the nonce for this mode as bytes. """ @@ -49,7 +51,7 @@ def nonce(self): class ModeWithAuthenticationTag(metaclass=abc.ABCMeta): @abc.abstractproperty - def tag(self): + def tag(self) -> bytes: """ The value of the tag supplied to the constructor of this mode. """ @@ -71,17 +73,22 @@ def _check_iv_length(self, algorithm): ) +def _check_nonce_length(nonce: bytes, name: str, algorithm): + if len(nonce) * 8 != algorithm.block_size: + raise ValueError( + "Invalid nonce size ({}) for {}.".format(len(nonce), name) + ) + + def _check_iv_and_key_length(self, algorithm): _check_aes_key_length(self, algorithm) _check_iv_length(self, algorithm) -@utils.register_interface(Mode) -@utils.register_interface(ModeWithInitializationVector) -class CBC(object): +class CBC(Mode, ModeWithInitializationVector): name = "CBC" - def __init__(self, initialization_vector): + def __init__(self, initialization_vector: bytes): utils._check_byteslike("initialization_vector", initialization_vector) self._initialization_vector = initialization_vector @@ -89,12 +96,10 @@ def __init__(self, initialization_vector): validate_for_algorithm = _check_iv_and_key_length -@utils.register_interface(Mode) -@utils.register_interface(ModeWithTweak) -class XTS(object): +class XTS(Mode, ModeWithTweak): name = "XTS" - def __init__(self, tweak): + def __init__(self, tweak: bytes): utils._check_byteslike("tweak", tweak) if len(tweak) != 16: @@ -104,7 +109,7 @@ def __init__(self, tweak): tweak = utils.read_only_property("_tweak") - def validate_for_algorithm(self, algorithm): + def validate_for_algorithm(self, algorithm: CipherAlgorithm): if algorithm.key_size not in (256, 512): raise ValueError( "The XTS specification requires a 256-bit key for AES-128-XTS" @@ -112,19 +117,16 @@ def validate_for_algorithm(self, algorithm): ) -@utils.register_interface(Mode) -class ECB(object): +class ECB(Mode): name = "ECB" validate_for_algorithm = _check_aes_key_length -@utils.register_interface(Mode) -@utils.register_interface(ModeWithInitializationVector) -class OFB(object): +class OFB(Mode, ModeWithInitializationVector): name = "OFB" - def __init__(self, initialization_vector): + def __init__(self, initialization_vector: bytes): utils._check_byteslike("initialization_vector", initialization_vector) self._initialization_vector = initialization_vector @@ -132,12 +134,10 @@ def __init__(self, initialization_vector): validate_for_algorithm = _check_iv_and_key_length -@utils.register_interface(Mode) -@utils.register_interface(ModeWithInitializationVector) -class CFB(object): +class CFB(Mode, ModeWithInitializationVector): name = "CFB" - def __init__(self, initialization_vector): + def __init__(self, initialization_vector: bytes): utils._check_byteslike("initialization_vector", initialization_vector) self._initialization_vector = initialization_vector @@ -145,12 +145,10 @@ def __init__(self, initialization_vector): validate_for_algorithm = _check_iv_and_key_length -@utils.register_interface(Mode) -@utils.register_interface(ModeWithInitializationVector) -class CFB8(object): +class CFB8(Mode, ModeWithInitializationVector): name = "CFB8" - def __init__(self, initialization_vector): + def __init__(self, initialization_vector: bytes): utils._check_byteslike("initialization_vector", initialization_vector) self._initialization_vector = initialization_vector @@ -158,36 +156,31 @@ def __init__(self, initialization_vector): validate_for_algorithm = _check_iv_and_key_length -@utils.register_interface(Mode) -@utils.register_interface(ModeWithNonce) -class CTR(object): +class CTR(Mode, ModeWithNonce): name = "CTR" - def __init__(self, nonce): + def __init__(self, nonce: bytes): utils._check_byteslike("nonce", nonce) self._nonce = nonce nonce = utils.read_only_property("_nonce") - def validate_for_algorithm(self, algorithm): + def validate_for_algorithm(self, algorithm: CipherAlgorithm): _check_aes_key_length(self, algorithm) - if len(self.nonce) * 8 != algorithm.block_size: - raise ValueError( - "Invalid nonce size ({}) for {}.".format( - len(self.nonce), self.name - ) - ) + _check_nonce_length(self.nonce, self.name, algorithm) -@utils.register_interface(Mode) -@utils.register_interface(ModeWithInitializationVector) -@utils.register_interface(ModeWithAuthenticationTag) -class GCM(object): +class GCM(Mode, ModeWithInitializationVector, ModeWithAuthenticationTag): name = "GCM" _MAX_ENCRYPTED_BYTES = (2 ** 39 - 256) // 8 _MAX_AAD_BYTES = (2 ** 64) // 8 - def __init__(self, initialization_vector, tag=None, min_tag_length=16): + def __init__( + self, + initialization_vector: bytes, + tag: typing.Optional[bytes] = None, + min_tag_length: int = 16, + ): # OpenSSL 3.0.0 constrains GCM IVs to [64, 1024] bits inclusive # This is a sane limit anyway so we'll enforce it here. utils._check_byteslike("initialization_vector", initialization_vector) @@ -213,5 +206,5 @@ def __init__(self, initialization_vector, tag=None, min_tag_length=16): tag = utils.read_only_property("_tag") initialization_vector = utils.read_only_property("_initialization_vector") - def validate_for_algorithm(self, algorithm): + def validate_for_algorithm(self, algorithm: CipherAlgorithm): _check_aes_key_length(self, algorithm) diff --git a/tests/doubles.py b/tests/doubles.py index 0a64606dde9a..6a4a48323ad0 100644 --- a/tests/doubles.py +++ b/tests/doubles.py @@ -21,7 +21,7 @@ class DummyCipherAlgorithm(object): class DummyMode(object): name = "dummy-mode" - def validate_for_algorithm(self, algorithm): + def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: pass From f5940f068de1c07641cd102826e476531574d435 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 30 Jan 2021 22:38:26 -0600 Subject: [PATCH 0074/2380] add serialization type hinting (#5718) * add serialization type hinting * reorganize to prevent circular dependency * review feedback * damn you black --- src/cryptography/hazmat/_types.py | 29 ++++++++++ .../hazmat/primitives/serialization/base.py | 28 +++++---- .../hazmat/primitives/serialization/pkcs12.py | 20 ++++++- .../hazmat/primitives/serialization/pkcs7.py | 57 +++++++++++++------ .../hazmat/primitives/serialization/ssh.py | 35 ++++++++++-- src/cryptography/x509/base.py | 15 +---- 6 files changed, 135 insertions(+), 49 deletions(-) create mode 100644 src/cryptography/hazmat/_types.py diff --git a/src/cryptography/hazmat/_types.py b/src/cryptography/hazmat/_types.py new file mode 100644 index 000000000000..ba29baf28b2c --- /dev/null +++ b/src/cryptography/hazmat/_types.py @@ -0,0 +1,29 @@ +# 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. + +import typing + +from cryptography.hazmat.primitives.asymmetric import ( + dsa, + ec, + ed25519, + ed448, + rsa, +) + + +_PUBLIC_KEY_TYPES = typing.Union[ + dsa.DSAPublicKey, + rsa.RSAPublicKey, + ec.EllipticCurvePublicKey, + ed25519.Ed25519PublicKey, + ed448.Ed448PublicKey, +] +_PRIVATE_KEY_TYPES = typing.Union[ + ed25519.Ed25519PrivateKey, + ed448.Ed448PrivateKey, + rsa.RSAPrivateKey, + dsa.DSAPrivateKey, + ec.EllipticCurvePrivateKey, +] diff --git a/src/cryptography/hazmat/primitives/serialization/base.py b/src/cryptography/hazmat/primitives/serialization/base.py index 9c6ae423e76c..cd737ec6aeee 100644 --- a/src/cryptography/hazmat/primitives/serialization/base.py +++ b/src/cryptography/hazmat/primitives/serialization/base.py @@ -4,38 +4,44 @@ import abc +import typing from enum import Enum -from cryptography import utils +from cryptography.hazmat._types import _PRIVATE_KEY_TYPES, _PUBLIC_KEY_TYPES from cryptography.hazmat.backends import _get_backend +from cryptography.hazmat.primitives.asymmetric import dh -def load_pem_private_key(data, password, backend=None): +def load_pem_private_key( + data: bytes, password: typing.Optional[bytes], backend=None +) -> _PRIVATE_KEY_TYPES: backend = _get_backend(backend) return backend.load_pem_private_key(data, password) -def load_pem_public_key(data, backend=None): +def load_pem_public_key(data: bytes, backend=None) -> _PUBLIC_KEY_TYPES: backend = _get_backend(backend) return backend.load_pem_public_key(data) -def load_pem_parameters(data, backend=None): +def load_pem_parameters(data: bytes, backend=None) -> dh.DHParameters: backend = _get_backend(backend) return backend.load_pem_parameters(data) -def load_der_private_key(data, password, backend=None): +def load_der_private_key( + data: bytes, password: typing.Optional[bytes], backend=None +) -> _PRIVATE_KEY_TYPES: backend = _get_backend(backend) return backend.load_der_private_key(data, password) -def load_der_public_key(data, backend=None): +def load_der_public_key(data: bytes, backend=None) -> _PUBLIC_KEY_TYPES: backend = _get_backend(backend) return backend.load_der_public_key(data) -def load_der_parameters(data, backend=None): +def load_der_parameters(data: bytes, backend=None) -> dh.DHParameters: backend = _get_backend(backend) return backend.load_der_parameters(data) @@ -73,15 +79,13 @@ class KeySerializationEncryption(metaclass=abc.ABCMeta): pass -@utils.register_interface(KeySerializationEncryption) -class BestAvailableEncryption(object): - def __init__(self, password): +class BestAvailableEncryption(KeySerializationEncryption): + def __init__(self, password: bytes): if not isinstance(password, bytes) or len(password) == 0: raise ValueError("Password must be 1 or more bytes.") self.password = password -@utils.register_interface(KeySerializationEncryption) -class NoEncryption(object): +class NoEncryption(KeySerializationEncryption): pass diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs12.py b/src/cryptography/hazmat/primitives/serialization/pkcs12.py index 76f713a21c85..26c2cdcc133a 100644 --- a/src/cryptography/hazmat/primitives/serialization/pkcs12.py +++ b/src/cryptography/hazmat/primitives/serialization/pkcs12.py @@ -2,6 +2,7 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. +import typing from cryptography import x509 from cryptography.hazmat.backends import _get_backend @@ -9,12 +10,27 @@ from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa -def load_key_and_certificates(data, password, backend=None): +def load_key_and_certificates( + data: bytes, password: typing.Optional[bytes], backend=None +): backend = _get_backend(backend) return backend.load_key_and_certificates_from_pkcs12(data, password) -def serialize_key_and_certificates(name, key, cert, cas, encryption_algorithm): +_ALLOWED_PKCS12_TYPES = typing.Union[ + rsa.RSAPrivateKeyWithSerialization, + dsa.DSAPrivateKeyWithSerialization, + ec.EllipticCurvePrivateKeyWithSerialization, +] + + +def serialize_key_and_certificates( + name: bytes, + key: typing.Optional[_ALLOWED_PKCS12_TYPES], + cert: typing.Optional[x509.Certificate], + cas: typing.Optional[typing.Iterable[x509.Certificate]], + encryption_algorithm: serialization.KeySerializationEncryption, +): if key is not None and not isinstance( key, ( diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs7.py b/src/cryptography/hazmat/primitives/serialization/pkcs7.py index ed82b8be461a..bcd9e330d58d 100644 --- a/src/cryptography/hazmat/primitives/serialization/pkcs7.py +++ b/src/cryptography/hazmat/primitives/serialization/pkcs7.py @@ -2,7 +2,7 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. - +import typing from enum import Enum from cryptography import x509 @@ -12,30 +12,57 @@ from cryptography.utils import _check_byteslike -def load_pem_pkcs7_certificates(data): +def load_pem_pkcs7_certificates(data: bytes) -> typing.List[x509.Certificate]: backend = _get_backend(None) return backend.load_pem_pkcs7_certificates(data) -def load_der_pkcs7_certificates(data): +def load_der_pkcs7_certificates(data: bytes) -> typing.List[x509.Certificate]: backend = _get_backend(None) return backend.load_der_pkcs7_certificates(data) +_ALLOWED_PKCS7_HASH_TYPES = typing.Union[ + hashes.SHA1, + hashes.SHA224, + hashes.SHA256, + hashes.SHA384, + hashes.SHA512, +] + +_ALLOWED_PRIVATE_KEY_TYPES = typing.Union[ + rsa.RSAPrivateKey, ec.EllipticCurvePrivateKey +] + + +class PKCS7Options(Enum): + Text = "Add text/plain MIME type" + Binary = "Don't translate input data into canonical MIME format" + DetachedSignature = "Don't embed data in the PKCS7 structure" + NoCapabilities = "Don't embed SMIME capabilities" + NoAttributes = "Don't embed authenticatedAttributes" + NoCerts = "Don't embed signer certificate" + + class PKCS7SignatureBuilder(object): def __init__(self, data=None, signers=[], additional_certs=[]): self._data = data self._signers = signers self._additional_certs = additional_certs - def set_data(self, data): + def set_data(self, data: bytes) -> "PKCS7SignatureBuilder": _check_byteslike("data", data) if self._data is not None: raise ValueError("data may only be set once") return PKCS7SignatureBuilder(data, self._signers) - def add_signer(self, certificate, private_key, hash_algorithm): + def add_signer( + self, + certificate: x509.Certificate, + private_key: _ALLOWED_PRIVATE_KEY_TYPES, + hash_algorithm: _ALLOWED_PKCS7_HASH_TYPES, + ) -> "PKCS7SignatureBuilder": if not isinstance( hash_algorithm, ( @@ -63,7 +90,9 @@ def add_signer(self, certificate, private_key, hash_algorithm): self._signers + [(certificate, private_key, hash_algorithm)], ) - def add_certificate(self, certificate): + def add_certificate( + self, certificate: x509.Certificate + ) -> "PKCS7SignatureBuilder": if not isinstance(certificate, x509.Certificate): raise TypeError("certificate must be a x509.Certificate") @@ -71,7 +100,12 @@ def add_certificate(self, certificate): self._data, self._signers, self._additional_certs + [certificate] ) - def sign(self, encoding, options, backend=None): + def sign( + self, + encoding: serialization.Encoding, + options: typing.Iterable[PKCS7Options], + backend=None, + ) -> bytes: if len(self._signers) == 0: raise ValueError("Must have at least one signer") if self._data is None: @@ -120,12 +154,3 @@ def sign(self, encoding, options, backend=None): backend = _get_backend(backend) return backend.pkcs7_sign(self, encoding, options) - - -class PKCS7Options(Enum): - Text = "Add text/plain MIME type" - Binary = "Don't translate input data into canonical MIME format" - DetachedSignature = "Don't embed data in the PKCS7 structure" - NoCapabilities = "Don't embed SMIME capabilities" - NoAttributes = "Don't embed authenticatedAttributes" - NoCerts = "Don't embed signer certificate" diff --git a/src/cryptography/hazmat/primitives/serialization/ssh.py b/src/cryptography/hazmat/primitives/serialization/ssh.py index 5b98d5140a74..f276c1e84a2d 100644 --- a/src/cryptography/hazmat/primitives/serialization/ssh.py +++ b/src/cryptography/hazmat/primitives/serialization/ssh.py @@ -7,6 +7,7 @@ import os import re import struct +import typing from base64 import encodebytes as _base64_encode from cryptography import utils @@ -464,7 +465,17 @@ def _lookup_kformat(key_type): raise UnsupportedAlgorithm("Unsupported key type: %r" % key_type) -def load_ssh_private_key(data, password, backend=None): +_SSH_PRIVATE_KEY_TYPES = typing.Union[ + ec.EllipticCurvePrivateKey, + rsa.RSAPrivateKey, + dsa.DSAPrivateKey, + ed25519.Ed25519PrivateKey, +] + + +def load_ssh_private_key( + data: bytes, password: typing.Optional[bytes], backend=None +) -> _SSH_PRIVATE_KEY_TYPES: """Load private key from OpenSSH custom encoding.""" utils._check_byteslike("data", data) backend = _get_backend(backend) @@ -538,7 +549,10 @@ def load_ssh_private_key(data, password, backend=None): return private_key -def serialize_ssh_private_key(private_key, password=None): +def serialize_ssh_private_key( + private_key: _SSH_PRIVATE_KEY_TYPES, + password: typing.Optional[bytes] = None, +): """Serialize private key with OpenSSH custom encoding.""" if password is not None: utils._check_bytes("password", password) @@ -613,11 +627,22 @@ def serialize_ssh_private_key(private_key, password=None): ciph.encryptor().update_into(buf[ofs:mlen], buf[ofs:]) txt = _ssh_pem_encode(buf[:mlen]) - buf[ofs:mlen] = bytearray(slen) + # Ignore the following type because mypy wants + # Sequence[bytes] but what we're passing is fine. + # https://github.com/python/mypy/issues/9999 + buf[ofs:mlen] = bytearray(slen) # type: ignore return txt -def load_ssh_public_key(data, backend=None): +_SSH_PUBLIC_KEY_TYPES = typing.Union[ + ec.EllipticCurvePublicKey, + rsa.RSAPublicKey, + dsa.DSAPublicKey, + ed25519.Ed25519PublicKey, +] + + +def load_ssh_public_key(data: bytes, backend=None) -> _SSH_PUBLIC_KEY_TYPES: """Load public key from OpenSSH one-line format.""" backend = _get_backend(backend) utils._check_byteslike("data", data) @@ -660,7 +685,7 @@ def load_ssh_public_key(data, backend=None): return public_key -def serialize_ssh_public_key(public_key): +def serialize_ssh_public_key(public_key: _SSH_PUBLIC_KEY_TYPES) -> bytes: """One-line public key format for OpenSSH""" if isinstance(public_key, ec.EllipticCurvePublicKey): key_type = _ecdsa_key_type(public_key) diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index 5c5e6c6daaad..5505fa3b6d5e 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -9,6 +9,7 @@ import typing from enum import Enum +from cryptography.hazmat._types import _PRIVATE_KEY_TYPES, _PUBLIC_KEY_TYPES from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ( @@ -24,20 +25,6 @@ _EARLIEST_UTC_TIME = datetime.datetime(1950, 1, 1) -_PUBLIC_KEY_TYPES = typing.Union[ - dsa.DSAPublicKey, - rsa.RSAPublicKey, - ec.EllipticCurvePublicKey, - ed25519.Ed25519PublicKey, - ed448.Ed448PublicKey, -] -_PRIVATE_KEY_TYPES = typing.Union[ - ed25519.Ed25519PrivateKey, - ed448.Ed448PrivateKey, - rsa.RSAPrivateKey, - dsa.DSAPrivateKey, - ec.EllipticCurvePrivateKey, -] class AttributeNotFound(Exception): From 6a8c0b55b99f95e1fcc8bb9c2b03fd9158d2081e Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 31 Jan 2021 10:37:26 -0600 Subject: [PATCH 0075/2380] make PrivateKeyWithSerialization an alias of PrivateKey (#5722) * make PrivateKeyWithSerialization an alias of PrivateKey * black --- CHANGELOG.rst | 16 ++++++------ docs/hazmat/primitives/asymmetric/dh.rst | 19 +++++--------- docs/hazmat/primitives/asymmetric/dsa.rst | 20 ++++++-------- docs/hazmat/primitives/asymmetric/ec.rst | 16 +++++------- docs/hazmat/primitives/asymmetric/rsa.rst | 26 +++++++------------ .../primitives/asymmetric/serialization.rst | 11 ++++---- .../hazmat/backends/openssl/dh.py | 6 ++--- .../hazmat/backends/openssl/dsa.py | 4 +-- .../hazmat/backends/openssl/ec.py | 4 +-- .../hazmat/backends/openssl/rsa.py | 8 +++--- .../hazmat/primitives/asymmetric/dh.py | 5 ++-- .../hazmat/primitives/asymmetric/dsa.py | 5 ++-- .../hazmat/primitives/asymmetric/ec.py | 7 +++-- .../hazmat/primitives/asymmetric/rsa.py | 5 ++-- .../hazmat/primitives/serialization/pkcs12.py | 12 ++++----- tests/hazmat/primitives/test_dh.py | 16 +++++------- tests/hazmat/primitives/test_rsa.py | 2 +- 17 files changed, 81 insertions(+), 101 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 053017b05a4a..96a947f34645 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -697,9 +697,9 @@ Changelog :meth:`~cryptography.hazmat.primitives.ciphers.CipherContext.update_into` on :class:`~cryptography.hazmat.primitives.ciphers.CipherContext`. * Added - :meth:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKeyWithSerialization.private_bytes` + :meth:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey.private_bytes` to - :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKeyWithSerialization`. + :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`. * Added :meth:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey.public_bytes` to @@ -1287,23 +1287,23 @@ Changelog :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization` and deprecated ``EllipticCurvePrivateKeyWithNumbers``. * Added - :meth:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization.private_bytes` + :meth:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey.private_bytes` to - :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization`. + :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`. * Added :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization` and deprecated ``RSAPrivateKeyWithNumbers``. * Added - :meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization.private_bytes` + :meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey.private_bytes` to - :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization`. + :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`. * Added :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKeyWithSerialization` and deprecated ``DSAPrivateKeyWithNumbers``. * Added - :meth:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKeyWithSerialization.private_bytes` + :meth:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey.private_bytes` to - :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKeyWithSerialization`. + :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`. * Added :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKeyWithSerialization` and deprecated ``RSAPublicKeyWithNumbers``. diff --git a/docs/hazmat/primitives/asymmetric/dh.rst b/docs/hazmat/primitives/asymmetric/dh.rst index 6b47da089378..3b8b58baed9a 100644 --- a/docs/hazmat/primitives/asymmetric/dh.rst +++ b/docs/hazmat/primitives/asymmetric/dh.rst @@ -195,9 +195,6 @@ Key interfaces .. versionadded:: 1.7 - A DH private key that is not an :term:`opaque key` also implements - :class:`DHPrivateKeyWithSerialization` to provide serialization methods. - .. attribute:: key_size The bit length of the prime modulus. @@ -223,15 +220,6 @@ Key interfaces :return bytes: The agreed key. The bytes are ordered in 'big' endian. - -.. class:: DHPrivateKeyWithSerialization - - .. versionadded:: 1.7 - - This interface contains additional methods relating to serialization. - Any object with this interface also has all the methods from - :class:`DHPrivateKey`. - .. method:: private_numbers() Return the numbers that make up this private key. @@ -266,6 +254,13 @@ Key interfaces :return bytes: Serialized key. +.. class:: DHPrivateKeyWithSerialization + + .. versionadded:: 1.7 + + Alias for :class:`DHPrivateKey`. + + .. class:: DHPublicKey .. versionadded:: 1.7 diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst index 788e4270b886..b151b0ef4a95 100644 --- a/docs/hazmat/primitives/asymmetric/dsa.rst +++ b/docs/hazmat/primitives/asymmetric/dsa.rst @@ -289,9 +289,7 @@ Key interfaces .. versionadded:: 0.3 - A `DSA`_ private key. A DSA private key that is not an - :term:`opaque key` also implements :class:`DSAPrivateKeyWithSerialization` - to provide serialization methods. + A `DSA`_ private key. .. method:: public_key() @@ -330,15 +328,6 @@ Key interfaces :return bytes: Signature. - -.. class:: DSAPrivateKeyWithSerialization - - .. versionadded:: 0.8 - - This interface contains additional methods relating to serialization. - Any object with this interface also has all the methods from - :class:`DSAPrivateKey`. - .. method:: private_numbers() Create a @@ -378,6 +367,13 @@ Key interfaces :return bytes: Serialized key. +.. class:: DSAPrivateKeyWithSerialization + + .. versionadded:: 0.8 + + Alias for :class:`DSAPrivateKey`. + + .. class:: DSAPublicKey .. versionadded:: 0.3 diff --git a/docs/hazmat/primitives/asymmetric/ec.rst b/docs/hazmat/primitives/asymmetric/ec.rst index 5691560f3c76..c45cc9ad74e6 100644 --- a/docs/hazmat/primitives/asymmetric/ec.rst +++ b/docs/hazmat/primitives/asymmetric/ec.rst @@ -627,15 +627,6 @@ Key Interfaces Size (in :term:`bits`) of a secret scalar for the curve (as generated by :func:`generate_private_key`). - -.. class:: EllipticCurvePrivateKeyWithSerialization - - .. versionadded:: 0.8 - - This interface contains additional methods relating to serialization. - Any object with this interface also has all the methods from - :class:`EllipticCurvePrivateKey`. - .. method:: private_numbers() Create a :class:`EllipticCurvePrivateNumbers` object. @@ -670,6 +661,13 @@ Key Interfaces :return bytes: Serialized key. +.. class:: EllipticCurvePrivateKeyWithSerialization + + .. versionadded:: 0.8 + + Alias for :class:`EllipticCurvePrivateKey`. + + .. class:: EllipticCurvePublicKey .. versionadded:: 0.5 diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst index be69c636cbc5..7a3e835a13d5 100644 --- a/docs/hazmat/primitives/asymmetric/rsa.rst +++ b/docs/hazmat/primitives/asymmetric/rsa.rst @@ -85,10 +85,8 @@ There is also support for :func:`loading public keys in the SSH format Key serialization ~~~~~~~~~~~~~~~~~ -If you have a private key that you've loaded or generated which implements the -:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization` -interface you can use -:meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization.private_bytes` +If you have a private key that you've loaded you can use +:meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey.private_bytes` to serialize the key. .. doctest:: @@ -536,9 +534,7 @@ Key interfaces .. versionadded:: 0.2 - An `RSA`_ private key. An RSA private key that is not an - :term:`opaque key` also implements :class:`RSAPrivateKeyWithSerialization` - to provide serialization methods. + An `RSA`_ private key. .. method:: decrypt(ciphertext, padding) @@ -587,15 +583,6 @@ Key interfaces :return bytes: Signature. - -.. class:: RSAPrivateKeyWithSerialization - - .. versionadded:: 0.8 - - This interface contains additional methods relating to serialization. - Any object with this interface also has all the methods from - :class:`RSAPrivateKey`. - .. method:: private_numbers() Create a @@ -635,6 +622,13 @@ Key interfaces :return bytes: Serialized key. +.. class:: RSAPrivateKeyWithSerialization + + .. versionadded:: 0.8 + + Alias for :class:`RSAPrivateKey`. + + .. class:: RSAPublicKey .. versionadded:: 0.2 diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst index 2324340e119c..07a7456e4992 100644 --- a/docs/hazmat/primitives/asymmetric/serialization.rst +++ b/docs/hazmat/primitives/asymmetric/serialization.rst @@ -924,15 +924,14 @@ Serialization Encryption Types Objects with this interface are usable as encryption types with methods like ``private_bytes`` available on - :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization` + :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey` , - :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization` - , :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKeyWithSerialization` + :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey` + , :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey` and - :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKeyWithSerialization`. + :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`. All other classes in this section represent the available choices for - encryption and have this interface. They are used with - :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization.private_bytes`. + encryption and have this interface. .. class:: BestAvailableEncryption(password) diff --git a/src/cryptography/hazmat/backends/openssl/dh.py b/src/cryptography/hazmat/backends/openssl/dh.py index 3bf138f24fd5..e6f332dac5f7 100644 --- a/src/cryptography/hazmat/backends/openssl/dh.py +++ b/src/cryptography/hazmat/backends/openssl/dh.py @@ -32,7 +32,7 @@ def _dh_cdata_to_parameters(dh_cdata, backend): return _DHParameters(backend, param_cdata) -@utils.register_interface(dh.DHParametersWithSerialization) +@utils.register_interface(dh.DHParameters) class _DHParameters(object): def __init__(self, backend, dh_cdata): self._backend = backend @@ -85,7 +85,7 @@ def _get_dh_num_bits(backend, dh_cdata): return backend._lib.BN_num_bits(p[0]) -@utils.register_interface(dh.DHPrivateKeyWithSerialization) +@utils.register_interface(dh.DHPrivateKey) class _DHPrivateKey(object): def __init__(self, backend, dh_cdata, evp_pkey): self._backend = backend @@ -204,7 +204,7 @@ def private_bytes(self, encoding, format, encryption_algorithm): ) -@utils.register_interface(dh.DHPublicKeyWithSerialization) +@utils.register_interface(dh.DHPublicKey) class _DHPublicKey(object): def __init__(self, backend, dh_cdata, evp_pkey): self._backend = backend diff --git a/src/cryptography/hazmat/backends/openssl/dsa.py b/src/cryptography/hazmat/backends/openssl/dsa.py index c172e40d0968..fb8c4b27c313 100644 --- a/src/cryptography/hazmat/backends/openssl/dsa.py +++ b/src/cryptography/hazmat/backends/openssl/dsa.py @@ -107,7 +107,7 @@ def generate_private_key(self): return self._backend.generate_dsa_private_key(self) -@utils.register_interface(dsa.DSAPrivateKeyWithSerialization) +@utils.register_interface(dsa.DSAPrivateKey) class _DSAPrivateKey(object): def __init__(self, backend, dsa_cdata, evp_pkey): self._backend = backend @@ -197,7 +197,7 @@ def sign(self, data, algorithm): return _dsa_sig_sign(self._backend, self, data) -@utils.register_interface(dsa.DSAPublicKeyWithSerialization) +@utils.register_interface(dsa.DSAPublicKey) class _DSAPublicKey(object): def __init__(self, backend, dsa_cdata, evp_pkey): self._backend = backend diff --git a/src/cryptography/hazmat/backends/openssl/ec.py b/src/cryptography/hazmat/backends/openssl/ec.py index c0b479758ca1..8977f489fd9b 100644 --- a/src/cryptography/hazmat/backends/openssl/ec.py +++ b/src/cryptography/hazmat/backends/openssl/ec.py @@ -138,7 +138,7 @@ def verify(self): ) -@utils.register_interface(ec.EllipticCurvePrivateKeyWithSerialization) +@utils.register_interface(ec.EllipticCurvePrivateKey) class _EllipticCurvePrivateKey(object): def __init__(self, backend, ec_key_cdata, evp_pkey): self._backend = backend @@ -236,7 +236,7 @@ def sign(self, data, signature_algorithm): return _ecdsa_sig_sign(self._backend, self, data) -@utils.register_interface(ec.EllipticCurvePublicKeyWithSerialization) +@utils.register_interface(ec.EllipticCurvePublicKey) class _EllipticCurvePublicKey(object): def __init__(self, backend, ec_key_cdata, evp_pkey): self._backend = backend diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py index 15d2f4f39da5..03dab9883b8e 100644 --- a/src/cryptography/hazmat/backends/openssl/rsa.py +++ b/src/cryptography/hazmat/backends/openssl/rsa.py @@ -29,8 +29,8 @@ calculate_max_pss_salt_length, ) from cryptography.hazmat.primitives.asymmetric.rsa import ( - RSAPrivateKeyWithSerialization, - RSAPublicKeyWithSerialization, + RSAPrivateKey, + RSAPublicKey, ) @@ -351,7 +351,7 @@ def verify(self): ) -@utils.register_interface(RSAPrivateKeyWithSerialization) +@utils.register_interface(RSAPrivateKey) class _RSAPrivateKey(object): def __init__(self, backend, rsa_cdata, evp_pkey): res = backend._lib.RSA_check_key(rsa_cdata) @@ -451,7 +451,7 @@ def sign(self, data, padding, algorithm): return _rsa_sig_sign(self._backend, padding, algorithm, self, data) -@utils.register_interface(RSAPublicKeyWithSerialization) +@utils.register_interface(RSAPublicKey) class _RSAPublicKey(object): def __init__(self, backend, rsa_cdata, evp_pkey): self._backend = backend diff --git a/src/cryptography/hazmat/primitives/asymmetric/dh.py b/src/cryptography/hazmat/primitives/asymmetric/dh.py index f954afbbbd03..85344fb1f0f2 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dh.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dh.py @@ -171,8 +171,6 @@ def exchange(self, peer_public_key): return shared key as bytes. """ - -class DHPrivateKeyWithSerialization(DHPrivateKey, metaclass=abc.ABCMeta): @abc.abstractmethod def private_numbers(self): """ @@ -186,6 +184,9 @@ def private_bytes(self, encoding, format, encryption_algorithm): """ +DHPrivateKeyWithSerialization = DHPrivateKey + + class DHPublicKey(metaclass=abc.ABCMeta): @abc.abstractproperty def key_size(self): diff --git a/src/cryptography/hazmat/primitives/asymmetric/dsa.py b/src/cryptography/hazmat/primitives/asymmetric/dsa.py index 6f5443e687b5..63931bc94b76 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dsa.py @@ -56,8 +56,6 @@ def sign(self, data, algorithm): Signs the data """ - -class DSAPrivateKeyWithSerialization(DSAPrivateKey, metaclass=abc.ABCMeta): @abc.abstractmethod def private_numbers(self): """ @@ -71,6 +69,9 @@ def private_bytes(self, encoding, format, encryption_algorithm): """ +DSAPrivateKeyWithSerialization = DSAPrivateKey + + class DSAPublicKey(metaclass=abc.ABCMeta): @abc.abstractproperty def key_size(self): diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index 29e389550766..ea2e93a8b5af 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -93,10 +93,6 @@ def sign(self, data, signature_algorithm): Signs the data """ - -class EllipticCurvePrivateKeyWithSerialization( - EllipticCurvePrivateKey, metaclass=abc.ABCMeta -): @abc.abstractmethod def private_numbers(self): """ @@ -110,6 +106,9 @@ def private_bytes(self, encoding, format, encryption_algorithm): """ +EllipticCurvePrivateKeyWithSerialization = EllipticCurvePrivateKey + + class EllipticCurvePublicKey(metaclass=abc.ABCMeta): @abc.abstractmethod def verifier(self, signature, signature_algorithm): diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py index da2fcdc14298..7214f46f897c 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py @@ -43,8 +43,6 @@ def sign(self, data, padding, algorithm): Signs the data. """ - -class RSAPrivateKeyWithSerialization(RSAPrivateKey, metaclass=abc.ABCMeta): @abc.abstractmethod def private_numbers(self): """ @@ -58,6 +56,9 @@ def private_bytes(self, encoding, format, encryption_algorithm): """ +RSAPrivateKeyWithSerialization = RSAPrivateKey + + class RSAPublicKey(metaclass=abc.ABCMeta): @abc.abstractmethod def verifier(self, signature, padding, algorithm): diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs12.py b/src/cryptography/hazmat/primitives/serialization/pkcs12.py index 26c2cdcc133a..191ac52fa654 100644 --- a/src/cryptography/hazmat/primitives/serialization/pkcs12.py +++ b/src/cryptography/hazmat/primitives/serialization/pkcs12.py @@ -18,9 +18,9 @@ def load_key_and_certificates( _ALLOWED_PKCS12_TYPES = typing.Union[ - rsa.RSAPrivateKeyWithSerialization, - dsa.DSAPrivateKeyWithSerialization, - ec.EllipticCurvePrivateKeyWithSerialization, + rsa.RSAPrivateKey, + dsa.DSAPrivateKey, + ec.EllipticCurvePrivateKey, ] @@ -34,9 +34,9 @@ def serialize_key_and_certificates( if key is not None and not isinstance( key, ( - rsa.RSAPrivateKeyWithSerialization, - dsa.DSAPrivateKeyWithSerialization, - ec.EllipticCurvePrivateKeyWithSerialization, + rsa.RSAPrivateKey, + dsa.DSAPrivateKey, + ec.EllipticCurvePrivateKey, ), ): raise TypeError("Key must be RSA, DSA, or EllipticCurve private key.") diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index f5db45dc8d3d..02536093d789 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -221,13 +221,9 @@ def test_convert_to_numbers(self, backend, with_q): deserialized_public = public.public_key(backend) deserialized_private = private.private_key(backend) - assert isinstance( - deserialized_params, dh.DHParametersWithSerialization - ) - assert isinstance(deserialized_public, dh.DHPublicKeyWithSerialization) - assert isinstance( - deserialized_private, dh.DHPrivateKeyWithSerialization - ) + assert isinstance(deserialized_params, dh.DHParameters) + assert isinstance(deserialized_public, dh.DHPublicKey) + assert isinstance(deserialized_private, dh.DHPrivateKey) @pytest.mark.skip_fips(reason="FIPS requires specific parameters") def test_numbers_unsupported_parameters(self, backend): @@ -270,16 +266,16 @@ def test_generate_dh(self, backend, with_q): assert isinstance(public, dh.DHPublicKey) assert public.key_size == key_size - assert isinstance(parameters, dh.DHParametersWithSerialization) + assert isinstance(parameters, dh.DHParameters) parameter_numbers = parameters.parameter_numbers() assert isinstance(parameter_numbers, dh.DHParameterNumbers) assert parameter_numbers.p.bit_length() == key_size - assert isinstance(public, dh.DHPublicKeyWithSerialization) + assert isinstance(public, dh.DHPublicKey) assert isinstance(public.public_numbers(), dh.DHPublicNumbers) assert isinstance(public.parameters(), dh.DHParameters) - assert isinstance(key, dh.DHPrivateKeyWithSerialization) + assert isinstance(key, dh.DHPrivateKey) assert isinstance(key.private_numbers(), dh.DHPrivateNumbers) assert isinstance(key.parameters(), dh.DHParameters) diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 82ba2bf09199..188338ef90f9 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -74,7 +74,7 @@ class DummyMGF(object): def _check_rsa_private_numbers_if_serializable(key): - if isinstance(key, rsa.RSAPrivateKeyWithSerialization): + if isinstance(key, rsa.RSAPrivateKey): _check_rsa_private_numbers(key.private_numbers()) From b24d522b05b2220fbcb74363e454c2997a0c7ab7 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 31 Jan 2021 12:14:13 -0600 Subject: [PATCH 0076/2380] type updates from turning on unchecked-defs on tests (#5720) test changes themselves will be in a separate PR --- mypy.ini | 2 + src/cryptography/hazmat/backends/__init__.py | 3 +- .../hazmat/bindings/openssl/binding.py | 2 +- .../hazmat/primitives/asymmetric/ec.py | 60 ++++-------- .../hazmat/primitives/serialization/base.py | 5 +- .../hazmat/primitives/serialization/pkcs12.py | 2 +- .../hazmat/primitives/twofactor/totp.py | 2 +- src/cryptography/utils.py | 4 +- src/cryptography/x509/extensions.py | 96 +++++++------------ src/cryptography/x509/ocsp.py | 20 +++- tox.ini | 2 +- 11 files changed, 85 insertions(+), 113 deletions(-) diff --git a/mypy.ini b/mypy.ini index addaace24a35..bf4cc82270c9 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,4 +1,6 @@ [mypy] +show_error_codes = True +check_untyped_defs = True [mypy-cryptography.hazmat.bindings._openssl] ignore_missing_imports = True diff --git a/src/cryptography/hazmat/backends/__init__.py b/src/cryptography/hazmat/backends/__init__.py index aabde5b7e132..72c65b197f09 100644 --- a/src/cryptography/hazmat/backends/__init__.py +++ b/src/cryptography/hazmat/backends/__init__.py @@ -2,8 +2,9 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. +import typing -_default_backend = None +_default_backend: typing.Any = None def default_backend(): diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py index bd67d97ef366..a2bc36a83a71 100644 --- a/src/cryptography/hazmat/bindings/openssl/binding.py +++ b/src/cryptography/hazmat/bindings/openssl/binding.py @@ -91,7 +91,7 @@ def _openssl_assert(lib, ok, errors=None): def build_conditional_library(lib, conditional_names): conditional_lib = types.ModuleType("lib") - conditional_lib._original_lib = lib + conditional_lib._original_lib = lib # type: ignore[attr-defined] excluded_names = set() for condition, names_cb in conditional_names.items(): if not getattr(lib, condition): diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index ea2e93a8b5af..c1b7473fcf22 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -4,6 +4,7 @@ import abc +import typing import warnings from cryptography import utils @@ -167,121 +168,102 @@ def from_encoded_point(cls, curve, data): EllipticCurvePublicKeyWithSerialization = EllipticCurvePublicKey -@utils.register_interface(EllipticCurve) -class SECT571R1(object): +class SECT571R1(EllipticCurve): name = "sect571r1" key_size = 570 -@utils.register_interface(EllipticCurve) -class SECT409R1(object): +class SECT409R1(EllipticCurve): name = "sect409r1" key_size = 409 -@utils.register_interface(EllipticCurve) -class SECT283R1(object): +class SECT283R1(EllipticCurve): name = "sect283r1" key_size = 283 -@utils.register_interface(EllipticCurve) -class SECT233R1(object): +class SECT233R1(EllipticCurve): name = "sect233r1" key_size = 233 -@utils.register_interface(EllipticCurve) -class SECT163R2(object): +class SECT163R2(EllipticCurve): name = "sect163r2" key_size = 163 -@utils.register_interface(EllipticCurve) -class SECT571K1(object): +class SECT571K1(EllipticCurve): name = "sect571k1" key_size = 571 -@utils.register_interface(EllipticCurve) -class SECT409K1(object): +class SECT409K1(EllipticCurve): name = "sect409k1" key_size = 409 -@utils.register_interface(EllipticCurve) -class SECT283K1(object): +class SECT283K1(EllipticCurve): name = "sect283k1" key_size = 283 -@utils.register_interface(EllipticCurve) -class SECT233K1(object): +class SECT233K1(EllipticCurve): name = "sect233k1" key_size = 233 -@utils.register_interface(EllipticCurve) -class SECT163K1(object): +class SECT163K1(EllipticCurve): name = "sect163k1" key_size = 163 -@utils.register_interface(EllipticCurve) -class SECP521R1(object): +class SECP521R1(EllipticCurve): name = "secp521r1" key_size = 521 -@utils.register_interface(EllipticCurve) -class SECP384R1(object): +class SECP384R1(EllipticCurve): name = "secp384r1" key_size = 384 -@utils.register_interface(EllipticCurve) -class SECP256R1(object): +class SECP256R1(EllipticCurve): name = "secp256r1" key_size = 256 -@utils.register_interface(EllipticCurve) -class SECP256K1(object): +class SECP256K1(EllipticCurve): name = "secp256k1" key_size = 256 -@utils.register_interface(EllipticCurve) -class SECP224R1(object): +class SECP224R1(EllipticCurve): name = "secp224r1" key_size = 224 -@utils.register_interface(EllipticCurve) -class SECP192R1(object): +class SECP192R1(EllipticCurve): name = "secp192r1" key_size = 192 -@utils.register_interface(EllipticCurve) -class BrainpoolP256R1(object): +class BrainpoolP256R1(EllipticCurve): name = "brainpoolP256r1" key_size = 256 -@utils.register_interface(EllipticCurve) -class BrainpoolP384R1(object): +class BrainpoolP384R1(EllipticCurve): name = "brainpoolP384r1" key_size = 384 -@utils.register_interface(EllipticCurve) -class BrainpoolP512R1(object): +class BrainpoolP512R1(EllipticCurve): name = "brainpoolP512r1" key_size = 512 -_CURVE_TYPES = { +_CURVE_TYPES: typing.Dict[str, typing.Type[EllipticCurve]] = { "prime192v1": SECP192R1, "prime256v1": SECP256R1, "secp192r1": SECP192R1, diff --git a/src/cryptography/hazmat/primitives/serialization/base.py b/src/cryptography/hazmat/primitives/serialization/base.py index cd737ec6aeee..2ce722cf486c 100644 --- a/src/cryptography/hazmat/primitives/serialization/base.py +++ b/src/cryptography/hazmat/primitives/serialization/base.py @@ -7,7 +7,10 @@ import typing from enum import Enum -from cryptography.hazmat._types import _PRIVATE_KEY_TYPES, _PUBLIC_KEY_TYPES +from cryptography.hazmat._types import ( + _PRIVATE_KEY_TYPES, + _PUBLIC_KEY_TYPES, +) from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.primitives.asymmetric import dh diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs12.py b/src/cryptography/hazmat/primitives/serialization/pkcs12.py index 191ac52fa654..e3ca34b9837e 100644 --- a/src/cryptography/hazmat/primitives/serialization/pkcs12.py +++ b/src/cryptography/hazmat/primitives/serialization/pkcs12.py @@ -25,7 +25,7 @@ def load_key_and_certificates( def serialize_key_and_certificates( - name: bytes, + name: typing.Optional[bytes], key: typing.Optional[_ALLOWED_PKCS12_TYPES], cert: typing.Optional[x509.Certificate], cas: typing.Optional[typing.Iterable[x509.Certificate]], diff --git a/src/cryptography/hazmat/primitives/twofactor/totp.py b/src/cryptography/hazmat/primitives/twofactor/totp.py index ba14e3ba3ca2..245295103181 100644 --- a/src/cryptography/hazmat/primitives/twofactor/totp.py +++ b/src/cryptography/hazmat/primitives/twofactor/totp.py @@ -36,7 +36,7 @@ def __init__( self._time_step = time_step self._hotp = HOTP(key, length, algorithm, backend, enforce_key_length) - def generate(self, time: int): + def generate(self, time: typing.Union[int, float]): counter = int(time / self._time_step) return self._hotp.generate(counter) diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index 48d90c64acf3..e6ea8d6e08a7 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -122,7 +122,9 @@ def __dir__(self): def deprecated(value, module_name, message, warning_class): module = sys.modules[module_name] if not isinstance(module, _ModuleWithDeprecations): - sys.modules[module_name] = _ModuleWithDeprecations(module) + sys.modules[module_name] = _ModuleWithDeprecations( + module + ) # type: ignore[assignment] return _DeprecatedValue(value, message, warning_class) diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index 0602908e480d..9f3d8f62d084 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -107,7 +107,7 @@ def oid(self) -> ObjectIdentifier: class Extensions(object): - def __init__(self, extensions: typing.List[ExtensionType]): + def __init__(self, extensions: typing.List["Extension"]): self._extensions = extensions def get_extension_for_oid(self, oid): @@ -139,8 +139,7 @@ def __repr__(self): return "".format(self._extensions) -@utils.register_interface(ExtensionType) -class CRLNumber(object): +class CRLNumber(ExtensionType): oid = ExtensionOID.CRL_NUMBER def __init__(self, crl_number): @@ -167,8 +166,7 @@ def __repr__(self): crl_number = utils.read_only_property("_crl_number") -@utils.register_interface(ExtensionType) -class AuthorityKeyIdentifier(object): +class AuthorityKeyIdentifier(ExtensionType): oid = ExtensionOID.AUTHORITY_KEY_IDENTIFIER def __init__( @@ -259,8 +257,7 @@ def __hash__(self): ) -@utils.register_interface(ExtensionType) -class SubjectKeyIdentifier(object): +class SubjectKeyIdentifier(ExtensionType): oid = ExtensionOID.SUBJECT_KEY_IDENTIFIER def __init__(self, digest): @@ -288,8 +285,7 @@ def __hash__(self): return hash(self.digest) -@utils.register_interface(ExtensionType) -class AuthorityInformationAccess(object): +class AuthorityInformationAccess(ExtensionType): oid = ExtensionOID.AUTHORITY_INFORMATION_ACCESS def __init__(self, descriptions): @@ -320,8 +316,7 @@ def __hash__(self): return hash(tuple(self._descriptions)) -@utils.register_interface(ExtensionType) -class SubjectInformationAccess(object): +class SubjectInformationAccess(ExtensionType): oid = ExtensionOID.SUBJECT_INFORMATION_ACCESS def __init__(self, descriptions): @@ -388,8 +383,7 @@ def __hash__(self): access_location = utils.read_only_property("_access_location") -@utils.register_interface(ExtensionType) -class BasicConstraints(object): +class BasicConstraints(ExtensionType): oid = ExtensionOID.BASIC_CONSTRAINTS def __init__(self, ca, path_length): @@ -430,8 +424,7 @@ def __hash__(self): return hash((self.ca, self.path_length)) -@utils.register_interface(ExtensionType) -class DeltaCRLIndicator(object): +class DeltaCRLIndicator(ExtensionType): oid = ExtensionOID.DELTA_CRL_INDICATOR def __init__(self, crl_number): @@ -458,8 +451,7 @@ def __repr__(self): return "".format(self) -@utils.register_interface(ExtensionType) -class CRLDistributionPoints(object): +class CRLDistributionPoints(ExtensionType): oid = ExtensionOID.CRL_DISTRIBUTION_POINTS def __init__(self, distribution_points): @@ -494,8 +486,7 @@ def __hash__(self): return hash(tuple(self._distribution_points)) -@utils.register_interface(ExtensionType) -class FreshestCRL(object): +class FreshestCRL(ExtensionType): oid = ExtensionOID.FRESHEST_CRL def __init__(self, distribution_points): @@ -607,12 +598,12 @@ def __ne__(self, other): def __hash__(self): if self.full_name is not None: - fn = tuple(self.full_name) + fn: typing.Optional[tuple] = tuple(self.full_name) else: fn = None if self.crl_issuer is not None: - crl_issuer = tuple(self.crl_issuer) + crl_issuer: typing.Optional[tuple] = tuple(self.crl_issuer) else: crl_issuer = None @@ -637,8 +628,7 @@ class ReasonFlags(Enum): remove_from_crl = "removeFromCRL" -@utils.register_interface(ExtensionType) -class PolicyConstraints(object): +class PolicyConstraints(ExtensionType): oid = ExtensionOID.POLICY_CONSTRAINTS def __init__(self, require_explicit_policy, inhibit_policy_mapping): @@ -698,8 +688,7 @@ def __hash__(self): ) -@utils.register_interface(ExtensionType) -class CertificatePolicies(object): +class CertificatePolicies(ExtensionType): oid = ExtensionOID.CERTIFICATE_POLICIES def __init__(self, policies): @@ -769,7 +758,7 @@ def __ne__(self, other): def __hash__(self): if self.policy_qualifiers is not None: - pq = tuple(self.policy_qualifiers) + pq: typing.Optional[tuple] = tuple(self.policy_qualifiers) else: pq = None @@ -850,8 +839,7 @@ def __hash__(self): notice_numbers = utils.read_only_property("_notice_numbers") -@utils.register_interface(ExtensionType) -class ExtendedKeyUsage(object): +class ExtendedKeyUsage(ExtensionType): oid = ExtensionOID.EXTENDED_KEY_USAGE def __init__(self, usages): @@ -881,8 +869,7 @@ def __hash__(self): return hash(tuple(self._usages)) -@utils.register_interface(ExtensionType) -class OCSPNoCheck(object): +class OCSPNoCheck(ExtensionType): oid = ExtensionOID.OCSP_NO_CHECK def __eq__(self, other): @@ -901,8 +888,7 @@ def __repr__(self): return "" -@utils.register_interface(ExtensionType) -class PrecertPoison(object): +class PrecertPoison(ExtensionType): oid = ExtensionOID.PRECERT_POISON def __eq__(self, other): @@ -921,8 +907,7 @@ def __repr__(self): return "" -@utils.register_interface(ExtensionType) -class TLSFeature(object): +class TLSFeature(ExtensionType): oid = ExtensionOID.TLS_FEATURE def __init__(self, features): @@ -970,8 +955,7 @@ class TLSFeatureType(Enum): _TLS_FEATURE_TYPE_TO_ENUM = {x.value: x for x in TLSFeatureType} -@utils.register_interface(ExtensionType) -class InhibitAnyPolicy(object): +class InhibitAnyPolicy(ExtensionType): oid = ExtensionOID.INHIBIT_ANY_POLICY def __init__(self, skip_certs): @@ -1001,8 +985,7 @@ def __hash__(self): skip_certs = utils.read_only_property("_skip_certs") -@utils.register_interface(ExtensionType) -class KeyUsage(object): +class KeyUsage(ExtensionType): oid = ExtensionOID.KEY_USAGE def __init__( @@ -1115,8 +1098,7 @@ def __hash__(self): ) -@utils.register_interface(ExtensionType) -class NameConstraints(object): +class NameConstraints(ExtensionType): oid = ExtensionOID.NAME_CONSTRAINTS def __init__(self, permitted_subtrees, excluded_subtrees): @@ -1182,12 +1164,12 @@ def __repr__(self): def __hash__(self): if self.permitted_subtrees is not None: - ps = tuple(self.permitted_subtrees) + ps: typing.Optional[tuple] = tuple(self.permitted_subtrees) else: ps = None if self.excluded_subtrees is not None: - es = tuple(self.excluded_subtrees) + es: typing.Optional[tuple] = tuple(self.excluded_subtrees) else: es = None @@ -1276,8 +1258,7 @@ def __hash__(self): return hash(tuple(self._general_names)) -@utils.register_interface(ExtensionType) -class SubjectAlternativeName(object): +class SubjectAlternativeName(ExtensionType): oid = ExtensionOID.SUBJECT_ALTERNATIVE_NAME def __init__(self, general_names): @@ -1304,8 +1285,7 @@ def __hash__(self): return hash(self._general_names) -@utils.register_interface(ExtensionType) -class IssuerAlternativeName(object): +class IssuerAlternativeName(ExtensionType): oid = ExtensionOID.ISSUER_ALTERNATIVE_NAME def __init__(self, general_names): @@ -1332,8 +1312,7 @@ def __hash__(self): return hash(self._general_names) -@utils.register_interface(ExtensionType) -class CertificateIssuer(object): +class CertificateIssuer(ExtensionType): oid = CRLEntryExtensionOID.CERTIFICATE_ISSUER def __init__(self, general_names): @@ -1360,8 +1339,7 @@ def __hash__(self): return hash(self._general_names) -@utils.register_interface(ExtensionType) -class CRLReason(object): +class CRLReason(ExtensionType): oid = CRLEntryExtensionOID.CRL_REASON def __init__(self, reason): @@ -1388,8 +1366,7 @@ def __hash__(self): reason = utils.read_only_property("_reason") -@utils.register_interface(ExtensionType) -class InvalidityDate(object): +class InvalidityDate(ExtensionType): oid = CRLEntryExtensionOID.INVALIDITY_DATE def __init__(self, invalidity_date): @@ -1418,8 +1395,7 @@ def __hash__(self): invalidity_date = utils.read_only_property("_invalidity_date") -@utils.register_interface(ExtensionType) -class PrecertificateSignedCertificateTimestamps(object): +class PrecertificateSignedCertificateTimestamps(ExtensionType): oid = ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS def __init__(self, signed_certificate_timestamps): @@ -1459,8 +1435,7 @@ def __ne__(self, other): return not self == other -@utils.register_interface(ExtensionType) -class SignedCertificateTimestamps(object): +class SignedCertificateTimestamps(ExtensionType): oid = ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS def __init__(self, signed_certificate_timestamps): @@ -1498,8 +1473,7 @@ def __ne__(self, other): return not self == other -@utils.register_interface(ExtensionType) -class OCSPNonce(object): +class OCSPNonce(ExtensionType): oid = OCSPExtensionOID.NONCE def __init__(self, nonce): @@ -1526,8 +1500,7 @@ def __repr__(self): nonce = utils.read_only_property("_nonce") -@utils.register_interface(ExtensionType) -class IssuingDistributionPoint(object): +class IssuingDistributionPoint(ExtensionType): oid = ExtensionOID.ISSUING_DISTRIBUTION_POINT def __init__( @@ -1668,8 +1641,7 @@ def __hash__(self): ) -@utils.register_interface(ExtensionType) -class UnrecognizedExtension(object): +class UnrecognizedExtension(ExtensionType): def __init__(self, oid, value): if not isinstance(oid, ObjectIdentifier): raise TypeError("oid must be an ObjectIdentifier") diff --git a/src/cryptography/x509/ocsp.py b/src/cryptography/x509/ocsp.py index 4d4992060f07..1c5de73e45b1 100644 --- a/src/cryptography/x509/ocsp.py +++ b/src/cryptography/x509/ocsp.py @@ -304,6 +304,12 @@ def single_extensions(self) -> x509.Extensions: The list of single response extensions. Not response extensions. """ + @abc.abstractmethod + def public_bytes(self, encoding: serialization.Encoding) -> bytes: + """ + Serializes the response to DER + """ + class OCSPRequestBuilder(object): def __init__(self, request=None, extensions=[]): @@ -365,9 +371,9 @@ def add_response( algorithm: hashes.HashAlgorithm, cert_status: OCSPCertStatus, this_update: datetime.datetime, - next_update: datetime.datetime, - revocation_time: datetime.datetime, - revocation_reason: x509.ReasonFlags, + next_update: typing.Optional[datetime.datetime], + revocation_time: typing.Optional[datetime.datetime], + revocation_reason: typing.Optional[x509.ReasonFlags], ) -> "OCSPResponseBuilder": if self._response is not None: raise ValueError("Only one response per OCSPResponse.") @@ -442,7 +448,9 @@ def add_extension( ) def sign( - self, private_key: _PRIVATE_KEY_TYPES, algorithm: hashes.HashAlgorithm + self, + private_key: _PRIVATE_KEY_TYPES, + algorithm: typing.Optional[hashes.HashAlgorithm], ) -> OCSPResponse: from cryptography.hazmat.backends.openssl.backend import backend @@ -456,7 +464,9 @@ def sign( ) @classmethod - def build_unsuccessful(cls, response_status: OCSPResponse) -> OCSPResponse: + def build_unsuccessful( + cls, response_status: OCSPResponseStatus + ) -> OCSPResponse: from cryptography.hazmat.backends.openssl.backend import backend if not isinstance(response_status, OCSPResponseStatus): diff --git a/tox.ini b/tox.ini index eebe1f79bdd5..1e6fbcf784d9 100644 --- a/tox.ini +++ b/tox.ini @@ -53,7 +53,7 @@ extras = deps = mypy commands = - mypy src/cryptography/ vectors/cryptography_vectors/ tests/ + mypy src/cryptography/ vectors/cryptography_vectors/ [testenv:rust] basepython = python3 From a98e708d4524b6278486a3e1ed359470941795ab Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 31 Jan 2021 16:24:37 -0600 Subject: [PATCH 0077/2380] remove DSAParametersWithNumbers (#5724) Merged into DSAParameters, just like we did years ago for everything else. Somehow we missed this one. --- CHANGELOG.rst | 2 +- docs/hazmat/primitives/asymmetric/dsa.rst | 7 ------- src/cryptography/hazmat/backends/openssl/dsa.py | 2 +- src/cryptography/hazmat/primitives/asymmetric/dsa.py | 5 +++-- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 96a947f34645..51953a595743 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1347,7 +1347,7 @@ Changelog were moved from ``cryptography.hazmat.primitives.interfaces`` to ``cryptography.hazmat.primitives.asymmetric``. * :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameters`, - :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParametersWithNumbers`, + ``DSAParametersWithNumbers``, :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`, ``DSAPrivateKeyWithNumbers``, :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey` and diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst index b151b0ef4a95..60b162cb530a 100644 --- a/docs/hazmat/primitives/asymmetric/dsa.rst +++ b/docs/hazmat/primitives/asymmetric/dsa.rst @@ -267,13 +267,6 @@ Key interfaces :return: An instance of :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`. - -.. class:: DSAParametersWithNumbers - - .. versionadded:: 0.5 - - Extends :class:`DSAParameters`. - .. method:: parameter_numbers() Create a diff --git a/src/cryptography/hazmat/backends/openssl/dsa.py b/src/cryptography/hazmat/backends/openssl/dsa.py index fb8c4b27c313..a0633942a745 100644 --- a/src/cryptography/hazmat/backends/openssl/dsa.py +++ b/src/cryptography/hazmat/backends/openssl/dsa.py @@ -83,7 +83,7 @@ def finalize(self): return _dsa_sig_sign(self._backend, self._private_key, data_to_sign) -@utils.register_interface(dsa.DSAParametersWithNumbers) +@utils.register_interface(dsa.DSAParameters) class _DSAParameters(object): def __init__(self, backend, dsa_cdata): self._backend = backend diff --git a/src/cryptography/hazmat/primitives/asymmetric/dsa.py b/src/cryptography/hazmat/primitives/asymmetric/dsa.py index 63931bc94b76..0f5be8da2d8d 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dsa.py @@ -16,8 +16,6 @@ def generate_private_key(self): Generates and returns a DSAPrivateKey. """ - -class DSAParametersWithNumbers(DSAParameters, metaclass=abc.ABCMeta): @abc.abstractmethod def parameter_numbers(self): """ @@ -25,6 +23,9 @@ def parameter_numbers(self): """ +DSAParametersWithNumbers = DSAParameters + + class DSAPrivateKey(metaclass=abc.ABCMeta): @abc.abstractproperty def key_size(self): From 488379122860ca11d5003dda69271e53684b91b6 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 31 Jan 2021 16:25:12 -0600 Subject: [PATCH 0078/2380] merge pep8, mypy, and packaging jobs into one flake job (#5723) --- .github/workflows/ci.yml | 2 +- tox.ini | 21 ++++++--------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 14dcfeb378dc..d4d1b8fffca5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: PYTHON: - - {VERSION: "3.9", TOXENV: "pep8,rust,mypy,packaging,docs", COVERAGE: "false"} + - {VERSION: "3.9", TOXENV: "flake,rust,docs", COVERAGE: "false"} - {VERSION: "pypy3", TOXENV: "pypy3"} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1i"}} diff --git a/tox.ini b/tox.ini index 1e6fbcf784d9..79cbfb83d7b8 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 2.4 -envlist = pypy3,py36,py37,py38,py39,docs,pep8,rust,packaging +envlist = pypy3,py36,py37,py38,py39,docs,flake,rust isolated_build = True [testenv] @@ -37,22 +37,19 @@ basepython = python3 commands = sphinx-build -W -b linkcheck docs docs/_build/html -[testenv:pep8] +[testenv:flake] basepython = python3 extras = pep8test -commands = - flake8 . - black --check . - -[testenv:mypy] -basepython = python3 -extras = test ssh deps = mypy + check-manifest commands = + flake8 . + black --check . + check-manifest mypy src/cryptography/ vectors/cryptography_vectors/ [testenv:rust] @@ -64,12 +61,6 @@ commands = cargo fmt --all -- --check cargo clippy -- -D warnings -[testenv:packaging] -deps = - check-manifest -commands = - check-manifest - [flake8] ignore = E203,E211,W503,W504 exclude = .tox,*.egg,.git,_build,.hypothesis From 343ac1344a2a6657743a71109e5db06bb6fa4e70 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 31 Jan 2021 18:27:41 -0600 Subject: [PATCH 0079/2380] enable mypy over tests (#5721) * clean mypy with tests dir * remove most no_type_check annotations * le sigh * remove unneeded comments --- tests/doubles.py | 20 +++--- tests/hazmat/backends/test_openssl_memleak.py | 2 + tests/hazmat/primitives/test_aead.py | 14 ++-- tests/hazmat/primitives/test_block.py | 14 ++-- tests/hazmat/primitives/test_chacha20.py | 4 +- tests/hazmat/primitives/test_ciphers.py | 18 ++--- tests/hazmat/primitives/test_cmac.py | 10 +-- tests/hazmat/primitives/test_constant_time.py | 6 +- tests/hazmat/primitives/test_dh.py | 4 +- tests/hazmat/primitives/test_dsa.py | 33 +++++----- tests/hazmat/primitives/test_ec.py | 23 +++++-- tests/hazmat/primitives/test_hashes.py | 4 +- tests/hazmat/primitives/test_hmac.py | 8 ++- tests/hazmat/primitives/test_kbkdf.py | 1 + tests/hazmat/primitives/test_padding.py | 4 +- tests/hazmat/primitives/test_pkcs12.py | 4 +- tests/hazmat/primitives/test_pkcs7.py | 40 ++++++----- tests/hazmat/primitives/test_rsa.py | 4 ++ tests/hazmat/primitives/test_serialization.py | 20 ++++-- tests/hazmat/primitives/test_x963_vectors.py | 3 +- .../hazmat/primitives/twofactor/test_hotp.py | 4 +- tests/hazmat/primitives/utils.py | 5 +- tests/test_cryptography_utils.py | 8 +-- tests/test_fernet.py | 16 +++-- tests/test_warnings.py | 3 + tests/utils.py | 34 ++++++---- tests/wycheproof/test_dsa.py | 2 + tests/wycheproof/test_ecdsa.py | 1 + tests/wycheproof/test_rsa.py | 7 +- tests/x509/test_ocsp.py | 59 ++++++++++++----- tests/x509/test_x509.py | 66 ++++++++++++++----- tests/x509/test_x509_crlbuilder.py | 10 +-- tests/x509/test_x509_ext.py | 32 +++++---- tests/x509/test_x509_revokedcertbuilder.py | 10 ++- tox.ini | 2 +- 35 files changed, 309 insertions(+), 186 deletions(-) diff --git a/tests/doubles.py b/tests/doubles.py index 6a4a48323ad0..dd9bb9f0a469 100644 --- a/tests/doubles.py +++ b/tests/doubles.py @@ -3,40 +3,36 @@ # for complete details. -from cryptography import utils from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives.ciphers import CipherAlgorithm from cryptography.hazmat.primitives.ciphers.modes import Mode -@utils.register_interface(CipherAlgorithm) -class DummyCipherAlgorithm(object): +class DummyCipherAlgorithm(CipherAlgorithm): name = "dummy-cipher" block_size = 128 key_size = None -@utils.register_interface(Mode) -class DummyMode(object): +class DummyMode(Mode): name = "dummy-mode" def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: pass -@utils.register_interface(hashes.HashAlgorithm) -class DummyHashAlgorithm(object): +class DummyHashAlgorithm(hashes.HashAlgorithm): name = "dummy-hash" block_size = None - digest_size = None + digest_size = 32 -@utils.register_interface(serialization.KeySerializationEncryption) -class DummyKeySerializationEncryption(object): +class DummyKeySerializationEncryption( + serialization.KeySerializationEncryption +): pass -@utils.register_interface(padding.AsymmetricPadding) -class DummyAsymmetricPadding(object): +class DummyAsymmetricPadding(padding.AsymmetricPadding): name = "dummy-padding" diff --git a/tests/hazmat/backends/test_openssl_memleak.py b/tests/hazmat/backends/test_openssl_memleak.py index 950a41ac9ed0..0c96516fa19f 100644 --- a/tests/hazmat/backends/test_openssl_memleak.py +++ b/tests/hazmat/backends/test_openssl_memleak.py @@ -147,6 +147,8 @@ def assert_no_memory_leaks(s, argv=[]): stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) + assert proc.stdout is not None + assert proc.stderr is not None try: proc.wait() if proc.returncode == 255: diff --git a/tests/hazmat/primitives/test_aead.py b/tests/hazmat/primitives/test_aead.py index 6787cb503e73..87df06c6a8f0 100644 --- a/tests/hazmat/primitives/test_aead.py +++ b/tests/hazmat/primitives/test_aead.py @@ -25,7 +25,7 @@ ) -class FakeData(object): +class FakeData(bytes): def __len__(self): return 2 ** 32 + 1 @@ -71,7 +71,7 @@ def test_generate_key(self): def test_bad_key(self, backend): with pytest.raises(TypeError): - ChaCha20Poly1305(object()) + ChaCha20Poly1305(object()) # type:ignore[arg-type] with pytest.raises(ValueError): ChaCha20Poly1305(b"0" * 31) @@ -215,7 +215,7 @@ def test_invalid_tag_length(self, backend): AESCCM(key, tag_length=2) with pytest.raises(TypeError): - AESCCM(key, tag_length="notanint") + AESCCM(key, tag_length="notanint") # type:ignore[arg-type] def test_invalid_nonce_length(self, backend): key = AESCCM.generate_key(128) @@ -298,14 +298,14 @@ def test_params_not_bytes(self, nonce, data, associated_data, backend): def test_bad_key(self, backend): with pytest.raises(TypeError): - AESCCM(object()) + AESCCM(object()) # type:ignore[arg-type] with pytest.raises(ValueError): AESCCM(b"0" * 31) def test_bad_generate_key(self, backend): with pytest.raises(TypeError): - AESCCM.generate_key(object()) + AESCCM.generate_key(object()) # type:ignore[arg-type] with pytest.raises(ValueError): AESCCM.generate_key(129) @@ -430,14 +430,14 @@ def test_invalid_nonce_length(self, length, backend): def test_bad_key(self, backend): with pytest.raises(TypeError): - AESGCM(object()) + AESGCM(object()) # type:ignore[arg-type] with pytest.raises(ValueError): AESGCM(b"0" * 31) def test_bad_generate_key(self, backend): with pytest.raises(TypeError): - AESGCM.generate_key(object()) + AESGCM.generate_key(object()) # type:ignore[arg-type] with pytest.raises(ValueError): AESGCM.generate_key(129) diff --git a/tests/hazmat/primitives/test_block.py b/tests/hazmat/primitives/test_block.py index 24df0e637935..50f9fbb91ab6 100644 --- a/tests/hazmat/primitives/test_block.py +++ b/tests/hazmat/primitives/test_block.py @@ -194,28 +194,28 @@ def test_gcm(self): class TestModesRequireBytes(object): def test_cbc(self): with pytest.raises(TypeError): - modes.CBC([1] * 16) + modes.CBC([1] * 16) # type:ignore[arg-type] def test_cfb(self): with pytest.raises(TypeError): - modes.CFB([1] * 16) + modes.CFB([1] * 16) # type:ignore[arg-type] def test_cfb8(self): with pytest.raises(TypeError): - modes.CFB8([1] * 16) + modes.CFB8([1] * 16) # type:ignore[arg-type] def test_ofb(self): with pytest.raises(TypeError): - modes.OFB([1] * 16) + modes.OFB([1] * 16) # type:ignore[arg-type] def test_ctr(self): with pytest.raises(TypeError): - modes.CTR([1] * 16) + modes.CTR([1] * 16) # type:ignore[arg-type] def test_gcm_iv(self): with pytest.raises(TypeError): - modes.GCM([1] * 16) + modes.GCM([1] * 16) # type:ignore[arg-type] def test_gcm_tag(self): with pytest.raises(TypeError): - modes.GCM(b"\x00" * 16, [1] * 16) + modes.GCM(b"\x00" * 16, [1] * 16) # type:ignore[arg-type] diff --git a/tests/hazmat/primitives/test_chacha20.py b/tests/hazmat/primitives/test_chacha20.py index 48733911148e..03165a4d1c32 100644 --- a/tests/hazmat/primitives/test_chacha20.py +++ b/tests/hazmat/primitives/test_chacha20.py @@ -66,8 +66,8 @@ def test_invalid_nonce(self): algorithms.ChaCha20(b"0" * 32, b"0") with pytest.raises(TypeError): - algorithms.ChaCha20(b"0" * 32, object()) + algorithms.ChaCha20(b"0" * 32, object()) # type:ignore[arg-type] def test_invalid_key_type(self): with pytest.raises(TypeError, match="key must be bytes"): - algorithms.ChaCha20("0" * 32, b"0" * 16) + algorithms.ChaCha20("0" * 32, b"0" * 16) # type:ignore[arg-type] diff --git a/tests/hazmat/primitives/test_ciphers.py b/tests/hazmat/primitives/test_ciphers.py index 5fb6a916e117..694141821096 100644 --- a/tests/hazmat/primitives/test_ciphers.py +++ b/tests/hazmat/primitives/test_ciphers.py @@ -45,7 +45,7 @@ def test_invalid_key_size(self): def test_invalid_key_type(self): with pytest.raises(TypeError, match="key must be bytes"): - AES("0" * 32) + AES("0" * 32) # type: ignore[arg-type] class TestAESXTS(object): @@ -59,7 +59,7 @@ def test_invalid_key_size_with_mode(self, mode, backend): def test_xts_tweak_not_bytes(self): with pytest.raises(TypeError): - modes.XTS(32) + modes.XTS(32) # type: ignore[arg-type] def test_xts_tweak_too_small(self): with pytest.raises(ValueError): @@ -93,7 +93,7 @@ def test_invalid_key_size(self): def test_invalid_key_type(self): with pytest.raises(TypeError, match="key must be bytes"): - Camellia("0" * 32) + Camellia("0" * 32) # type: ignore[arg-type] class TestTripleDES(object): @@ -108,7 +108,7 @@ def test_invalid_key_size(self): def test_invalid_key_type(self): with pytest.raises(TypeError, match="key must be bytes"): - TripleDES("0" * 16) + TripleDES("0" * 16) # type: ignore[arg-type] class TestBlowfish(object): @@ -126,7 +126,7 @@ def test_invalid_key_size(self): def test_invalid_key_type(self): with pytest.raises(TypeError, match="key must be bytes"): - Blowfish("0" * 8) + Blowfish("0" * 8) # type: ignore[arg-type] class TestCAST5(object): @@ -144,7 +144,7 @@ def test_invalid_key_size(self): def test_invalid_key_type(self): with pytest.raises(TypeError, match="key must be bytes"): - CAST5("0" * 10) + CAST5("0" * 10) # type: ignore[arg-type] class TestARC4(object): @@ -170,7 +170,7 @@ def test_invalid_key_size(self): def test_invalid_key_type(self): with pytest.raises(TypeError, match="key must be bytes"): - ARC4("0" * 10) + ARC4("0" * 10) # type: ignore[arg-type] class TestIDEA(object): @@ -184,7 +184,7 @@ def test_invalid_key_size(self): def test_invalid_key_type(self): with pytest.raises(TypeError, match="key must be bytes"): - IDEA("0" * 16) + IDEA("0" * 16) # type: ignore[arg-type] class TestSEED(object): @@ -198,7 +198,7 @@ def test_invalid_key_size(self): def test_invalid_key_type(self): with pytest.raises(TypeError, match="key must be bytes"): - SEED("0" * 16) + SEED("0" * 16) # type: ignore[arg-type] def test_invalid_backend(): diff --git a/tests/hazmat/primitives/test_cmac.py b/tests/hazmat/primitives/test_cmac.py index 03c4cd8a6ca0..0022ab05c5e6 100644 --- a/tests/hazmat/primitives/test_cmac.py +++ b/tests/hazmat/primitives/test_cmac.py @@ -80,7 +80,7 @@ def test_aes_verify(self, backend, params): cmac = CMAC(AES(binascii.unhexlify(key)), backend) cmac.update(binascii.unhexlify(message)) - assert cmac.verify(binascii.unhexlify(output)) is None + cmac.verify(binascii.unhexlify(output)) @pytest.mark.supported( only_if=lambda backend: backend.cmac_algorithm_supported( @@ -122,7 +122,7 @@ def test_3des_verify(self, backend, params): cmac = CMAC(TripleDES(binascii.unhexlify(key)), backend) cmac.update(binascii.unhexlify(message)) - assert cmac.verify(binascii.unhexlify(output)) is None + cmac.verify(binascii.unhexlify(output)) @pytest.mark.supported( only_if=lambda backend: backend.cmac_algorithm_supported( @@ -145,7 +145,7 @@ def test_invalid_verify(self, backend): def test_invalid_algorithm(self, backend): key = b"0102030405" with pytest.raises(TypeError): - CMAC(ARC4(key), backend) + CMAC(ARC4(key), backend) # type: ignore[arg-type] @pytest.mark.supported( only_if=lambda backend: backend.cmac_algorithm_supported( @@ -181,10 +181,10 @@ def test_verify_reject_unicode(self, backend): cmac = CMAC(AES(key), backend) with pytest.raises(TypeError): - cmac.update("") + cmac.update("") # type: ignore[arg-type] with pytest.raises(TypeError): - cmac.verify("") + cmac.verify("") # type: ignore[arg-type] @pytest.mark.supported( only_if=lambda backend: backend.cmac_algorithm_supported( diff --git a/tests/hazmat/primitives/test_constant_time.py b/tests/hazmat/primitives/test_constant_time.py index 39e51b4052a7..5e3fdfb25d49 100644 --- a/tests/hazmat/primitives/test_constant_time.py +++ b/tests/hazmat/primitives/test_constant_time.py @@ -11,13 +11,13 @@ class TestConstantTimeBytesEq(object): def test_reject_unicode(self): with pytest.raises(TypeError): - constant_time.bytes_eq(b"foo", "foo") + constant_time.bytes_eq(b"foo", "foo") # type: ignore[arg-type] with pytest.raises(TypeError): - constant_time.bytes_eq("foo", b"foo") + constant_time.bytes_eq("foo", b"foo") # type: ignore[arg-type] with pytest.raises(TypeError): - constant_time.bytes_eq("foo", "foo") + constant_time.bytes_eq("foo", "foo") # type: ignore[arg-type] def test_compares(self): assert constant_time.bytes_eq(b"foo", b"foo") is True diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index 02536093d789..4845ae7ef45a 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -6,6 +6,7 @@ import binascii import itertools import os +import typing import pytest @@ -203,7 +204,7 @@ def test_convert_to_numbers(self, backend, with_q): )[0] p = int(vector["p"], 16) g = int(vector["g"], 16) - q = int(vector["q"], 16) + q: typing.Optional[int] = int(vector["q"], 16) else: parameters = backend.generate_dh_private_key_and_parameters(2, 512) @@ -388,6 +389,7 @@ def test_load_256bit_key_from_pkcs8(self, backend): mode="rb", ) key = serialization.load_pem_private_key(data, None, backend) + assert isinstance(key, dh.DHPrivateKey) assert key.key_size == 256 @pytest.mark.parametrize( diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py index b247247dd947..56d37d84f093 100644 --- a/tests/hazmat/primitives/test_dsa.py +++ b/tests/hazmat/primitives/test_dsa.py @@ -5,6 +5,7 @@ import itertools import os +import typing import pytest @@ -30,6 +31,14 @@ load_vectors_from_file, ) +_ALGORITHMS_DICT: typing.Dict[str, typing.Type[hashes.HashAlgorithm]] = { + "SHA1": hashes.SHA1, + "SHA224": hashes.SHA224, + "SHA256": hashes.SHA256, + "SHA384": hashes.SHA384, + "SHA512": hashes.SHA512, +} + def _skip_if_dsa_not_supported(backend, algorithm, p, q, g): if not backend.dsa_parameters_supported( @@ -378,14 +387,6 @@ def test_large_p(self, backend): @pytest.mark.requires_backend_interface(interface=DSABackend) class TestDSAVerification(object): - _algorithms_dict = { - "SHA1": hashes.SHA1, - "SHA224": hashes.SHA224, - "SHA256": hashes.SHA256, - "SHA384": hashes.SHA384, - "SHA512": hashes.SHA512, - } - def test_dsa_verification(self, backend, subtests): vectors = load_vectors_from_file( os.path.join("asymmetric", "DSA", "FIPS_186-3", "SigVer.rsp"), @@ -394,7 +395,7 @@ def test_dsa_verification(self, backend, subtests): for vector in vectors: with subtests.test(): digest_algorithm = vector["digest_algorithm"].replace("-", "") - algorithm = self._algorithms_dict[digest_algorithm] + algorithm = _ALGORITHMS_DICT[digest_algorithm] _skip_if_dsa_not_supported( backend, algorithm, vector["p"], vector["q"], vector["g"] @@ -485,14 +486,6 @@ def test_prehashed_unsupported_in_verifier_ctx(self, backend): @pytest.mark.requires_backend_interface(interface=DSABackend) class TestDSASignature(object): - _algorithms_dict = { - "SHA1": hashes.SHA1, - "SHA224": hashes.SHA224, - "SHA256": hashes.SHA256, - "SHA384": hashes.SHA384, - "SHA512": hashes.SHA512, - } - def test_dsa_signing(self, backend, subtests): vectors = load_vectors_from_file( os.path.join("asymmetric", "DSA", "FIPS_186-3", "SigGen.txt"), @@ -501,7 +494,7 @@ def test_dsa_signing(self, backend, subtests): for vector in vectors: with subtests.test(): digest_algorithm = vector["digest_algorithm"].replace("-", "") - algorithm = self._algorithms_dict[digest_algorithm] + algorithm = _ALGORITHMS_DICT[digest_algorithm] _skip_if_dsa_not_supported( backend, algorithm, vector["p"], vector["q"], vector["g"] @@ -711,6 +704,7 @@ def test_private_bytes_encrypted_pem(self, backend, fmt, password): lambda pemfile: pemfile.read().encode(), ) key = serialization.load_pem_private_key(key_bytes, None, backend) + assert isinstance(key, dsa.DSAPrivateKey) serialized = key.private_bytes( serialization.Encoding.PEM, fmt, @@ -719,6 +713,7 @@ def test_private_bytes_encrypted_pem(self, backend, fmt, password): loaded_key = serialization.load_pem_private_key( serialized, password, backend ) + assert isinstance(loaded_key, dsa.DSAPrivateKey) loaded_priv_num = loaded_key.private_numbers() priv_num = key.private_numbers() assert loaded_priv_num == priv_num @@ -752,6 +747,7 @@ def test_private_bytes_encrypted_der(self, backend, fmt, password): lambda pemfile: pemfile.read().encode(), ) key = serialization.load_pem_private_key(key_bytes, None, backend) + assert isinstance(key, dsa.DSAPrivateKey) serialized = key.private_bytes( serialization.Encoding.DER, fmt, @@ -760,6 +756,7 @@ def test_private_bytes_encrypted_der(self, backend, fmt, password): loaded_key = serialization.load_der_private_key( serialized, password, backend ) + assert isinstance(loaded_key, dsa.DSAPrivateKey) loaded_priv_num = loaded_key.private_numbers() priv_num = key.private_numbers() assert loaded_priv_num == priv_num diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index f6569ec6056a..b69475a12d9d 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -6,6 +6,7 @@ import binascii import itertools import os +import typing from binascii import hexlify import pytest @@ -35,7 +36,7 @@ raises_unsupported_algorithm, ) -_HASH_TYPES = { +_HASH_TYPES: typing.Dict[str, typing.Type[hashes.HashAlgorithm]] = { "SHA-1": hashes.SHA1, "SHA-224": hashes.SHA224, "SHA-256": hashes.SHA256, @@ -81,14 +82,12 @@ def test_get_curve_for_oid(): ec.get_curve_for_oid(x509.ObjectIdentifier("1.1.1.1")) -@utils.register_interface(ec.EllipticCurve) -class DummyCurve(object): +class DummyCurve(ec.EllipticCurve): name = "dummy-curve" key_size = 1 -@utils.register_interface(ec.EllipticCurveSignatureAlgorithm) -class DummySignatureAlgorithm(object): +class DummySignatureAlgorithm(ec.EllipticCurveSignatureAlgorithm): algorithm = None @@ -290,7 +289,9 @@ def test_with_numbers(self, backend, subtests): ) for vector, hash_type in vectors: with subtests.test(): - curve_type = ec._CURVE_TYPES[vector["curve"]] + curve_type: typing.Type[ec.EllipticCurve] = ec._CURVE_TYPES[ + vector["curve"] + ] _skip_ecdsa_vector(backend, curve_type, hash_type) @@ -502,7 +503,9 @@ def test_signatures(self, backend, subtests): for vector in vectors: with subtests.test(): hash_type = _HASH_TYPES[vector["digest_algorithm"]] - curve_type = ec._CURVE_TYPES[vector["curve"]] + curve_type: typing.Type[ec.EllipticCurve] = ec._CURVE_TYPES[ + vector["curve"] + ] _skip_ecdsa_vector(backend, curve_type, hash_type) @@ -689,6 +692,7 @@ def test_private_bytes_encrypted_pem(self, backend, fmt, password): lambda pemfile: pemfile.read().encode(), ) key = serialization.load_pem_private_key(key_bytes, None, backend) + assert isinstance(key, ec.EllipticCurvePrivateKey) serialized = key.private_bytes( serialization.Encoding.PEM, fmt, @@ -697,6 +701,7 @@ def test_private_bytes_encrypted_pem(self, backend, fmt, password): loaded_key = serialization.load_pem_private_key( serialized, password, backend ) + assert isinstance(loaded_key, ec.EllipticCurvePrivateKey) loaded_priv_num = loaded_key.private_numbers() priv_num = key.private_numbers() assert loaded_priv_num == priv_num @@ -732,6 +737,7 @@ def test_private_bytes_encrypted_der(self, backend, fmt, password): lambda pemfile: pemfile.read().encode(), ) key = serialization.load_pem_private_key(key_bytes, None, backend) + assert isinstance(key, ec.EllipticCurvePrivateKey) serialized = key.private_bytes( serialization.Encoding.DER, fmt, @@ -740,6 +746,7 @@ def test_private_bytes_encrypted_der(self, backend, fmt, password): loaded_key = serialization.load_der_private_key( serialized, password, backend ) + assert isinstance(loaded_key, ec.EllipticCurvePrivateKey) loaded_priv_num = loaded_key.private_numbers() priv_num = key.private_numbers() assert loaded_priv_num == priv_num @@ -778,10 +785,12 @@ def test_private_bytes_unencrypted( lambda pemfile: pemfile.read().encode(), ) key = serialization.load_pem_private_key(key_bytes, None, backend) + assert isinstance(key, ec.EllipticCurvePrivateKey) serialized = key.private_bytes( encoding, fmt, serialization.NoEncryption() ) loaded_key = loader_func(serialized, None, backend) + assert isinstance(loaded_key, ec.EllipticCurvePrivateKey) loaded_priv_num = loaded_key.private_numbers() priv_num = key.private_numbers() assert loaded_priv_num == priv_num diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py index 105f862d8619..559eb6d674c4 100644 --- a/tests/hazmat/primitives/test_hashes.py +++ b/tests/hazmat/primitives/test_hashes.py @@ -21,11 +21,11 @@ class TestHashContext(object): def test_hash_reject_unicode(self, backend): m = hashes.Hash(hashes.SHA1(), backend=backend) with pytest.raises(TypeError): - m.update("\u00FC") + m.update("\u00FC") # type: ignore[arg-type] def test_hash_algorithm_instance(self, backend): with pytest.raises(TypeError): - hashes.Hash(hashes.SHA1, backend=backend) + hashes.Hash(hashes.SHA1, backend=backend) # type: ignore[arg-type] def test_raises_after_finalize(self, backend): h = hashes.Hash(hashes.SHA1(), backend=backend) diff --git a/tests/hazmat/primitives/test_hmac.py b/tests/hazmat/primitives/test_hmac.py index 618f47322cde..0321eff94b1f 100644 --- a/tests/hazmat/primitives/test_hmac.py +++ b/tests/hazmat/primitives/test_hmac.py @@ -36,11 +36,13 @@ class TestHMAC(object): def test_hmac_reject_unicode(self, backend): h = hmac.HMAC(b"mykey", hashes.SHA1(), backend=backend) with pytest.raises(TypeError): - h.update("\u00FC") + h.update("\u00FC") # type: ignore[arg-type] def test_hmac_algorithm_instance(self, backend): with pytest.raises(TypeError): - hmac.HMAC(b"key", hashes.SHA1, backend=backend) + hmac.HMAC( + b"key", hashes.SHA1, backend=backend # type: ignore[arg-type] + ) def test_raises_after_finalize(self, backend): h = hmac.HMAC(b"key", hashes.SHA1(), backend=backend) @@ -76,7 +78,7 @@ def test_invalid_verify(self, backend): def test_verify_reject_unicode(self, backend): h = hmac.HMAC(b"", hashes.SHA1(), backend=backend) with pytest.raises(TypeError): - h.verify("") + h.verify("") # type: ignore[arg-type] def test_unsupported_hash(self, backend): with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_HASH): diff --git a/tests/hazmat/primitives/test_kbkdf.py b/tests/hazmat/primitives/test_kbkdf.py index 3f13a0c7c774..b80d33f220da 100644 --- a/tests/hazmat/primitives/test_kbkdf.py +++ b/tests/hazmat/primitives/test_kbkdf.py @@ -284,6 +284,7 @@ def test_unicode_error_label(self, backend): CounterLocation.BeforeFixed, "label", b"context", + None, backend=backend, ) diff --git a/tests/hazmat/primitives/test_padding.py b/tests/hazmat/primitives/test_padding.py index 2a526401f117..bd2d8d73bce5 100644 --- a/tests/hazmat/primitives/test_padding.py +++ b/tests/hazmat/primitives/test_padding.py @@ -158,10 +158,10 @@ def test_invalid_padding(self, size, padded): def test_non_bytes(self): padder = padding.ANSIX923(128).padder() with pytest.raises(TypeError): - padder.update("abc") + padder.update("abc") # type: ignore[arg-type] unpadder = padding.ANSIX923(128).unpadder() with pytest.raises(TypeError): - unpadder.update("abc") + unpadder.update("abc") # type: ignore[arg-type] def test_zany_py2_bytes_subclass(self): class mybytes(bytes): # noqa: N801 diff --git a/tests/hazmat/primitives/test_pkcs12.py b/tests/hazmat/primitives/test_pkcs12.py index 9880666bbb1d..6691204e2e40 100644 --- a/tests/hazmat/primitives/test_pkcs12.py +++ b/tests/hazmat/primitives/test_pkcs12.py @@ -114,7 +114,9 @@ def test_load_pkcs12_key_only(self, backend): def test_non_bytes(self, backend): with pytest.raises(TypeError): - load_key_and_certificates(b"irrelevant", object(), backend) + load_key_and_certificates( + b"irrelevant", object(), backend # type: ignore[arg-type] + ) def test_not_a_pkcs12(self, backend): with pytest.raises(ValueError): diff --git a/tests/hazmat/primitives/test_pkcs7.py b/tests/hazmat/primitives/test_pkcs7.py index 5985863c6404..8ee06db05073 100644 --- a/tests/hazmat/primitives/test_pkcs7.py +++ b/tests/hazmat/primitives/test_pkcs7.py @@ -4,6 +4,7 @@ import os +import typing import pytest @@ -28,11 +29,11 @@ def test_load_invalid_pem_pkcs7(self): def test_not_bytes_der(self): with pytest.raises(TypeError): - pkcs7.load_der_pkcs7_certificates(38) + pkcs7.load_der_pkcs7_certificates(38) # type: ignore[arg-type] def test_not_bytes_pem(self): with pytest.raises(TypeError): - pkcs7.load_pem_pkcs7_certificates(38) + pkcs7.load_pem_pkcs7_certificates(38) # type: ignore[arg-type] def test_load_pkcs7_pem(self): certs = load_vectors_from_file( @@ -143,7 +144,7 @@ class TestPKCS7Builder(object): def test_invalid_data(self): builder = pkcs7.PKCS7SignatureBuilder() with pytest.raises(TypeError): - builder.set_data("not bytes") + builder.set_data("not bytes") # type: ignore[arg-type] def test_set_data_twice(self): builder = pkcs7.PKCS7SignatureBuilder().set_data(b"test") @@ -167,14 +168,14 @@ def test_unsupported_hash_alg(self): cert, key = _load_cert_key() with pytest.raises(TypeError): pkcs7.PKCS7SignatureBuilder().add_signer( - cert, key, hashes.SHA512_256() + cert, key, hashes.SHA512_256() # type: ignore[arg-type] ) def test_not_a_cert(self): cert, key = _load_cert_key() with pytest.raises(TypeError): pkcs7.PKCS7SignatureBuilder().add_signer( - b"notacert", key, hashes.SHA256() + b"notacert", key, hashes.SHA256() # type: ignore[arg-type] ) @pytest.mark.supported( @@ -197,7 +198,10 @@ def test_sign_invalid_options(self): .add_signer(cert, key, hashes.SHA256()) ) with pytest.raises(ValueError): - builder.sign(serialization.Encoding.SMIME, [b"invalid"]) + builder.sign( + serialization.Encoding.SMIME, + [b"invalid"], # type: ignore[list-item] + ) def test_sign_invalid_encoding(self): cert, key = _load_cert_key() @@ -298,7 +302,7 @@ def test_sign_byteslike(self): def test_sign_pem(self, backend): data = b"hello world" cert, key = _load_cert_key() - options = [] + options: typing.List[pkcs7.PKCS7Options] = [] builder = ( pkcs7.PKCS7SignatureBuilder() .set_data(data) @@ -334,7 +338,7 @@ def test_sign_alternate_digests_der( .set_data(data) .add_signer(cert, key, hash_alg) ) - options = [] + options: typing.List[pkcs7.PKCS7Options] = [] sig = builder.sign(serialization.Encoding.DER, options) assert expected_value in sig _pkcs7_verify( @@ -367,7 +371,7 @@ def test_sign_alternate_digests_detached(self, hash_alg, expected_value): def test_sign_attached(self, backend): data = b"hello world" cert, key = _load_cert_key() - options = [] + options: typing.List[pkcs7.PKCS7Options] = [] builder = ( pkcs7.PKCS7SignatureBuilder() .set_data(data) @@ -395,7 +399,7 @@ def test_sign_binary(self, backend): .set_data(data) .add_signer(cert, key, hashes.SHA256()) ) - options = [] + options: typing.List[pkcs7.PKCS7Options] = [] sig_no_binary = builder.sign(serialization.Encoding.DER, options) sig_binary = builder.sign( serialization.Encoding.DER, [pkcs7.PKCS7Options.Binary] @@ -431,7 +435,7 @@ def test_sign_smime_canonicalization(self, backend): .add_signer(cert, key, hashes.SHA256()) ) - options = [] + options: typing.List[pkcs7.PKCS7Options] = [] sig_binary = builder.sign(serialization.Encoding.DER, options) # LF gets converted to CR+LF (SMIME canonical form) # so data should not be present in the sig @@ -541,7 +545,7 @@ def test_sign_no_certs(self, backend): .add_signer(cert, key, hashes.SHA256()) ) - options = [] + options: typing.List[pkcs7.PKCS7Options] = [] sig = builder.sign(serialization.Encoding.DER, options) assert sig.count(cert.public_bytes(serialization.Encoding.DER)) == 1 @@ -572,7 +576,7 @@ def test_multiple_signers(self, backend): .add_signer(cert, key, hashes.SHA512()) .add_signer(rsa_cert, rsa_key, hashes.SHA512()) ) - options = [] + options: typing.List[pkcs7.PKCS7Options] = [] sig = builder.sign(serialization.Encoding.DER, options) # There should be three SHA512 OIDs in this structure assert sig.count(b"\x06\t`\x86H\x01e\x03\x04\x02\x03") == 3 @@ -608,7 +612,7 @@ def test_multiple_signers_different_hash_algs(self, backend): .add_signer(cert, key, hashes.SHA384()) .add_signer(rsa_cert, rsa_key, hashes.SHA512()) ) - options = [] + options: typing.List[pkcs7.PKCS7Options] = [] sig = builder.sign(serialization.Encoding.DER, options) # There should be two SHA384 and two SHA512 OIDs in this structure assert sig.count(b"\x06\t`\x86H\x01e\x03\x04\x02\x02") == 2 @@ -624,7 +628,9 @@ def test_multiple_signers_different_hash_algs(self, backend): def test_add_additional_cert_not_a_cert(self, backend): with pytest.raises(TypeError): - pkcs7.PKCS7SignatureBuilder().add_certificate(b"notacert") + pkcs7.PKCS7SignatureBuilder().add_certificate( + b"notacert" # type: ignore[arg-type] + ) def test_add_additional_cert(self, backend): data = b"hello world" @@ -642,7 +648,7 @@ def test_add_additional_cert(self, backend): .add_signer(cert, key, hashes.SHA384()) .add_certificate(rsa_cert) ) - options = [] + options: typing.List[pkcs7.PKCS7Options] = [] sig = builder.sign(serialization.Encoding.DER, options) assert ( sig.count(rsa_cert.public_bytes(serialization.Encoding.DER)) == 1 @@ -665,7 +671,7 @@ def test_add_multiple_additional_certs(self, backend): .add_certificate(rsa_cert) .add_certificate(rsa_cert) ) - options = [] + options: typing.List[pkcs7.PKCS7Options] = [] sig = builder.sign(serialization.Encoding.DER, options) assert ( sig.count(rsa_cert.public_bytes(serialization.Encoding.DER)) == 2 diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 188338ef90f9..069fb0977bb8 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -276,6 +276,7 @@ def test_oaep_label_decrypt(self, vector, backend): private_key = serialization.load_der_private_key( binascii.unhexlify(vector["key"]), None, backend ) + assert isinstance(private_key, rsa.RSAPrivateKey) assert vector["oaepdigest"] == b"SHA512" decrypted = private_key.decrypt( binascii.unhexlify(vector["input"]), @@ -844,6 +845,7 @@ def test_invalid_signature_sequence_removed(self, backend): b"bda3b33946490057b9a3003d3fd9daf7c4778b43fd46144d945d815f12628ff4" ) public_key = serialization.load_der_public_key(key_der, backend) + assert isinstance(public_key, rsa.RSAPublicKey) with pytest.raises(InvalidSignature): public_key.verify( sig, @@ -2164,6 +2166,7 @@ def test_private_bytes_encrypted_pem(self, backend, fmt, password): loaded_key = serialization.load_pem_private_key( serialized, password, backend ) + assert isinstance(loaded_key, rsa.RSAPrivateKey) loaded_priv_num = loaded_key.private_numbers() priv_num = key.private_numbers() assert loaded_priv_num == priv_num @@ -2201,6 +2204,7 @@ def test_private_bytes_encrypted_der(self, backend, fmt, password): loaded_key = serialization.load_der_private_key( serialized, password, backend ) + assert isinstance(loaded_key, rsa.RSAPrivateKey) loaded_priv_num = loaded_key.private_numbers() priv_num = key.private_numbers() assert loaded_priv_num == priv_num diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index 06e427acd21c..ca969e031cfc 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -30,6 +30,7 @@ from cryptography.hazmat.primitives.serialization import ( BestAvailableEncryption, Encoding, + KeySerializationEncryption, NoEncryption, PrivateFormat, PublicFormat, @@ -172,7 +173,9 @@ def test_password_not_bytes(self, key_path, backend): load_vectors_from_file( key_file, lambda derfile: load_der_private_key( - derfile.read(), password, backend + derfile.read(), + password, # type:ignore[arg-type] + backend, ), mode="rb", ) @@ -630,7 +633,9 @@ def test_password_not_bytes(self, key_path, backend): load_vectors_from_file( key_file, lambda pemfile: load_pem_private_key( - pemfile.read().encode(), password, backend + pemfile.read().encode(), + password, # type:ignore[arg-type] + backend, ), ) @@ -1247,6 +1252,7 @@ def test_load_ssh_public_key_ecdsa_nist_p384(self, backend): b"qQtRSEU8Tg== root@cloud-server-01" ) key = load_ssh_public_key(ssh_key, backend) + assert isinstance(key, ec.EllipticCurvePublicKey) expected_x = int( "31541830871345183397582554827482786756220448716666815789487537666" @@ -1273,6 +1279,7 @@ def test_load_ssh_public_key_ecdsa_nist_p521(self, backend): b"root@cloud-server-01" ) key = load_ssh_public_key(ssh_key, backend) + assert isinstance(key, ec.EllipticCurvePublicKey) expected_x = int( "54124123120178189598842622575230904027376313369742467279346415219" @@ -1379,7 +1386,7 @@ def test_load_ssh_public_key_trailing_data(self, backend): class TestKeySerializationEncryptionTypes(object): def test_non_bytes_password(self): with pytest.raises(ValueError): - BestAvailableEncryption(object()) + BestAvailableEncryption(object()) # type:ignore[arg-type] def test_encryption_with_zero_length_password(self): with pytest.raises(ValueError): @@ -1961,7 +1968,7 @@ def test_load_ssh_private_key(self, key_file, backend): ) # serialize with own code and reload - encryption = NoEncryption() + encryption: KeySerializationEncryption = NoEncryption() if password: encryption = BestAvailableEncryption(password) priv_data2 = private_key.private_bytes( @@ -2294,7 +2301,10 @@ def test_serialize_ssh_private_key_errors(self, backend): # bad object type with pytest.raises(ValueError): - ssh.serialize_ssh_private_key(object(), None) + ssh.serialize_ssh_private_key( + object(), # type:ignore[arg-type] + None, + ) private_key = ec.generate_private_key(ec.SECP256R1(), backend) diff --git a/tests/hazmat/primitives/test_x963_vectors.py b/tests/hazmat/primitives/test_x963_vectors.py index b374b6e7a5a0..ef3a186e1894 100644 --- a/tests/hazmat/primitives/test_x963_vectors.py +++ b/tests/hazmat/primitives/test_x963_vectors.py @@ -5,6 +5,7 @@ import binascii import os +import typing import pytest @@ -27,7 +28,7 @@ def _skip_hashfn_unsupported(backend, hashfn): @pytest.mark.requires_backend_interface(interface=HashBackend) class TestX963(object): - _algorithms_dict = { + _algorithms_dict: typing.Dict[str, typing.Type[hashes.HashAlgorithm]] = { "SHA-1": hashes.SHA1, "SHA-224": hashes.SHA224, "SHA-256": hashes.SHA256, diff --git a/tests/hazmat/primitives/twofactor/test_hotp.py b/tests/hazmat/primitives/twofactor/test_hotp.py index 2b65cde963de..04013b166fe4 100644 --- a/tests/hazmat/primitives/twofactor/test_hotp.py +++ b/tests/hazmat/primitives/twofactor/test_hotp.py @@ -49,7 +49,7 @@ def test_invalid_algorithm(self, backend): secret = os.urandom(16) with pytest.raises(TypeError): - HOTP(secret, 6, MD5(), backend) + HOTP(secret, 6, MD5(), backend) # type: ignore[arg-type] @pytest.mark.parametrize("params", vectors) def test_truncate(self, backend, params): @@ -94,7 +94,7 @@ def test_length_not_int(self, backend): secret = b"12345678901234567890" with pytest.raises(TypeError): - HOTP(secret, b"foo", SHA1(), backend) + HOTP(secret, b"foo", SHA1(), backend) # type: ignore[arg-type] def test_get_provisioning_uri(self, backend): secret = b"12345678901234567890" diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py index 8bee115e23ea..44af12dcbf4f 100644 --- a/tests/hazmat/primitives/utils.py +++ b/tests/hazmat/primitives/utils.py @@ -5,6 +5,7 @@ import binascii import os +import typing import pytest @@ -411,7 +412,9 @@ def test_kbkdf(self, backend, subtests): def kbkdf_counter_mode_test(backend, params): - supported_algorithms = { + supported_algorithms: typing.Dict[ + str, typing.Type[hashes.HashAlgorithm] + ] = { "hmac_sha1": hashes.SHA1, "hmac_sha224": hashes.SHA224, "hmac_sha256": hashes.SHA256, diff --git a/tests/test_cryptography_utils.py b/tests/test_cryptography_utils.py index ba6da5c50a05..6b795e0c683a 100644 --- a/tests/test_cryptography_utils.py +++ b/tests/test_cryptography_utils.py @@ -2,6 +2,7 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. +import typing import pytest @@ -10,14 +11,14 @@ class TestCachedProperty(object): def test_simple(self): - accesses = [] - class T(object): @utils.cached_property def t(self): accesses.append(None) return 14 + accesses: typing.List[typing.Optional[T]] = [] + assert T.t t = T() assert t.t == 14 @@ -32,14 +33,13 @@ def t(self): assert len(accesses) == 2 def test_set(self): - accesses = [] - class T(object): @utils.cached_property def t(self): accesses.append(None) return 14 + accesses: typing.List[typing.Optional[T]] = [] t = T() with pytest.raises(AttributeError): t.t = None diff --git a/tests/test_fernet.py b/tests/test_fernet.py index a2afaa596331..fc21398834a8 100644 --- a/tests/test_fernet.py +++ b/tests/test_fernet.py @@ -112,9 +112,9 @@ def test_non_base64_token(self, backend): def test_unicode(self, backend): f = Fernet(base64.urlsafe_b64encode(b"\x00" * 32), backend=backend) with pytest.raises(TypeError): - f.encrypt("") + f.encrypt("") # type: ignore[arg-type] with pytest.raises(TypeError): - f.decrypt("") + f.decrypt("") # type: ignore[arg-type] def test_timestamp_ignored_no_ttl(self, monkeypatch, backend): f = Fernet(base64.urlsafe_b64encode(b"\x00" * 32), backend=backend) @@ -128,7 +128,11 @@ def test_ttl_required_in_decrypt_at_time(self, monkeypatch, backend): pt = b"encrypt me" token = f.encrypt(pt) with pytest.raises(ValueError): - f.decrypt_at_time(token, ttl=None, current_time=int(time.time())) + f.decrypt_at_time( + token, + ttl=None, # type: ignore[arg-type] + current_time=int(time.time()), + ) @pytest.mark.parametrize("message", [b"", b"Abc!", b"\x00\xFF\x00\x80"]) def test_roundtrips(self, message, backend): @@ -184,7 +188,9 @@ def test_decrypt_at_time(self, backend): with pytest.raises(InvalidToken): f.decrypt_at_time(token, ttl=1, current_time=102) with pytest.raises(ValueError): - f.decrypt_at_time(token, ttl=None, current_time=100) + f.decrypt_at_time( + token, ttl=None, current_time=100 # type: ignore[arg-type] + ) def test_no_fernets(self, backend): with pytest.raises(ValueError): @@ -192,7 +198,7 @@ def test_no_fernets(self, backend): def test_non_iterable_argument(self, backend): with pytest.raises(TypeError): - MultiFernet(None) + MultiFernet(None) # type: ignore[arg-type] def test_rotate(self, backend): f1 = Fernet(base64.urlsafe_b64encode(b"\x00" * 32), backend=backend) diff --git a/tests/test_warnings.py b/tests/test_warnings.py index d08f31e3a5a7..cff639dd6810 100644 --- a/tests/test_warnings.py +++ b/tests/test_warnings.py @@ -5,6 +5,7 @@ import sys import types +import typing import warnings import pytest @@ -13,6 +14,7 @@ class TestDeprecated(object): + @typing.no_type_check def test_deprecated(self, monkeypatch): mod = types.ModuleType("TestDeprecated/test_deprecated") monkeypatch.setitem(sys.modules, mod.__name__, mod) @@ -47,6 +49,7 @@ def test_deprecated(self, monkeypatch): assert "Y" in dir(mod) + @typing.no_type_check def test_deleting_deprecated_members(self, monkeypatch): mod = types.ModuleType("TestDeprecated/test_deprecated") monkeypatch.setitem(sys.modules, mod.__name__, mod) diff --git a/tests/utils.py b/tests/utils.py index 4ec85d776648..60c988096398 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -8,6 +8,7 @@ import json import os import re +import typing from contextlib import contextmanager import pytest @@ -43,7 +44,7 @@ def load_vectors_from_file(filename, loader, mode="r"): def load_nist_vectors(vector_data): - test_data = None + test_data = {} data = [] for line in vector_data: @@ -108,7 +109,7 @@ def load_cryptrec_vectors(vector_data): def load_hash_vectors(vector_data): - vectors = [] + vectors: typing.List[typing.Union[KeyedHashVector, HashVector]] = [] key = None msg = None md = None @@ -150,11 +151,11 @@ def load_pkcs1_vectors(vector_data): """ Loads data out of RSA PKCS #1 vector files. """ - private_key_vector = None - public_key_vector = None + private_key_vector: typing.Optional[typing.Dict[str, typing.Any]] = None + public_key_vector: typing.Optional[typing.Dict[str, typing.Any]] = None attr = None - key = None - example_vector = None + key: typing.Any = None + example_vector: typing.Optional[typing.Dict[str, typing.Any]] = None examples = [] vectors = [] for line in vector_data: @@ -165,8 +166,8 @@ def load_pkcs1_vectors(vector_data): ): if example_vector: for key, value in example_vector.items(): - hex_str = "".join(value).replace(" ", "").encode("ascii") - example_vector[key] = hex_str + hex_bytes = "".join(value).replace(" ", "").encode("ascii") + example_vector[key] = hex_bytes examples.append(example_vector) attr = None @@ -191,8 +192,8 @@ def load_pkcs1_vectors(vector_data): "# =============================================" ): for key, value in example_vector.items(): - hex_str = "".join(value).replace(" ", "").encode("ascii") - example_vector[key] = hex_str + hex_bytes = "".join(value).replace(" ", "").encode("ascii") + example_vector[key] = hex_bytes examples.append(example_vector) example_vector = None attr = None @@ -277,7 +278,7 @@ def load_pkcs1_vectors(vector_data): def load_rsa_nist_vectors(vector_data): - test_data = None + test_data: typing.Dict[str, typing.Any] = {} p = None salt_length = None data = [] @@ -540,7 +541,7 @@ def load_kasvs_dh_vectors(vector_data): result_rx = re.compile(r"([FP]) \(([0-9]+) -") vectors = [] - data = {"fail_z": False, "fail_agree": False} + data: typing.Dict[str, typing.Any] = {"fail_z": False, "fail_agree": False} for line in vector_data: line = line.strip() @@ -568,6 +569,7 @@ def load_kasvs_dh_vectors(vector_data): elif line.startswith("Result = "): result_str = line.split("=")[1].strip() match = result_rx.match(result_str) + assert match is not None if match.group(1) == "F": if int(match.group(2)) in (5, 10): @@ -641,7 +643,7 @@ def load_kasvs_ecdh_vectors(vector_data): break # Data - data = { + data: typing.Dict[str, typing.Any] = { "CAVS": {}, "IUT": {}, } @@ -677,6 +679,7 @@ def load_kasvs_ecdh_vectors(vector_data): elif line.startswith("Result = "): result_str = line.split("=")[1].strip() match = result_rx.match(result_str) + assert match is not None if match.group(1) == "F": data["fail"] = True @@ -729,14 +732,17 @@ def load_x963_vectors(vector_data): vector["key_data_length"] = key_data_len elif line.startswith("Z"): vector["Z"] = line.split("=")[1].strip() + assert vector["Z"] is not None assert ((shared_secret_len + 7) // 8) * 2 == len(vector["Z"]) elif line.startswith("SharedInfo"): if shared_info_len != 0: vector["sharedinfo"] = line.split("=")[1].strip() + assert vector["sharedinfo"] is not None silen = len(vector["sharedinfo"]) assert ((shared_info_len + 7) // 8) * 2 == silen elif line.startswith("key_data"): vector["key_data"] = line.split("=")[1].strip() + assert vector["key_data"] is not None assert ((key_data_len + 7) // 8) * 2 == len(vector["key_data"]) vectors.append(vector) vector = {} @@ -801,7 +807,7 @@ def load_ed25519_vectors(vector_data): def load_nist_ccm_vectors(vector_data): - test_data = None + test_data = {} section_data = None global_data = {} new_section = False diff --git a/tests/wycheproof/test_dsa.py b/tests/wycheproof/test_dsa.py index 1bcf31f024b2..ac4647ef1b6f 100644 --- a/tests/wycheproof/test_dsa.py +++ b/tests/wycheproof/test_dsa.py @@ -10,6 +10,7 @@ from cryptography.exceptions import InvalidSignature from cryptography.hazmat.backends.interfaces import DSABackend from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric import dsa from .utils import wycheproof_tests @@ -33,6 +34,7 @@ def test_dsa_signature(backend, wycheproof): key = serialization.load_der_public_key( binascii.unhexlify(wycheproof.testgroup["keyDer"]), backend ) + assert isinstance(key, dsa.DSAPublicKey) digest = _DIGESTS[wycheproof.testgroup["sha"]] if wycheproof.valid or ( diff --git a/tests/wycheproof/test_ecdsa.py b/tests/wycheproof/test_ecdsa.py index e1bdbace66fe..b7f252c6df82 100644 --- a/tests/wycheproof/test_ecdsa.py +++ b/tests/wycheproof/test_ecdsa.py @@ -62,6 +62,7 @@ def test_ecdsa_signature(backend, wycheproof): key = serialization.load_der_public_key( binascii.unhexlify(wycheproof.testgroup["keyDer"]), backend ) + assert isinstance(key, ec.EllipticCurvePublicKey) except (UnsupportedAlgorithm, ValueError): # In some OpenSSL 1.0.2s, some keys fail to load with ValueError, # instead of Unsupported Algorithm. We can remove handling for that diff --git a/tests/wycheproof/test_rsa.py b/tests/wycheproof/test_rsa.py index 5df466c50538..4c1f1fff2cf3 100644 --- a/tests/wycheproof/test_rsa.py +++ b/tests/wycheproof/test_rsa.py @@ -10,7 +10,7 @@ from cryptography.exceptions import InvalidSignature from cryptography.hazmat.backends.interfaces import RSABackend from cryptography.hazmat.primitives import hashes, serialization -from cryptography.hazmat.primitives.asymmetric import padding +from cryptography.hazmat.primitives.asymmetric import padding, rsa from .utils import wycheproof_tests @@ -69,6 +69,7 @@ def test_rsa_pkcs1v15_signature(backend, wycheproof): key = serialization.load_der_public_key( binascii.unhexlify(wycheproof.testgroup["keyDer"]), backend ) + assert isinstance(key, rsa.RSAPublicKey) digest = _DIGESTS[wycheproof.testgroup["sha"]] if digest is None or not backend.hash_supported(digest): @@ -100,6 +101,7 @@ def test_rsa_pkcs1v15_signature_generation(backend, wycheproof): password=None, backend=backend, ) + assert isinstance(key, rsa.RSAPrivateKey) digest = _DIGESTS[wycheproof.testgroup["sha"]] sig = key.sign( @@ -126,6 +128,7 @@ def test_rsa_pss_signature(backend, wycheproof): key = serialization.load_der_public_key( binascii.unhexlify(wycheproof.testgroup["keyDer"]), backend ) + assert isinstance(key, rsa.RSAPublicKey) digest = _DIGESTS[wycheproof.testgroup["sha"]] mgf_digest = _DIGESTS[wycheproof.testgroup["mgfSha"]] @@ -187,6 +190,7 @@ def test_rsa_oaep_encryption(backend, wycheproof): password=None, backend=backend, ) + assert isinstance(key, rsa.RSAPrivateKey) digest = _DIGESTS[wycheproof.testgroup["sha"]] mgf_digest = _DIGESTS[wycheproof.testgroup["mgfSha"]] @@ -227,6 +231,7 @@ def test_rsa_pkcs1_encryption(backend, wycheproof): password=None, backend=backend, ) + assert isinstance(key, rsa.RSAPrivateKey) if wycheproof.valid: pt = key.decrypt( diff --git a/tests/x509/test_ocsp.py b/tests/x509/test_ocsp.py index 38e1ca5b0873..5793f6d62be3 100644 --- a/tests/x509/test_ocsp.py +++ b/tests/x509/test_ocsp.py @@ -169,16 +169,27 @@ def test_add_extension_twice(self): def test_add_invalid_extension(self): builder = ocsp.OCSPRequestBuilder() with pytest.raises(TypeError): - builder.add_extension("notanext", False) + builder.add_extension( + "notanext", # type:ignore[arg-type] + False, + ) def test_create_ocsp_request_invalid_cert(self): cert, issuer = _cert_and_issuer() builder = ocsp.OCSPRequestBuilder() with pytest.raises(TypeError): - builder.add_certificate(b"notacert", issuer, hashes.SHA1()) + builder.add_certificate( + b"notacert", # type:ignore[arg-type] + issuer, + hashes.SHA1(), + ) with pytest.raises(TypeError): - builder.add_certificate(cert, b"notacert", hashes.SHA1()) + builder.add_certificate( + cert, + b"notacert", # type:ignore[arg-type] + hashes.SHA1(), + ) def test_create_ocsp_request(self): cert, issuer = _cert_and_issuer() @@ -245,7 +256,7 @@ def test_invalid_add_response(self): builder = ocsp.OCSPResponseBuilder() with pytest.raises(TypeError): builder.add_response( - "bad", + "bad", # type:ignore[arg-type] issuer, hashes.SHA256(), ocsp.OCSPCertStatus.GOOD, @@ -257,7 +268,7 @@ def test_invalid_add_response(self): with pytest.raises(TypeError): builder.add_response( cert, - "bad", + "bad", # type:ignore[arg-type] hashes.SHA256(), ocsp.OCSPCertStatus.GOOD, time, @@ -269,7 +280,7 @@ def test_invalid_add_response(self): builder.add_response( cert, issuer, - "notahash", + "notahash", # type:ignore[arg-type] ocsp.OCSPCertStatus.GOOD, time, time, @@ -282,7 +293,7 @@ def test_invalid_add_response(self): issuer, hashes.SHA256(), ocsp.OCSPCertStatus.GOOD, - "bad", + "bad", # type:ignore[arg-type] time, None, None, @@ -294,14 +305,21 @@ def test_invalid_add_response(self): hashes.SHA256(), ocsp.OCSPCertStatus.GOOD, time, - "bad", + "bad", # type:ignore[arg-type] None, None, ) with pytest.raises(TypeError): builder.add_response( - cert, issuer, hashes.SHA256(), 0, time, time, None, None + cert, + issuer, + hashes.SHA256(), + 0, # type:ignore[arg-type] + time, + time, + None, + None, ) with pytest.raises(ValueError): builder.add_response( @@ -345,7 +363,7 @@ def test_invalid_add_response(self): time, time, time, - 0, + 0, # type:ignore[arg-type] ) with pytest.raises(ValueError): builder.add_response( @@ -364,9 +382,9 @@ def test_invalid_certificates(self): with pytest.raises(ValueError): builder.certificates([]) with pytest.raises(TypeError): - builder.certificates(["notacert"]) + builder.certificates(["notacert"]) # type: ignore[list-item] with pytest.raises(TypeError): - builder.certificates("invalid") + builder.certificates("invalid") # type: ignore[arg-type] _, issuer = _cert_and_issuer() builder = builder.certificates([issuer]) @@ -377,9 +395,12 @@ def test_invalid_responder_id(self): builder = ocsp.OCSPResponseBuilder() cert, _ = _cert_and_issuer() with pytest.raises(TypeError): - builder.responder_id(ocsp.OCSPResponderEncoding.HASH, "invalid") + builder.responder_id( + ocsp.OCSPResponderEncoding.HASH, + "invalid", # type: ignore[arg-type] + ) with pytest.raises(TypeError): - builder.responder_id("notanenum", cert) + builder.responder_id("notanenum", cert) # type: ignore[arg-type] builder = builder.responder_id(ocsp.OCSPResponderEncoding.NAME, cert) with pytest.raises(ValueError): @@ -388,7 +409,9 @@ def test_invalid_responder_id(self): def test_invalid_extension(self): builder = ocsp.OCSPResponseBuilder() with pytest.raises(TypeError): - builder.add_extension("notanextension", True) + builder.add_extension( + "notanextension", True # type: ignore[arg-type] + ) def test_sign_no_response(self): builder = ocsp.OCSPResponseBuilder() @@ -439,7 +462,7 @@ def test_sign_invalid_hash_algorithm(self): None, ) with pytest.raises(TypeError): - builder.sign(private_key, "notahash") + builder.sign(private_key, "notahash") # type: ignore[arg-type] def test_sign_good_cert(self): builder = ocsp.OCSPResponseBuilder() @@ -689,7 +712,9 @@ def test_build_non_successful_statuses(self, status, der): def test_invalid_build_not_a_status(self): with pytest.raises(TypeError): - ocsp.OCSPResponseBuilder.build_unsuccessful("notastatus") + ocsp.OCSPResponseBuilder.build_unsuccessful( + "notastatus" # type: ignore[arg-type] + ) def test_invalid_build_successful_status(self): with pytest.raises(ValueError): diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 78f591b1ee74..fa16333ef499 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -2107,10 +2107,10 @@ def test_issuer_name_must_be_a_name_type(self): builder = x509.CertificateBuilder() with pytest.raises(TypeError): - builder.issuer_name("subject") + builder.issuer_name("subject") # type:ignore[arg-type] with pytest.raises(TypeError): - builder.issuer_name(object) + builder.issuer_name(object) # type:ignore[arg-type] def test_issuer_name_may_only_be_set_once(self): name = x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) @@ -2123,10 +2123,10 @@ def test_subject_name_must_be_a_name_type(self): builder = x509.CertificateBuilder() with pytest.raises(TypeError): - builder.subject_name("subject") + builder.subject_name("subject") # type:ignore[arg-type] with pytest.raises(TypeError): - builder.subject_name(object) + builder.subject_name(object) # type:ignore[arg-type] def test_subject_name_may_only_be_set_once(self): name = x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) @@ -2172,7 +2172,9 @@ def test_public_key_may_only_be_set_once(self, backend): def test_serial_number_must_be_an_integer_type(self): with pytest.raises(TypeError): - x509.CertificateBuilder().serial_number(10.0) + x509.CertificateBuilder().serial_number( + 10.0 # type:ignore[arg-type] + ) def test_serial_number_must_be_non_negative(self): with pytest.raises(ValueError): @@ -2283,10 +2285,14 @@ def test_earliest_time(self, backend): def test_invalid_not_valid_after(self): with pytest.raises(TypeError): - x509.CertificateBuilder().not_valid_after(104204304504) + x509.CertificateBuilder().not_valid_after( + 104204304504 # type:ignore[arg-type] + ) with pytest.raises(TypeError): - x509.CertificateBuilder().not_valid_after(datetime.time()) + x509.CertificateBuilder().not_valid_after( + datetime.time() # type:ignore[arg-type] + ) with pytest.raises(ValueError): x509.CertificateBuilder().not_valid_after( @@ -2327,10 +2333,14 @@ def test_aware_not_valid_before(self, backend): def test_invalid_not_valid_before(self): with pytest.raises(TypeError): - x509.CertificateBuilder().not_valid_before(104204304504) + x509.CertificateBuilder().not_valid_before( + 104204304504 # type:ignore[arg-type] + ) with pytest.raises(TypeError): - x509.CertificateBuilder().not_valid_before(datetime.time()) + x509.CertificateBuilder().not_valid_before( + datetime.time() # type:ignore[arg-type] + ) with pytest.raises(ValueError): x509.CertificateBuilder().not_valid_before( @@ -2361,7 +2371,10 @@ def test_add_invalid_extension_type(self): builder = x509.CertificateBuilder() with pytest.raises(TypeError): - builder.add_extension(object(), False) + builder.add_extension( + object(), # type:ignore[arg-type] + False, + ) @pytest.mark.requires_backend_interface(interface=RSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) @@ -3756,13 +3769,16 @@ def test_add_duplicate_extension(self): def test_set_invalid_subject(self): builder = x509.CertificateSigningRequestBuilder() with pytest.raises(TypeError): - builder.subject_name("NotAName") + builder.subject_name("NotAName") # type:ignore[arg-type] def test_add_invalid_extension_type(self): builder = x509.CertificateSigningRequestBuilder() with pytest.raises(TypeError): - builder.add_extension(object(), False) + builder.add_extension( + object(), # type:ignore[arg-type] + False, + ) def test_add_unsupported_extension(self, backend): private_key = RSA_KEY_2048.private_key(backend) @@ -3935,11 +3951,15 @@ def test_add_attributes(self, backend): def test_add_attribute_bad_types(self, backend): request = x509.CertificateSigningRequestBuilder() with pytest.raises(TypeError): - request.add_attribute(b"not an oid", b"val") + request.add_attribute( + b"not an oid", # type:ignore[arg-type] + b"val", + ) with pytest.raises(TypeError): request.add_attribute( - x509.oid.AttributeOID.CHALLENGE_PASSWORD, 383 + x509.oid.AttributeOID.CHALLENGE_PASSWORD, + 383, # type:ignore[arg-type] ) def test_duplicate_attribute(self, backend): @@ -4743,15 +4763,23 @@ def test_alternate_type(self): def test_init_bad_oid(self): with pytest.raises(TypeError): - x509.NameAttribute(None, "value") + x509.NameAttribute( + None, # type:ignore[arg-type] + "value", + ) def test_init_bad_value(self): with pytest.raises(TypeError): - x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), b"bytes") + x509.NameAttribute( + x509.ObjectIdentifier("2.999.1"), + b"bytes", # type:ignore[arg-type] + ) def test_init_none_value(self): with pytest.raises(TypeError): - x509.NameAttribute(NameOID.ORGANIZATION_NAME, None) + x509.NameAttribute( + NameOID.ORGANIZATION_NAME, None # type:ignore[arg-type] + ) def test_init_bad_country_code_value(self): with pytest.raises(ValueError): @@ -4814,7 +4842,9 @@ def test_init_empty(self): def test_init_not_nameattribute(self): with pytest.raises(TypeError): - x509.RelativeDistinguishedName(["not-a-NameAttribute"]) + x509.RelativeDistinguishedName( + ["not-a-NameAttribute"] # type:ignore[list-item] + ) def test_init_duplicate_attribute(self): with pytest.raises(ValueError): diff --git a/tests/x509/test_x509_crlbuilder.py b/tests/x509/test_x509_crlbuilder.py index 036769e972cc..cbf0b073b5a5 100644 --- a/tests/x509/test_x509_crlbuilder.py +++ b/tests/x509/test_x509_crlbuilder.py @@ -34,7 +34,7 @@ class TestCertificateRevocationListBuilder(object): def test_issuer_name_invalid(self): builder = x509.CertificateRevocationListBuilder() with pytest.raises(TypeError): - builder.issuer_name("notanx509name") + builder.issuer_name("notanx509name") # type:ignore[arg-type] def test_set_issuer_name_twice(self): builder = x509.CertificateRevocationListBuilder().issuer_name( @@ -75,7 +75,7 @@ def test_aware_last_update(self, backend): def test_last_update_invalid(self): builder = x509.CertificateRevocationListBuilder() with pytest.raises(TypeError): - builder.last_update("notadatetime") + builder.last_update("notadatetime") # type:ignore[arg-type] def test_last_update_before_1950(self): builder = x509.CertificateRevocationListBuilder() @@ -119,7 +119,7 @@ def test_aware_next_update(self, backend): def test_next_update_invalid(self): builder = x509.CertificateRevocationListBuilder() with pytest.raises(TypeError): - builder.next_update("notadatetime") + builder.next_update("notadatetime") # type:ignore[arg-type] def test_next_update_before_1950(self): builder = x509.CertificateRevocationListBuilder() @@ -159,13 +159,13 @@ def test_add_invalid_extension(self): builder = x509.CertificateRevocationListBuilder() with pytest.raises(TypeError): - builder.add_extension(object(), False) + builder.add_extension(object(), False) # type:ignore[arg-type] def test_add_invalid_revoked_certificate(self): builder = x509.CertificateRevocationListBuilder() with pytest.raises(TypeError): - builder.add_revoked_certificate(object()) + builder.add_revoked_certificate(object()) # type:ignore[arg-type] @pytest.mark.requires_backend_interface(interface=RSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index b41e11eee1cb..011649f4ecd9 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -1669,10 +1669,10 @@ def test_init(self): assert name.value == "*.xn--4ca7aey.example.com" with pytest.raises(TypeError): - x509.DNSName(1.3) + x509.DNSName(1.3) # type:ignore[arg-type] with pytest.raises(TypeError): - x509.DNSName(b"bytes not allowed") + x509.DNSName(b"bytes not allowed") # type:ignore[arg-type] def test_ne(self): n1 = x509.DNSName("test1") @@ -1692,10 +1692,10 @@ def test_hash(self): class TestDirectoryName(object): def test_not_name(self): with pytest.raises(TypeError): - x509.DirectoryName(b"notaname") + x509.DirectoryName(b"notaname") # type:ignore[arg-type] with pytest.raises(TypeError): - x509.DirectoryName(1.3) + x509.DirectoryName(1.3) # type:ignore[arg-type] def test_repr(self): name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, "value1")]) @@ -1754,10 +1754,10 @@ def test_equality(self): def test_not_text(self): with pytest.raises(TypeError): - x509.RFC822Name(1.3) + x509.RFC822Name(1.3) # type:ignore[arg-type] with pytest.raises(TypeError): - x509.RFC822Name(b"bytes") + x509.RFC822Name(b"bytes") # type:ignore[arg-type] def test_invalid_email(self): with pytest.raises(ValueError): @@ -1794,7 +1794,7 @@ def test_equality(self): def test_not_text(self): with pytest.raises(TypeError): - x509.UniformResourceIdentifier(1.3) + x509.UniformResourceIdentifier(1.3) # type:ignore[arg-type] def test_no_parsed_hostname(self): gn = x509.UniformResourceIdentifier("singlelabel") @@ -1830,10 +1830,10 @@ def test_repr(self): class TestRegisteredID(object): def test_not_oid(self): with pytest.raises(TypeError): - x509.RegisteredID(b"notanoid") + x509.RegisteredID(b"notanoid") # type:ignore[arg-type] with pytest.raises(TypeError): - x509.RegisteredID(1.3) + x509.RegisteredID(1.3) # type:ignore[arg-type] def test_repr(self): gn = x509.RegisteredID(NameOID.COMMON_NAME) @@ -1864,10 +1864,10 @@ def test_hash(self): class TestIPAddress(object): def test_not_ipaddress(self): with pytest.raises(TypeError): - x509.IPAddress(b"notanipaddress") + x509.IPAddress(b"notanipaddress") # type:ignore[arg-type] with pytest.raises(TypeError): - x509.IPAddress(1.3) + x509.IPAddress(1.3) # type:ignore[arg-type] def test_repr(self): gn = x509.IPAddress(ipaddress.IPv4Address("127.0.0.1")) @@ -1904,10 +1904,16 @@ def test_hash(self): class TestOtherName(object): def test_invalid_args(self): with pytest.raises(TypeError): - x509.OtherName(b"notanobjectidentifier", b"derdata") + x509.OtherName( + b"notanobjectidentifier", # type:ignore[arg-type] + b"derdata", + ) with pytest.raises(TypeError): - x509.OtherName(x509.ObjectIdentifier("1.2.3.4"), "notderdata") + x509.OtherName( + x509.ObjectIdentifier("1.2.3.4"), + "notderdata", # type:ignore[arg-type] + ) def test_repr(self): gn = x509.OtherName(x509.ObjectIdentifier("1.2.3.4"), b"derdata") diff --git a/tests/x509/test_x509_revokedcertbuilder.py b/tests/x509/test_x509_revokedcertbuilder.py index 0d24f53792f8..34738e513e9a 100644 --- a/tests/x509/test_x509_revokedcertbuilder.py +++ b/tests/x509/test_x509_revokedcertbuilder.py @@ -16,7 +16,9 @@ class TestRevokedCertificateBuilder(object): def test_serial_number_must_be_integer(self): with pytest.raises(TypeError): - x509.RevokedCertificateBuilder().serial_number("notanx509name") + x509.RevokedCertificateBuilder().serial_number( + "notanx509name" # type: ignore[arg-type] + ) def test_serial_number_must_be_non_negative(self): with pytest.raises(ValueError): @@ -77,7 +79,9 @@ def test_aware_revocation_date(self, backend): def test_revocation_date_invalid(self): with pytest.raises(TypeError): - x509.RevokedCertificateBuilder().revocation_date("notadatetime") + x509.RevokedCertificateBuilder().revocation_date( + "notadatetime" # type: ignore[arg-type] + ) def test_revocation_date_before_1950(self): with pytest.raises(ValueError): @@ -105,7 +109,7 @@ def test_add_extension_checks_for_duplicates(self): def test_add_invalid_extension(self): with pytest.raises(TypeError): x509.RevokedCertificateBuilder().add_extension( - "notanextension", False + "notanextension", False # type: ignore[arg-type] ) @pytest.mark.requires_backend_interface(interface=X509Backend) diff --git a/tox.ini b/tox.ini index 79cbfb83d7b8..e58612ce5fd6 100644 --- a/tox.ini +++ b/tox.ini @@ -50,7 +50,7 @@ commands = flake8 . black --check . check-manifest - mypy src/cryptography/ vectors/cryptography_vectors/ + mypy src/cryptography/ vectors/cryptography_vectors/ tests/ [testenv:rust] basepython = python3 From 089af2765c58aed0e532cd23f8859d076e3f3717 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 31 Jan 2021 18:56:06 -0600 Subject: [PATCH 0080/2380] DH types (#5725) --- .../hazmat/backends/openssl/dh.py | 56 ++++--- .../hazmat/primitives/asymmetric/dh.py | 155 ++++++++++-------- tests/hazmat/primitives/test_dh.py | 12 +- 3 files changed, 124 insertions(+), 99 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/dh.py b/src/cryptography/hazmat/backends/openssl/dh.py index e6f332dac5f7..65ddaeec5fe2 100644 --- a/src/cryptography/hazmat/backends/openssl/dh.py +++ b/src/cryptography/hazmat/backends/openssl/dh.py @@ -3,7 +3,6 @@ # for complete details. -from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import dh @@ -32,13 +31,12 @@ def _dh_cdata_to_parameters(dh_cdata, backend): return _DHParameters(backend, param_cdata) -@utils.register_interface(dh.DHParameters) -class _DHParameters(object): +class _DHParameters(dh.DHParameters): def __init__(self, backend, dh_cdata): self._backend = backend self._dh_cdata = dh_cdata - def parameter_numbers(self): + def parameter_numbers(self) -> dh.DHParameterNumbers: p = self._backend._ffi.new("BIGNUM **") g = self._backend._ffi.new("BIGNUM **") q = self._backend._ffi.new("BIGNUM **") @@ -55,10 +53,14 @@ def parameter_numbers(self): q=q_val, ) - def generate_private_key(self): + def generate_private_key(self) -> dh.DHPrivateKey: return self._backend.generate_dh_private_key(self) - def parameter_bytes(self, encoding, format): + def parameter_bytes( + self, + encoding: serialization.Encoding, + format: serialization.ParameterFormat, + ) -> bytes: if format is not serialization.ParameterFormat.PKCS3: raise ValueError("Only PKCS3 serialization is supported") if not self._backend._lib.Cryptography_HAS_EVP_PKEY_DHX: @@ -78,15 +80,14 @@ def parameter_bytes(self, encoding, format): return self._backend._parameter_bytes(encoding, format, self._dh_cdata) -def _get_dh_num_bits(backend, dh_cdata): +def _get_dh_num_bits(backend, dh_cdata) -> int: p = backend._ffi.new("BIGNUM **") backend._lib.DH_get0_pqg(dh_cdata, p, backend._ffi.NULL, backend._ffi.NULL) backend.openssl_assert(p[0] != backend._ffi.NULL) return backend._lib.BN_num_bits(p[0]) -@utils.register_interface(dh.DHPrivateKey) -class _DHPrivateKey(object): +class _DHPrivateKey(dh.DHPrivateKey): def __init__(self, backend, dh_cdata, evp_pkey): self._backend = backend self._dh_cdata = dh_cdata @@ -94,10 +95,10 @@ def __init__(self, backend, dh_cdata, evp_pkey): self._key_size_bytes = self._backend._lib.DH_size(dh_cdata) @property - def key_size(self): + def key_size(self) -> int: return _get_dh_num_bits(self._backend, self._dh_cdata) - def private_numbers(self): + def private_numbers(self) -> dh.DHPrivateNumbers: p = self._backend._ffi.new("BIGNUM **") g = self._backend._ffi.new("BIGNUM **") q = self._backend._ffi.new("BIGNUM **") @@ -125,12 +126,13 @@ def private_numbers(self): x=self._backend._bn_to_int(priv_key[0]), ) - def exchange(self, peer_public_key): - + def exchange(self, peer_public_key: dh.DHPublicKey) -> bytes: buf = self._backend._ffi.new("unsigned char[]", self._key_size_bytes) pub_key = self._backend._ffi.new("BIGNUM **") self._backend._lib.DH_get0_key( - peer_public_key._dh_cdata, pub_key, self._backend._ffi.NULL + peer_public_key._dh_cdata, # type: ignore[attr-defined] + pub_key, + self._backend._ffi.NULL, ) self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) res = self._backend._lib.DH_compute_key( @@ -155,7 +157,7 @@ def exchange(self, peer_public_key): return key - def public_key(self): + def public_key(self) -> dh.DHPublicKey: dh_cdata = _dh_params_dup(self._dh_cdata, self._backend) pub_key = self._backend._ffi.new("BIGNUM **") self._backend._lib.DH_get0_key( @@ -172,10 +174,15 @@ def public_key(self): evp_pkey = self._backend._dh_cdata_to_evp_pkey(dh_cdata) return _DHPublicKey(self._backend, dh_cdata, evp_pkey) - def parameters(self): + def parameters(self) -> dh.DHParameters: return _dh_cdata_to_parameters(self._dh_cdata, self._backend) - def private_bytes(self, encoding, format, encryption_algorithm): + def private_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PrivateFormat, + encryption_algorithm: serialization.KeySerializationEncryption, + ) -> bytes: if format is not serialization.PrivateFormat.PKCS8: raise ValueError( "DH private keys support only PKCS8 serialization" @@ -204,8 +211,7 @@ def private_bytes(self, encoding, format, encryption_algorithm): ) -@utils.register_interface(dh.DHPublicKey) -class _DHPublicKey(object): +class _DHPublicKey(dh.DHPublicKey): def __init__(self, backend, dh_cdata, evp_pkey): self._backend = backend self._dh_cdata = dh_cdata @@ -213,10 +219,10 @@ def __init__(self, backend, dh_cdata, evp_pkey): self._key_size_bits = _get_dh_num_bits(self._backend, self._dh_cdata) @property - def key_size(self): + def key_size(self) -> int: return self._key_size_bits - def public_numbers(self): + def public_numbers(self) -> dh.DHPublicNumbers: p = self._backend._ffi.new("BIGNUM **") g = self._backend._ffi.new("BIGNUM **") q = self._backend._ffi.new("BIGNUM **") @@ -241,10 +247,14 @@ def public_numbers(self): y=self._backend._bn_to_int(pub_key[0]), ) - def parameters(self): + def parameters(self) -> dh.DHParameters: return _dh_cdata_to_parameters(self._dh_cdata, self._backend) - def public_bytes(self, encoding, format): + def public_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PublicFormat, + ) -> bytes: if format is not serialization.PublicFormat.SubjectPublicKeyInfo: raise ValueError( "DH public keys support only " diff --git a/src/cryptography/hazmat/primitives/asymmetric/dh.py b/src/cryptography/hazmat/primitives/asymmetric/dh.py index 85344fb1f0f2..1d4f997391fb 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dh.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dh.py @@ -4,9 +4,11 @@ import abc +import typing from cryptography import utils from cryptography.hazmat.backends import _get_backend +from cryptography.hazmat.primitives import serialization _MIN_MODULUS_SIZE = 512 @@ -17,41 +19,47 @@ def generate_parameters(generator, key_size, backend=None): return backend.generate_dh_parameters(generator, key_size) -class DHPrivateNumbers(object): - def __init__(self, x, public_numbers): - if not isinstance(x, int): - raise TypeError("x must be an integer.") +class DHParameterNumbers(object): + def __init__(self, p: int, g: int, q: typing.Optional[int] = None): + if not isinstance(p, int) or not isinstance(g, int): + raise TypeError("p and g must be integers") + if q is not None and not isinstance(q, int): + raise TypeError("q must be integer or None") - if not isinstance(public_numbers, DHPublicNumbers): - raise TypeError( - "public_numbers must be an instance of " "DHPublicNumbers." + if g < 2: + raise ValueError("DH generator must be 2 or greater") + + if p.bit_length() < _MIN_MODULUS_SIZE: + raise ValueError( + "p (modulus) must be at least {}-bit".format(_MIN_MODULUS_SIZE) ) - self._x = x - self._public_numbers = public_numbers + self._p = p + self._g = g + self._q = q def __eq__(self, other): - if not isinstance(other, DHPrivateNumbers): + if not isinstance(other, DHParameterNumbers): return NotImplemented return ( - self._x == other._x - and self._public_numbers == other._public_numbers + self._p == other._p and self._g == other._g and self._q == other._q ) def __ne__(self, other): return not self == other - def private_key(self, backend=None): + def parameters(self, backend=None): backend = _get_backend(backend) - return backend.load_dh_private_numbers(self) + return backend.load_dh_parameter_numbers(self) - public_numbers = utils.read_only_property("_public_numbers") - x = utils.read_only_property("_x") + p = utils.read_only_property("_p") + g = utils.read_only_property("_g") + q = utils.read_only_property("_q") class DHPublicNumbers(object): - def __init__(self, y, parameter_numbers): + def __init__(self, y, parameter_numbers: DHParameterNumbers): if not isinstance(y, int): raise TypeError("y must be an integer.") @@ -83,60 +91,58 @@ def public_key(self, backend=None): parameter_numbers = utils.read_only_property("_parameter_numbers") -class DHParameterNumbers(object): - def __init__(self, p, g, q=None): - if not isinstance(p, int) or not isinstance(g, int): - raise TypeError("p and g must be integers") - if q is not None and not isinstance(q, int): - raise TypeError("q must be integer or None") - - if g < 2: - raise ValueError("DH generator must be 2 or greater") +class DHPrivateNumbers(object): + def __init__(self, x, public_numbers: DHPublicNumbers): + if not isinstance(x, int): + raise TypeError("x must be an integer.") - if p.bit_length() < _MIN_MODULUS_SIZE: - raise ValueError( - "p (modulus) must be at least {}-bit".format(_MIN_MODULUS_SIZE) + if not isinstance(public_numbers, DHPublicNumbers): + raise TypeError( + "public_numbers must be an instance of " "DHPublicNumbers." ) - self._p = p - self._g = g - self._q = q + self._x = x + self._public_numbers = public_numbers def __eq__(self, other): - if not isinstance(other, DHParameterNumbers): + if not isinstance(other, DHPrivateNumbers): return NotImplemented return ( - self._p == other._p and self._g == other._g and self._q == other._q + self._x == other._x + and self._public_numbers == other._public_numbers ) def __ne__(self, other): return not self == other - def parameters(self, backend=None): + def private_key(self, backend=None) -> "DHPrivateKey": backend = _get_backend(backend) - return backend.load_dh_parameter_numbers(self) + return backend.load_dh_private_numbers(self) - p = utils.read_only_property("_p") - g = utils.read_only_property("_g") - q = utils.read_only_property("_q") + public_numbers = utils.read_only_property("_public_numbers") + x = utils.read_only_property("_x") class DHParameters(metaclass=abc.ABCMeta): @abc.abstractmethod - def generate_private_key(self): + def generate_private_key(self) -> "DHPrivateKey": """ Generates and returns a DHPrivateKey. """ @abc.abstractmethod - def parameter_bytes(self, encoding, format): + def parameter_bytes( + self, + encoding: "serialization.Encoding", + format: "serialization.ParameterFormat", + ): """ Returns the parameters serialized as bytes. """ @abc.abstractmethod - def parameter_numbers(self): + def parameter_numbers(self) -> DHParameterNumbers: """ Returns a DHParameterNumbers. """ @@ -145,72 +151,81 @@ def parameter_numbers(self): DHParametersWithSerialization = DHParameters -class DHPrivateKey(metaclass=abc.ABCMeta): +class DHPublicKey(metaclass=abc.ABCMeta): @abc.abstractproperty - def key_size(self): + def key_size(self) -> int: """ The bit length of the prime modulus. """ @abc.abstractmethod - def public_key(self): + def parameters(self) -> DHParameters: """ - The DHPublicKey associated with this private key. + The DHParameters object associated with this public key. """ @abc.abstractmethod - def parameters(self): + def public_numbers(self) -> DHPublicNumbers: """ - The DHParameters object associated with this private key. + Returns a DHPublicNumbers. """ @abc.abstractmethod - def exchange(self, peer_public_key): + def public_bytes( + self, + encoding: "serialization.Encoding", + format: "serialization.PublicFormat", + ) -> bytes: """ - Given peer's DHPublicKey, carry out the key exchange and - return shared key as bytes. + Returns the key serialized as bytes. """ - @abc.abstractmethod - def private_numbers(self): + +DHPublicKeyWithSerialization = DHPublicKey + + +class DHPrivateKey(metaclass=abc.ABCMeta): + @abc.abstractproperty + def key_size(self) -> int: """ - Returns a DHPrivateNumbers. + The bit length of the prime modulus. """ @abc.abstractmethod - def private_bytes(self, encoding, format, encryption_algorithm): + def public_key(self) -> DHPublicKey: """ - Returns the key serialized as bytes. + The DHPublicKey associated with this private key. """ - -DHPrivateKeyWithSerialization = DHPrivateKey - - -class DHPublicKey(metaclass=abc.ABCMeta): - @abc.abstractproperty - def key_size(self): + @abc.abstractmethod + def parameters(self) -> DHParameters: """ - The bit length of the prime modulus. + The DHParameters object associated with this private key. """ @abc.abstractmethod - def parameters(self): + def exchange(self, peer_public_key: DHPublicKey) -> bytes: """ - The DHParameters object associated with this public key. + Given peer's DHPublicKey, carry out the key exchange and + return shared key as bytes. """ @abc.abstractmethod - def public_numbers(self): + def private_numbers(self) -> DHPrivateNumbers: """ - Returns a DHPublicNumbers. + Returns a DHPrivateNumbers. """ @abc.abstractmethod - def public_bytes(self, encoding, format): + def private_bytes( + self, + encoding: "serialization.Encoding", + format: "serialization.PrivateFormat", + encryption_algorithm: "serialization.KeySerializationEncryption", + ): """ Returns the key serialized as bytes. """ -DHPublicKeyWithSerialization = DHPublicKey +DHPrivateKeyWithSerialization = DHPrivateKey diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index 4845ae7ef45a..131807fc0860 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -50,13 +50,13 @@ def test_dh_parameternumbers(): assert params.g == 2 with pytest.raises(TypeError): - dh.DHParameterNumbers(None, 2) + dh.DHParameterNumbers(None, 2) # type: ignore[arg-type] with pytest.raises(TypeError): - dh.DHParameterNumbers(P_1536, None) + dh.DHParameterNumbers(P_1536, None) # type: ignore[arg-type] with pytest.raises(TypeError): - dh.DHParameterNumbers(None, None) + dh.DHParameterNumbers(None, None) # type: ignore[arg-type] with pytest.raises(ValueError): dh.DHParameterNumbers(P_1536, 1) @@ -72,7 +72,7 @@ def test_dh_parameternumbers(): assert params.q == 1245 with pytest.raises(TypeError): - dh.DHParameterNumbers(P_1536, 2, "hello") + dh.DHParameterNumbers(P_1536, 2, "hello") # type: ignore[arg-type] def test_dh_numbers(): @@ -84,7 +84,7 @@ def test_dh_numbers(): assert public.y == 1 with pytest.raises(TypeError): - dh.DHPublicNumbers(1, None) + dh.DHPublicNumbers(1, None) # type: ignore[arg-type] with pytest.raises(TypeError): dh.DHPublicNumbers(None, params) @@ -95,7 +95,7 @@ def test_dh_numbers(): assert private.x == 1 with pytest.raises(TypeError): - dh.DHPrivateNumbers(1, None) + dh.DHPrivateNumbers(1, None) # type: ignore[arg-type] with pytest.raises(TypeError): dh.DHPrivateNumbers(None, public) From e0c94828bd4bbf45d7b943791fe4e493b30a505f Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 31 Jan 2021 19:27:49 -0600 Subject: [PATCH 0081/2380] reorg some types to prevent an import cycle (#5727) --- .../hazmat/primitives/_serialization.py | 54 +++++++++++++++++++ .../primitives/serialization/__init__.py | 4 +- 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/cryptography/hazmat/primitives/_serialization.py diff --git a/src/cryptography/hazmat/primitives/_serialization.py b/src/cryptography/hazmat/primitives/_serialization.py new file mode 100644 index 000000000000..96a5ed9b75d9 --- /dev/null +++ b/src/cryptography/hazmat/primitives/_serialization.py @@ -0,0 +1,54 @@ +# 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. + +import abc +from enum import Enum + +# This exists to break an import cycle. These classes are normally accessible +# from the serialization module. + + +class Encoding(Enum): + PEM = "PEM" + DER = "DER" + OpenSSH = "OpenSSH" + Raw = "Raw" + X962 = "ANSI X9.62" + SMIME = "S/MIME" + + +class PrivateFormat(Enum): + PKCS8 = "PKCS8" + TraditionalOpenSSL = "TraditionalOpenSSL" + Raw = "Raw" + OpenSSH = "OpenSSH" + + +class PublicFormat(Enum): + SubjectPublicKeyInfo = "X.509 subjectPublicKeyInfo with PKCS#1" + PKCS1 = "Raw PKCS#1" + OpenSSH = "OpenSSH" + Raw = "Raw" + CompressedPoint = "X9.62 Compressed Point" + UncompressedPoint = "X9.62 Uncompressed Point" + + +class ParameterFormat(Enum): + PKCS3 = "PKCS3" + + +class KeySerializationEncryption(metaclass=abc.ABCMeta): + pass + + +class BestAvailableEncryption(KeySerializationEncryption): + def __init__(self, password: bytes): + if not isinstance(password, bytes) or len(password) == 0: + raise ValueError("Password must be 1 or more bytes.") + + self.password = password + + +class NoEncryption(KeySerializationEncryption): + pass diff --git a/src/cryptography/hazmat/primitives/serialization/__init__.py b/src/cryptography/hazmat/primitives/serialization/__init__.py index 0e2a952764d2..1e0174b033de 100644 --- a/src/cryptography/hazmat/primitives/serialization/__init__.py +++ b/src/cryptography/hazmat/primitives/serialization/__init__.py @@ -3,7 +3,7 @@ # for complete details. -from cryptography.hazmat.primitives.serialization.base import ( +from cryptography.hazmat.primitives._serialization import ( BestAvailableEncryption, Encoding, KeySerializationEncryption, @@ -11,6 +11,8 @@ ParameterFormat, PrivateFormat, PublicFormat, +) +from cryptography.hazmat.primitives.serialization.base import ( load_der_parameters, load_der_private_key, load_der_public_key, From c05987e95182326dbe0ff061875968cd3f9ec37c Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 31 Jan 2021 21:04:32 -0600 Subject: [PATCH 0082/2380] dsa type hinting (#5726) --- .../hazmat/backends/openssl/dsa.py | 81 ++++++---- .../hazmat/primitives/asymmetric/dsa.py | 138 +++++++++++------- .../hazmat/primitives/serialization/base.py | 47 ------ tests/hazmat/primitives/test_dsa.py | 40 +++-- 4 files changed, 168 insertions(+), 138 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/dsa.py b/src/cryptography/hazmat/backends/openssl/dsa.py index a0633942a745..d3c54b82fad1 100644 --- a/src/cryptography/hazmat/backends/openssl/dsa.py +++ b/src/cryptography/hazmat/backends/openssl/dsa.py @@ -3,6 +3,8 @@ # for complete details. +import typing + from cryptography import utils from cryptography.exceptions import InvalidSignature from cryptography.hazmat.backends.openssl.utils import ( @@ -10,11 +12,12 @@ _check_not_prehashed, _warn_sign_verify_deprecated, ) -from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ( AsymmetricSignatureContext, AsymmetricVerificationContext, dsa, + utils as asym_utils, ) @@ -46,8 +49,7 @@ def _dsa_sig_verify(backend, public_key, signature, data): raise InvalidSignature -@utils.register_interface(AsymmetricVerificationContext) -class _DSAVerificationContext(object): +class _DSAVerificationContext(AsymmetricVerificationContext): def __init__(self, backend, public_key, signature, algorithm): self._backend = backend self._public_key = public_key @@ -67,29 +69,32 @@ def verify(self): ) -@utils.register_interface(AsymmetricSignatureContext) -class _DSASignatureContext(object): - def __init__(self, backend, private_key, algorithm): +class _DSASignatureContext(AsymmetricSignatureContext): + def __init__( + self, + backend, + private_key: dsa.DSAPrivateKey, + algorithm: hashes.HashAlgorithm, + ): self._backend = backend self._private_key = private_key self._algorithm = algorithm self._hash_ctx = hashes.Hash(self._algorithm, self._backend) - def update(self, data): + def update(self, data: bytes) -> None: self._hash_ctx.update(data) - def finalize(self): + def finalize(self) -> bytes: data_to_sign = self._hash_ctx.finalize() return _dsa_sig_sign(self._backend, self._private_key, data_to_sign) -@utils.register_interface(dsa.DSAParameters) -class _DSAParameters(object): +class _DSAParameters(dsa.DSAParameters): def __init__(self, backend, dsa_cdata): self._backend = backend self._dsa_cdata = dsa_cdata - def parameter_numbers(self): + def parameter_numbers(self) -> dsa.DSAParameterNumbers: p = self._backend._ffi.new("BIGNUM **") q = self._backend._ffi.new("BIGNUM **") g = self._backend._ffi.new("BIGNUM **") @@ -103,12 +108,11 @@ def parameter_numbers(self): g=self._backend._bn_to_int(g[0]), ) - def generate_private_key(self): + def generate_private_key(self) -> dsa.DSAPrivateKey: return self._backend.generate_dsa_private_key(self) -@utils.register_interface(dsa.DSAPrivateKey) -class _DSAPrivateKey(object): +class _DSAPrivateKey(dsa.DSAPrivateKey): def __init__(self, backend, dsa_cdata, evp_pkey): self._backend = backend self._dsa_cdata = dsa_cdata @@ -123,12 +127,14 @@ def __init__(self, backend, dsa_cdata, evp_pkey): key_size = utils.read_only_property("_key_size") - def signer(self, signature_algorithm): + def signer( + self, signature_algorithm: hashes.HashAlgorithm + ) -> AsymmetricSignatureContext: _warn_sign_verify_deprecated() _check_not_prehashed(signature_algorithm) return _DSASignatureContext(self._backend, self, signature_algorithm) - def private_numbers(self): + def private_numbers(self) -> dsa.DSAPrivateNumbers: p = self._backend._ffi.new("BIGNUM **") q = self._backend._ffi.new("BIGNUM **") g = self._backend._ffi.new("BIGNUM **") @@ -153,7 +159,7 @@ def private_numbers(self): x=self._backend._bn_to_int(priv_key[0]), ) - def public_key(self): + def public_key(self) -> dsa.DSAPublicKey: dsa_cdata = self._backend._lib.DSAparams_dup(self._dsa_cdata) self._backend.openssl_assert(dsa_cdata != self._backend._ffi.NULL) dsa_cdata = self._backend._ffi.gc( @@ -172,7 +178,7 @@ def public_key(self): evp_pkey = self._backend._dsa_cdata_to_evp_pkey(dsa_cdata) return _DSAPublicKey(self._backend, dsa_cdata, evp_pkey) - def parameters(self): + def parameters(self) -> dsa.DSAParameters: dsa_cdata = self._backend._lib.DSAparams_dup(self._dsa_cdata) self._backend.openssl_assert(dsa_cdata != self._backend._ffi.NULL) dsa_cdata = self._backend._ffi.gc( @@ -180,7 +186,12 @@ def parameters(self): ) return _DSAParameters(self._backend, dsa_cdata) - def private_bytes(self, encoding, format, encryption_algorithm): + def private_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PrivateFormat, + encryption_algorithm: serialization.KeySerializationEncryption, + ) -> bytes: return self._backend._private_key_bytes( encoding, format, @@ -190,15 +201,18 @@ def private_bytes(self, encoding, format, encryption_algorithm): self._dsa_cdata, ) - def sign(self, data, algorithm): + def sign( + self, + data: bytes, + algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], + ) -> bytes: data, algorithm = _calculate_digest_and_algorithm( self._backend, data, algorithm ) return _dsa_sig_sign(self._backend, self, data) -@utils.register_interface(dsa.DSAPublicKey) -class _DSAPublicKey(object): +class _DSAPublicKey(dsa.DSAPublicKey): def __init__(self, backend, dsa_cdata, evp_pkey): self._backend = backend self._dsa_cdata = dsa_cdata @@ -212,7 +226,11 @@ def __init__(self, backend, dsa_cdata, evp_pkey): key_size = utils.read_only_property("_key_size") - def verifier(self, signature, signature_algorithm): + def verifier( + self, + signature: bytes, + signature_algorithm: hashes.HashAlgorithm, + ) -> AsymmetricVerificationContext: _warn_sign_verify_deprecated() utils._check_bytes("signature", signature) @@ -221,7 +239,7 @@ def verifier(self, signature, signature_algorithm): self._backend, self, signature, signature_algorithm ) - def public_numbers(self): + def public_numbers(self) -> dsa.DSAPublicNumbers: p = self._backend._ffi.new("BIGNUM **") q = self._backend._ffi.new("BIGNUM **") g = self._backend._ffi.new("BIGNUM **") @@ -243,19 +261,28 @@ def public_numbers(self): y=self._backend._bn_to_int(pub_key[0]), ) - def parameters(self): + def parameters(self) -> dsa.DSAParameters: dsa_cdata = self._backend._lib.DSAparams_dup(self._dsa_cdata) dsa_cdata = self._backend._ffi.gc( dsa_cdata, self._backend._lib.DSA_free ) return _DSAParameters(self._backend, dsa_cdata) - def public_bytes(self, encoding, format): + def public_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PublicFormat, + ) -> bytes: return self._backend._public_key_bytes( encoding, format, self, self._evp_pkey, None ) - def verify(self, signature, data, algorithm): + def verify( + self, + signature: bytes, + data: bytes, + algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], + ): data, algorithm = _calculate_digest_and_algorithm( self._backend, data, algorithm ) diff --git a/src/cryptography/hazmat/primitives/asymmetric/dsa.py b/src/cryptography/hazmat/primitives/asymmetric/dsa.py index 0f5be8da2d8d..c6f991bc7492 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dsa.py @@ -4,20 +4,27 @@ import abc +import typing from cryptography import utils from cryptography.hazmat.backends import _get_backend +from cryptography.hazmat.primitives import _serialization, hashes +from cryptography.hazmat.primitives.asymmetric import ( + AsymmetricSignatureContext, + AsymmetricVerificationContext, + utils as asym_utils, +) class DSAParameters(metaclass=abc.ABCMeta): @abc.abstractmethod - def generate_private_key(self): + def generate_private_key(self) -> "DSAPrivateKey": """ Generates and returns a DSAPrivateKey. """ @abc.abstractmethod - def parameter_numbers(self): + def parameter_numbers(self) -> "DSAParameterNumbers": """ Returns a DSAParameterNumbers. """ @@ -28,43 +35,55 @@ def parameter_numbers(self): class DSAPrivateKey(metaclass=abc.ABCMeta): @abc.abstractproperty - def key_size(self): + def key_size(self) -> int: """ The bit length of the prime modulus. """ @abc.abstractmethod - def public_key(self): + def public_key(self) -> "DSAPublicKey": """ The DSAPublicKey associated with this private key. """ @abc.abstractmethod - def parameters(self): + def parameters(self) -> DSAParameters: """ The DSAParameters object associated with this private key. """ @abc.abstractmethod - def signer(self, signature_algorithm): + def signer( + self, + signature_algorithm: hashes.HashAlgorithm, + ) -> AsymmetricSignatureContext: """ Returns an AsymmetricSignatureContext used for signing data. """ @abc.abstractmethod - def sign(self, data, algorithm): + def sign( + self, + data: bytes, + algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], + ) -> bytes: """ Signs the data """ @abc.abstractmethod - def private_numbers(self): + def private_numbers(self) -> "DSAPrivateNumbers": """ Returns a DSAPrivateNumbers. """ @abc.abstractmethod - def private_bytes(self, encoding, format, encryption_algorithm): + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: """ Returns the key serialized as bytes. """ @@ -75,37 +94,50 @@ def private_bytes(self, encoding, format, encryption_algorithm): class DSAPublicKey(metaclass=abc.ABCMeta): @abc.abstractproperty - def key_size(self): + def key_size(self) -> int: """ The bit length of the prime modulus. """ @abc.abstractmethod - def parameters(self): + def parameters(self) -> DSAParameters: """ The DSAParameters object associated with this public key. """ @abc.abstractmethod - def verifier(self, signature, signature_algorithm): + def verifier( + self, + signature: bytes, + signature_algorithm: hashes.HashAlgorithm, + ) -> AsymmetricVerificationContext: """ Returns an AsymmetricVerificationContext used for signing data. """ @abc.abstractmethod - def public_numbers(self): + def public_numbers(self) -> "DSAPublicNumbers": """ Returns a DSAPublicNumbers. """ @abc.abstractmethod - def public_bytes(self, encoding, format): + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: """ Returns the key serialized as bytes. """ @abc.abstractmethod - def verify(self, signature, data, algorithm): + def verify( + self, + signature: bytes, + data: bytes, + algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], + ): """ Verifies the signature of the data. """ @@ -114,40 +146,8 @@ def verify(self, signature, data, algorithm): DSAPublicKeyWithSerialization = DSAPublicKey -def generate_parameters(key_size, backend=None): - backend = _get_backend(backend) - return backend.generate_dsa_parameters(key_size) - - -def generate_private_key(key_size, backend=None): - backend = _get_backend(backend) - return backend.generate_dsa_private_key_and_parameters(key_size) - - -def _check_dsa_parameters(parameters): - if parameters.p.bit_length() not in [1024, 2048, 3072, 4096]: - raise ValueError( - "p must be exactly 1024, 2048, 3072, or 4096 bits long" - ) - if parameters.q.bit_length() not in [160, 224, 256]: - raise ValueError("q must be exactly 160, 224, or 256 bits long") - - if not (1 < parameters.g < parameters.p): - raise ValueError("g, p don't satisfy 1 < g < p.") - - -def _check_dsa_private_numbers(numbers): - parameters = numbers.public_numbers.parameter_numbers - _check_dsa_parameters(parameters) - if numbers.x <= 0 or numbers.x >= parameters.q: - raise ValueError("x must be > 0 and < q.") - - if numbers.public_numbers.y != pow(parameters.g, numbers.x, parameters.p): - raise ValueError("y must be equal to (g ** x % p).") - - class DSAParameterNumbers(object): - def __init__(self, p, q, g): + def __init__(self, p: int, q: int, g: int): if ( not isinstance(p, int) or not isinstance(q, int) @@ -165,7 +165,7 @@ def __init__(self, p, q, g): q = utils.read_only_property("_q") g = utils.read_only_property("_g") - def parameters(self, backend=None): + def parameters(self, backend=None) -> DSAParameters: backend = _get_backend(backend) return backend.load_dsa_parameter_numbers(self) @@ -186,7 +186,7 @@ def __repr__(self): class DSAPublicNumbers(object): - def __init__(self, y, parameter_numbers): + def __init__(self, y: int, parameter_numbers: DSAParameterNumbers): if not isinstance(y, int): raise TypeError("DSAPublicNumbers y argument must be an integer.") @@ -201,7 +201,7 @@ def __init__(self, y, parameter_numbers): y = utils.read_only_property("_y") parameter_numbers = utils.read_only_property("_parameter_numbers") - def public_key(self, backend=None): + def public_key(self, backend=None) -> DSAPublicKey: backend = _get_backend(backend) return backend.load_dsa_public_numbers(self) @@ -225,7 +225,7 @@ def __repr__(self): class DSAPrivateNumbers(object): - def __init__(self, x, public_numbers): + def __init__(self, x: int, public_numbers: DSAPublicNumbers): if not isinstance(x, int): raise TypeError("DSAPrivateNumbers x argument must be an integer.") @@ -239,7 +239,7 @@ def __init__(self, x, public_numbers): x = utils.read_only_property("_x") public_numbers = utils.read_only_property("_public_numbers") - def private_key(self, backend=None): + def private_key(self, backend=None) -> DSAPrivateKey: backend = _get_backend(backend) return backend.load_dsa_private_numbers(self) @@ -253,3 +253,35 @@ def __eq__(self, other): def __ne__(self, other): return not self == other + + +def generate_parameters(key_size: int, backend=None) -> DSAParameters: + backend = _get_backend(backend) + return backend.generate_dsa_parameters(key_size) + + +def generate_private_key(key_size: int, backend=None) -> DSAPrivateKey: + backend = _get_backend(backend) + return backend.generate_dsa_private_key_and_parameters(key_size) + + +def _check_dsa_parameters(parameters: DSAParameterNumbers): + if parameters.p.bit_length() not in [1024, 2048, 3072, 4096]: + raise ValueError( + "p must be exactly 1024, 2048, 3072, or 4096 bits long" + ) + if parameters.q.bit_length() not in [160, 224, 256]: + raise ValueError("q must be exactly 160, 224, or 256 bits long") + + if not (1 < parameters.g < parameters.p): + raise ValueError("g, p don't satisfy 1 < g < p.") + + +def _check_dsa_private_numbers(numbers: DSAPrivateNumbers): + parameters = numbers.public_numbers.parameter_numbers + _check_dsa_parameters(parameters) + if numbers.x <= 0 or numbers.x >= parameters.q: + raise ValueError("x must be > 0 and < q.") + + if numbers.public_numbers.y != pow(parameters.g, numbers.x, parameters.p): + raise ValueError("y must be equal to (g ** x % p).") diff --git a/src/cryptography/hazmat/primitives/serialization/base.py b/src/cryptography/hazmat/primitives/serialization/base.py index 2ce722cf486c..00334b2e3b16 100644 --- a/src/cryptography/hazmat/primitives/serialization/base.py +++ b/src/cryptography/hazmat/primitives/serialization/base.py @@ -3,9 +3,7 @@ # for complete details. -import abc import typing -from enum import Enum from cryptography.hazmat._types import ( _PRIVATE_KEY_TYPES, @@ -47,48 +45,3 @@ def load_der_public_key(data: bytes, backend=None) -> _PUBLIC_KEY_TYPES: def load_der_parameters(data: bytes, backend=None) -> dh.DHParameters: backend = _get_backend(backend) return backend.load_der_parameters(data) - - -class Encoding(Enum): - PEM = "PEM" - DER = "DER" - OpenSSH = "OpenSSH" - Raw = "Raw" - X962 = "ANSI X9.62" - SMIME = "S/MIME" - - -class PrivateFormat(Enum): - PKCS8 = "PKCS8" - TraditionalOpenSSL = "TraditionalOpenSSL" - Raw = "Raw" - OpenSSH = "OpenSSH" - - -class PublicFormat(Enum): - SubjectPublicKeyInfo = "X.509 subjectPublicKeyInfo with PKCS#1" - PKCS1 = "Raw PKCS#1" - OpenSSH = "OpenSSH" - Raw = "Raw" - CompressedPoint = "X9.62 Compressed Point" - UncompressedPoint = "X9.62 Uncompressed Point" - - -class ParameterFormat(Enum): - PKCS3 = "PKCS3" - - -class KeySerializationEncryption(metaclass=abc.ABCMeta): - pass - - -class BestAvailableEncryption(KeySerializationEncryption): - def __init__(self, password: bytes): - if not isinstance(password, bytes) or len(password) == 0: - raise ValueError("Password must be 1 or more bytes.") - - self.password = password - - -class NoEncryption(KeySerializationEncryption): - pass diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py index 56d37d84f093..6d8b2867fb81 100644 --- a/tests/hazmat/primitives/test_dsa.py +++ b/tests/hazmat/primitives/test_dsa.py @@ -474,14 +474,18 @@ def test_prehashed_unsupported_in_signer_ctx(self, backend): with pytest.raises(TypeError), pytest.warns( CryptographyDeprecationWarning ): - private_key.signer(Prehashed(hashes.SHA1())) + private_key.signer( + Prehashed(hashes.SHA1()) # type: ignore[arg-type] + ) def test_prehashed_unsupported_in_verifier_ctx(self, backend): public_key = DSA_KEY_1024.private_key(backend).public_key() with pytest.raises(TypeError), pytest.warns( CryptographyDeprecationWarning ): - public_key.verifier(b"0" * 64, Prehashed(hashes.SHA1())) + public_key.verifier( + b"0" * 64, Prehashed(hashes.SHA1()) # type: ignore[arg-type] + ) @pytest.mark.requires_backend_interface(interface=DSABackend) @@ -566,13 +570,13 @@ def test_dsa_parameter_numbers(self): def test_dsa_parameter_numbers_invalid_types(self): with pytest.raises(TypeError): - dsa.DSAParameterNumbers(p=None, q=2, g=3) + dsa.DSAParameterNumbers(p=None, q=2, g=3) # type: ignore[arg-type] with pytest.raises(TypeError): - dsa.DSAParameterNumbers(p=1, q=None, g=3) + dsa.DSAParameterNumbers(p=1, q=None, g=3) # type: ignore[arg-type] with pytest.raises(TypeError): - dsa.DSAParameterNumbers(p=1, q=2, g=None) + dsa.DSAParameterNumbers(p=1, q=2, g=None) # type: ignore[arg-type] def test_dsa_public_numbers(self): parameter_numbers = dsa.DSAParameterNumbers(p=1, q=2, g=3) @@ -584,11 +588,16 @@ def test_dsa_public_numbers(self): def test_dsa_public_numbers_invalid_types(self): with pytest.raises(TypeError): - dsa.DSAPublicNumbers(y=4, parameter_numbers=None) + dsa.DSAPublicNumbers( + y=4, parameter_numbers=None # type: ignore[arg-type] + ) with pytest.raises(TypeError): parameter_numbers = dsa.DSAParameterNumbers(p=1, q=2, g=3) - dsa.DSAPublicNumbers(y=None, parameter_numbers=parameter_numbers) + dsa.DSAPublicNumbers( + y=None, # type: ignore[arg-type] + parameter_numbers=parameter_numbers, + ) def test_dsa_private_numbers(self): parameter_numbers = dsa.DSAParameterNumbers(p=1, q=2, g=3) @@ -607,10 +616,15 @@ def test_dsa_private_numbers_invalid_types(self): y=4, parameter_numbers=parameter_numbers ) with pytest.raises(TypeError): - dsa.DSAPrivateNumbers(x=4, public_numbers=None) + dsa.DSAPrivateNumbers( + x=4, + public_numbers=None, # type: ignore[arg-type] + ) with pytest.raises(TypeError): - dsa.DSAPrivateNumbers(x=None, public_numbers=public_numbers) + dsa.DSAPrivateNumbers( + x=None, public_numbers=public_numbers # type: ignore[arg-type] + ) def test_repr(self): parameter_numbers = dsa.DSAParameterNumbers(p=1, q=2, g=3) @@ -965,13 +979,17 @@ def test_public_bytes_invalid_encoding(self, backend): key = DSA_KEY_2048.private_key(backend).public_key() with pytest.raises(TypeError): key.public_bytes( - "notencoding", serialization.PublicFormat.SubjectPublicKeyInfo + "notencoding", # type: ignore[arg-type] + serialization.PublicFormat.SubjectPublicKeyInfo, ) def test_public_bytes_invalid_format(self, backend): key = DSA_KEY_2048.private_key(backend).public_key() with pytest.raises(TypeError): - key.public_bytes(serialization.Encoding.PEM, "invalidformat") + key.public_bytes( + serialization.Encoding.PEM, + "invalidformat", # type: ignore[arg-type] + ) def test_public_bytes_pkcs1_unsupported(self, backend): key = DSA_KEY_2048.private_key(backend).public_key() From a47884cdfae4063d5a2187a2d269600b557ac6f6 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 31 Jan 2021 22:17:03 -0600 Subject: [PATCH 0083/2380] ed448 type hints (#5730) --- .../hazmat/backends/openssl/ed448.py | 31 ++++++++++++------- .../hazmat/primitives/asymmetric/ed448.py | 26 +++++++++++----- tests/hazmat/primitives/test_ed448.py | 12 ++++--- 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/ed448.py b/src/cryptography/hazmat/backends/openssl/ed448.py index 0738c44e2f24..c787efdc6e46 100644 --- a/src/cryptography/hazmat/backends/openssl/ed448.py +++ b/src/cryptography/hazmat/backends/openssl/ed448.py @@ -3,7 +3,7 @@ # for complete details. -from cryptography import exceptions, utils +from cryptography import exceptions from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric.ed448 import ( Ed448PrivateKey, @@ -14,13 +14,16 @@ _ED448_SIG_SIZE = 114 -@utils.register_interface(Ed448PublicKey) -class _Ed448PublicKey(object): +class _Ed448PublicKey(Ed448PublicKey): def __init__(self, backend, evp_pkey): self._backend = backend self._evp_pkey = evp_pkey - def public_bytes(self, encoding, format): + def public_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PublicFormat, + ) -> bytes: if ( encoding is serialization.Encoding.Raw or format is serialization.PublicFormat.Raw @@ -39,7 +42,7 @@ def public_bytes(self, encoding, format): encoding, format, self, self._evp_pkey, None ) - def _raw_public_bytes(self): + def _raw_public_bytes(self) -> bytes: buf = self._backend._ffi.new("unsigned char []", _ED448_KEY_SIZE) buflen = self._backend._ffi.new("size_t *", _ED448_KEY_SIZE) res = self._backend._lib.EVP_PKEY_get_raw_public_key( @@ -49,7 +52,7 @@ def _raw_public_bytes(self): self._backend.openssl_assert(buflen[0] == _ED448_KEY_SIZE) return self._backend._ffi.buffer(buf, _ED448_KEY_SIZE)[:] - def verify(self, signature, data): + def verify(self, signature: bytes, data: bytes) -> None: evp_md_ctx = self._backend._lib.EVP_MD_CTX_new() self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) evp_md_ctx = self._backend._ffi.gc( @@ -71,13 +74,12 @@ def verify(self, signature, data): raise exceptions.InvalidSignature -@utils.register_interface(Ed448PrivateKey) -class _Ed448PrivateKey(object): +class _Ed448PrivateKey(Ed448PrivateKey): def __init__(self, backend, evp_pkey): self._backend = backend self._evp_pkey = evp_pkey - def public_key(self): + def public_key(self) -> Ed448PublicKey: buf = self._backend._ffi.new("unsigned char []", _ED448_KEY_SIZE) buflen = self._backend._ffi.new("size_t *", _ED448_KEY_SIZE) res = self._backend._lib.EVP_PKEY_get_raw_public_key( @@ -88,7 +90,7 @@ def public_key(self): public_bytes = self._backend._ffi.buffer(buf)[:] return self._backend.ed448_load_public_bytes(public_bytes) - def sign(self, data): + def sign(self, data: bytes) -> bytes: evp_md_ctx = self._backend._lib.EVP_MD_CTX_new() self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) evp_md_ctx = self._backend._ffi.gc( @@ -111,7 +113,12 @@ def sign(self, data): self._backend.openssl_assert(buflen[0] == _ED448_SIG_SIZE) return self._backend._ffi.buffer(buf, buflen[0])[:] - def private_bytes(self, encoding, format, encryption_algorithm): + def private_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PrivateFormat, + encryption_algorithm: serialization.KeySerializationEncryption, + ) -> bytes: if ( encoding is serialization.Encoding.Raw or format is serialization.PublicFormat.Raw @@ -134,7 +141,7 @@ def private_bytes(self, encoding, format, encryption_algorithm): encoding, format, encryption_algorithm, self, self._evp_pkey, None ) - def _raw_private_bytes(self): + def _raw_private_bytes(self) -> bytes: buf = self._backend._ffi.new("unsigned char []", _ED448_KEY_SIZE) buflen = self._backend._ffi.new("size_t *", _ED448_KEY_SIZE) res = self._backend._lib.EVP_PKEY_get_raw_private_key( diff --git a/src/cryptography/hazmat/primitives/asymmetric/ed448.py b/src/cryptography/hazmat/primitives/asymmetric/ed448.py index 3550e81e8aaf..41985462142c 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ed448.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ed448.py @@ -6,11 +6,12 @@ import abc from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.primitives import _serialization class Ed448PublicKey(metaclass=abc.ABCMeta): @classmethod - def from_public_bytes(cls, data): + def from_public_bytes(cls, data: bytes) -> "Ed448PublicKey": from cryptography.hazmat.backends.openssl.backend import backend if not backend.ed448_supported(): @@ -22,13 +23,17 @@ def from_public_bytes(cls, data): return backend.ed448_load_public_bytes(data) @abc.abstractmethod - def public_bytes(self, encoding, format): + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: """ The serialized bytes of the public key. """ @abc.abstractmethod - def verify(self, signature, data): + def verify(self, signature: bytes, data: bytes): """ Verify the signature. """ @@ -36,7 +41,7 @@ def verify(self, signature, data): class Ed448PrivateKey(metaclass=abc.ABCMeta): @classmethod - def generate(cls): + def generate(cls) -> "Ed448PrivateKey": from cryptography.hazmat.backends.openssl.backend import backend if not backend.ed448_supported(): @@ -47,7 +52,7 @@ def generate(cls): return backend.ed448_generate_key() @classmethod - def from_private_bytes(cls, data): + def from_private_bytes(cls, data: bytes) -> "Ed448PrivateKey": from cryptography.hazmat.backends.openssl.backend import backend if not backend.ed448_supported(): @@ -59,19 +64,24 @@ def from_private_bytes(cls, data): return backend.ed448_load_private_bytes(data) @abc.abstractmethod - def public_key(self): + def public_key(self) -> Ed448PublicKey: """ The Ed448PublicKey derived from the private key. """ @abc.abstractmethod - def sign(self, data): + def sign(self, data: bytes) -> bytes: """ Signs the data. """ @abc.abstractmethod - def private_bytes(self, encoding, format, encryption_algorithm): + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ): """ The serialized bytes of the private key. """ diff --git a/tests/hazmat/primitives/test_ed448.py b/tests/hazmat/primitives/test_ed448.py index 6065ae8e4c3d..5019bc2e48cb 100644 --- a/tests/hazmat/primitives/test_ed448.py +++ b/tests/hazmat/primitives/test_ed448.py @@ -165,11 +165,15 @@ def test_round_trip_private_serialization( def test_invalid_type_public_bytes(self, backend): with pytest.raises(TypeError): - Ed448PublicKey.from_public_bytes(object()) + Ed448PublicKey.from_public_bytes( + object() # type: ignore[arg-type] + ) def test_invalid_type_private_bytes(self, backend): with pytest.raises(TypeError): - Ed448PrivateKey.from_private_bytes(object()) + Ed448PrivateKey.from_private_bytes( + object() # type: ignore[arg-type] + ) def test_invalid_length_from_public_bytes(self, backend): with pytest.raises(ValueError): @@ -189,14 +193,14 @@ def test_invalid_private_bytes(self, backend): key.private_bytes( serialization.Encoding.Raw, serialization.PrivateFormat.Raw, - None, + None, # type: ignore[arg-type] ) with pytest.raises(ValueError): key.private_bytes( serialization.Encoding.Raw, serialization.PrivateFormat.PKCS8, - None, + None, # type: ignore[arg-type] ) with pytest.raises(ValueError): From c9ec582aeb89fe5ee9b9c131294378340bf6ecc5 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 31 Jan 2021 22:19:34 -0600 Subject: [PATCH 0084/2380] add EC type hinting (#5729) --- .../hazmat/backends/openssl/ec.py | 106 ++++++++++++------ .../hazmat/primitives/asymmetric/ec.py | 100 ++++++++++++----- tests/hazmat/primitives/test_ec.py | 22 ++-- tests/wycheproof/test_ecdh.py | 2 + 4 files changed, 160 insertions(+), 70 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/ec.py b/src/cryptography/hazmat/backends/openssl/ec.py index 8977f489fd9b..3f54d72811e6 100644 --- a/src/cryptography/hazmat/backends/openssl/ec.py +++ b/src/cryptography/hazmat/backends/openssl/ec.py @@ -22,7 +22,9 @@ ) -def _check_signature_algorithm(signature_algorithm): +def _check_signature_algorithm( + signature_algorithm: ec.EllipticCurveSignatureAlgorithm, +): if not isinstance(signature_algorithm, ec.ECDSA): raise UnsupportedAlgorithm( "Unsupported elliptic curve signature algorithm.", @@ -104,42 +106,50 @@ def _ecdsa_sig_verify(backend, public_key, signature, data): raise InvalidSignature -@utils.register_interface(AsymmetricSignatureContext) -class _ECDSASignatureContext(object): - def __init__(self, backend, private_key, algorithm): +class _ECDSASignatureContext(AsymmetricSignatureContext): + def __init__( + self, + backend, + private_key: ec.EllipticCurvePrivateKey, + algorithm: hashes.HashAlgorithm, + ): self._backend = backend self._private_key = private_key self._digest = hashes.Hash(algorithm, backend) - def update(self, data): + def update(self, data: bytes) -> None: self._digest.update(data) - def finalize(self): + def finalize(self) -> bytes: digest = self._digest.finalize() return _ecdsa_sig_sign(self._backend, self._private_key, digest) -@utils.register_interface(AsymmetricVerificationContext) -class _ECDSAVerificationContext(object): - def __init__(self, backend, public_key, signature, algorithm): +class _ECDSAVerificationContext(AsymmetricVerificationContext): + def __init__( + self, + backend, + public_key: ec.EllipticCurvePublicKey, + signature: bytes, + algorithm: hashes.HashAlgorithm, + ): self._backend = backend self._public_key = public_key self._signature = signature self._digest = hashes.Hash(algorithm, backend) - def update(self, data): + def update(self, data: bytes) -> None: self._digest.update(data) - def verify(self): + def verify(self) -> None: digest = self._digest.finalize() _ecdsa_sig_verify( self._backend, self._public_key, self._signature, digest ) -@utils.register_interface(ec.EllipticCurvePrivateKey) -class _EllipticCurvePrivateKey(object): +class _EllipticCurvePrivateKey(ec.EllipticCurvePrivateKey): def __init__(self, backend, ec_key_cdata, evp_pkey): self._backend = backend self._ec_key = ec_key_cdata @@ -152,18 +162,24 @@ def __init__(self, backend, ec_key_cdata, evp_pkey): curve = utils.read_only_property("_curve") @property - def key_size(self): + def key_size(self) -> int: return self.curve.key_size - def signer(self, signature_algorithm): + def signer( + self, signature_algorithm: ec.EllipticCurveSignatureAlgorithm + ) -> AsymmetricSignatureContext: _warn_sign_verify_deprecated() _check_signature_algorithm(signature_algorithm) _check_not_prehashed(signature_algorithm.algorithm) + # This assert is to help mypy realize what type this object holds + assert isinstance(signature_algorithm.algorithm, hashes.HashAlgorithm) return _ECDSASignatureContext( self._backend, self, signature_algorithm.algorithm ) - def exchange(self, algorithm, peer_public_key): + def exchange( + self, algorithm: ec.ECDH, peer_public_key: ec.EllipticCurvePublicKey + ) -> bytes: if not ( self._backend.elliptic_curve_exchange_algorithm_supported( algorithm, self.curve @@ -184,7 +200,7 @@ def exchange(self, algorithm, peer_public_key): self._backend.openssl_assert(z_len > 0) z_buf = self._backend._ffi.new("uint8_t[]", z_len) peer_key = self._backend._lib.EC_KEY_get0_public_key( - peer_public_key._ec_key + peer_public_key._ec_key # type: ignore[attr-defined] ) r = self._backend._lib.ECDH_compute_key( @@ -193,7 +209,7 @@ def exchange(self, algorithm, peer_public_key): self._backend.openssl_assert(r > 0) return self._backend._ffi.buffer(z_buf)[:z_len] - def public_key(self): + def public_key(self) -> ec.EllipticCurvePublicKey: group = self._backend._lib.EC_KEY_get0_group(self._ec_key) self._backend.openssl_assert(group != self._backend._ffi.NULL) @@ -210,7 +226,7 @@ def public_key(self): return _EllipticCurvePublicKey(self._backend, public_ec_key, evp_pkey) - def private_numbers(self): + def private_numbers(self) -> ec.EllipticCurvePrivateNumbers: bn = self._backend._lib.EC_KEY_get0_private_key(self._ec_key) private_value = self._backend._bn_to_int(bn) return ec.EllipticCurvePrivateNumbers( @@ -218,7 +234,12 @@ def private_numbers(self): public_numbers=self.public_key().public_numbers(), ) - def private_bytes(self, encoding, format, encryption_algorithm): + def private_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PrivateFormat, + encryption_algorithm: serialization.KeySerializationEncryption, + ) -> bytes: return self._backend._private_key_bytes( encoding, format, @@ -228,16 +249,21 @@ def private_bytes(self, encoding, format, encryption_algorithm): self._ec_key, ) - def sign(self, data, signature_algorithm): + def sign( + self, + data: bytes, + signature_algorithm: ec.EllipticCurveSignatureAlgorithm, + ) -> bytes: _check_signature_algorithm(signature_algorithm) data, algorithm = _calculate_digest_and_algorithm( - self._backend, data, signature_algorithm._algorithm + self._backend, + data, + signature_algorithm._algorithm, # type: ignore[attr-defined] ) return _ecdsa_sig_sign(self._backend, self, data) -@utils.register_interface(ec.EllipticCurvePublicKey) -class _EllipticCurvePublicKey(object): +class _EllipticCurvePublicKey(ec.EllipticCurvePublicKey): def __init__(self, backend, ec_key_cdata, evp_pkey): self._backend = backend self._ec_key = ec_key_cdata @@ -250,20 +276,26 @@ def __init__(self, backend, ec_key_cdata, evp_pkey): curve = utils.read_only_property("_curve") @property - def key_size(self): + def key_size(self) -> int: return self.curve.key_size - def verifier(self, signature, signature_algorithm): + def verifier( + self, + signature: bytes, + signature_algorithm: ec.EllipticCurveSignatureAlgorithm, + ) -> AsymmetricVerificationContext: _warn_sign_verify_deprecated() utils._check_bytes("signature", signature) _check_signature_algorithm(signature_algorithm) _check_not_prehashed(signature_algorithm.algorithm) + # This assert is to help mypy realize what type this object holds + assert isinstance(signature_algorithm.algorithm, hashes.HashAlgorithm) return _ECDSAVerificationContext( self._backend, self, signature, signature_algorithm.algorithm ) - def public_numbers(self): + def public_numbers(self) -> ec.EllipticCurvePublicNumbers: get_func, group = self._backend._ec_key_determine_group_get_func( self._ec_key ) @@ -282,7 +314,7 @@ def public_numbers(self): return ec.EllipticCurvePublicNumbers(x=x, y=y, curve=self._curve) - def _encode_point(self, format): + def _encode_point(self, format: serialization.PublicFormat) -> bytes: if format is serialization.PublicFormat.CompressedPoint: conversion = self._backend._lib.POINT_CONVERSION_COMPRESSED else: @@ -306,8 +338,11 @@ def _encode_point(self, format): return self._backend._ffi.buffer(buf)[:] - def public_bytes(self, encoding, format): - + def public_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PublicFormat, + ) -> bytes: if ( encoding is serialization.Encoding.X962 or format is serialization.PublicFormat.CompressedPoint @@ -328,9 +363,16 @@ def public_bytes(self, encoding, format): encoding, format, self, self._evp_pkey, None ) - def verify(self, signature, data, signature_algorithm): + def verify( + self, + signature: bytes, + data: bytes, + signature_algorithm: ec.EllipticCurveSignatureAlgorithm, + ) -> None: _check_signature_algorithm(signature_algorithm) data, algorithm = _calculate_digest_and_algorithm( - self._backend, data, signature_algorithm._algorithm + self._backend, + data, + signature_algorithm._algorithm, # type: ignore[attr-defined] ) _ecdsa_sig_verify(self._backend, self, signature, data) diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index c1b7473fcf22..734226920678 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -10,6 +10,12 @@ from cryptography import utils from cryptography.hazmat._oid import ObjectIdentifier from cryptography.hazmat.backends import _get_backend +from cryptography.hazmat.primitives import _serialization, hashes +from cryptography.hazmat.primitives.asymmetric import ( + AsymmetricSignatureContext, + AsymmetricVerificationContext, + utils as asym_utils, +) class EllipticCurveOID(object): @@ -36,13 +42,13 @@ class EllipticCurveOID(object): class EllipticCurve(metaclass=abc.ABCMeta): @abc.abstractproperty - def name(self): + def name(self) -> str: """ The name of the curve. e.g. secp256r1. """ @abc.abstractproperty - def key_size(self): + def key_size(self) -> int: """ Bit size of a secret scalar for the curve. """ @@ -50,7 +56,9 @@ def key_size(self): class EllipticCurveSignatureAlgorithm(metaclass=abc.ABCMeta): @abc.abstractproperty - def algorithm(self): + def algorithm( + self, + ) -> typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm]: """ The digest algorithm used with this signature. """ @@ -58,50 +66,64 @@ def algorithm(self): class EllipticCurvePrivateKey(metaclass=abc.ABCMeta): @abc.abstractmethod - def signer(self, signature_algorithm): + def signer( + self, + signature_algorithm: EllipticCurveSignatureAlgorithm, + ) -> AsymmetricSignatureContext: """ Returns an AsymmetricSignatureContext used for signing data. """ @abc.abstractmethod - def exchange(self, algorithm, peer_public_key): + def exchange( + self, algorithm: "ECDH", peer_public_key: "EllipticCurvePublicKey" + ) -> bytes: """ Performs a key exchange operation using the provided algorithm with the provided peer's public key. """ @abc.abstractmethod - def public_key(self): + def public_key(self) -> "EllipticCurvePublicKey": """ The EllipticCurvePublicKey for this private key. """ @abc.abstractproperty - def curve(self): + def curve(self) -> EllipticCurve: """ The EllipticCurve that this key is on. """ @abc.abstractproperty - def key_size(self): + def key_size(self) -> int: """ Bit size of a secret scalar for the curve. """ @abc.abstractmethod - def sign(self, data, signature_algorithm): + def sign( + self, + data, + signature_algorithm: EllipticCurveSignatureAlgorithm, + ) -> bytes: """ Signs the data """ @abc.abstractmethod - def private_numbers(self): + def private_numbers(self) -> "EllipticCurvePrivateNumbers": """ Returns an EllipticCurvePrivateNumbers. """ @abc.abstractmethod - def private_bytes(self, encoding, format, encryption_algorithm): + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: """ Returns the key serialized as bytes. """ @@ -112,43 +134,58 @@ def private_bytes(self, encoding, format, encryption_algorithm): class EllipticCurvePublicKey(metaclass=abc.ABCMeta): @abc.abstractmethod - def verifier(self, signature, signature_algorithm): + def verifier( + self, + signature: bytes, + signature_algorithm: EllipticCurveSignatureAlgorithm, + ) -> AsymmetricVerificationContext: """ Returns an AsymmetricVerificationContext used for signing data. """ @abc.abstractproperty - def curve(self): + def curve(self) -> EllipticCurve: """ The EllipticCurve that this key is on. """ @abc.abstractproperty - def key_size(self): + def key_size(self) -> int: """ Bit size of a secret scalar for the curve. """ @abc.abstractmethod - def public_numbers(self): + def public_numbers(self) -> "EllipticCurvePublicNumbers": """ Returns an EllipticCurvePublicNumbers. """ @abc.abstractmethod - def public_bytes(self, encoding, format): + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: """ Returns the key serialized as bytes. """ @abc.abstractmethod - def verify(self, signature, data, signature_algorithm): + def verify( + self, + signature: bytes, + data: bytes, + algorithm: EllipticCurveSignatureAlgorithm, + ) -> None: """ Verifies the signature of the data. """ @classmethod - def from_encoded_point(cls, curve, data): + def from_encoded_point( + cls, curve: EllipticCurve, data: bytes + ) -> "EllipticCurvePublicKey": utils._check_bytes("data", data) if not isinstance(curve, EllipticCurve): @@ -288,20 +325,23 @@ class BrainpoolP512R1(EllipticCurve): } -@utils.register_interface(EllipticCurveSignatureAlgorithm) -class ECDSA(object): +class ECDSA(EllipticCurveSignatureAlgorithm): def __init__(self, algorithm): self._algorithm = algorithm algorithm = utils.read_only_property("_algorithm") -def generate_private_key(curve, backend=None): +def generate_private_key( + curve: EllipticCurve, backend=None +) -> EllipticCurvePrivateKey: backend = _get_backend(backend) return backend.generate_elliptic_curve_private_key(curve) -def derive_private_key(private_value, curve, backend=None): +def derive_private_key( + private_value: int, curve: EllipticCurve, backend=None +) -> EllipticCurvePrivateKey: backend = _get_backend(backend) if not isinstance(private_value, int): raise TypeError("private_value must be an integer type.") @@ -316,7 +356,7 @@ def derive_private_key(private_value, curve, backend=None): class EllipticCurvePublicNumbers(object): - def __init__(self, x, y, curve): + def __init__(self, x: int, y: int, curve: EllipticCurve): if not isinstance(x, int) or not isinstance(y, int): raise TypeError("x and y must be integers.") @@ -327,11 +367,11 @@ def __init__(self, x, y, curve): self._x = x self._curve = curve - def public_key(self, backend=None): + def public_key(self, backend=None) -> EllipticCurvePublicKey: backend = _get_backend(backend) return backend.load_elliptic_curve_public_numbers(self) - def encode_point(self): + def encode_point(self) -> bytes: warnings.warn( "encode_point has been deprecated on EllipticCurvePublicNumbers" " and will be removed in a future version. Please use " @@ -349,7 +389,9 @@ def encode_point(self): ) @classmethod - def from_encoded_point(cls, curve, data): + def from_encoded_point( + cls, curve: EllipticCurve, data: bytes + ) -> "EllipticCurvePublicNumbers": if not isinstance(curve, EllipticCurve): raise TypeError("curve must be an EllipticCurve instance") @@ -402,7 +444,9 @@ def __repr__(self): class EllipticCurvePrivateNumbers(object): - def __init__(self, private_value, public_numbers): + def __init__( + self, private_value: int, public_numbers: EllipticCurvePublicNumbers + ): if not isinstance(private_value, int): raise TypeError("private_value must be an integer.") @@ -415,7 +459,7 @@ def __init__(self, private_value, public_numbers): self._private_value = private_value self._public_numbers = public_numbers - def private_key(self, backend=None): + def private_key(self, backend=None) -> EllipticCurvePrivateKey: backend = _get_backend(backend) return backend.load_elliptic_curve_private_numbers(self) diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index b69475a12d9d..c089adc43c76 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -88,7 +88,7 @@ class DummyCurve(ec.EllipticCurve): class DummySignatureAlgorithm(ec.EllipticCurveSignatureAlgorithm): - algorithm = None + algorithm = hashes.SHA256() @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) @@ -129,10 +129,10 @@ def test_derive_private_key_errors(backend): _skip_curve_unsupported(backend, curve) with pytest.raises(TypeError): - ec.derive_private_key("one", curve, backend) + ec.derive_private_key("one", curve, backend) # type: ignore[arg-type] with pytest.raises(TypeError): - ec.derive_private_key(10, "five", backend) + ec.derive_private_key(10, "five", backend) # type: ignore[arg-type] with pytest.raises(ValueError): ec.derive_private_key(-7, curve, backend) @@ -167,7 +167,7 @@ def test_invalid_ec_numbers_args(private_value, x, y, curve): def test_invalid_private_numbers_public_numbers(): with pytest.raises(TypeError): - ec.EllipticCurvePrivateNumbers(1, None) + ec.EllipticCurvePrivateNumbers(1, None) # type: ignore[arg-type] def test_encode_point(): @@ -233,7 +233,7 @@ def test_from_encoded_point_not_a_curve(): with pytest.raises(TypeError): with pytest.warns(CryptographyDeprecationWarning): ec.EllipticCurvePublicNumbers.from_encoded_point( - "notacurve", b"\x04data" + "notacurve", b"\x04data" # type: ignore[arg-type] ) @@ -1128,7 +1128,7 @@ def test_from_encoded_point_empty_byte_string(self): def test_from_encoded_point_not_a_curve(self): with pytest.raises(TypeError): ec.EllipticCurvePublicKey.from_encoded_point( - "notacurve", b"\x04data" + "notacurve", b"\x04data" # type: ignore[arg-type] ) def test_from_encoded_point_unsupported_encoding(self): @@ -1187,7 +1187,9 @@ def test_signature_not_bytes(self, backend): with pytest.raises(TypeError), pytest.warns( CryptographyDeprecationWarning ): - public_key.verifier(1234, ec.ECDSA(hashes.SHA256())) + public_key.verifier( + 1234, ec.ECDSA(hashes.SHA256()) # type: ignore[arg-type] + ) @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) @@ -1241,15 +1243,15 @@ def test_key_exchange_with_vectors(self, backend, subtests): peer_pubkey = public_numbers.public_key(backend) z = private_key.exchange(ec.ECDH(), peer_pubkey) - z = int(hexlify(z).decode("ascii"), 16) + zz = int(hexlify(z).decode("ascii"), 16) # At this point fail indicates that one of the underlying keys # was changed. This results in a non-matching derived key. if vector["fail"]: # Errno 8 indicates Z should be changed. assert vector["errno"] == 8 - assert z != vector["Z"] + assert zz != vector["Z"] else: - assert z == vector["Z"] + assert zz == vector["Z"] @pytest.mark.parametrize( "vector", diff --git a/tests/wycheproof/test_ecdh.py b/tests/wycheproof/test_ecdh.py index a1a90c141b78..510ec93373a9 100644 --- a/tests/wycheproof/test_ecdh.py +++ b/tests/wycheproof/test_ecdh.py @@ -66,6 +66,7 @@ def test_ecdh(backend, wycheproof): public_key = serialization.load_der_public_key( binascii.unhexlify(wycheproof.testcase["public"]), backend ) + assert isinstance(public_key, ec.EllipticCurvePublicKey) except NotImplementedError: assert wycheproof.has_flag("UnnamedCurve") return @@ -93,6 +94,7 @@ def test_ecdh(backend, wycheproof): ) def test_ecdh_ecpoint(backend, wycheproof): curve = _CURVES[wycheproof.testgroup["curve"]] + assert isinstance(curve, ec.EllipticCurve) _skip_exchange_algorithm_unsupported(backend, ec.ECDH(), curve) private_key = ec.derive_private_key( From fe99089442826f7777067ceb7fb5bdb317b6465d Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 31 Jan 2021 22:23:13 -0600 Subject: [PATCH 0085/2380] add type hinting for ed25519 (#5728) --- .../hazmat/backends/openssl/ed25519.py | 31 ++++++++++++------- .../hazmat/primitives/asymmetric/ed25519.py | 26 +++++++++++----- tests/hazmat/primitives/test_ed25519.py | 12 ++++--- tests/hazmat/primitives/test_pkcs7.py | 2 +- 4 files changed, 46 insertions(+), 25 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/ed25519.py b/src/cryptography/hazmat/backends/openssl/ed25519.py index 7c57c8bd2a7b..ff6c20d7422d 100644 --- a/src/cryptography/hazmat/backends/openssl/ed25519.py +++ b/src/cryptography/hazmat/backends/openssl/ed25519.py @@ -3,7 +3,7 @@ # for complete details. -from cryptography import exceptions, utils +from cryptography import exceptions from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric.ed25519 import ( Ed25519PrivateKey, @@ -13,13 +13,16 @@ ) -@utils.register_interface(Ed25519PublicKey) -class _Ed25519PublicKey(object): +class _Ed25519PublicKey(Ed25519PublicKey): def __init__(self, backend, evp_pkey): self._backend = backend self._evp_pkey = evp_pkey - def public_bytes(self, encoding, format): + def public_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PublicFormat, + ) -> bytes: if ( encoding is serialization.Encoding.Raw or format is serialization.PublicFormat.Raw @@ -38,7 +41,7 @@ def public_bytes(self, encoding, format): encoding, format, self, self._evp_pkey, None ) - def _raw_public_bytes(self): + def _raw_public_bytes(self) -> bytes: buf = self._backend._ffi.new("unsigned char []", _ED25519_KEY_SIZE) buflen = self._backend._ffi.new("size_t *", _ED25519_KEY_SIZE) res = self._backend._lib.EVP_PKEY_get_raw_public_key( @@ -48,7 +51,7 @@ def _raw_public_bytes(self): self._backend.openssl_assert(buflen[0] == _ED25519_KEY_SIZE) return self._backend._ffi.buffer(buf, _ED25519_KEY_SIZE)[:] - def verify(self, signature, data): + def verify(self, signature: bytes, data: bytes) -> None: evp_md_ctx = self._backend._lib.EVP_MD_CTX_new() self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) evp_md_ctx = self._backend._ffi.gc( @@ -70,13 +73,12 @@ def verify(self, signature, data): raise exceptions.InvalidSignature -@utils.register_interface(Ed25519PrivateKey) -class _Ed25519PrivateKey(object): +class _Ed25519PrivateKey(Ed25519PrivateKey): def __init__(self, backend, evp_pkey): self._backend = backend self._evp_pkey = evp_pkey - def public_key(self): + def public_key(self) -> Ed25519PublicKey: buf = self._backend._ffi.new("unsigned char []", _ED25519_KEY_SIZE) buflen = self._backend._ffi.new("size_t *", _ED25519_KEY_SIZE) res = self._backend._lib.EVP_PKEY_get_raw_public_key( @@ -87,7 +89,7 @@ def public_key(self): public_bytes = self._backend._ffi.buffer(buf)[:] return self._backend.ed25519_load_public_bytes(public_bytes) - def sign(self, data): + def sign(self, data: bytes) -> bytes: evp_md_ctx = self._backend._lib.EVP_MD_CTX_new() self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) evp_md_ctx = self._backend._ffi.gc( @@ -110,7 +112,12 @@ def sign(self, data): self._backend.openssl_assert(buflen[0] == _ED25519_SIG_SIZE) return self._backend._ffi.buffer(buf, buflen[0])[:] - def private_bytes(self, encoding, format, encryption_algorithm): + def private_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PrivateFormat, + encryption_algorithm: serialization.KeySerializationEncryption, + ) -> bytes: if ( encoding is serialization.Encoding.Raw or format is serialization.PublicFormat.Raw @@ -133,7 +140,7 @@ def private_bytes(self, encoding, format, encryption_algorithm): encoding, format, encryption_algorithm, self, self._evp_pkey, None ) - def _raw_private_bytes(self): + def _raw_private_bytes(self) -> bytes: buf = self._backend._ffi.new("unsigned char []", _ED25519_KEY_SIZE) buflen = self._backend._ffi.new("size_t *", _ED25519_KEY_SIZE) res = self._backend._lib.EVP_PKEY_get_raw_private_key( diff --git a/src/cryptography/hazmat/primitives/asymmetric/ed25519.py b/src/cryptography/hazmat/primitives/asymmetric/ed25519.py index 3b82a7e37588..381dc26722dc 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ed25519.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ed25519.py @@ -6,6 +6,7 @@ import abc from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.primitives import _serialization _ED25519_KEY_SIZE = 32 @@ -14,7 +15,7 @@ class Ed25519PublicKey(metaclass=abc.ABCMeta): @classmethod - def from_public_bytes(cls, data): + def from_public_bytes(cls, data: bytes) -> "Ed25519PublicKey": from cryptography.hazmat.backends.openssl.backend import backend if not backend.ed25519_supported(): @@ -26,13 +27,17 @@ def from_public_bytes(cls, data): return backend.ed25519_load_public_bytes(data) @abc.abstractmethod - def public_bytes(self, encoding, format): + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: """ The serialized bytes of the public key. """ @abc.abstractmethod - def verify(self, signature, data): + def verify(self, signature: bytes, data: bytes): """ Verify the signature. """ @@ -40,7 +45,7 @@ def verify(self, signature, data): class Ed25519PrivateKey(metaclass=abc.ABCMeta): @classmethod - def generate(cls): + def generate(cls) -> "Ed25519PrivateKey": from cryptography.hazmat.backends.openssl.backend import backend if not backend.ed25519_supported(): @@ -52,7 +57,7 @@ def generate(cls): return backend.ed25519_generate_key() @classmethod - def from_private_bytes(cls, data): + def from_private_bytes(cls, data: bytes) -> "Ed25519PrivateKey": from cryptography.hazmat.backends.openssl.backend import backend if not backend.ed25519_supported(): @@ -64,19 +69,24 @@ def from_private_bytes(cls, data): return backend.ed25519_load_private_bytes(data) @abc.abstractmethod - def public_key(self): + def public_key(self) -> Ed25519PublicKey: """ The Ed25519PublicKey derived from the private key. """ @abc.abstractmethod - def private_bytes(self, encoding, format, encryption_algorithm): + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ): """ The serialized bytes of the private key. """ @abc.abstractmethod - def sign(self, data): + def sign(self, data: bytes) -> bytes: """ Signs the data. """ diff --git a/tests/hazmat/primitives/test_ed25519.py b/tests/hazmat/primitives/test_ed25519.py index ce74ee8f2d00..baaf67d63ac9 100644 --- a/tests/hazmat/primitives/test_ed25519.py +++ b/tests/hazmat/primitives/test_ed25519.py @@ -118,11 +118,15 @@ def test_load_public_bytes(self, backend): def test_invalid_type_public_bytes(self, backend): with pytest.raises(TypeError): - Ed25519PublicKey.from_public_bytes(object()) + Ed25519PublicKey.from_public_bytes( + object() # type: ignore[arg-type] + ) def test_invalid_type_private_bytes(self, backend): with pytest.raises(TypeError): - Ed25519PrivateKey.from_private_bytes(object()) + Ed25519PrivateKey.from_private_bytes( + object() # type: ignore[arg-type] + ) def test_invalid_length_from_public_bytes(self, backend): with pytest.raises(ValueError): @@ -142,14 +146,14 @@ def test_invalid_private_bytes(self, backend): key.private_bytes( serialization.Encoding.Raw, serialization.PrivateFormat.Raw, - None, + None, # type: ignore[arg-type] ) with pytest.raises(ValueError): key.private_bytes( serialization.Encoding.Raw, serialization.PrivateFormat.PKCS8, - None, + None, # type: ignore[arg-type] ) with pytest.raises(ValueError): diff --git a/tests/hazmat/primitives/test_pkcs7.py b/tests/hazmat/primitives/test_pkcs7.py index 8ee06db05073..6bc65eef3104 100644 --- a/tests/hazmat/primitives/test_pkcs7.py +++ b/tests/hazmat/primitives/test_pkcs7.py @@ -187,7 +187,7 @@ def test_unsupported_key_type(self, backend): key = ed25519.Ed25519PrivateKey.generate() with pytest.raises(TypeError): pkcs7.PKCS7SignatureBuilder().add_signer( - cert, key, hashes.SHA256() + cert, key, hashes.SHA256() # type: ignore[arg-type] ) def test_sign_invalid_options(self): From c1ccce75e0b3bda6ec1351860b13021332e41344 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 31 Jan 2021 22:24:04 -0600 Subject: [PATCH 0086/2380] poly1305 type hints (#5732) --- src/cryptography/hazmat/primitives/poly1305.py | 12 ++++++------ tests/hazmat/primitives/test_poly1305.py | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/cryptography/hazmat/primitives/poly1305.py b/src/cryptography/hazmat/primitives/poly1305.py index 9243d51a654f..f7819eaf4dc7 100644 --- a/src/cryptography/hazmat/primitives/poly1305.py +++ b/src/cryptography/hazmat/primitives/poly1305.py @@ -12,7 +12,7 @@ class Poly1305(object): - def __init__(self, key): + def __init__(self, key: bytes): from cryptography.hazmat.backends.openssl.backend import backend if not backend.poly1305_supported(): @@ -22,20 +22,20 @@ def __init__(self, key): ) self._ctx = backend.create_poly1305_ctx(key) - def update(self, data): + def update(self, data: bytes) -> None: if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") utils._check_byteslike("data", data) self._ctx.update(data) - def finalize(self): + def finalize(self) -> bytes: if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") mac = self._ctx.finalize() self._ctx = None return mac - def verify(self, tag): + def verify(self, tag: bytes) -> None: utils._check_bytes("tag", tag) if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") @@ -44,13 +44,13 @@ def verify(self, tag): ctx.verify(tag) @classmethod - def generate_tag(cls, key, data): + def generate_tag(cls, key: bytes, data: bytes) -> bytes: p = Poly1305(key) p.update(data) return p.finalize() @classmethod - def verify_tag(cls, key, data, tag): + def verify_tag(cls, key: bytes, data: bytes, tag: bytes) -> None: p = Poly1305(key) p.update(data) p.verify(tag) diff --git a/tests/hazmat/primitives/test_poly1305.py b/tests/hazmat/primitives/test_poly1305.py index 8cb40b3b13b1..280c9fb2c5d4 100644 --- a/tests/hazmat/primitives/test_poly1305.py +++ b/tests/hazmat/primitives/test_poly1305.py @@ -70,10 +70,10 @@ def test_raises_after_finalize(self, backend): def test_reject_unicode(self, backend): poly = Poly1305(b"0" * 32) with pytest.raises(TypeError): - poly.update("") + poly.update("") # type:ignore[arg-type] with pytest.raises(TypeError): - Poly1305.generate_tag(b"0" * 32, "") + Poly1305.generate_tag(b"0" * 32, "") # type:ignore[arg-type] def test_verify(self, backend): poly = Poly1305(b"0" * 32) @@ -106,17 +106,17 @@ def test_invalid_verify(self, backend): def test_verify_reject_unicode(self, backend): poly = Poly1305(b"0" * 32) with pytest.raises(TypeError): - poly.verify("") + poly.verify("") # type:ignore[arg-type] with pytest.raises(TypeError): - Poly1305.verify_tag(b"0" * 32, b"msg", "") + Poly1305.verify_tag(b"0" * 32, b"msg", "") # type:ignore[arg-type] def test_invalid_key_type(self, backend): with pytest.raises(TypeError): - Poly1305(object()) + Poly1305(object()) # type:ignore[arg-type] with pytest.raises(TypeError): - Poly1305.generate_tag(object(), b"msg") + Poly1305.generate_tag(object(), b"msg") # type:ignore[arg-type] def test_invalid_key_length(self, backend): with pytest.raises(ValueError): From d8123ed62d2ef05635e10f685a0b2a9ff6e06efe Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 31 Jan 2021 22:35:36 -0600 Subject: [PATCH 0087/2380] x25519/x448 type hints (#5731) * x25519 type hints * x448 type hints --- .../hazmat/backends/openssl/x25519.py | 28 +++++++++++-------- .../hazmat/backends/openssl/x448.py | 28 +++++++++++-------- .../hazmat/primitives/asymmetric/x25519.py | 24 +++++++++++----- .../hazmat/primitives/asymmetric/x448.py | 24 +++++++++++----- tests/hazmat/primitives/test_x25519.py | 14 ++++++---- tests/hazmat/primitives/test_x448.py | 6 ++-- 6 files changed, 80 insertions(+), 44 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/x25519.py b/src/cryptography/hazmat/backends/openssl/x25519.py index d0f60a075393..c2eb87ad4f98 100644 --- a/src/cryptography/hazmat/backends/openssl/x25519.py +++ b/src/cryptography/hazmat/backends/openssl/x25519.py @@ -3,7 +3,6 @@ # for complete details. -from cryptography import utils from cryptography.hazmat.backends.openssl.utils import _evp_pkey_derive from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric.x25519 import ( @@ -15,13 +14,16 @@ _X25519_KEY_SIZE = 32 -@utils.register_interface(X25519PublicKey) -class _X25519PublicKey(object): +class _X25519PublicKey(X25519PublicKey): def __init__(self, backend, evp_pkey): self._backend = backend self._evp_pkey = evp_pkey - def public_bytes(self, encoding, format): + def public_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PublicFormat, + ) -> bytes: if ( encoding is serialization.Encoding.Raw or format is serialization.PublicFormat.Raw @@ -40,7 +42,7 @@ def public_bytes(self, encoding, format): encoding, format, self, self._evp_pkey, None ) - def _raw_public_bytes(self): + def _raw_public_bytes(self) -> bytes: ucharpp = self._backend._ffi.new("unsigned char **") res = self._backend._lib.EVP_PKEY_get1_tls_encodedpoint( self._evp_pkey, ucharpp @@ -53,13 +55,12 @@ def _raw_public_bytes(self): return self._backend._ffi.buffer(data, res)[:] -@utils.register_interface(X25519PrivateKey) -class _X25519PrivateKey(object): +class _X25519PrivateKey(X25519PrivateKey): def __init__(self, backend, evp_pkey): self._backend = backend self._evp_pkey = evp_pkey - def public_key(self): + def public_key(self) -> X25519PublicKey: bio = self._backend._create_mem_bio_gc() res = self._backend._lib.i2d_PUBKEY_bio(bio, self._evp_pkey) self._backend.openssl_assert(res == 1) @@ -72,13 +73,18 @@ def public_key(self): ) return _X25519PublicKey(self._backend, evp_pkey) - def exchange(self, peer_public_key): + def exchange(self, peer_public_key: X25519PublicKey) -> bytes: if not isinstance(peer_public_key, X25519PublicKey): raise TypeError("peer_public_key must be X25519PublicKey.") return _evp_pkey_derive(self._backend, self._evp_pkey, peer_public_key) - def private_bytes(self, encoding, format, encryption_algorithm): + def private_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PrivateFormat, + encryption_algorithm: serialization.KeySerializationEncryption, + ) -> bytes: if ( encoding is serialization.Encoding.Raw or format is serialization.PublicFormat.Raw @@ -101,7 +107,7 @@ def private_bytes(self, encoding, format, encryption_algorithm): encoding, format, encryption_algorithm, self, self._evp_pkey, None ) - def _raw_private_bytes(self): + def _raw_private_bytes(self) -> bytes: # When we drop support for CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 we can # switch this to EVP_PKEY_new_raw_private_key # The trick we use here is serializing to a PKCS8 key and just diff --git a/src/cryptography/hazmat/backends/openssl/x448.py b/src/cryptography/hazmat/backends/openssl/x448.py index 7d836204ce60..8d3ceb11388a 100644 --- a/src/cryptography/hazmat/backends/openssl/x448.py +++ b/src/cryptography/hazmat/backends/openssl/x448.py @@ -3,7 +3,6 @@ # for complete details. -from cryptography import utils from cryptography.hazmat.backends.openssl.utils import _evp_pkey_derive from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric.x448 import ( @@ -14,13 +13,16 @@ _X448_KEY_SIZE = 56 -@utils.register_interface(X448PublicKey) -class _X448PublicKey(object): +class _X448PublicKey(X448PublicKey): def __init__(self, backend, evp_pkey): self._backend = backend self._evp_pkey = evp_pkey - def public_bytes(self, encoding, format): + def public_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PublicFormat, + ) -> bytes: if ( encoding is serialization.Encoding.Raw or format is serialization.PublicFormat.Raw @@ -39,7 +41,7 @@ def public_bytes(self, encoding, format): encoding, format, self, self._evp_pkey, None ) - def _raw_public_bytes(self): + def _raw_public_bytes(self) -> bytes: buf = self._backend._ffi.new("unsigned char []", _X448_KEY_SIZE) buflen = self._backend._ffi.new("size_t *", _X448_KEY_SIZE) res = self._backend._lib.EVP_PKEY_get_raw_public_key( @@ -50,13 +52,12 @@ def _raw_public_bytes(self): return self._backend._ffi.buffer(buf, _X448_KEY_SIZE)[:] -@utils.register_interface(X448PrivateKey) -class _X448PrivateKey(object): +class _X448PrivateKey(X448PrivateKey): def __init__(self, backend, evp_pkey): self._backend = backend self._evp_pkey = evp_pkey - def public_key(self): + def public_key(self) -> X448PublicKey: buf = self._backend._ffi.new("unsigned char []", _X448_KEY_SIZE) buflen = self._backend._ffi.new("size_t *", _X448_KEY_SIZE) res = self._backend._lib.EVP_PKEY_get_raw_public_key( @@ -66,13 +67,18 @@ def public_key(self): self._backend.openssl_assert(buflen[0] == _X448_KEY_SIZE) return self._backend.x448_load_public_bytes(buf) - def exchange(self, peer_public_key): + def exchange(self, peer_public_key: X448PublicKey) -> bytes: if not isinstance(peer_public_key, X448PublicKey): raise TypeError("peer_public_key must be X448PublicKey.") return _evp_pkey_derive(self._backend, self._evp_pkey, peer_public_key) - def private_bytes(self, encoding, format, encryption_algorithm): + def private_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PrivateFormat, + encryption_algorithm: serialization.KeySerializationEncryption, + ) -> bytes: if ( encoding is serialization.Encoding.Raw or format is serialization.PublicFormat.Raw @@ -95,7 +101,7 @@ def private_bytes(self, encoding, format, encryption_algorithm): encoding, format, encryption_algorithm, self, self._evp_pkey, None ) - def _raw_private_bytes(self): + def _raw_private_bytes(self) -> bytes: buf = self._backend._ffi.new("unsigned char []", _X448_KEY_SIZE) buflen = self._backend._ffi.new("size_t *", _X448_KEY_SIZE) res = self._backend._lib.EVP_PKEY_get_raw_private_key( diff --git a/src/cryptography/hazmat/primitives/asymmetric/x25519.py b/src/cryptography/hazmat/primitives/asymmetric/x25519.py index ac7ebdf0d12c..690af78c2152 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/x25519.py +++ b/src/cryptography/hazmat/primitives/asymmetric/x25519.py @@ -6,11 +6,12 @@ import abc from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.primitives import _serialization class X25519PublicKey(metaclass=abc.ABCMeta): @classmethod - def from_public_bytes(cls, data): + def from_public_bytes(cls, data: bytes) -> "X25519PublicKey": from cryptography.hazmat.backends.openssl.backend import backend if not backend.x25519_supported(): @@ -22,7 +23,11 @@ def from_public_bytes(cls, data): return backend.x25519_load_public_bytes(data) @abc.abstractmethod - def public_bytes(self, encoding, format): + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: """ The serialized bytes of the public key. """ @@ -30,7 +35,7 @@ def public_bytes(self, encoding, format): class X25519PrivateKey(metaclass=abc.ABCMeta): @classmethod - def generate(cls): + def generate(cls) -> "X25519PrivateKey": from cryptography.hazmat.backends.openssl.backend import backend if not backend.x25519_supported(): @@ -41,7 +46,7 @@ def generate(cls): return backend.x25519_generate_key() @classmethod - def from_private_bytes(cls, data): + def from_private_bytes(cls, data: bytes) -> "X25519PrivateKey": from cryptography.hazmat.backends.openssl.backend import backend if not backend.x25519_supported(): @@ -53,19 +58,24 @@ def from_private_bytes(cls, data): return backend.x25519_load_private_bytes(data) @abc.abstractmethod - def public_key(self): + def public_key(self) -> X25519PublicKey: """ The serialized bytes of the public key. """ @abc.abstractmethod - def private_bytes(self, encoding, format, encryption_algorithm): + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: """ The serialized bytes of the private key. """ @abc.abstractmethod - def exchange(self, peer_public_key): + def exchange(self, peer_public_key: X25519PublicKey) -> bytes: """ Performs a key exchange operation using the provided peer's public key. """ diff --git a/src/cryptography/hazmat/primitives/asymmetric/x448.py b/src/cryptography/hazmat/primitives/asymmetric/x448.py index 46ad3f0e2515..4282543d92bc 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/x448.py +++ b/src/cryptography/hazmat/primitives/asymmetric/x448.py @@ -6,11 +6,12 @@ import abc from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.primitives import _serialization class X448PublicKey(metaclass=abc.ABCMeta): @classmethod - def from_public_bytes(cls, data): + def from_public_bytes(cls, data) -> "X448PublicKey": from cryptography.hazmat.backends.openssl.backend import backend if not backend.x448_supported(): @@ -22,7 +23,11 @@ def from_public_bytes(cls, data): return backend.x448_load_public_bytes(data) @abc.abstractmethod - def public_bytes(self, encoding, format): + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: """ The serialized bytes of the public key. """ @@ -30,7 +35,7 @@ def public_bytes(self, encoding, format): class X448PrivateKey(metaclass=abc.ABCMeta): @classmethod - def generate(cls): + def generate(cls) -> "X448PrivateKey": from cryptography.hazmat.backends.openssl.backend import backend if not backend.x448_supported(): @@ -41,7 +46,7 @@ def generate(cls): return backend.x448_generate_key() @classmethod - def from_private_bytes(cls, data): + def from_private_bytes(cls, data: bytes) -> "X448PrivateKey": from cryptography.hazmat.backends.openssl.backend import backend if not backend.x448_supported(): @@ -53,19 +58,24 @@ def from_private_bytes(cls, data): return backend.x448_load_private_bytes(data) @abc.abstractmethod - def public_key(self): + def public_key(self) -> X448PublicKey: """ The serialized bytes of the public key. """ @abc.abstractmethod - def private_bytes(self, encoding, format, encryption_algorithm): + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: """ The serialized bytes of the private key. """ @abc.abstractmethod - def exchange(self, peer_public_key): + def exchange(self, peer_public_key: X448PublicKey) -> bytes: """ Performs a key exchange operation using the provided peer's public key. """ diff --git a/tests/hazmat/primitives/test_x25519.py b/tests/hazmat/primitives/test_x25519.py index a572e7bf0d69..6156f7961b24 100644 --- a/tests/hazmat/primitives/test_x25519.py +++ b/tests/hazmat/primitives/test_x25519.py @@ -97,9 +97,13 @@ def test_null_shared_key_raises_error(self, backend): def test_public_bytes_bad_args(self, backend): key = X25519PrivateKey.generate().public_key() with pytest.raises(ValueError): - key.public_bytes(None, serialization.PublicFormat.Raw) + key.public_bytes( + None, serialization.PublicFormat.Raw # type: ignore[arg-type] + ) with pytest.raises(TypeError): - key.public_bytes(serialization.Encoding.Raw) + key.public_bytes( + serialization.Encoding.Raw # type: ignore[call-arg] + ) # These vectors are also from RFC 7748 # https://tools.ietf.org/html/rfc7748#section-6.1 @@ -160,7 +164,7 @@ def test_generate(self, backend): def test_invalid_type_exchange(self, backend): key = X25519PrivateKey.generate() with pytest.raises(TypeError): - key.exchange(object()) + key.exchange(object()) # type: ignore[arg-type] def test_invalid_length_from_public_bytes(self, backend): with pytest.raises(ValueError): @@ -182,14 +186,14 @@ def test_invalid_private_bytes(self, backend): key.private_bytes( serialization.Encoding.Raw, serialization.PrivateFormat.Raw, - None, + None, # type: ignore[arg-type] ) with pytest.raises(ValueError): key.private_bytes( serialization.Encoding.Raw, serialization.PrivateFormat.PKCS8, - None, + None, # type: ignore[arg-type] ) with pytest.raises(ValueError): diff --git a/tests/hazmat/primitives/test_x448.py b/tests/hazmat/primitives/test_x448.py index 89423b67cc21..6e0a060c32d6 100644 --- a/tests/hazmat/primitives/test_x448.py +++ b/tests/hazmat/primitives/test_x448.py @@ -179,7 +179,7 @@ def test_generate(self, backend): def test_invalid_type_exchange(self, backend): key = X448PrivateKey.generate() with pytest.raises(TypeError): - key.exchange(object()) + key.exchange(object()) # type: ignore[arg-type] def test_invalid_length_from_public_bytes(self, backend): with pytest.raises(ValueError): @@ -201,14 +201,14 @@ def test_invalid_private_bytes(self, backend): key.private_bytes( serialization.Encoding.Raw, serialization.PrivateFormat.Raw, - None, + None, # type: ignore[arg-type] ) with pytest.raises(ValueError): key.private_bytes( serialization.Encoding.Raw, serialization.PrivateFormat.PKCS8, - None, + None, # type: ignore[arg-type] ) with pytest.raises(ValueError): From d67d8e7c670585c29594bd3ed95d98d657c3903d Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 31 Jan 2021 23:33:53 -0600 Subject: [PATCH 0088/2380] type hints for asym utils (#5734) --- .../hazmat/primitives/asymmetric/utils.py | 8 +++++--- tests/hazmat/primitives/test_asym_utils.py | 12 ++++++------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/cryptography/hazmat/primitives/asymmetric/utils.py b/src/cryptography/hazmat/primitives/asymmetric/utils.py index ecc68c3bce2e..1118abcf251f 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/utils.py +++ b/src/cryptography/hazmat/primitives/asymmetric/utils.py @@ -3,6 +3,8 @@ # for complete details. +import typing + from cryptography import utils from cryptography.hazmat._der import ( DERReader, @@ -14,14 +16,14 @@ from cryptography.hazmat.primitives import hashes -def decode_dss_signature(signature): +def decode_dss_signature(signature: bytes) -> typing.Tuple[int, int]: with DERReader(signature).read_single_element(SEQUENCE) as seq: r = seq.read_element(INTEGER).as_integer() s = seq.read_element(INTEGER).as_integer() return r, s -def encode_dss_signature(r, s): +def encode_dss_signature(r: int, s: int) -> bytes: return encode_der( SEQUENCE, encode_der(INTEGER, encode_der_integer(r)), @@ -30,7 +32,7 @@ def encode_dss_signature(r, s): class Prehashed(object): - def __init__(self, algorithm): + def __init__(self, algorithm: hashes.HashAlgorithm): if not isinstance(algorithm, hashes.HashAlgorithm): raise TypeError("Expected instance of HashAlgorithm.") diff --git a/tests/hazmat/primitives/test_asym_utils.py b/tests/hazmat/primitives/test_asym_utils.py index dd837af7f09f..0891cc87aa1d 100644 --- a/tests/hazmat/primitives/test_asym_utils.py +++ b/tests/hazmat/primitives/test_asym_utils.py @@ -35,19 +35,19 @@ def test_dss_signature(): def test_encode_dss_non_integer(): with pytest.raises(ValueError): - encode_dss_signature("h", 3) + encode_dss_signature("h", 3) # type: ignore[arg-type] with pytest.raises(ValueError): - encode_dss_signature("3", "2") + encode_dss_signature("3", "2") # type: ignore[arg-type] with pytest.raises(ValueError): - encode_dss_signature(3, "h") + encode_dss_signature(3, "h") # type: ignore[arg-type] with pytest.raises(ValueError): - encode_dss_signature(3.3, 1.2) + encode_dss_signature(3.3, 1.2) # type: ignore[arg-type] with pytest.raises(ValueError): - encode_dss_signature("hello", "world") + encode_dss_signature("hello", "world") # type: ignore[arg-type] def test_encode_dss_negative(): @@ -73,4 +73,4 @@ def test_decode_dss_invalid_asn1(): def test_pass_invalid_prehashed_arg(): with pytest.raises(TypeError): - Prehashed(object()) + Prehashed(object()) # type: ignore[arg-type] From 83692df7a82be01dbe3041b3911a0fe3f5ce04a9 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 1 Feb 2021 13:46:48 -0600 Subject: [PATCH 0089/2380] add optional block_size to the HashAlgorithm interface (#5736) This makes typing ConcatKDF easier --- src/cryptography/hazmat/primitives/hashes.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/cryptography/hazmat/primitives/hashes.py b/src/cryptography/hazmat/primitives/hashes.py index b296f15969d4..33907a35a7c5 100644 --- a/src/cryptography/hazmat/primitives/hashes.py +++ b/src/cryptography/hazmat/primitives/hashes.py @@ -3,6 +3,7 @@ # for complete details. import abc +import typing from cryptography import utils from cryptography.exceptions import ( @@ -27,6 +28,13 @@ def digest_size(self) -> int: The size of the resulting digest in bytes. """ + @abc.abstractproperty + def block_size(self) -> typing.Optional[int]: + """ + The internal block size of the hash function, or None if the hash + function does not use blocks internally (e.g. SHA3). + """ + class HashContext(metaclass=abc.ABCMeta): @abc.abstractproperty @@ -148,25 +156,30 @@ class SHA512(HashAlgorithm): class SHA3_224(HashAlgorithm): # noqa: N801 name = "sha3-224" digest_size = 28 + block_size = None class SHA3_256(HashAlgorithm): # noqa: N801 name = "sha3-256" digest_size = 32 + block_size = None class SHA3_384(HashAlgorithm): # noqa: N801 name = "sha3-384" digest_size = 48 + block_size = None class SHA3_512(HashAlgorithm): # noqa: N801 name = "sha3-512" digest_size = 64 + block_size = None class SHAKE128(HashAlgorithm, ExtendableOutputFunction): name = "shake128" + block_size = None def __init__(self, digest_size: int): if not isinstance(digest_size, int): @@ -182,6 +195,7 @@ def __init__(self, digest_size: int): class SHAKE256(HashAlgorithm, ExtendableOutputFunction): name = "shake256" + block_size = None def __init__(self, digest_size: int): if not isinstance(digest_size, int): From 3d58647904ddfbf05a256e48a806c4847fc9c5df Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 1 Feb 2021 15:53:47 -0600 Subject: [PATCH 0090/2380] KDF type hinting (#5735) * KDF type hinting * more types * less contortions --- .../hazmat/primitives/kdf/__init__.py | 4 +- .../hazmat/primitives/kdf/concatkdf.py | 64 +++++++++++++------ .../hazmat/primitives/kdf/hkdf.py | 39 +++++++---- .../hazmat/primitives/kdf/kbkdf.py | 30 ++++----- .../hazmat/primitives/kdf/pbkdf2.py | 18 ++++-- .../hazmat/primitives/kdf/scrypt.py | 11 ++-- .../hazmat/primitives/kdf/x963kdf.py | 16 +++-- tests/hazmat/primitives/test_concatkdf.py | 36 +++++++---- tests/hazmat/primitives/test_hkdf.py | 26 ++++++-- tests/hazmat/primitives/test_kbkdf.py | 16 ++--- tests/hazmat/primitives/test_pbkdf2hmac.py | 10 ++- tests/hazmat/primitives/test_scrypt.py | 6 +- tests/hazmat/primitives/test_x963kdf.py | 15 +++-- 13 files changed, 188 insertions(+), 103 deletions(-) diff --git a/src/cryptography/hazmat/primitives/kdf/__init__.py b/src/cryptography/hazmat/primitives/kdf/__init__.py index 883bd1fd3cdb..38e2f8bc4d66 100644 --- a/src/cryptography/hazmat/primitives/kdf/__init__.py +++ b/src/cryptography/hazmat/primitives/kdf/__init__.py @@ -8,14 +8,14 @@ class KeyDerivationFunction(metaclass=abc.ABCMeta): @abc.abstractmethod - def derive(self, key_material): + def derive(self, key_material: bytes) -> bytes: """ Deterministically generates and returns a new key based on the existing key material. """ @abc.abstractmethod - def verify(self, key_material, expected_key): + def verify(self, key_material: bytes, expected_key: bytes) -> None: """ Checks whether the key generated by the key material matches the expected derived key. Raises an exception if they do not match. diff --git a/src/cryptography/hazmat/primitives/kdf/concatkdf.py b/src/cryptography/hazmat/primitives/kdf/concatkdf.py index 85970fa574bd..196d3a492e29 100644 --- a/src/cryptography/hazmat/primitives/kdf/concatkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/concatkdf.py @@ -4,6 +4,7 @@ import struct +import typing from cryptography import utils from cryptography.exceptions import ( @@ -19,11 +20,15 @@ from cryptography.hazmat.primitives.kdf import KeyDerivationFunction -def _int_to_u32be(n): +def _int_to_u32be(n: int) -> bytes: return struct.pack(">I", n) -def _common_args_checks(algorithm, length, otherinfo): +def _common_args_checks( + algorithm: hashes.HashAlgorithm, + length: int, + otherinfo: typing.Optional[bytes], +): max_length = algorithm.digest_size * (2 ** 32 - 1) if length > max_length: raise ValueError( @@ -33,7 +38,12 @@ def _common_args_checks(algorithm, length, otherinfo): utils._check_bytes("otherinfo", otherinfo) -def _concatkdf_derive(key_material, length, auxfn, otherinfo): +def _concatkdf_derive( + key_material: bytes, + length: int, + auxfn: typing.Callable[[], hashes.HashContext], + otherinfo: bytes, +) -> bytes: utils._check_byteslike("key_material", key_material) output = [b""] outlen = 0 @@ -51,17 +61,20 @@ def _concatkdf_derive(key_material, length, auxfn, otherinfo): return b"".join(output)[:length] -@utils.register_interface(KeyDerivationFunction) -class ConcatKDFHash(object): - def __init__(self, algorithm, length, otherinfo, backend=None): +class ConcatKDFHash(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + length: int, + otherinfo: typing.Optional[bytes], + backend=None, + ): backend = _get_backend(backend) _common_args_checks(algorithm, length, otherinfo) self._algorithm = algorithm self._length = length - self._otherinfo = otherinfo - if self._otherinfo is None: - self._otherinfo = b"" + self._otherinfo: bytes = otherinfo if otherinfo is not None else b"" if not isinstance(backend, HashBackend): raise UnsupportedAlgorithm( @@ -71,10 +84,10 @@ def __init__(self, algorithm, length, otherinfo, backend=None): self._backend = backend self._used = False - def _hash(self): + def _hash(self) -> hashes.Hash: return hashes.Hash(self._algorithm, self._backend) - def derive(self, key_material): + def derive(self, key_material: bytes) -> bytes: if self._used: raise AlreadyFinalized self._used = True @@ -82,22 +95,31 @@ def derive(self, key_material): key_material, self._length, self._hash, self._otherinfo ) - def verify(self, key_material, expected_key): + def verify(self, key_material: bytes, expected_key: bytes) -> None: if not constant_time.bytes_eq(self.derive(key_material), expected_key): raise InvalidKey -@utils.register_interface(KeyDerivationFunction) -class ConcatKDFHMAC(object): - def __init__(self, algorithm, length, salt, otherinfo, backend=None): +class ConcatKDFHMAC(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + length: int, + salt: typing.Optional[bytes], + otherinfo: typing.Optional[bytes], + backend=None, + ): backend = _get_backend(backend) _common_args_checks(algorithm, length, otherinfo) self._algorithm = algorithm self._length = length - self._otherinfo = otherinfo - if self._otherinfo is None: - self._otherinfo = b"" + self._otherinfo: bytes = otherinfo if otherinfo is not None else b"" + + if algorithm.block_size is None: + raise TypeError( + "{} is unsupported for ConcatKDF".format(algorithm.name) + ) if salt is None: salt = b"\x00" * algorithm.block_size @@ -114,10 +136,10 @@ def __init__(self, algorithm, length, salt, otherinfo, backend=None): self._backend = backend self._used = False - def _hmac(self): + def _hmac(self) -> hmac.HMAC: return hmac.HMAC(self._salt, self._algorithm, self._backend) - def derive(self, key_material): + def derive(self, key_material: bytes): if self._used: raise AlreadyFinalized self._used = True @@ -125,6 +147,6 @@ def derive(self, key_material): key_material, self._length, self._hmac, self._otherinfo ) - def verify(self, key_material, expected_key): + def verify(self, key_material: bytes, expected_key: bytes) -> None: if not constant_time.bytes_eq(self.derive(key_material), expected_key): raise InvalidKey diff --git a/src/cryptography/hazmat/primitives/kdf/hkdf.py b/src/cryptography/hazmat/primitives/kdf/hkdf.py index 17191a2d42fb..9a05a139265b 100644 --- a/src/cryptography/hazmat/primitives/kdf/hkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/hkdf.py @@ -3,6 +3,8 @@ # for complete details. +import typing + from cryptography import utils from cryptography.exceptions import ( AlreadyFinalized, @@ -12,13 +14,19 @@ ) from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.backends.interfaces import HMACBackend -from cryptography.hazmat.primitives import constant_time, hmac +from cryptography.hazmat.primitives import constant_time, hashes, hmac from cryptography.hazmat.primitives.kdf import KeyDerivationFunction -@utils.register_interface(KeyDerivationFunction) -class HKDF(object): - def __init__(self, algorithm, length, salt, info, backend=None): +class HKDF(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + length: int, + salt: typing.Optional[bytes], + info: typing.Optional[bytes], + backend=None, + ): backend = _get_backend(backend) if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( @@ -39,23 +47,28 @@ def __init__(self, algorithm, length, salt, info, backend=None): self._hkdf_expand = HKDFExpand(self._algorithm, length, info, backend) - def _extract(self, key_material): + def _extract(self, key_material: bytes) -> bytes: h = hmac.HMAC(self._salt, self._algorithm, backend=self._backend) h.update(key_material) return h.finalize() - def derive(self, key_material): + def derive(self, key_material: bytes) -> bytes: utils._check_byteslike("key_material", key_material) return self._hkdf_expand.derive(self._extract(key_material)) - def verify(self, key_material, expected_key): + def verify(self, key_material: bytes, expected_key: bytes) -> None: if not constant_time.bytes_eq(self.derive(key_material), expected_key): raise InvalidKey -@utils.register_interface(KeyDerivationFunction) -class HKDFExpand(object): - def __init__(self, algorithm, length, info, backend=None): +class HKDFExpand(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + length: int, + info: typing.Optional[bytes], + backend=None, + ): backend = _get_backend(backend) if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( @@ -85,7 +98,7 @@ def __init__(self, algorithm, length, info, backend=None): self._used = False - def _expand(self, key_material): + def _expand(self, key_material: bytes) -> bytes: output = [b""] counter = 1 @@ -99,7 +112,7 @@ def _expand(self, key_material): return b"".join(output)[: self._length] - def derive(self, key_material): + def derive(self, key_material: bytes) -> bytes: utils._check_byteslike("key_material", key_material) if self._used: raise AlreadyFinalized @@ -107,6 +120,6 @@ def derive(self, key_material): self._used = True return self._expand(key_material) - def verify(self, key_material, expected_key): + def verify(self, key_material: bytes, expected_key: bytes) -> None: if not constant_time.bytes_eq(self.derive(key_material), expected_key): raise InvalidKey diff --git a/src/cryptography/hazmat/primitives/kdf/kbkdf.py b/src/cryptography/hazmat/primitives/kdf/kbkdf.py index cc092533172f..ac36474fd7ae 100644 --- a/src/cryptography/hazmat/primitives/kdf/kbkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/kbkdf.py @@ -3,6 +3,7 @@ # for complete details. +import typing from enum import Enum from cryptography import utils @@ -27,19 +28,18 @@ class CounterLocation(Enum): AfterFixed = "after_fixed" -@utils.register_interface(KeyDerivationFunction) -class KBKDFHMAC(object): +class KBKDFHMAC(KeyDerivationFunction): def __init__( self, - algorithm, - mode, - length, - rlen, - llen, - location, - label, - context, - fixed, + algorithm: hashes.HashAlgorithm, + mode: Mode, + length: int, + rlen: int, + llen: typing.Optional[int], + location: CounterLocation, + label: typing.Optional[bytes], + context: typing.Optional[bytes], + fixed: typing.Optional[bytes], backend=None, ): backend = _get_backend(backend) @@ -101,7 +101,7 @@ def __init__( self._used = False self._fixed_data = fixed - def _valid_byte_length(self, value): + def _valid_byte_length(self, value: int) -> bool: if not isinstance(value, int): raise TypeError("value must be of type int") @@ -110,7 +110,7 @@ def _valid_byte_length(self, value): return False return True - def derive(self, key_material): + def derive(self, key_material: bytes) -> bytes: if self._used: raise AlreadyFinalized @@ -146,7 +146,7 @@ def derive(self, key_material): return b"".join(output)[: self._length] - def _generate_fixed_input(self): + def _generate_fixed_input(self) -> bytes: if self._fixed_data and isinstance(self._fixed_data, bytes): return self._fixed_data @@ -154,6 +154,6 @@ def _generate_fixed_input(self): return b"".join([self._label, b"\x00", self._context, l_val]) - def verify(self, key_material, expected_key): + def verify(self, key_material: bytes, expected_key: bytes) -> None: if not constant_time.bytes_eq(self.derive(key_material), expected_key): raise InvalidKey diff --git a/src/cryptography/hazmat/primitives/kdf/pbkdf2.py b/src/cryptography/hazmat/primitives/kdf/pbkdf2.py index 00cc0955ae5c..d1c10af53591 100644 --- a/src/cryptography/hazmat/primitives/kdf/pbkdf2.py +++ b/src/cryptography/hazmat/primitives/kdf/pbkdf2.py @@ -12,13 +12,19 @@ ) from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.backends.interfaces import PBKDF2HMACBackend -from cryptography.hazmat.primitives import constant_time +from cryptography.hazmat.primitives import constant_time, hashes from cryptography.hazmat.primitives.kdf import KeyDerivationFunction -@utils.register_interface(KeyDerivationFunction) -class PBKDF2HMAC(object): - def __init__(self, algorithm, length, salt, iterations, backend=None): +class PBKDF2HMAC(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + length: int, + salt: bytes, + iterations: int, + backend=None, + ): backend = _get_backend(backend) if not isinstance(backend, PBKDF2HMACBackend): raise UnsupportedAlgorithm( @@ -41,7 +47,7 @@ def __init__(self, algorithm, length, salt, iterations, backend=None): self._iterations = iterations self._backend = backend - def derive(self, key_material): + def derive(self, key_material: bytes) -> bytes: if self._used: raise AlreadyFinalized("PBKDF2 instances can only be used once.") self._used = True @@ -55,7 +61,7 @@ def derive(self, key_material): key_material, ) - def verify(self, key_material, expected_key): + def verify(self, key_material: bytes, expected_key: bytes) -> None: derived_key = self.derive(key_material) if not constant_time.bytes_eq(derived_key, expected_key): raise InvalidKey("Keys do not match.") diff --git a/src/cryptography/hazmat/primitives/kdf/scrypt.py b/src/cryptography/hazmat/primitives/kdf/scrypt.py index 7d25e79cef59..7547dca5c095 100644 --- a/src/cryptography/hazmat/primitives/kdf/scrypt.py +++ b/src/cryptography/hazmat/primitives/kdf/scrypt.py @@ -23,9 +23,10 @@ _MEM_LIMIT = sys.maxsize // 2 -@utils.register_interface(KeyDerivationFunction) -class Scrypt(object): - def __init__(self, salt, length, n, r, p, backend=None): +class Scrypt(KeyDerivationFunction): + def __init__( + self, salt: bytes, length: int, n: int, r: int, p: int, backend=None + ): backend = _get_backend(backend) if not isinstance(backend, ScryptBackend): raise UnsupportedAlgorithm( @@ -51,7 +52,7 @@ def __init__(self, salt, length, n, r, p, backend=None): self._p = p self._backend = backend - def derive(self, key_material): + def derive(self, key_material: bytes) -> bytes: if self._used: raise AlreadyFinalized("Scrypt instances can only be used once.") self._used = True @@ -61,7 +62,7 @@ def derive(self, key_material): key_material, self._salt, self._length, self._n, self._r, self._p ) - def verify(self, key_material, expected_key): + def verify(self, key_material: bytes, expected_key: bytes) -> None: derived_key = self.derive(key_material) if not constant_time.bytes_eq(derived_key, expected_key): raise InvalidKey("Keys do not match.") diff --git a/src/cryptography/hazmat/primitives/kdf/x963kdf.py b/src/cryptography/hazmat/primitives/kdf/x963kdf.py index 1d9aae17f13e..21a47f665ff3 100644 --- a/src/cryptography/hazmat/primitives/kdf/x963kdf.py +++ b/src/cryptography/hazmat/primitives/kdf/x963kdf.py @@ -4,6 +4,7 @@ import struct +import typing from cryptography import utils from cryptography.exceptions import ( @@ -22,9 +23,14 @@ def _int_to_u32be(n): return struct.pack(">I", n) -@utils.register_interface(KeyDerivationFunction) -class X963KDF(object): - def __init__(self, algorithm, length, sharedinfo, backend=None): +class X963KDF(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + length: int, + sharedinfo: typing.Optional[bytes], + backend=None, + ): backend = _get_backend(backend) max_len = algorithm.digest_size * (2 ** 32 - 1) @@ -47,7 +53,7 @@ def __init__(self, algorithm, length, sharedinfo, backend=None): self._backend = backend self._used = False - def derive(self, key_material): + def derive(self, key_material: bytes) -> bytes: if self._used: raise AlreadyFinalized self._used = True @@ -68,6 +74,6 @@ def derive(self, key_material): return b"".join(output)[: self._length] - def verify(self, key_material, expected_key): + def verify(self, key_material: bytes, expected_key: bytes) -> None: if not constant_time.bytes_eq(self.derive(key_material), expected_key): raise InvalidKey diff --git a/tests/hazmat/primitives/test_concatkdf.py b/tests/hazmat/primitives/test_concatkdf.py index bb90bb15353d..8a6ee2e41200 100644 --- a/tests/hazmat/primitives/test_concatkdf.py +++ b/tests/hazmat/primitives/test_concatkdf.py @@ -79,7 +79,7 @@ def test_verify(self, backend): ckdf = ConcatKDFHash(hashes.SHA256(), 16, oinfo, backend) - assert ckdf.verify(prk, okm) is None + ckdf.verify(prk, okm) def test_invalid_verify(self, backend): prk = binascii.unhexlify( @@ -99,7 +99,10 @@ def test_invalid_verify(self, backend): def test_unicode_typeerror(self, backend): with pytest.raises(TypeError): ConcatKDFHash( - hashes.SHA256(), 16, otherinfo="foo", backend=backend + hashes.SHA256(), + 16, + otherinfo="foo", # type: ignore[arg-type] + backend=backend, ) with pytest.raises(TypeError): @@ -107,21 +110,21 @@ def test_unicode_typeerror(self, backend): hashes.SHA256(), 16, otherinfo=None, backend=backend ) - ckdf.derive("foo") + ckdf.derive("foo") # type: ignore[arg-type] with pytest.raises(TypeError): ckdf = ConcatKDFHash( hashes.SHA256(), 16, otherinfo=None, backend=backend ) - ckdf.verify("foo", b"bar") + ckdf.verify("foo", b"bar") # type: ignore[arg-type] with pytest.raises(TypeError): ckdf = ConcatKDFHash( hashes.SHA256(), 16, otherinfo=None, backend=backend ) - ckdf.verify(b"foo", "bar") + ckdf.verify(b"foo", "bar") # type: ignore[arg-type] @pytest.mark.requires_backend_interface(interface=HMACBackend) @@ -224,7 +227,7 @@ def test_verify(self, backend): ckdf = ConcatKDFHMAC(hashes.SHA512(), 32, None, oinfo, backend) - assert ckdf.verify(prk, okm) is None + ckdf.verify(prk, okm) def test_invalid_verify(self, backend): prk = binascii.unhexlify( @@ -248,7 +251,7 @@ def test_unicode_typeerror(self, backend): ConcatKDFHMAC( hashes.SHA256(), 16, - salt="foo", + salt="foo", # type: ignore[arg-type] otherinfo=None, backend=backend, ) @@ -258,7 +261,7 @@ def test_unicode_typeerror(self, backend): hashes.SHA256(), 16, salt=None, - otherinfo="foo", + otherinfo="foo", # type: ignore[arg-type] backend=backend, ) @@ -267,21 +270,32 @@ def test_unicode_typeerror(self, backend): hashes.SHA256(), 16, salt=None, otherinfo=None, backend=backend ) - ckdf.derive("foo") + ckdf.derive("foo") # type: ignore[arg-type] with pytest.raises(TypeError): ckdf = ConcatKDFHMAC( hashes.SHA256(), 16, salt=None, otherinfo=None, backend=backend ) - ckdf.verify("foo", b"bar") + ckdf.verify("foo", b"bar") # type: ignore[arg-type] with pytest.raises(TypeError): ckdf = ConcatKDFHMAC( hashes.SHA256(), 16, salt=None, otherinfo=None, backend=backend ) - ckdf.verify(b"foo", "bar") + ckdf.verify(b"foo", "bar") # type: ignore[arg-type] + + def test_unsupported_hash_algorithm(self, backend): + # ConcatKDF requires a hash algorithm with an internal block size. + with pytest.raises(TypeError): + ConcatKDFHMAC( + hashes.SHA3_256(), + 16, + salt=None, + otherinfo=None, + backend=backend, + ) def test_invalid_backend(): diff --git a/tests/hazmat/primitives/test_hkdf.py b/tests/hazmat/primitives/test_hkdf.py index 640dd60a76f1..5ee6680b998e 100644 --- a/tests/hazmat/primitives/test_hkdf.py +++ b/tests/hazmat/primitives/test_hkdf.py @@ -64,31 +64,43 @@ def test_verify_invalid(self, backend): def test_unicode_typeerror(self, backend): with pytest.raises(TypeError): - HKDF(hashes.SHA256(), 16, salt="foo", info=None, backend=backend) + HKDF( + hashes.SHA256(), + 16, + salt="foo", # type: ignore[arg-type] + info=None, + backend=backend, + ) with pytest.raises(TypeError): - HKDF(hashes.SHA256(), 16, salt=None, info="foo", backend=backend) + HKDF( + hashes.SHA256(), + 16, + salt=None, + info="foo", # type: ignore[arg-type] + backend=backend, + ) with pytest.raises(TypeError): hkdf = HKDF( hashes.SHA256(), 16, salt=None, info=None, backend=backend ) - hkdf.derive("foo") + hkdf.derive("foo") # type: ignore[arg-type] with pytest.raises(TypeError): hkdf = HKDF( hashes.SHA256(), 16, salt=None, info=None, backend=backend ) - hkdf.verify("foo", b"bar") + hkdf.verify("foo", b"bar") # type: ignore[arg-type] with pytest.raises(TypeError): hkdf = HKDF( hashes.SHA256(), 16, salt=None, info=None, backend=backend ) - hkdf.verify(b"foo", "bar") + hkdf.verify(b"foo", "bar") # type: ignore[arg-type] def test_derive_short_output(self, backend): hkdf = HKDF(hashes.SHA256(), 4, salt=None, info=None, backend=backend) @@ -174,7 +186,7 @@ def test_verify(self, backend): info = binascii.unhexlify(b"f0f1f2f3f4f5f6f7f8f9") hkdf = HKDFExpand(hashes.SHA256(), 42, info, backend) - assert hkdf.verify(prk, binascii.unhexlify(okm)) is None + hkdf.verify(prk, binascii.unhexlify(okm)) def test_invalid_verify(self, backend): prk = binascii.unhexlify( @@ -201,7 +213,7 @@ def test_unicode_error(self, backend): hkdf = HKDFExpand(hashes.SHA256(), 42, info, backend) with pytest.raises(TypeError): - hkdf.derive("first") + hkdf.derive("first") # type: ignore[arg-type] def test_invalid_backend(): diff --git a/tests/hazmat/primitives/test_kbkdf.py b/tests/hazmat/primitives/test_kbkdf.py index b80d33f220da..2c94d18167bd 100644 --- a/tests/hazmat/primitives/test_kbkdf.py +++ b/tests/hazmat/primitives/test_kbkdf.py @@ -144,7 +144,7 @@ def test_r_type(self, backend): hashes.SHA1(), Mode.CounterMode, 32, - b"r", + b"r", # type: ignore[arg-type] 4, CounterLocation.BeforeFixed, b"label", @@ -160,7 +160,7 @@ def test_l_type(self, backend): Mode.CounterMode, 32, 4, - b"l", + b"l", # type: ignore[arg-type] CounterLocation.BeforeFixed, b"label", b"context", @@ -187,7 +187,7 @@ def test_unsupported_mode(self, backend): with pytest.raises(TypeError): KBKDFHMAC( hashes.SHA256(), - None, + None, # type: ignore[arg-type] 32, 4, 4, @@ -206,7 +206,7 @@ def test_unsupported_location(self, backend): 32, 4, 4, - None, + None, # type: ignore[arg-type] b"label", b"context", None, @@ -231,7 +231,7 @@ def test_unsupported_parameters(self, backend): def test_unsupported_hash(self, backend): with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_HASH): KBKDFHMAC( - object(), + object(), # type: ignore[arg-type] Mode.CounterMode, 32, 4, @@ -282,7 +282,7 @@ def test_unicode_error_label(self, backend): 4, 4, CounterLocation.BeforeFixed, - "label", + "label", # type: ignore[arg-type] b"context", None, backend=backend, @@ -298,7 +298,7 @@ def test_unicode_error_context(self, backend): 4, CounterLocation.BeforeFixed, b"label", - "context", + "context", # type: ignore[arg-type] None, backend=backend, ) @@ -317,7 +317,7 @@ def test_unicode_error_key_material(self, backend): None, backend=backend, ) - kdf.derive("material") + kdf.derive("material") # type: ignore[arg-type] def test_buffer_protocol(self, backend): kdf = KBKDFHMAC( diff --git a/tests/hazmat/primitives/test_pbkdf2hmac.py b/tests/hazmat/primitives/test_pbkdf2hmac.py index e8ee805edd32..8586debe4f1f 100644 --- a/tests/hazmat/primitives/test_pbkdf2hmac.py +++ b/tests/hazmat/primitives/test_pbkdf2hmac.py @@ -44,12 +44,18 @@ def test_invalid_key(self, backend): def test_unicode_error_with_salt(self, backend): with pytest.raises(TypeError): - PBKDF2HMAC(hashes.SHA1(), 20, "salt", 10, backend) + PBKDF2HMAC( + hashes.SHA1(), + 20, + "salt", # type: ignore[arg-type] + 10, + backend, + ) def test_unicode_error_with_key_material(self, backend): kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, backend) with pytest.raises(TypeError): - kdf.derive("unicode here") + kdf.derive("unicode here") # type: ignore[arg-type] def test_buffer_protocol(self, backend): kdf = PBKDF2HMAC(hashes.SHA1(), 10, b"salt", 10, backend) diff --git a/tests/hazmat/primitives/test_scrypt.py b/tests/hazmat/primitives/test_scrypt.py index 6d68769705af..f6bbd0bcf295 100644 --- a/tests/hazmat/primitives/test_scrypt.py +++ b/tests/hazmat/primitives/test_scrypt.py @@ -94,7 +94,7 @@ def test_salt_not_bytes(self, backend): with pytest.raises(TypeError): Scrypt( - salt, + salt, # type: ignore[arg-type] length, work_factor, block_size, @@ -140,7 +140,7 @@ def test_password_not_bytes(self, backend): ) with pytest.raises(TypeError): - scrypt.derive(password) + scrypt.derive(password) # type: ignore[arg-type] def test_buffer_protocol(self, backend): password = bytearray(b"password") @@ -180,7 +180,7 @@ def test_verify(self, backend, params): parallelization_factor, backend, ) - assert scrypt.verify(password, binascii.unhexlify(derived_key)) is None + scrypt.verify(password, binascii.unhexlify(derived_key)) def test_invalid_verify(self, backend): password = b"password" diff --git a/tests/hazmat/primitives/test_x963kdf.py b/tests/hazmat/primitives/test_x963kdf.py index a02ea11dd0a7..08c94db84645 100644 --- a/tests/hazmat/primitives/test_x963kdf.py +++ b/tests/hazmat/primitives/test_x963kdf.py @@ -71,7 +71,7 @@ def test_verify(self, backend): xkdf = X963KDF(hashes.SHA256(), 128, sharedinfo, backend) - assert xkdf.verify(key, derivedkey) is None + xkdf.verify(key, derivedkey) def test_invalid_verify(self, backend): key = binascii.unhexlify( @@ -85,28 +85,33 @@ def test_invalid_verify(self, backend): def test_unicode_typeerror(self, backend): with pytest.raises(TypeError): - X963KDF(hashes.SHA256(), 16, sharedinfo="foo", backend=backend) + X963KDF( + hashes.SHA256(), + 16, + sharedinfo="foo", # type: ignore[arg-type] + backend=backend, + ) with pytest.raises(TypeError): xkdf = X963KDF( hashes.SHA256(), 16, sharedinfo=None, backend=backend ) - xkdf.derive("foo") + xkdf.derive("foo") # type: ignore[arg-type] with pytest.raises(TypeError): xkdf = X963KDF( hashes.SHA256(), 16, sharedinfo=None, backend=backend ) - xkdf.verify("foo", b"bar") + xkdf.verify("foo", b"bar") # type: ignore[arg-type] with pytest.raises(TypeError): xkdf = X963KDF( hashes.SHA256(), 16, sharedinfo=None, backend=backend ) - xkdf.verify(b"foo", "bar") + xkdf.verify(b"foo", "bar") # type: ignore[arg-type] def test_invalid_backend(): From ba9beaa8cd2b270b6c5bcfa9bcef48e94aec76cf Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 1 Feb 2021 16:08:48 -0600 Subject: [PATCH 0091/2380] rsa type hinting (#5733) * rsa type hinting * remove unused import * missed return type * type fixes * ignores no longer required * black gets me every time * Update src/cryptography/hazmat/backends/openssl/rsa.py Co-authored-by: Alex Gaynor Co-authored-by: Alex Gaynor --- .../hazmat/backends/openssl/rsa.py | 128 +++++++++++++----- .../hazmat/primitives/asymmetric/padding.py | 10 +- .../hazmat/primitives/asymmetric/rsa.py | 112 +++++++++++---- tests/hazmat/primitives/test_rsa.py | 48 +++++-- tests/wycheproof/test_rsa.py | 1 + tests/x509/test_x509.py | 2 +- 6 files changed, 218 insertions(+), 83 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py index 03dab9883b8e..74375ca0e983 100644 --- a/src/cryptography/hazmat/backends/openssl/rsa.py +++ b/src/cryptography/hazmat/backends/openssl/rsa.py @@ -3,6 +3,8 @@ # for complete details. +import typing + from cryptography import utils from cryptography.exceptions import ( InvalidSignature, @@ -14,11 +16,11 @@ _check_not_prehashed, _warn_sign_verify_deprecated, ) -from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ( AsymmetricSignatureContext, AsymmetricVerificationContext, - rsa, + utils as asym_utils, ) from cryptography.hazmat.primitives.asymmetric.padding import ( AsymmetricPadding, @@ -30,11 +32,17 @@ ) from cryptography.hazmat.primitives.asymmetric.rsa import ( RSAPrivateKey, + RSAPrivateNumbers, RSAPublicKey, + RSAPublicNumbers, ) -def _get_rsa_pss_salt_length(pss, key, hash_algorithm): +def _get_rsa_pss_salt_length( + pss: PSS, + key: typing.Union[RSAPrivateKey, RSAPublicKey], + hash_algorithm: hashes.HashAlgorithm, +) -> int: salt = pss._salt_length if salt is MGF1.MAX_LENGTH or salt is PSS.MAX_LENGTH: @@ -43,7 +51,12 @@ def _get_rsa_pss_salt_length(pss, key, hash_algorithm): return salt -def _enc_dec_rsa(backend, key, data, padding): +def _enc_dec_rsa( + backend, + key: typing.Union["_RSAPrivateKey", "_RSAPublicKey"], + data: bytes, + padding: AsymmetricPadding, +) -> bytes: if not isinstance(padding, AsymmetricPadding): raise TypeError("Padding must be an instance of AsymmetricPadding.") @@ -74,7 +87,13 @@ def _enc_dec_rsa(backend, key, data, padding): return _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding) -def _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding): +def _enc_dec_rsa_pkey_ctx( + backend, + key: typing.Union["_RSAPrivateKey", "_RSAPublicKey"], + data: bytes, + padding_enum: int, + padding: AsymmetricPadding, +) -> bytes: if isinstance(key, _RSAPublicKey): init = backend._lib.EVP_PKEY_encrypt_init crypt = backend._lib.EVP_PKEY_encrypt @@ -294,9 +313,14 @@ def _rsa_sig_recover(backend, padding, algorithm, public_key, signature): return resbuf -@utils.register_interface(AsymmetricSignatureContext) -class _RSASignatureContext(object): - def __init__(self, backend, private_key, padding, algorithm): +class _RSASignatureContext(AsymmetricSignatureContext): + def __init__( + self, + backend, + private_key: RSAPrivateKey, + padding: AsymmetricPadding, + algorithm: hashes.HashAlgorithm, + ): self._backend = backend self._private_key = private_key @@ -308,10 +332,10 @@ def __init__(self, backend, private_key, padding, algorithm): self._algorithm = algorithm self._hash_ctx = hashes.Hash(self._algorithm, self._backend) - def update(self, data): + def update(self, data: bytes) -> None: self._hash_ctx.update(data) - def finalize(self): + def finalize(self) -> bytes: return _rsa_sig_sign( self._backend, self._padding, @@ -321,9 +345,15 @@ def finalize(self): ) -@utils.register_interface(AsymmetricVerificationContext) -class _RSAVerificationContext(object): - def __init__(self, backend, public_key, signature, padding, algorithm): +class _RSAVerificationContext(AsymmetricVerificationContext): + def __init__( + self, + backend, + public_key: RSAPublicKey, + signature: bytes, + padding: AsymmetricPadding, + algorithm: hashes.HashAlgorithm, + ): self._backend = backend self._public_key = public_key self._signature = signature @@ -337,10 +367,10 @@ def __init__(self, backend, public_key, signature, padding, algorithm): self._algorithm = algorithm self._hash_ctx = hashes.Hash(self._algorithm, self._backend) - def update(self, data): + def update(self, data: bytes) -> None: self._hash_ctx.update(data) - def verify(self): + def verify(self) -> None: return _rsa_sig_verify( self._backend, self._padding, @@ -351,8 +381,7 @@ def verify(self): ) -@utils.register_interface(RSAPrivateKey) -class _RSAPrivateKey(object): +class _RSAPrivateKey(RSAPrivateKey): def __init__(self, backend, rsa_cdata, evp_pkey): res = backend._lib.RSA_check_key(rsa_cdata) if res != 1: @@ -380,26 +409,28 @@ def __init__(self, backend, rsa_cdata, evp_pkey): key_size = utils.read_only_property("_key_size") - def signer(self, padding, algorithm): + def signer( + self, padding: AsymmetricPadding, algorithm: hashes.HashAlgorithm + ) -> AsymmetricSignatureContext: _warn_sign_verify_deprecated() _check_not_prehashed(algorithm) return _RSASignatureContext(self._backend, self, padding, algorithm) - def decrypt(self, ciphertext, padding): + def decrypt(self, ciphertext: bytes, padding: AsymmetricPadding) -> bytes: key_size_bytes = (self.key_size + 7) // 8 if key_size_bytes != len(ciphertext): raise ValueError("Ciphertext length must be equal to key size.") return _enc_dec_rsa(self._backend, self, ciphertext, padding) - def public_key(self): + def public_key(self) -> RSAPublicKey: ctx = self._backend._lib.RSAPublicKey_dup(self._rsa_cdata) self._backend.openssl_assert(ctx != self._backend._ffi.NULL) ctx = self._backend._ffi.gc(ctx, self._backend._lib.RSA_free) evp_pkey = self._backend._rsa_cdata_to_evp_pkey(ctx) return _RSAPublicKey(self._backend, ctx, evp_pkey) - def private_numbers(self): + def private_numbers(self) -> RSAPrivateNumbers: n = self._backend._ffi.new("BIGNUM **") e = self._backend._ffi.new("BIGNUM **") d = self._backend._ffi.new("BIGNUM **") @@ -421,20 +452,25 @@ def private_numbers(self): self._backend.openssl_assert(dmp1[0] != self._backend._ffi.NULL) self._backend.openssl_assert(dmq1[0] != self._backend._ffi.NULL) self._backend.openssl_assert(iqmp[0] != self._backend._ffi.NULL) - return rsa.RSAPrivateNumbers( + return RSAPrivateNumbers( p=self._backend._bn_to_int(p[0]), q=self._backend._bn_to_int(q[0]), d=self._backend._bn_to_int(d[0]), dmp1=self._backend._bn_to_int(dmp1[0]), dmq1=self._backend._bn_to_int(dmq1[0]), iqmp=self._backend._bn_to_int(iqmp[0]), - public_numbers=rsa.RSAPublicNumbers( + public_numbers=RSAPublicNumbers( e=self._backend._bn_to_int(e[0]), n=self._backend._bn_to_int(n[0]), ), ) - def private_bytes(self, encoding, format, encryption_algorithm): + def private_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PrivateFormat, + encryption_algorithm: serialization.KeySerializationEncryption, + ) -> bytes: return self._backend._private_key_bytes( encoding, format, @@ -444,15 +480,19 @@ def private_bytes(self, encoding, format, encryption_algorithm): self._rsa_cdata, ) - def sign(self, data, padding, algorithm): + def sign( + self, + data: bytes, + padding: AsymmetricPadding, + algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], + ) -> bytes: data, algorithm = _calculate_digest_and_algorithm( self._backend, data, algorithm ) return _rsa_sig_sign(self._backend, padding, algorithm, self, data) -@utils.register_interface(RSAPublicKey) -class _RSAPublicKey(object): +class _RSAPublicKey(RSAPublicKey): def __init__(self, backend, rsa_cdata, evp_pkey): self._backend = backend self._rsa_cdata = rsa_cdata @@ -470,7 +510,12 @@ def __init__(self, backend, rsa_cdata, evp_pkey): key_size = utils.read_only_property("_key_size") - def verifier(self, signature, padding, algorithm): + def verifier( + self, + signature: bytes, + padding: AsymmetricPadding, + algorithm: hashes.HashAlgorithm, + ) -> AsymmetricVerificationContext: _warn_sign_verify_deprecated() utils._check_bytes("signature", signature) @@ -479,10 +524,10 @@ def verifier(self, signature, padding, algorithm): self._backend, self, signature, padding, algorithm ) - def encrypt(self, plaintext, padding): + def encrypt(self, plaintext: bytes, padding: AsymmetricPadding) -> bytes: return _enc_dec_rsa(self._backend, self, plaintext, padding) - def public_numbers(self): + def public_numbers(self) -> RSAPublicNumbers: n = self._backend._ffi.new("BIGNUM **") e = self._backend._ffi.new("BIGNUM **") self._backend._lib.RSA_get0_key( @@ -490,17 +535,27 @@ def public_numbers(self): ) self._backend.openssl_assert(n[0] != self._backend._ffi.NULL) self._backend.openssl_assert(e[0] != self._backend._ffi.NULL) - return rsa.RSAPublicNumbers( + return RSAPublicNumbers( e=self._backend._bn_to_int(e[0]), n=self._backend._bn_to_int(n[0]), ) - def public_bytes(self, encoding, format): + def public_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PublicFormat, + ) -> bytes: return self._backend._public_key_bytes( encoding, format, self, self._evp_pkey, self._rsa_cdata ) - def verify(self, signature, data, padding, algorithm): + def verify( + self, + signature: bytes, + data: bytes, + padding: AsymmetricPadding, + algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], + ) -> None: data, algorithm = _calculate_digest_and_algorithm( self._backend, data, algorithm ) @@ -508,7 +563,12 @@ def verify(self, signature, data, padding, algorithm): self._backend, padding, algorithm, self, signature, data ) - def recover_data_from_signature(self, signature, padding, algorithm): + def recover_data_from_signature( + self, + signature: bytes, + padding: AsymmetricPadding, + algorithm: typing.Optional[hashes.HashAlgorithm], + ) -> bytes: _check_not_prehashed(algorithm) return _rsa_sig_recover( self._backend, padding, algorithm, self, signature diff --git a/src/cryptography/hazmat/primitives/asymmetric/padding.py b/src/cryptography/hazmat/primitives/asymmetric/padding.py index 8515614728af..289c75f8ec33 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/padding.py +++ b/src/cryptography/hazmat/primitives/asymmetric/padding.py @@ -5,7 +5,6 @@ import abc -from cryptography import utils from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import rsa @@ -18,13 +17,11 @@ def name(self): """ -@utils.register_interface(AsymmetricPadding) -class PKCS1v15(object): +class PKCS1v15(AsymmetricPadding): name = "EMSA-PKCS1-v1_5" -@utils.register_interface(AsymmetricPadding) -class PSS(object): +class PSS(AsymmetricPadding): MAX_LENGTH = object() name = "EMSA-PSS" @@ -43,8 +40,7 @@ def __init__(self, mgf, salt_length): self._salt_length = salt_length -@utils.register_interface(AsymmetricPadding) -class OAEP(object): +class OAEP(AsymmetricPadding): name = "EME-OAEP" def __init__(self, mgf, algorithm, label): diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py index 7214f46f897c..c4aeeeaafcfd 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py @@ -4,53 +4,73 @@ import abc +import typing from math import gcd from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.backends.interfaces import RSABackend +from cryptography.hazmat.primitives import _serialization, hashes +from cryptography.hazmat.primitives.asymmetric import ( + AsymmetricSignatureContext, + AsymmetricVerificationContext, + utils as asym_utils, +) +from cryptography.hazmat.primitives.asymmetric.padding import AsymmetricPadding class RSAPrivateKey(metaclass=abc.ABCMeta): @abc.abstractmethod - def signer(self, padding, algorithm): + def signer( + self, padding: AsymmetricPadding, algorithm: hashes.HashAlgorithm + ) -> AsymmetricSignatureContext: """ Returns an AsymmetricSignatureContext used for signing data. """ @abc.abstractmethod - def decrypt(self, ciphertext, padding): + def decrypt(self, ciphertext: bytes, padding: AsymmetricPadding) -> bytes: """ Decrypts the provided ciphertext. """ @abc.abstractproperty - def key_size(self): + def key_size(self) -> int: """ The bit length of the public modulus. """ @abc.abstractmethod - def public_key(self): + def public_key(self) -> "RSAPublicKey": """ The RSAPublicKey associated with this private key. """ @abc.abstractmethod - def sign(self, data, padding, algorithm): + def sign( + self, + data: bytes, + padding: AsymmetricPadding, + algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], + ) -> bytes: """ Signs the data. """ @abc.abstractmethod - def private_numbers(self): + def private_numbers(self) -> "RSAPrivateNumbers": """ Returns an RSAPrivateNumbers. """ @abc.abstractmethod - def private_bytes(self, encoding, format, encryption_algorithm): + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: """ Returns the key serialized as bytes. """ @@ -61,43 +81,63 @@ def private_bytes(self, encoding, format, encryption_algorithm): class RSAPublicKey(metaclass=abc.ABCMeta): @abc.abstractmethod - def verifier(self, signature, padding, algorithm): + def verifier( + self, + signature: bytes, + padding: AsymmetricPadding, + algorithm: hashes.HashAlgorithm, + ) -> AsymmetricVerificationContext: """ Returns an AsymmetricVerificationContext used for verifying signatures. """ @abc.abstractmethod - def encrypt(self, plaintext, padding): + def encrypt(self, plaintext: bytes, padding: AsymmetricPadding) -> bytes: """ Encrypts the given plaintext. """ @abc.abstractproperty - def key_size(self): + def key_size(self) -> int: """ The bit length of the public modulus. """ @abc.abstractmethod - def public_numbers(self): + def public_numbers(self) -> "RSAPublicNumbers": """ Returns an RSAPublicNumbers """ @abc.abstractmethod - def public_bytes(self, encoding, format): + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: """ Returns the key serialized as bytes. """ @abc.abstractmethod - def verify(self, signature, data, padding, algorithm): + def verify( + self, + signature: bytes, + data: bytes, + padding: AsymmetricPadding, + algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], + ) -> None: """ Verifies the signature of the data. """ @abc.abstractmethod - def recover_data_from_signature(self, signature, padding, algorithm): + def recover_data_from_signature( + self, + signature: bytes, + padding: AsymmetricPadding, + algorithm: typing.Optional[hashes.HashAlgorithm], + ) -> bytes: """ Recovers the original data from the signature. """ @@ -106,7 +146,9 @@ def recover_data_from_signature(self, signature, padding, algorithm): RSAPublicKeyWithSerialization = RSAPublicKey -def generate_private_key(public_exponent, key_size, backend=None): +def generate_private_key( + public_exponent: int, key_size: int, backend=None +) -> RSAPrivateKey: backend = _get_backend(backend) if not isinstance(backend, RSABackend): raise UnsupportedAlgorithm( @@ -118,7 +160,7 @@ def generate_private_key(public_exponent, key_size, backend=None): return backend.generate_rsa_private_key(public_exponent, key_size) -def _verify_rsa_parameters(public_exponent, key_size): +def _verify_rsa_parameters(public_exponent: int, key_size: int): if public_exponent not in (3, 65537): raise ValueError( "public_exponent must be either 3 (for legacy compatibility) or " @@ -130,7 +172,14 @@ def _verify_rsa_parameters(public_exponent, key_size): def _check_private_key_components( - p, q, private_exponent, dmp1, dmq1, iqmp, public_exponent, modulus + p: int, + q: int, + private_exponent: int, + dmp1: int, + dmq1: int, + iqmp: int, + public_exponent: int, + modulus: int, ): if modulus < 3: raise ValueError("modulus must be >= 3.") @@ -169,7 +218,7 @@ def _check_private_key_components( raise ValueError("p*q must equal modulus.") -def _check_public_key_components(e, n): +def _check_public_key_components(e: int, n: int): if n < 3: raise ValueError("n must be >= 3.") @@ -180,7 +229,7 @@ def _check_public_key_components(e, n): raise ValueError("e must be odd.") -def _modinv(e, m): +def _modinv(e: int, m: int): """ Modular Multiplicative Inverse. Returns x such that: (x*e) mod m == 1 """ @@ -193,14 +242,14 @@ def _modinv(e, m): return x1 % m -def rsa_crt_iqmp(p, q): +def rsa_crt_iqmp(p: int, q: int): """ Compute the CRT (q ** -1) % p value from RSA primes p and q. """ return _modinv(q, p) -def rsa_crt_dmp1(private_exponent, p): +def rsa_crt_dmp1(private_exponent: int, p: int): """ Compute the CRT private_exponent % (p - 1) value from the RSA private_exponent (d) and p. @@ -208,7 +257,7 @@ def rsa_crt_dmp1(private_exponent, p): return private_exponent % (p - 1) -def rsa_crt_dmq1(private_exponent, q): +def rsa_crt_dmq1(private_exponent: int, q: int): """ Compute the CRT private_exponent % (q - 1) value from the RSA private_exponent (d) and q. @@ -222,7 +271,7 @@ def rsa_crt_dmq1(private_exponent, q): _MAX_RECOVERY_ATTEMPTS = 1000 -def rsa_recover_prime_factors(n, e, d): +def rsa_recover_prime_factors(n: int, e: int, d: int): """ Compute factors p and q from the private exponent d. We assume that n has no more than two factors. This function is adapted from code in PyCrypto. @@ -266,7 +315,16 @@ def rsa_recover_prime_factors(n, e, d): class RSAPrivateNumbers(object): - def __init__(self, p, q, d, dmp1, dmq1, iqmp, public_numbers): + def __init__( + self, + p: int, + q: int, + d: int, + dmp1: int, + dmq1: int, + iqmp: int, + public_numbers: "RSAPublicNumbers", + ): if ( not isinstance(p, int) or not isinstance(q, int) @@ -302,7 +360,7 @@ def __init__(self, p, q, d, dmp1, dmq1, iqmp, public_numbers): iqmp = utils.read_only_property("_iqmp") public_numbers = utils.read_only_property("_public_numbers") - def private_key(self, backend=None): + def private_key(self, backend=None) -> RSAPrivateKey: backend = _get_backend(backend) return backend.load_rsa_private_numbers(self) @@ -338,7 +396,7 @@ def __hash__(self): class RSAPublicNumbers(object): - def __init__(self, e, n): + def __init__(self, e: int, n: int): if not isinstance(e, int) or not isinstance(n, int): raise TypeError("RSAPublicNumbers arguments must be integers.") @@ -348,7 +406,7 @@ def __init__(self, e, n): e = utils.read_only_property("_e") n = utils.read_only_property("_n") - def public_key(self, backend=None): + def public_key(self, backend=None) -> RSAPublicKey: backend = _get_backend(backend) return backend.load_rsa_public_numbers(self) diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 069fb0977bb8..2ab0f2625565 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -591,7 +591,11 @@ def test_unsupported_padding(self, backend): def test_padding_incorrect_type(self, backend): private_key = RSA_KEY_512.private_key(backend) with pytest.raises(TypeError): - private_key.sign(b"msg", "notpadding", hashes.SHA1()) + private_key.sign( + b"msg", + "notpadding", # type: ignore[arg-type] + hashes.SHA1(), + ) @pytest.mark.supported( only_if=lambda backend: backend.rsa_padding_supported( @@ -708,7 +712,8 @@ def test_prehashed_unsupported_in_signer_ctx(self, backend): CryptographyDeprecationWarning ): private_key.signer( - padding.PKCS1v15(), asym_utils.Prehashed(hashes.SHA1()) + padding.PKCS1v15(), + asym_utils.Prehashed(hashes.SHA1()), # type: ignore[arg-type] ) @pytest.mark.supported( @@ -725,7 +730,7 @@ def test_prehashed_unsupported_in_verifier_ctx(self, backend): public_key.verifier( b"0" * 64, padding.PKCS1v15(), - asym_utils.Prehashed(hashes.SHA1()), + asym_utils.Prehashed(hashes.SHA1()), # type: ignore[arg-type] ) def test_prehashed_unsupported_in_signature_recover(self, backend): @@ -737,7 +742,9 @@ def test_prehashed_unsupported_in_signature_recover(self, backend): prehashed_alg = asym_utils.Prehashed(hashes.SHA1()) with pytest.raises(TypeError): public_key.recover_data_from_signature( - signature, padding.PKCS1v15(), prehashed_alg + signature, + padding.PKCS1v15(), + prehashed_alg, # type: ignore[arg-type] ) def test_corrupted_private_key(self, backend): @@ -1018,7 +1025,7 @@ def test_invalid_pss_signature_recover(self, backend): # Hash algorithm can not be absent for PSS padding with pytest.raises(TypeError): public_key.recover_data_from_signature( - signature, pss_padding, None + signature, pss_padding, None # type: ignore[arg-type] ) # Signature data recovery not supported with PSS @@ -1078,7 +1085,12 @@ def test_padding_incorrect_type(self, backend): private_key = RSA_KEY_512.private_key(backend) public_key = private_key.public_key() with pytest.raises(TypeError): - public_key.verify(b"sig", b"msg", "notpadding", hashes.SHA1()) + public_key.verify( + b"sig", + b"msg", + "notpadding", # type: ignore[arg-type] + hashes.SHA1(), + ) @pytest.mark.supported( only_if=lambda backend: backend.rsa_padding_supported( @@ -1900,7 +1912,9 @@ def test_unsupported_padding(self, backend): with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING): public_key.encrypt(b"somedata", DummyAsymmetricPadding()) with pytest.raises(TypeError): - public_key.encrypt(b"somedata", padding=object()) + public_key.encrypt( + b"somedata", padding=object() # type: ignore[arg-type] + ) def test_unsupported_oaep_mgf(self, backend): private_key = RSA_KEY_512.private_key(backend) @@ -1955,10 +1969,10 @@ def test_rsa_public_numbers_create_key(self, backend): def test_public_numbers_invalid_types(self): with pytest.raises(TypeError): - rsa.RSAPublicNumbers(e=None, n=15) + rsa.RSAPublicNumbers(e=None, n=15) # type: ignore[arg-type] with pytest.raises(TypeError): - rsa.RSAPublicNumbers(e=1, n=None) + rsa.RSAPublicNumbers(e=1, n=None) # type: ignore[arg-type] @pytest.mark.parametrize( ("p", "q", "d", "dmp1", "dmq1", "iqmp", "public_numbers"), @@ -2295,7 +2309,7 @@ def test_private_bytes_invalid_encoding(self, backend): key = RSA_KEY_2048.private_key(backend) with pytest.raises(TypeError): key.private_bytes( - "notencoding", + "notencoding", # type: ignore[arg-type] serialization.PrivateFormat.PKCS8, serialization.NoEncryption(), ) @@ -2305,7 +2319,7 @@ def test_private_bytes_invalid_format(self, backend): with pytest.raises(TypeError): key.private_bytes( serialization.Encoding.PEM, - "invalidformat", + "invalidformat", # type: ignore[arg-type] serialization.NoEncryption(), ) @@ -2315,7 +2329,7 @@ def test_private_bytes_invalid_encryption_algorithm(self, backend): key.private_bytes( serialization.Encoding.PEM, serialization.PrivateFormat.TraditionalOpenSSL, - "notanencalg", + "notanencalg", # type: ignore[arg-type] ) def test_private_bytes_unsupported_encryption_type(self, backend): @@ -2414,12 +2428,18 @@ def test_public_bytes_openssh(self, backend): def test_public_bytes_invalid_encoding(self, backend): key = RSA_KEY_2048.private_key(backend).public_key() with pytest.raises(TypeError): - key.public_bytes("notencoding", serialization.PublicFormat.PKCS1) + key.public_bytes( + "notencoding", # type: ignore[arg-type] + serialization.PublicFormat.PKCS1, + ) def test_public_bytes_invalid_format(self, backend): key = RSA_KEY_2048.private_key(backend).public_key() with pytest.raises(TypeError): - key.public_bytes(serialization.Encoding.PEM, "invalidformat") + key.public_bytes( + serialization.Encoding.PEM, + "invalidformat", # type: ignore[arg-type] + ) @pytest.mark.parametrize( ("encoding", "fmt"), diff --git a/tests/wycheproof/test_rsa.py b/tests/wycheproof/test_rsa.py index 4c1f1fff2cf3..440b09291f8b 100644 --- a/tests/wycheproof/test_rsa.py +++ b/tests/wycheproof/test_rsa.py @@ -103,6 +103,7 @@ def test_rsa_pkcs1v15_signature_generation(backend, wycheproof): ) assert isinstance(key, rsa.RSAPrivateKey) digest = _DIGESTS[wycheproof.testgroup["sha"]] + assert digest is not None sig = key.sign( binascii.unhexlify(wycheproof.testcase["msg"]), diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index fa16333ef499..39f7bb951d41 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -2158,7 +2158,7 @@ def test_public_key_must_be_public_key(self, backend): builder = x509.CertificateBuilder() with pytest.raises(TypeError): - builder.public_key(private_key) + builder.public_key(private_key) # type: ignore[arg-type] @pytest.mark.requires_backend_interface(interface=RSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) From e6352d5ef2798f9cb8ec2fd330605606117b515b Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 1 Feb 2021 20:31:42 -0500 Subject: [PATCH 0092/2380] Added typing for a bunch of methods (#5737) --- src/cryptography/hazmat/_der.py | 21 +++++++++++-------- src/cryptography/hazmat/_oid.py | 2 +- .../hazmat/primitives/constant_time.py | 2 +- src/cryptography/hazmat/primitives/padding.py | 8 +++---- .../hazmat/primitives/twofactor/hotp.py | 8 +++---- .../hazmat/primitives/twofactor/totp.py | 6 +++--- .../hazmat/primitives/twofactor/utils.py | 2 +- src/cryptography/utils.py | 2 +- .../hazmat/primitives/twofactor/test_hotp.py | 3 +-- .../hazmat/primitives/twofactor/test_totp.py | 9 +++----- tests/hazmat/test_der.py | 3 ++- 11 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/cryptography/hazmat/_der.py b/src/cryptography/hazmat/_der.py index e00e97e9f5a5..fa5940b23672 100644 --- a/src/cryptography/hazmat/_der.py +++ b/src/cryptography/hazmat/_der.py @@ -2,6 +2,7 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. +import typing from cryptography.utils import int_to_bytes @@ -47,21 +48,21 @@ def check_empty(self): if not self.is_empty(): raise ValueError("Invalid DER input: trailing data") - def read_byte(self): + def read_byte(self) -> int: if len(self.data) < 1: raise ValueError("Invalid DER input: insufficient data") ret = self.data[0] self.data = self.data[1:] return ret - def read_bytes(self, n): + def read_bytes(self, n) -> memoryview: if len(self.data) < n: raise ValueError("Invalid DER input: insufficient data") ret = self.data[:n] self.data = self.data[n:] return ret - def read_any_element(self): + def read_any_element(self) -> typing.Tuple[int, "DERReader"]: tag = self.read_byte() # Tag numbers 31 or higher are stored in multiple bytes. No supported # ASN.1 types use such tags, so reject these. @@ -97,22 +98,24 @@ def read_any_element(self): body = self.read_bytes(length) return tag, DERReader(body) - def read_element(self, expected_tag): + def read_element(self, expected_tag: int) -> "DERReader": tag, body = self.read_any_element() if tag != expected_tag: raise ValueError("Invalid DER input: unexpected tag") return body - def read_single_element(self, expected_tag): + def read_single_element(self, expected_tag: int) -> "DERReader": with self: return self.read_element(expected_tag) - def read_optional_element(self, expected_tag): + def read_optional_element( + self, expected_tag: int + ) -> typing.Optional["DERReader"]: if len(self.data) > 0 and self.data[0] == expected_tag: return self.read_element(expected_tag) return None - def as_integer(self): + def as_integer(self) -> int: if len(self.data) == 0: raise ValueError("Invalid DER input: empty integer contents") first = self.data[0] @@ -129,7 +132,7 @@ def as_integer(self): return int.from_bytes(self.data, "big") -def encode_der_integer(x): +def encode_der_integer(x: int) -> bytes: if not isinstance(x, int): raise ValueError("Value must be an integer") if x < 0: @@ -138,7 +141,7 @@ def encode_der_integer(x): return int_to_bytes(x, n) -def encode_der(tag, *children): +def encode_der(tag: int, *children: bytes) -> bytes: length = 0 for child in children: length += len(child) diff --git a/src/cryptography/hazmat/_oid.py b/src/cryptography/hazmat/_oid.py index baf2d535c904..27eeb7d7d7ff 100644 --- a/src/cryptography/hazmat/_oid.py +++ b/src/cryptography/hazmat/_oid.py @@ -7,7 +7,7 @@ class ObjectIdentifier(object): - def __init__(self, dotted_string): + def __init__(self, dotted_string: str): self._dotted_string = dotted_string nodes = self._dotted_string.split(".") diff --git a/src/cryptography/hazmat/primitives/constant_time.py b/src/cryptography/hazmat/primitives/constant_time.py index 9a773f86d58a..a02fa9c45345 100644 --- a/src/cryptography/hazmat/primitives/constant_time.py +++ b/src/cryptography/hazmat/primitives/constant_time.py @@ -6,7 +6,7 @@ import hmac -def bytes_eq(a: bytes, b: bytes): +def bytes_eq(a: bytes, b: bytes) -> bool: if not isinstance(a, bytes) or not isinstance(b, bytes): raise TypeError("a and b must be bytes.") diff --git a/src/cryptography/hazmat/primitives/padding.py b/src/cryptography/hazmat/primitives/padding.py index afed91341c0a..e6f46eb4fa0b 100644 --- a/src/cryptography/hazmat/primitives/padding.py +++ b/src/cryptography/hazmat/primitives/padding.py @@ -35,7 +35,7 @@ def _byte_padding_check(block_size: int) -> None: def _byte_padding_update( buffer_: typing.Optional[bytes], data: bytes, block_size: int -): +) -> typing.Tuple[bytes, bytes]: if buffer_ is None: raise AlreadyFinalized("Context was already finalized.") @@ -55,7 +55,7 @@ def _byte_padding_pad( buffer_: typing.Optional[bytes], block_size: int, paddingfn: typing.Callable[[int], bytes], -): +) -> bytes: if buffer_ is None: raise AlreadyFinalized("Context was already finalized.") @@ -65,7 +65,7 @@ def _byte_padding_pad( def _byte_unpadding_update( buffer_: typing.Optional[bytes], data: bytes, block_size: int -): +) -> typing.Tuple[bytes, bytes]: if buffer_ is None: raise AlreadyFinalized("Context was already finalized.") @@ -85,7 +85,7 @@ def _byte_unpadding_check( buffer_: typing.Optional[bytes], block_size: int, checkfn: typing.Callable[[bytes, int], int], -): +) -> bytes: if buffer_ is None: raise AlreadyFinalized("Context was already finalized.") diff --git a/src/cryptography/hazmat/primitives/twofactor/hotp.py b/src/cryptography/hazmat/primitives/twofactor/hotp.py index ae6769ac7664..01da4707b421 100644 --- a/src/cryptography/hazmat/primitives/twofactor/hotp.py +++ b/src/cryptography/hazmat/primitives/twofactor/hotp.py @@ -51,16 +51,16 @@ def __init__( self._algorithm = algorithm self._backend = backend - def generate(self, counter: int): + def generate(self, counter: int) -> bytes: truncated_value = self._dynamic_truncate(counter) hotp = truncated_value % (10 ** self._length) return "{0:0{1}}".format(hotp, self._length).encode() - def verify(self, hotp: bytes, counter: int): + def verify(self, hotp: bytes, counter: int) -> None: if not constant_time.bytes_eq(self.generate(counter), hotp): raise InvalidToken("Supplied HOTP value does not match.") - def _dynamic_truncate(self, counter: int): + def _dynamic_truncate(self, counter: int) -> int: ctx = hmac.HMAC(self._key, self._algorithm, self._backend) ctx.update(struct.pack(">Q", counter)) hmac_value = ctx.finalize() @@ -71,7 +71,7 @@ def _dynamic_truncate(self, counter: int): def get_provisioning_uri( self, account_name: str, counter: int, issuer: typing.Optional[str] - ): + ) -> str: return _generate_uri( self, "hotp", account_name, issuer, [("counter", int(counter))] ) diff --git a/src/cryptography/hazmat/primitives/twofactor/totp.py b/src/cryptography/hazmat/primitives/twofactor/totp.py index 245295103181..727891180489 100644 --- a/src/cryptography/hazmat/primitives/twofactor/totp.py +++ b/src/cryptography/hazmat/primitives/twofactor/totp.py @@ -36,17 +36,17 @@ def __init__( self._time_step = time_step self._hotp = HOTP(key, length, algorithm, backend, enforce_key_length) - def generate(self, time: typing.Union[int, float]): + def generate(self, time: typing.Union[int, float]) -> bytes: counter = int(time / self._time_step) return self._hotp.generate(counter) - def verify(self, totp: bytes, time: int): + def verify(self, totp: bytes, time: int) -> None: if not constant_time.bytes_eq(self.generate(time), totp): raise InvalidToken("Supplied TOTP value does not match.") def get_provisioning_uri( self, account_name: str, issuer: typing.Optional[str] - ): + ) -> str: return _generate_uri( self._hotp, "totp", diff --git a/src/cryptography/hazmat/primitives/twofactor/utils.py b/src/cryptography/hazmat/primitives/twofactor/utils.py index 60b5e928eaec..fcf40c8837cf 100644 --- a/src/cryptography/hazmat/primitives/twofactor/utils.py +++ b/src/cryptography/hazmat/primitives/twofactor/utils.py @@ -14,7 +14,7 @@ def _generate_uri( account_name: str, issuer: typing.Optional[str], extra_parameters, -): +) -> str: parameters = [ ("digits", hotp._length), ("secret", base64.b32encode(hotp._key)), diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index e6ea8d6e08a7..9bf31faadbec 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -59,7 +59,7 @@ def register_decorator(klass): return register_decorator -def int_to_bytes(integer: int, length: typing.Optional[int] = None): +def int_to_bytes(integer: int, length: typing.Optional[int] = None) -> bytes: return integer.to_bytes( length or (integer.bit_length() + 7) // 8 or 1, "big" ) diff --git a/tests/hazmat/primitives/twofactor/test_hotp.py b/tests/hazmat/primitives/twofactor/test_hotp.py index 04013b166fe4..66c9b4ba0e43 100644 --- a/tests/hazmat/primitives/twofactor/test_hotp.py +++ b/tests/hazmat/primitives/twofactor/test_hotp.py @@ -78,8 +78,7 @@ def test_verify(self, backend, params): hotp_value = params["hotp"] hotp = HOTP(secret, 6, SHA1(), backend) - - assert hotp.verify(hotp_value, counter) is None + hotp.verify(hotp_value, counter) def test_invalid_verify(self, backend): secret = b"12345678901234567890" diff --git a/tests/hazmat/primitives/twofactor/test_totp.py b/tests/hazmat/primitives/twofactor/test_totp.py index f590896801ea..87c1e6144e9b 100644 --- a/tests/hazmat/primitives/twofactor/test_totp.py +++ b/tests/hazmat/primitives/twofactor/test_totp.py @@ -80,8 +80,7 @@ def test_verify_sha1(self, backend, params): totp_value = params["totp"] totp = TOTP(secret, 8, hashes.SHA1(), 30, backend) - - assert totp.verify(totp_value, time) is None + totp.verify(totp_value, time) @pytest.mark.supported( only_if=lambda backend: backend.hmac_supported(hashes.SHA256()), @@ -96,8 +95,7 @@ def test_verify_sha256(self, backend, params): totp_value = params["totp"] totp = TOTP(secret, 8, hashes.SHA256(), 30, backend) - - assert totp.verify(totp_value, time) is None + totp.verify(totp_value, time) @pytest.mark.supported( only_if=lambda backend: backend.hmac_supported(hashes.SHA512()), @@ -112,8 +110,7 @@ def test_verify_sha512(self, backend, params): totp_value = params["totp"] totp = TOTP(secret, 8, hashes.SHA512(), 30, backend) - - assert totp.verify(totp_value, time) is None + totp.verify(totp_value, time) def test_invalid_verify(self, backend): secret = b"12345678901234567890" diff --git a/tests/hazmat/test_der.py b/tests/hazmat/test_der.py index 8820ac1865a4..aeae01db3f9f 100644 --- a/tests/hazmat/test_der.py +++ b/tests/hazmat/test_der.py @@ -90,6 +90,7 @@ def test_der(): # Parsing a present optional element should work. integer = inner.read_optional_element(INTEGER) + assert integer is not None assert integer.as_integer() == 42 octet_string = inner.read_element(OCTET_STRING) @@ -228,4 +229,4 @@ def test_invalid_integer_encode(): encode_der_integer(-1) with pytest.raises(ValueError): - encode_der_integer("not an integer") + encode_der_integer("not an integer") # type: ignore[arg-type] From da8d490ed24f247769d3a67ed694debf659909b2 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 1 Feb 2021 22:43:36 -0500 Subject: [PATCH 0093/2380] Added typing for more of ciphers (#5738) --- .../hazmat/backends/openssl/ciphers.py | 10 ++--- .../hazmat/primitives/_cipheralgorithm.py | 13 ++++-- .../hazmat/primitives/ciphers/aead.py | 4 +- .../hazmat/primitives/ciphers/algorithms.py | 2 +- .../hazmat/primitives/ciphers/base.py | 43 +++++++++++-------- tests/doubles.py | 3 +- tests/hazmat/primitives/test_block.py | 4 +- tests/hazmat/primitives/test_ciphers.py | 2 +- 8 files changed, 49 insertions(+), 32 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py index 760774079766..2b10681b31d6 100644 --- a/src/cryptography/hazmat/backends/openssl/ciphers.py +++ b/src/cryptography/hazmat/backends/openssl/ciphers.py @@ -118,12 +118,12 @@ def __init__(self, backend, cipher, mode, operation): self._backend._lib.EVP_CIPHER_CTX_set_padding(ctx, 0) self._ctx = ctx - def update(self, data): + def update(self, data: bytes) -> bytes: buf = bytearray(len(data) + self._block_size_bytes - 1) n = self.update_into(data, buf) return bytes(buf[:n]) - def update_into(self, data, buf): + def update_into(self, data: bytes, buf) -> int: total_data_len = len(data) if len(buf) < (total_data_len + self._block_size_bytes - 1): raise ValueError( @@ -151,7 +151,7 @@ def update_into(self, data, buf): return total_out - def finalize(self): + def finalize(self) -> bytes: if ( self._operation == self._DECRYPT and isinstance(self._mode, modes.ModeWithAuthenticationTag) @@ -202,7 +202,7 @@ def finalize(self): self._backend.openssl_assert(res == 1) return self._backend._ffi.buffer(buf)[: outlen[0]] - def finalize_with_tag(self, tag): + def finalize_with_tag(self, tag: bytes) -> bytes: if len(tag) < self._mode._min_tag_length: raise ValueError( "Authentication tag must be {} bytes or longer.".format( @@ -216,7 +216,7 @@ def finalize_with_tag(self, tag): self._tag = tag return self.finalize() - def authenticate_additional_data(self, data): + def authenticate_additional_data(self, data: bytes) -> None: outlen = self._backend._ffi.new("int *") res = self._backend._lib.EVP_CipherUpdate( self._ctx, diff --git a/src/cryptography/hazmat/primitives/_cipheralgorithm.py b/src/cryptography/hazmat/primitives/_cipheralgorithm.py index f13d02d2d7e2..04ca5a987901 100644 --- a/src/cryptography/hazmat/primitives/_cipheralgorithm.py +++ b/src/cryptography/hazmat/primitives/_cipheralgorithm.py @@ -3,6 +3,7 @@ # for complete details. import abc +import typing # This exists to break an import cycle. It is normally accessible from the @@ -11,13 +12,19 @@ class CipherAlgorithm(metaclass=abc.ABCMeta): @abc.abstractproperty - def name(self): + def name(self) -> str: """ A string naming this mode (e.g. "AES", "Camellia"). """ @abc.abstractproperty - def key_size(self): + def key_sizes(self) -> typing.FrozenSet[int]: + """ + Valid key sizes for this algorithm in bits + """ + + @abc.abstractproperty + def key_size(self) -> int: """ The size of the key being used as an integer in bits (e.g. 128, 256). """ @@ -25,7 +32,7 @@ def key_size(self): class BlockCipherAlgorithm(metaclass=abc.ABCMeta): @abc.abstractproperty - def block_size(self): + def block_size(self) -> int: """ The size of a block as an integer in bits (e.g. 64, 128). """ diff --git a/src/cryptography/hazmat/primitives/ciphers/aead.py b/src/cryptography/hazmat/primitives/ciphers/aead.py index b539c6a46386..5c7cdc25b0ac 100644 --- a/src/cryptography/hazmat/primitives/ciphers/aead.py +++ b/src/cryptography/hazmat/primitives/ciphers/aead.py @@ -136,14 +136,14 @@ def decrypt( backend, self, nonce, data, associated_data, self._tag_length ) - def _validate_lengths(self, nonce, data_len): + def _validate_lengths(self, nonce: bytes, data_len: int): # For information about computing this, see # https://tools.ietf.org/html/rfc3610#section-2.1 l_val = 15 - len(nonce) if 2 ** (8 * l_val) < data_len: raise ValueError("Data too long for nonce") - def _check_params(self, nonce, data, associated_data): + def _check_params(self, nonce: bytes, data: bytes, associated_data: bytes): utils._check_byteslike("nonce", nonce) utils._check_bytes("data", data) utils._check_bytes("associated_data", associated_data) diff --git a/src/cryptography/hazmat/primitives/ciphers/algorithms.py b/src/cryptography/hazmat/primitives/ciphers/algorithms.py index cb1f252d49f8..ed72516611f3 100644 --- a/src/cryptography/hazmat/primitives/ciphers/algorithms.py +++ b/src/cryptography/hazmat/primitives/ciphers/algorithms.py @@ -11,7 +11,7 @@ from cryptography.hazmat.primitives.ciphers.modes import ModeWithNonce -def _verify_key_size(algorithm, key): +def _verify_key_size(algorithm: CipherAlgorithm, key: bytes): # Verify that the key is instance of bytes utils._check_byteslike("key", key) diff --git a/src/cryptography/hazmat/primitives/ciphers/base.py b/src/cryptography/hazmat/primitives/ciphers/base.py index 1b98637216f7..6f02597a725b 100644 --- a/src/cryptography/hazmat/primitives/ciphers/base.py +++ b/src/cryptography/hazmat/primitives/ciphers/base.py @@ -4,6 +4,7 @@ import abc +import typing from cryptography import utils from cryptography.exceptions import ( @@ -21,7 +22,7 @@ class BlockCipherAlgorithm(metaclass=abc.ABCMeta): @abc.abstractproperty - def block_size(self): + def block_size(self) -> int: """ The size of a block as an integer in bits (e.g. 64, 128). """ @@ -29,21 +30,21 @@ def block_size(self): class CipherContext(metaclass=abc.ABCMeta): @abc.abstractmethod - def update(self, data): + def update(self, data: bytes) -> bytes: """ Processes the provided bytes through the cipher and returns the results as bytes. """ @abc.abstractmethod - def update_into(self, data, buf): + def update_into(self, data: bytes, buf) -> int: """ Processes the provided bytes and writes the resulting data into the provided buffer. Returns the number of bytes written. """ @abc.abstractmethod - def finalize(self): + def finalize(self) -> bytes: """ Returns the results of processing the final block as bytes. """ @@ -51,7 +52,7 @@ def finalize(self): class AEADCipherContext(metaclass=abc.ABCMeta): @abc.abstractmethod - def authenticate_additional_data(self, data): + def authenticate_additional_data(self, data: bytes) -> None: """ Authenticates the provided bytes. """ @@ -59,7 +60,7 @@ def authenticate_additional_data(self, data): class AEADDecryptionContext(metaclass=abc.ABCMeta): @abc.abstractmethod - def finalize_with_tag(self, tag): + def finalize_with_tag(self, tag: bytes) -> bytes: """ Returns the results of processing the final block as bytes and allows delayed passing of the authentication tag. @@ -68,7 +69,7 @@ def finalize_with_tag(self, tag): class AEADEncryptionContext(metaclass=abc.ABCMeta): @abc.abstractproperty - def tag(self): + def tag(self) -> bytes: """ Returns tag bytes. This is only available after encryption is finalized. @@ -76,7 +77,12 @@ def tag(self): class Cipher(object): - def __init__(self, algorithm, mode, backend=None): + def __init__( + self, + algorithm: CipherAlgorithm, + mode: typing.Optional[modes.Mode], + backend=None, + ): backend = _get_backend(backend) if not isinstance(backend, CipherBackend): raise UnsupportedAlgorithm( @@ -126,17 +132,17 @@ class _CipherContext(object): def __init__(self, ctx): self._ctx = ctx - def update(self, data): + def update(self, data: bytes) -> bytes: if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") return self._ctx.update(data) - def update_into(self, data, buf): + def update_into(self, data: bytes, buf) -> int: if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") return self._ctx.update_into(data, buf) - def finalize(self): + def finalize(self) -> bytes: if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") data = self._ctx.finalize() @@ -155,7 +161,7 @@ def __init__(self, ctx): self._tag = None self._updated = False - def _check_limit(self, data_size): + def _check_limit(self, data_size: int): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") self._updated = True @@ -167,15 +173,15 @@ def _check_limit(self, data_size): ) ) - def update(self, data): + def update(self, data: bytes) -> bytes: self._check_limit(len(data)) return self._ctx.update(data) - def update_into(self, data, buf): + def update_into(self, data: bytes, buf) -> int: self._check_limit(len(data)) return self._ctx.update_into(data, buf) - def finalize(self): + def finalize(self) -> bytes: if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") data = self._ctx.finalize() @@ -183,7 +189,7 @@ def finalize(self): self._ctx = None return data - def finalize_with_tag(self, tag): + def finalize_with_tag(self, tag: bytes) -> bytes: if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") data = self._ctx.finalize_with_tag(tag) @@ -191,7 +197,7 @@ def finalize_with_tag(self, tag): self._ctx = None return data - def authenticate_additional_data(self, data): + def authenticate_additional_data(self, data: bytes) -> None: if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") if self._updated: @@ -211,9 +217,10 @@ def authenticate_additional_data(self, data): @utils.register_interface(AEADEncryptionContext) class _AEADEncryptionContext(_AEADCipherContext): @property - def tag(self): + def tag(self) -> bytes: if self._ctx is not None: raise NotYetFinalized( "You must finalize encryption before " "getting the tag." ) + assert self._tag is not None return self._tag diff --git a/tests/doubles.py b/tests/doubles.py index dd9bb9f0a469..de79fbe8c435 100644 --- a/tests/doubles.py +++ b/tests/doubles.py @@ -12,7 +12,8 @@ class DummyCipherAlgorithm(CipherAlgorithm): name = "dummy-cipher" block_size = 128 - key_size = None + key_size = 256 + key_sizes = frozenset([256]) class DummyMode(Mode): diff --git a/tests/hazmat/primitives/test_block.py b/tests/hazmat/primitives/test_block.py index 50f9fbb91ab6..1e01628ad7aa 100644 --- a/tests/hazmat/primitives/test_block.py +++ b/tests/hazmat/primitives/test_block.py @@ -45,7 +45,9 @@ def test_creates_decryptor(self, backend): def test_instantiate_with_non_algorithm(self, backend): algorithm = object() with pytest.raises(TypeError): - Cipher(algorithm, mode=None, backend=backend) + Cipher( + algorithm, mode=None, backend=backend # type: ignore[arg-type] + ) @pytest.mark.requires_backend_interface(interface=CipherBackend) diff --git a/tests/hazmat/primitives/test_ciphers.py b/tests/hazmat/primitives/test_ciphers.py index 694141821096..e82e3c26d995 100644 --- a/tests/hazmat/primitives/test_ciphers.py +++ b/tests/hazmat/primitives/test_ciphers.py @@ -205,7 +205,7 @@ def test_invalid_backend(): pretend_backend = object() with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE): - ciphers.Cipher(AES(b"AAAAAAAAAAAAAAAA"), modes.ECB, pretend_backend) + ciphers.Cipher(AES(b"AAAAAAAAAAAAAAAA"), modes.ECB(), pretend_backend) @pytest.mark.supported( From cba69f1922803f4f29a3fde01741890d88b8e217 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Feb 2021 08:56:29 -0500 Subject: [PATCH 0094/2380] Bump libc from 0.2.84 to 0.2.85 in /src/rust (#5739) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.84 to 0.2.85. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.84...0.2.85) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index f1a6f69eb439..59a5194c48b2 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -76,9 +76,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.84" +version = "0.2.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cca32fa0182e8c0989459524dc356b8f2b5c10f1b9eb521b7d182c03cf8c5ff" +checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3" [[package]] name = "lock_api" From d125d85458dd9c8f7fbcc28b6988a4fcae1fde06 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 2 Feb 2021 10:16:28 -0500 Subject: [PATCH 0095/2380] Use caching of rust artifacts in GHA (#5740) --- .github/workflows/ci.yml | 48 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d4d1b8fffca5..c8c17e9b2761 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,6 +32,14 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v2 + - uses: actions/cache@v2 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + src/rust/target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + - name: Setup python uses: actions/setup-python@v2.2.1 with: @@ -107,6 +115,14 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v2 + - uses: actions/cache@v2 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + src/rust/target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + - run: 'git clone --depth=1 https://github.com/google/wycheproof "$HOME/wycheproof"' - run: | echo "OPENSSL_FORCE_FIPS_MODE=1" >> $GITHUB_ENV @@ -135,6 +151,14 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v2 + - uses: actions/cache@v2 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + src/rust/target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}-${{ matrix.RUST }} + - name: Setup python uses: actions/setup-python@v2.2.1 with: @@ -169,6 +193,14 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v2 + - uses: actions/cache@v2 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + src/rust/target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + - name: Setup python uses: actions/setup-python@v2.2.1 with: @@ -220,6 +252,14 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v2 + - uses: actions/cache@v2 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + src/rust/target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + - name: Setup python uses: actions/setup-python@v2.2.1 with: @@ -273,6 +313,14 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v2 + - uses: actions/cache@v2 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + src/rust/target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + - name: Setup python uses: actions/setup-python@v2.2.1 with: From fb3c73a0b111017bbc0559301588321c9ae9759b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Feb 2021 08:43:16 -0500 Subject: [PATCH 0096/2380] Bump ctor from 0.1.18 to 0.1.19 in /src/rust (#5741) Bumps [ctor](https://github.com/mmastrac/rust-ctor) from 0.1.18 to 0.1.19. - [Release notes](https://github.com/mmastrac/rust-ctor/releases) - [Commits](https://github.com/mmastrac/rust-ctor/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 59a5194c48b2..d4b90b8c4203 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -15,9 +15,9 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10bcb9d7dcbf7002aaffbb53eac22906b64cdcc127971dcc387d8eb7c95d5560" +checksum = "e8f45d9ad417bcef4817d614a501ab55cdd96a6fdb24f49aab89a54acfd66b19" dependencies = [ "quote", "syn", From 0b41cb2b61d873c1204fad4fbc994c68ac7e0dd3 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 4 Feb 2021 18:43:41 -0500 Subject: [PATCH 0097/2380] Added typing for a bunch of random stuff (#5743) --- .../hazmat/primitives/asymmetric/dh.py | 8 +++---- .../hazmat/primitives/asymmetric/ec.py | 2 +- .../hazmat/primitives/asymmetric/ed25519.py | 2 +- .../hazmat/primitives/asymmetric/padding.py | 17 +++++++++++---- .../hazmat/primitives/asymmetric/rsa.py | 18 +++++++++------- .../hazmat/primitives/kdf/concatkdf.py | 2 +- .../hazmat/primitives/serialization/pkcs12.py | 20 +++++++++++------- tests/hazmat/backends/test_openssl.py | 4 +++- tests/hazmat/primitives/test_pkcs12.py | 3 +++ tests/hazmat/primitives/test_rsa.py | 21 +++++++++++++------ tests/wycheproof/test_rsa.py | 2 ++ 11 files changed, 65 insertions(+), 34 deletions(-) diff --git a/src/cryptography/hazmat/primitives/asymmetric/dh.py b/src/cryptography/hazmat/primitives/asymmetric/dh.py index 1d4f997391fb..9c53e509288b 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dh.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dh.py @@ -14,7 +14,7 @@ _MIN_MODULUS_SIZE = 512 -def generate_parameters(generator, key_size, backend=None): +def generate_parameters(generator, key_size, backend=None) -> "DHParameters": backend = _get_backend(backend) return backend.generate_dh_parameters(generator, key_size) @@ -83,7 +83,7 @@ def __eq__(self, other): def __ne__(self, other): return not self == other - def public_key(self, backend=None): + def public_key(self, backend=None) -> "DHPublicKey": backend = _get_backend(backend) return backend.load_dh_public_numbers(self) @@ -136,7 +136,7 @@ def parameter_bytes( self, encoding: "serialization.Encoding", format: "serialization.ParameterFormat", - ): + ) -> bytes: """ Returns the parameters serialized as bytes. """ @@ -222,7 +222,7 @@ def private_bytes( encoding: "serialization.Encoding", format: "serialization.PrivateFormat", encryption_algorithm: "serialization.KeySerializationEncryption", - ): + ) -> bytes: """ Returns the key serialized as bytes. """ diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index 734226920678..6374305d8754 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -509,7 +509,7 @@ class ECDH(object): } -def get_curve_for_oid(oid): +def get_curve_for_oid(oid: ObjectIdentifier) -> typing.Type[EllipticCurve]: try: return _OID_TO_CURVE[oid] except KeyError: diff --git a/src/cryptography/hazmat/primitives/asymmetric/ed25519.py b/src/cryptography/hazmat/primitives/asymmetric/ed25519.py index 381dc26722dc..8e649bf04a7e 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ed25519.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ed25519.py @@ -37,7 +37,7 @@ def public_bytes( """ @abc.abstractmethod - def verify(self, signature: bytes, data: bytes): + def verify(self, signature: bytes, data: bytes) -> None: """ Verify the signature. """ diff --git a/src/cryptography/hazmat/primitives/asymmetric/padding.py b/src/cryptography/hazmat/primitives/asymmetric/padding.py index 289c75f8ec33..a3b850ff5725 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/padding.py +++ b/src/cryptography/hazmat/primitives/asymmetric/padding.py @@ -4,6 +4,7 @@ import abc +import typing from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import rsa @@ -11,7 +12,7 @@ class AsymmetricPadding(metaclass=abc.ABCMeta): @abc.abstractproperty - def name(self): + def name(self) -> str: """ A string naming this padding (e.g. "PSS", "PKCS1"). """ @@ -43,7 +44,12 @@ def __init__(self, mgf, salt_length): class OAEP(AsymmetricPadding): name = "EME-OAEP" - def __init__(self, mgf, algorithm, label): + def __init__( + self, + mgf: "MGF1", + algorithm: hashes.HashAlgorithm, + label: typing.Optional[bytes], + ): if not isinstance(algorithm, hashes.HashAlgorithm): raise TypeError("Expected instance of hashes.HashAlgorithm.") @@ -55,14 +61,17 @@ def __init__(self, mgf, algorithm, label): class MGF1(object): MAX_LENGTH = object() - def __init__(self, algorithm): + def __init__(self, algorithm: hashes.HashAlgorithm): if not isinstance(algorithm, hashes.HashAlgorithm): raise TypeError("Expected instance of hashes.HashAlgorithm.") self._algorithm = algorithm -def calculate_max_pss_salt_length(key, hash_algorithm): +def calculate_max_pss_salt_length( + key: typing.Union["rsa.RSAPrivateKey", "rsa.RSAPublicKey"], + hash_algorithm: hashes.HashAlgorithm, +) -> int: if not isinstance(key, (rsa.RSAPrivateKey, rsa.RSAPublicKey)): raise TypeError("key must be an RSA public or private key") # bit length - 1 per RFC 3447 diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py index c4aeeeaafcfd..375356002814 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py @@ -160,7 +160,7 @@ def generate_private_key( return backend.generate_rsa_private_key(public_exponent, key_size) -def _verify_rsa_parameters(public_exponent: int, key_size: int): +def _verify_rsa_parameters(public_exponent: int, key_size: int) -> None: if public_exponent not in (3, 65537): raise ValueError( "public_exponent must be either 3 (for legacy compatibility) or " @@ -180,7 +180,7 @@ def _check_private_key_components( iqmp: int, public_exponent: int, modulus: int, -): +) -> None: if modulus < 3: raise ValueError("modulus must be >= 3.") @@ -218,7 +218,7 @@ def _check_private_key_components( raise ValueError("p*q must equal modulus.") -def _check_public_key_components(e: int, n: int): +def _check_public_key_components(e: int, n: int) -> None: if n < 3: raise ValueError("n must be >= 3.") @@ -229,7 +229,7 @@ def _check_public_key_components(e: int, n: int): raise ValueError("e must be odd.") -def _modinv(e: int, m: int): +def _modinv(e: int, m: int) -> int: """ Modular Multiplicative Inverse. Returns x such that: (x*e) mod m == 1 """ @@ -242,14 +242,14 @@ def _modinv(e: int, m: int): return x1 % m -def rsa_crt_iqmp(p: int, q: int): +def rsa_crt_iqmp(p: int, q: int) -> int: """ Compute the CRT (q ** -1) % p value from RSA primes p and q. """ return _modinv(q, p) -def rsa_crt_dmp1(private_exponent: int, p: int): +def rsa_crt_dmp1(private_exponent: int, p: int) -> int: """ Compute the CRT private_exponent % (p - 1) value from the RSA private_exponent (d) and p. @@ -257,7 +257,7 @@ def rsa_crt_dmp1(private_exponent: int, p: int): return private_exponent % (p - 1) -def rsa_crt_dmq1(private_exponent: int, q: int): +def rsa_crt_dmq1(private_exponent: int, q: int) -> int: """ Compute the CRT private_exponent % (q - 1) value from the RSA private_exponent (d) and q. @@ -271,7 +271,9 @@ def rsa_crt_dmq1(private_exponent: int, q: int): _MAX_RECOVERY_ATTEMPTS = 1000 -def rsa_recover_prime_factors(n: int, e: int, d: int): +def rsa_recover_prime_factors( + n: int, e: int, d: int +) -> typing.Tuple[int, int]: """ Compute factors p and q from the private exponent d. We assume that n has no more than two factors. This function is adapted from code in PyCrypto. diff --git a/src/cryptography/hazmat/primitives/kdf/concatkdf.py b/src/cryptography/hazmat/primitives/kdf/concatkdf.py index 196d3a492e29..4b7fce878acb 100644 --- a/src/cryptography/hazmat/primitives/kdf/concatkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/concatkdf.py @@ -139,7 +139,7 @@ def __init__( def _hmac(self) -> hmac.HMAC: return hmac.HMAC(self._salt, self._algorithm, self._backend) - def derive(self, key_material: bytes): + def derive(self, key_material: bytes) -> bytes: if self._used: raise AlreadyFinalized self._used = True diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs12.py b/src/cryptography/hazmat/primitives/serialization/pkcs12.py index e3ca34b9837e..1dabfca5534a 100644 --- a/src/cryptography/hazmat/primitives/serialization/pkcs12.py +++ b/src/cryptography/hazmat/primitives/serialization/pkcs12.py @@ -10,13 +10,6 @@ from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa -def load_key_and_certificates( - data: bytes, password: typing.Optional[bytes], backend=None -): - backend = _get_backend(backend) - return backend.load_key_and_certificates_from_pkcs12(data, password) - - _ALLOWED_PKCS12_TYPES = typing.Union[ rsa.RSAPrivateKey, dsa.DSAPrivateKey, @@ -24,13 +17,24 @@ def load_key_and_certificates( ] +def load_key_and_certificates( + data: bytes, password: typing.Optional[bytes], backend=None +) -> typing.Tuple[ + typing.Optional[_ALLOWED_PKCS12_TYPES], + typing.Optional[x509.Certificate], + typing.List[x509.Certificate], +]: + backend = _get_backend(backend) + return backend.load_key_and_certificates_from_pkcs12(data, password) + + def serialize_key_and_certificates( name: typing.Optional[bytes], key: typing.Optional[_ALLOWED_PKCS12_TYPES], cert: typing.Optional[x509.Certificate], cas: typing.Optional[typing.Iterable[x509.Certificate]], encryption_algorithm: serialization.KeySerializationEncryption, -): +) -> bytes: if key is not None and not isinstance( key, ( diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index ff112c61cd7a..4211b5d39128 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -407,7 +407,9 @@ def test_rsa_padding_unsupported_mgf(self): assert ( backend.rsa_padding_supported( padding.OAEP( - mgf=DummyMGF(), algorithm=hashes.SHA1(), label=None + mgf=DummyMGF(), # type: ignore[arg-type] + algorithm=hashes.SHA1(), + label=None, ), ) is False diff --git a/tests/hazmat/primitives/test_pkcs12.py b/tests/hazmat/primitives/test_pkcs12.py index 6691204e2e40..b5de09f95ca4 100644 --- a/tests/hazmat/primitives/test_pkcs12.py +++ b/tests/hazmat/primitives/test_pkcs12.py @@ -186,6 +186,7 @@ def test_generate(self, backend, name, encryption_algorithm, password): p12, password, backend ) assert parsed_cert == cert + assert parsed_key is not None assert parsed_key.private_numbers() == key.private_numbers() assert parsed_more_certs == [] @@ -204,6 +205,7 @@ def test_generate_with_cert_key_ca(self, backend): p12, None, backend ) assert parsed_cert == cert + assert parsed_key is not None assert parsed_key.private_numbers() == key.private_numbers() assert parsed_more_certs == [cert2, cert3] @@ -247,6 +249,7 @@ def test_generate_no_cert(self, backend): p12, None, backend ) assert parsed_cert is None + assert parsed_key is not None assert parsed_key.private_numbers() == key.private_numbers() assert parsed_more_certs == [] diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 2ab0f2625565..6d2f32145a27 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -609,7 +609,8 @@ def test_unsupported_pss_mgf(self, backend): private_key.sign( b"msg", padding.PSS( - mgf=DummyMGF(), salt_length=padding.PSS.MAX_LENGTH + mgf=DummyMGF(), # type: ignore[arg-type] + salt_length=padding.PSS.MAX_LENGTH, ), hashes.SHA1(), ) @@ -1455,7 +1456,9 @@ class TestRSAPKCS1Verification(object): class TestPSS(object): def test_calculate_max_pss_salt_length(self): with pytest.raises(TypeError): - padding.calculate_max_pss_salt_length(object(), hashes.SHA256()) + padding.calculate_max_pss_salt_length( + object(), hashes.SHA256() # type:ignore[arg-type] + ) def test_invalid_salt_length_not_integer(self): with pytest.raises(TypeError): @@ -1486,7 +1489,7 @@ def test_valid_pss_parameters_maximum(self): class TestMGF1(object): def test_invalid_hash_algorithm(self): with pytest.raises(TypeError): - padding.MGF1(b"not_a_hash") + padding.MGF1(b"not_a_hash") # type:ignore[arg-type] def test_valid_mgf1_parameters(self): algorithm = hashes.SHA1() @@ -1498,7 +1501,9 @@ class TestOAEP(object): def test_invalid_algorithm(self): mgf = padding.MGF1(hashes.SHA1()) with pytest.raises(TypeError): - padding.OAEP(mgf=mgf, algorithm=b"", label=None) + padding.OAEP( + mgf=mgf, algorithm=b"", label=None # type:ignore[arg-type] + ) @pytest.mark.requires_backend_interface(interface=RSABackend) @@ -1738,7 +1743,9 @@ def test_unsupported_oaep_mgf(self, backend): private_key.decrypt( b"0" * 64, padding.OAEP( - mgf=DummyMGF(), algorithm=hashes.SHA1(), label=None + mgf=DummyMGF(), # type: ignore[arg-type] + algorithm=hashes.SHA1(), + label=None, ), ) @@ -1924,7 +1931,9 @@ def test_unsupported_oaep_mgf(self, backend): public_key.encrypt( b"ciphertext", padding.OAEP( - mgf=DummyMGF(), algorithm=hashes.SHA1(), label=None + mgf=DummyMGF(), # type: ignore[arg-type] + algorithm=hashes.SHA1(), + label=None, ), ) diff --git a/tests/wycheproof/test_rsa.py b/tests/wycheproof/test_rsa.py index 440b09291f8b..0b0983da3590 100644 --- a/tests/wycheproof/test_rsa.py +++ b/tests/wycheproof/test_rsa.py @@ -194,6 +194,8 @@ def test_rsa_oaep_encryption(backend, wycheproof): assert isinstance(key, rsa.RSAPrivateKey) digest = _DIGESTS[wycheproof.testgroup["sha"]] mgf_digest = _DIGESTS[wycheproof.testgroup["mgfSha"]] + assert digest is not None + assert mgf_digest is not None padding_algo = padding.OAEP( mgf=padding.MGF1(algorithm=mgf_digest), From 9d1669534f95d276412fe224f5a9c413a814f759 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 6 Feb 2021 11:43:23 -0500 Subject: [PATCH 0098/2380] Linker script is no longer required for building your own OpenSSL (#5746) fixes #5683 --- docs/installation.rst | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index 313996233070..9f7eb1d7d75b 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -143,17 +143,7 @@ this when configuring OpenSSL: .. code-block:: console - $ ./config -Wl,--version-script=openssl.ld -Wl,-Bsymbolic-functions -fPIC shared - -You'll also need to generate your own ``openssl.ld`` file. For example:: - - OPENSSL_1.1.0E_CUSTOM { - global: - *; - }; - -You should replace the version string on the first line as appropriate for your -build. + $ ./config -Wl,-Bsymbolic-functions -fPIC shared Static Wheels ~~~~~~~~~~~~~ From 06cbf77371881e80ea4b5e349136dcc53749fc0c Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 7 Feb 2021 11:20:09 -0600 Subject: [PATCH 0099/2380] port changelog and fix back to master for CVE-2020-36242 (#5748) --- CHANGELOG.rst | 9 +++++++++ src/cryptography/hazmat/backends/openssl/ciphers.py | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 51953a595743..2de79e2060dd 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -20,6 +20,15 @@ Changelog they do not yet cover all public APIs, users can begin using them to type check their code with ``mypy``. +.. _v3-3-2: + +3.3.2 - 2021-02-07 +~~~~~~~~~~~~~~~~~~ + +* **SECURITY ISSUE:** Fixed a bug where certain sequences of ``update()`` calls + when symmetrically encrypting very large payloads (>2GB) could result in an + integer overflow, leading to buffer overflows. *CVE-2020-36242* + .. _v3-3-1: 3.3.1 - 2020-12-09 diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py index 2b10681b31d6..0f96795fdc73 100644 --- a/src/cryptography/hazmat/backends/openssl/ciphers.py +++ b/src/cryptography/hazmat/backends/openssl/ciphers.py @@ -16,7 +16,7 @@ class _CipherContext(object): _ENCRYPT = 1 _DECRYPT = 0 - _MAX_CHUNK_SIZE = 2 ** 31 - 1 + _MAX_CHUNK_SIZE = 2 ** 30 - 1 def __init__(self, backend, cipher, mode, operation): self._backend = backend From 2c11ad53c07179e03ea2f60813cb52d83f766292 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 7 Feb 2021 13:28:56 -0500 Subject: [PATCH 0100/2380] 3.4 release (#5749) --- CHANGELOG.rst | 11 ++++------- src/cryptography/__about__.py | 2 +- vectors/cryptography_vectors/__about__.py | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2de79e2060dd..15f94549726b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,10 +3,8 @@ Changelog .. _v3-4: -3.4 - `master`_ -~~~~~~~~~~~~~~~ - -.. note:: This version is not yet released and is under active development. +3.4 - 2021-02-07 +~~~~~~~~~~~~~~~~ * **BACKWARDS INCOMPATIBLE:** Support for Python 2 has been removed. * We now ship ``manylinux2014`` wheels and no longer ship ``manylinux1`` @@ -16,9 +14,8 @@ Changelog themselves will need to have the Rust toolchain installed. Users who use an officially produced wheel will not need to make any changes. The minimum supported Rust version is 1.45.0. -* ``cryptography`` has begun including :pep:`484` type hints on its APIs. While - they do not yet cover all public APIs, users can begin using them to type - check their code with ``mypy``. +* ``cryptography`` now has :pep:`484` type hints on nearly all of of its public + APIs. Users can begin using them to type check their code with ``mypy``. .. _v3-3-2: diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py index ab91153ecfe1..2e71757c56b5 100644 --- a/src/cryptography/__about__.py +++ b/src/cryptography/__about__.py @@ -21,7 +21,7 @@ ) __uri__ = "https://github.com/pyca/cryptography" -__version__ = "3.4.dev1" +__version__ = "3.4" __author__ = "The Python Cryptographic Authority and individual contributors" __email__ = "cryptography-dev@python.org" diff --git a/vectors/cryptography_vectors/__about__.py b/vectors/cryptography_vectors/__about__.py index fe4c6e5f19d9..bed5270de919 100644 --- a/vectors/cryptography_vectors/__about__.py +++ b/vectors/cryptography_vectors/__about__.py @@ -18,7 +18,7 @@ __uri__ = "https://github.com/pyca/cryptography" -__version__ = "3.4.dev1" +__version__ = "3.4" __author__ = "The Python Cryptographic Authority and individual contributors" __email__ = "cryptography-dev@python.org" From c22f3230f28d02362c626bec6c6bf6d82e7e06d9 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 7 Feb 2021 14:38:03 -0500 Subject: [PATCH 0101/2380] fix macos target for wheel builder (#5751) --- .github/workflows/wheel-builder.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 528c07fd4ac0..fa564effeae8 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -92,6 +92,8 @@ jobs: LDFLAGS="${HOME}/openssl-macos-x86-64/lib/libcrypto.a ${HOME}/openssl-macos-x86-64/lib/libssl.a" \ CFLAGS="-I${HOME}/openssl-macos-x86-64/include -mmacosx-version-min=10.10 -march=core2" \ ../venv/bin/python setup.py bdist_wheel --py-limited-api=${{ matrix.PYTHON.ABI_VERSION }} && mv dist/cryptography*.whl ../wheelhouse + env: + MACOSX_DEPLOYMENT_TARGET: "10.10" - run: venv/bin/pip install -f wheelhouse --no-index cryptography - 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'))" From 9f931ff99e13f68e6b8235d7ccdd0e688435fa52 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 7 Feb 2021 14:38:15 -0500 Subject: [PATCH 0102/2380] fixed manylinxu wheel builder for rust (#5750) --- .github/workflows/wheel-builder.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index fa564effeae8..cb7b11615684 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -32,6 +32,8 @@ jobs: LDFLAGS="-L/opt/pyca/cryptography/openssl/lib" \ CFLAGS="-I/opt/pyca/cryptography/openssl/include -Wl,--exclude-libs,ALL" \ ../.venv/bin/python setup.py bdist_wheel $PY_LIMITED_API && mv dist/cryptography*.whl ../tmpwheelhouse + env: + RUSTUP_HOME: /root/.rustup - run: auditwheel repair --plat ${{ matrix.MANYLINUX.NAME }} tmpwheelhouse/cryptograph*.whl -w wheelhouse/ - run: unzip wheelhouse/*.whl -d execstack.check - run: | From cac6703ccafafa4f879bad1d69ae926fb4e426ca Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 7 Feb 2021 14:22:02 -0600 Subject: [PATCH 0103/2380] reopen master for 3.5 (#5752) * reopen master for 3.5 * Update CHANGELOG.rst Co-authored-by: Alex Gaynor Co-authored-by: Alex Gaynor --- CHANGELOG.rst | 7 +++++++ src/cryptography/__about__.py | 2 +- vectors/cryptography_vectors/__about__.py | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 15f94549726b..23498769ea40 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,13 @@ Changelog ========= +.. _v3-5: + +3.5 - `master`_ +~~~~~~~~~~~~~~~~ + + .. note:: This version is not yet released and is under active development. + .. _v3-4: 3.4 - 2021-02-07 diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py index 2e71757c56b5..451d0fe52ff4 100644 --- a/src/cryptography/__about__.py +++ b/src/cryptography/__about__.py @@ -21,7 +21,7 @@ ) __uri__ = "https://github.com/pyca/cryptography" -__version__ = "3.4" +__version__ = "3.5.dev1" __author__ = "The Python Cryptographic Authority and individual contributors" __email__ = "cryptography-dev@python.org" diff --git a/vectors/cryptography_vectors/__about__.py b/vectors/cryptography_vectors/__about__.py index bed5270de919..eee22cf0e5bb 100644 --- a/vectors/cryptography_vectors/__about__.py +++ b/vectors/cryptography_vectors/__about__.py @@ -18,7 +18,7 @@ __uri__ = "https://github.com/pyca/cryptography" -__version__ = "3.4" +__version__ = "3.5.dev1" __author__ = "The Python Cryptographic Authority and individual contributors" __email__ = "cryptography-dev@python.org" From ab537a610dbde082ab2910b2dbaa648aa03640d0 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 7 Feb 2021 16:06:02 -0500 Subject: [PATCH 0104/2380] Try to assist folks having issues with older pips (#5757) * Try to assist folks having issues with older pips * Update setup.py * Update setup.py --- setup.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 58de2f4a8c5c..9fb3e3200401 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,21 @@ from setuptools import find_packages, setup -from setuptools_rust import RustExtension +try: + from setuptools_rust import RustExtension +except ImportError: + print( + """ + =============================DEBUG ASSISTANCE========================== + If you are seeing an error here please try the following to + successfully install cryptography: + + Upgrade to the latest pip and try again. This will fix errors for most + users. See: https://pip.pypa.io/en/stable/installing/#upgrading-pip + =============================DEBUG ASSISTANCE========================== + """ + ) + raise base_dir = os.path.dirname(__file__) From a3e435f1b1ecaddce14849f502426d0605133fc8 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 7 Feb 2021 15:06:34 -0600 Subject: [PATCH 0105/2380] update issue template with more words few people will read (#5759) --- .github/ISSUE_TEMPLATE.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE.rst b/.github/ISSUE_TEMPLATE.rst index 011d571c9f19..ea489382c1a2 100644 --- a/.github/ISSUE_TEMPLATE.rst +++ b/.github/ISSUE_TEMPLATE.rst @@ -1,9 +1,13 @@ If you're filing a bug (as opposed to a feature request), please try the following things: +* Check the FAQ to see if your issue is covered there: + https://cryptography.io/en/latest/faq.html * Upgrade to the latest version of ``setuptools`` and ``pip`` * Make sure you're on a supported version of OpenSSL * Try with the latest version of ``cryptography`` +* Be sure you have the required compilers (both a C compiler and Rust) + installed if you aren't using the binary wheels. If none of that works, please make sure to include the following information in your bug report: @@ -15,4 +19,4 @@ your bug report: Please do not report security issues on Github! Follow the instructions in our documentation for reporting security issues: -https://cryptography.io/en/latest/security/ +https://cryptography.io/en/latest/security.html From 4f03b8e89921c5f975cb0ea0e13b6420ffa88700 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 7 Feb 2021 15:11:20 -0600 Subject: [PATCH 0106/2380] fix import cycle with asymmetricpadding (#5758) * fix import cycle with asymmetricpadding * Update src/cryptography/hazmat/primitives/_asymmetric.py --- .../hazmat/primitives/_asymmetric.py | 17 +++++++++++++++++ .../hazmat/primitives/asymmetric/padding.py | 10 +--------- .../hazmat/primitives/asymmetric/rsa.py | 2 +- 3 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 src/cryptography/hazmat/primitives/_asymmetric.py diff --git a/src/cryptography/hazmat/primitives/_asymmetric.py b/src/cryptography/hazmat/primitives/_asymmetric.py new file mode 100644 index 000000000000..cdadbdeff799 --- /dev/null +++ b/src/cryptography/hazmat/primitives/_asymmetric.py @@ -0,0 +1,17 @@ +# 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. + +import abc + + +# This exists to break an import cycle. It is normally accessible from the +# asymmetric padding module. + + +class AsymmetricPadding(metaclass=abc.ABCMeta): + @abc.abstractproperty + def name(self) -> str: + """ + A string naming this padding (e.g. "PSS", "PKCS1"). + """ diff --git a/src/cryptography/hazmat/primitives/asymmetric/padding.py b/src/cryptography/hazmat/primitives/asymmetric/padding.py index a3b850ff5725..301c64c92898 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/padding.py +++ b/src/cryptography/hazmat/primitives/asymmetric/padding.py @@ -3,21 +3,13 @@ # for complete details. -import abc import typing from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives._asymmetric import AsymmetricPadding from cryptography.hazmat.primitives.asymmetric import rsa -class AsymmetricPadding(metaclass=abc.ABCMeta): - @abc.abstractproperty - def name(self) -> str: - """ - A string naming this padding (e.g. "PSS", "PKCS1"). - """ - - class PKCS1v15(AsymmetricPadding): name = "EMSA-PKCS1-v1_5" diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py index 375356002814..213e518db41a 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py @@ -12,12 +12,12 @@ from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.backends.interfaces import RSABackend from cryptography.hazmat.primitives import _serialization, hashes +from cryptography.hazmat.primitives._asymmetric import AsymmetricPadding from cryptography.hazmat.primitives.asymmetric import ( AsymmetricSignatureContext, AsymmetricVerificationContext, utils as asym_utils, ) -from cryptography.hazmat.primitives.asymmetric.padding import AsymmetricPadding class RSAPrivateKey(metaclass=abc.ABCMeta): From 585c53f382dab5a35caf265490801fb659297364 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 7 Feb 2021 16:23:25 -0600 Subject: [PATCH 0107/2380] forward port 3.4.1 changelog (#5762) --- CHANGELOG.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 23498769ea40..4522f628b0a0 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,15 @@ Changelog .. note:: This version is not yet released and is under active development. +.. _v3-4-1: + +3.4.1 - 2021-02-07 +~~~~~~~~~~~~~~~~~~ + +* Fixed a circular import issue. +* Added additional debug output to assist users seeing installation errors + due to outdated ``pip`` or missing ``rustc``. + .. _v3-4: 3.4 - 2021-02-07 From ab96eccb743be3d7e412143fb9529a2304451653 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 7 Feb 2021 17:30:55 -0500 Subject: [PATCH 0108/2380] include cargo in the docs for alpine (#5763) --- docs/installation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.rst b/docs/installation.rst index 9f7eb1d7d75b..6d89a7971c79 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -94,7 +94,7 @@ Alpine .. code-block:: console - $ sudo apk add gcc musl-dev python3-dev libffi-dev openssl-dev + $ sudo apk add gcc musl-dev python3-dev libffi-dev openssl-dev cargo If you get an error with ``openssl-dev`` you may have to use ``libressl-dev``. From f9277dc3763b2aeaeebc1b3d87c781d3f2ef3c84 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Feb 2021 08:46:28 -0500 Subject: [PATCH 0109/2380] Bump actions/cache from v2 to v2.1.4 (#5770) Bumps [actions/cache](https://github.com/actions/cache) from v2 to v2.1.4. - [Release notes](https://github.com/actions/cache/releases) - [Commits](https://github.com/actions/cache/compare/v2...26968a09c0ea4f3e233fdddbafd1166051a095f6) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c8c17e9b2761..72d10002a40d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v2 - - uses: actions/cache@v2 + - uses: actions/cache@v2.1.4 with: path: | ~/.cargo/registry @@ -65,7 +65,7 @@ jobs: CONFIG_FLAGS: ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }} if: matrix.PYTHON.OPENSSL - name: Load cache - uses: actions/cache@v2 + uses: actions/cache@v2.1.4 id: ossl-cache with: path: ${{ github.workspace }}/osslcache @@ -115,7 +115,7 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v2 - - uses: actions/cache@v2 + - uses: actions/cache@v2.1.4 with: path: | ~/.cargo/registry @@ -151,7 +151,7 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v2 - - uses: actions/cache@v2 + - uses: actions/cache@v2.1.4 with: path: | ~/.cargo/registry @@ -193,7 +193,7 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v2 - - uses: actions/cache@v2 + - uses: actions/cache@v2.1.4 with: path: | ~/.cargo/registry @@ -252,7 +252,7 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v2 - - uses: actions/cache@v2 + - uses: actions/cache@v2.1.4 with: path: | ~/.cargo/registry @@ -313,7 +313,7 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v2 - - uses: actions/cache@v2 + - uses: actions/cache@v2.1.4 with: path: | ~/.cargo/registry From 13e7e56c6094639cce1293f88a633270dfbe037c Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Mon, 8 Feb 2021 15:07:59 +0100 Subject: [PATCH 0110/2380] Interface: Make annotation check optional (#5775) * Interface: Make annotation check optional Fixes: https://github.com/pyca/cryptography/issues/5774 Signed-off-by: Christian Heimes * Use param.replace() Co-authored-by: Stanislav Levin Signed-off-by: Christian Heimes Co-authored-by: Stanislav Levin --- src/cryptography/utils.py | 25 +++++++++++++++++++------ tests/test_interfaces.py | 24 ++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index 9bf31faadbec..ef0fc44332d0 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -41,8 +41,8 @@ def read_only_property(name: str): def register_interface(iface): - def register_decorator(klass): - verify_interface(iface, klass) + def register_decorator(klass, *, check_annotations=False): + verify_interface(iface, klass, check_annotations=check_annotations) iface.register(klass) return klass @@ -50,9 +50,9 @@ def register_decorator(klass): def register_interface_if(predicate, iface): - def register_decorator(klass): + def register_decorator(klass, *, check_annotations=False): if predicate: - verify_interface(iface, klass) + verify_interface(iface, klass, check_annotations=check_annotations) iface.register(klass) return klass @@ -69,7 +69,16 @@ class InterfaceNotImplemented(Exception): pass -def verify_interface(iface, klass): +def strip_annotation(signature): + return inspect.Signature( + [ + param.replace(annotation=inspect.Parameter.empty) + for param in signature.parameters.values() + ] + ) + + +def verify_interface(iface, klass, *, check_annotations=False): for method in iface.__abstractmethods__: if not hasattr(klass, method): raise InterfaceNotImplemented( @@ -80,7 +89,11 @@ def verify_interface(iface, klass): continue sig = inspect.signature(getattr(iface, method)) actual = inspect.signature(getattr(klass, method)) - if sig != actual: + if check_annotations: + ok = sig == actual + else: + ok = strip_annotation(sig) == strip_annotation(actual) + if not ok: raise InterfaceNotImplemented( "{}.{}'s signature differs from the expected. Expected: " "{!r}. Received: {!r}".format(klass, method, sig, actual) diff --git a/tests/test_interfaces.py b/tests/test_interfaces.py index c5c579da0ca7..89d802aed017 100644 --- a/tests/test_interfaces.py +++ b/tests/test_interfaces.py @@ -77,3 +77,27 @@ def property(self): # Invoke this to ensure the line is covered NonImplementer().property verify_interface(SimpleInterface, NonImplementer) + + def test_signature_mismatch(self): + class SimpleInterface(metaclass=abc.ABCMeta): + @abc.abstractmethod + def method(self, other: object) -> int: + """Method with signature""" + + class ClassWithoutSignature: + def method(self, other): + """Method without signature""" + + class ClassWithSignature: + def method(self, other: object) -> int: + """Method with signature""" + + verify_interface(SimpleInterface, ClassWithoutSignature) + verify_interface(SimpleInterface, ClassWithSignature) + with pytest.raises(InterfaceNotImplemented): + verify_interface( + SimpleInterface, ClassWithoutSignature, check_annotations=True + ) + verify_interface( + SimpleInterface, ClassWithSignature, check_annotations=True + ) From 048f7c6cb4cd5a46b252e17c3463d254e1c552ab Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Mon, 8 Feb 2021 15:32:58 +0100 Subject: [PATCH 0111/2380] Remove setuptools_rust from install requirement (#5779) * Remove setuptools_rust from install requirement setuptools_rust is only required for building cryptography. Fixes: https://github.com/pyca/cryptography/issues/5778 Signed-off-by: Christian Heimes * sdist needs setuptools_rust Signed-off-by: Christian Heimes --- setup.py | 12 +++++++++--- tox.ini | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 9fb3e3200401..0142faccea85 100644 --- a/setup.py +++ b/setup.py @@ -39,8 +39,11 @@ exec(f.read(), about) -# `setup_requirements` must be kept in sync with `pyproject.toml` -setup_requirements = ["cffi>=1.12", "setuptools-rust>=0.11.4"] +# `install_requirements` and `setup_requirements` must be kept in sync with +# `pyproject.toml` +setuptools_rust = "setuptools-rust>=0.11.4" +install_requirements = ["cffi>=1.12"] +setup_requirements = install_requirements + [setuptools_rust] if os.environ.get("CRYPTOGRAPHY_DONT_BUILD_RUST"): rust_extensions = [] @@ -102,7 +105,7 @@ ), include_package_data=True, python_requires=">=3.6", - install_requires=setup_requirements, + install_requires=install_requirements, setup_requires=setup_requirements, extras_require={ "test": [ @@ -125,6 +128,9 @@ "twine >= 1.12.0", "sphinxcontrib-spelling >= 4.0.1", ], + "sdist": [ + setuptools_rust, + ], "pep8test": [ "black", "flake8", diff --git a/tox.ini b/tox.ini index e58612ce5fd6..93f4b253ab8d 100644 --- a/tox.ini +++ b/tox.ini @@ -20,6 +20,7 @@ commands = extras = docs docstest + sdist basepython = python3 commands = sphinx-build -T -W -b html -d {envtmpdir}/doctrees docs docs/_build/html From 9aa369af8c02d86a096e8c5338faa5b83e5cf2ee Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Mon, 8 Feb 2021 15:58:34 +0100 Subject: [PATCH 0112/2380] Update build instructions (#5764) The Rust version in CentOS 7 SCL is too old to build cryptography. Signed-off-by: Christian Heimes --- docs/installation.rst | 12 ++++++------ docs/spelling_wordlist.txt | 2 ++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index 6d89a7971c79..7edd92432d30 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -103,16 +103,16 @@ Debian/Ubuntu .. code-block:: console - $ sudo apt-get install build-essential libssl-dev libffi-dev python3-dev + $ sudo apt-get install build-essential libssl-dev libffi-dev \ + python3-dev cargo -RHEL/CentOS -~~~~~~~~~~~ +Fedora/RHEL 8/CentOS 8 +~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: console - $ sudo yum install redhat-rpm-config gcc libffi-devel python-devel \ - openssl-devel - + $ sudo dnf install redhat-rpm-config gcc libffi-devel python3-devel \ + openssl-devel cargo Building ~~~~~~~~ diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt index f59c3e413506..cad47e53677a 100644 --- a/docs/spelling_wordlist.txt +++ b/docs/spelling_wordlist.txt @@ -14,6 +14,7 @@ Botan Brainpool Bullseye Capitan +CentOS changelog Changelog ciphertext @@ -80,6 +81,7 @@ online paddings Parallelization personalization +RHEL pickleable plaintext Poly From 5fdc9c1b8563c2ffe99d6dff3f0632fb9dc29936 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 8 Feb 2021 10:18:13 -0500 Subject: [PATCH 0113/2380] More aggressively point people at Rust version docs (#5782) --- docs/faq.rst | 4 +++- docs/installation.rst | 2 ++ setup.py | 5 ++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/faq.rst b/docs/faq.rst index 7eec9c53b427..4123a1cf8461 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -123,7 +123,9 @@ Installing ``cryptography`` fails with ``error: Can not find Rust compiler`` Building ``cryptography`` from source requires you have :ref:`Rust installed and available` on your ``PATH``. You may be able to fix this by upgrading to a newer version of ``pip`` which will install a pre-compiled -``cryptography`` wheel. If not, you'll need to install Rust. +``cryptography`` wheel. If not, you'll need to install Rust. Follow the +:ref:`instructions` to ensure you install a recent Rust +version. For the current release *only* you can temporarily bypass the requirement to have Rust installed by setting the ``CRYPTOGRAPHY_DONT_BUILD_RUST`` environment diff --git a/docs/installation.rst b/docs/installation.rst index 7edd92432d30..e167f5af10d6 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -273,6 +273,8 @@ Building ``cryptography`` requires having a working Rust toolchain. The current minimum supported Rust version is 1.45.0. Instructions for installing Rust can be found on `the Rust Project's website`_. +We recommend installing Rust with ``rustup`` (as documented by the Rust +Project) in order to ensure you have a recent version. .. _`Homebrew`: https://brew.sh .. _`MacPorts`: https://www.macports.org diff --git a/setup.py b/setup.py index 0142faccea85..7e19d38e5c31 100644 --- a/setup.py +++ b/setup.py @@ -169,7 +169,10 @@ instructions for your platform. 3) Check our frequently asked questions for more information: https://cryptography.io/en/latest/faq.html - 4) Ensure you have a recent Rust toolchain installed. + 4) Ensure you have a recent Rust toolchain installed: + https://cryptography.io/en/latest/installation.html#rust + 5) If you are experiencing issues with Rust for *this release only* you may + set the environment variable `CRYPTOGRAPHY_DONT_BUILD_RUST=1`. =============================DEBUG ASSISTANCE============================= """ ) From b20507ae687dc2bf1841e7d7bc89cd4237177ae1 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 8 Feb 2021 10:50:39 -0600 Subject: [PATCH 0114/2380] link a lot more things, repeat advice in more places (#5785) * link a lot more things, repeat advice in more places * updated with Christian's comments * empty commit poor github --- docs/installation.rst | 69 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 6 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index e167f5af10d6..310f13c9f3b7 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -7,6 +7,9 @@ You can install ``cryptography`` with ``pip``: $ pip install cryptography +If this does not work please **upgrade your pip** first, as that is the +single most common cause of installation problems. + Supported platforms ------------------- @@ -72,18 +75,26 @@ local `wheel cache`_. Building cryptography on Linux ------------------------------ +.. note:: + + If you are on RHEL/CentOS/Fedora/Debian/Ubuntu or another distribution + derived from the preceding list, then you should **upgrade pip** and + attempt to install ``cryptography`` again before following the instructions + to compile it below. These platforms will receive a binary wheel and + require no compiler if you have an updated ``pip``! + ``cryptography`` ships ``manylinux`` wheels (as of 2.0) so all dependencies -are included. For users on pip 19.0 or above running on a ``manylinux2010`` (or -greater) compatible distribution (almost everything except Alpine) all you -should need to do is: +are included. For users on **pip 19.0** or above running on a ``manylinux2010`` +(or greater) compatible distribution (almost everything **except Alpine**) all +you should need to do is: .. code-block:: console $ pip install cryptography If you are on Alpine or just want to compile it yourself then -``cryptography`` requires a compiler, headers for Python (if you're not -using ``pypy``), and headers for the OpenSSL and ``libffi`` libraries +``cryptography`` requires a C compiler, a Rust compiler, headers for Python (if +you're not using ``pypy``), and headers for the OpenSSL and ``libffi`` libraries available on your system. On all Linux distributions you will need to have :ref:`Rust installed and @@ -92,6 +103,12 @@ available`. Alpine ~~~~~~ +.. warning:: + + The Rust available by default in Alpine < 3.13 is older than the minimum + supported version. See the :ref:`Rust installation instructions + ` for information about installing a newer Rust. + .. code-block:: console $ sudo apk add gcc musl-dev python3-dev libffi-dev openssl-dev cargo @@ -101,6 +118,14 @@ If you get an error with ``openssl-dev`` you may have to use ``libressl-dev``. Debian/Ubuntu ~~~~~~~~~~~~~ +.. warning:: + + The Rust available in current Debian stable and some Ubuntu versions is + older than the minimum supported version. Ubuntu 18.04 and 20.04 are + sufficiently new, but otherwise please see the + :ref:`Rust installation instructions ` for information + about installing a newer Rust. + .. code-block:: console $ sudo apt-get install build-essential libssl-dev libffi-dev \ @@ -109,11 +134,33 @@ Debian/Ubuntu Fedora/RHEL 8/CentOS 8 ~~~~~~~~~~~~~~~~~~~~~~ +.. warning:: + + For RHEL and CentOS you must be on version 8.3 or newer for the command + below to install a sufficiently new Rust. If your Rust is less than 1.45.0 + please see the :ref:`Rust installation instructions ` + for information about installing a newer Rust. + .. code-block:: console $ sudo dnf install redhat-rpm-config gcc libffi-devel python3-devel \ openssl-devel cargo +RHEL 7/CentOS 7 +~~~~~~~~~~~~~~~ + +.. warning:: + + You must install Rust using the :ref:`Rust installation instructions + `. ``cryptography`` requires a Rust version newer than + what is provided in the distribution packages. + +.. code-block:: console + + $ sudo yum install redhat-rpm-config gcc libffi-devel python-devel \ + openssl-devel + + Building ~~~~~~~~ @@ -269,8 +316,18 @@ local `wheel cache`_. Rust ---- +.. note:: + + If you are on RHEL/CentOS/Fedora/Debian/Ubuntu or another distribution + derived from the preceding list, then you should **upgrade ``pip``** (in + a virtual environment!) and attempt to install ``cryptography`` again + before trying to install the Rust toolchain. These platforms will receive + a binary wheel and require no compiler if you have an updated ``pip``! + Building ``cryptography`` requires having a working Rust toolchain. The current -minimum supported Rust version is 1.45.0. +minimum supported Rust version is 1.45.0. **This is newer than the Rust most +package managers ship**, so users will likely need to install with the +instructions below. Instructions for installing Rust can be found on `the Rust Project's website`_. We recommend installing Rust with ``rustup`` (as documented by the Rust From 9bf3880bc5b68903dae372d0953a5db820914172 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 8 Feb 2021 12:31:35 -0500 Subject: [PATCH 0115/2380] forward port 3.4.2 changelog (#5786) --- CHANGELOG.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4522f628b0a0..de952c3bffad 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,16 @@ Changelog .. note:: This version is not yet released and is under active development. +.. _v3-4-2: + +3.4.2 - 2021-02-08 +~~~~~~~~~~~~~~~~~~ + +* Improvements to make the rust transition a bit easier. This includes some + better error messages and small dependency fixes. If you experience + installation problems **Be sure to update pip** first, then check the + :doc:`FAQ `. + .. _v3-4-1: 3.4.1 - 2021-02-07 From e6df973a92e9026dc6f1a63e575bab1ff9b99910 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 8 Feb 2021 12:01:53 -0600 Subject: [PATCH 0116/2380] docs docs docs (#5788) --- docs/installation.rst | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index 310f13c9f3b7..ea2f33c7bb94 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -273,10 +273,12 @@ This will install a compiler (clang) along with (most of) the required development headers. You will also need to have :ref:`Rust installed and -available`. +available`, which can be obtained from `Homebrew`_, +`MacPorts`_, or directly from the Rust website. -You'll also need OpenSSL, which you can obtain from `Homebrew`_ or `MacPorts`_. -Cryptography does **not** support Apple's deprecated OpenSSL distribution. +Finally you need OpenSSL, which you can obtain from `Homebrew`_ or `MacPorts`_. +Cryptography does **not** support the OpenSSL/LibreSSL libraries Apple ships +in its base operating system. To build cryptography and dynamically link it: @@ -284,14 +286,14 @@ To build cryptography and dynamically link it: .. code-block:: console - $ brew install openssl@1.1 + $ brew install openssl@1.1 rust $ env LDFLAGS="-L$(brew --prefix openssl@1.1)/lib" CFLAGS="-I$(brew --prefix openssl@1.1)/include" pip install cryptography `MacPorts`_: .. code-block:: console - $ sudo port install openssl + $ sudo port install openssl rust $ env LDFLAGS="-L/opt/local/lib" CFLAGS="-I/opt/local/include" pip install cryptography You can also build cryptography statically: @@ -300,14 +302,14 @@ You can also build cryptography statically: .. code-block:: console - $ brew install openssl@1.1 + $ brew install openssl@1.1 rust $ env CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS=1 LDFLAGS="$(brew --prefix openssl@1.1)/lib/libssl.a $(brew --prefix openssl@1.1)/lib/libcrypto.a" CFLAGS="-I$(brew --prefix openssl@1.1)/include" pip install cryptography `MacPorts`_: .. code-block:: console - $ sudo port install openssl + $ sudo port install openssl rust $ env CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS=1 LDFLAGS="/opt/local/lib/libssl.a /opt/local/lib/libcrypto.a" CFLAGS="-I/opt/local/include" pip install cryptography If you need to rebuild ``cryptography`` for any reason be sure to clear the @@ -319,7 +321,7 @@ Rust .. note:: If you are on RHEL/CentOS/Fedora/Debian/Ubuntu or another distribution - derived from the preceding list, then you should **upgrade ``pip``** (in + derived from the preceding list, then you should **upgrade pip** (in a virtual environment!) and attempt to install ``cryptography`` again before trying to install the Rust toolchain. These platforms will receive a binary wheel and require no compiler if you have an updated ``pip``! From f01dcd62affe5dbc9f9dddc31f095cf15abcde9d Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 8 Feb 2021 19:09:31 -0500 Subject: [PATCH 0117/2380] Specify an MSRV in setup.py (#5789) --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 7e19d38e5c31..1a22695427a4 100644 --- a/setup.py +++ b/setup.py @@ -59,6 +59,7 @@ if platform.python_implementation() == "PyPy" else ["pyo3/abi3-py36"] ), + rust_version=">=1.45.0", ) ] From 9954a67ea93a101dc4a41331188ad9ac6c51409a Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 8 Feb 2021 23:11:43 -0600 Subject: [PATCH 0118/2380] port 3.4.3 changelog to master (#5792) --- CHANGELOG.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index de952c3bffad..02c2e76910c0 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,14 @@ Changelog .. note:: This version is not yet released and is under active development. +.. _v3-4-3: + +3.4.3 - 2021-02-08 +~~~~~~~~~~~~~~~~~~ + +* Specify our supported Rust version (>=1.45.0) in our ``setup.py`` so users + on older versions will get a clear error message. + .. _v3-4-2: 3.4.2 - 2021-02-08 From 4b7ebaff0e3e01af1229d5f4c3dd5b152a43cb85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Feb 2021 08:45:46 -0500 Subject: [PATCH 0119/2380] Bump libc from 0.2.85 to 0.2.86 in /src/rust (#5793) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.85 to 0.2.86. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.85...0.2.86) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index d4b90b8c4203..88161c27d45d 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -76,9 +76,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.85" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3" +checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" [[package]] name = "lock_api" From f6ca69c2af0f6728bc59ccad3513c5189bc5589e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 9 Feb 2021 10:38:33 -0500 Subject: [PATCH 0120/2380] fixed a circular import error (due to type hints) (#5800) fixes #5794 closes #5795 --- src/cryptography/hazmat/primitives/serialization/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cryptography/hazmat/primitives/serialization/base.py b/src/cryptography/hazmat/primitives/serialization/base.py index 00334b2e3b16..9f7531db2f7a 100644 --- a/src/cryptography/hazmat/primitives/serialization/base.py +++ b/src/cryptography/hazmat/primitives/serialization/base.py @@ -25,7 +25,7 @@ def load_pem_public_key(data: bytes, backend=None) -> _PUBLIC_KEY_TYPES: return backend.load_pem_public_key(data) -def load_pem_parameters(data: bytes, backend=None) -> dh.DHParameters: +def load_pem_parameters(data: bytes, backend=None) -> "dh.DHParameters": backend = _get_backend(backend) return backend.load_pem_parameters(data) @@ -42,6 +42,6 @@ def load_der_public_key(data: bytes, backend=None) -> _PUBLIC_KEY_TYPES: return backend.load_der_public_key(data) -def load_der_parameters(data: bytes, backend=None) -> dh.DHParameters: +def load_der_parameters(data: bytes, backend=None) -> "dh.DHParameters": backend = _get_backend(backend) return backend.load_der_parameters(data) From e8ec55cedc2e164f3c22d43768007e0d43ff9803 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 9 Feb 2021 11:31:25 -0500 Subject: [PATCH 0121/2380] Added a py.typed so mypy prefers us to typeshed (#5802) closes #5796 --- MANIFEST.in | 1 + src/cryptography/py.typed | 0 2 files changed, 1 insertion(+) create mode 100644 src/cryptography/py.typed diff --git a/MANIFEST.in b/MANIFEST.in index 4b4ec2dfc8e5..78889eaeb541 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -7,6 +7,7 @@ include LICENSE.PSF include README.rst include pyproject.toml +recursive-include src py.typed recursive-include docs * recursive-include src/_cffi_src *.py *.c *.h diff --git a/src/cryptography/py.typed b/src/cryptography/py.typed new file mode 100644 index 000000000000..e69de29bb2d1 From 4bbf9dfce880c40040f8a15a7f2994b66e716dcc Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 9 Feb 2021 14:25:47 -0500 Subject: [PATCH 0122/2380] Added a unit test to protect against import cycles (#5804) --- tests/test_meta.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tests/test_meta.py diff --git a/tests/test_meta.py b/tests/test_meta.py new file mode 100644 index 000000000000..d89daad81027 --- /dev/null +++ b/tests/test_meta.py @@ -0,0 +1,38 @@ +# 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. + +import os +import pkgutil +import subprocess +import sys +import typing + +import cryptography + + +def find_all_modules() -> typing.List[str]: + return sorted( + mod + for _, mod, _ in pkgutil.walk_packages( + cryptography.__path__, # type: ignore[attr-defined] + prefix=cryptography.__name__ + ".", + ) + ) + + +def test_no_circular_imports(subtests): + env = os.environ.copy() + env["PYTHONPATH"] = os.pathsep.join(sys.path) + + # When using pytest-cov it attempts to instrument subprocesses. This + # causes the memleak tests to raise exceptions. + # we don't need coverage so we remove the env vars. + env.pop("COV_CORE_CONFIG", None) + env.pop("COV_CORE_DATAFILE", None) + env.pop("COV_CORE_SOURCE", None) + + for module in find_all_modules(): + with subtests.test(): + argv = [sys.executable, "-c", f"__import__({module!r})"] + subprocess.check_call(argv, env=env) From aef024dc5668028f9f2ac67152a9573beb6606fe Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 9 Feb 2021 14:59:45 -0500 Subject: [PATCH 0123/2380] forward port 3.4.4 changelog (#5805) --- CHANGELOG.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 02c2e76910c0..afd1d61372a7 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,15 @@ Changelog .. note:: This version is not yet released and is under active development. +.. _v3-4-4: + +3.4.4 - 2021-02-09 +~~~~~~~~~~~~~~~~~~ + +* Added a ``py.typed`` file so that ``mypy`` will know to use our type + annotations. +* Fixed an import cycle that could be triggered by certain import sequences. + .. _v3-4-3: 3.4.3 - 2021-02-08 From 395384e811e46edebffce04ec84f484882d6a49f Mon Sep 17 00:00:00 2001 From: Markus Wamser Date: Wed, 10 Feb 2021 16:01:33 +0100 Subject: [PATCH 0124/2380] fix signature of EllipticCurvePublicKey.verify() (#5808) The signature change was introduced in https://github.com/pyca/cryptography/pull/5729 but is inconsistent with respect to related methods, breaks backward compatibility and compatibility with the OpenSSL backend (and maybe other backends) when named arguments are used. --- src/cryptography/hazmat/primitives/asymmetric/ec.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index 6374305d8754..56c5f9a02c21 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -176,7 +176,7 @@ def verify( self, signature: bytes, data: bytes, - algorithm: EllipticCurveSignatureAlgorithm, + signature_algorithm: EllipticCurveSignatureAlgorithm, ) -> None: """ Verifies the signature of the data. From 278fece69889898f0638dd4429cf40481e18ee14 Mon Sep 17 00:00:00 2001 From: Dan Halperin Date: Wed, 10 Feb 2021 12:32:21 -0800 Subject: [PATCH 0125/2380] Name: update get_attributes_for_oid return type (#5809) `List` gives more power to the caller. Note that `RelativeDistinguishedName`, the same function returns a `List`. Is there a reason this was `Iterable` only for `Name`? If we don't want to promise `List`, `Sequence` is another alternative. --- src/cryptography/x509/name.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptography/x509/name.py b/src/cryptography/x509/name.py index c183160e0aca..a579aa219638 100644 --- a/src/cryptography/x509/name.py +++ b/src/cryptography/x509/name.py @@ -216,7 +216,7 @@ def rfc4514_string(self) -> str: attr.rfc4514_string() for attr in reversed(self._attributes) ) - def get_attributes_for_oid(self, oid) -> typing.Iterable[NameAttribute]: + def get_attributes_for_oid(self, oid) -> typing.List[NameAttribute]: return [i for i in self if i.oid == oid] @property From 9efc6d46fb98a52a9bb956096a9389f21bd8de92 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 11 Feb 2021 11:47:20 -0500 Subject: [PATCH 0126/2380] fix a false positive from the latest clippy (#5813) --- src/rust/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs index f06ac5f02125..1580ca4fcef7 100644 --- a/src/rust/src/lib.rs +++ b/src/rust/src/lib.rs @@ -3,6 +3,8 @@ // for complete details. #[pyo3::prelude::pymodule] +// False positive: https://github.com/rust-lang/rust-clippy/issues/6721 +#[allow(clippy::unnecessary_wraps)] fn _rust(_py: pyo3::Python<'_>, _m: &pyo3::types::PyModule) -> pyo3::PyResult<()> { Ok(()) } From 5511445e95a16fa12b464d57ace4bb17855fe844 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 11 Feb 2021 13:56:46 -0500 Subject: [PATCH 0127/2380] Start typing a bunch of stuff from x509 extensions (#5812) --- src/cryptography/x509/extensions.py | 60 +++++++++++++-------- src/cryptography/x509/general_name.py | 21 +++----- tests/x509/test_ocsp.py | 4 +- tests/x509/test_x509.py | 4 +- tests/x509/test_x509_ext.py | 77 ++++++++++++++++++++------- 5 files changed, 110 insertions(+), 56 deletions(-) diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index 9f3d8f62d084..2f8612277d8f 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -990,15 +990,15 @@ class KeyUsage(ExtensionType): def __init__( self, - digital_signature, - content_commitment, - key_encipherment, - data_encipherment, - key_agreement, - key_cert_sign, - crl_sign, - encipher_only, - decipher_only, + digital_signature: bool, + content_commitment: bool, + key_encipherment: bool, + data_encipherment: bool, + key_agreement: bool, + key_cert_sign: bool, + crl_sign: bool, + encipher_only: bool, + decipher_only: bool, ): if not key_agreement and (encipher_only or decipher_only): raise ValueError( @@ -1101,7 +1101,11 @@ def __hash__(self): class NameConstraints(ExtensionType): oid = ExtensionOID.NAME_CONSTRAINTS - def __init__(self, permitted_subtrees, excluded_subtrees): + def __init__( + self, + permitted_subtrees: typing.Optional[typing.Iterable[GeneralName]], + excluded_subtrees: typing.Optional[typing.Iterable[GeneralName]], + ): if permitted_subtrees is not None: permitted_subtrees = list(permitted_subtrees) if not all(isinstance(x, GeneralName) for x in permitted_subtrees): @@ -1180,7 +1184,9 @@ def __hash__(self): class Extension(object): - def __init__(self, oid, critical, value): + def __init__( + self, oid: ObjectIdentifier, critical: bool, value: ExtensionType + ): if not isinstance(oid, ObjectIdentifier): raise TypeError( "oid argument must be an ObjectIdentifier instance." @@ -1221,7 +1227,7 @@ def __hash__(self): class GeneralNames(object): - def __init__(self, general_names): + def __init__(self, general_names: typing.Iterable[GeneralName]): general_names = list(general_names) if not all(isinstance(x, GeneralName) for x in general_names): raise TypeError( @@ -1233,7 +1239,7 @@ def __init__(self, general_names): __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") - def get_values_for_type(self, type): + def get_values_for_type(self, type: typing.Type[GeneralName]): # Return the value of each GeneralName, except for OtherName instances # which we return directly because it has two important properties not # just one value. @@ -1261,7 +1267,7 @@ def __hash__(self): class SubjectAlternativeName(ExtensionType): oid = ExtensionOID.SUBJECT_ALTERNATIVE_NAME - def __init__(self, general_names): + def __init__(self, general_names: typing.Iterable[GeneralName]): self._general_names = GeneralNames(general_names) __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") @@ -1288,7 +1294,7 @@ def __hash__(self): class IssuerAlternativeName(ExtensionType): oid = ExtensionOID.ISSUER_ALTERNATIVE_NAME - def __init__(self, general_names): + def __init__(self, general_names: typing.Iterable[GeneralName]): self._general_names = GeneralNames(general_names) __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") @@ -1315,7 +1321,7 @@ def __hash__(self): class CertificateIssuer(ExtensionType): oid = CRLEntryExtensionOID.CERTIFICATE_ISSUER - def __init__(self, general_names): + def __init__(self, general_names: typing.Iterable[GeneralName]): self._general_names = GeneralNames(general_names) __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") @@ -1342,7 +1348,7 @@ def __hash__(self): class CRLReason(ExtensionType): oid = CRLEntryExtensionOID.CRL_REASON - def __init__(self, reason): + def __init__(self, reason: ReasonFlags): if not isinstance(reason, ReasonFlags): raise TypeError("reason must be an element from ReasonFlags") @@ -1369,7 +1375,7 @@ def __hash__(self): class InvalidityDate(ExtensionType): oid = CRLEntryExtensionOID.INVALIDITY_DATE - def __init__(self, invalidity_date): + def __init__(self, invalidity_date: datetime.datetime): if not isinstance(invalidity_date, datetime.datetime): raise TypeError("invalidity_date must be a datetime.datetime") @@ -1398,7 +1404,12 @@ def __hash__(self): class PrecertificateSignedCertificateTimestamps(ExtensionType): oid = ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS - def __init__(self, signed_certificate_timestamps): + def __init__( + self, + signed_certificate_timestamps: typing.Iterable[ + SignedCertificateTimestamp + ], + ): signed_certificate_timestamps = list(signed_certificate_timestamps) if not all( isinstance(sct, SignedCertificateTimestamp) @@ -1438,7 +1449,12 @@ def __ne__(self, other): class SignedCertificateTimestamps(ExtensionType): oid = ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS - def __init__(self, signed_certificate_timestamps): + def __init__( + self, + signed_certificate_timestamps: typing.Iterable[ + SignedCertificateTimestamp + ], + ): signed_certificate_timestamps = list(signed_certificate_timestamps) if not all( isinstance(sct, SignedCertificateTimestamp) @@ -1476,7 +1492,7 @@ def __ne__(self, other): class OCSPNonce(ExtensionType): oid = OCSPExtensionOID.NONCE - def __init__(self, nonce): + def __init__(self, nonce: bytes): if not isinstance(nonce, bytes): raise TypeError("nonce must be bytes") @@ -1642,7 +1658,7 @@ def __hash__(self): class UnrecognizedExtension(ExtensionType): - def __init__(self, oid, value): + def __init__(self, oid: ObjectIdentifier, value: bytes): if not isinstance(oid, ObjectIdentifier): raise TypeError("oid must be an ObjectIdentifier") self._oid = oid diff --git a/src/cryptography/x509/general_name.py b/src/cryptography/x509/general_name.py index 6683e9313ce8..a83471e93131 100644 --- a/src/cryptography/x509/general_name.py +++ b/src/cryptography/x509/general_name.py @@ -40,8 +40,7 @@ def value(self): """ -@utils.register_interface(GeneralName) -class RFC822Name(object): +class RFC822Name(GeneralName): def __init__(self, value: str): if isinstance(value, str): try: @@ -87,8 +86,7 @@ def __hash__(self) -> int: return hash(self.value) -@utils.register_interface(GeneralName) -class DNSName(object): +class DNSName(GeneralName): def __init__(self, value: str): if isinstance(value, str): try: @@ -128,8 +126,7 @@ def __hash__(self) -> int: return hash(self.value) -@utils.register_interface(GeneralName) -class UniformResourceIdentifier(object): +class UniformResourceIdentifier(GeneralName): def __init__(self, value: str): if isinstance(value, str): try: @@ -169,8 +166,7 @@ def __hash__(self) -> int: return hash(self.value) -@utils.register_interface(GeneralName) -class DirectoryName(object): +class DirectoryName(GeneralName): def __init__(self, value: Name): if not isinstance(value, Name): raise TypeError("value must be a Name") @@ -195,8 +191,7 @@ def __hash__(self) -> int: return hash(self.value) -@utils.register_interface(GeneralName) -class RegisteredID(object): +class RegisteredID(GeneralName): def __init__(self, value: ObjectIdentifier): if not isinstance(value, ObjectIdentifier): raise TypeError("value must be an ObjectIdentifier") @@ -221,8 +216,7 @@ def __hash__(self) -> int: return hash(self.value) -@utils.register_interface(GeneralName) -class IPAddress(object): +class IPAddress(GeneralName): def __init__( self, value: typing.Union[ @@ -267,8 +261,7 @@ def __hash__(self) -> int: return hash(self.value) -@utils.register_interface(GeneralName) -class OtherName(object): +class OtherName(GeneralName): def __init__(self, type_id: ObjectIdentifier, value: bytes): if not isinstance(type_id, ObjectIdentifier): raise TypeError("type_id must be an ObjectIdentifier") diff --git a/tests/x509/test_ocsp.py b/tests/x509/test_ocsp.py index 5793f6d62be3..5d9da790af9f 100644 --- a/tests/x509/test_ocsp.py +++ b/tests/x509/test_ocsp.py @@ -726,7 +726,9 @@ def test_invalid_build_successful_status(self): class TestSignedCertificateTimestampsExtension(object): def test_init(self): with pytest.raises(TypeError): - x509.SignedCertificateTimestamps([object()]) + x509.SignedCertificateTimestamps( + [object()] # type: ignore[list-item] + ) def test_repr(self): assert repr(x509.SignedCertificateTimestamps([])) == ( diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 39f7bb951d41..b1e86f43647e 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -4070,7 +4070,9 @@ def test_subject_alt_name_unsupported_general_name(self, backend): x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, "SAN")]) ) .add_extension( - x509.SubjectAlternativeName([FakeGeneralName("")]), + x509.SubjectAlternativeName( + [FakeGeneralName("")] # type:ignore[list-item] + ), critical=False, ) ) diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index 011649f4ecd9..938357f2d514 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -56,12 +56,16 @@ class TestExtension(object): def test_not_an_oid(self): bc = x509.BasicConstraints(ca=False, path_length=None) with pytest.raises(TypeError): - x509.Extension("notanoid", True, bc) + x509.Extension("notanoid", True, bc) # type:ignore[arg-type] def test_critical_not_a_bool(self): bc = x509.BasicConstraints(ca=False, path_length=None) with pytest.raises(TypeError): - x509.Extension(ExtensionOID.BASIC_CONSTRAINTS, "notabool", bc) + x509.Extension( + ExtensionOID.BASIC_CONSTRAINTS, + "notabool", # type:ignore[arg-type] + bc, + ) def test_repr(self): bc = x509.BasicConstraints(ca=False, path_length=None) @@ -73,16 +77,38 @@ def test_repr(self): ) def test_eq(self): - ext1 = x509.Extension(x509.ObjectIdentifier("1.2.3.4"), False, "value") - ext2 = x509.Extension(x509.ObjectIdentifier("1.2.3.4"), False, "value") + ext1 = x509.Extension( + x509.ObjectIdentifier("1.2.3.4"), + False, + x509.BasicConstraints(ca=False, path_length=None), + ) + ext2 = x509.Extension( + x509.ObjectIdentifier("1.2.3.4"), + False, + x509.BasicConstraints(ca=False, path_length=None), + ) assert ext1 == ext2 def test_ne(self): - ext1 = x509.Extension(x509.ObjectIdentifier("1.2.3.4"), False, "value") - ext2 = x509.Extension(x509.ObjectIdentifier("1.2.3.5"), False, "value") - ext3 = x509.Extension(x509.ObjectIdentifier("1.2.3.4"), True, "value") + ext1 = x509.Extension( + x509.ObjectIdentifier("1.2.3.4"), + False, + x509.BasicConstraints(ca=False, path_length=None), + ) + ext2 = x509.Extension( + x509.ObjectIdentifier("1.2.3.5"), + False, + x509.BasicConstraints(ca=False, path_length=None), + ) + ext3 = x509.Extension( + x509.ObjectIdentifier("1.2.3.4"), + True, + x509.BasicConstraints(ca=False, path_length=None), + ) ext4 = x509.Extension( - x509.ObjectIdentifier("1.2.3.4"), False, "value4" + x509.ObjectIdentifier("1.2.3.4"), + False, + x509.BasicConstraints(ca=True, path_length=None), ) assert ext1 != ext2 assert ext1 != ext3 @@ -181,7 +207,9 @@ def test_indexing(self): class TestUnrecognizedExtension(object): def test_invalid_oid(self): with pytest.raises(TypeError): - x509.UnrecognizedExtension("notanoid", b"somedata") + x509.UnrecognizedExtension( + "notanoid", b"somedata" # type:ignore[arg-type] + ) def test_eq(self): ext1 = x509.UnrecognizedExtension( @@ -289,7 +317,7 @@ def test_hash(self): class TestCRLReason(object): def test_invalid_reason_flags(self): with pytest.raises(TypeError): - x509.CRLReason("notareason") + x509.CRLReason("notareason") # type:ignore[arg-type] def test_eq(self): reason1 = x509.CRLReason(x509.ReasonFlags.unspecified) @@ -346,7 +374,7 @@ def test_hash(self): class TestInvalidityDate(object): def test_invalid_invalidity_date(self): with pytest.raises(TypeError): - x509.InvalidityDate("notadate") + x509.InvalidityDate("notadate") # type:ignore[arg-type] def test_eq(self): invalid1 = x509.InvalidityDate(datetime.datetime(2015, 1, 1, 1, 1)) @@ -1990,7 +2018,12 @@ def test_indexing(self): def test_invalid_general_names(self): with pytest.raises(TypeError): - x509.GeneralNames([x509.DNSName("cryptography.io"), "invalid"]) + x509.GeneralNames( + [ + x509.DNSName("cryptography.io"), + "invalid", # type:ignore[list-item] + ] + ) def test_repr(self): gns = x509.GeneralNames([x509.DNSName("cryptography.io")]) @@ -2049,7 +2082,10 @@ def test_indexing(self): def test_invalid_general_names(self): with pytest.raises(TypeError): x509.IssuerAlternativeName( - [x509.DNSName("cryptography.io"), "invalid"] + [ + x509.DNSName("cryptography.io"), + "invalid", # type:ignore[list-item] + ] ) def test_repr(self): @@ -2157,7 +2193,10 @@ def test_indexing(self): def test_invalid_general_names(self): with pytest.raises(TypeError): x509.SubjectAlternativeName( - [x509.DNSName("cryptography.io"), "invalid"] + [ + x509.DNSName("cryptography.io"), + "invalid", # type:ignore[list-item] + ] ) def test_repr(self): @@ -3335,11 +3374,11 @@ def test_ipaddress_allowed_type(self): def test_invalid_permitted_subtrees(self): with pytest.raises(TypeError): - x509.NameConstraints("badpermitted", None) + x509.NameConstraints("badpermitted", None) # type:ignore[arg-type] def test_invalid_excluded_subtrees(self): with pytest.raises(TypeError): - x509.NameConstraints(None, "badexcluded") + x509.NameConstraints(None, "badexcluded") # type:ignore[arg-type] def test_no_subtrees(self): with pytest.raises(ValueError): @@ -5365,7 +5404,9 @@ def test_hash(self, backend): class TestPrecertificateSignedCertificateTimestampsExtension(object): def test_init(self): with pytest.raises(TypeError): - x509.PrecertificateSignedCertificateTimestamps([object()]) + x509.PrecertificateSignedCertificateTimestamps( + [object()] # type:ignore[list-item] + ) def test_repr(self): assert repr(x509.PrecertificateSignedCertificateTimestamps([])) == ( @@ -5566,7 +5607,7 @@ def test_invalid_certificate_policies_data(self, backend): class TestOCSPNonce(object): def test_non_bytes(self): with pytest.raises(TypeError): - x509.OCSPNonce(38) + x509.OCSPNonce(38) # type:ignore[arg-type] def test_eq(self): nonce1 = x509.OCSPNonce(b"0" * 5) From 250b992d37fb64fb4b9a0373d4e307e58beb37ce Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 11 Feb 2021 21:42:04 -0500 Subject: [PATCH 0128/2380] part 2 of typing x509 extensions (#5815) --- .../hazmat/backends/openssl/decode_asn1.py | 2 +- src/cryptography/x509/extensions.py | 97 +++++++++++------ tests/x509/test_x509_ext.py | 102 ++++++++++++------ 3 files changed, 138 insertions(+), 63 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 96ba4cdbc42c..167acc078743 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -768,7 +768,7 @@ def _asn1_string_to_ascii(backend, asn1_string): return _asn1_string_to_bytes(backend, asn1_string).decode("ascii") -def _asn1_string_to_utf8(backend, asn1_string): +def _asn1_string_to_utf8(backend, asn1_string) -> str: buf = backend._ffi.new("unsigned char **") res = backend._lib.ASN1_STRING_to_UTF8(buf, asn1_string) if res == -1: diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index 2f8612277d8f..6cae016a1c60 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -17,6 +17,7 @@ OBJECT_IDENTIFIER, SEQUENCE, ) +from cryptography.hazmat._types import _PUBLIC_KEY_TYPES from cryptography.hazmat.primitives import constant_time, serialization from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey @@ -33,7 +34,7 @@ ) -def _key_identifier_from_public_key(public_key): +def _key_identifier_from_public_key(public_key: _PUBLIC_KEY_TYPES) -> bytes: if isinstance(public_key, RSAPublicKey): data = public_key.public_bytes( serialization.Encoding.DER, @@ -54,7 +55,7 @@ def _key_identifier_from_public_key(public_key): reader = DERReader(serialized) with reader.read_single_element(SEQUENCE) as public_key_info: algorithm = public_key_info.read_element(SEQUENCE) - public_key = public_key_info.read_element(BIT_STRING) + public_key_data = public_key_info.read_element(BIT_STRING) # Double-check the algorithm structure. with algorithm: @@ -65,10 +66,10 @@ def _key_identifier_from_public_key(public_key): # BIT STRING contents begin with the number of padding bytes added. It # must be zero for SubjectPublicKeyInfo structures. - if public_key.read_byte() != 0: + if public_key_data.read_byte() != 0: raise ValueError("Invalid public key encoding") - data = public_key.data + data = public_key_data.data return hashlib.sha1(data).digest() @@ -110,14 +111,14 @@ class Extensions(object): def __init__(self, extensions: typing.List["Extension"]): self._extensions = extensions - def get_extension_for_oid(self, oid): + def get_extension_for_oid(self, oid: ObjectIdentifier) -> "Extension": for ext in self: if ext.oid == oid: return ext raise ExtensionNotFound("No {} extension was found".format(oid), oid) - def get_extension_for_class(self, extclass): + def get_extension_for_class(self, extclass) -> "Extension": if extclass is UnrecognizedExtension: raise TypeError( "UnrecognizedExtension can't be used with " @@ -142,7 +143,7 @@ def __repr__(self): class CRLNumber(ExtensionType): oid = ExtensionOID.CRL_NUMBER - def __init__(self, crl_number): + def __init__(self, crl_number: int): if not isinstance(crl_number, int): raise TypeError("crl_number must be an integer") @@ -171,9 +172,9 @@ class AuthorityKeyIdentifier(ExtensionType): def __init__( self, - key_identifier, - authority_cert_issuer, - authority_cert_serial_number, + key_identifier: typing.Optional[bytes], + authority_cert_issuer: typing.Optional[typing.Iterable[GeneralName]], + authority_cert_serial_number: typing.Optional[int], ): if (authority_cert_issuer is None) != ( authority_cert_serial_number is None @@ -203,7 +204,9 @@ def __init__( self._authority_cert_serial_number = authority_cert_serial_number @classmethod - def from_issuer_public_key(cls, public_key): + def from_issuer_public_key( + cls, public_key: _PUBLIC_KEY_TYPES + ) -> "AuthorityKeyIdentifier": digest = _key_identifier_from_public_key(public_key) return cls( key_identifier=digest, @@ -212,7 +215,9 @@ def from_issuer_public_key(cls, public_key): ) @classmethod - def from_issuer_subject_key_identifier(cls, ski): + def from_issuer_subject_key_identifier( + cls, ski: "SubjectKeyIdentifier" + ) -> "AuthorityKeyIdentifier": return cls( key_identifier=ski.digest, authority_cert_issuer=None, @@ -260,11 +265,13 @@ def __hash__(self): class SubjectKeyIdentifier(ExtensionType): oid = ExtensionOID.SUBJECT_KEY_IDENTIFIER - def __init__(self, digest): + def __init__(self, digest: bytes): self._digest = digest @classmethod - def from_public_key(cls, public_key): + def from_public_key( + cls, public_key: _PUBLIC_KEY_TYPES + ) -> "SubjectKeyIdentifier": return cls(_key_identifier_from_public_key(public_key)) digest = utils.read_only_property("_digest") @@ -288,7 +295,7 @@ def __hash__(self): class AuthorityInformationAccess(ExtensionType): oid = ExtensionOID.AUTHORITY_INFORMATION_ACCESS - def __init__(self, descriptions): + def __init__(self, descriptions: typing.Iterable["AccessDescription"]): descriptions = list(descriptions) if not all(isinstance(x, AccessDescription) for x in descriptions): raise TypeError( @@ -319,7 +326,7 @@ def __hash__(self): class SubjectInformationAccess(ExtensionType): oid = ExtensionOID.SUBJECT_INFORMATION_ACCESS - def __init__(self, descriptions): + def __init__(self, descriptions: typing.Iterable["AccessDescription"]): descriptions = list(descriptions) if not all(isinstance(x, AccessDescription) for x in descriptions): raise TypeError( @@ -348,7 +355,9 @@ def __hash__(self): class AccessDescription(object): - def __init__(self, access_method, access_location): + def __init__( + self, access_method: ObjectIdentifier, access_location: GeneralName + ): if not isinstance(access_method, ObjectIdentifier): raise TypeError("access_method must be an ObjectIdentifier") @@ -386,7 +395,7 @@ def __hash__(self): class BasicConstraints(ExtensionType): oid = ExtensionOID.BASIC_CONSTRAINTS - def __init__(self, ca, path_length): + def __init__(self, ca: bool, path_length: typing.Optional[int]): if not isinstance(ca, bool): raise TypeError("ca must be a boolean value") @@ -427,7 +436,7 @@ def __hash__(self): class DeltaCRLIndicator(ExtensionType): oid = ExtensionOID.DELTA_CRL_INDICATOR - def __init__(self, crl_number): + def __init__(self, crl_number: int): if not isinstance(crl_number, int): raise TypeError("crl_number must be an integer") @@ -454,7 +463,9 @@ def __repr__(self): class CRLDistributionPoints(ExtensionType): oid = ExtensionOID.CRL_DISTRIBUTION_POINTS - def __init__(self, distribution_points): + def __init__( + self, distribution_points: typing.Iterable["DistributionPoint"] + ): distribution_points = list(distribution_points) if not all( isinstance(x, DistributionPoint) for x in distribution_points @@ -489,7 +500,9 @@ def __hash__(self): class FreshestCRL(ExtensionType): oid = ExtensionOID.FRESHEST_CRL - def __init__(self, distribution_points): + def __init__( + self, distribution_points: typing.Iterable["DistributionPoint"] + ): distribution_points = list(distribution_points) if not all( isinstance(x, DistributionPoint) for x in distribution_points @@ -522,7 +535,13 @@ def __hash__(self): class DistributionPoint(object): - def __init__(self, full_name, relative_name, reasons, crl_issuer): + def __init__( + self, + full_name: typing.Optional[typing.Iterable[GeneralName]], + relative_name: typing.Optional[RelativeDistinguishedName], + reasons: typing.Optional[typing.FrozenSet["ReasonFlags"]], + crl_issuer: typing.Optional[typing.Iterable[GeneralName]], + ): if full_name and relative_name: raise ValueError( "You cannot provide both full_name and relative_name, at " @@ -631,7 +650,11 @@ class ReasonFlags(Enum): class PolicyConstraints(ExtensionType): oid = ExtensionOID.POLICY_CONSTRAINTS - def __init__(self, require_explicit_policy, inhibit_policy_mapping): + def __init__( + self, + require_explicit_policy: typing.Optional[int], + inhibit_policy_mapping: typing.Optional[int], + ): if require_explicit_policy is not None and not isinstance( require_explicit_policy, int ): @@ -691,7 +714,7 @@ def __hash__(self): class CertificatePolicies(ExtensionType): oid = ExtensionOID.CERTIFICATE_POLICIES - def __init__(self, policies): + def __init__(self, policies: typing.Iterable["PolicyInformation"]): policies = list(policies) if not all(isinstance(x, PolicyInformation) for x in policies): raise TypeError( @@ -720,7 +743,13 @@ def __hash__(self): class PolicyInformation(object): - def __init__(self, policy_identifier, policy_qualifiers): + def __init__( + self, + policy_identifier: ObjectIdentifier, + policy_qualifiers: typing.Optional[ + typing.Iterable[typing.Union[str, "UserNotice"]] + ], + ): if not isinstance(policy_identifier, ObjectIdentifier): raise TypeError("policy_identifier must be an ObjectIdentifier") @@ -769,7 +798,11 @@ def __hash__(self): class UserNotice(object): - def __init__(self, notice_reference, explicit_text): + def __init__( + self, + notice_reference: typing.Optional["NoticeReference"], + explicit_text: typing.Optional[str], + ): if notice_reference and not isinstance( notice_reference, NoticeReference ): @@ -806,7 +839,11 @@ def __hash__(self): class NoticeReference(object): - def __init__(self, organization, notice_numbers): + def __init__( + self, + organization: typing.Optional[str], + notice_numbers: typing.Iterable[int], + ): self._organization = organization notice_numbers = list(notice_numbers) if not all(isinstance(x, int) for x in notice_numbers): @@ -842,7 +879,7 @@ def __hash__(self): class ExtendedKeyUsage(ExtensionType): oid = ExtensionOID.EXTENDED_KEY_USAGE - def __init__(self, usages): + def __init__(self, usages: typing.Iterable[ObjectIdentifier]): usages = list(usages) if not all(isinstance(x, ObjectIdentifier) for x in usages): raise TypeError( @@ -910,7 +947,7 @@ def __repr__(self): class TLSFeature(ExtensionType): oid = ExtensionOID.TLS_FEATURE - def __init__(self, features): + def __init__(self, features: typing.Iterable["TLSFeatureType"]): features = list(features) if ( not all(isinstance(x, TLSFeatureType) for x in features) @@ -958,7 +995,7 @@ class TLSFeatureType(Enum): class InhibitAnyPolicy(ExtensionType): oid = ExtensionOID.INHIBIT_ANY_POLICY - def __init__(self, skip_certs): + def __init__(self, skip_certs: int): if not isinstance(skip_certs, int): raise TypeError("skip_certs must be an integer") diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index 938357f2d514..b8f226d5f848 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -7,6 +7,7 @@ import datetime import ipaddress import os +import typing import pretend @@ -138,7 +139,7 @@ def test_hash(self): class TestTLSFeature(object): def test_not_enum_type(self): with pytest.raises(TypeError): - x509.TLSFeature([3]) + x509.TLSFeature([3]) # type:ignore[list-item] def test_empty_list(self): with pytest.raises(TypeError): @@ -346,7 +347,7 @@ def test_repr(self): class TestDeltaCRLIndicator(object): def test_not_int(self): with pytest.raises(TypeError): - x509.DeltaCRLIndicator("notanint") + x509.DeltaCRLIndicator("notanint") # type:ignore[arg-type] def test_eq(self): delta1 = x509.DeltaCRLIndicator(1) @@ -404,11 +405,13 @@ def test_hash(self): class TestNoticeReference(object): def test_notice_numbers_not_all_int(self): with pytest.raises(TypeError): - x509.NoticeReference("org", [1, 2, "three"]) + x509.NoticeReference( + "org", [1, 2, "three"] # type:ignore[list-item] + ) def test_notice_numbers_none(self): with pytest.raises(TypeError): - x509.NoticeReference("org", None) + x509.NoticeReference("org", None) # type:ignore[arg-type] def test_iter_input(self): numbers = [1, 3, 4] @@ -447,7 +450,7 @@ def test_hash(self): class TestUserNotice(object): def test_notice_reference_invalid(self): with pytest.raises(TypeError): - x509.UserNotice("invalid", None) + x509.UserNotice("invalid", None) # type:ignore[arg-type] def test_notice_reference_none(self): un = x509.UserNotice(None, "text") @@ -491,7 +494,7 @@ def test_hash(self): class TestPolicyInformation(object): def test_invalid_policy_identifier(self): with pytest.raises(TypeError): - x509.PolicyInformation("notanoid", None) + x509.PolicyInformation("notanoid", None) # type:ignore[arg-type] def test_none_policy_qualifiers(self): pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), None) @@ -506,7 +509,10 @@ def test_policy_qualifiers(self): def test_invalid_policy_identifiers(self): with pytest.raises(TypeError): - x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), [1, 2]) + x509.PolicyInformation( + x509.ObjectIdentifier("1.2.3"), + [1, 2], # type:ignore[list-item] + ) def test_iter_input(self): qual = ["foo", "bar"] @@ -514,7 +520,10 @@ def test_iter_input(self): assert list(pi.policy_qualifiers) == qual def test_repr(self): - pq = ["string", x509.UserNotice(None, "hi")] + pq: typing.List[typing.Union[str, x509.UserNotice]] = [ + "string", + x509.UserNotice(None, "hi"), + ] pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), pq) assert repr(pi) == ( " Date: Thu, 11 Feb 2021 22:15:39 -0500 Subject: [PATCH 0129/2380] Updates for our new main branch (#5818) --- .github/workflows/ci.yml | 4 ++-- CHANGELOG.rst | 6 +++--- README.rst | 8 ++++---- docs/development/reviewing-patches.rst | 6 +++--- docs/security.rst | 4 ++-- release.py | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 72d10002a40d..ba020a4a915f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,7 @@ on: pull_request: {} push: branches: - - master + - main - '*.*.x' tags: - '*.*' @@ -338,7 +338,7 @@ jobs: - run: ./.github/downstream.d/${{ matrix.DOWNSTREAM }}.sh run docs-linkcheck: - if: github.event_name == 'push' && github.ref == 'refs/heads/master' + if: github.event_name == 'push' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest name: "linkcheck" timeout-minutes: 30 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index afd1d61372a7..0570a16eacce 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,8 +3,8 @@ Changelog .. _v3-5: -3.5 - `master`_ -~~~~~~~~~~~~~~~~ +3.5 - `main`_ +~~~~~~~~~~~~~ .. note:: This version is not yet released and is under active development. @@ -1691,5 +1691,5 @@ Changelog * Initial release. -.. _`master`: https://github.com/pyca/cryptography/ +.. _`main`: https://github.com/pyca/cryptography/ .. _`cffi`: https://cffi.readthedocs.io/ diff --git a/README.rst b/README.rst index 06bdbbec1f65..bb5f6f300666 100644 --- a/README.rst +++ b/README.rst @@ -9,11 +9,11 @@ pyca/cryptography :target: https://cryptography.io :alt: Latest Docs -.. image:: https://github.com/pyca/cryptography/workflows/CI/badge.svg?branch=master - :target: https://github.com/pyca/cryptography/actions?query=workflow%3ACI+branch%3Amaster +.. image:: https://github.com/pyca/cryptography/workflows/CI/badge.svg?branch=main + :target: https://github.com/pyca/cryptography/actions?query=workflow%3ACI+branch%3Amain -.. image:: https://codecov.io/github/pyca/cryptography/coverage.svg?branch=master - :target: https://codecov.io/github/pyca/cryptography?branch=master +.. image:: https://codecov.io/github/pyca/cryptography/coverage.svg?branch=main + :target: https://codecov.io/github/pyca/cryptography?branch=main ``cryptography`` is a package which provides cryptographic recipes and diff --git a/docs/development/reviewing-patches.rst b/docs/development/reviewing-patches.rst index 084461830be3..d3d66482aaed 100644 --- a/docs/development/reviewing-patches.rst +++ b/docs/development/reviewing-patches.rst @@ -41,15 +41,15 @@ Merge requirements Because cryptography is so complex, and the implications of getting it wrong so devastating, ``cryptography`` has a strict merge policy for committers: -* Patches must *never* be pushed directly to ``master``, all changes (even the +* Patches must *never* be pushed directly to ``main``, all changes (even the most trivial typo fixes!) must be submitted as a pull request. * A committer may *never* merge their own pull request, a second party must merge their changes. If multiple people work on a pull request, it must be merged by someone who did not work on it. * A patch that breaks tests, or introduces regressions by changing or removing existing tests should not be merged. Tests must always be passing on - ``master``. -* If somehow the tests get into a failing state on ``master`` (such as by a + ``main``. +* If somehow the tests get into a failing state on ``main`` (such as by a backwards incompatible release of a dependency) no pull requests may be merged until this is rectified. * All merged patches must have 100% test coverage. diff --git a/docs/security.rst b/docs/security.rst index d11f2700012a..6cd9dbe33937 100644 --- a/docs/security.rst +++ b/docs/security.rst @@ -64,7 +64,7 @@ further follow-up emails. Supported Versions ------------------ -At any given time, we will provide security support for the `master`_ branch +At any given time, we will provide security support for the `main`_ branch as well as the most recent release. New releases for OpenSSL updates @@ -89,4 +89,4 @@ The steps for issuing a security release are described in our :doc:`/doing-a-release` documentation. -.. _`master`: https://github.com/pyca/cryptography +.. _`main`: https://github.com/pyca/cryptography diff --git a/release.py b/release.py index 3416c8c56340..f5cf54d92575 100644 --- a/release.py +++ b/release.py @@ -90,7 +90,7 @@ def build_github_actions_wheels(token, version): "Accept": "application/vnd.github.v3+json", "Authorization": "token {}".format(token), }, - data=json.dumps({"ref": "master", "inputs": {"version": version}}), + data=json.dumps({"ref": "main", "inputs": {"version": version}}), ) response.raise_for_status() From 5ec07b89a203c896042c8dc1f6f810789c6ab573 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 11 Feb 2021 21:19:44 -0600 Subject: [PATCH 0130/2380] document how we should publish CVEs more rigorously (#5819) short version: in git commit, in changelog, in GH security advisory --- docs/doing-a-release.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/doing-a-release.rst b/docs/doing-a-release.rst index 5583ac4c2692..12d6bb063f18 100644 --- a/docs/doing-a-release.rst +++ b/docs/doing-a-release.rst @@ -13,7 +13,11 @@ security vulnerability, you should also include the following steps: included in the :doc:`changelog`. Ideally you should request the CVE before starting the release process so that the CVE is available at the time of the release. -* Ensure that the :doc:`changelog` entry credits whoever reported the issue. +* Document the CVE in the git commit that fixes the issue. +* Ensure that the :doc:`changelog` entry credits whoever reported the issue and + contains the assigned CVE. +* Publish a GitHub Security Advisory on the repository with all relevant + information. * The release should be announced on the `oss-security`_ mailing list, in addition to the regular announcement lists. From 32e540d10cbb17dd524d40fdb41fa4abfdcde1c4 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 12 Feb 2021 13:34:01 -0500 Subject: [PATCH 0131/2380] Add a comment to our readthedocs config file (#5821) --- .readthedocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.readthedocs.yml b/.readthedocs.yml index 728bb390c30c..ac4882422355 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -1,5 +1,6 @@ version: 2 build: + # First RTD build env which includes a rust toolchain image: "7.0" From 4b6b5063d3b2d8370be7dac9c264688e083b28cd Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 12 Feb 2021 15:43:56 -0500 Subject: [PATCH 0132/2380] Document that Rust is required at build time only (#5822) * Document that Rust is required at build time only * Update docs/faq.rst Co-authored-by: Paul Kehrer * Update docs/installation.rst Co-authored-by: Paul Kehrer Co-authored-by: Paul Kehrer --- docs/faq.rst | 5 +++++ docs/installation.rst | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/docs/faq.rst b/docs/faq.rst index 4123a1cf8461..c43396cf911e 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -127,6 +127,11 @@ by upgrading to a newer version of ``pip`` which will install a pre-compiled :ref:`instructions` to ensure you install a recent Rust version. +Rust is only required during the build phase of ``cryptography``, you do not +need to have Rust installed after you've built ``cryptography``. This is the +same as the C compiler toolchain which is also required to build +``cryptography``, but not afterwards. + For the current release *only* you can temporarily bypass the requirement to have Rust installed by setting the ``CRYPTOGRAPHY_DONT_BUILD_RUST`` environment variable. Note that this option will be removed in the next release and not diff --git a/docs/installation.rst b/docs/installation.rst index ea2f33c7bb94..ee435a6b4f22 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -335,6 +335,14 @@ Instructions for installing Rust can be found on `the Rust Project's website`_. We recommend installing Rust with ``rustup`` (as documented by the Rust Project) in order to ensure you have a recent version. +Rust is only required when building ``cryptography``, meaning that you may +install it for the duration of your ``pip install`` command and then remove it +from a system. A Rust toolchain is not required to **use** ``cryptography``. In +deployments such as ``docker``, you may use a multi-stage ``Dockerfile`` where +you install Rust during the build phase but do not install it in the runtime +image. This is the same as the C compiler toolchain which is also required to +build ``cryptography``, but not afterwards. + .. _`Homebrew`: https://brew.sh .. _`MacPorts`: https://www.macports.org .. _`a binary distribution`: https://wiki.openssl.org/index.php/Binaries From e82cd4e4e5947cc733876d815a455aa624b87141 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 13 Feb 2021 12:25:31 -0500 Subject: [PATCH 0133/2380] change to a new version scheme (#5825) * change to a new version scheme fixes #5801 * Update docs/api-stability.rst Co-authored-by: Paul Kehrer * line length Co-authored-by: Paul Kehrer --- CHANGELOG.rst | 6 +-- docs/api-stability.rst | 51 +++++++++++++++++------ src/cryptography/__about__.py | 2 +- vectors/cryptography_vectors/__about__.py | 2 +- 4 files changed, 43 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 0570a16eacce..39e9e78bc78e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,10 +1,10 @@ Changelog ========= -.. _v3-5: +.. _v35-0-0: -3.5 - `main`_ -~~~~~~~~~~~~~ +35.0.0 - `main`_ +~~~~~~~~~~~~~~~~ .. note:: This version is not yet released and is under active development. diff --git a/docs/api-stability.rst b/docs/api-stability.rst index fd34ced0aba1..3822702d3937 100644 --- a/docs/api-stability.rst +++ b/docs/api-stability.rst @@ -37,18 +37,23 @@ policy as necessary in order to resolve a security issue or harden Versioning ---------- -This project uses a custom versioning scheme as described below. +Version 35.0.0+ +~~~~~~~~~~~~~~~ -Given a version ``cryptography X.Y.Z``, +Beginning with release 35.0.0 ``cryptography`` uses a Firefox-inspired version +scheme. -* ``X.Y`` is a decimal number that is incremented for - potentially-backwards-incompatible releases. +Given a version ``cryptography X.Y.Z``, - * This increases like a standard decimal. - In other words, 0.9 is the ninth release, and 1.0 is the tenth (not 0.10). - The dividing decimal point can effectively be ignored. +* ``X`` indicates the major version number. This is incremented on any feature + release. +* ``Y`` is always ``0``. +* ``Z`` is an integer that is incremented for minor backward-compatible + releases (such as fixing security issues or correcting regressions in a major + release). -* ``Z`` is an integer that is incremented for backward-compatible releases. +This scheme is compatible with `SemVer`_, though many major releases will +**not** include any backwards-incompatible changes. Deprecation ~~~~~~~~~~~ @@ -56,16 +61,36 @@ Deprecation From time to time we will want to change the behavior of an API or remove it entirely. In that case, here's how the process will work: -* In ``cryptography X.Y`` the feature exists. -* In ``cryptography X.Y + 0.1`` using that feature will emit a +* In ``cryptography X.0.0`` the feature exists. +* In ``cryptography (X + 1).0.0`` using that feature will emit a ``UserWarning``. -* In ``cryptography X.Y + 0.2`` using that feature will emit a +* In ``cryptography (X + 2).0.0`` using that feature will emit a ``UserWarning``. -* In ``cryptography X.Y + 0.3`` the feature will be removed or changed. +* In ``cryptography (X + 3).0.0`` the feature will be removed or changed. In short, code that runs without warnings will always continue to work for a -period of two releases. +period of two major releases. From time to time, we may decide to deprecate an API that is particularly widely used. In these cases, we may decide to provide an extended deprecation period, at our discretion. + +Previous Scheme +~~~~~~~~~~~~~~~ + +Before version 35.0.0 this project uses a custom versioning scheme as described +below. + +Given a version ``cryptography X.Y.Z``, + +* ``X.Y`` is a decimal number that is incremented for + potentially-backwards-incompatible releases. + + * This increases like a standard decimal. + In other words, 0.9 is the ninth release, and 1.0 is the tenth (not 0.10). + The dividing decimal point can effectively be ignored. + +* ``Z`` is an integer that is incremented for backward-compatible releases. + + +.. _`SemVer`: https://semver.org/ diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py index 451d0fe52ff4..a035fa12ffd2 100644 --- a/src/cryptography/__about__.py +++ b/src/cryptography/__about__.py @@ -21,7 +21,7 @@ ) __uri__ = "https://github.com/pyca/cryptography" -__version__ = "3.5.dev1" +__version__ = "35.0.0.dev1" __author__ = "The Python Cryptographic Authority and individual contributors" __email__ = "cryptography-dev@python.org" diff --git a/vectors/cryptography_vectors/__about__.py b/vectors/cryptography_vectors/__about__.py index eee22cf0e5bb..05fa40efc53d 100644 --- a/vectors/cryptography_vectors/__about__.py +++ b/vectors/cryptography_vectors/__about__.py @@ -18,7 +18,7 @@ __uri__ = "https://github.com/pyca/cryptography" -__version__ = "3.5.dev1" +__version__ = "35.0.0.dev1" __author__ = "The Python Cryptographic Authority and individual contributors" __email__ = "cryptography-dev@python.org" From 2ed07926a9a19595f51ed1b6c5f985652c16bda8 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 13 Feb 2021 12:31:44 -0500 Subject: [PATCH 0134/2380] Start replacing read_only_property with dedicated functions (#5824) read_only_property is basically impossible for mypy to check --- .../hazmat/primitives/asymmetric/dh.py | 15 +++++++------ .../hazmat/primitives/asymmetric/dsa.py | 15 +++++++------ .../hazmat/primitives/asymmetric/ec.py | 21 ++++++++++++------- .../hazmat/primitives/asymmetric/rsa.py | 19 ++++++++--------- .../hazmat/primitives/asymmetric/utils.py | 3 +-- tests/hazmat/primitives/test_asym_utils.py | 6 ++++++ 6 files changed, 44 insertions(+), 35 deletions(-) diff --git a/src/cryptography/hazmat/primitives/asymmetric/dh.py b/src/cryptography/hazmat/primitives/asymmetric/dh.py index 9c53e509288b..6867f5365510 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dh.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dh.py @@ -6,7 +6,6 @@ import abc import typing -from cryptography import utils from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.primitives import serialization @@ -53,9 +52,9 @@ def parameters(self, backend=None): backend = _get_backend(backend) return backend.load_dh_parameter_numbers(self) - p = utils.read_only_property("_p") - g = utils.read_only_property("_g") - q = utils.read_only_property("_q") + p = property(lambda self: self._p) + g = property(lambda self: self._g) + q = property(lambda self: self._q) class DHPublicNumbers(object): @@ -87,8 +86,8 @@ def public_key(self, backend=None) -> "DHPublicKey": backend = _get_backend(backend) return backend.load_dh_public_numbers(self) - y = utils.read_only_property("_y") - parameter_numbers = utils.read_only_property("_parameter_numbers") + y = property(lambda self: self._y) + parameter_numbers = property(lambda self: self._parameter_numbers) class DHPrivateNumbers(object): @@ -120,8 +119,8 @@ def private_key(self, backend=None) -> "DHPrivateKey": backend = _get_backend(backend) return backend.load_dh_private_numbers(self) - public_numbers = utils.read_only_property("_public_numbers") - x = utils.read_only_property("_x") + public_numbers = property(lambda self: self._public_numbers) + x = property(lambda self: self._x) class DHParameters(metaclass=abc.ABCMeta): diff --git a/src/cryptography/hazmat/primitives/asymmetric/dsa.py b/src/cryptography/hazmat/primitives/asymmetric/dsa.py index c6f991bc7492..7946c02a7c60 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dsa.py @@ -6,7 +6,6 @@ import abc import typing -from cryptography import utils from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.primitives import _serialization, hashes from cryptography.hazmat.primitives.asymmetric import ( @@ -161,9 +160,9 @@ def __init__(self, p: int, q: int, g: int): self._q = q self._g = g - p = utils.read_only_property("_p") - q = utils.read_only_property("_q") - g = utils.read_only_property("_g") + p = property(lambda self: self._p) + q = property(lambda self: self._q) + g = property(lambda self: self._g) def parameters(self, backend=None) -> DSAParameters: backend = _get_backend(backend) @@ -198,8 +197,8 @@ def __init__(self, y: int, parameter_numbers: DSAParameterNumbers): self._y = y self._parameter_numbers = parameter_numbers - y = utils.read_only_property("_y") - parameter_numbers = utils.read_only_property("_parameter_numbers") + y = property(lambda self: self._y) + parameter_numbers = property(lambda self: self._parameter_numbers) def public_key(self, backend=None) -> DSAPublicKey: backend = _get_backend(backend) @@ -236,8 +235,8 @@ def __init__(self, x: int, public_numbers: DSAPublicNumbers): self._public_numbers = public_numbers self._x = x - x = utils.read_only_property("_x") - public_numbers = utils.read_only_property("_public_numbers") + x = property(lambda self: self._x) + public_numbers = property(lambda self: self._public_numbers) def private_key(self, backend=None) -> DSAPrivateKey: backend = _get_backend(backend) diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index 56c5f9a02c21..41dc5b58079c 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -326,10 +326,17 @@ class BrainpoolP512R1(EllipticCurve): class ECDSA(EllipticCurveSignatureAlgorithm): - def __init__(self, algorithm): + def __init__( + self, + algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], + ): self._algorithm = algorithm - algorithm = utils.read_only_property("_algorithm") + @property + def algorithm( + self, + ) -> typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm]: + return self._algorithm def generate_private_key( @@ -415,9 +422,9 @@ def from_encoded_point( else: raise ValueError("Unsupported elliptic curve point type") - curve = utils.read_only_property("_curve") - x = utils.read_only_property("_x") - y = utils.read_only_property("_y") + curve = property(lambda self: self._curve) + x = property(lambda self: self._x) + y = property(lambda self: self._y) def __eq__(self, other): if not isinstance(other, EllipticCurvePublicNumbers): @@ -463,8 +470,8 @@ def private_key(self, backend=None) -> EllipticCurvePrivateKey: backend = _get_backend(backend) return backend.load_elliptic_curve_private_numbers(self) - private_value = utils.read_only_property("_private_value") - public_numbers = utils.read_only_property("_public_numbers") + private_value = property(lambda self: self._private_value) + public_numbers = property(lambda self: self._public_numbers) def __eq__(self, other): if not isinstance(other, EllipticCurvePrivateNumbers): diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py index 213e518db41a..106e464bc49a 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py @@ -7,7 +7,6 @@ import typing from math import gcd -from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.backends.interfaces import RSABackend @@ -354,13 +353,13 @@ def __init__( self._iqmp = iqmp self._public_numbers = public_numbers - p = utils.read_only_property("_p") - q = utils.read_only_property("_q") - d = utils.read_only_property("_d") - dmp1 = utils.read_only_property("_dmp1") - dmq1 = utils.read_only_property("_dmq1") - iqmp = utils.read_only_property("_iqmp") - public_numbers = utils.read_only_property("_public_numbers") + p = property(lambda self: self._p) + q = property(lambda self: self._q) + d = property(lambda self: self._d) + dmp1 = property(lambda self: self._dmp1) + dmq1 = property(lambda self: self._dmq1) + iqmp = property(lambda self: self._iqmp) + public_numbers = property(lambda self: self._public_numbers) def private_key(self, backend=None) -> RSAPrivateKey: backend = _get_backend(backend) @@ -405,8 +404,8 @@ def __init__(self, e: int, n: int): self._e = e self._n = n - e = utils.read_only_property("_e") - n = utils.read_only_property("_n") + e = property(lambda self: self._e) + n = property(lambda self: self._n) def public_key(self, backend=None) -> RSAPublicKey: backend = _get_backend(backend) diff --git a/src/cryptography/hazmat/primitives/asymmetric/utils.py b/src/cryptography/hazmat/primitives/asymmetric/utils.py index 1118abcf251f..931df018414b 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/utils.py +++ b/src/cryptography/hazmat/primitives/asymmetric/utils.py @@ -5,7 +5,6 @@ import typing -from cryptography import utils from cryptography.hazmat._der import ( DERReader, INTEGER, @@ -39,4 +38,4 @@ def __init__(self, algorithm: hashes.HashAlgorithm): self._algorithm = algorithm self._digest_size = algorithm.digest_size - digest_size = utils.read_only_property("_digest_size") + digest_size = property(lambda self: self._digest_size) diff --git a/tests/hazmat/primitives/test_asym_utils.py b/tests/hazmat/primitives/test_asym_utils.py index 0891cc87aa1d..e4f22d7303e9 100644 --- a/tests/hazmat/primitives/test_asym_utils.py +++ b/tests/hazmat/primitives/test_asym_utils.py @@ -5,6 +5,7 @@ import pytest +from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric.utils import ( Prehashed, decode_dss_signature, @@ -74,3 +75,8 @@ def test_decode_dss_invalid_asn1(): def test_pass_invalid_prehashed_arg(): with pytest.raises(TypeError): Prehashed(object()) # type: ignore[arg-type] + + +def test_prehashed_digest_size(): + p = Prehashed(hashes.SHA256()) + assert p.digest_size == 32 From 7e30277483f5556ba05ab57edec11f0b8eebbb6e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 13 Feb 2021 14:35:56 -0500 Subject: [PATCH 0135/2380] Bump pyo3 and lower MSRV (#5823) --- .github/workflows/ci.yml | 3 +- docs/installation.rst | 6 ++-- setup.py | 2 +- src/rust/Cargo.lock | 74 +++++++++++++++++++++++++++++++--------- 4 files changed, 64 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba020a4a915f..e599991971ce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -143,7 +143,8 @@ jobs: PYTHON: - {VERSION: "3.9", TOXENV: "py39"} RUST: - # Cover MSRV and in-dev versions + # Cover MSRV (and likely next MSRV) and in-dev versions + - 1.41.0 - 1.45.0 - beta - nightly diff --git a/docs/installation.rst b/docs/installation.rst index ee435a6b4f22..278e680ce1f5 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -105,7 +105,7 @@ Alpine .. warning:: - The Rust available by default in Alpine < 3.13 is older than the minimum + The Rust available by default in Alpine < 3.12 is older than the minimum supported version. See the :ref:`Rust installation instructions ` for information about installing a newer Rust. @@ -137,7 +137,7 @@ Fedora/RHEL 8/CentOS 8 .. warning:: For RHEL and CentOS you must be on version 8.3 or newer for the command - below to install a sufficiently new Rust. If your Rust is less than 1.45.0 + below to install a sufficiently new Rust. If your Rust is less than 1.41.0 please see the :ref:`Rust installation instructions ` for information about installing a newer Rust. @@ -327,7 +327,7 @@ Rust a binary wheel and require no compiler if you have an updated ``pip``! Building ``cryptography`` requires having a working Rust toolchain. The current -minimum supported Rust version is 1.45.0. **This is newer than the Rust most +minimum supported Rust version is 1.41.0. **This is newer than the Rust most package managers ship**, so users will likely need to install with the instructions below. diff --git a/setup.py b/setup.py index 1a22695427a4..74f69e7148a6 100644 --- a/setup.py +++ b/setup.py @@ -59,7 +59,7 @@ if platform.python_implementation() == "PyPy" else ["pyo3/abi3-py36"] ), - rust_version=">=1.45.0", + rust_version=">=1.41.0", ) ] diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 88161c27d45d..94f89ff74762 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -1,5 +1,11 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + [[package]] name = "cfg-if" version = "1.0.0" @@ -36,10 +42,24 @@ dependencies = [ [[package]] name = "indoc" -version = "1.0.3" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8" +dependencies = [ + "indoc-impl", + "proc-macro-hack", +] + +[[package]] +name = "indoc-impl" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a75aeaaef0ce18b58056d306c27b07436fbb34b8816c53094b76dd81803136" +checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0" dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", "unindent", ] @@ -102,9 +122,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ccb628cad4f84851442432c60ad8e1f607e29752d0bf072cbd0baf28aa34272" +checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" dependencies = [ "cfg-if", "instant", @@ -116,9 +136,28 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.4" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5d65c4d95931acda4498f675e332fcbdc9a06705cd07086c510e9b6009cd1c1" +checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" +dependencies = [ + "paste-impl", + "proc-macro-hack", +] + +[[package]] +name = "paste-impl" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" +dependencies = [ + "proc-macro-hack", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" @@ -131,9 +170,9 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00ca634cf3acd58a599b535ed6cb188223298977d471d146121792bfa23b754c" +checksum = "4837b8e8e18a102c23f79d1e9a110b597ea3b684c95e874eb1ad88f8683109c3" dependencies = [ "cfg-if", "ctor", @@ -148,9 +187,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "483ac516dbda6789a5b4be0271e7a31b9ad4ec8c0a5955050e8076f72bdbef8f" +checksum = "a47f2c300ceec3e58064fd5f8f5b61230f2ffd64bde4970c81fdd0563a2db1bb" dependencies = [ "pyo3-macros-backend", "quote", @@ -159,9 +198,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15230cabcda008f03565ed8bac40f094cbb5ee1b46e6551f1ec3a0e922cf7df9" +checksum = "87b097e5d84fcbe3e167f400fbedd657820a375b034c78bd852050749a575d66" dependencies = [ "proc-macro2", "quote", @@ -170,18 +209,21 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ "proc-macro2", ] [[package]] name = "redox_syscall" -version = "0.1.57" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" +checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570" +dependencies = [ + "bitflags", +] [[package]] name = "scopeguard" From 151aa097cdf4632f382bc8c95d7771ed7290cf66 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 13 Feb 2021 17:17:39 -0600 Subject: [PATCH 0136/2380] port 3.4.5 changelog (#5828) --- CHANGELOG.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 39e9e78bc78e..91e50b278243 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,19 @@ Changelog .. note:: This version is not yet released and is under active development. +.. _v3-4-5: + +3.4.5 - 2021-02-13 +~~~~~~~~~~~~~~~~~~ + +* Various improvements to type hints. +* Lower the minimum supported Rust version (MSRV) to >=1.41.0. This change + improves compatibility with system-provided Rust on several Linux + distributions. +* ``cryptography`` will be switching to a new versioning scheme with its next + feature release. More information is available in our + :doc:`/api-stability` documentation. + .. _v3-4-4: 3.4.4 - 2021-02-09 From a15b5808ebc80da42d6c54663eb8070141343eb6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Feb 2021 08:47:11 -0500 Subject: [PATCH 0137/2380] Bump redox_syscall from 0.2.4 to 0.2.5 in /src/rust (#5832) Bumps redox_syscall from 0.2.4 to 0.2.5. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 94f89ff74762..83fd7eb8f48b 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -218,9 +218,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570" +checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" dependencies = [ "bitflags", ] From 96801ff92e861c8ee333c14afda691d1025e5e8f Mon Sep 17 00:00:00 2001 From: Mathias Ertl Date: Mon, 15 Feb 2021 22:11:50 +0100 Subject: [PATCH 0138/2380] add typehints for read only properties (#5826) * add typehints for read only properties * fix typing in test cases * fix last missing assertion * add typehints to all read_only_properties where type hints are already available * check for isnot None instead, as per PR suggestion * convert read_only_property to @property decorators * remove unused import * use List instead of Iterable for return values * use @property instead of read_only_property * fix type errors * remove last occurance of annotated read_only_property * use is not None check (works because we now return list) * fix unused import --- src/cryptography/hazmat/_oid.py | 7 +- .../hazmat/backends/openssl/hashes.py | 5 +- .../hazmat/backends/openssl/hmac.py | 5 +- .../hazmat/primitives/ciphers/algorithms.py | 4 +- .../hazmat/primitives/ciphers/modes.py | 39 +++- src/cryptography/hazmat/primitives/hashes.py | 20 +- src/cryptography/hazmat/primitives/hmac.py | 4 +- src/cryptography/x509/extensions.py | 201 +++++++++++++----- src/cryptography/x509/general_name.py | 41 +++- src/cryptography/x509/name.py | 12 +- tests/x509/test_x509_crlbuilder.py | 1 + tests/x509/test_x509_ext.py | 6 + 12 files changed, 259 insertions(+), 86 deletions(-) diff --git a/src/cryptography/hazmat/_oid.py b/src/cryptography/hazmat/_oid.py index 27eeb7d7d7ff..3e22ea9f284e 100644 --- a/src/cryptography/hazmat/_oid.py +++ b/src/cryptography/hazmat/_oid.py @@ -3,9 +3,6 @@ # for complete details. -from cryptography import utils - - class ObjectIdentifier(object): def __init__(self, dotted_string: str): self._dotted_string = dotted_string @@ -73,4 +70,6 @@ def _name(self): return _OID_NAMES.get(self, "Unknown OID") - dotted_string = utils.read_only_property("_dotted_string") + @property + def dotted_string(self) -> str: + return self._dotted_string diff --git a/src/cryptography/hazmat/backends/openssl/hashes.py b/src/cryptography/hazmat/backends/openssl/hashes.py index 823d24f91595..aa816c122663 100644 --- a/src/cryptography/hazmat/backends/openssl/hashes.py +++ b/src/cryptography/hazmat/backends/openssl/hashes.py @@ -3,7 +3,6 @@ # for complete details. -from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.primitives import hashes @@ -34,7 +33,9 @@ def __init__(self, backend, algorithm: hashes.HashAlgorithm, ctx=None): self._ctx = ctx - algorithm = utils.read_only_property("_algorithm") + @property + def algorithm(self) -> hashes.HashAlgorithm: + return self._algorithm def copy(self) -> "_HashContext": copied_ctx = self._backend._lib.EVP_MD_CTX_new() diff --git a/src/cryptography/hazmat/backends/openssl/hmac.py b/src/cryptography/hazmat/backends/openssl/hmac.py index e9e461300f7a..c9c28f5967ae 100644 --- a/src/cryptography/hazmat/backends/openssl/hmac.py +++ b/src/cryptography/hazmat/backends/openssl/hmac.py @@ -3,7 +3,6 @@ # for complete details. -from cryptography import utils from cryptography.exceptions import ( InvalidSignature, UnsupportedAlgorithm, @@ -40,7 +39,9 @@ def __init__( self._ctx = ctx self._key = key - algorithm = utils.read_only_property("_algorithm") + @property + def algorithm(self) -> hashes.HashAlgorithm: + return self._algorithm def copy(self) -> "_HMACContext": copied_ctx = self._backend._lib.HMAC_CTX_new() diff --git a/src/cryptography/hazmat/primitives/ciphers/algorithms.py b/src/cryptography/hazmat/primitives/ciphers/algorithms.py index ed72516611f3..b1c321941510 100644 --- a/src/cryptography/hazmat/primitives/ciphers/algorithms.py +++ b/src/cryptography/hazmat/primitives/ciphers/algorithms.py @@ -146,7 +146,9 @@ def __init__(self, key: bytes, nonce: bytes): self._nonce = nonce - nonce = utils.read_only_property("_nonce") + @property + def nonce(self) -> bytes: + return self._nonce @property def key_size(self) -> int: diff --git a/src/cryptography/hazmat/primitives/ciphers/modes.py b/src/cryptography/hazmat/primitives/ciphers/modes.py index 5265aad2378a..ec14412e53c4 100644 --- a/src/cryptography/hazmat/primitives/ciphers/modes.py +++ b/src/cryptography/hazmat/primitives/ciphers/modes.py @@ -51,7 +51,7 @@ def nonce(self) -> bytes: class ModeWithAuthenticationTag(metaclass=abc.ABCMeta): @abc.abstractproperty - def tag(self) -> bytes: + def tag(self) -> typing.Optional[bytes]: """ The value of the tag supplied to the constructor of this mode. """ @@ -92,7 +92,10 @@ def __init__(self, initialization_vector: bytes): utils._check_byteslike("initialization_vector", initialization_vector) self._initialization_vector = initialization_vector - initialization_vector = utils.read_only_property("_initialization_vector") + @property + def initialization_vector(self) -> bytes: + return self._initialization_vector + validate_for_algorithm = _check_iv_and_key_length @@ -107,7 +110,9 @@ def __init__(self, tweak: bytes): self._tweak = tweak - tweak = utils.read_only_property("_tweak") + @property + def tweak(self) -> bytes: + return self._tweak def validate_for_algorithm(self, algorithm: CipherAlgorithm): if algorithm.key_size not in (256, 512): @@ -130,7 +135,10 @@ def __init__(self, initialization_vector: bytes): utils._check_byteslike("initialization_vector", initialization_vector) self._initialization_vector = initialization_vector - initialization_vector = utils.read_only_property("_initialization_vector") + @property + def initialization_vector(self) -> bytes: + return self._initialization_vector + validate_for_algorithm = _check_iv_and_key_length @@ -141,7 +149,10 @@ def __init__(self, initialization_vector: bytes): utils._check_byteslike("initialization_vector", initialization_vector) self._initialization_vector = initialization_vector - initialization_vector = utils.read_only_property("_initialization_vector") + @property + def initialization_vector(self) -> bytes: + return self._initialization_vector + validate_for_algorithm = _check_iv_and_key_length @@ -152,7 +163,10 @@ def __init__(self, initialization_vector: bytes): utils._check_byteslike("initialization_vector", initialization_vector) self._initialization_vector = initialization_vector - initialization_vector = utils.read_only_property("_initialization_vector") + @property + def initialization_vector(self) -> bytes: + return self._initialization_vector + validate_for_algorithm = _check_iv_and_key_length @@ -163,7 +177,9 @@ def __init__(self, nonce: bytes): utils._check_byteslike("nonce", nonce) self._nonce = nonce - nonce = utils.read_only_property("_nonce") + @property + def nonce(self) -> bytes: + return self._nonce def validate_for_algorithm(self, algorithm: CipherAlgorithm): _check_aes_key_length(self, algorithm) @@ -203,8 +219,13 @@ def __init__( self._tag = tag self._min_tag_length = min_tag_length - tag = utils.read_only_property("_tag") - initialization_vector = utils.read_only_property("_initialization_vector") + @property + def tag(self) -> typing.Optional[bytes]: + return self._tag + + @property + def initialization_vector(self) -> bytes: + return self._initialization_vector def validate_for_algorithm(self, algorithm: CipherAlgorithm): _check_aes_key_length(self, algorithm) diff --git a/src/cryptography/hazmat/primitives/hashes.py b/src/cryptography/hazmat/primitives/hashes.py index 33907a35a7c5..4f92d6d271da 100644 --- a/src/cryptography/hazmat/primitives/hashes.py +++ b/src/cryptography/hazmat/primitives/hashes.py @@ -88,7 +88,9 @@ def __init__(self, algorithm: HashAlgorithm, backend=None, ctx=None): else: self._ctx = ctx - algorithm = utils.read_only_property("_algorithm") + @property + def algorithm(self) -> HashAlgorithm: + return self._algorithm def update(self, data: bytes) -> None: if self._ctx is None: @@ -190,7 +192,9 @@ def __init__(self, digest_size: int): self._digest_size = digest_size - digest_size = utils.read_only_property("_digest_size") + @property + def digest_size(self) -> int: + return self._digest_size class SHAKE256(HashAlgorithm, ExtendableOutputFunction): @@ -206,7 +210,9 @@ def __init__(self, digest_size: int): self._digest_size = digest_size - digest_size = utils.read_only_property("_digest_size") + @property + def digest_size(self) -> int: + return self._digest_size class MD5(HashAlgorithm): @@ -228,7 +234,9 @@ def __init__(self, digest_size: int): self._digest_size = digest_size - digest_size = utils.read_only_property("_digest_size") + @property + def digest_size(self) -> int: + return self._digest_size class BLAKE2s(HashAlgorithm): @@ -244,4 +252,6 @@ def __init__(self, digest_size: int): self._digest_size = digest_size - digest_size = utils.read_only_property("_digest_size") + @property + def digest_size(self) -> int: + return self._digest_size diff --git a/src/cryptography/hazmat/primitives/hmac.py b/src/cryptography/hazmat/primitives/hmac.py index 5911925b8bdc..927fb87bdf53 100644 --- a/src/cryptography/hazmat/primitives/hmac.py +++ b/src/cryptography/hazmat/primitives/hmac.py @@ -40,7 +40,9 @@ def __init__( else: self._ctx = ctx - algorithm = utils.read_only_property("_algorithm") + @property + def algorithm(self) -> hashes.HashAlgorithm: + return self._algorithm def update(self, data: bytes) -> None: if self._ctx is None: diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index 6cae016a1c60..94072aab7f3f 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -164,7 +164,9 @@ def __hash__(self): def __repr__(self): return "".format(self.crl_number) - crl_number = utils.read_only_property("_crl_number") + @property + def crl_number(self) -> int: + return self._crl_number class AuthorityKeyIdentifier(ExtensionType): @@ -255,11 +257,19 @@ def __hash__(self): (self.key_identifier, aci, self.authority_cert_serial_number) ) - key_identifier = utils.read_only_property("_key_identifier") - authority_cert_issuer = utils.read_only_property("_authority_cert_issuer") - authority_cert_serial_number = utils.read_only_property( - "_authority_cert_serial_number" - ) + @property + def key_identifier(self) -> typing.Optional[bytes]: + return self._key_identifier + + @property + def authority_cert_issuer( + self, + ) -> typing.Optional[typing.List[GeneralName]]: + return self._authority_cert_issuer + + @property + def authority_cert_serial_number(self) -> typing.Optional[int]: + return self._authority_cert_serial_number class SubjectKeyIdentifier(ExtensionType): @@ -274,7 +284,9 @@ def from_public_key( ) -> "SubjectKeyIdentifier": return cls(_key_identifier_from_public_key(public_key)) - digest = utils.read_only_property("_digest") + @property + def digest(self) -> bytes: + return self._digest def __repr__(self): return "".format(self.digest) @@ -388,8 +400,13 @@ def __ne__(self, other): def __hash__(self): return hash((self.access_method, self.access_location)) - access_method = utils.read_only_property("_access_method") - access_location = utils.read_only_property("_access_location") + @property + def access_method(self) -> ObjectIdentifier: + return self._access_method + + @property + def access_location(self) -> GeneralName: + return self._access_location class BasicConstraints(ExtensionType): @@ -412,8 +429,13 @@ def __init__(self, ca: bool, path_length: typing.Optional[int]): self._ca = ca self._path_length = path_length - ca = utils.read_only_property("_ca") - path_length = utils.read_only_property("_path_length") + @property + def ca(self) -> bool: + return self._ca + + @property + def path_length(self) -> typing.Optional[int]: + return self._path_length def __repr__(self): return ( @@ -442,7 +464,9 @@ def __init__(self, crl_number: int): self._crl_number = crl_number - crl_number = utils.read_only_property("_crl_number") + @property + def crl_number(self) -> int: + return self._crl_number def __eq__(self, other): if not isinstance(other, DeltaCRLIndicator): @@ -548,7 +572,7 @@ def __init__( "least one must be None." ) - if full_name: + if full_name is not None: full_name = list(full_name) if not all(isinstance(x, GeneralName) for x in full_name): raise TypeError( @@ -561,7 +585,7 @@ def __init__( "relative_name must be a RelativeDistinguishedName" ) - if crl_issuer: + if crl_issuer is not None: crl_issuer = list(crl_issuer) if not all(isinstance(x, GeneralName) for x in crl_issuer): raise TypeError( @@ -628,10 +652,21 @@ def __hash__(self): return hash((fn, self.relative_name, self.reasons, crl_issuer)) - full_name = utils.read_only_property("_full_name") - relative_name = utils.read_only_property("_relative_name") - reasons = utils.read_only_property("_reasons") - crl_issuer = utils.read_only_property("_crl_issuer") + @property + def full_name(self) -> typing.Optional[typing.List[GeneralName]]: + return self._full_name + + @property + def relative_name(self) -> typing.Optional[RelativeDistinguishedName]: + return self._relative_name + + @property + def reasons(self) -> typing.Optional[typing.FrozenSet["ReasonFlags"]]: + return self._reasons + + @property + def crl_issuer(self) -> typing.Optional[typing.List[GeneralName]]: + return self._crl_issuer class ReasonFlags(Enum): @@ -703,12 +738,13 @@ def __hash__(self): (self.require_explicit_policy, self.inhibit_policy_mapping) ) - require_explicit_policy = utils.read_only_property( - "_require_explicit_policy" - ) - inhibit_policy_mapping = utils.read_only_property( - "_inhibit_policy_mapping" - ) + @property + def require_explicit_policy(self) -> typing.Optional[int]: + return self._require_explicit_policy + + @property + def inhibit_policy_mapping(self) -> typing.Optional[int]: + return self._inhibit_policy_mapping class CertificatePolicies(ExtensionType): @@ -755,7 +791,7 @@ def __init__( self._policy_identifier = policy_identifier - if policy_qualifiers: + if policy_qualifiers is not None: policy_qualifiers = list(policy_qualifiers) if not all( isinstance(x, (str, UserNotice)) for x in policy_qualifiers @@ -793,8 +829,15 @@ def __hash__(self): return hash((self.policy_identifier, pq)) - policy_identifier = utils.read_only_property("_policy_identifier") - policy_qualifiers = utils.read_only_property("_policy_qualifiers") + @property + def policy_identifier(self) -> ObjectIdentifier: + return self._policy_identifier + + @property + def policy_qualifiers( + self, + ) -> typing.Optional[typing.List[typing.Union[str, "UserNotice"]]]: + return self._policy_qualifiers class UserNotice(object): @@ -834,8 +877,13 @@ def __ne__(self, other): def __hash__(self): return hash((self.notice_reference, self.explicit_text)) - notice_reference = utils.read_only_property("_notice_reference") - explicit_text = utils.read_only_property("_explicit_text") + @property + def notice_reference(self) -> typing.Optional["NoticeReference"]: + return self._notice_reference + + @property + def explicit_text(self) -> typing.Optional[str]: + return self._explicit_text class NoticeReference(object): @@ -872,8 +920,13 @@ def __ne__(self, other): def __hash__(self): return hash((self.organization, tuple(self.notice_numbers))) - organization = utils.read_only_property("_organization") - notice_numbers = utils.read_only_property("_notice_numbers") + @property + def organization(self) -> typing.Optional[str]: + return self._organization + + @property + def notice_numbers(self) -> typing.List[int]: + return self._notice_numbers class ExtendedKeyUsage(ExtensionType): @@ -1019,7 +1072,9 @@ def __ne__(self, other): def __hash__(self): return hash(self.skip_certs) - skip_certs = utils.read_only_property("_skip_certs") + @property + def skip_certs(self) -> int: + return self._skip_certs class KeyUsage(ExtensionType): @@ -1053,13 +1108,33 @@ def __init__( self._encipher_only = encipher_only self._decipher_only = decipher_only - digital_signature = utils.read_only_property("_digital_signature") - content_commitment = utils.read_only_property("_content_commitment") - key_encipherment = utils.read_only_property("_key_encipherment") - data_encipherment = utils.read_only_property("_data_encipherment") - key_agreement = utils.read_only_property("_key_agreement") - key_cert_sign = utils.read_only_property("_key_cert_sign") - crl_sign = utils.read_only_property("_crl_sign") + @property + def digital_signature(self) -> bool: + return self._digital_signature + + @property + def content_commitment(self) -> bool: + return self._content_commitment + + @property + def key_encipherment(self) -> bool: + return self._key_encipherment + + @property + def data_encipherment(self) -> bool: + return self._data_encipherment + + @property + def key_agreement(self) -> bool: + return self._key_agreement + + @property + def key_cert_sign(self) -> bool: + return self._key_cert_sign + + @property + def crl_sign(self) -> bool: + return self._crl_sign @property def encipher_only(self): @@ -1216,8 +1291,17 @@ def __hash__(self): return hash((ps, es)) - permitted_subtrees = utils.read_only_property("_permitted_subtrees") - excluded_subtrees = utils.read_only_property("_excluded_subtrees") + @property + def permitted_subtrees( + self, + ) -> typing.Optional[typing.List[GeneralName]]: + return self._permitted_subtrees + + @property + def excluded_subtrees( + self, + ) -> typing.Optional[typing.List[GeneralName]]: + return self._excluded_subtrees class Extension(object): @@ -1236,9 +1320,17 @@ def __init__( self._critical = critical self._value = value - oid = utils.read_only_property("_oid") - critical = utils.read_only_property("_critical") - value = utils.read_only_property("_value") + @property + def oid(self) -> ObjectIdentifier: + return self._oid + + @property + def critical(self) -> bool: + return self._critical + + @property + def value(self) -> ExtensionType: + return self._value def __repr__(self): return ( @@ -1406,7 +1498,9 @@ def __ne__(self, other): def __hash__(self): return hash(self.reason) - reason = utils.read_only_property("_reason") + @property + def reason(self) -> ReasonFlags: + return self._reason class InvalidityDate(ExtensionType): @@ -1435,7 +1529,9 @@ def __ne__(self, other): def __hash__(self): return hash(self.invalidity_date) - invalidity_date = utils.read_only_property("_invalidity_date") + @property + def invalidity_date(self) -> datetime.datetime: + return self._invalidity_date class PrecertificateSignedCertificateTimestamps(ExtensionType): @@ -1550,7 +1646,9 @@ def __hash__(self): def __repr__(self): return "".format(self) - nonce = utils.read_only_property("_nonce") + @property + def nonce(self) -> bytes: + return self._nonce class IssuingDistributionPoint(ExtensionType): @@ -1701,8 +1799,13 @@ def __init__(self, oid: ObjectIdentifier, value: bytes): self._oid = oid self._value = value - oid = utils.read_only_property("_oid") - value = utils.read_only_property("_value") + @property + def oid(self) -> ObjectIdentifier: + return self._oid + + @property + def value(self) -> bytes: + return self._value def __repr__(self): return ( diff --git a/src/cryptography/x509/general_name.py b/src/cryptography/x509/general_name.py index a83471e93131..e9495909018b 100644 --- a/src/cryptography/x509/general_name.py +++ b/src/cryptography/x509/general_name.py @@ -8,7 +8,6 @@ import typing from email.utils import parseaddr -from cryptography import utils from cryptography.x509.name import Name from cryptography.x509.oid import ObjectIdentifier @@ -62,7 +61,9 @@ def __init__(self, value: str): self._value = value - value = utils.read_only_property("_value") + @property + def value(self) -> str: + return self._value @classmethod def _init_without_validation(cls, value): @@ -102,7 +103,9 @@ def __init__(self, value: str): self._value = value - value = utils.read_only_property("_value") + @property + def value(self) -> str: + return self._value @classmethod def _init_without_validation(cls, value): @@ -142,7 +145,9 @@ def __init__(self, value: str): self._value = value - value = utils.read_only_property("_value") + @property + def value(self) -> str: + return self._value @classmethod def _init_without_validation(cls, value): @@ -173,7 +178,9 @@ def __init__(self, value: Name): self._value = value - value = utils.read_only_property("_value") + @property + def value(self) -> Name: + return self._value def __repr__(self) -> str: return "".format(self.value) @@ -198,7 +205,9 @@ def __init__(self, value: ObjectIdentifier): self._value = value - value = utils.read_only_property("_value") + @property + def value(self) -> ObjectIdentifier: + return self._value def __repr__(self) -> str: return "".format(self.value) @@ -243,7 +252,16 @@ def __init__( self._value = value - value = utils.read_only_property("_value") + @property + def value( + self, + ) -> typing.Union[ + ipaddress.IPv4Address, + ipaddress.IPv6Address, + ipaddress.IPv4Network, + ipaddress.IPv6Network, + ]: + return self._value def __repr__(self) -> str: return "".format(self.value) @@ -271,8 +289,13 @@ def __init__(self, type_id: ObjectIdentifier, value: bytes): self._type_id = type_id self._value = value - type_id = utils.read_only_property("_type_id") - value = utils.read_only_property("_value") + @property + def type_id(self) -> ObjectIdentifier: + return self._type_id + + @property + def value(self) -> bytes: + return self._value def __repr__(self) -> str: return "".format( diff --git a/src/cryptography/x509/name.py b/src/cryptography/x509/name.py index a579aa219638..2d506f73bb39 100644 --- a/src/cryptography/x509/name.py +++ b/src/cryptography/x509/name.py @@ -5,7 +5,6 @@ import typing from enum import Enum -from cryptography import utils from cryptography.hazmat.backends import _get_backend from cryptography.x509.oid import NameOID, ObjectIdentifier @@ -108,8 +107,13 @@ def __init__(self, oid: ObjectIdentifier, value: str, _type=_SENTINEL): self._value = value self._type = _type - oid = utils.read_only_property("_oid") - value = utils.read_only_property("_value") + @property + def oid(self) -> ObjectIdentifier: + return self._oid + + @property + def value(self) -> str: + return self._value def rfc4514_string(self) -> str: """ @@ -220,7 +224,7 @@ def get_attributes_for_oid(self, oid) -> typing.List[NameAttribute]: return [i for i in self if i.oid == oid] @property - def rdns(self) -> typing.Iterable[RelativeDistinguishedName]: + def rdns(self) -> typing.List[RelativeDistinguishedName]: return self._attributes def public_bytes(self, backend=None) -> bytes: diff --git a/tests/x509/test_x509_crlbuilder.py b/tests/x509/test_x509_crlbuilder.py index cbf0b073b5a5..88725710d7fd 100644 --- a/tests/x509/test_x509_crlbuilder.py +++ b/tests/x509/test_x509_crlbuilder.py @@ -366,6 +366,7 @@ def test_freshestcrl_extension(self, backend): ext1 = crl.extensions.get_extension_for_class(x509.FreshestCRL) assert ext1.critical is False assert isinstance(ext1.value[0], x509.DistributionPoint) + assert ext1.value[0].full_name is not None uri = ext1.value[0].full_name[0] assert isinstance(uri, x509.UniformResourceIdentifier) assert uri.value == "http://d.om/delta" diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index b8f226d5f848..41a35e264b24 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -517,6 +517,7 @@ def test_invalid_policy_identifiers(self): def test_iter_input(self): qual = ["foo", "bar"] pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), iter(qual)) + assert pi.policy_qualifiers is not None assert list(pi.policy_qualifiers) == qual def test_repr(self): @@ -1104,6 +1105,7 @@ def test_iter_input(self): ) ] aki = x509.AuthorityKeyIdentifier(b"digest", iter(dirnames), 1234) + assert aki.authority_cert_issuer is not None assert list(aki.authority_cert_issuer) == dirnames def test_repr(self): @@ -3429,7 +3431,9 @@ def test_excluded_none(self): def test_iter_input(self): subtrees = [x509.IPAddress(ipaddress.IPv4Network("192.168.0.0/24"))] nc = x509.NameConstraints(iter(subtrees), iter(subtrees)) + assert nc.permitted_subtrees is not None assert list(nc.permitted_subtrees) == subtrees + assert nc.excluded_subtrees is not None assert list(nc.excluded_subtrees) == subtrees def test_repr(self): @@ -3781,7 +3785,9 @@ def test_iter_input(self): frozenset([x509.ReasonFlags.ca_compromise]), iter(issuer), ) + assert dp.full_name is not None assert list(dp.full_name) == name + assert dp.crl_issuer is not None assert list(dp.crl_issuer) == issuer def test_repr(self): From 4f48f39543a09eb336f3ccc053006cdd029ab22f Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 15 Feb 2021 22:19:18 -0600 Subject: [PATCH 0139/2380] test against libre 3.2.4 (#5835) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e599991971ce..77ddfd8b99b9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "2.9.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.0.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.1.5"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.2.3"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.2.4"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.3.1"}} RUST: - stable From ade36103176145fa774050c5ff9f73b03b28187d Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 16 Feb 2021 08:54:16 -0500 Subject: [PATCH 0140/2380] protect against integer overfows in release rust (#5836) this would have categorically prevented CVE-2020-36242 --- src/rust/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 8d154fbbe48d..bcb9add10020 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -14,3 +14,4 @@ crate-type = ["cdylib"] [profile.release] lto = "thin" +overflow-checks = true From 208b95dac29e53224f20f8ddfc6783a7a8576934 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 16 Feb 2021 11:56:59 -0500 Subject: [PATCH 0141/2380] update here too (#5839) --- .github/ISSUE_TEMPLATE/openssl-release.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/openssl-release.md b/.github/ISSUE_TEMPLATE/openssl-release.md index 336953722fb2..c9ee70436bac 100644 --- a/.github/ISSUE_TEMPLATE/openssl-release.md +++ b/.github/ISSUE_TEMPLATE/openssl-release.md @@ -1,7 +1,7 @@ - [ ] Windows, macOS, `manylinux` - - [ ] Send a pull request to `pyca/infra` updating the [version and hash](https://github.com/pyca/infra/blob/master/cryptography-manylinux/openssl-version.sh) + - [ ] Send a pull request to `pyca/infra` updating the [version and hash](https://github.com/pyca/infra/blob/main/cryptography-manylinux/openssl-version.sh) - [ ] Wait for it to be merged - [ ] Wait for the Github Actions job to complete - [ ] Changelog entry - [ ] Release -- [ ] Forward port changelog entry (if releasing from release branch) \ No newline at end of file +- [ ] Forward port changelog entry (if releasing from release branch) From 21f1bc607a311c4974c7d4f9a93a0a8b4eaad621 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 16 Feb 2021 11:57:18 -0500 Subject: [PATCH 0142/2380] Update for branch name change (#5838) --- .github/workflows/download_openssl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/download_openssl.py b/.github/workflows/download_openssl.py index 46b3b7f0ee02..496e05385b0e 100644 --- a/.github/workflows/download_openssl.py +++ b/.github/workflows/download_openssl.py @@ -51,7 +51,7 @@ def main(platform, target): print("Looking for: {}".format(target)) runs_url = ( "https://api.github.com/repos/pyca/infra/actions/workflows/" - "{}/runs?branch=master&status=success".format(workflow) + "{}/runs?branch=main&status=success".format(workflow) ) response = get_response(session, runs_url, token).json() From c37a445a19b4c293047d0e9d77dc39b9ff9972c4 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 16 Feb 2021 15:12:41 -0600 Subject: [PATCH 0143/2380] 1.1.1j in more places (#5841) --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 77ddfd8b99b9..026a5020178f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,9 +18,9 @@ jobs: - {VERSION: "3.9", TOXENV: "flake,rust,docs", COVERAGE: "false"} - {VERSION: "pypy3", TOXENV: "pypy3"} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1i"}} - - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1i"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1i", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1j"}} + - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1j"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1j", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "2.9.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.0.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.1.5"}} From 9a2e1dfacd54fbae855a5fcc85857548b4ba2617 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 16 Feb 2021 16:18:35 -0600 Subject: [PATCH 0144/2380] port 3.4.6 changelog (#5842) * port 3.4.6 changelog Also link CVE-2020-36242 to CVE-2021-23840 since our 3.3.2 security fix is just a workaround for the OpenSSL issue. * Update CHANGELOG.rst Co-authored-by: Alex Gaynor Co-authored-by: Alex Gaynor --- CHANGELOG.rst | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 91e50b278243..8a7a663c76d8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,14 @@ Changelog .. note:: This version is not yet released and is under active development. +.. _v3-4-6: + +3.4.6 - 2021-02-16 +~~~~~~~~~~~~~~~~~~ + +* Updated Windows, macOS, and ``manylinux`` wheels to be compiled with + OpenSSL 1.1.1j. + .. _v3-4-5: 3.4.5 - 2021-02-13 @@ -80,7 +88,9 @@ Changelog * **SECURITY ISSUE:** Fixed a bug where certain sequences of ``update()`` calls when symmetrically encrypting very large payloads (>2GB) could result in an - integer overflow, leading to buffer overflows. *CVE-2020-36242* + integer overflow, leading to buffer overflows. *CVE-2020-36242* **Update:** + This fix is a workaround for *CVE-2021-23840* in OpenSSL, fixed in OpenSSL + 1.1.1j. .. _v3-3-1: From 577e058798e0e6ae04eac07f958f1072e351e859 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 18 Feb 2021 16:57:43 -0600 Subject: [PATCH 0145/2380] Strict is deprecated (#5846) * Strict is deprecated * bump pytest dep --- setup.py | 2 +- tox.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 74f69e7148a6..e448479caa19 100644 --- a/setup.py +++ b/setup.py @@ -110,7 +110,7 @@ setup_requires=setup_requirements, extras_require={ "test": [ - "pytest>=6.0", + "pytest>=6.2.0", "pytest-cov", "pytest-subtests", "pytest-xdist", diff --git a/tox.ini b/tox.ini index 93f4b253ab8d..3130777c6c47 100644 --- a/tox.ini +++ b/tox.ini @@ -14,7 +14,7 @@ deps = passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH USERNAME PYTHONIOENCODING OPENSSL_FORCE_FIPS_MODE commands = pip list - pytest -n auto --cov=cryptography --cov=tests --capture=no --strict --durations=10 {posargs} + pytest -n auto --cov=cryptography --cov=tests --capture=no --strict-markers --durations=10 {posargs} [testenv:docs] extras = From 770e3d18954483f6bc90d5166552a309b7a22c85 Mon Sep 17 00:00:00 2001 From: Robert Martin Date: Sat, 20 Feb 2021 07:56:55 -0600 Subject: [PATCH 0146/2380] Fix typo in error messages: can not => cannot (#5851) --- src/cryptography/hazmat/primitives/kdf/concatkdf.py | 2 +- src/cryptography/hazmat/primitives/kdf/hkdf.py | 2 +- src/cryptography/hazmat/primitives/kdf/x963kdf.py | 2 +- tests/hazmat/primitives/test_rsa.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cryptography/hazmat/primitives/kdf/concatkdf.py b/src/cryptography/hazmat/primitives/kdf/concatkdf.py index 4b7fce878acb..6ec4cbd372b4 100644 --- a/src/cryptography/hazmat/primitives/kdf/concatkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/concatkdf.py @@ -32,7 +32,7 @@ def _common_args_checks( max_length = algorithm.digest_size * (2 ** 32 - 1) if length > max_length: raise ValueError( - "Can not derive keys larger than {} bits.".format(max_length) + "Cannot derive keys larger than {} bits.".format(max_length) ) if otherinfo is not None: utils._check_bytes("otherinfo", otherinfo) diff --git a/src/cryptography/hazmat/primitives/kdf/hkdf.py b/src/cryptography/hazmat/primitives/kdf/hkdf.py index 9a05a139265b..6b65b0c0717b 100644 --- a/src/cryptography/hazmat/primitives/kdf/hkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/hkdf.py @@ -84,7 +84,7 @@ def __init__( if length > max_length: raise ValueError( - "Can not derive keys larger than {} octets.".format(max_length) + "Cannot derive keys larger than {} octets.".format(max_length) ) self._length = length diff --git a/src/cryptography/hazmat/primitives/kdf/x963kdf.py b/src/cryptography/hazmat/primitives/kdf/x963kdf.py index 21a47f665ff3..1a67d3ee0c4f 100644 --- a/src/cryptography/hazmat/primitives/kdf/x963kdf.py +++ b/src/cryptography/hazmat/primitives/kdf/x963kdf.py @@ -36,7 +36,7 @@ def __init__( max_len = algorithm.digest_size * (2 ** 32 - 1) if length > max_len: raise ValueError( - "Can not derive keys larger than {} bits.".format(max_len) + "Cannot derive keys larger than {} bits.".format(max_len) ) if sharedinfo is not None: utils._check_bytes("sharedinfo", sharedinfo) diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 6d2f32145a27..46f011f477dc 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -1023,7 +1023,7 @@ def test_invalid_pss_signature_recover(self, backend): ) signature = private_key.sign(b"sign me", pss_padding, hashes.SHA1()) - # Hash algorithm can not be absent for PSS padding + # Hash algorithm cannot be absent for PSS padding with pytest.raises(TypeError): public_key.recover_data_from_signature( signature, pss_padding, None # type: ignore[arg-type] From 2b94360394a4fa177701954f96f864cfa7c65b9f Mon Sep 17 00:00:00 2001 From: Mathias Ertl Date: Sat, 20 Feb 2021 16:38:56 +0100 Subject: [PATCH 0147/2380] make Extension a generic class (fixes #5830) (#5831) --- .../hazmat/backends/openssl/decode_asn1.py | 3 ++- src/cryptography/x509/extensions.py | 14 +++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 167acc078743..e62c25406b39 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -5,6 +5,7 @@ import datetime import ipaddress +import typing from cryptography import x509 from cryptography.hazmat._der import DERReader, INTEGER, NULL, SEQUENCE @@ -185,7 +186,7 @@ def __init__(self, backend, ext_count, get_ext, handlers): self._backend = backend def parse(self, x509_obj): - extensions = [] + extensions: typing.List[x509.Extension[x509.ExtensionType]] = [] seen_oids = set() for i in range(self.ext_count(x509_obj)): ext = self.get_ext(x509_obj, i) diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index 94072aab7f3f..95e3a9f39d45 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -33,6 +33,8 @@ ObjectIdentifier, ) +ExtensionTypeVar = typing.TypeVar("ExtensionTypeVar", bound="ExtensionType") + def _key_identifier_from_public_key(public_key: _PUBLIC_KEY_TYPES) -> bytes: if isinstance(public_key, RSAPublicKey): @@ -108,17 +110,19 @@ def oid(self) -> ObjectIdentifier: class Extensions(object): - def __init__(self, extensions: typing.List["Extension"]): + def __init__(self, extensions: typing.List["Extension[ExtensionType]"]): self._extensions = extensions - def get_extension_for_oid(self, oid: ObjectIdentifier) -> "Extension": + def get_extension_for_oid( + self, oid: ObjectIdentifier + ) -> "Extension[ExtensionType]": for ext in self: if ext.oid == oid: return ext raise ExtensionNotFound("No {} extension was found".format(oid), oid) - def get_extension_for_class(self, extclass) -> "Extension": + def get_extension_for_class(self, extclass) -> "Extension[ExtensionType]": if extclass is UnrecognizedExtension: raise TypeError( "UnrecognizedExtension can't be used with " @@ -1304,9 +1308,9 @@ def excluded_subtrees( return self._excluded_subtrees -class Extension(object): +class Extension(typing.Generic[ExtensionTypeVar]): def __init__( - self, oid: ObjectIdentifier, critical: bool, value: ExtensionType + self, oid: ObjectIdentifier, critical: bool, value: ExtensionTypeVar ): if not isinstance(oid, ObjectIdentifier): raise TypeError( From 540a9828cc704abf3ebad7ee5b56852cf25e5aaa Mon Sep 17 00:00:00 2001 From: Arnaud Durand Date: Sun, 21 Feb 2021 19:36:24 +0100 Subject: [PATCH 0148/2380] Add key_identifier property to SubjectKeyIdentifier (#5849) Fix #5848 --- docs/x509/reference.rst | 9 +++++++++ src/cryptography/x509/extensions.py | 4 ++++ tests/x509/test_x509_ext.py | 1 + 3 files changed, 14 insertions(+) diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst index c6eba06f881e..df09af148926 100644 --- a/docs/x509/reference.rst +++ b/docs/x509/reference.rst @@ -1945,6 +1945,15 @@ X.509 Extensions Returns :attr:`~cryptography.x509.oid.ExtensionOID.SUBJECT_KEY_IDENTIFIER`. + .. attribute:: key_identifier + + .. versionadded:: 35.0.0 + + :type: bytes + + A value derived from the public key used to verify the certificate's + signature. + .. attribute:: digest :type: bytes diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index 95e3a9f39d45..aad8bcfd9c5b 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -292,6 +292,10 @@ def from_public_key( def digest(self) -> bytes: return self._digest + @property + def key_identifier(self) -> bytes: + return self._digest + def __repr__(self): return "".format(self.digest) diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index 41a35e264b24..f74f3d5a5f56 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -994,6 +994,7 @@ def test_properties(self): value = binascii.unhexlify(b"092384932230498bc980aa8098456f6ff7ff3ac9") ski = x509.SubjectKeyIdentifier(value) assert ski.digest == value + assert ski.key_identifier == value def test_repr(self): ski = x509.SubjectKeyIdentifier( From d7fcfb5a0a692d32df0283b95b0bcfdca9f71db9 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 21 Feb 2021 13:26:04 -0600 Subject: [PATCH 0149/2380] simplify docs a bit (#5855) --- docs/x509/reference.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst index df09af148926..216896f045cc 100644 --- a/docs/x509/reference.rst +++ b/docs/x509/reference.rst @@ -1951,14 +1951,13 @@ X.509 Extensions :type: bytes - A value derived from the public key used to verify the certificate's - signature. + The binary value of the identifier. .. attribute:: digest :type: bytes - The binary value of the identifier. + The binary value of the identifier. An alias of ``key_identifier``. .. classmethod:: from_public_key(public_key) From f1127596560211661d5deb42afafa1993a6338e6 Mon Sep 17 00:00:00 2001 From: Mathias Ertl Date: Sun, 21 Feb 2021 20:26:24 +0100 Subject: [PATCH 0150/2380] add typehint for name (#5856) --- src/cryptography/hazmat/_oid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptography/hazmat/_oid.py b/src/cryptography/hazmat/_oid.py index 3e22ea9f284e..84268b8dea45 100644 --- a/src/cryptography/hazmat/_oid.py +++ b/src/cryptography/hazmat/_oid.py @@ -64,7 +64,7 @@ def __hash__(self): return hash(self.dotted_string) @property - def _name(self): + def _name(self) -> str: # Lazy import to avoid an import cycle from cryptography.x509.oid import _OID_NAMES From 82a12a54b602c994cd0361d1b95bcb4047d67a31 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 21 Feb 2021 14:28:00 -0500 Subject: [PATCH 0151/2380] Convert unpadding code to Rust (#5668) --- docs/faq.rst | 5 -- mypy.ini | 2 +- setup.py | 36 +++----- src/_cffi_src/build_padding.py | 26 ------ src/_cffi_src/hazmat_src/padding.c | 65 -------------- src/_cffi_src/hazmat_src/padding.h | 6 -- src/cryptography/hazmat/primitives/padding.py | 13 +-- src/rust/src/lib.rs | 85 ++++++++++++++++++- tox.ini | 1 + 9 files changed, 106 insertions(+), 133 deletions(-) delete mode 100644 src/_cffi_src/build_padding.py delete mode 100644 src/_cffi_src/hazmat_src/padding.c delete mode 100644 src/_cffi_src/hazmat_src/padding.h diff --git a/docs/faq.rst b/docs/faq.rst index c43396cf911e..cfa2952fec29 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -132,11 +132,6 @@ need to have Rust installed after you've built ``cryptography``. This is the same as the C compiler toolchain which is also required to build ``cryptography``, but not afterwards. -For the current release *only* you can temporarily bypass the requirement to -have Rust installed by setting the ``CRYPTOGRAPHY_DONT_BUILD_RUST`` environment -variable. Note that this option will be removed in the next release and not -having Rust available will be a hard error. - Why are there no wheels for my Python3.x version? ------------------------------------------------- diff --git a/mypy.ini b/mypy.ini index bf4cc82270c9..a1755b1fe0be 100644 --- a/mypy.ini +++ b/mypy.ini @@ -4,7 +4,7 @@ check_untyped_defs = True [mypy-cryptography.hazmat.bindings._openssl] ignore_missing_imports = True -[mypy-cryptography.hazmat.bindings._padding] +[mypy-cryptography.hazmat.bindings._rust] ignore_missing_imports = True [mypy-iso8601] diff --git a/setup.py b/setup.py index e448479caa19..f524c2be3d03 100644 --- a/setup.py +++ b/setup.py @@ -45,24 +45,6 @@ install_requirements = ["cffi>=1.12"] setup_requirements = install_requirements + [setuptools_rust] -if os.environ.get("CRYPTOGRAPHY_DONT_BUILD_RUST"): - rust_extensions = [] -else: - rust_extensions = [ - RustExtension( - "_rust", - "src/rust/Cargo.toml", - py_limited_api=True, - # Enable abi3 mode if we're not using PyPy. - features=( - [] - if platform.python_implementation() == "PyPy" - else ["pyo3/abi3-py36"] - ), - rust_version=">=1.41.0", - ) - ] - with open(os.path.join(base_dir, "README.rst")) as f: long_description = f.read() @@ -147,9 +129,21 @@ ext_package="cryptography.hazmat.bindings", cffi_modules=[ "src/_cffi_src/build_openssl.py:ffi", - "src/_cffi_src/build_padding.py:ffi", ], - rust_extensions=rust_extensions, + rust_extensions=[ + RustExtension( + "_rust", + "src/rust/Cargo.toml", + py_limited_api=True, + # Enable abi3 mode if we're not using PyPy. + features=( + [] + if platform.python_implementation() == "PyPy" + else ["pyo3/abi3-py36"] + ), + rust_version=">=1.41.0", + ) + ], ) except: # noqa: E722 # Note: This is a bare exception that re-raises so that we don't interfere @@ -172,8 +166,6 @@ https://cryptography.io/en/latest/faq.html 4) Ensure you have a recent Rust toolchain installed: https://cryptography.io/en/latest/installation.html#rust - 5) If you are experiencing issues with Rust for *this release only* you may - set the environment variable `CRYPTOGRAPHY_DONT_BUILD_RUST=1`. =============================DEBUG ASSISTANCE============================= """ ) diff --git a/src/_cffi_src/build_padding.py b/src/_cffi_src/build_padding.py deleted file mode 100644 index 61f36ef69109..000000000000 --- a/src/_cffi_src/build_padding.py +++ /dev/null @@ -1,26 +0,0 @@ -# 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. - - -import os - -from _cffi_src.utils import build_ffi, compiler_type, extra_link_args - - -with open( - os.path.join(os.path.dirname(__file__), "hazmat_src/padding.h") -) as f: - types = f.read() - -with open( - os.path.join(os.path.dirname(__file__), "hazmat_src/padding.c") -) as f: - functions = f.read() - -ffi = build_ffi( - module_name="_padding", - cdef_source=types, - verify_source=functions, - extra_link_args=extra_link_args(compiler_type()), -) diff --git a/src/_cffi_src/hazmat_src/padding.c b/src/_cffi_src/hazmat_src/padding.c deleted file mode 100644 index a6e05dee1e39..000000000000 --- a/src/_cffi_src/hazmat_src/padding.c +++ /dev/null @@ -1,65 +0,0 @@ -// 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. - -/* Returns the value of the input with the most-significant-bit copied to all - of the bits. */ -static uint16_t Cryptography_DUPLICATE_MSB_TO_ALL(uint16_t a) { - return (1 - (a >> (sizeof(uint16_t) * 8 - 1))) - 1; -} - -/* This returns 0xFFFF if a < b else 0x0000, but does so in a constant time - fashion */ -static uint16_t Cryptography_constant_time_lt(uint16_t a, uint16_t b) { - a -= b; - return Cryptography_DUPLICATE_MSB_TO_ALL(a); -} - -uint8_t Cryptography_check_pkcs7_padding(const uint8_t *data, - uint16_t block_len) { - uint16_t i; - uint16_t pad_size = data[block_len - 1]; - uint16_t mismatch = 0; - for (i = 0; i < block_len; i++) { - unsigned int mask = Cryptography_constant_time_lt(i, pad_size); - uint16_t b = data[block_len - 1 - i]; - mismatch |= (mask & (pad_size ^ b)); - } - - /* Check to make sure the pad_size was within the valid range. */ - mismatch |= ~Cryptography_constant_time_lt(0, pad_size); - mismatch |= Cryptography_constant_time_lt(block_len, pad_size); - - /* Make sure any bits set are copied to the lowest bit */ - mismatch |= mismatch >> 8; - mismatch |= mismatch >> 4; - mismatch |= mismatch >> 2; - mismatch |= mismatch >> 1; - /* Now check the low bit to see if it's set */ - return (mismatch & 1) == 0; -} - -uint8_t Cryptography_check_ansix923_padding(const uint8_t *data, - uint16_t block_len) { - uint16_t i; - uint16_t pad_size = data[block_len - 1]; - uint16_t mismatch = 0; - /* Skip the first one with the pad size */ - for (i = 1; i < block_len; i++) { - unsigned int mask = Cryptography_constant_time_lt(i, pad_size); - uint16_t b = data[block_len - 1 - i]; - mismatch |= (mask & b); - } - - /* Check to make sure the pad_size was within the valid range. */ - mismatch |= ~Cryptography_constant_time_lt(0, pad_size); - mismatch |= Cryptography_constant_time_lt(block_len, pad_size); - - /* Make sure any bits set are copied to the lowest bit */ - mismatch |= mismatch >> 8; - mismatch |= mismatch >> 4; - mismatch |= mismatch >> 2; - mismatch |= mismatch >> 1; - /* Now check the low bit to see if it's set */ - return (mismatch & 1) == 0; -} diff --git a/src/_cffi_src/hazmat_src/padding.h b/src/_cffi_src/hazmat_src/padding.h deleted file mode 100644 index fb023c171108..000000000000 --- a/src/_cffi_src/hazmat_src/padding.h +++ /dev/null @@ -1,6 +0,0 @@ -// 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. - -uint8_t Cryptography_check_pkcs7_padding(const uint8_t *, uint8_t); -uint8_t Cryptography_check_ansix923_padding(const uint8_t *, uint8_t); diff --git a/src/cryptography/hazmat/primitives/padding.py b/src/cryptography/hazmat/primitives/padding.py index e6f46eb4fa0b..ccfde74049e7 100644 --- a/src/cryptography/hazmat/primitives/padding.py +++ b/src/cryptography/hazmat/primitives/padding.py @@ -8,7 +8,10 @@ from cryptography import utils from cryptography.exceptions import AlreadyFinalized -from cryptography.hazmat.bindings._padding import lib +from cryptography.hazmat.bindings._rust import ( + check_ansix923_padding, + check_pkcs7_padding, +) class PaddingContext(metaclass=abc.ABCMeta): @@ -84,7 +87,7 @@ def _byte_unpadding_update( def _byte_unpadding_check( buffer_: typing.Optional[bytes], block_size: int, - checkfn: typing.Callable[[bytes, int], int], + checkfn: typing.Callable[[bytes], int], ) -> bytes: if buffer_ is None: raise AlreadyFinalized("Context was already finalized.") @@ -92,7 +95,7 @@ def _byte_unpadding_check( if len(buffer_) != block_size // 8: raise ValueError("Invalid padding bytes.") - valid = checkfn(buffer_, block_size // 8) + valid = checkfn(buffer_) if not valid: raise ValueError("Invalid padding bytes.") @@ -154,7 +157,7 @@ def update(self, data: bytes) -> bytes: def finalize(self) -> bytes: result = _byte_unpadding_check( - self._buffer, self.block_size, lib.Cryptography_check_pkcs7_padding + self._buffer, self.block_size, check_pkcs7_padding ) self._buffer = None return result @@ -215,7 +218,7 @@ def finalize(self) -> bytes: result = _byte_unpadding_check( self._buffer, self.block_size, - lib.Cryptography_check_ansix923_padding, + check_ansix923_padding, ) self._buffer = None return result diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs index 1580ca4fcef7..3257b35e123f 100644 --- a/src/rust/src/lib.rs +++ b/src/rust/src/lib.rs @@ -2,9 +2,88 @@ // 2.0, and the BSD License. See the LICENSE file in the root of this repository // for complete details. +use std::convert::TryInto; + +/// Returns the value of the input with the most-significant-bit copied to all +/// of the bits. +fn duplicate_msb_to_all(a: u8) -> u8 { + 0u8.wrapping_sub(a >> 7) +} + +/// This returns 0xFF if a < b else 0x00, but does so in a constant time +/// fashion. +fn constant_time_lt(a: u8, b: u8) -> u8 { + // Derived from: + // https://github.com/openssl/openssl/blob/OpenSSL_1_1_1i/include/internal/constant_time.h#L120 + duplicate_msb_to_all(a ^ ((a ^ b) | (a.wrapping_sub(b) ^ b))) +} + +#[pyo3::prelude::pyfunction] +fn check_pkcs7_padding(data: &[u8]) -> bool { + let mut mismatch = 0; + let pad_size = *data.last().unwrap(); + let len: u8 = data.len().try_into().expect("data too long"); + for (i, b) in (0..len).zip(data.iter().rev()) { + let mask = constant_time_lt(i, pad_size); + mismatch |= mask & (pad_size ^ b); + } + + // Check to make sure the pad_size was within the valid range. + mismatch |= !constant_time_lt(0, pad_size); + mismatch |= constant_time_lt(len, pad_size); + + // Make sure any bits set are copied to the lowest bit + mismatch |= mismatch >> 4; + mismatch |= mismatch >> 2; + mismatch |= mismatch >> 1; + + // Now check the low bit to see if it's set + (mismatch & 1) == 0 +} + +#[pyo3::prelude::pyfunction] +fn check_ansix923_padding(data: &[u8]) -> bool { + let mut mismatch = 0; + let pad_size = *data.last().unwrap(); + let len: u8 = data.len().try_into().expect("data too long"); + // Skip the first one with the pad size + for (i, b) in (1..len).zip(data[..data.len() - 1].iter().rev()) { + let mask = constant_time_lt(i, pad_size); + mismatch |= mask & b; + } + + // Check to make sure the pad_size was within the valid range. + mismatch |= !constant_time_lt(0, pad_size); + mismatch |= constant_time_lt(len, pad_size); + + // Make sure any bits set are copied to the lowest bit + mismatch |= mismatch >> 4; + mismatch |= mismatch >> 2; + mismatch |= mismatch >> 1; + + // Now check the low bit to see if it's set + (mismatch & 1) == 0 +} + #[pyo3::prelude::pymodule] -// False positive: https://github.com/rust-lang/rust-clippy/issues/6721 -#[allow(clippy::unnecessary_wraps)] -fn _rust(_py: pyo3::Python<'_>, _m: &pyo3::types::PyModule) -> pyo3::PyResult<()> { +fn _rust(_py: pyo3::Python<'_>, m: &pyo3::types::PyModule) -> pyo3::PyResult<()> { + m.add_function(pyo3::wrap_pyfunction!(check_pkcs7_padding, m)?)?; + m.add_function(pyo3::wrap_pyfunction!(check_ansix923_padding, m)?)?; + Ok(()) } + +#[cfg(test)] +mod tests { + use super::constant_time_lt; + + #[test] + fn test_constant_time_lt() { + for a in 0..=255 { + for b in 0..=255 { + let expected = if a < b { 0xff } else { 0 }; + assert_eq!(constant_time_lt(a, b), expected); + } + } + } +} diff --git a/tox.ini b/tox.ini index 3130777c6c47..bdc4da283493 100644 --- a/tox.ini +++ b/tox.ini @@ -61,6 +61,7 @@ allowlist_externals = commands = cargo fmt --all -- --check cargo clippy -- -D warnings + cargo test [flake8] ignore = E203,E211,W503,W504 From 8928e8e1d2fd3fcc8f8fb0738a45aa16b0ec570c Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 21 Feb 2021 16:11:34 -0600 Subject: [PATCH 0152/2380] test pypy3.6 and pypy3.7 (#5857) --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 026a5020178f..e68f089a73af 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,8 @@ jobs: matrix: PYTHON: - {VERSION: "3.9", TOXENV: "flake,rust,docs", COVERAGE: "false"} - - {VERSION: "pypy3", TOXENV: "pypy3"} + - {VERSION: "pypy-3.6", TOXENV: "pypy3"} + - {VERSION: "pypy-3.7", TOXENV: "pypy3"} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1j"}} - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1j"}} From 7491e6b4fdd38cf1163bb89df0c122b293957c5a Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 21 Feb 2021 16:53:44 -0600 Subject: [PATCH 0153/2380] remove virtualenv in wheel builders (#5858) now that we're py3+ only we should be able to directly use venv --- .github/workflows/wheel-builder.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index cb7b11615684..e67feaf48429 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -19,7 +19,7 @@ jobs: CONTAINER: "cryptography-manylinux2014:x86_64" name: "${{ matrix.PYTHON }} for ${{ matrix.MANYLINUX.NAME }}" steps: - - run: /opt/python/${{ matrix.PYTHON }}/bin/python -m virtualenv .venv + - run: /opt/python/${{ matrix.PYTHON }}/bin/python -m venv .venv - name: Install Python dependencies run: .venv/bin/pip install -U pip wheel cffi six ipaddress setuptools-rust - run: .venv/bin/pip download cryptography==${{ github.event.inputs.version }} --no-deps --no-binary cryptography && tar zxvf cryptography*.tar.gz && mkdir tmpwheelhouse @@ -71,7 +71,7 @@ jobs: sudo installer -pkg python.pkg -target / env: PYTHON_DOWNLOAD_URL: ${{ matrix.PYTHON.DOWNLOAD_URL }} - - run: ${{ matrix.PYTHON.BIN_PATH }} -m pip install -U virtualenv requests + - run: ${{ matrix.PYTHON.BIN_PATH }} -m pip install -U requests - name: Download OpenSSL run: | ${{ matrix.PYTHON.BIN_PATH }} .github/workflows/download_openssl.py macos openssl-macos-x86-64 @@ -84,7 +84,7 @@ jobs: override: true default: true - - run: ${{ matrix.PYTHON.BIN_PATH }} -m virtualenv venv + - run: ${{ matrix.PYTHON.BIN_PATH }} -m venv venv - run: venv/bin/pip install -U pip wheel cffi six ipaddress setuptools-rust - run: venv/bin/pip download cryptography==${{ github.event.inputs.version }} --no-deps --no-binary cryptography && tar zxvf cryptography*.tar.gz && mkdir wheelhouse - name: Build the wheel From 5efb07d0308047386fa83628d2dec7579b514b15 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 21 Feb 2021 19:12:10 -0600 Subject: [PATCH 0154/2380] don't use virtualenv in zuul wheel building either (#5860) * don't use virtualenv in zuul wheel building either * we need wheel and not these other things * newer pip, also don't need six --- .../wheel/roles/build-wheel-manylinux/files/build-wheels.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/files/build-wheels.sh b/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/files/build-wheels.sh index b701c21fa532..d28ff4e7961a 100644 --- a/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/files/build-wheels.sh +++ b/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/files/build-wheels.sh @@ -9,9 +9,9 @@ for P in ${PYTHONS}; do PYBIN=/opt/python/${P}/bin - "${PYBIN}"/python -m virtualenv .venv + "${PYBIN}"/python -m venv .venv - .venv/bin/pip install cffi six ipaddress "enum34; python_version < '3'" setuptools-rust + .venv/bin/pip install -U pip wheel cffi setuptools-rust REGEX="cp3([0-9])*" if [[ "${PYBIN}" =~ $REGEX ]]; then From dd09d500f9187df9f620aa7c984d01738cb60b11 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 21 Feb 2021 20:02:58 -0600 Subject: [PATCH 0155/2380] build pypy wheels too (#5859) * build pypy wheels too * remove unneeded packages --- .github/workflows/wheel-builder.yml | 31 +++++++++++++++-------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index e67feaf48429..090a70d526a9 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -11,22 +11,23 @@ jobs: container: ghcr.io/pyca/${{ matrix.MANYLINUX.CONTAINER }} strategy: matrix: - PYTHON: ["cp36-cp36m"] + PYTHON: + - { VERSION: "cp36-cp36m", PATH: "/opt/python/cp36-cp36m/bin/python", ABI_VERSION: 'cp36' } + - { VERSION: "pypy3.6", PATH: "/opt/pypy3.6/bin/pypy" } + - { VERSION: "pypy3.7", PATH: "/opt/pypy3.7/bin/pypy" } MANYLINUX: - - NAME: manylinux2010_x86_64 - CONTAINER: "cryptography-manylinux2010:x86_64" - - NAME: manylinux2014_x86_64 - CONTAINER: "cryptography-manylinux2014:x86_64" - name: "${{ matrix.PYTHON }} for ${{ matrix.MANYLINUX.NAME }}" + - { NAME: "manylinux2010_x86_64", CONTAINER: "cryptography-manylinux2010:x86_64" } + - { NAME: "manylinux2014_x86_64", CONTAINER: "cryptography-manylinux2014:x86_64" } + name: "${{ matrix.PYTHON.VERSION }} for ${{ matrix.MANYLINUX.NAME }}" steps: - - run: /opt/python/${{ matrix.PYTHON }}/bin/python -m venv .venv + - run: ${{ matrix.PYTHON.PATH }} -m venv .venv - name: Install Python dependencies - run: .venv/bin/pip install -U pip wheel cffi six ipaddress setuptools-rust + run: .venv/bin/pip install -U pip wheel cffi setuptools-rust - run: .venv/bin/pip download cryptography==${{ github.event.inputs.version }} --no-deps --no-binary cryptography && tar zxvf cryptography*.tar.gz && mkdir tmpwheelhouse - - run: | - REGEX="cp3([0-9])*" - if [[ "${{ matrix.PYTHON }}" =~ $REGEX ]]; then - PY_LIMITED_API="--py-limited-api=cp3${BASH_REMATCH[1]}" + - name: Build the wheel + run: | + if [ -n "${{ matrix.PYTHON.ABI_VERSION }}" ]; then + PY_LIMITED_API="--py-limited-api=${{ matrix.PYTHON.ABI_VERSION }}" fi cd cryptography* LDFLAGS="-L/opt/pyca/cryptography/openssl/lib" \ @@ -51,7 +52,7 @@ jobs: - run: mv wheelhouse/cryptography*.whl cryptography-wheelhouse/ - uses: actions/upload-artifact@v1 with: - name: "cryptography-${{ github.event.inputs.version }}-${{ matrix.MANYLINUX.NAME }}-${{ matrix.PYTHON }}" + name: "cryptography-${{ github.event.inputs.version }}-${{ matrix.MANYLINUX.NAME }}-${{ matrix.PYTHON.VERSION }}" path: cryptography-wheelhouse/ macos: @@ -85,7 +86,7 @@ jobs: default: true - run: ${{ matrix.PYTHON.BIN_PATH }} -m venv venv - - run: venv/bin/pip install -U pip wheel cffi six ipaddress setuptools-rust + - run: venv/bin/pip install -U pip wheel cffi setuptools-rust - run: venv/bin/pip download cryptography==${{ github.event.inputs.version }} --no-deps --no-binary cryptography && tar zxvf cryptography*.tar.gz && mkdir wheelhouse - name: Build the wheel run: | @@ -142,7 +143,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} shell: bash - - run: python -m pip install -U pip wheel cffi six ipaddress setuptools-rust + - run: python -m pip install -U pip wheel cffi setuptools-rust - run: pip download cryptography==${{ github.event.inputs.version }} --no-deps --no-binary cryptography && tar zxvf cryptography*.tar.gz && mkdir wheelhouse shell: bash - run: cd cryptography* && python setup.py bdist_wheel --py-limited-api=${{ matrix.PYTHON.ABI_VERSION }} && mv dist/cryptography*.whl ../wheelhouse From b157a7e5c472197a0e703d964fb4bf2420f2efe1 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Fri, 26 Feb 2021 16:31:20 -0500 Subject: [PATCH 0156/2380] Remove unused X509 verification flags bindings (#5868) These don't appear to be used in pyopenssl or cryptography.io. One less source of conditionals. --- src/_cffi_src/openssl/x509_vfy.py | 25 ------------------- .../hazmat/bindings/openssl/_conditional.py | 15 ----------- 2 files changed, 40 deletions(-) diff --git a/src/_cffi_src/openssl/x509_vfy.py b/src/_cffi_src/openssl/x509_vfy.py index 66cc0176115d..4642d827765c 100644 --- a/src/_cffi_src/openssl/x509_vfy.py +++ b/src/_cffi_src/openssl/x509_vfy.py @@ -18,7 +18,6 @@ """ TYPES = """ -static const long Cryptography_HAS_102_VERIFICATION; static const long Cryptography_HAS_110_VERIFICATION_PARAMS; static const long Cryptography_HAS_X509_STORE_CTX_GET_ISSUER; @@ -90,12 +89,6 @@ static const int X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX; static const int X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; static const int X509_V_ERR_CRL_PATH_VALIDATION_ERROR; -static const int X509_V_ERR_SUITE_B_INVALID_VERSION; -static const int X509_V_ERR_SUITE_B_INVALID_ALGORITHM; -static const int X509_V_ERR_SUITE_B_INVALID_CURVE; -static const int X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM; -static const int X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED; -static const int X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256; static const int X509_V_ERR_HOSTNAME_MISMATCH; static const int X509_V_ERR_EMAIL_MISMATCH; static const int X509_V_ERR_IP_ADDRESS_MISMATCH; @@ -118,9 +111,6 @@ static const long X509_V_FLAG_USE_DELTAS; static const long X509_V_FLAG_CHECK_SS_SIGNATURE; static const long X509_V_FLAG_TRUSTED_FIRST; -static const long X509_V_FLAG_SUITEB_128_LOS_ONLY; -static const long X509_V_FLAG_SUITEB_192_LOS; -static const long X509_V_FLAG_SUITEB_128_LOS; static const long X509_V_FLAG_PARTIAL_CHAIN; static const long X509_V_FLAG_NO_ALT_CHAINS; static const long X509_V_FLAG_NO_CHECK_TIME; @@ -224,21 +214,6 @@ """ CUSTOMIZATIONS = """ -#if !CRYPTOGRAPHY_IS_LIBRESSL -static const long Cryptography_HAS_102_VERIFICATION = 1; -#else -static const long Cryptography_HAS_102_VERIFICATION = 0; -static const long X509_V_ERR_SUITE_B_INVALID_VERSION = 0; -static const long X509_V_ERR_SUITE_B_INVALID_ALGORITHM = 0; -static const long X509_V_ERR_SUITE_B_INVALID_CURVE = 0; -static const long X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM = 0; -static const long X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED = 0; -static const long X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 = 0; -static const long X509_V_FLAG_SUITEB_128_LOS_ONLY = 0; -static const long X509_V_FLAG_SUITEB_192_LOS = 0; -static const long X509_V_FLAG_SUITEB_128_LOS = 0; -#endif - #if CRYPTOGRAPHY_IS_LIBRESSL static const long Cryptography_HAS_110_VERIFICATION_PARAMS = 0; #ifndef X509_CHECK_FLAG_NEVER_CHECK_SUBJECT diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index 8654835796b6..aaa7d1392028 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -31,20 +31,6 @@ def cryptography_has_ssl3_method(): ] -def cryptography_has_102_verification(): - return [ - "X509_V_ERR_SUITE_B_INVALID_VERSION", - "X509_V_ERR_SUITE_B_INVALID_ALGORITHM", - "X509_V_ERR_SUITE_B_INVALID_CURVE", - "X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM", - "X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED", - "X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256", - "X509_V_FLAG_SUITEB_128_LOS_ONLY", - "X509_V_FLAG_SUITEB_192_LOS", - "X509_V_FLAG_SUITEB_128_LOS", - ] - - def cryptography_has_110_verification_params(): return ["X509_CHECK_FLAG_NEVER_CHECK_SUBJECT"] @@ -280,7 +266,6 @@ def cryptography_has_get_proto_version(): "Cryptography_HAS_RSA_OAEP_MD": cryptography_has_rsa_oaep_md, "Cryptography_HAS_RSA_OAEP_LABEL": cryptography_has_rsa_oaep_label, "Cryptography_HAS_SSL3_METHOD": cryptography_has_ssl3_method, - "Cryptography_HAS_102_VERIFICATION": cryptography_has_102_verification, "Cryptography_HAS_110_VERIFICATION_PARAMS": ( cryptography_has_110_verification_params ), From 1f4794cae956213b882c26c0070af097598cc57b Mon Sep 17 00:00:00 2001 From: Mathias Ertl Date: Sat, 27 Feb 2021 17:19:54 +0100 Subject: [PATCH 0157/2380] Strict typehints for extensions and OIDs (#5870) * add typehint for name * strictly type ObjectIdentifier * explicit reexport for mypy * type (most) of extensions.py * minor cleanup * more consistently return None in constructors * revert explicit reexport, as requested * use _make_sequence_methods for now (#5870) * mark oid as normal type-hinted property so that classes can access it * fix spelling (upper case) use short form for reference * annotate as ClassVar * add type ignore for special extension class --- docs/x509/reference.rst | 6 + src/cryptography/hazmat/_oid.py | 12 +- src/cryptography/x509/extensions.py | 475 +++++++++++++++------------- 3 files changed, 269 insertions(+), 224 deletions(-) diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst index 216896f045cc..105f8e10686c 100644 --- a/docs/x509/reference.rst +++ b/docs/x509/reference.rst @@ -1574,6 +1574,12 @@ X.509 Extensions This is the interface against which all the following extension types are registered. + .. attribute:: oid + + :type: :class:`ObjectIdentifier` + + Returns the OID associated with the given extension type. + .. class:: KeyUsage(digital_signature, content_commitment, key_encipherment, data_encipherment, key_agreement, key_cert_sign, crl_sign, encipher_only, decipher_only) .. versionadded:: 0.9 diff --git a/src/cryptography/hazmat/_oid.py b/src/cryptography/hazmat/_oid.py index 84268b8dea45..dbd04bc37609 100644 --- a/src/cryptography/hazmat/_oid.py +++ b/src/cryptography/hazmat/_oid.py @@ -2,9 +2,11 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. +import typing + class ObjectIdentifier(object): - def __init__(self, dotted_string: str): + def __init__(self, dotted_string: str) -> None: self._dotted_string = dotted_string nodes = self._dotted_string.split(".") @@ -46,21 +48,21 @@ def __init__(self, dotted_string: str): % (self._dotted_string) ) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, ObjectIdentifier): return NotImplemented return self.dotted_string == other.dotted_string - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __repr__(self): + def __repr__(self) -> str: return "".format( self.dotted_string, self._name ) - def __hash__(self): + def __hash__(self) -> int: return hash(self.dotted_string) @property diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index aad8bcfd9c5b..e57190dda8e7 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -10,7 +10,6 @@ import typing from enum import Enum -from cryptography import utils from cryptography.hazmat._der import ( BIT_STRING, DERReader, @@ -76,8 +75,8 @@ def _key_identifier_from_public_key(public_key: _PUBLIC_KEY_TYPES) -> bytes: return hashlib.sha1(data).digest() -def _make_sequence_methods(field_name): - def len_method(self): +def _make_sequence_methods(field_name: str): + def len_method(self) -> int: return len(getattr(self, field_name)) def iter_method(self): @@ -90,27 +89,25 @@ def getitem_method(self, idx): class DuplicateExtension(Exception): - def __init__(self, msg: str, oid: ObjectIdentifier): + def __init__(self, msg: str, oid: ObjectIdentifier) -> None: super(DuplicateExtension, self).__init__(msg) self.oid = oid class ExtensionNotFound(Exception): - def __init__(self, msg: str, oid: ObjectIdentifier): + def __init__(self, msg: str, oid: ObjectIdentifier) -> None: super(ExtensionNotFound, self).__init__(msg) self.oid = oid class ExtensionType(metaclass=abc.ABCMeta): - @abc.abstractproperty - def oid(self) -> ObjectIdentifier: - """ - Returns the oid associated with the given extension type. - """ + oid: typing.ClassVar[ObjectIdentifier] class Extensions(object): - def __init__(self, extensions: typing.List["Extension[ExtensionType]"]): + def __init__( + self, extensions: typing.List["Extension[ExtensionType]"] + ) -> None: self._extensions = extensions def get_extension_for_oid( @@ -122,7 +119,9 @@ def get_extension_for_oid( raise ExtensionNotFound("No {} extension was found".format(oid), oid) - def get_extension_for_class(self, extclass) -> "Extension[ExtensionType]": + def get_extension_for_class( + self, extclass: typing.Type[ExtensionType] + ) -> "Extension[ExtensionType]": if extclass is UnrecognizedExtension: raise TypeError( "UnrecognizedExtension can't be used with " @@ -140,32 +139,32 @@ def get_extension_for_class(self, extclass) -> "Extension[ExtensionType]": __len__, __iter__, __getitem__ = _make_sequence_methods("_extensions") - def __repr__(self): + def __repr__(self) -> str: return "".format(self._extensions) class CRLNumber(ExtensionType): oid = ExtensionOID.CRL_NUMBER - def __init__(self, crl_number: int): + def __init__(self, crl_number: int) -> None: if not isinstance(crl_number, int): raise TypeError("crl_number must be an integer") self._crl_number = crl_number - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, CRLNumber): return NotImplemented return self.crl_number == other.crl_number - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(self.crl_number) - def __repr__(self): + def __repr__(self) -> str: return "".format(self.crl_number) @property @@ -181,7 +180,7 @@ def __init__( key_identifier: typing.Optional[bytes], authority_cert_issuer: typing.Optional[typing.Iterable[GeneralName]], authority_cert_serial_number: typing.Optional[int], - ): + ) -> None: if (authority_cert_issuer is None) != ( authority_cert_serial_number is None ): @@ -230,7 +229,7 @@ def from_issuer_subject_key_identifier( authority_cert_serial_number=None, ) - def __repr__(self): + def __repr__(self) -> str: return ( "".format(self) ) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, AuthorityKeyIdentifier): return NotImplemented @@ -249,10 +248,10 @@ def __eq__(self, other): == other.authority_cert_serial_number ) - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: if self.authority_cert_issuer is None: aci = None else: @@ -279,7 +278,7 @@ def authority_cert_serial_number(self) -> typing.Optional[int]: class SubjectKeyIdentifier(ExtensionType): oid = ExtensionOID.SUBJECT_KEY_IDENTIFIER - def __init__(self, digest: bytes): + def __init__(self, digest: bytes) -> None: self._digest = digest @classmethod @@ -296,26 +295,28 @@ def digest(self) -> bytes: def key_identifier(self) -> bytes: return self._digest - def __repr__(self): + def __repr__(self) -> str: return "".format(self.digest) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, SubjectKeyIdentifier): return NotImplemented return constant_time.bytes_eq(self.digest, other.digest) - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(self.digest) class AuthorityInformationAccess(ExtensionType): oid = ExtensionOID.AUTHORITY_INFORMATION_ACCESS - def __init__(self, descriptions: typing.Iterable["AccessDescription"]): + def __init__( + self, descriptions: typing.Iterable["AccessDescription"] + ) -> None: descriptions = list(descriptions) if not all(isinstance(x, AccessDescription) for x in descriptions): raise TypeError( @@ -327,26 +328,28 @@ def __init__(self, descriptions: typing.Iterable["AccessDescription"]): __len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions") - def __repr__(self): + def __repr__(self) -> str: return "".format(self._descriptions) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, AuthorityInformationAccess): return NotImplemented return self._descriptions == other._descriptions - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(tuple(self._descriptions)) class SubjectInformationAccess(ExtensionType): oid = ExtensionOID.SUBJECT_INFORMATION_ACCESS - def __init__(self, descriptions: typing.Iterable["AccessDescription"]): + def __init__( + self, descriptions: typing.Iterable["AccessDescription"] + ) -> None: descriptions = list(descriptions) if not all(isinstance(x, AccessDescription) for x in descriptions): raise TypeError( @@ -358,26 +361,26 @@ def __init__(self, descriptions: typing.Iterable["AccessDescription"]): __len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions") - def __repr__(self): + def __repr__(self) -> str: return "".format(self._descriptions) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, SubjectInformationAccess): return NotImplemented return self._descriptions == other._descriptions - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(tuple(self._descriptions)) class AccessDescription(object): def __init__( self, access_method: ObjectIdentifier, access_location: GeneralName - ): + ) -> None: if not isinstance(access_method, ObjectIdentifier): raise TypeError("access_method must be an ObjectIdentifier") @@ -387,13 +390,13 @@ def __init__( self._access_method = access_method self._access_location = access_location - def __repr__(self): + def __repr__(self) -> str: return ( "".format(self) ) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, AccessDescription): return NotImplemented @@ -402,10 +405,10 @@ def __eq__(self, other): and self.access_location == other.access_location ) - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash((self.access_method, self.access_location)) @property @@ -420,7 +423,7 @@ def access_location(self) -> GeneralName: class BasicConstraints(ExtensionType): oid = ExtensionOID.BASIC_CONSTRAINTS - def __init__(self, ca: bool, path_length: typing.Optional[int]): + def __init__(self, ca: bool, path_length: typing.Optional[int]) -> None: if not isinstance(ca, bool): raise TypeError("ca must be a boolean value") @@ -445,28 +448,28 @@ def ca(self) -> bool: def path_length(self) -> typing.Optional[int]: return self._path_length - def __repr__(self): + def __repr__(self) -> str: return ( "" ).format(self) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, BasicConstraints): return NotImplemented return self.ca == other.ca and self.path_length == other.path_length - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash((self.ca, self.path_length)) class DeltaCRLIndicator(ExtensionType): oid = ExtensionOID.DELTA_CRL_INDICATOR - def __init__(self, crl_number: int): + def __init__(self, crl_number: int) -> None: if not isinstance(crl_number, int): raise TypeError("crl_number must be an integer") @@ -476,19 +479,19 @@ def __init__(self, crl_number: int): def crl_number(self) -> int: return self._crl_number - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, DeltaCRLIndicator): return NotImplemented return self.crl_number == other.crl_number - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(self.crl_number) - def __repr__(self): + def __repr__(self) -> str: return "".format(self) @@ -497,7 +500,7 @@ class CRLDistributionPoints(ExtensionType): def __init__( self, distribution_points: typing.Iterable["DistributionPoint"] - ): + ) -> None: distribution_points = list(distribution_points) if not all( isinstance(x, DistributionPoint) for x in distribution_points @@ -513,19 +516,19 @@ def __init__( "_distribution_points" ) - def __repr__(self): + def __repr__(self) -> str: return "".format(self._distribution_points) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, CRLDistributionPoints): return NotImplemented return self._distribution_points == other._distribution_points - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(tuple(self._distribution_points)) @@ -534,7 +537,7 @@ class FreshestCRL(ExtensionType): def __init__( self, distribution_points: typing.Iterable["DistributionPoint"] - ): + ) -> None: distribution_points = list(distribution_points) if not all( isinstance(x, DistributionPoint) for x in distribution_points @@ -550,19 +553,19 @@ def __init__( "_distribution_points" ) - def __repr__(self): + def __repr__(self) -> str: return "".format(self._distribution_points) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, FreshestCRL): return NotImplemented return self._distribution_points == other._distribution_points - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(tuple(self._distribution_points)) @@ -573,7 +576,7 @@ def __init__( relative_name: typing.Optional[RelativeDistinguishedName], reasons: typing.Optional[typing.FrozenSet["ReasonFlags"]], crl_issuer: typing.Optional[typing.Iterable[GeneralName]], - ): + ) -> None: if full_name and relative_name: raise ValueError( "You cannot provide both full_name and relative_name, at " @@ -626,14 +629,14 @@ def __init__( self._reasons = reasons self._crl_issuer = crl_issuer - def __repr__(self): + def __repr__(self) -> str: return ( "".format(self) ) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, DistributionPoint): return NotImplemented @@ -644,17 +647,21 @@ def __eq__(self, other): and self.crl_issuer == other.crl_issuer ) - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: if self.full_name is not None: - fn: typing.Optional[tuple] = tuple(self.full_name) + fn: typing.Optional[typing.Tuple[GeneralName, ...]] = tuple( + self.full_name + ) else: fn = None if self.crl_issuer is not None: - crl_issuer: typing.Optional[tuple] = tuple(self.crl_issuer) + crl_issuer: typing.Optional[ + typing.Tuple[GeneralName, ...] + ] = tuple(self.crl_issuer) else: crl_issuer = None @@ -697,7 +704,7 @@ def __init__( self, require_explicit_policy: typing.Optional[int], inhibit_policy_mapping: typing.Optional[int], - ): + ) -> None: if require_explicit_policy is not None and not isinstance( require_explicit_policy, int ): @@ -722,14 +729,14 @@ def __init__( self._require_explicit_policy = require_explicit_policy self._inhibit_policy_mapping = inhibit_policy_mapping - def __repr__(self): + def __repr__(self) -> str: return ( "".format(self) ) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, PolicyConstraints): return NotImplemented @@ -738,10 +745,10 @@ def __eq__(self, other): and self.inhibit_policy_mapping == other.inhibit_policy_mapping ) - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash( (self.require_explicit_policy, self.inhibit_policy_mapping) ) @@ -758,7 +765,7 @@ def inhibit_policy_mapping(self) -> typing.Optional[int]: class CertificatePolicies(ExtensionType): oid = ExtensionOID.CERTIFICATE_POLICIES - def __init__(self, policies: typing.Iterable["PolicyInformation"]): + def __init__(self, policies: typing.Iterable["PolicyInformation"]) -> None: policies = list(policies) if not all(isinstance(x, PolicyInformation) for x in policies): raise TypeError( @@ -770,19 +777,19 @@ def __init__(self, policies: typing.Iterable["PolicyInformation"]): __len__, __iter__, __getitem__ = _make_sequence_methods("_policies") - def __repr__(self): + def __repr__(self) -> str: return "".format(self._policies) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, CertificatePolicies): return NotImplemented return self._policies == other._policies - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(tuple(self._policies)) @@ -793,7 +800,7 @@ def __init__( policy_qualifiers: typing.Optional[ typing.Iterable[typing.Union[str, "UserNotice"]] ], - ): + ) -> None: if not isinstance(policy_identifier, ObjectIdentifier): raise TypeError("policy_identifier must be an ObjectIdentifier") @@ -811,13 +818,13 @@ def __init__( self._policy_qualifiers = policy_qualifiers - def __repr__(self): + def __repr__(self) -> str: return ( "".format(self) ) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, PolicyInformation): return NotImplemented @@ -826,12 +833,14 @@ def __eq__(self, other): and self.policy_qualifiers == other.policy_qualifiers ) - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: if self.policy_qualifiers is not None: - pq: typing.Optional[tuple] = tuple(self.policy_qualifiers) + pq: typing.Optional[ + typing.Tuple[typing.Union[str, "UserNotice"], ...] + ] = tuple(self.policy_qualifiers) else: pq = None @@ -853,7 +862,7 @@ def __init__( self, notice_reference: typing.Optional["NoticeReference"], explicit_text: typing.Optional[str], - ): + ) -> None: if notice_reference and not isinstance( notice_reference, NoticeReference ): @@ -864,13 +873,13 @@ def __init__( self._notice_reference = notice_reference self._explicit_text = explicit_text - def __repr__(self): + def __repr__(self) -> str: return ( "".format(self) ) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, UserNotice): return NotImplemented @@ -879,10 +888,10 @@ def __eq__(self, other): and self.explicit_text == other.explicit_text ) - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash((self.notice_reference, self.explicit_text)) @property @@ -899,7 +908,7 @@ def __init__( self, organization: typing.Optional[str], notice_numbers: typing.Iterable[int], - ): + ) -> None: self._organization = organization notice_numbers = list(notice_numbers) if not all(isinstance(x, int) for x in notice_numbers): @@ -907,13 +916,13 @@ def __init__( self._notice_numbers = notice_numbers - def __repr__(self): + def __repr__(self) -> str: return ( "".format(self) ) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, NoticeReference): return NotImplemented @@ -922,10 +931,10 @@ def __eq__(self, other): and self.notice_numbers == other.notice_numbers ) - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash((self.organization, tuple(self.notice_numbers))) @property @@ -940,7 +949,7 @@ def notice_numbers(self) -> typing.List[int]: class ExtendedKeyUsage(ExtensionType): oid = ExtensionOID.EXTENDED_KEY_USAGE - def __init__(self, usages: typing.Iterable[ObjectIdentifier]): + def __init__(self, usages: typing.Iterable[ObjectIdentifier]) -> None: usages = list(usages) if not all(isinstance(x, ObjectIdentifier) for x in usages): raise TypeError( @@ -951,64 +960,64 @@ def __init__(self, usages: typing.Iterable[ObjectIdentifier]): __len__, __iter__, __getitem__ = _make_sequence_methods("_usages") - def __repr__(self): + def __repr__(self) -> str: return "".format(self._usages) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, ExtendedKeyUsage): return NotImplemented return self._usages == other._usages - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(tuple(self._usages)) class OCSPNoCheck(ExtensionType): oid = ExtensionOID.OCSP_NO_CHECK - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, OCSPNoCheck): return NotImplemented return True - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(OCSPNoCheck) - def __repr__(self): + def __repr__(self) -> str: return "" class PrecertPoison(ExtensionType): oid = ExtensionOID.PRECERT_POISON - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, PrecertPoison): return NotImplemented return True - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(PrecertPoison) - def __repr__(self): + def __repr__(self) -> str: return "" class TLSFeature(ExtensionType): oid = ExtensionOID.TLS_FEATURE - def __init__(self, features: typing.Iterable["TLSFeatureType"]): + def __init__(self, features: typing.Iterable["TLSFeatureType"]) -> None: features = list(features) if ( not all(isinstance(x, TLSFeatureType) for x in features) @@ -1023,19 +1032,19 @@ def __init__(self, features: typing.Iterable["TLSFeatureType"]): __len__, __iter__, __getitem__ = _make_sequence_methods("_features") - def __repr__(self): + def __repr__(self) -> str: return "".format(self) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, TLSFeature): return NotImplemented return self._features == other._features - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(tuple(self._features)) @@ -1056,7 +1065,7 @@ class TLSFeatureType(Enum): class InhibitAnyPolicy(ExtensionType): oid = ExtensionOID.INHIBIT_ANY_POLICY - def __init__(self, skip_certs: int): + def __init__(self, skip_certs: int) -> None: if not isinstance(skip_certs, int): raise TypeError("skip_certs must be an integer") @@ -1065,19 +1074,19 @@ def __init__(self, skip_certs: int): self._skip_certs = skip_certs - def __repr__(self): + def __repr__(self) -> str: return "".format(self) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, InhibitAnyPolicy): return NotImplemented return self.skip_certs == other.skip_certs - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(self.skip_certs) @property @@ -1099,7 +1108,7 @@ def __init__( crl_sign: bool, encipher_only: bool, decipher_only: bool, - ): + ) -> None: if not key_agreement and (encipher_only or decipher_only): raise ValueError( "encipher_only and decipher_only can only be true when " @@ -1145,7 +1154,7 @@ def crl_sign(self) -> bool: return self._crl_sign @property - def encipher_only(self): + def encipher_only(self) -> bool: if not self.key_agreement: raise ValueError( "encipher_only is undefined unless key_agreement is true" @@ -1154,7 +1163,7 @@ def encipher_only(self): return self._encipher_only @property - def decipher_only(self): + def decipher_only(self) -> bool: if not self.key_agreement: raise ValueError( "decipher_only is undefined unless key_agreement is true" @@ -1162,7 +1171,7 @@ def decipher_only(self): else: return self._decipher_only - def __repr__(self): + def __repr__(self) -> str: try: encipher_only = self.encipher_only decipher_only = self.decipher_only @@ -1183,7 +1192,7 @@ def __repr__(self): "encipher_only={1}, decipher_only={2})>" ).format(self, encipher_only, decipher_only) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, KeyUsage): return NotImplemented @@ -1199,10 +1208,10 @@ def __eq__(self, other): and self._decipher_only == other._decipher_only ) - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash( ( self.digital_signature, @@ -1225,7 +1234,7 @@ def __init__( self, permitted_subtrees: typing.Optional[typing.Iterable[GeneralName]], excluded_subtrees: typing.Optional[typing.Iterable[GeneralName]], - ): + ) -> None: if permitted_subtrees is not None: permitted_subtrees = list(permitted_subtrees) if not all(isinstance(x, GeneralName) for x in permitted_subtrees): @@ -1255,7 +1264,7 @@ def __init__( self._permitted_subtrees = permitted_subtrees self._excluded_subtrees = excluded_subtrees - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, NameConstraints): return NotImplemented @@ -1264,10 +1273,10 @@ def __eq__(self, other): and self.permitted_subtrees == other.permitted_subtrees ) - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def _validate_ip_name(self, tree): + def _validate_ip_name(self, tree: typing.Iterable[GeneralName]) -> None: if any( isinstance(name, IPAddress) and not isinstance( @@ -1280,20 +1289,24 @@ def _validate_ip_name(self, tree): " IPv6Network object" ) - def __repr__(self): + def __repr__(self) -> str: return ( "".format(self) ) - def __hash__(self): + def __hash__(self) -> int: if self.permitted_subtrees is not None: - ps: typing.Optional[tuple] = tuple(self.permitted_subtrees) + ps: typing.Optional[typing.Tuple[GeneralName, ...]] = tuple( + self.permitted_subtrees + ) else: ps = None if self.excluded_subtrees is not None: - es: typing.Optional[tuple] = tuple(self.excluded_subtrees) + es: typing.Optional[typing.Tuple[GeneralName, ...]] = tuple( + self.excluded_subtrees + ) else: es = None @@ -1315,7 +1328,7 @@ def excluded_subtrees( class Extension(typing.Generic[ExtensionTypeVar]): def __init__( self, oid: ObjectIdentifier, critical: bool, value: ExtensionTypeVar - ): + ) -> None: if not isinstance(oid, ObjectIdentifier): raise TypeError( "oid argument must be an ObjectIdentifier instance." @@ -1340,13 +1353,13 @@ def critical(self) -> bool: def value(self) -> ExtensionType: return self._value - def __repr__(self): + def __repr__(self) -> str: return ( "" ).format(self) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, Extension): return NotImplemented @@ -1356,15 +1369,15 @@ def __eq__(self, other): and self.value == other.value ) - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash((self.oid, self.critical, self.value)) class GeneralNames(object): - def __init__(self, general_names: typing.Iterable[GeneralName]): + def __init__(self, general_names: typing.Iterable[GeneralName]) -> None: general_names = list(general_names) if not all(isinstance(x, GeneralName) for x in general_names): raise TypeError( @@ -1376,7 +1389,9 @@ def __init__(self, general_names: typing.Iterable[GeneralName]): __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") - def get_values_for_type(self, type: typing.Type[GeneralName]): + def get_values_for_type( + self, type: typing.Type[GeneralName] + ) -> typing.List[GeneralName]: # Return the value of each GeneralName, except for OtherName instances # which we return directly because it has two important properties not # just one value. @@ -1385,125 +1400,131 @@ def get_values_for_type(self, type: typing.Type[GeneralName]): objs = (i.value for i in objs) return list(objs) - def __repr__(self): + def __repr__(self) -> str: return "".format(self._general_names) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, GeneralNames): return NotImplemented return self._general_names == other._general_names - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(tuple(self._general_names)) class SubjectAlternativeName(ExtensionType): oid = ExtensionOID.SUBJECT_ALTERNATIVE_NAME - def __init__(self, general_names: typing.Iterable[GeneralName]): + def __init__(self, general_names: typing.Iterable[GeneralName]) -> None: self._general_names = GeneralNames(general_names) __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") - def get_values_for_type(self, type): + def get_values_for_type( + self, type: typing.Type[GeneralName] + ) -> typing.List[GeneralName]: return self._general_names.get_values_for_type(type) - def __repr__(self): + def __repr__(self) -> str: return "".format(self._general_names) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, SubjectAlternativeName): return NotImplemented return self._general_names == other._general_names - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(self._general_names) class IssuerAlternativeName(ExtensionType): oid = ExtensionOID.ISSUER_ALTERNATIVE_NAME - def __init__(self, general_names: typing.Iterable[GeneralName]): + def __init__(self, general_names: typing.Iterable[GeneralName]) -> None: self._general_names = GeneralNames(general_names) __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") - def get_values_for_type(self, type): + def get_values_for_type( + self, type: typing.Type[GeneralName] + ) -> typing.List[GeneralName]: return self._general_names.get_values_for_type(type) - def __repr__(self): + def __repr__(self) -> str: return "".format(self._general_names) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, IssuerAlternativeName): return NotImplemented return self._general_names == other._general_names - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(self._general_names) class CertificateIssuer(ExtensionType): oid = CRLEntryExtensionOID.CERTIFICATE_ISSUER - def __init__(self, general_names: typing.Iterable[GeneralName]): + def __init__(self, general_names: typing.Iterable[GeneralName]) -> None: self._general_names = GeneralNames(general_names) __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") - def get_values_for_type(self, type): + def get_values_for_type( + self, type: typing.Type[GeneralName] + ) -> typing.List[GeneralName]: return self._general_names.get_values_for_type(type) - def __repr__(self): + def __repr__(self) -> str: return "".format(self._general_names) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, CertificateIssuer): return NotImplemented return self._general_names == other._general_names - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(self._general_names) class CRLReason(ExtensionType): oid = CRLEntryExtensionOID.CRL_REASON - def __init__(self, reason: ReasonFlags): + def __init__(self, reason: ReasonFlags) -> None: if not isinstance(reason, ReasonFlags): raise TypeError("reason must be an element from ReasonFlags") self._reason = reason - def __repr__(self): + def __repr__(self) -> str: return "".format(self._reason) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, CRLReason): return NotImplemented return self.reason == other.reason - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(self.reason) @property @@ -1514,27 +1535,27 @@ def reason(self) -> ReasonFlags: class InvalidityDate(ExtensionType): oid = CRLEntryExtensionOID.INVALIDITY_DATE - def __init__(self, invalidity_date: datetime.datetime): + def __init__(self, invalidity_date: datetime.datetime) -> None: if not isinstance(invalidity_date, datetime.datetime): raise TypeError("invalidity_date must be a datetime.datetime") self._invalidity_date = invalidity_date - def __repr__(self): + def __repr__(self) -> str: return "".format( self._invalidity_date ) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, InvalidityDate): return NotImplemented return self.invalidity_date == other.invalidity_date - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(self.invalidity_date) @property @@ -1550,7 +1571,7 @@ def __init__( signed_certificate_timestamps: typing.Iterable[ SignedCertificateTimestamp ], - ): + ) -> None: signed_certificate_timestamps = list(signed_certificate_timestamps) if not all( isinstance(sct, SignedCertificateTimestamp) @@ -1566,15 +1587,15 @@ def __init__( "_signed_certificate_timestamps" ) - def __repr__(self): + def __repr__(self) -> str: return "".format( list(self) ) - def __hash__(self): + def __hash__(self) -> int: return hash(tuple(self._signed_certificate_timestamps)) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, PrecertificateSignedCertificateTimestamps): return NotImplemented @@ -1583,7 +1604,7 @@ def __eq__(self, other): == other._signed_certificate_timestamps ) - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other @@ -1595,7 +1616,7 @@ def __init__( signed_certificate_timestamps: typing.Iterable[ SignedCertificateTimestamp ], - ): + ) -> None: signed_certificate_timestamps = list(signed_certificate_timestamps) if not all( isinstance(sct, SignedCertificateTimestamp) @@ -1611,13 +1632,13 @@ def __init__( "_signed_certificate_timestamps" ) - def __repr__(self): + def __repr__(self) -> str: return "".format(list(self)) - def __hash__(self): + def __hash__(self) -> int: return hash(tuple(self._signed_certificate_timestamps)) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, SignedCertificateTimestamps): return NotImplemented @@ -1626,32 +1647,32 @@ def __eq__(self, other): == other._signed_certificate_timestamps ) - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other class OCSPNonce(ExtensionType): oid = OCSPExtensionOID.NONCE - def __init__(self, nonce: bytes): + def __init__(self, nonce: bytes) -> None: if not isinstance(nonce, bytes): raise TypeError("nonce must be bytes") self._nonce = nonce - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, OCSPNonce): return NotImplemented return self.nonce == other.nonce - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash(self.nonce) - def __repr__(self): + def __repr__(self) -> str: return "".format(self) @property @@ -1664,14 +1685,14 @@ class IssuingDistributionPoint(ExtensionType): def __init__( self, - full_name, - relative_name, - only_contains_user_certs, - only_contains_ca_certs, - only_some_reasons, - indirect_crl, - only_contains_attribute_certs, - ): + full_name: typing.Optional[typing.List[GeneralName]], + relative_name: typing.Optional[RelativeDistinguishedName], + only_contains_user_certs: bool, + only_contains_ca_certs: bool, + only_some_reasons: typing.Optional[typing.FrozenSet[ReasonFlags]], + indirect_crl: bool, + only_contains_attribute_certs: bool, + ) -> None: if only_some_reasons and ( not isinstance(only_some_reasons, frozenset) or not all(isinstance(x, ReasonFlags) for x in only_some_reasons) @@ -1742,7 +1763,7 @@ def __init__( self._full_name = full_name self._relative_name = relative_name - def __repr__(self): + def __repr__(self) -> str: return ( "".format(self) ) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, IssuingDistributionPoint): return NotImplemented @@ -1769,10 +1790,10 @@ def __eq__(self, other): == other.only_contains_attribute_certs ) - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash( ( self.full_name, @@ -1785,50 +1806,66 @@ def __hash__(self): ) ) - full_name = utils.read_only_property("_full_name") - relative_name = utils.read_only_property("_relative_name") - only_contains_user_certs = utils.read_only_property( - "_only_contains_user_certs" - ) - only_contains_ca_certs = utils.read_only_property( - "_only_contains_ca_certs" - ) - only_some_reasons = utils.read_only_property("_only_some_reasons") - indirect_crl = utils.read_only_property("_indirect_crl") - only_contains_attribute_certs = utils.read_only_property( - "_only_contains_attribute_certs" - ) + @property + def full_name(self) -> typing.Optional[typing.List[GeneralName]]: + return self._full_name + + @property + def relative_name(self) -> typing.Optional[RelativeDistinguishedName]: + return self._relative_name + + @property + def only_contains_user_certs(self) -> bool: + return self._only_contains_user_certs + + @property + def only_contains_ca_certs(self) -> bool: + return self._only_contains_ca_certs + + @property + def only_some_reasons( + self, + ) -> typing.Optional[typing.FrozenSet[ReasonFlags]]: + return self._only_some_reasons + + @property + def indirect_crl(self) -> bool: + return self._indirect_crl + + @property + def only_contains_attribute_certs(self) -> bool: + return self._only_contains_attribute_certs class UnrecognizedExtension(ExtensionType): - def __init__(self, oid: ObjectIdentifier, value: bytes): + def __init__(self, oid: ObjectIdentifier, value: bytes) -> None: if not isinstance(oid, ObjectIdentifier): raise TypeError("oid must be an ObjectIdentifier") self._oid = oid self._value = value @property - def oid(self) -> ObjectIdentifier: + def oid(self) -> ObjectIdentifier: # type: ignore[override] return self._oid @property def value(self) -> bytes: return self._value - def __repr__(self): + def __repr__(self) -> str: return ( "".format(self) ) - def __eq__(self, other): + def __eq__(self, other: typing.Any) -> bool: if not isinstance(other, UnrecognizedExtension): return NotImplemented return self.oid == other.oid and self.value == other.value - def __ne__(self, other): + def __ne__(self, other: typing.Any) -> bool: return not self == other - def __hash__(self): + def __hash__(self) -> int: return hash((self.oid, self.value)) From 60c67792b46d7f6a38ba7540ad768572cd505fe7 Mon Sep 17 00:00:00 2001 From: Mathias Ertl Date: Sat, 27 Feb 2021 22:00:50 +0100 Subject: [PATCH 0158/2380] consistently typecast to list (#5873) --- src/cryptography/x509/extensions.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index e57190dda8e7..d43f2b8d2a58 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -106,9 +106,9 @@ class ExtensionType(metaclass=abc.ABCMeta): class Extensions(object): def __init__( - self, extensions: typing.List["Extension[ExtensionType]"] + self, extensions: typing.Iterable["Extension[ExtensionType]"] ) -> None: - self._extensions = extensions + self._extensions = list(extensions) def get_extension_for_oid( self, oid: ObjectIdentifier @@ -1685,7 +1685,7 @@ class IssuingDistributionPoint(ExtensionType): def __init__( self, - full_name: typing.Optional[typing.List[GeneralName]], + full_name: typing.Optional[typing.Iterable[GeneralName]], relative_name: typing.Optional[RelativeDistinguishedName], only_contains_user_certs: bool, only_contains_ca_certs: bool, @@ -1693,6 +1693,9 @@ def __init__( indirect_crl: bool, only_contains_attribute_certs: bool, ) -> None: + if full_name is not None: + full_name = list(full_name) + if only_some_reasons and ( not isinstance(only_some_reasons, frozenset) or not all(isinstance(x, ReasonFlags) for x in only_some_reasons) From dcbec5ea993b22fa7033c0cf37f8abab6b3fc9e6 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 27 Feb 2021 18:34:39 -0500 Subject: [PATCH 0159/2380] Annotate asymetric contexts (#5874) --- src/cryptography/hazmat/primitives/asymmetric/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cryptography/hazmat/primitives/asymmetric/__init__.py b/src/cryptography/hazmat/primitives/asymmetric/__init__.py index efa23a6e8cd7..f4953efcc532 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/__init__.py +++ b/src/cryptography/hazmat/primitives/asymmetric/__init__.py @@ -8,13 +8,13 @@ class AsymmetricSignatureContext(metaclass=abc.ABCMeta): @abc.abstractmethod - def update(self, data): + def update(self, data: bytes) -> None: """ Processes the provided bytes and returns nothing. """ @abc.abstractmethod - def finalize(self): + def finalize(self) -> bytes: """ Returns the signature as bytes. """ @@ -22,13 +22,13 @@ def finalize(self): class AsymmetricVerificationContext(metaclass=abc.ABCMeta): @abc.abstractmethod - def update(self, data): + def update(self, data: bytes) -> None: """ Processes the provided bytes and returns nothing. """ @abc.abstractmethod - def verify(self): + def verify(self) -> None: """ Raises an exception if the bytes provided to update do not match the signature or the signature does not match the public key. From e0e9688a29de5920a764ca7bedb72744b0e4491e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 27 Feb 2021 19:18:13 -0500 Subject: [PATCH 0160/2380] Type a bunch of random functions (#5875) --- src/cryptography/hazmat/_der.py | 10 +++++----- src/cryptography/x509/general_name.py | 14 ++++++++------ src/cryptography/x509/name.py | 14 ++++++++++---- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/cryptography/hazmat/_der.py b/src/cryptography/hazmat/_der.py index fa5940b23672..ba1db4caf682 100644 --- a/src/cryptography/hazmat/_der.py +++ b/src/cryptography/hazmat/_der.py @@ -31,20 +31,20 @@ class DERReader(object): - def __init__(self, data): + def __init__(self, data: bytes) -> None: self.data = memoryview(data) - def __enter__(self): + def __enter__(self) -> "DERReader": return self def __exit__(self, exc_type, exc_value, tb): if exc_value is None: self.check_empty() - def is_empty(self): + def is_empty(self) -> bool: return len(self.data) == 0 - def check_empty(self): + def check_empty(self) -> None: if not self.is_empty(): raise ValueError("Invalid DER input: trailing data") @@ -55,7 +55,7 @@ def read_byte(self) -> int: self.data = self.data[1:] return ret - def read_bytes(self, n) -> memoryview: + def read_bytes(self, n: int) -> memoryview: if len(self.data) < n: raise ValueError("Invalid DER input: insufficient data") ret = self.data[:n] diff --git a/src/cryptography/x509/general_name.py b/src/cryptography/x509/general_name.py index e9495909018b..f16aef85e15f 100644 --- a/src/cryptography/x509/general_name.py +++ b/src/cryptography/x509/general_name.py @@ -26,14 +26,14 @@ class UnsupportedGeneralNameType(Exception): - def __init__(self, msg, type): + def __init__(self, msg: str, type: int) -> None: super(UnsupportedGeneralNameType, self).__init__(msg) self.type = type class GeneralName(metaclass=abc.ABCMeta): @abc.abstractproperty - def value(self): + def value(self) -> typing.Any: """ Return the value of the object """ @@ -66,7 +66,7 @@ def value(self) -> str: return self._value @classmethod - def _init_without_validation(cls, value): + def _init_without_validation(cls, value: str) -> "RFC822Name": instance = cls.__new__(cls) instance._value = value return instance @@ -108,12 +108,12 @@ def value(self) -> str: return self._value @classmethod - def _init_without_validation(cls, value): + def _init_without_validation(cls, value: str) -> "DNSName": instance = cls.__new__(cls) instance._value = value return instance - def __repr__(self): + def __repr__(self) -> str: return "".format(self.value) def __eq__(self, other: object) -> bool: @@ -150,7 +150,9 @@ def value(self) -> str: return self._value @classmethod - def _init_without_validation(cls, value): + def _init_without_validation( + cls, value: str + ) -> "UniformResourceIdentifier": instance = cls.__new__(cls) instance._value = value return instance diff --git a/src/cryptography/x509/name.py b/src/cryptography/x509/name.py index 2d506f73bb39..5c171ad615c1 100644 --- a/src/cryptography/x509/name.py +++ b/src/cryptography/x509/name.py @@ -48,7 +48,7 @@ class _ASN1Type(Enum): } -def _escape_dn_value(val): +def _escape_dn_value(val: str) -> str: """Escape special characters in RFC4514 Distinguished Name value.""" if not val: @@ -73,7 +73,9 @@ def _escape_dn_value(val): class NameAttribute(object): - def __init__(self, oid: ObjectIdentifier, value: str, _type=_SENTINEL): + def __init__( + self, oid: ObjectIdentifier, value: str, _type=_SENTINEL + ) -> None: if not isinstance(oid, ObjectIdentifier): raise TypeError( "oid argument must be an ObjectIdentifier instance." @@ -156,7 +158,9 @@ def __init__(self, attributes: typing.Iterable[NameAttribute]): if len(self._attribute_set) != len(attributes): raise ValueError("duplicate attributes are not allowed") - def get_attributes_for_oid(self, oid) -> typing.List[NameAttribute]: + def get_attributes_for_oid( + self, oid: ObjectIdentifier + ) -> typing.List[NameAttribute]: return [i for i in self if i.oid == oid] def rfc4514_string(self) -> str: @@ -220,7 +224,9 @@ def rfc4514_string(self) -> str: attr.rfc4514_string() for attr in reversed(self._attributes) ) - def get_attributes_for_oid(self, oid) -> typing.List[NameAttribute]: + def get_attributes_for_oid( + self, oid: ObjectIdentifier + ) -> typing.List[NameAttribute]: return [i for i in self if i.oid == oid] @property From 616cdd32203192692e177501bfc59234374d870a Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 27 Feb 2021 21:39:59 -0500 Subject: [PATCH 0161/2380] Update comment (#5876) --- tests/x509/test_x509.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index b1e86f43647e..3acb3ef9c3dc 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -1814,7 +1814,7 @@ def read_next_rdn_value_tag(reader): assert read_next_rdn_value_tag(subject) == PRINTABLE_STRING assert read_next_rdn_value_tag(issuer) == PRINTABLE_STRING if ( - # This only works correctly in OpenSSL 1.1.0f+ and 1.0.2l+ + # This only works correctly in OpenSSL 1.1.0f+ backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER ): assert read_next_rdn_value_tag(subject) == PRINTABLE_STRING From 0cb83aeb71822cd30c75c7c5acda09c4e8160ca9 Mon Sep 17 00:00:00 2001 From: tobyp Date: Sun, 28 Feb 2021 20:19:44 +0100 Subject: [PATCH 0162/2380] Add SM3 hash algorithm (#5833) Co-authored-by: Tobias Peter --- .../primitives/cryptographic-hashes.rst | 15 +++++++++ src/cryptography/hazmat/primitives/hashes.py | 6 ++++ tests/hazmat/primitives/test_hash_vectors.py | 14 +++++++++ tests/hazmat/primitives/test_hashes.py | 12 +++++++ .../cryptography_vectors/hashes/SM3/oscca.txt | 31 +++++++++++++++++++ 5 files changed, 78 insertions(+) create mode 100644 vectors/cryptography_vectors/hashes/SM3/oscca.txt diff --git a/docs/hazmat/primitives/cryptographic-hashes.rst b/docs/hazmat/primitives/cryptographic-hashes.rst index 4cdc034a6b84..f79f8d7066cb 100644 --- a/docs/hazmat/primitives/cryptographic-hashes.rst +++ b/docs/hazmat/primitives/cryptographic-hashes.rst @@ -245,6 +245,19 @@ MD5 message digest and has practical known collision attacks. +SM3 +~~~ + +.. class:: SM3() + + .. versionadded:: 35.0.0 + + SM3 is a cryptographic hash function standardized by the Chinese National + Cryptography Administration in `GM/T 0004-2012`_. It produces 256-bit + message digests. (An English description is available at + `draft-oscca-cfrg-sm3-02`_.) + + Interfaces ~~~~~~~~~~ @@ -286,3 +299,5 @@ Interfaces .. _`Lifetimes of cryptographic hash functions`: https://valerieaurora.org/hash.html .. _`BLAKE2`: https://blake2.net .. _`length-extension attacks`: https://en.wikipedia.org/wiki/Length_extension_attack +.. _`GM/T 0004-2012`: http://www.oscca.gov.cn/sca/xxgk/2010-12/17/1002389/files/302a3ada057c4a73830536d03e683110.pdf +.. _`draft-oscca-cfrg-sm3-02`: https://tools.ietf.org/id/draft-oscca-cfrg-sm3-02.html diff --git a/src/cryptography/hazmat/primitives/hashes.py b/src/cryptography/hazmat/primitives/hashes.py index 4f92d6d271da..6552fb95de68 100644 --- a/src/cryptography/hazmat/primitives/hashes.py +++ b/src/cryptography/hazmat/primitives/hashes.py @@ -255,3 +255,9 @@ def __init__(self, digest_size: int): @property def digest_size(self) -> int: return self._digest_size + + +class SM3(HashAlgorithm): + name = "sm3" + digest_size = 32 + block_size = 64 diff --git a/tests/hazmat/primitives/test_hash_vectors.py b/tests/hazmat/primitives/test_hash_vectors.py index 553eee37599f..6b76f8db9550 100644 --- a/tests/hazmat/primitives/test_hash_vectors.py +++ b/tests/hazmat/primitives/test_hash_vectors.py @@ -275,3 +275,17 @@ def test_shake256_variable(self, backend, subtests): m = hashes.Hash(shake, backend=backend) m.update(msg) assert m.finalize() == binascii.unhexlify(vector["output"]) + + +@pytest.mark.supported( + only_if=lambda backend: backend.hash_supported(hashes.SM3()), + skip_message="Does not support SM3", +) +@pytest.mark.requires_backend_interface(interface=HashBackend) +class TestSM3(object): + test_sm3 = generate_hash_test( + load_hash_vectors, + os.path.join("hashes", "SM3"), + ["oscca.txt"], + hashes.SM3(), + ) diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py index 559eb6d674c4..c0f5a9282c81 100644 --- a/tests/hazmat/primitives/test_hashes.py +++ b/tests/hazmat/primitives/test_hashes.py @@ -195,3 +195,15 @@ def test_invalid_digest_size(self, xof): with pytest.raises(ValueError): xof(digest_size=0) + + +@pytest.mark.supported( + only_if=lambda backend: backend.hash_supported(hashes.SM3()), + skip_message="Does not support SM3", +) +@pytest.mark.requires_backend_interface(interface=HashBackend) +class TestSM3(object): + test_sm3 = generate_base_hash_test( + hashes.SM3(), + digest_size=32, + ) diff --git a/vectors/cryptography_vectors/hashes/SM3/oscca.txt b/vectors/cryptography_vectors/hashes/SM3/oscca.txt new file mode 100644 index 000000000000..b0d0475ce7c5 --- /dev/null +++ b/vectors/cryptography_vectors/hashes/SM3/oscca.txt @@ -0,0 +1,31 @@ +# Vectors from https://raw.githubusercontent.com/torvalds/linux/master/crypto/testmgr.h, +# originally from http://www.oscca.gov.cn/UpFile/20101222141857786.pdf and +# https://github.com/adamws/oscca-sm3 +# Reformatted to work with the NIST loader +# SM3 + +Len = 0 +Msg = 00 +MD = 1ab21d8355cfa17f8e61194831e81a8f22bec8c728fefb747ed035eb5082aa2b + +Len = 8 +Msg = 61 +MD = 623476ac18f65a2909e43c7fec61b49c7e764a91a18ccb82f1917a29c86c5e88 + +# A.1. Example 1 +Len = 24 +Msg = 616263 +MD = 66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0 + +# A.1. Example 2 +Len = 208 +Msg = 6162636465666768696a6b6c6d6e6f707172737475767778797a +MD = b80fe97a4da24afc277564f66a359ef440462ad28dcc6d63adb24d5c20a61595 + +Len = 512 +Msg = 61626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364 +MD = debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732 + +Len = 2048 +Msg = 61626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364 +MD = b965764c8bebb091c7602b74afd34eefb531dccb4e0076d9b7cd813199b45971 From f69f27b1dd20ad2d24f48053a72545527e808104 Mon Sep 17 00:00:00 2001 From: tobyp Date: Sun, 28 Feb 2021 20:57:50 +0100 Subject: [PATCH 0163/2380] Add SM4 symmetric block cipher (#5834) Co-authored-by: Tobias Peter --- .../primitives/symmetric-encryption.rst | 15 +++ .../hazmat/backends/openssl/backend.py | 5 + .../hazmat/primitives/ciphers/algorithms.py | 13 +++ tests/hazmat/primitives/test_sm4.py | 99 +++++++++++++++++++ .../SM4/draft-ribose-cfrg-sm4-10-cbc.txt | 17 ++++ .../SM4/draft-ribose-cfrg-sm4-10-cfb.txt | 17 ++++ .../SM4/draft-ribose-cfrg-sm4-10-ctr.txt | 17 ++++ .../SM4/draft-ribose-cfrg-sm4-10-ecb.txt | 28 ++++++ .../SM4/draft-ribose-cfrg-sm4-10-ofb.txt | 17 ++++ 9 files changed, 228 insertions(+) create mode 100644 tests/hazmat/primitives/test_sm4.py create mode 100644 vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-cbc.txt create mode 100644 vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-cfb.txt create mode 100644 vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-ctr.txt create mode 100644 vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-ecb.txt create mode 100644 vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-ofb.txt diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst index 8551acb2693f..6e10d67fef82 100644 --- a/docs/hazmat/primitives/symmetric-encryption.rst +++ b/docs/hazmat/primitives/symmetric-encryption.rst @@ -196,6 +196,19 @@ Algorithms :term:`bits` in length. :type key: :term:`bytes-like` +.. class:: SM4(key) + + .. versionadded:: 35.0.0 + + SM4 is a block cipher developed by the Chinese Government and standardized + in the `GB/T 32907-2016`_. It is used in the Chinese WAPI + (Wired Authentication and Privacy Infrastructure) standard. (An English + description is available at `draft-ribose-cfrg-sm4-10`_.) + + :param key: The secret key. This must be kept secret. ``128`` + :term:`bits` in length. + :type key: :term:`bytes-like` + Weak ciphers ------------ @@ -815,3 +828,5 @@ Exceptions .. _`International Data Encryption Algorithm`: https://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm .. _`OpenPGP`: https://www.openpgp.org/ .. _`disk encryption`: https://en.wikipedia.org/wiki/Disk_encryption_theory#XTS +.. _`GB/T 32907-2016`: http://www.cnnic.cn/gcjsyj/qyjsyj/mmsfbz/sm4/201312/t20131204_43341.htm +.. _`draft-ribose-cfrg-sm4-10`: https://tools.ietf.org/html/draft-ribose-cfrg-sm4-10 diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 271873d92ad2..bb934094086a 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -135,6 +135,7 @@ ChaCha20, IDEA, SEED, + SM4, TripleDES, ) from cryptography.hazmat.primitives.ciphers.modes import ( @@ -411,6 +412,10 @@ def _register_default_ciphers(self): ChaCha20, type(None), GetCipherByName("chacha20") ) self.register_cipher_adapter(AES, XTS, _get_xts_cipher) + for mode_cls in [ECB, CBC, OFB, CFB, CTR]: + self.register_cipher_adapter( + SM4, mode_cls, GetCipherByName("sm4-{mode.name}") + ) def _register_x509_ext_parsers(self): ext_handlers = _EXTENSION_HANDLERS_BASE.copy() diff --git a/src/cryptography/hazmat/primitives/ciphers/algorithms.py b/src/cryptography/hazmat/primitives/ciphers/algorithms.py index b1c321941510..2fafa8ead883 100644 --- a/src/cryptography/hazmat/primitives/ciphers/algorithms.py +++ b/src/cryptography/hazmat/primitives/ciphers/algorithms.py @@ -153,3 +153,16 @@ def nonce(self) -> bytes: @property def key_size(self) -> int: return len(self.key) * 8 + + +class SM4(CipherAlgorithm, BlockCipherAlgorithm): + name = "SM4" + block_size = 128 + key_sizes = frozenset([128]) + + def __init__(self, key: bytes): + self.key = _verify_key_size(self, key) + + @property + def key_size(self) -> int: + return len(self.key) * 8 diff --git a/tests/hazmat/primitives/test_sm4.py b/tests/hazmat/primitives/test_sm4.py new file mode 100644 index 000000000000..b7573443f791 --- /dev/null +++ b/tests/hazmat/primitives/test_sm4.py @@ -0,0 +1,99 @@ +# 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. + +import binascii +import os + +import pytest + +from cryptography.hazmat.backends.interfaces import CipherBackend +from cryptography.hazmat.primitives.ciphers import algorithms, modes + +from .utils import generate_encrypt_test +from ...utils import load_nist_vectors + + +@pytest.mark.supported( + only_if=lambda backend: backend.cipher_supported( + algorithms.SM4(b"\x00" * 16), modes.ECB() + ), + skip_message="Does not support SM4 ECB", +) +@pytest.mark.requires_backend_interface(interface=CipherBackend) +class TestSM4ModeECB(object): + test_ecb = generate_encrypt_test( + load_nist_vectors, + os.path.join("ciphers", "SM4"), + ["draft-ribose-cfrg-sm4-10-ecb.txt"], + lambda key, **kwargs: algorithms.SM4(binascii.unhexlify((key))), + lambda **kwargs: modes.ECB(), + ) + + +@pytest.mark.supported( + only_if=lambda backend: backend.cipher_supported( + algorithms.SM4(b"\x00" * 16), modes.CBC(b"\x00" * 16) + ), + skip_message="Does not support SM4 CBC", +) +@pytest.mark.requires_backend_interface(interface=CipherBackend) +class TestSM4ModeCBC(object): + test_cbc = generate_encrypt_test( + load_nist_vectors, + os.path.join("ciphers", "SM4"), + ["draft-ribose-cfrg-sm4-10-cbc.txt"], + lambda key, **kwargs: algorithms.SM4(binascii.unhexlify((key))), + lambda iv, **kwargs: modes.CBC(binascii.unhexlify(iv)), + ) + + +@pytest.mark.supported( + only_if=lambda backend: backend.cipher_supported( + algorithms.SM4(b"\x00" * 16), modes.OFB(b"\x00" * 16) + ), + skip_message="Does not support SM4 OFB", +) +@pytest.mark.requires_backend_interface(interface=CipherBackend) +class TestSM4ModeOFB(object): + test_ofb = generate_encrypt_test( + load_nist_vectors, + os.path.join("ciphers", "SM4"), + ["draft-ribose-cfrg-sm4-10-ofb.txt"], + lambda key, **kwargs: algorithms.SM4(binascii.unhexlify((key))), + lambda iv, **kwargs: modes.OFB(binascii.unhexlify(iv)), + ) + + +@pytest.mark.supported( + only_if=lambda backend: backend.cipher_supported( + algorithms.SM4(b"\x00" * 16), modes.CFB(b"\x00" * 16) + ), + skip_message="Does not support SM4 CFB", +) +@pytest.mark.requires_backend_interface(interface=CipherBackend) +class TestSM4ModeCFB(object): + test_cfb = generate_encrypt_test( + load_nist_vectors, + os.path.join("ciphers", "SM4"), + ["draft-ribose-cfrg-sm4-10-cfb.txt"], + lambda key, **kwargs: algorithms.SM4(binascii.unhexlify((key))), + lambda iv, **kwargs: modes.CFB(binascii.unhexlify(iv)), + ) + + +@pytest.mark.supported( + only_if=lambda backend: backend.cipher_supported( + algorithms.SM4(b"\x00" * 16), modes.CTR(b"\x00" * 16) + ), + skip_message="Does not support SM4 CTR", +) +@pytest.mark.requires_backend_interface(interface=CipherBackend) +class TestSM4ModeCTR(object): + test_cfb = generate_encrypt_test( + load_nist_vectors, + os.path.join("ciphers", "SM4"), + ["draft-ribose-cfrg-sm4-10-ctr.txt"], + lambda key, **kwargs: algorithms.SM4(binascii.unhexlify((key))), + lambda iv, **kwargs: modes.CTR(binascii.unhexlify(iv)), + ) diff --git a/vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-cbc.txt b/vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-cbc.txt new file mode 100644 index 000000000000..49c5f8516803 --- /dev/null +++ b/vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-cbc.txt @@ -0,0 +1,17 @@ +# Vectors from draft-ribose-cfrg-sm4-10.txt. Reformatted to work with the NIST loader +# SM4 CBC +[ENCRYPT] + +# A.2.2.1 +COUNT = 0 +KEY = 0123456789abcdeffedcba9876543210 +PLAINTEXT = aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffaaaaaaaabbbbbbbb +IV = 000102030405060708090a0b0c0d0e0f +CIPHERTEXT = 78ebb11cc40b0a48312aaeb2040244cb4cb7016951909226979b0d15dc6a8f6d + +# A.2.2.2 +COUNT = 1 +KEY = fedcba98765432100123456789abcdef +PLAINTEXT = aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffaaaaaaaabbbbbbbb +IV = 000102030405060708090a0b0c0d0e0f +CIPHERTEXT = 0d3a6ddc2d21c698857215587b7bb59a91f2c147911a4144665e1fa1d40bae38 diff --git a/vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-cfb.txt b/vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-cfb.txt new file mode 100644 index 000000000000..4c2e4abf3706 --- /dev/null +++ b/vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-cfb.txt @@ -0,0 +1,17 @@ +# Vectors from draft-ribose-cfrg-sm4-10.txt. Reformatted to work with the NIST loader +# SM4 CFB +[ENCRYPT] + +# A.2.4.1 +COUNT = 0 +KEY = 0123456789abcdeffedcba9876543210 +PLAINTEXT = aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffaaaaaaaabbbbbbbb +IV = 000102030405060708090a0b0c0d0e0f +CIPHERTEXT = ac3236cb861dd316e6413b4e3c7524b769d4c54ed433b9a0346009beb37b2b3f + +# A.2.4.2 +COUNT = 1 +KEY = fedcba98765432100123456789abcdef +PLAINTEXT = aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffaaaaaaaabbbbbbbb +IV = 000102030405060708090a0b0c0d0e0f +CIPHERTEXT = 5dcccd25a84ba16560d7f265887068490d9b86ff20c3bfe115ffa02ca6192cc5 diff --git a/vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-ctr.txt b/vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-ctr.txt new file mode 100644 index 000000000000..0aea1572a8f6 --- /dev/null +++ b/vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-ctr.txt @@ -0,0 +1,17 @@ +# Vectors from draft-ribose-cfrg-sm4-10.txt. Reformatted to work with the NIST loader +# SM4 CTR +[ENCRYPT] + +# A.2.5.1 +COUNT = 0 +KEY = 0123456789abcdeffedcba9876543210 +PLAINTEXT = aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbccccccccccccccccddddddddddddddddeeeeeeeeeeeeeeeeffffffffffffffffaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb +IV = 000102030405060708090a0b0c0d0e0f +CIPHERTEXT = ac3236cb970cc20791364c395a1342d1a3cbc1878c6f30cd074cce385cdd70c7f234bc0e24c11980fd1286310ce37b926e02fcd0faa0baf38b2933851d824514 + +# A.2.5.2 +COUNT = 1 +KEY = fedcba98765432100123456789abcdef +PLAINTEXT = aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbccccccccccccccccddddddddddddddddeeeeeeeeeeeeeeeeffffffffffffffffaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb +IV = 000102030405060708090a0b0c0d0e0f +CIPHERTEXT = 5dcccd25b95ab07417a08512ee160e2f8f661521cbbab44cc87138445bc29e5c0ae0297205d62704173b21239b887f6c8cb5b800917a2488284bde9e16ea2906 diff --git a/vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-ecb.txt b/vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-ecb.txt new file mode 100644 index 000000000000..c9a6874228fe --- /dev/null +++ b/vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-ecb.txt @@ -0,0 +1,28 @@ +# Vectors from draft-ribose-cfrg-sm4-10.txt. Reformatted to work with the NIST loader +# Originally from GB/T 32907-2016 Example 1 +# SM4 ECB +[ENCRYPT] + +# A.1.1/A.1.2 +COUNT = 0 +KEY = 0123456789abcdeffedcba9876543210 +PLAINTEXT = 0123456789abcdeffedcba9876543210 +CIPHERTEXT = 681edf34d206965e86b3e94f536e4246 + +# A.1.4/A.1.5 +COUNT = 1 +KEY = fedcba98765432100123456789abcdef +PLAINTEXT = 000102030405060708090a0b0c0d0e0f +CIPHERTEXT = f766678f13f01adeac1b3ea955adb594 + +# A.2.1.1 +COUNT = 2 +KEY = 0123456789abcdeffedcba9876543210 +PLAINTEXT = aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffaaaaaaaabbbbbbbb +CIPHERTEXT = 5ec8143de509cff7b5179f8f474b86192f1d305a7fb17df985f81c8482192304 + +# A.2.1.2 +COUNT = 3 +KEY = fedcba98765432100123456789abcdef +PLAINTEXT = aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffaaaaaaaabbbbbbbb +CIPHERTEXT = c5876897e4a59bbba72a10c83872245b12dd90bc2d200692b529a4155ac9e600 diff --git a/vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-ofb.txt b/vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-ofb.txt new file mode 100644 index 000000000000..27c611d2a8f5 --- /dev/null +++ b/vectors/cryptography_vectors/ciphers/SM4/draft-ribose-cfrg-sm4-10-ofb.txt @@ -0,0 +1,17 @@ +# Vectors from draft-ribose-cfrg-sm4-10.txt. Reformatted to work with the NIST loader +# SM4 OFB +[ENCRYPT] + +# A.2.3.1 +COUNT = 0 +KEY = 0123456789abcdeffedcba9876543210 +PLAINTEXT = aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffaaaaaaaabbbbbbbb +IV = 000102030405060708090a0b0c0d0e0f +CIPHERTEXT = ac3236cb861dd316e6413b4e3c7524b71d01aca2487ca582cbf5463e6698539b + +# A.2.3.2 +COUNT = 1 +KEY = fedcba98765432100123456789abcdef +PLAINTEXT = aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffaaaaaaaabbbbbbbb +IV = 000102030405060708090a0b0c0d0e0f +CIPHERTEXT = 5dcccd25a84ba16560d7f2658870684933fa16bd5cd9c856cacaa1e101897a97 From bdca10e3f7c850a54bda9e9332b8df9493d0a8fa Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 28 Feb 2021 15:26:12 -0600 Subject: [PATCH 0164/2380] tell people SM3/SM4 are available for compat/compliance reasons (#5878) * tell people SM3/SM4 are available for compat/compliance reasons * add to changelog and linkcheck fix * tweaked language --- CHANGELOG.rst | 6 ++++++ docs/hazmat/primitives/cryptographic-hashes.rst | 3 ++- docs/hazmat/primitives/symmetric-encryption.rst | 7 ++++--- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 8a7a663c76d8..f2aaebb5c27a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,12 @@ Changelog .. note:: This version is not yet released and is under active development. +* Added support for + :class:`~cryptography.hazmat.primitives.hashes.SM3` and + :class:`~cryptography.hazmat.primitives.ciphers.algorithms.SM4`, + when using OpenSSL 1.1.1. These algorithms are provided for compatibility + in regions where they may be required, and are not generally recommended. + .. _v3-4-6: 3.4.6 - 2021-02-16 diff --git a/docs/hazmat/primitives/cryptographic-hashes.rst b/docs/hazmat/primitives/cryptographic-hashes.rst index f79f8d7066cb..a113992513e3 100644 --- a/docs/hazmat/primitives/cryptographic-hashes.rst +++ b/docs/hazmat/primitives/cryptographic-hashes.rst @@ -255,7 +255,8 @@ SM3 SM3 is a cryptographic hash function standardized by the Chinese National Cryptography Administration in `GM/T 0004-2012`_. It produces 256-bit message digests. (An English description is available at - `draft-oscca-cfrg-sm3-02`_.) + `draft-oscca-cfrg-sm3-02`_.) This hash should be used for compatibility + purposes where required and is not otherwise recommended for use. Interfaces diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst index 6e10d67fef82..985a9502c345 100644 --- a/docs/hazmat/primitives/symmetric-encryption.rst +++ b/docs/hazmat/primitives/symmetric-encryption.rst @@ -201,9 +201,11 @@ Algorithms .. versionadded:: 35.0.0 SM4 is a block cipher developed by the Chinese Government and standardized - in the `GB/T 32907-2016`_. It is used in the Chinese WAPI + in the GB/T 32907-2016. It is used in the Chinese WAPI (Wired Authentication and Privacy Infrastructure) standard. (An English - description is available at `draft-ribose-cfrg-sm4-10`_.) + description is available at `draft-ribose-cfrg-sm4-10`_.) This block + cipher should be used for compatibility purposes where required and is + not otherwise recommended for use. :param key: The secret key. This must be kept secret. ``128`` :term:`bits` in length. @@ -828,5 +830,4 @@ Exceptions .. _`International Data Encryption Algorithm`: https://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm .. _`OpenPGP`: https://www.openpgp.org/ .. _`disk encryption`: https://en.wikipedia.org/wiki/Disk_encryption_theory#XTS -.. _`GB/T 32907-2016`: http://www.cnnic.cn/gcjsyj/qyjsyj/mmsfbz/sm4/201312/t20131204_43341.htm .. _`draft-ribose-cfrg-sm4-10`: https://tools.ietf.org/html/draft-ribose-cfrg-sm4-10 From e2449138c0bfce8ea82cad050be0e8355508ab43 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 28 Feb 2021 16:06:11 -0600 Subject: [PATCH 0165/2380] fix pkcs12 parse ordering. fixes #5872 (#5879) * fix pkcs12 parse ordering. fixes #5872 * remove an unneeded print * simplify the test a bit more * index * black * Update tests/hazmat/primitives/test_pkcs12.py Co-authored-by: Alex Gaynor Co-authored-by: Alex Gaynor --- .../hazmat/backends/openssl/backend.py | 8 +-- tests/hazmat/primitives/test_pkcs12.py | 58 ++++++++++++++++++- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index bb934094086a..9dc4ca059ca4 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -2524,7 +2524,9 @@ def load_key_and_certificates_from_pkcs12(self, data, password): if sk_x509_ptr[0] != self._ffi.NULL: sk_x509 = self._ffi.gc(sk_x509_ptr[0], self._lib.sk_X509_free) num = self._lib.sk_X509_num(sk_x509_ptr[0]) - for i in range(num): + # In OpenSSL < 3.0.0 PKCS12 parsing reverses the order of the + # certificates. + for i in reversed(range(num)): x509 = self._lib.sk_X509_value(sk_x509, i) self.openssl_assert(x509 != self._ffi.NULL) x509 = self._ffi.gc(x509, self._lib.X509_free) @@ -2567,9 +2569,7 @@ def serialize_key_and_certificates_to_pkcs12( sk_x509 = self._lib.sk_X509_new_null() sk_x509 = self._ffi.gc(sk_x509, self._lib.sk_X509_free) - # reverse the list when building the stack so that they're encoded - # in the order they were originally provided. it is a mystery - for ca in reversed(cas): + for ca in cas: res = self._lib.sk_X509_push(sk_x509, ca._x509) backend.openssl_assert(res >= 1) diff --git a/tests/hazmat/primitives/test_pkcs12.py b/tests/hazmat/primitives/test_pkcs12.py index b5de09f95ca4..b1759a1bc8ab 100644 --- a/tests/hazmat/primitives/test_pkcs12.py +++ b/tests/hazmat/primitives/test_pkcs12.py @@ -4,13 +4,15 @@ import os +from datetime import datetime import pytest from cryptography import x509 from cryptography.hazmat.backends.interfaces import DERSerializationBackend from cryptography.hazmat.backends.openssl.backend import _RC2 -from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives.serialization import load_pem_private_key from cryptography.hazmat.primitives.serialization.pkcs12 import ( load_key_and_certificates, @@ -273,3 +275,57 @@ def test_generate_unsupported_encryption_type(self, backend): DummyKeySerializationEncryption(), ) assert str(exc.value) == "Unsupported key encryption type" + + +def test_pkcs12_ordering(): + """ + In OpenSSL < 3.0.0 PKCS12 parsing reverses the order. However, we + accidentally thought it was **encoding** that did it, leading to bug + https://github.com/pyca/cryptography/issues/5872 + This test ensures our ordering is correct going forward. + """ + + def make_cert(name): + key = ec.generate_private_key(ec.SECP256R1()) + subject = x509.Name( + [ + x509.NameAttribute(x509.NameOID.COMMON_NAME, name), + ] + ) + now = datetime.utcnow() + cert = ( + x509.CertificateBuilder() + .subject_name(subject) + .issuer_name(subject) + .public_key(key.public_key()) + .serial_number(x509.random_serial_number()) + .not_valid_before(now) + .not_valid_after(now) + .sign(key, hashes.SHA256()) + ) + return (key, cert) + + # Make some certificates with distinct names. + a_name = "A" * 20 + b_name = "B" * 20 + c_name = "C" * 20 + a_key, a_cert = make_cert(a_name) + _, b_cert = make_cert(b_name) + _, c_cert = make_cert(c_name) + + # Bundle them in a PKCS#12 file in order A, B, C. + p12 = serialize_key_and_certificates( + b"p12", a_key, a_cert, [b_cert, c_cert], serialization.NoEncryption() + ) + + # Parse them out. The API should report them in the same order. + (key, cert, certs) = load_key_and_certificates(p12, None) + assert cert == a_cert + assert certs == [b_cert, c_cert] + + # The ordering in the PKCS#12 file itself should also match. + a_idx = p12.index(a_name.encode("utf-8")) + b_idx = p12.index(b_name.encode("utf-8")) + c_idx = p12.index(c_name.encode("utf-8")) + + assert a_idx < b_idx < c_idx From 08c6484cd9534a2fc6a2accad17d1cc61d7ba764 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 28 Feb 2021 17:00:52 -0600 Subject: [PATCH 0166/2380] update ocsp docs to use sha256 (#5880) rfc 6960 suggests it and we want our docs to be best practice --- docs/x509/ocsp.rst | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/docs/x509/ocsp.rst b/docs/x509/ocsp.rst index 6a3e1e7064f2..99864620d854 100644 --- a/docs/x509/ocsp.rst +++ b/docs/x509/ocsp.rst @@ -168,16 +168,19 @@ Creating Requests .. doctest:: >>> from cryptography.hazmat.primitives import serialization - >>> from cryptography.hazmat.primitives.hashes import SHA1 + >>> from cryptography.hazmat.primitives.hashes import SHA256 >>> from cryptography.x509 import load_pem_x509_certificate, ocsp >>> cert = load_pem_x509_certificate(pem_cert) >>> issuer = load_pem_x509_certificate(pem_issuer) >>> builder = ocsp.OCSPRequestBuilder() - >>> # SHA1 is in this example because RFC 5019 mandates its use. - >>> builder = builder.add_certificate(cert, issuer, SHA1()) + >>> # SHA256 is in this example because while RFC 5019 originally + >>> # required SHA1 RFC 6960 updates that to SHA256. + >>> # However, depending on your requirements you may need to use SHA1 + >>> # for compatibility reasons. + >>> builder = builder.add_certificate(cert, issuer, SHA256()) >>> req = builder.build() >>> base64.b64encode(req.public_bytes(serialization.Encoding.DER)) - b'MEMwQTA/MD0wOzAJBgUrDgMCGgUABBRAC0Z68eay0wmDug1gfn5ZN0gkxAQUw5zz/NNGCDS7zkZ/oHxb8+IIy1kCAj8g' + b'MF8wXTBbMFkwVzANBglghkgBZQMEAgEFAAQgn3BowBaoh77h17ULfkX6781dUDPD82Taj8wO1jZWhZoEINxPgjoQth3w7q4AouKKerMxIMIuUG4EuWU2pZfwih52AgI/IA==' Loading Responses ~~~~~~~~~~~~~~~~~ @@ -321,9 +324,12 @@ Creating Responses >>> responder_cert = load_pem_x509_certificate(pem_responder_cert) >>> responder_key = serialization.load_pem_private_key(pem_responder_key, None) >>> builder = ocsp.OCSPResponseBuilder() - >>> # SHA1 is in this example because RFC 5019 mandates its use. + >>> # SHA256 is in this example because while RFC 5019 originally + >>> # required SHA1 RFC 6960 updates that to SHA256. + >>> # However, depending on your requirements you may need to use SHA1 + >>> # for compatibility reasons. >>> builder = builder.add_response( - ... cert=cert, issuer=issuer, algorithm=hashes.SHA1(), + ... cert=cert, issuer=issuer, algorithm=hashes.SHA256(), ... cert_status=ocsp.OCSPCertStatus.GOOD, ... this_update=datetime.datetime.now(), ... next_update=datetime.datetime.now(), From 38381f63f61470128814f5daefa596c8ba3a0e09 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 28 Feb 2021 17:14:29 -0600 Subject: [PATCH 0167/2380] keep on typing (#5881) * keep on typing * swear i did this --- .../hazmat/primitives/twofactor/hotp.py | 33 +++++++++++++++- .../hazmat/primitives/twofactor/totp.py | 2 +- .../hazmat/primitives/twofactor/utils.py | 38 ------------------- 3 files changed, 33 insertions(+), 40 deletions(-) delete mode 100644 src/cryptography/hazmat/primitives/twofactor/utils.py diff --git a/src/cryptography/hazmat/primitives/twofactor/hotp.py b/src/cryptography/hazmat/primitives/twofactor/hotp.py index 01da4707b421..26e786fd4c37 100644 --- a/src/cryptography/hazmat/primitives/twofactor/hotp.py +++ b/src/cryptography/hazmat/primitives/twofactor/hotp.py @@ -3,8 +3,10 @@ # for complete details. +import base64 import struct import typing +from urllib.parse import quote, urlencode from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.backends import _get_backend @@ -12,12 +14,41 @@ from cryptography.hazmat.primitives import constant_time, hmac from cryptography.hazmat.primitives.hashes import SHA1, SHA256, SHA512 from cryptography.hazmat.primitives.twofactor import InvalidToken -from cryptography.hazmat.primitives.twofactor.utils import _generate_uri _ALLOWED_HASH_TYPES = typing.Union[SHA1, SHA256, SHA512] +def _generate_uri( + hotp: "HOTP", + type_name: str, + account_name: str, + issuer: typing.Optional[str], + extra_parameters, +) -> str: + parameters = [ + ("digits", hotp._length), + ("secret", base64.b32encode(hotp._key)), + ("algorithm", hotp._algorithm.name.upper()), + ] + + if issuer is not None: + parameters.append(("issuer", issuer)) + + parameters.extend(extra_parameters) + + uriparts = { + "type": type_name, + "label": ( + "%s:%s" % (quote(issuer), quote(account_name)) + if issuer + else quote(account_name) + ), + "parameters": urlencode(parameters), + } + return "otpauth://{type}/{label}?{parameters}".format(**uriparts) + + class HOTP(object): def __init__( self, diff --git a/src/cryptography/hazmat/primitives/twofactor/totp.py b/src/cryptography/hazmat/primitives/twofactor/totp.py index 727891180489..92bf6496867d 100644 --- a/src/cryptography/hazmat/primitives/twofactor/totp.py +++ b/src/cryptography/hazmat/primitives/twofactor/totp.py @@ -12,8 +12,8 @@ from cryptography.hazmat.primitives.twofactor.hotp import ( HOTP, _ALLOWED_HASH_TYPES, + _generate_uri, ) -from cryptography.hazmat.primitives.twofactor.utils import _generate_uri class TOTP(object): diff --git a/src/cryptography/hazmat/primitives/twofactor/utils.py b/src/cryptography/hazmat/primitives/twofactor/utils.py deleted file mode 100644 index fcf40c8837cf..000000000000 --- a/src/cryptography/hazmat/primitives/twofactor/utils.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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. - - -import base64 -import typing -from urllib.parse import quote, urlencode - - -def _generate_uri( - hotp, - type_name: str, - account_name: str, - issuer: typing.Optional[str], - extra_parameters, -) -> str: - parameters = [ - ("digits", hotp._length), - ("secret", base64.b32encode(hotp._key)), - ("algorithm", hotp._algorithm.name.upper()), - ] - - if issuer is not None: - parameters.append(("issuer", issuer)) - - parameters.extend(extra_parameters) - - uriparts = { - "type": type_name, - "label": ( - "%s:%s" % (quote(issuer), quote(account_name)) - if issuer - else quote(account_name) - ), - "parameters": urlencode(parameters), - } - return "otpauth://{type}/{label}?{parameters}".format(**uriparts) From ed1dea60795d6b0fd844a8da9a5e81569fff8eb3 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 28 Feb 2021 17:59:39 -0600 Subject: [PATCH 0168/2380] changes to support typing backend (#5882) this gets rid of the conditional backend type registration --- .../hazmat/backends/interfaces.py | 6 ++++ .../hazmat/backends/openssl/backend.py | 34 ++++++++++--------- tests/hazmat/primitives/test_scrypt.py | 4 +++ 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/cryptography/hazmat/backends/interfaces.py b/src/cryptography/hazmat/backends/interfaces.py index c5dfed3114c6..d5debb5426e0 100644 --- a/src/cryptography/hazmat/backends/interfaces.py +++ b/src/cryptography/hazmat/backends/interfaces.py @@ -378,3 +378,9 @@ def derive_scrypt(self, key_material, salt, length, n, r, p): """ Return bytes derived from provided Scrypt parameters. """ + + @abc.abstractmethod + def scrypt_supported(self): + """ + Return True if Scrypt is supported. + """ diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 9dc4ca059ca4..fb0070386505 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -161,22 +161,21 @@ class _RC2(object): pass -@utils.register_interface(CipherBackend) -@utils.register_interface(CMACBackend) -@utils.register_interface(DERSerializationBackend) -@utils.register_interface(DHBackend) -@utils.register_interface(DSABackend) -@utils.register_interface(EllipticCurveBackend) -@utils.register_interface(HashBackend) -@utils.register_interface(HMACBackend) -@utils.register_interface(PBKDF2HMACBackend) -@utils.register_interface(RSABackend) -@utils.register_interface(PEMSerializationBackend) -@utils.register_interface(X509Backend) -@utils.register_interface_if( - binding.Binding().lib.Cryptography_HAS_SCRYPT, ScryptBackend -) -class Backend(object): +class Backend( + CipherBackend, + CMACBackend, + DERSerializationBackend, + DHBackend, + DSABackend, + EllipticCurveBackend, + HashBackend, + HMACBackend, + PBKDF2HMACBackend, + RSABackend, + PEMSerializationBackend, + ScryptBackend, + X509Backend, +): """ OpenSSL API binding interfaces. """ @@ -343,6 +342,9 @@ def hash_supported(self, algorithm): evp_md = self._evp_md_from_algorithm(algorithm) return evp_md != self._ffi.NULL + def scrypt_supported(self): + return self._lib.Cryptography_HAS_SCRYPT == 1 + def hmac_supported(self, algorithm): return self.hash_supported(algorithm) diff --git a/tests/hazmat/primitives/test_scrypt.py b/tests/hazmat/primitives/test_scrypt.py index f6bbd0bcf295..d3fea28ca7c8 100644 --- a/tests/hazmat/primitives/test_scrypt.py +++ b/tests/hazmat/primitives/test_scrypt.py @@ -44,6 +44,10 @@ def test_memory_limit_skip(): _skip_if_memory_limited(2 ** 31, {"p": 16, "r": 64, "n": 1024}) +@pytest.mark.supported( + only_if=lambda backend: backend.scrypt_supported(), + skip_message="Does not support Scrypt", +) @pytest.mark.requires_backend_interface(interface=ScryptBackend) class TestScrypt(object): @pytest.mark.parametrize("params", vectors) From 245d15b5636392113af7db501196fd2930f776f8 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 1 Mar 2021 12:59:24 -0500 Subject: [PATCH 0169/2380] Remove requires_backend_interface from tests because it was useless (#5884) --- pyproject.toml | 1 - tests/conftest.py | 13 -- tests/hazmat/backends/test_openssl.py | 3 - tests/hazmat/primitives/test_3des.py | 6 - tests/hazmat/primitives/test_aead.py | 5 - tests/hazmat/primitives/test_aes.py | 9 -- tests/hazmat/primitives/test_aes_gcm.py | 2 - tests/hazmat/primitives/test_arc4.py | 2 - tests/hazmat/primitives/test_block.py | 5 - tests/hazmat/primitives/test_blowfish.py | 5 - tests/hazmat/primitives/test_camellia.py | 5 - tests/hazmat/primitives/test_cast5.py | 5 - tests/hazmat/primitives/test_chacha20.py | 2 - tests/hazmat/primitives/test_ciphers.py | 4 - tests/hazmat/primitives/test_cmac.py | 2 - tests/hazmat/primitives/test_concatkdf.py | 4 - tests/hazmat/primitives/test_dh.py | 15 --- tests/hazmat/primitives/test_dsa.py | 12 -- tests/hazmat/primitives/test_ec.py | 18 --- tests/hazmat/primitives/test_hash_vectors.py | 18 --- tests/hazmat/primitives/test_hashes.py | 12 -- tests/hazmat/primitives/test_hkdf.py | 3 - tests/hazmat/primitives/test_hkdf_vectors.py | 3 - tests/hazmat/primitives/test_hmac.py | 3 - tests/hazmat/primitives/test_hmac_vectors.py | 8 -- tests/hazmat/primitives/test_idea.py | 5 - tests/hazmat/primitives/test_kbkdf.py | 2 - tests/hazmat/primitives/test_kbkdf_vectors.py | 5 - tests/hazmat/primitives/test_keywrap.py | 3 - .../primitives/test_pbkdf2hmac_vectors.py | 2 - tests/hazmat/primitives/test_pkcs12.py | 2 - tests/hazmat/primitives/test_rsa.py | 17 --- tests/hazmat/primitives/test_scrypt.py | 2 - tests/hazmat/primitives/test_seed.py | 5 - tests/hazmat/primitives/test_serialization.py | 29 ----- tests/hazmat/primitives/test_sm4.py | 6 - tests/hazmat/primitives/test_x963_vectors.py | 2 - tests/hazmat/primitives/test_x963kdf.py | 2 - .../hazmat/primitives/twofactor/test_hotp.py | 2 - .../hazmat/primitives/twofactor/test_totp.py | 2 - tests/test_fernet.py | 5 - tests/wycheproof/test_aes.py | 5 - tests/wycheproof/test_chacha20poly1305.py | 2 - tests/wycheproof/test_cmac.py | 2 - tests/wycheproof/test_dsa.py | 2 - tests/wycheproof/test_ecdh.py | 3 - tests/wycheproof/test_ecdsa.py | 2 - tests/wycheproof/test_keywrap.py | 3 - tests/wycheproof/test_rsa.py | 4 - tests/x509/test_x509.py | 120 ------------------ tests/x509/test_x509_crlbuilder.py | 44 ------- tests/x509/test_x509_ext.py | 68 ---------- tests/x509/test_x509_revokedcertbuilder.py | 9 -- 53 files changed, 520 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ecd77063890c..2c90d97ae06c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,6 @@ target-version = ["py36"] [tool.pytest.ini_options] addopts = "-r s" markers = [ - "requires_backend_interface: this test requires a specific backend interface", "skip_fips: this test is not executed in FIPS mode", "supported: parametrized test requiring only_if and skip_message", "wycheproof_tests: this test runs a wycheproof fixture", diff --git a/tests/conftest.py b/tests/conftest.py index 43debdd61a85..2fea50c17b8f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -31,18 +31,5 @@ def pytest_runtest_setup(item): @pytest.fixture() def backend(request): - required_interfaces = [ - mark.kwargs["interface"] - for mark in request.node.iter_markers("requires_backend_interface") - ] - if not all( - isinstance(openssl_backend, iface) for iface in required_interfaces - ): - pytest.skip( - "OpenSSL doesn't implement required interfaces: {}".format( - required_interfaces - ) - ) - check_backend_support(openssl_backend, request) return openssl_backend diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index 4211b5d39128..e6abadbd099e 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -13,7 +13,6 @@ from cryptography import x509 from cryptography.exceptions import InternalError, _Reasons -from cryptography.hazmat.backends.interfaces import DHBackend, RSABackend from cryptography.hazmat.backends.openssl.backend import Backend, backend from cryptography.hazmat.backends.openssl.ec import _sn_to_elliptic_curve from cryptography.hazmat.primitives import hashes, serialization @@ -566,7 +565,6 @@ def test_sn_to_elliptic_curve_not_supported(self): _sn_to_elliptic_curve(backend, b"fake") -@pytest.mark.requires_backend_interface(interface=RSABackend) class TestRSAPEMSerialization(object): def test_password_length_limit(self): password = b"x" * 1024 @@ -607,7 +605,6 @@ def test_numeric_string_x509_name_entry(self): backend._lib.Cryptography_HAS_EVP_PKEY_DHX == 1, reason="Requires OpenSSL without EVP_PKEY_DHX (< 1.0.2)", ) -@pytest.mark.requires_backend_interface(interface=DHBackend) class TestOpenSSLDHSerialization(object): @pytest.mark.parametrize( "vector", diff --git a/tests/hazmat/primitives/test_3des.py b/tests/hazmat/primitives/test_3des.py index f1bca78c0454..53c2080df0e1 100644 --- a/tests/hazmat/primitives/test_3des.py +++ b/tests/hazmat/primitives/test_3des.py @@ -12,7 +12,6 @@ import pytest -from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives.ciphers import algorithms, modes from .utils import generate_encrypt_test @@ -25,7 +24,6 @@ ), skip_message="Does not support TripleDES CBC", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestTripleDESModeCBC(object): test_kat = generate_encrypt_test( load_nist_vectors, @@ -58,7 +56,6 @@ class TestTripleDESModeCBC(object): ), skip_message="Does not support TripleDES OFB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestTripleDESModeOFB(object): test_kat = generate_encrypt_test( load_nist_vectors, @@ -91,7 +88,6 @@ class TestTripleDESModeOFB(object): ), skip_message="Does not support TripleDES CFB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestTripleDESModeCFB(object): test_kat = generate_encrypt_test( load_nist_vectors, @@ -124,7 +120,6 @@ class TestTripleDESModeCFB(object): ), skip_message="Does not support TripleDES CFB8", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestTripleDESModeCFB8(object): test_kat = generate_encrypt_test( load_nist_vectors, @@ -157,7 +152,6 @@ class TestTripleDESModeCFB8(object): ), skip_message="Does not support TripleDES ECB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestTripleDESModeECB(object): test_kat = generate_encrypt_test( load_nist_vectors, diff --git a/tests/hazmat/primitives/test_aead.py b/tests/hazmat/primitives/test_aead.py index 87df06c6a8f0..e90308a07533 100644 --- a/tests/hazmat/primitives/test_aead.py +++ b/tests/hazmat/primitives/test_aead.py @@ -9,7 +9,6 @@ import pytest from cryptography.exceptions import InvalidTag, UnsupportedAlgorithm, _Reasons -from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives.ciphers.aead import ( AESCCM, AESGCM, @@ -42,7 +41,6 @@ def _aead_supported(cls): _aead_supported(ChaCha20Poly1305), reason="Requires OpenSSL without ChaCha20Poly1305 support", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) def test_chacha20poly1305_unsupported_on_older_openssl(backend): with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER): ChaCha20Poly1305(ChaCha20Poly1305.generate_key()) @@ -52,7 +50,6 @@ def test_chacha20poly1305_unsupported_on_older_openssl(backend): not _aead_supported(ChaCha20Poly1305), reason="Does not support ChaCha20Poly1305", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestChaCha20Poly1305(object): def test_data_too_large(self): key = ChaCha20Poly1305.generate_key() @@ -185,7 +182,6 @@ def test_buffer_protocol(self, backend): assert computed_pt2 == pt -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestAESCCM(object): def test_data_too_large(self): key = AESCCM.generate_key(128) @@ -359,7 +355,6 @@ def _load_gcm_vectors(): return [x for x in vectors if len(x["tag"]) == 32 and len(x["iv"]) >= 16] -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestAESGCM(object): def test_data_too_large(self): key = AESGCM.generate_key(128) diff --git a/tests/hazmat/primitives/test_aes.py b/tests/hazmat/primitives/test_aes.py index c9cb980037f8..29a9404633fb 100644 --- a/tests/hazmat/primitives/test_aes.py +++ b/tests/hazmat/primitives/test_aes.py @@ -8,7 +8,6 @@ import pytest -from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives.ciphers import algorithms, base, modes from .utils import _load_all_params, generate_encrypt_test @@ -22,7 +21,6 @@ ), skip_message="Does not support AES XTS", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestAESModeXTS(object): def test_xts_vectors(self, backend, subtests): # This list comprehension excludes any vector that does not have a @@ -61,7 +59,6 @@ def test_xts_vectors(self, backend, subtests): ), skip_message="Does not support AES CBC", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestAESModeCBC(object): test_cbc = generate_encrypt_test( load_nist_vectors, @@ -94,7 +91,6 @@ class TestAESModeCBC(object): ), skip_message="Does not support AES ECB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestAESModeECB(object): test_ecb = generate_encrypt_test( load_nist_vectors, @@ -127,7 +123,6 @@ class TestAESModeECB(object): ), skip_message="Does not support AES OFB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestAESModeOFB(object): test_ofb = generate_encrypt_test( load_nist_vectors, @@ -160,7 +155,6 @@ class TestAESModeOFB(object): ), skip_message="Does not support AES CFB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestAESModeCFB(object): test_cfb = generate_encrypt_test( load_nist_vectors, @@ -193,7 +187,6 @@ class TestAESModeCFB(object): ), skip_message="Does not support AES CFB8", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestAESModeCFB8(object): test_cfb8 = generate_encrypt_test( load_nist_vectors, @@ -226,7 +219,6 @@ class TestAESModeCFB8(object): ), skip_message="Does not support AES CTR", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestAESModeCTR(object): test_ctr = generate_encrypt_test( load_nist_vectors, @@ -250,7 +242,6 @@ class TestAESModeCTR(object): DummyMode(), ], ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) def test_buffer_protocol_alternate_modes(mode, backend): data = bytearray(b"sixteen_byte_msg") key = algorithms.AES(bytearray(os.urandom(32))) diff --git a/tests/hazmat/primitives/test_aes_gcm.py b/tests/hazmat/primitives/test_aes_gcm.py index 77f9c6f2757c..bae213da82d9 100644 --- a/tests/hazmat/primitives/test_aes_gcm.py +++ b/tests/hazmat/primitives/test_aes_gcm.py @@ -8,7 +8,6 @@ import pytest -from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives.ciphers import algorithms, base, modes from .utils import generate_aead_test @@ -21,7 +20,6 @@ ), skip_message="Does not support AES GCM", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestAESModeGCM(object): test_gcm = generate_aead_test( load_nist_vectors, diff --git a/tests/hazmat/primitives/test_arc4.py b/tests/hazmat/primitives/test_arc4.py index be40b578c398..61c7a82d9619 100644 --- a/tests/hazmat/primitives/test_arc4.py +++ b/tests/hazmat/primitives/test_arc4.py @@ -8,7 +8,6 @@ import pytest -from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives.ciphers import algorithms from .utils import generate_stream_encryption_test @@ -21,7 +20,6 @@ ), skip_message="Does not support ARC4", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestARC4(object): test_rfc = generate_stream_encryption_test( load_nist_vectors, diff --git a/tests/hazmat/primitives/test_block.py b/tests/hazmat/primitives/test_block.py index 1e01628ad7aa..135c2a0907ab 100644 --- a/tests/hazmat/primitives/test_block.py +++ b/tests/hazmat/primitives/test_block.py @@ -8,7 +8,6 @@ import pytest from cryptography.exceptions import AlreadyFinalized, _Reasons -from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives.ciphers import ( Cipher, algorithms, @@ -24,7 +23,6 @@ from ...utils import raises_unsupported_algorithm -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestCipher(object): def test_creates_encryptor(self, backend): cipher = Cipher( @@ -50,7 +48,6 @@ def test_instantiate_with_non_algorithm(self, backend): ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestCipherContext(object): def test_use_after_finalize(self, backend): cipher = Cipher( @@ -134,7 +131,6 @@ def test_incorrectly_padded(self, backend): ), skip_message="Does not support AES GCM", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestAEADCipherContext(object): test_aead_exceptions = generate_aead_exception_test( algorithms.AES, @@ -146,7 +142,6 @@ class TestAEADCipherContext(object): ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestModeValidation(object): def test_cbc(self, backend): with pytest.raises(ValueError): diff --git a/tests/hazmat/primitives/test_blowfish.py b/tests/hazmat/primitives/test_blowfish.py index ca0aaaa7848f..beb95062c1a3 100644 --- a/tests/hazmat/primitives/test_blowfish.py +++ b/tests/hazmat/primitives/test_blowfish.py @@ -8,7 +8,6 @@ import pytest -from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives.ciphers import algorithms, modes from .utils import generate_encrypt_test @@ -21,7 +20,6 @@ ), skip_message="Does not support Blowfish ECB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestBlowfishModeECB(object): test_ecb = generate_encrypt_test( load_nist_vectors, @@ -38,7 +36,6 @@ class TestBlowfishModeECB(object): ), skip_message="Does not support Blowfish CBC", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestBlowfishModeCBC(object): test_cbc = generate_encrypt_test( load_nist_vectors, @@ -55,7 +52,6 @@ class TestBlowfishModeCBC(object): ), skip_message="Does not support Blowfish OFB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestBlowfishModeOFB(object): test_ofb = generate_encrypt_test( load_nist_vectors, @@ -72,7 +68,6 @@ class TestBlowfishModeOFB(object): ), skip_message="Does not support Blowfish CFB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestBlowfishModeCFB(object): test_cfb = generate_encrypt_test( load_nist_vectors, diff --git a/tests/hazmat/primitives/test_camellia.py b/tests/hazmat/primitives/test_camellia.py index f903c8156625..b783383d03e3 100644 --- a/tests/hazmat/primitives/test_camellia.py +++ b/tests/hazmat/primitives/test_camellia.py @@ -8,7 +8,6 @@ import pytest -from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives.ciphers import algorithms, modes from .utils import generate_encrypt_test @@ -21,7 +20,6 @@ ), skip_message="Does not support Camellia ECB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestCamelliaModeECB(object): test_ecb = generate_encrypt_test( load_cryptrec_vectors, @@ -42,7 +40,6 @@ class TestCamelliaModeECB(object): ), skip_message="Does not support Camellia CBC", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestCamelliaModeCBC(object): test_cbc = generate_encrypt_test( load_nist_vectors, @@ -59,7 +56,6 @@ class TestCamelliaModeCBC(object): ), skip_message="Does not support Camellia OFB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestCamelliaModeOFB(object): test_ofb = generate_encrypt_test( load_nist_vectors, @@ -76,7 +72,6 @@ class TestCamelliaModeOFB(object): ), skip_message="Does not support Camellia CFB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestCamelliaModeCFB(object): test_cfb = generate_encrypt_test( load_nist_vectors, diff --git a/tests/hazmat/primitives/test_cast5.py b/tests/hazmat/primitives/test_cast5.py index 9b720594795a..093330bd7f78 100644 --- a/tests/hazmat/primitives/test_cast5.py +++ b/tests/hazmat/primitives/test_cast5.py @@ -8,7 +8,6 @@ import pytest -from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives.ciphers import algorithms, modes from .utils import generate_encrypt_test @@ -21,7 +20,6 @@ ), skip_message="Does not support CAST5 ECB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestCAST5ModeECB(object): test_ecb = generate_encrypt_test( load_nist_vectors, @@ -38,7 +36,6 @@ class TestCAST5ModeECB(object): ), skip_message="Does not support CAST5 CBC", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestCAST5ModeCBC(object): test_cbc = generate_encrypt_test( load_nist_vectors, @@ -55,7 +52,6 @@ class TestCAST5ModeCBC(object): ), skip_message="Does not support CAST5 OFB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestCAST5ModeOFB(object): test_ofb = generate_encrypt_test( load_nist_vectors, @@ -72,7 +68,6 @@ class TestCAST5ModeOFB(object): ), skip_message="Does not support CAST5 CFB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestCAST5ModeCFB(object): test_cfb = generate_encrypt_test( load_nist_vectors, diff --git a/tests/hazmat/primitives/test_chacha20.py b/tests/hazmat/primitives/test_chacha20.py index 03165a4d1c32..72e63c376c15 100644 --- a/tests/hazmat/primitives/test_chacha20.py +++ b/tests/hazmat/primitives/test_chacha20.py @@ -9,7 +9,6 @@ import pytest -from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives.ciphers import Cipher, algorithms from .utils import _load_all_params @@ -22,7 +21,6 @@ ), skip_message="Does not support ChaCha20", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestChaCha20(object): @pytest.mark.parametrize( "vector", diff --git a/tests/hazmat/primitives/test_ciphers.py b/tests/hazmat/primitives/test_ciphers.py index e82e3c26d995..f00282eccdeb 100644 --- a/tests/hazmat/primitives/test_ciphers.py +++ b/tests/hazmat/primitives/test_ciphers.py @@ -9,7 +9,6 @@ import pytest from cryptography.exceptions import AlreadyFinalized, _Reasons -from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives import ciphers from cryptography.hazmat.primitives.ciphers import modes from cryptography.hazmat.primitives.ciphers.algorithms import ( @@ -49,7 +48,6 @@ def test_invalid_key_type(self): class TestAESXTS(object): - @pytest.mark.requires_backend_interface(interface=CipherBackend) @pytest.mark.parametrize( "mode", (modes.CBC, modes.CTR, modes.CFB, modes.CFB8, modes.OFB) ) @@ -65,7 +63,6 @@ def test_xts_tweak_too_small(self): with pytest.raises(ValueError): modes.XTS(b"0") - @pytest.mark.requires_backend_interface(interface=CipherBackend) def test_xts_wrong_key_size(self, backend): with pytest.raises(ValueError): ciphers.Cipher(AES(b"0" * 16), modes.XTS(b"0" * 16), backend) @@ -214,7 +211,6 @@ def test_invalid_backend(): ), skip_message="Does not support AES ECB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestCipherUpdateInto(object): @pytest.mark.parametrize( "params", diff --git a/tests/hazmat/primitives/test_cmac.py b/tests/hazmat/primitives/test_cmac.py index 0022ab05c5e6..1c8841ac849e 100644 --- a/tests/hazmat/primitives/test_cmac.py +++ b/tests/hazmat/primitives/test_cmac.py @@ -12,7 +12,6 @@ InvalidSignature, _Reasons, ) -from cryptography.hazmat.backends.interfaces import CMACBackend from cryptography.hazmat.primitives.ciphers.algorithms import ( AES, ARC4, @@ -48,7 +47,6 @@ fake_key = b"\x00" * 16 -@pytest.mark.requires_backend_interface(interface=CMACBackend) class TestCMAC(object): @pytest.mark.supported( only_if=lambda backend: backend.cmac_algorithm_supported( diff --git a/tests/hazmat/primitives/test_concatkdf.py b/tests/hazmat/primitives/test_concatkdf.py index 8a6ee2e41200..18134eecac06 100644 --- a/tests/hazmat/primitives/test_concatkdf.py +++ b/tests/hazmat/primitives/test_concatkdf.py @@ -8,8 +8,6 @@ import pytest from cryptography.exceptions import AlreadyFinalized, InvalidKey, _Reasons -from cryptography.hazmat.backends.interfaces import HMACBackend -from cryptography.hazmat.backends.interfaces import HashBackend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.concatkdf import ConcatKDFHMAC from cryptography.hazmat.primitives.kdf.concatkdf import ConcatKDFHash @@ -17,7 +15,6 @@ from ...utils import raises_unsupported_algorithm -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestConcatKDFHash(object): def test_length_limit(self, backend): big_length = hashes.SHA256().digest_size * (2 ** 32 - 1) + 1 @@ -127,7 +124,6 @@ def test_unicode_typeerror(self, backend): ckdf.verify(b"foo", "bar") # type: ignore[arg-type] -@pytest.mark.requires_backend_interface(interface=HMACBackend) class TestConcatKDFHMAC(object): def test_length_limit(self, backend): big_length = hashes.SHA256().digest_size * (2 ** 32 - 1) + 1 diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index 131807fc0860..b37eca4eba54 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -10,11 +10,6 @@ import pytest -from cryptography.hazmat.backends.interfaces import ( - DERSerializationBackend, - DHBackend, - PEMSerializationBackend, -) from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import dh @@ -140,7 +135,6 @@ def test_dh_public_numbers_equality(): assert public != object() -@pytest.mark.requires_backend_interface(interface=DHBackend) class TestDH(object): def test_small_key_generate_dh(self, backend): with pytest.raises(ValueError): @@ -440,9 +434,6 @@ def test_dh_vectors_with_q(self, backend, vector): assert int.from_bytes(symkey2, "big") == int(vector["z"], 16) -@pytest.mark.requires_backend_interface(interface=DHBackend) -@pytest.mark.requires_backend_interface(interface=PEMSerializationBackend) -@pytest.mark.requires_backend_interface(interface=DERSerializationBackend) class TestDHPrivateKeySerialization(object): @pytest.mark.parametrize( ("encoding", "loader_func"), @@ -630,9 +621,6 @@ def test_private_bytes_unsupported_encryption_type(self, backend): ) -@pytest.mark.requires_backend_interface(interface=DHBackend) -@pytest.mark.requires_backend_interface(interface=PEMSerializationBackend) -@pytest.mark.requires_backend_interface(interface=DERSerializationBackend) class TestDHPublicKeySerialization(object): @pytest.mark.parametrize( ("encoding", "loader_func"), @@ -759,9 +747,6 @@ def test_public_bytes_pkcs1_unsupported(self, backend): ) -@pytest.mark.requires_backend_interface(interface=DHBackend) -@pytest.mark.requires_backend_interface(interface=PEMSerializationBackend) -@pytest.mark.requires_backend_interface(interface=DERSerializationBackend) class TestDHParameterSerialization(object): @pytest.mark.parametrize( ("encoding", "loader_func"), diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py index 6d8b2867fb81..066f83c4eca1 100644 --- a/tests/hazmat/primitives/test_dsa.py +++ b/tests/hazmat/primitives/test_dsa.py @@ -10,10 +10,6 @@ import pytest from cryptography.exceptions import AlreadyFinalized, InvalidSignature -from cryptography.hazmat.backends.interfaces import ( - DSABackend, - PEMSerializationBackend, -) from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import dsa from cryptography.hazmat.primitives.asymmetric.utils import ( @@ -49,13 +45,11 @@ def _skip_if_dsa_not_supported(backend, algorithm, p, q, g): ) -@pytest.mark.requires_backend_interface(interface=DSABackend) def test_skip_if_dsa_not_supported(backend): with pytest.raises(pytest.skip.Exception): _skip_if_dsa_not_supported(backend, DummyHashAlgorithm(), 1, 1, 1) -@pytest.mark.requires_backend_interface(interface=DSABackend) class TestDSA(object): def test_generate_dsa_parameters(self, backend): parameters = dsa.generate_parameters(2048, backend) @@ -385,7 +379,6 @@ def test_large_p(self, backend): ).private_key(backend) -@pytest.mark.requires_backend_interface(interface=DSABackend) class TestDSAVerification(object): def test_dsa_verification(self, backend, subtests): vectors = load_vectors_from_file( @@ -488,7 +481,6 @@ def test_prehashed_unsupported_in_verifier_ctx(self, backend): ) -@pytest.mark.requires_backend_interface(interface=DSABackend) class TestDSASignature(object): def test_dsa_signing(self, backend, subtests): vectors = load_vectors_from_file( @@ -693,8 +685,6 @@ def test_private_numbers_ne(self): assert priv != object() -@pytest.mark.requires_backend_interface(interface=DSABackend) -@pytest.mark.requires_backend_interface(interface=PEMSerializationBackend) class TestDSASerialization(object): @pytest.mark.parametrize( ("fmt", "password"), @@ -916,8 +906,6 @@ def test_private_bytes_unsupported_encryption_type(self, backend): ) -@pytest.mark.requires_backend_interface(interface=DSABackend) -@pytest.mark.requires_backend_interface(interface=PEMSerializationBackend) class TestDSAPEMPublicKeySerialization(object): @pytest.mark.parametrize( ("key_path", "loader_func", "encoding"), diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index c089adc43c76..708395867b6b 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -12,10 +12,6 @@ import pytest from cryptography import exceptions, utils, x509 -from cryptography.hazmat.backends.interfaces import ( - EllipticCurveBackend, - PEMSerializationBackend, -) from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives.asymmetric.utils import ( @@ -91,25 +87,21 @@ class DummySignatureAlgorithm(ec.EllipticCurveSignatureAlgorithm): algorithm = hashes.SHA256() -@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) def test_skip_curve_unsupported(backend): with pytest.raises(pytest.skip.Exception): _skip_curve_unsupported(backend, DummyCurve()) -@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) def test_skip_exchange_algorithm_unsupported(backend): with pytest.raises(pytest.skip.Exception): _skip_exchange_algorithm_unsupported(backend, ec.ECDH(), DummyCurve()) -@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) def test_skip_ecdsa_vector(backend): with pytest.raises(pytest.skip.Exception): _skip_ecdsa_vector(backend, DummyCurve, hashes.SHA256) -@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) def test_derive_private_key_success(backend): curve = ec.SECP256K1() _skip_curve_unsupported(backend, curve) @@ -123,7 +115,6 @@ def test_derive_private_key_success(backend): assert private_numbers == derived_key.private_numbers() -@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) def test_derive_private_key_errors(backend): curve = ec.SECP256K1() _skip_curve_unsupported(backend, curve) @@ -266,7 +257,6 @@ def test_ec_private_numbers_hash(): assert hash(numbers1) != hash(numbers3) -@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) def test_ec_key_key_size(backend): curve = ec.SECP256R1() _skip_curve_unsupported(backend, curve) @@ -275,7 +265,6 @@ def test_ec_key_key_size(backend): assert key.public_key().key_size == 256 -@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) class TestECWithNumbers(object): def test_with_numbers(self, backend, subtests): vectors = itertools.product( @@ -310,7 +299,6 @@ def test_with_numbers(self, backend, subtests): assert curve_type().name == priv_num.public_numbers.curve.name -@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) class TestECDSAVectors(object): def test_signing_with_example_keys(self, backend, subtests): vectors = itertools.product( @@ -666,8 +654,6 @@ def test_private_numbers_ne(self): assert priv != object() -@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) -@pytest.mark.requires_backend_interface(interface=PEMSerializationBackend) class TestECSerialization(object): @pytest.mark.parametrize( ("fmt", "password"), @@ -924,8 +910,6 @@ def test_public_bytes_from_derived_public_key(self, backend): assert parsed_public -@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) -@pytest.mark.requires_backend_interface(interface=PEMSerializationBackend) class TestEllipticCurvePEMPublicKeySerialization(object): @pytest.mark.parametrize( ("key_path", "loader_func", "encoding"), @@ -1178,7 +1162,6 @@ def test_serialize_point(self, vector, backend): ) -@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) class TestECDSAVerification(object): def test_signature_not_bytes(self, backend): _skip_curve_unsupported(backend, ec.SECP256R1()) @@ -1192,7 +1175,6 @@ def test_signature_not_bytes(self, backend): ) -@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) class TestECDH(object): def test_key_exchange_with_vectors(self, backend, subtests): vectors = load_vectors_from_file( diff --git a/tests/hazmat/primitives/test_hash_vectors.py b/tests/hazmat/primitives/test_hash_vectors.py index 6b76f8db9550..be345563265d 100644 --- a/tests/hazmat/primitives/test_hash_vectors.py +++ b/tests/hazmat/primitives/test_hash_vectors.py @@ -8,7 +8,6 @@ import pytest -from cryptography.hazmat.backends.interfaces import HashBackend from cryptography.hazmat.primitives import hashes from .utils import _load_all_params, generate_hash_test @@ -19,7 +18,6 @@ only_if=lambda backend: backend.hash_supported(hashes.SHA1()), skip_message="Does not support SHA1", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSHA1(object): test_sha1 = generate_hash_test( load_hash_vectors, @@ -33,7 +31,6 @@ class TestSHA1(object): only_if=lambda backend: backend.hash_supported(hashes.SHA224()), skip_message="Does not support SHA224", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSHA224(object): test_sha224 = generate_hash_test( load_hash_vectors, @@ -47,7 +44,6 @@ class TestSHA224(object): only_if=lambda backend: backend.hash_supported(hashes.SHA256()), skip_message="Does not support SHA256", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSHA256(object): test_sha256 = generate_hash_test( load_hash_vectors, @@ -61,7 +57,6 @@ class TestSHA256(object): only_if=lambda backend: backend.hash_supported(hashes.SHA384()), skip_message="Does not support SHA384", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSHA384(object): test_sha384 = generate_hash_test( load_hash_vectors, @@ -75,7 +70,6 @@ class TestSHA384(object): only_if=lambda backend: backend.hash_supported(hashes.SHA512()), skip_message="Does not support SHA512", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSHA512(object): test_sha512 = generate_hash_test( load_hash_vectors, @@ -89,7 +83,6 @@ class TestSHA512(object): only_if=lambda backend: backend.hash_supported(hashes.SHA512_224()), skip_message="Does not support SHA512/224", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSHA512224(object): test_sha512_224 = generate_hash_test( load_hash_vectors, @@ -103,7 +96,6 @@ class TestSHA512224(object): only_if=lambda backend: backend.hash_supported(hashes.SHA512_256()), skip_message="Does not support SHA512/256", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSHA512256(object): test_sha512_256 = generate_hash_test( load_hash_vectors, @@ -117,7 +109,6 @@ class TestSHA512256(object): only_if=lambda backend: backend.hash_supported(hashes.MD5()), skip_message="Does not support MD5", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestMD5(object): test_md5 = generate_hash_test( load_hash_vectors, @@ -133,7 +124,6 @@ class TestMD5(object): ), skip_message="Does not support BLAKE2b", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestBLAKE2b(object): test_b2b = generate_hash_test( load_hash_vectors, @@ -149,7 +139,6 @@ class TestBLAKE2b(object): ), skip_message="Does not support BLAKE2s", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestBLAKE2s256(object): test_b2s = generate_hash_test( load_hash_vectors, @@ -163,7 +152,6 @@ class TestBLAKE2s256(object): only_if=lambda backend: backend.hash_supported(hashes.SHA3_224()), skip_message="Does not support SHA3_224", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSHA3224(object): test_sha3_224 = generate_hash_test( load_hash_vectors, @@ -177,7 +165,6 @@ class TestSHA3224(object): only_if=lambda backend: backend.hash_supported(hashes.SHA3_256()), skip_message="Does not support SHA3_256", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSHA3256(object): test_sha3_256 = generate_hash_test( load_hash_vectors, @@ -191,7 +178,6 @@ class TestSHA3256(object): only_if=lambda backend: backend.hash_supported(hashes.SHA3_384()), skip_message="Does not support SHA3_384", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSHA3384(object): test_sha3_384 = generate_hash_test( load_hash_vectors, @@ -205,7 +191,6 @@ class TestSHA3384(object): only_if=lambda backend: backend.hash_supported(hashes.SHA3_512()), skip_message="Does not support SHA3_512", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSHA3512(object): test_sha3_512 = generate_hash_test( load_hash_vectors, @@ -221,7 +206,6 @@ class TestSHA3512(object): ), skip_message="Does not support SHAKE128", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSHAKE128(object): test_shake128 = generate_hash_test( load_hash_vectors, @@ -252,7 +236,6 @@ def test_shake128_variable(self, backend, subtests): ), skip_message="Does not support SHAKE256", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSHAKE256(object): test_shake256 = generate_hash_test( load_hash_vectors, @@ -281,7 +264,6 @@ def test_shake256_variable(self, backend, subtests): only_if=lambda backend: backend.hash_supported(hashes.SM3()), skip_message="Does not support SM3", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSM3(object): test_sm3 = generate_hash_test( load_hash_vectors, diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py index c0f5a9282c81..67de7947bb25 100644 --- a/tests/hazmat/primitives/test_hashes.py +++ b/tests/hazmat/primitives/test_hashes.py @@ -8,7 +8,6 @@ import pytest from cryptography.exceptions import AlreadyFinalized, _Reasons -from cryptography.hazmat.backends.interfaces import HashBackend from cryptography.hazmat.primitives import hashes from .utils import generate_base_hash_test @@ -16,7 +15,6 @@ from ...utils import raises_unsupported_algorithm -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestHashContext(object): def test_hash_reject_unicode(self, backend): m = hashes.Hash(hashes.SHA1(), backend=backend) @@ -49,7 +47,6 @@ def test_unsupported_hash(self, backend): only_if=lambda backend: backend.hash_supported(hashes.SHA1()), skip_message="Does not support SHA1", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSHA1(object): test_sha1 = generate_base_hash_test( hashes.SHA1(), @@ -61,7 +58,6 @@ class TestSHA1(object): only_if=lambda backend: backend.hash_supported(hashes.SHA224()), skip_message="Does not support SHA224", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSHA224(object): test_sha224 = generate_base_hash_test( hashes.SHA224(), @@ -73,7 +69,6 @@ class TestSHA224(object): only_if=lambda backend: backend.hash_supported(hashes.SHA256()), skip_message="Does not support SHA256", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSHA256(object): test_sha256 = generate_base_hash_test( hashes.SHA256(), @@ -85,7 +80,6 @@ class TestSHA256(object): only_if=lambda backend: backend.hash_supported(hashes.SHA384()), skip_message="Does not support SHA384", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSHA384(object): test_sha384 = generate_base_hash_test( hashes.SHA384(), @@ -97,7 +91,6 @@ class TestSHA384(object): only_if=lambda backend: backend.hash_supported(hashes.SHA512()), skip_message="Does not support SHA512", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSHA512(object): test_sha512 = generate_base_hash_test( hashes.SHA512(), @@ -109,7 +102,6 @@ class TestSHA512(object): only_if=lambda backend: backend.hash_supported(hashes.MD5()), skip_message="Does not support MD5", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestMD5(object): test_md5 = generate_base_hash_test( hashes.MD5(), @@ -123,7 +115,6 @@ class TestMD5(object): ), skip_message="Does not support BLAKE2b", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestBLAKE2b(object): test_blake2b = generate_base_hash_test( hashes.BLAKE2b(digest_size=64), @@ -147,7 +138,6 @@ def test_invalid_digest_size(self, backend): ), skip_message="Does not support BLAKE2s", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestBLAKE2s(object): test_blake2s = generate_base_hash_test( hashes.BLAKE2s(digest_size=32), @@ -172,7 +162,6 @@ def test_invalid_backend(): hashes.Hash(hashes.SHA1(), pretend_backend) -@pytest.mark.requires_backend_interface(interface=HashBackend) def test_buffer_protocol_hash(backend): data = binascii.unhexlify(b"b4190e") h = hashes.Hash(hashes.SHA256(), backend) @@ -201,7 +190,6 @@ def test_invalid_digest_size(self, xof): only_if=lambda backend: backend.hash_supported(hashes.SM3()), skip_message="Does not support SM3", ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestSM3(object): test_sm3 = generate_base_hash_test( hashes.SM3(), diff --git a/tests/hazmat/primitives/test_hkdf.py b/tests/hazmat/primitives/test_hkdf.py index 5ee6680b998e..80b27b9a9150 100644 --- a/tests/hazmat/primitives/test_hkdf.py +++ b/tests/hazmat/primitives/test_hkdf.py @@ -9,7 +9,6 @@ import pytest from cryptography.exceptions import AlreadyFinalized, InvalidKey, _Reasons -from cryptography.hazmat.backends.interfaces import HMACBackend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.hkdf import HKDF, HKDFExpand @@ -20,7 +19,6 @@ ) -@pytest.mark.requires_backend_interface(interface=HMACBackend) class TestHKDF(object): def test_length_limit(self, backend): big_length = 255 * hashes.SHA256().digest_size + 1 @@ -138,7 +136,6 @@ def test_buffer_protocol(self, backend): assert hkdf.derive(ikm) == binascii.unhexlify(vector["okm"]) -@pytest.mark.requires_backend_interface(interface=HMACBackend) class TestHKDFExpand(object): def test_derive(self, backend): prk = binascii.unhexlify( diff --git a/tests/hazmat/primitives/test_hkdf_vectors.py b/tests/hazmat/primitives/test_hkdf_vectors.py index 7561369436ad..f3df7594db75 100644 --- a/tests/hazmat/primitives/test_hkdf_vectors.py +++ b/tests/hazmat/primitives/test_hkdf_vectors.py @@ -7,7 +7,6 @@ import pytest -from cryptography.hazmat.backends.interfaces import HMACBackend from cryptography.hazmat.primitives import hashes from .utils import generate_hkdf_test @@ -18,7 +17,6 @@ only_if=lambda backend: backend.hmac_supported(hashes.SHA1()), skip_message="Does not support SHA1.", ) -@pytest.mark.requires_backend_interface(interface=HMACBackend) class TestHKDFSHA1(object): test_hkdfsha1 = generate_hkdf_test( load_nist_vectors, @@ -32,7 +30,6 @@ class TestHKDFSHA1(object): only_if=lambda backend: backend.hmac_supported(hashes.SHA256()), skip_message="Does not support SHA256.", ) -@pytest.mark.requires_backend_interface(interface=HMACBackend) class TestHKDFSHA256(object): test_hkdfsha256 = generate_hkdf_test( load_nist_vectors, diff --git a/tests/hazmat/primitives/test_hmac.py b/tests/hazmat/primitives/test_hmac.py index 0321eff94b1f..1cbd39c10538 100644 --- a/tests/hazmat/primitives/test_hmac.py +++ b/tests/hazmat/primitives/test_hmac.py @@ -12,7 +12,6 @@ InvalidSignature, _Reasons, ) -from cryptography.hazmat.backends.interfaces import HMACBackend from cryptography.hazmat.primitives import hashes, hmac from .utils import generate_base_hmac_test @@ -24,14 +23,12 @@ only_if=lambda backend: backend.hmac_supported(hashes.MD5()), skip_message="Does not support MD5", ) -@pytest.mark.requires_backend_interface(interface=HMACBackend) class TestHMACCopy(object): test_copy = generate_base_hmac_test( hashes.MD5(), ) -@pytest.mark.requires_backend_interface(interface=HMACBackend) class TestHMAC(object): def test_hmac_reject_unicode(self, backend): h = hmac.HMAC(b"mykey", hashes.SHA1(), backend=backend) diff --git a/tests/hazmat/primitives/test_hmac_vectors.py b/tests/hazmat/primitives/test_hmac_vectors.py index fd2a4041dae1..808b17d196cb 100644 --- a/tests/hazmat/primitives/test_hmac_vectors.py +++ b/tests/hazmat/primitives/test_hmac_vectors.py @@ -7,7 +7,6 @@ import pytest -from cryptography.hazmat.backends.interfaces import HMACBackend from cryptography.hazmat.primitives import hashes, hmac from .utils import generate_hmac_test @@ -18,7 +17,6 @@ only_if=lambda backend: backend.hmac_supported(hashes.MD5()), skip_message="Does not support MD5", ) -@pytest.mark.requires_backend_interface(interface=HMACBackend) class TestHMACMD5(object): test_hmac_md5 = generate_hmac_test( load_hash_vectors, @@ -32,7 +30,6 @@ class TestHMACMD5(object): only_if=lambda backend: backend.hmac_supported(hashes.SHA1()), skip_message="Does not support SHA1", ) -@pytest.mark.requires_backend_interface(interface=HMACBackend) class TestHMACSHA1(object): test_hmac_sha1 = generate_hmac_test( load_hash_vectors, @@ -46,7 +43,6 @@ class TestHMACSHA1(object): only_if=lambda backend: backend.hmac_supported(hashes.SHA224()), skip_message="Does not support SHA224", ) -@pytest.mark.requires_backend_interface(interface=HMACBackend) class TestHMACSHA224(object): test_hmac_sha224 = generate_hmac_test( load_hash_vectors, @@ -60,7 +56,6 @@ class TestHMACSHA224(object): only_if=lambda backend: backend.hmac_supported(hashes.SHA256()), skip_message="Does not support SHA256", ) -@pytest.mark.requires_backend_interface(interface=HMACBackend) class TestHMACSHA256(object): test_hmac_sha256 = generate_hmac_test( load_hash_vectors, @@ -74,7 +69,6 @@ class TestHMACSHA256(object): only_if=lambda backend: backend.hmac_supported(hashes.SHA384()), skip_message="Does not support SHA384", ) -@pytest.mark.requires_backend_interface(interface=HMACBackend) class TestHMACSHA384(object): test_hmac_sha384 = generate_hmac_test( load_hash_vectors, @@ -88,7 +82,6 @@ class TestHMACSHA384(object): only_if=lambda backend: backend.hmac_supported(hashes.SHA512()), skip_message="Does not support SHA512", ) -@pytest.mark.requires_backend_interface(interface=HMACBackend) class TestHMACSHA512(object): test_hmac_sha512 = generate_hmac_test( load_hash_vectors, @@ -104,7 +97,6 @@ class TestHMACSHA512(object): ), skip_message="Does not support BLAKE2", ) -@pytest.mark.requires_backend_interface(interface=HMACBackend) class TestHMACBLAKE2(object): def test_blake2b(self, backend): h = hmac.HMAC(b"0" * 64, hashes.BLAKE2b(digest_size=64), backend) diff --git a/tests/hazmat/primitives/test_idea.py b/tests/hazmat/primitives/test_idea.py index ea5dbb2f4188..4f98960a2a7d 100644 --- a/tests/hazmat/primitives/test_idea.py +++ b/tests/hazmat/primitives/test_idea.py @@ -8,7 +8,6 @@ import pytest -from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives.ciphers import algorithms, modes from .utils import generate_encrypt_test @@ -21,7 +20,6 @@ ), skip_message="Does not support IDEA ECB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestIDEAModeECB(object): test_ecb = generate_encrypt_test( load_nist_vectors, @@ -38,7 +36,6 @@ class TestIDEAModeECB(object): ), skip_message="Does not support IDEA CBC", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestIDEAModeCBC(object): test_cbc = generate_encrypt_test( load_nist_vectors, @@ -55,7 +52,6 @@ class TestIDEAModeCBC(object): ), skip_message="Does not support IDEA OFB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestIDEAModeOFB(object): test_ofb = generate_encrypt_test( load_nist_vectors, @@ -72,7 +68,6 @@ class TestIDEAModeOFB(object): ), skip_message="Does not support IDEA CFB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestIDEAModeCFB(object): test_cfb = generate_encrypt_test( load_nist_vectors, diff --git a/tests/hazmat/primitives/test_kbkdf.py b/tests/hazmat/primitives/test_kbkdf.py index 2c94d18167bd..ddbf953b1323 100644 --- a/tests/hazmat/primitives/test_kbkdf.py +++ b/tests/hazmat/primitives/test_kbkdf.py @@ -6,7 +6,6 @@ import pytest from cryptography.exceptions import AlreadyFinalized, InvalidKey, _Reasons -from cryptography.hazmat.backends.interfaces import HMACBackend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.kbkdf import ( CounterLocation, @@ -18,7 +17,6 @@ from ...utils import raises_unsupported_algorithm -@pytest.mark.requires_backend_interface(interface=HMACBackend) class TestKBKDFHMAC(object): def test_invalid_key(self, backend): kdf = KBKDFHMAC( diff --git a/tests/hazmat/primitives/test_kbkdf_vectors.py b/tests/hazmat/primitives/test_kbkdf_vectors.py index 7545a85da7be..fffd28ad4b10 100644 --- a/tests/hazmat/primitives/test_kbkdf_vectors.py +++ b/tests/hazmat/primitives/test_kbkdf_vectors.py @@ -5,15 +5,10 @@ import os -import pytest - -from cryptography.hazmat.backends.interfaces import HMACBackend - from .utils import generate_kbkdf_counter_mode_test from ...utils import load_nist_kbkdf_vectors -@pytest.mark.requires_backend_interface(interface=HMACBackend) class TestCounterKDFCounterMode(object): test_kbkdfctr = generate_kbkdf_counter_mode_test( load_nist_kbkdf_vectors, diff --git a/tests/hazmat/primitives/test_keywrap.py b/tests/hazmat/primitives/test_keywrap.py index c5486fe1ee1c..e46ed7924ea8 100644 --- a/tests/hazmat/primitives/test_keywrap.py +++ b/tests/hazmat/primitives/test_keywrap.py @@ -8,7 +8,6 @@ import pytest -from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives import keywrap from cryptography.hazmat.primitives.ciphers import algorithms, modes @@ -16,7 +15,6 @@ from ...utils import load_nist_vectors -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestAESKeyWrap(object): @pytest.mark.supported( only_if=lambda backend: backend.cipher_supported( @@ -124,7 +122,6 @@ def test_unwrap_invalid_wrapped_key_length(self, backend): skip_message="Does not support AES key wrap (RFC 5649) because AES-ECB" " is unsupported", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestAESKeyWrapWithPadding(object): def test_wrap(self, backend, subtests): params = _load_all_params( diff --git a/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py b/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py index 6b02540284ff..255009de428c 100644 --- a/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py +++ b/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py @@ -5,7 +5,6 @@ import pytest -from cryptography.hazmat.backends.interfaces import PBKDF2HMACBackend from cryptography.hazmat.primitives import hashes from .utils import generate_pbkdf2_test @@ -16,7 +15,6 @@ only_if=lambda backend: backend.pbkdf2_hmac_supported(hashes.SHA1()), skip_message="Does not support SHA1 for PBKDF2HMAC", ) -@pytest.mark.requires_backend_interface(interface=PBKDF2HMACBackend) class TestPBKDF2HMACSHA1(object): test_pbkdf2_sha1 = generate_pbkdf2_test( load_nist_vectors, diff --git a/tests/hazmat/primitives/test_pkcs12.py b/tests/hazmat/primitives/test_pkcs12.py index b1759a1bc8ab..f99c121d9554 100644 --- a/tests/hazmat/primitives/test_pkcs12.py +++ b/tests/hazmat/primitives/test_pkcs12.py @@ -9,7 +9,6 @@ import pytest from cryptography import x509 -from cryptography.hazmat.backends.interfaces import DERSerializationBackend from cryptography.hazmat.backends.openssl.backend import _RC2 from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ec @@ -23,7 +22,6 @@ from ...doubles import DummyKeySerializationEncryption -@pytest.mark.requires_backend_interface(interface=DERSerializationBackend) class TestPKCS12Loading(object): def _test_load_pkcs12_ec_keys(self, filename, password, backend): cert = load_vectors_from_file( diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 46f011f477dc..9c98dbbab2e7 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -14,10 +14,6 @@ InvalidSignature, _Reasons, ) -from cryptography.hazmat.backends.interfaces import ( - PEMSerializationBackend, - RSABackend, -) from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ( padding, @@ -138,7 +134,6 @@ def _skip_pss_hash_algorithm_unsupported(backend, hash_alg): ) -@pytest.mark.requires_backend_interface(interface=RSABackend) def test_skip_pss_hash_algorithm_unsupported(backend): with pytest.raises(pytest.skip.Exception): _skip_pss_hash_algorithm_unsupported(backend, DummyHashAlgorithm()) @@ -168,7 +163,6 @@ def test_modular_inverse(): ) -@pytest.mark.requires_backend_interface(interface=RSABackend) class TestRSA(object): @pytest.mark.parametrize( ("public_exponent", "key_size"), @@ -390,7 +384,6 @@ def test_rsa_generate_invalid_backend(): rsa.generate_private_key(65537, 2048, pretend_backend) -@pytest.mark.requires_backend_interface(interface=RSABackend) class TestRSASignature(object): @pytest.mark.supported( only_if=lambda backend: backend.rsa_padding_supported( @@ -755,7 +748,6 @@ def test_corrupted_private_key(self, backend): ) -@pytest.mark.requires_backend_interface(interface=RSABackend) class TestRSAVerification(object): @pytest.mark.supported( only_if=lambda backend: backend.rsa_padding_supported( @@ -1212,7 +1204,6 @@ def test_prehashed_digest_mismatch(self, backend): public_key.verify(b"\x00" * 64, data, pkcs, prehashed_alg) -@pytest.mark.requires_backend_interface(interface=RSABackend) class TestRSAPSSMGF1Verification(object): test_rsa_pss_mgf1_sha1 = pytest.mark.supported( only_if=lambda backend: backend.rsa_padding_supported( @@ -1350,7 +1341,6 @@ class TestRSAPSSMGF1Verification(object): ) -@pytest.mark.requires_backend_interface(interface=RSABackend) class TestRSAPKCS1Verification(object): test_rsa_pkcs1v15_verify_sha1 = pytest.mark.supported( only_if=lambda backend: ( @@ -1506,7 +1496,6 @@ def test_invalid_algorithm(self): ) -@pytest.mark.requires_backend_interface(interface=RSABackend) class TestRSADecryption(object): @pytest.mark.supported( only_if=lambda backend: backend.rsa_padding_supported( @@ -1750,7 +1739,6 @@ def test_unsupported_oaep_mgf(self, backend): ) -@pytest.mark.requires_backend_interface(interface=RSABackend) class TestRSAEncryption(object): @pytest.mark.supported( only_if=lambda backend: backend.rsa_padding_supported( @@ -1938,7 +1926,6 @@ def test_unsupported_oaep_mgf(self, backend): ) -@pytest.mark.requires_backend_interface(interface=RSABackend) class TestRSANumbers(object): def test_rsa_public_numbers(self): public_numbers = rsa.RSAPublicNumbers(e=1, n=15) @@ -2160,8 +2147,6 @@ def test_invalid_recover_prime_factors(self): rsa.rsa_recover_prime_factors(34, 3, 7) -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=PEMSerializationBackend) class TestRSAPrivateKeySerialization(object): @pytest.mark.parametrize( ("fmt", "password"), @@ -2351,8 +2336,6 @@ def test_private_bytes_unsupported_encryption_type(self, backend): ) -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=PEMSerializationBackend) class TestRSAPEMPublicKeySerialization(object): @pytest.mark.parametrize( ("key_path", "loader_func", "encoding", "format"), diff --git a/tests/hazmat/primitives/test_scrypt.py b/tests/hazmat/primitives/test_scrypt.py index d3fea28ca7c8..63e6b35ced1f 100644 --- a/tests/hazmat/primitives/test_scrypt.py +++ b/tests/hazmat/primitives/test_scrypt.py @@ -13,7 +13,6 @@ InvalidKey, UnsupportedAlgorithm, ) -from cryptography.hazmat.backends.interfaces import ScryptBackend from cryptography.hazmat.primitives.kdf.scrypt import Scrypt, _MEM_LIMIT from tests.utils import load_nist_vectors, load_vectors_from_file @@ -48,7 +47,6 @@ def test_memory_limit_skip(): only_if=lambda backend: backend.scrypt_supported(), skip_message="Does not support Scrypt", ) -@pytest.mark.requires_backend_interface(interface=ScryptBackend) class TestScrypt(object): @pytest.mark.parametrize("params", vectors) def test_derive(self, backend, params): diff --git a/tests/hazmat/primitives/test_seed.py b/tests/hazmat/primitives/test_seed.py index e01aa0d8b45a..3225ddda5ac7 100644 --- a/tests/hazmat/primitives/test_seed.py +++ b/tests/hazmat/primitives/test_seed.py @@ -8,7 +8,6 @@ import pytest -from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives.ciphers import algorithms, modes from .utils import generate_encrypt_test @@ -21,7 +20,6 @@ ), skip_message="Does not support SEED ECB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestSEEDModeECB(object): test_ecb = generate_encrypt_test( load_nist_vectors, @@ -38,7 +36,6 @@ class TestSEEDModeECB(object): ), skip_message="Does not support SEED CBC", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestSEEDModeCBC(object): test_cbc = generate_encrypt_test( load_nist_vectors, @@ -55,7 +52,6 @@ class TestSEEDModeCBC(object): ), skip_message="Does not support SEED OFB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestSEEDModeOFB(object): test_ofb = generate_encrypt_test( load_nist_vectors, @@ -72,7 +68,6 @@ class TestSEEDModeOFB(object): ), skip_message="Does not support SEED CFB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestSEEDModeCFB(object): test_cfb = generate_encrypt_test( load_nist_vectors, diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index ca969e031cfc..ed3f8e7f8f05 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -11,13 +11,6 @@ import pytest from cryptography.exceptions import UnsupportedAlgorithm -from cryptography.hazmat.backends.interfaces import ( - DERSerializationBackend, - DSABackend, - EllipticCurveBackend, - PEMSerializationBackend, - RSABackend, -) from cryptography.hazmat.primitives.asymmetric import ( dsa, ec, @@ -64,7 +57,6 @@ def _skip_fips_format(key_path, password, backend): class TestBufferProtocolSerialization(object): - @pytest.mark.requires_backend_interface(interface=RSABackend) @pytest.mark.parametrize( ("key_path", "password"), [ @@ -85,7 +77,6 @@ def test_load_der_rsa_private_key(self, key_path, password, backend): assert isinstance(key, rsa.RSAPrivateKey) _check_rsa_private_numbers(key.private_numbers()) - @pytest.mark.requires_backend_interface(interface=RSABackend) @pytest.mark.parametrize( ("key_path", "password"), [ @@ -115,9 +106,7 @@ def test_load_pem_rsa_private_key(self, key_path, password, backend): _check_rsa_private_numbers(key.private_numbers()) -@pytest.mark.requires_backend_interface(interface=DERSerializationBackend) class TestDERSerialization(object): - @pytest.mark.requires_backend_interface(interface=RSABackend) @pytest.mark.parametrize( ("key_path", "password"), [ @@ -139,7 +128,6 @@ def test_load_der_rsa_private_key(self, key_path, password, backend): assert isinstance(key, rsa.RSAPrivateKey) _check_rsa_private_numbers(key.private_numbers()) - @pytest.mark.requires_backend_interface(interface=DSABackend) @pytest.mark.parametrize( ("key_path", "password"), [ @@ -164,7 +152,6 @@ def test_load_der_dsa_private_key(self, key_path, password, backend): @pytest.mark.parametrize( "key_path", [["DER_Serialization", "enc-rsa-pkcs8.der"]] ) - @pytest.mark.requires_backend_interface(interface=RSABackend) def test_password_not_bytes(self, key_path, backend): key_file = os.path.join("asymmetric", *key_path) password = "this password is not bytes" @@ -187,7 +174,6 @@ def test_password_not_bytes(self, key_path, backend): (["DER_Serialization", "ec_private_key_encrypted.der"], b"123456"), ], ) - @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) def test_load_der_ec_private_key(self, key_path, password, backend): _skip_curve_unsupported(backend, ec.SECP256R1()) key = load_vectors_from_file( @@ -206,7 +192,6 @@ def test_load_der_ec_private_key(self, key_path, password, backend): @pytest.mark.parametrize( "key_path", [["DER_Serialization", "enc-rsa-pkcs8.der"]] ) - @pytest.mark.requires_backend_interface(interface=RSABackend) def test_wrong_password(self, key_path, backend): key_file = os.path.join("asymmetric", *key_path) password = b"this password is wrong" @@ -223,7 +208,6 @@ def test_wrong_password(self, key_path, backend): @pytest.mark.parametrize( "key_path", [["DER_Serialization", "unenc-rsa-pkcs8.der"]] ) - @pytest.mark.requires_backend_interface(interface=RSABackend) def test_unused_password(self, key_path, backend): key_file = os.path.join("asymmetric", *key_path) password = b"this password will not be used" @@ -243,7 +227,6 @@ def test_unused_password(self, key_path, backend): [["DER_Serialization", "enc-rsa-pkcs8.der"]], [b"", None] ), ) - @pytest.mark.requires_backend_interface(interface=RSABackend) def test_missing_password(self, key_path, password, backend): key_file = os.path.join("asymmetric", *key_path) @@ -330,7 +313,6 @@ def test_corrupt_traditional_format_der(self, backend): os.path.join("asymmetric", "public", "PKCS1", "rsa.pub.der"), ], ) - @pytest.mark.requires_backend_interface(interface=RSABackend) def test_load_der_rsa_public_key(self, key_file, backend): key = load_vectors_from_file( key_file, @@ -357,7 +339,6 @@ def test_load_der_invalid_public_key(self, backend): ), ], ) - @pytest.mark.requires_backend_interface(interface=DSABackend) def test_load_der_dsa_public_key(self, key_file, backend): key = load_vectors_from_file( key_file, @@ -367,7 +348,6 @@ def test_load_der_dsa_public_key(self, key_file, backend): assert key assert isinstance(key, dsa.DSAPublicKey) - @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) def test_load_ec_public_key(self, backend): _skip_curve_unsupported(backend, ec.SECP256R1()) key = load_vectors_from_file( @@ -389,7 +369,6 @@ def test_wrong_parameters_format(self, backend): load_der_parameters(param_data, backend) -@pytest.mark.requires_backend_interface(interface=PEMSerializationBackend) class TestPEMSerialization(object): @pytest.mark.parametrize( ("key_file", "password"), @@ -461,7 +440,6 @@ def test_load_dsa_private_key(self, key_path, password, backend): (["PEM_Serialization", "ec_private_key_encrypted.pem"], b"123456"), ], ) - @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) def test_load_pem_ec_private_key(self, key_path, password, backend): _skip_curve_unsupported(backend, ec.SECP256R1()) _skip_fips_format(key_path, password, backend) @@ -518,7 +496,6 @@ def test_load_pem_dsa_public_key(self, key_file, backend): assert key assert isinstance(key, dsa.DSAPublicKey) - @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) def test_load_ec_public_key(self, backend): _skip_curve_unsupported(backend, ec.SECP256R1()) key = load_vectors_from_file( @@ -976,7 +953,6 @@ def test_load_bad_encryption_oid_key(self, key_file, password, backend): ) -@pytest.mark.requires_backend_interface(interface=RSABackend) class TestRSASSHSerialization(object): def test_load_ssh_public_key_unsupported(self, backend): ssh_key = b"ecdsa-sha2-junk AAAAE2VjZHNhLXNoYTItbmlzdHAyNTY=" @@ -1089,7 +1065,6 @@ def test_load_ssh_public_key_rsa(self, backend): assert numbers == expected -@pytest.mark.requires_backend_interface(interface=DSABackend) class TestDSSSSHSerialization(object): def test_load_ssh_public_key_dss_too_short(self, backend): ssh_key = b"ssh-dss" @@ -1203,7 +1178,6 @@ def test_load_ssh_public_key_dss(self, backend): assert numbers == expected -@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) class TestECDSASSHSerialization(object): def test_load_ssh_public_key_ecdsa_nist_p256(self, backend): _skip_curve_unsupported(backend, ec.SECP256R1()) @@ -1822,9 +1796,6 @@ def test_dh_private_key(self, backend): private_key.private_bytes(enc, fmt, NoEncryption()) -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=DSABackend) -@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) class TestOpenSSHSerialization(object): @pytest.mark.parametrize( ("key_file", "cert_file"), diff --git a/tests/hazmat/primitives/test_sm4.py b/tests/hazmat/primitives/test_sm4.py index b7573443f791..b5152d79858a 100644 --- a/tests/hazmat/primitives/test_sm4.py +++ b/tests/hazmat/primitives/test_sm4.py @@ -7,7 +7,6 @@ import pytest -from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives.ciphers import algorithms, modes from .utils import generate_encrypt_test @@ -20,7 +19,6 @@ ), skip_message="Does not support SM4 ECB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestSM4ModeECB(object): test_ecb = generate_encrypt_test( load_nist_vectors, @@ -37,7 +35,6 @@ class TestSM4ModeECB(object): ), skip_message="Does not support SM4 CBC", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestSM4ModeCBC(object): test_cbc = generate_encrypt_test( load_nist_vectors, @@ -54,7 +51,6 @@ class TestSM4ModeCBC(object): ), skip_message="Does not support SM4 OFB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestSM4ModeOFB(object): test_ofb = generate_encrypt_test( load_nist_vectors, @@ -71,7 +67,6 @@ class TestSM4ModeOFB(object): ), skip_message="Does not support SM4 CFB", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestSM4ModeCFB(object): test_cfb = generate_encrypt_test( load_nist_vectors, @@ -88,7 +83,6 @@ class TestSM4ModeCFB(object): ), skip_message="Does not support SM4 CTR", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) class TestSM4ModeCTR(object): test_cfb = generate_encrypt_test( load_nist_vectors, diff --git a/tests/hazmat/primitives/test_x963_vectors.py b/tests/hazmat/primitives/test_x963_vectors.py index ef3a186e1894..8006a9a040b6 100644 --- a/tests/hazmat/primitives/test_x963_vectors.py +++ b/tests/hazmat/primitives/test_x963_vectors.py @@ -9,7 +9,6 @@ import pytest -from cryptography.hazmat.backends.interfaces import HashBackend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.x963kdf import X963KDF @@ -26,7 +25,6 @@ def _skip_hashfn_unsupported(backend, hashfn): ) -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestX963(object): _algorithms_dict: typing.Dict[str, typing.Type[hashes.HashAlgorithm]] = { "SHA-1": hashes.SHA1, diff --git a/tests/hazmat/primitives/test_x963kdf.py b/tests/hazmat/primitives/test_x963kdf.py index 08c94db84645..5254aa006cb3 100644 --- a/tests/hazmat/primitives/test_x963kdf.py +++ b/tests/hazmat/primitives/test_x963kdf.py @@ -8,14 +8,12 @@ import pytest from cryptography.exceptions import AlreadyFinalized, InvalidKey, _Reasons -from cryptography.hazmat.backends.interfaces import HashBackend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.x963kdf import X963KDF from ...utils import raises_unsupported_algorithm -@pytest.mark.requires_backend_interface(interface=HashBackend) class TestX963KDF(object): def test_length_limit(self, backend): big_length = hashes.SHA256().digest_size * (2 ** 32 - 1) + 1 diff --git a/tests/hazmat/primitives/twofactor/test_hotp.py b/tests/hazmat/primitives/twofactor/test_hotp.py index 66c9b4ba0e43..979f3f004efc 100644 --- a/tests/hazmat/primitives/twofactor/test_hotp.py +++ b/tests/hazmat/primitives/twofactor/test_hotp.py @@ -8,7 +8,6 @@ import pytest from cryptography.exceptions import _Reasons -from cryptography.hazmat.backends.interfaces import HMACBackend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.hashes import MD5, SHA1 from cryptography.hazmat.primitives.twofactor import InvalidToken @@ -27,7 +26,6 @@ only_if=lambda backend: backend.hmac_supported(hashes.SHA1()), skip_message="Does not support HMAC-SHA1.", ) -@pytest.mark.requires_backend_interface(interface=HMACBackend) class TestHOTP(object): def test_invalid_key_length(self, backend): secret = os.urandom(10) diff --git a/tests/hazmat/primitives/twofactor/test_totp.py b/tests/hazmat/primitives/twofactor/test_totp.py index 87c1e6144e9b..0159773399e2 100644 --- a/tests/hazmat/primitives/twofactor/test_totp.py +++ b/tests/hazmat/primitives/twofactor/test_totp.py @@ -6,7 +6,6 @@ import pytest from cryptography.exceptions import _Reasons -from cryptography.hazmat.backends.interfaces import HMACBackend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.twofactor import InvalidToken from cryptography.hazmat.primitives.twofactor.totp import TOTP @@ -20,7 +19,6 @@ vectors = load_vectors_from_file("twofactor/rfc-6238.txt", load_nist_vectors) -@pytest.mark.requires_backend_interface(interface=HMACBackend) class TestTOTP(object): @pytest.mark.supported( only_if=lambda backend: backend.hmac_supported(hashes.SHA1()), diff --git a/tests/test_fernet.py b/tests/test_fernet.py index fc21398834a8..a8a140e98266 100644 --- a/tests/test_fernet.py +++ b/tests/test_fernet.py @@ -17,7 +17,6 @@ from cryptography.fernet import Fernet, InvalidToken, MultiFernet from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.backends.interfaces import CipherBackend, HMACBackend from cryptography.hazmat.primitives.ciphers import algorithms, modes import cryptography_vectors @@ -39,8 +38,6 @@ def test_default_backend(): assert f._backend is default_backend() -@pytest.mark.requires_backend_interface(interface=CipherBackend) -@pytest.mark.requires_backend_interface(interface=HMACBackend) @pytest.mark.supported( only_if=lambda backend: backend.cipher_supported( algorithms.AES(b"\x00" * 32), modes.CBC(b"\x00" * 16) @@ -152,8 +149,6 @@ def test_extract_timestamp(self, monkeypatch, backend): f.extract_timestamp(b"nonsensetoken") -@pytest.mark.requires_backend_interface(interface=CipherBackend) -@pytest.mark.requires_backend_interface(interface=HMACBackend) @pytest.mark.supported( only_if=lambda backend: backend.cipher_supported( algorithms.AES(b"\x00" * 32), modes.CBC(b"\x00" * 16) diff --git a/tests/wycheproof/test_aes.py b/tests/wycheproof/test_aes.py index c041b47e15c4..891d8df4301b 100644 --- a/tests/wycheproof/test_aes.py +++ b/tests/wycheproof/test_aes.py @@ -8,7 +8,6 @@ import pytest from cryptography.exceptions import InvalidTag -from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives import padding from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives.ciphers.aead import AESCCM, AESGCM @@ -17,7 +16,6 @@ from ..hazmat.primitives.test_aead import _aead_supported -@pytest.mark.requires_backend_interface(interface=CipherBackend) @wycheproof_tests("aes_cbc_pkcs5_test.json") def test_aes_cbc_pkcs5(backend, wycheproof): key = binascii.unhexlify(wycheproof.testcase["key"]) @@ -45,7 +43,6 @@ def test_aes_cbc_pkcs5(backend, wycheproof): unpadder.update(padded_msg) + unpadder.finalize() -@pytest.mark.requires_backend_interface(interface=CipherBackend) @wycheproof_tests("aes_gcm_test.json") def test_aes_gcm(backend, wycheproof): key = binascii.unhexlify(wycheproof.testcase["key"]) @@ -90,7 +87,6 @@ def test_aes_gcm(backend, wycheproof): dec.finalize() -@pytest.mark.requires_backend_interface(interface=CipherBackend) @wycheproof_tests("aes_gcm_test.json") def test_aes_gcm_aead_api(backend, wycheproof): key = binascii.unhexlify(wycheproof.testcase["key"]) @@ -124,7 +120,6 @@ def test_aes_gcm_aead_api(backend, wycheproof): not _aead_supported(AESCCM), reason="Requires OpenSSL with AES-CCM support", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) @wycheproof_tests("aes_ccm_test.json") def test_aes_ccm_aead_api(backend, wycheproof): key = binascii.unhexlify(wycheproof.testcase["key"]) diff --git a/tests/wycheproof/test_chacha20poly1305.py b/tests/wycheproof/test_chacha20poly1305.py index 9c94c58f74d9..d36ea66a7750 100644 --- a/tests/wycheproof/test_chacha20poly1305.py +++ b/tests/wycheproof/test_chacha20poly1305.py @@ -8,7 +8,6 @@ import pytest from cryptography.exceptions import InvalidTag -from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305 from .utils import wycheproof_tests @@ -19,7 +18,6 @@ not _aead_supported(ChaCha20Poly1305), reason="Requires OpenSSL with ChaCha20Poly1305 support", ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) @wycheproof_tests("chacha20_poly1305_test.json") def test_chacha2poly1305(backend, wycheproof): key = binascii.unhexlify(wycheproof.testcase["key"]) diff --git a/tests/wycheproof/test_cmac.py b/tests/wycheproof/test_cmac.py index 21ce9af888f8..bca84805d7b9 100644 --- a/tests/wycheproof/test_cmac.py +++ b/tests/wycheproof/test_cmac.py @@ -8,14 +8,12 @@ import pytest from cryptography.exceptions import InvalidSignature -from cryptography.hazmat.backends.interfaces import CMACBackend from cryptography.hazmat.primitives.ciphers.algorithms import AES from cryptography.hazmat.primitives.cmac import CMAC from .utils import wycheproof_tests -@pytest.mark.requires_backend_interface(interface=CMACBackend) @wycheproof_tests("aes_cmac_test.json") def test_aes_cmac(backend, wycheproof): key = binascii.unhexlify(wycheproof.testcase["key"]) diff --git a/tests/wycheproof/test_dsa.py b/tests/wycheproof/test_dsa.py index ac4647ef1b6f..3d31ee170dd5 100644 --- a/tests/wycheproof/test_dsa.py +++ b/tests/wycheproof/test_dsa.py @@ -8,7 +8,6 @@ import pytest from cryptography.exceptions import InvalidSignature -from cryptography.hazmat.backends.interfaces import DSABackend from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import dsa @@ -22,7 +21,6 @@ } -@pytest.mark.requires_backend_interface(interface=DSABackend) @wycheproof_tests( "dsa_test.json", "dsa_2048_224_sha224_test.json", diff --git a/tests/wycheproof/test_ecdh.py b/tests/wycheproof/test_ecdh.py index 510ec93373a9..02bf1182b0f6 100644 --- a/tests/wycheproof/test_ecdh.py +++ b/tests/wycheproof/test_ecdh.py @@ -8,7 +8,6 @@ import pytest from cryptography.exceptions import UnsupportedAlgorithm -from cryptography.hazmat.backends.interfaces import EllipticCurveBackend from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import ec @@ -36,7 +35,6 @@ } -@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) @wycheproof_tests( "ecdh_test.json", "ecdh_brainpoolP224r1_test.json", @@ -85,7 +83,6 @@ def test_ecdh(backend, wycheproof): private_key.exchange(ec.ECDH(), public_key) -@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) @wycheproof_tests( "ecdh_secp224r1_ecpoint_test.json", "ecdh_secp256r1_ecpoint_test.json", diff --git a/tests/wycheproof/test_ecdsa.py b/tests/wycheproof/test_ecdsa.py index b7f252c6df82..2f7b7425b3d9 100644 --- a/tests/wycheproof/test_ecdsa.py +++ b/tests/wycheproof/test_ecdsa.py @@ -8,7 +8,6 @@ import pytest from cryptography.exceptions import InvalidSignature, UnsupportedAlgorithm -from cryptography.hazmat.backends.interfaces import EllipticCurveBackend from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ec @@ -28,7 +27,6 @@ } -@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) @wycheproof_tests( "ecdsa_test.json", "ecdsa_brainpoolP224r1_sha224_test.json", diff --git a/tests/wycheproof/test_keywrap.py b/tests/wycheproof/test_keywrap.py index 6a8cfd08bc69..7aec26989b20 100644 --- a/tests/wycheproof/test_keywrap.py +++ b/tests/wycheproof/test_keywrap.py @@ -7,13 +7,11 @@ import pytest -from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives import keywrap from .utils import wycheproof_tests -@pytest.mark.requires_backend_interface(interface=CipherBackend) @wycheproof_tests("kwp_test.json") def test_keywrap_with_padding(backend, wycheproof): wrapping_key = binascii.unhexlify(wycheproof.testcase["key"]) @@ -38,7 +36,6 @@ def test_keywrap_with_padding(backend, wycheproof): ) -@pytest.mark.requires_backend_interface(interface=CipherBackend) @wycheproof_tests("kw_test.json") def test_keywrap(backend, wycheproof): wrapping_key = binascii.unhexlify(wycheproof.testcase["key"]) diff --git a/tests/wycheproof/test_rsa.py b/tests/wycheproof/test_rsa.py index 0b0983da3590..73ff711154d9 100644 --- a/tests/wycheproof/test_rsa.py +++ b/tests/wycheproof/test_rsa.py @@ -8,7 +8,6 @@ import pytest from cryptography.exceptions import InvalidSignature -from cryptography.hazmat.backends.interfaces import RSABackend from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import padding, rsa @@ -41,7 +40,6 @@ def should_verify(backend, wycheproof): return False -@pytest.mark.requires_backend_interface(interface=RSABackend) @wycheproof_tests( "rsa_signature_test.json", "rsa_signature_2048_sha224_test.json", @@ -113,7 +111,6 @@ def test_rsa_pkcs1v15_signature_generation(backend, wycheproof): assert sig == binascii.unhexlify(wycheproof.testcase["sig"]) -@pytest.mark.requires_backend_interface(interface=RSABackend) @wycheproof_tests( "rsa_pss_2048_sha1_mgf1_20_test.json", "rsa_pss_2048_sha256_mgf1_0_test.json", @@ -164,7 +161,6 @@ def test_rsa_pss_signature(backend, wycheproof): ) -@pytest.mark.requires_backend_interface(interface=RSABackend) @wycheproof_tests( "rsa_oaep_2048_sha1_mgf1sha1_test.json", "rsa_oaep_2048_sha224_mgf1sha1_test.json", diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 3acb3ef9c3dc..87b6b29e6fdb 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -30,12 +30,6 @@ SET, UTC_TIME, ) -from cryptography.hazmat.backends.interfaces import ( - DSABackend, - EllipticCurveBackend, - RSABackend, - X509Backend, -) from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ( dh, @@ -134,7 +128,6 @@ def _parse_cert(der): ) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestCertificateRevocationList(object): def test_load_pem_crl(self, backend): crl = _load_cert( @@ -484,7 +477,6 @@ def test_verify_argument_must_be_a_public_key(self, backend): crl.is_signature_valid(object) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestRevokedCertificate(object): def test_revoked_basics(self, backend): crl = _load_cert( @@ -672,8 +664,6 @@ def test_get_revoked_certificate_doesnt_reorder(self, backend): assert crl[2].serial_number == 3 -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestRSACertificate(object): def test_load_pem_cert(self, backend): cert = _load_cert( @@ -1247,8 +1237,6 @@ def test_parse_tls_feature_extension(self, backend): ) -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestRSACertificateRequest(object): @pytest.mark.parametrize( ("path", "loader_func"), @@ -1822,8 +1810,6 @@ def read_next_rdn_value_tag(reader): class TestCertificateBuilder(object): - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_checks_for_unsupported_extensions(self, backend): private_key = RSA_KEY_2048.private_key(backend) builder = ( @@ -1844,8 +1830,6 @@ def test_checks_for_unsupported_extensions(self, backend): with pytest.raises(NotImplementedError): builder.sign(private_key, hashes.SHA1(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_encode_nonstandard_aia(self, backend): private_key = RSA_KEY_2048.private_key(backend) @@ -1875,8 +1859,6 @@ def test_encode_nonstandard_aia(self, backend): builder.sign(private_key, hashes.SHA256(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_encode_nonstandard_sia(self, backend): private_key = RSA_KEY_2048.private_key(backend) @@ -1910,8 +1892,6 @@ def test_encode_nonstandard_sia(self, backend): ) assert ext.value == sia - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_subject_dn_asn1_types(self, backend): private_key = RSA_KEY_2048.private_key(backend) @@ -1969,8 +1949,6 @@ def test_subject_dn_asn1_types(self, backend): [datetime.datetime(1970, 2, 1), datetime.datetime(9999, 12, 31)], ], ) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_extreme_times(self, not_valid_before, not_valid_after, backend): private_key = RSA_KEY_2048.private_key(backend) builder = ( @@ -1993,8 +1971,6 @@ def test_extreme_times(self, not_valid_before, not_valid_after, backend): assert parsed.not_before_tag == UTC_TIME assert parsed.not_after_tag == GENERALIZED_TIME - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_no_subject_name(self, backend): subject_private_key = RSA_KEY_2048.private_key(backend) builder = ( @@ -2010,8 +1986,6 @@ def test_no_subject_name(self, backend): with pytest.raises(ValueError): builder.sign(subject_private_key, hashes.SHA256(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_no_issuer_name(self, backend): subject_private_key = RSA_KEY_2048.private_key(backend) builder = ( @@ -2027,8 +2001,6 @@ def test_no_issuer_name(self, backend): with pytest.raises(ValueError): builder.sign(subject_private_key, hashes.SHA256(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_no_public_key(self, backend): subject_private_key = RSA_KEY_2048.private_key(backend) builder = ( @@ -2046,8 +2018,6 @@ def test_no_public_key(self, backend): with pytest.raises(ValueError): builder.sign(subject_private_key, hashes.SHA256(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_no_not_valid_before(self, backend): subject_private_key = RSA_KEY_2048.private_key(backend) builder = ( @@ -2065,8 +2035,6 @@ def test_no_not_valid_before(self, backend): with pytest.raises(ValueError): builder.sign(subject_private_key, hashes.SHA256(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_no_not_valid_after(self, backend): subject_private_key = RSA_KEY_2048.private_key(backend) builder = ( @@ -2084,8 +2052,6 @@ def test_no_not_valid_after(self, backend): with pytest.raises(ValueError): builder.sign(subject_private_key, hashes.SHA256(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_no_serial_number(self, backend): subject_private_key = RSA_KEY_2048.private_key(backend) builder = ( @@ -2151,8 +2117,6 @@ def test_not_valid_after_before_not_valid_before(self): with pytest.raises(ValueError): builder.not_valid_after(datetime.datetime(2001, 1, 1, 12, 1)) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_public_key_must_be_public_key(self, backend): private_key = RSA_KEY_2048.private_key(backend) builder = x509.CertificateBuilder() @@ -2160,8 +2124,6 @@ def test_public_key_must_be_public_key(self, backend): with pytest.raises(TypeError): builder.public_key(private_key) # type: ignore[arg-type] - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_public_key_may_only_be_set_once(self, backend): private_key = RSA_KEY_2048.private_key(backend) public_key = private_key.public_key() @@ -2184,8 +2146,6 @@ def test_serial_number_must_be_positive(self): with pytest.raises(ValueError): x509.CertificateBuilder().serial_number(0) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_minimal_serial_number(self, backend): subject_private_key = RSA_KEY_2048.private_key(backend) builder = ( @@ -2204,8 +2164,6 @@ def test_minimal_serial_number(self, backend): cert = builder.sign(subject_private_key, hashes.SHA256(), backend) assert cert.serial_number == 1 - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_biggest_serial_number(self, backend): subject_private_key = RSA_KEY_2048.private_key(backend) builder = ( @@ -2234,8 +2192,6 @@ def test_serial_number_may_only_be_set_once(self): with pytest.raises(ValueError): builder.serial_number(20) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_aware_not_valid_after(self, backend): time = datetime.datetime(2012, 1, 16, 22, 43) tz = pytz.timezone("US/Pacific") @@ -2258,8 +2214,6 @@ def test_aware_not_valid_after(self, backend): cert = cert_builder.sign(private_key, hashes.SHA256(), backend) assert cert.not_valid_after == utc_time - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_earliest_time(self, backend): time = datetime.datetime(1950, 1, 1) private_key = RSA_KEY_2048.private_key(backend) @@ -2307,8 +2261,6 @@ def test_not_valid_after_may_only_be_set_once(self): with pytest.raises(ValueError): builder.not_valid_after(datetime.datetime.now()) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_aware_not_valid_before(self, backend): time = datetime.datetime(2012, 1, 16, 22, 43) tz = pytz.timezone("US/Pacific") @@ -2376,8 +2328,6 @@ def test_add_invalid_extension_type(self): False, ) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) @pytest.mark.parametrize("algorithm", [object(), None]) def test_sign_with_unsupported_hash(self, algorithm, backend): private_key = RSA_KEY_2048.private_key(backend) @@ -2402,7 +2352,6 @@ def test_sign_with_unsupported_hash(self, algorithm, backend): only_if=lambda backend: backend.ed25519_supported(), skip_message="Requires OpenSSL with Ed25519 support", ) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_sign_with_unsupported_hash_ed25519(self, backend): private_key = ed25519.Ed25519PrivateKey.generate() builder = ( @@ -2426,7 +2375,6 @@ def test_sign_with_unsupported_hash_ed25519(self, backend): only_if=lambda backend: backend.ed448_supported(), skip_message="Requires OpenSSL with Ed448 support", ) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_sign_with_unsupported_hash_ed448(self, backend): private_key = ed448.Ed448PrivateKey.generate() builder = ( @@ -2446,8 +2394,6 @@ def test_sign_with_unsupported_hash_ed448(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA256(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) @pytest.mark.supported( only_if=lambda backend: backend.hash_supported(hashes.MD5()), skip_message="Requires OpenSSL with MD5 support", @@ -2470,8 +2416,6 @@ def test_sign_rsa_with_md5(self, backend): cert = builder.sign(private_key, hashes.MD5(), backend) assert isinstance(cert.signature_hash_algorithm, hashes.MD5) - @pytest.mark.requires_backend_interface(interface=DSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) @pytest.mark.supported( only_if=lambda backend: backend.hash_supported(hashes.MD5()), skip_message="Requires OpenSSL with MD5 support", @@ -2494,8 +2438,6 @@ def test_sign_dsa_with_md5(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.MD5(), backend) - @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) @pytest.mark.supported( only_if=lambda backend: backend.hash_supported(hashes.MD5()), skip_message="Requires OpenSSL with MD5 support", @@ -2519,8 +2461,6 @@ def test_sign_ec_with_md5(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.MD5(), backend) - @pytest.mark.requires_backend_interface(interface=DSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_build_cert_with_dsa_private_key(self, backend): issuer_private_key = DSA_KEY_2048.private_key(backend) subject_private_key = DSA_KEY_2048.private_key(backend) @@ -2567,8 +2507,6 @@ def test_build_cert_with_dsa_private_key(self, backend): x509.DNSName("cryptography.io"), ] - @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_build_cert_with_ec_private_key(self, backend): _skip_curve_unsupported(backend, ec.SECP256R1()) issuer_private_key = ec.generate_private_key(ec.SECP256R1(), backend) @@ -2620,7 +2558,6 @@ def test_build_cert_with_ec_private_key(self, backend): only_if=lambda backend: backend.ed25519_supported(), skip_message="Requires OpenSSL with Ed25519 support", ) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_build_cert_with_ed25519(self, backend): issuer_private_key = ed25519.Ed25519PrivateKey.generate() subject_private_key = ed25519.Ed25519PrivateKey.generate() @@ -2676,8 +2613,6 @@ def test_build_cert_with_ed25519(self, backend): only_if=lambda backend: backend.ed25519_supported(), skip_message="Requires OpenSSL with Ed25519 support", ) - @pytest.mark.requires_backend_interface(interface=X509Backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) def test_build_cert_with_public_ed25519_rsa_sig(self, backend): issuer_private_key = RSA_KEY_2048.private_key(backend) subject_private_key = ed25519.Ed25519PrivateKey.generate() @@ -2716,7 +2651,6 @@ def test_build_cert_with_public_ed25519_rsa_sig(self, backend): only_if=lambda backend: backend.ed448_supported(), skip_message="Requires OpenSSL with Ed448 support", ) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_build_cert_with_ed448(self, backend): issuer_private_key = ed448.Ed448PrivateKey.generate() subject_private_key = ed448.Ed448PrivateKey.generate() @@ -2772,8 +2706,6 @@ def test_build_cert_with_ed448(self, backend): only_if=lambda backend: backend.ed448_supported(), skip_message="Requires OpenSSL with Ed448 support", ) - @pytest.mark.requires_backend_interface(interface=X509Backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) def test_build_cert_with_public_ed448_rsa_sig(self, backend): issuer_private_key = RSA_KEY_2048.private_key(backend) subject_private_key = ed448.Ed448PrivateKey.generate() @@ -2808,8 +2740,6 @@ def test_build_cert_with_public_ed448_rsa_sig(self, backend): assert isinstance(cert.signature_hash_algorithm, hashes.SHA256) assert isinstance(cert.public_key(), ed448.Ed448PublicKey) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_build_cert_with_rsa_key_too_small(self, backend): issuer_private_key = RSA_KEY_512.private_key(backend) subject_private_key = RSA_KEY_512.private_key(backend) @@ -2834,8 +2764,6 @@ def test_build_cert_with_rsa_key_too_small(self, backend): with pytest.raises(ValueError): builder.sign(issuer_private_key, hashes.SHA512(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) @pytest.mark.parametrize( "add_ext", [ @@ -3228,8 +3156,6 @@ def test_ext(self, add_ext, backend): assert ext.critical is False assert ext.value == add_ext - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_key_usage(self, backend): issuer_private_key = RSA_KEY_2048.private_key(backend) subject_private_key = RSA_KEY_2048.private_key(backend) @@ -3280,8 +3206,6 @@ def test_key_usage(self, backend): decipher_only=False, ) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_build_ca_request_with_path_length_none(self, backend): private_key = RSA_KEY_2048.private_key(backend) @@ -3317,8 +3241,6 @@ def test_build_ca_request_with_path_length_none(self, backend): ) ], ) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_unrecognized_extension(self, backend, unrecognized): private_key = RSA_KEY_2048.private_key(backend) @@ -3343,9 +3265,7 @@ def test_unrecognized_extension(self, backend, unrecognized): assert ext.value == unrecognized -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestCertificateSigningRequestBuilder(object): - @pytest.mark.requires_backend_interface(interface=RSABackend) def test_sign_invalid_hash_algorithm(self, backend): private_key = RSA_KEY_2048.private_key(backend) @@ -3359,7 +3279,6 @@ def test_sign_invalid_hash_algorithm(self, backend): only_if=lambda backend: backend.ed25519_supported(), skip_message="Requires OpenSSL with Ed25519 support", ) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_request_with_unsupported_hash_ed25519(self, backend): private_key = ed25519.Ed25519PrivateKey.generate() builder = x509.CertificateSigningRequestBuilder().subject_name( @@ -3373,7 +3292,6 @@ def test_request_with_unsupported_hash_ed25519(self, backend): only_if=lambda backend: backend.ed448_supported(), skip_message="Requires OpenSSL with Ed448 support", ) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_request_with_unsupported_hash_ed448(self, backend): private_key = ed448.Ed448PrivateKey.generate() builder = x509.CertificateSigningRequestBuilder().subject_name( @@ -3383,7 +3301,6 @@ def test_request_with_unsupported_hash_ed448(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA256(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) @pytest.mark.supported( only_if=lambda backend: backend.hash_supported(hashes.MD5()), skip_message="Requires OpenSSL with MD5 support", @@ -3397,7 +3314,6 @@ def test_sign_rsa_with_md5(self, backend): request = builder.sign(private_key, hashes.MD5(), backend) assert isinstance(request.signature_hash_algorithm, hashes.MD5) - @pytest.mark.requires_backend_interface(interface=DSABackend) @pytest.mark.supported( only_if=lambda backend: backend.hash_supported(hashes.MD5()), skip_message="Requires OpenSSL with MD5 support", @@ -3410,7 +3326,6 @@ def test_sign_dsa_with_md5(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.MD5(), backend) - @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) @pytest.mark.supported( only_if=lambda backend: backend.hash_supported(hashes.MD5()), skip_message="Requires OpenSSL with MD5 support", @@ -3424,7 +3339,6 @@ def test_sign_ec_with_md5(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.MD5(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) def test_no_subject_name(self, backend): private_key = RSA_KEY_2048.private_key(backend) @@ -3432,7 +3346,6 @@ def test_no_subject_name(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA256(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) def test_build_ca_request_with_rsa(self, backend): private_key = RSA_KEY_2048.private_key(backend) @@ -3463,7 +3376,6 @@ def test_build_ca_request_with_rsa(self, backend): assert basic_constraints.value.ca is True assert basic_constraints.value.path_length == 2 - @pytest.mark.requires_backend_interface(interface=RSABackend) def test_build_ca_request_with_unicode(self, backend): private_key = RSA_KEY_2048.private_key(backend) @@ -3493,7 +3405,6 @@ def test_build_ca_request_with_unicode(self, backend): x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA\U0001f37a"), ] - @pytest.mark.requires_backend_interface(interface=RSABackend) def test_subject_dn_asn1_types(self, backend): private_key = RSA_KEY_2048.private_key(backend) @@ -3552,7 +3463,6 @@ def test_subject_dn_asn1_types(self, backend): == asn1_type ) - @pytest.mark.requires_backend_interface(interface=RSABackend) def test_build_ca_request_with_multivalue_rdns(self, backend): private_key = RSA_KEY_2048.private_key(backend) subject = x509.Name( @@ -3582,7 +3492,6 @@ def test_build_ca_request_with_multivalue_rdns(self, backend): assert isinstance(loaded_request.subject, x509.Name) assert loaded_request.subject == subject - @pytest.mark.requires_backend_interface(interface=RSABackend) def test_build_nonca_request_with_rsa(self, backend): private_key = RSA_KEY_2048.private_key(backend) @@ -3612,7 +3521,6 @@ def test_build_nonca_request_with_rsa(self, backend): assert basic_constraints.value.ca is False assert basic_constraints.value.path_length is None - @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) def test_build_ca_request_with_ec(self, backend): _skip_curve_unsupported(backend, ec.SECP256R1()) private_key = ec.generate_private_key(ec.SECP256R1(), backend) @@ -3652,7 +3560,6 @@ def test_build_ca_request_with_ec(self, backend): only_if=lambda backend: backend.ed25519_supported(), skip_message="Requires OpenSSL with Ed25519 support", ) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_build_ca_request_with_ed25519(self, backend): private_key = ed25519.Ed25519PrivateKey.generate() @@ -3691,7 +3598,6 @@ def test_build_ca_request_with_ed25519(self, backend): only_if=lambda backend: backend.ed448_supported(), skip_message="Requires OpenSSL with Ed448 support", ) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_build_ca_request_with_ed448(self, backend): private_key = ed448.Ed448PrivateKey.generate() @@ -3726,7 +3632,6 @@ def test_build_ca_request_with_ed448(self, backend): assert basic_constraints.value.ca is True assert basic_constraints.value.path_length == 2 - @pytest.mark.requires_backend_interface(interface=DSABackend) def test_build_ca_request_with_dsa(self, backend): private_key = DSA_KEY_2048.private_key(backend) @@ -3902,7 +3807,6 @@ def test_add_two_extensions(self, backend): ) assert list(ext.value) == [x509.DNSName("cryptography.io")] - @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) def test_add_attributes(self, backend): _skip_curve_unsupported(backend, ec.SECP256R1()) private_key = ec.generate_private_key(ec.SECP256R1(), backend) @@ -4104,7 +4008,6 @@ def test_extended_key_usage(self, backend): assert ext.critical is False assert ext.value == eku - @pytest.mark.requires_backend_interface(interface=RSABackend) def test_rsa_key_too_small(self, backend): private_key = RSA_KEY_512.private_key(backend) builder = x509.CertificateSigningRequestBuilder() @@ -4115,8 +4018,6 @@ def test_rsa_key_too_small(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA512(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_build_cert_with_aia(self, backend): issuer_private_key = RSA_KEY_2048.private_key(backend) subject_private_key = RSA_KEY_2048.private_key(backend) @@ -4159,8 +4060,6 @@ def test_build_cert_with_aia(self, backend): ) assert ext.value == aia - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_build_cert_with_sia(self, backend): issuer_private_key = RSA_KEY_2048.private_key(backend) subject_private_key = RSA_KEY_2048.private_key(backend) @@ -4199,8 +4098,6 @@ def test_build_cert_with_sia(self, backend): ) assert ext.value == sia - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_build_cert_with_ski(self, backend): issuer_private_key = RSA_KEY_2048.private_key(backend) subject_private_key = RSA_KEY_2048.private_key(backend) @@ -4282,8 +4179,6 @@ def test_build_cert_with_ski(self, backend): ), ], ) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_build_cert_with_aki(self, aki, backend): issuer_private_key = RSA_KEY_2048.private_key(backend) subject_private_key = RSA_KEY_2048.private_key(backend) @@ -4341,8 +4236,6 @@ def test_ocsp_nocheck(self, backend): assert isinstance(ext.value, x509.OCSPNoCheck) -@pytest.mark.requires_backend_interface(interface=DSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestDSACertificate(object): def test_load_dsa_cert(self, backend): cert = _load_cert( @@ -4465,8 +4358,6 @@ def test_tbs_certificate_bytes(self, backend): ) -@pytest.mark.requires_backend_interface(interface=DSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestDSACertificateRequest(object): @pytest.mark.parametrize( ("path", "loader_func"), @@ -4539,8 +4430,6 @@ def test_tbs_certrequest_bytes(self, backend): ) -@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestECDSACertificate(object): def test_load_ecdsa_cert(self, backend): _skip_curve_unsupported(backend, ec.SECP384R1()) @@ -4630,8 +4519,6 @@ def test_load_ecdsa_no_named_curve(self, backend): cert.public_key() -@pytest.mark.requires_backend_interface(interface=X509Backend) -@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) class TestECDSACertificateRequest(object): @pytest.mark.parametrize( ("path", "loader_func"), @@ -4699,7 +4586,6 @@ def test_tbs_certrequest_bytes(self, backend): ) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestOtherCertificate(object): def test_unsupported_subject_public_key_info(self, backend): cert = _load_cert( @@ -5105,7 +4991,6 @@ def test_not_nameattribute(self): with pytest.raises(TypeError): x509.Name(["not-a-NameAttribute"]) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_bytes(self, backend): name = x509.Name( [ @@ -5118,7 +5003,6 @@ def test_bytes(self, backend): b"b060355040a0c0450794341" ) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_bmpstring_bytes(self, backend): # For this test we need an odd length string. BMPString is UCS-2 # encoded so it will always be even length and OpenSSL will error if @@ -5138,7 +5022,6 @@ def test_bmpstring_bytes(self, backend): b"7000680079002e0069006f310d300b060355040a0c0450794341" ) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_universalstring_bytes(self, backend): # UniversalString is UCS-4 name = x509.Name( @@ -5162,7 +5045,6 @@ def test_universalstring_bytes(self, backend): only_if=lambda backend: backend.ed25519_supported(), skip_message="Requires OpenSSL with Ed25519 support", ) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestEd25519Certificate(object): def test_load_pem_cert(self, backend): cert = _load_cert( @@ -5190,7 +5072,6 @@ def test_deepcopy(self, backend): only_if=lambda backend: backend.ed448_supported(), skip_message="Requires OpenSSL with Ed448 support", ) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestEd448Certificate(object): def test_load_pem_cert(self, backend): cert = _load_cert( @@ -5206,7 +5087,6 @@ def test_load_pem_cert(self, backend): assert cert.signature_algorithm_oid == SignatureAlgorithmOID.ED448 -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestSignatureRejection(object): """Test if signing rejects DH keys properly.""" diff --git a/tests/x509/test_x509_crlbuilder.py b/tests/x509/test_x509_crlbuilder.py index 88725710d7fd..b32322f975e6 100644 --- a/tests/x509/test_x509_crlbuilder.py +++ b/tests/x509/test_x509_crlbuilder.py @@ -10,12 +10,6 @@ import pytz from cryptography import x509 -from cryptography.hazmat.backends.interfaces import ( - DSABackend, - EllipticCurveBackend, - RSABackend, - X509Backend, -) from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import ec, ed25519, ed448 from cryptography.x509.oid import ( @@ -45,8 +39,6 @@ def test_set_issuer_name_twice(self): x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_aware_last_update(self, backend): last_time = datetime.datetime(2012, 1, 16, 22, 43) tz = pytz.timezone("US/Pacific") @@ -89,8 +81,6 @@ def test_set_last_update_twice(self): with pytest.raises(ValueError): builder.last_update(datetime.datetime(2002, 1, 1, 12, 1)) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_aware_next_update(self, backend): next_time = datetime.datetime(2022, 1, 16, 22, 43) tz = pytz.timezone("US/Pacific") @@ -167,8 +157,6 @@ def test_add_invalid_revoked_certificate(self): with pytest.raises(TypeError): builder.add_revoked_certificate(object()) # type:ignore[arg-type] - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_no_issuer_name(self, backend): private_key = RSA_KEY_2048.private_key(backend) builder = ( @@ -180,8 +168,6 @@ def test_no_issuer_name(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA256(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_no_last_update(self, backend): private_key = RSA_KEY_2048.private_key(backend) builder = ( @@ -195,8 +181,6 @@ def test_no_last_update(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA256(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_no_next_update(self, backend): private_key = RSA_KEY_2048.private_key(backend) builder = ( @@ -210,8 +194,6 @@ def test_no_next_update(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA256(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_sign_empty_list(self, backend): private_key = RSA_KEY_2048.private_key(backend) last_update = datetime.datetime(2002, 1, 1, 12, 1) @@ -260,8 +242,6 @@ def test_sign_empty_list(self, backend): ), ], ) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_sign_extensions(self, backend, extension): private_key = RSA_KEY_2048.private_key(backend) last_update = datetime.datetime(2002, 1, 1, 12, 1) @@ -289,8 +269,6 @@ def test_sign_extensions(self, backend, extension): assert ext.critical is False assert ext.value == extension - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_sign_multiple_extensions_critical(self, backend): private_key = RSA_KEY_2048.private_key(backend) last_update = datetime.datetime(2002, 1, 1, 12, 1) @@ -328,8 +306,6 @@ def test_sign_multiple_extensions_critical(self, backend): assert ext2.critical is True assert ext2.value == ian - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_freshestcrl_extension(self, backend): private_key = RSA_KEY_2048.private_key(backend) last_update = datetime.datetime(2002, 1, 1, 12, 1) @@ -371,8 +347,6 @@ def test_freshestcrl_extension(self, backend): assert isinstance(uri, x509.UniformResourceIdentifier) assert uri.value == "http://d.om/delta" - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_add_unsupported_extension(self, backend): private_key = RSA_KEY_2048.private_key(backend) last_update = datetime.datetime(2002, 1, 1, 12, 1) @@ -395,8 +369,6 @@ def test_add_unsupported_extension(self, backend): with pytest.raises(NotImplementedError): builder.sign(private_key, hashes.SHA256(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_sign_rsa_key_too_small(self, backend): private_key = RSA_KEY_512.private_key(backend) last_update = datetime.datetime(2002, 1, 1, 12, 1) @@ -419,8 +391,6 @@ def test_sign_rsa_key_too_small(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA512(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_sign_with_invalid_hash(self, backend): private_key = RSA_KEY_2048.private_key(backend) last_update = datetime.datetime(2002, 1, 1, 12, 1) @@ -447,7 +417,6 @@ def test_sign_with_invalid_hash(self, backend): only_if=lambda backend: backend.ed25519_supported(), skip_message="Requires OpenSSL with Ed25519 support", ) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_sign_with_invalid_hash_ed25519(self, backend): private_key = ed25519.Ed25519PrivateKey.generate() last_update = datetime.datetime(2002, 1, 1, 12, 1) @@ -476,7 +445,6 @@ def test_sign_with_invalid_hash_ed25519(self, backend): only_if=lambda backend: backend.ed448_supported(), skip_message="Requires OpenSSL with Ed448 support", ) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_sign_with_invalid_hash_ed448(self, backend): private_key = ed448.Ed448PrivateKey.generate() last_update = datetime.datetime(2002, 1, 1, 12, 1) @@ -501,8 +469,6 @@ def test_sign_with_invalid_hash_ed448(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA256(), backend) - @pytest.mark.requires_backend_interface(interface=DSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_sign_dsa_key(self, backend): private_key = DSA_KEY_2048.private_key(backend) invalidity_date = x509.InvalidityDate( @@ -551,8 +517,6 @@ def test_sign_dsa_key(self, backend): assert ext.critical is False assert ext.value == invalidity_date - @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_sign_ec_key(self, backend): _skip_curve_unsupported(backend, ec.SECP256R1()) private_key = ec.generate_private_key(ec.SECP256R1(), backend) @@ -606,7 +570,6 @@ def test_sign_ec_key(self, backend): only_if=lambda backend: backend.ed25519_supported(), skip_message="Requires OpenSSL with Ed25519 support", ) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_sign_ed25519_key(self, backend): private_key = ed25519.Ed25519PrivateKey.generate() invalidity_date = x509.InvalidityDate( @@ -661,7 +624,6 @@ def test_sign_ed25519_key(self, backend): only_if=lambda backend: backend.ed448_supported(), skip_message="Requires OpenSSL with Ed448 support", ) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_sign_ed448_key(self, backend): private_key = ed448.Ed448PrivateKey.generate() invalidity_date = x509.InvalidityDate( @@ -712,8 +674,6 @@ def test_sign_ed448_key(self, backend): assert ext.critical is False assert ext.value == invalidity_date - @pytest.mark.requires_backend_interface(interface=DSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_dsa_key_sign_md5(self, backend): private_key = DSA_KEY_2048.private_key(backend) last_time = datetime.datetime(2012, 1, 16, 22, 43) @@ -736,8 +696,6 @@ def test_dsa_key_sign_md5(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.MD5(), backend) - @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_ec_key_sign_md5(self, backend): _skip_curve_unsupported(backend, ec.SECP256R1()) private_key = EC_KEY_SECP256R1.private_key(backend) @@ -761,8 +719,6 @@ def test_ec_key_sign_md5(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.MD5(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_sign_with_revoked_certificates(self, backend): private_key = RSA_KEY_2048.private_key(backend) last_update = datetime.datetime(2002, 1, 1, 12, 1) diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index f74f3d5a5f56..5fd3b527f5eb 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -14,12 +14,6 @@ import pytest from cryptography import x509 -from cryptography.hazmat.backends.interfaces import ( - DSABackend, - EllipticCurveBackend, - RSABackend, - X509Backend, -) from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import ec from cryptography.x509 import DNSName, NameConstraints, SubjectAlternativeName @@ -569,7 +563,6 @@ def test_hash(self): assert hash(pi) != hash(pi3) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestCertificatePolicies(object): def test_invalid_policies(self): pq = ["string"] @@ -665,8 +658,6 @@ def test_hash(self): assert hash(cp) != hash(cp3) -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestCertificatePoliciesExtension(object): def test_cps_uri_policy_qualifier(self, backend): cert = _load_cert( @@ -1278,8 +1269,6 @@ def test_hash(self): assert hash(eku) != hash(eku3) -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestExtensions(object): def test_no_extensions(self, backend): cert = _load_cert( @@ -1332,7 +1321,6 @@ def test_unsupported_critical_extension(self, backend): ) assert ext.value.value == b"value" - @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) def test_unsupported_extension(self, backend): cert = _load_cert( os.path.join("x509", "custom", "unsupported_extension_2.pem"), @@ -1410,8 +1398,6 @@ def test_repr(self, backend): ) -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestBasicConstraintsExtension(object): def test_ca_true_pathlen_6(self, backend): cert = _load_cert( @@ -1504,8 +1490,6 @@ def test_basic_constraint_not_critical(self, backend): class TestSubjectKeyIdentifierExtension(object): - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_subject_key_identifier(self, backend): cert = _load_cert( os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"), @@ -1522,8 +1506,6 @@ def test_subject_key_identifier(self, backend): b"580184241bbc2b52944a3da510721451f5af3ac9" ) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_no_subject_key_identifier(self, backend): cert = _load_cert( os.path.join("x509", "custom", "bc_path_length_zero.pem"), @@ -1535,8 +1517,6 @@ def test_no_subject_key_identifier(self, backend): ExtensionOID.SUBJECT_KEY_IDENTIFIER ) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_from_rsa_public_key(self, backend): cert = _load_cert( os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"), @@ -1549,8 +1529,6 @@ def test_from_rsa_public_key(self, backend): ski = x509.SubjectKeyIdentifier.from_public_key(cert.public_key()) assert ext.value == ski - @pytest.mark.requires_backend_interface(interface=DSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_from_dsa_public_key(self, backend): cert = _load_cert( os.path.join("x509", "custom", "dsa_selfsigned_ca.pem"), @@ -1564,8 +1542,6 @@ def test_from_dsa_public_key(self, backend): ski = x509.SubjectKeyIdentifier.from_public_key(cert.public_key()) assert ext.value == ski - @pytest.mark.requires_backend_interface(interface=DSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_invalid_bit_string_padding_from_public_key(self, backend): data = load_vectors_from_file( filename=os.path.join( @@ -1580,8 +1556,6 @@ def test_invalid_bit_string_padding_from_public_key(self, backend): with pytest.raises(ValueError): _key_identifier_from_public_key(pretend_key) - @pytest.mark.requires_backend_interface(interface=DSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_no_optional_params_allowed_from_public_key(self, backend): data = load_vectors_from_file( filename=os.path.join( @@ -1598,8 +1572,6 @@ def test_no_optional_params_allowed_from_public_key(self, backend): b"24c0133a6a492f2c48a18c7648e515db5ac76749" ) - @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_from_ec_public_key(self, backend): _skip_curve_unsupported(backend, ec.SECP384R1()) cert = _load_cert( @@ -1618,7 +1590,6 @@ def test_from_ec_public_key(self, backend): only_if=lambda backend: backend.ed25519_supported(), skip_message="Requires OpenSSL with Ed25519 support", ) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_from_ed25519_public_key(self, backend): cert = _load_cert( os.path.join("x509", "ed25519", "root-ed25519.pem"), @@ -1636,7 +1607,6 @@ def test_from_ed25519_public_key(self, backend): only_if=lambda backend: backend.ed448_supported(), skip_message="Requires OpenSSL with Ed448 support", ) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_from_ed448_public_key(self, backend): cert = _load_cert( os.path.join("x509", "ed448", "root-ed448.pem"), @@ -1651,8 +1621,6 @@ def test_from_ed448_public_key(self, backend): assert ext.value == ski -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestKeyUsageExtension(object): def test_no_key_usage(self, backend): cert = _load_cert( @@ -2140,8 +2108,6 @@ def test_hash(self): assert hash(ian) != hash(ian3) -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestRSAIssuerAlternativeNameExtension(object): def test_uri(self, backend): cert = _load_cert( @@ -2251,8 +2217,6 @@ def test_hash(self): assert hash(san) != hash(san3) -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestRSASubjectAlternativeNameExtension(object): def test_dns_name(self, backend): cert = _load_cert( @@ -2552,8 +2516,6 @@ def test_certbuilder(self, backend): assert result == sans -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestExtendedKeyUsageExtension(object): def test_eku(self, backend): cert = _load_cert( @@ -2698,8 +2660,6 @@ def test_hash(self): assert hash(pc) != hash(pc3) -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestPolicyConstraintsExtension(object): def test_inhibit_policy_mapping(self, backend): cert = _load_cert( @@ -3098,8 +3058,6 @@ def test_hash(self): assert hash(sia) != hash(sia3) -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestSubjectInformationAccessExtension(object): def test_sia(self, backend): cert = _load_cert( @@ -3129,8 +3087,6 @@ def test_sia(self, backend): ) -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestAuthorityInformationAccessExtension(object): def test_aia_ocsp_ca_issuers(self, backend): cert = _load_cert( @@ -3253,8 +3209,6 @@ def test_aia_ca_issuers_only(self, backend): ) -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestAuthorityKeyIdentifierExtension(object): def test_aki_keyid(self, backend): cert = _load_cert( @@ -3499,8 +3453,6 @@ def test_hash(self): assert hash(nc3) != hash(nc4) -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestNameConstraintsExtension(object): def test_permitted_excluded(self, backend): cert = _load_cert( @@ -4354,8 +4306,6 @@ def test_indexing(self): assert ci[2:6:2] == [ci[2], ci[4]] -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestCRLDistributionPointsExtension(object): def test_fullname_and_crl_issuer(self, backend): cert = _load_cert( @@ -4641,8 +4591,6 @@ def test_crl_empty_hostname(self, backend): ) -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestFreshestCRLExtension(object): def test_vector(self, backend): cert = _load_cert( @@ -4689,8 +4637,6 @@ def test_vector(self, backend): ) -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestOCSPNoCheckExtension(object): def test_nocheck(self, backend): cert = _load_cert( @@ -4759,8 +4705,6 @@ def test_hash(self): assert hash(iap) != hash(iap3) -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestInhibitAnyPolicyExtension(object): def test_inhibit_any_policy(self, backend): cert = _load_cert( @@ -4926,8 +4870,6 @@ class TestIssuingDistributionPointExtension(object): ), ], ) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_vectors(self, filename, expected, backend): crl = _load_cert( os.path.join("x509", "custom", filename), @@ -5132,8 +5074,6 @@ def test_hash(self): assert hash(idp1) == hash(idp2) assert hash(idp1) != hash(idp3) - @pytest.mark.requires_backend_interface(interface=RSABackend) - @pytest.mark.requires_backend_interface(interface=X509Backend) @pytest.mark.parametrize( "idp", [ @@ -5284,8 +5224,6 @@ def test_generate(self, idp, backend): assert ext.value == idp -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestPrecertPoisonExtension(object): def test_load(self, backend): cert = _load_cert( @@ -5340,8 +5278,6 @@ def test_repr(self): assert repr(pcp) == "" -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestSignedCertificateTimestamps(object): @pytest.mark.supported( only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), @@ -5444,8 +5380,6 @@ def test_hash(self, backend): assert hash(sct) != hash(sct3) -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestPrecertificateSignedCertificateTimestampsExtension(object): def test_init(self): with pytest.raises(TypeError): @@ -5636,8 +5570,6 @@ def test_skips_scts_if_unsupported(self, backend): assert isinstance(ext.value, x509.UnrecognizedExtension) -@pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.requires_backend_interface(interface=X509Backend) class TestInvalidExtension(object): def test_invalid_certificate_policies_data(self, backend): cert = _load_cert( diff --git a/tests/x509/test_x509_revokedcertbuilder.py b/tests/x509/test_x509_revokedcertbuilder.py index 34738e513e9a..b504185d3e36 100644 --- a/tests/x509/test_x509_revokedcertbuilder.py +++ b/tests/x509/test_x509_revokedcertbuilder.py @@ -10,7 +10,6 @@ import pytz from cryptography import x509 -from cryptography.hazmat.backends.interfaces import X509Backend class TestRevokedCertificateBuilder(object): @@ -28,7 +27,6 @@ def test_serial_number_must_be_positive(self): with pytest.raises(ValueError): x509.RevokedCertificateBuilder().serial_number(0) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_minimal_serial_number(self, backend): revocation_date = datetime.datetime(2002, 1, 1, 12, 1) builder = ( @@ -40,7 +38,6 @@ def test_minimal_serial_number(self, backend): revoked_certificate = builder.build(backend) assert revoked_certificate.serial_number == 1 - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_biggest_serial_number(self, backend): revocation_date = datetime.datetime(2002, 1, 1, 12, 1) builder = ( @@ -61,7 +58,6 @@ def test_set_serial_number_twice(self): with pytest.raises(ValueError): builder.serial_number(4) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_aware_revocation_date(self, backend): time = datetime.datetime(2012, 1, 16, 22, 43) tz = pytz.timezone("US/Pacific") @@ -112,7 +108,6 @@ def test_add_invalid_extension(self): "notanextension", False # type: ignore[arg-type] ) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_no_serial_number(self, backend): builder = x509.RevokedCertificateBuilder().revocation_date( datetime.datetime(2002, 1, 1, 12, 1) @@ -121,14 +116,12 @@ def test_no_serial_number(self, backend): with pytest.raises(ValueError): builder.build(backend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_no_revocation_date(self, backend): builder = x509.RevokedCertificateBuilder().serial_number(3) with pytest.raises(ValueError): builder.build(backend) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_create_revoked(self, backend): serial_number = 333 revocation_date = datetime.datetime(2002, 1, 1, 12, 1) @@ -151,7 +144,6 @@ def test_create_revoked(self, backend): x509.CertificateIssuer([x509.DNSName("cryptography.io")]), ], ) - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_add_extensions(self, backend, extension): serial_number = 333 revocation_date = datetime.datetime(2002, 1, 1, 12, 1) @@ -172,7 +164,6 @@ def test_add_extensions(self, backend, extension): assert ext.critical is False assert ext.value == extension - @pytest.mark.requires_backend_interface(interface=X509Backend) def test_add_multiple_extensions(self, backend): serial_number = 333 revocation_date = datetime.datetime(2002, 1, 1, 12, 1) From 17ec5db3374e7804c840cb2bafbe25cd07d9b065 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 1 Mar 2021 16:40:25 -0500 Subject: [PATCH 0170/2380] Delete unused register_interface_if (#5883) --- src/cryptography/utils.py | 10 ---------- tests/test_interfaces.py | 23 ----------------------- 2 files changed, 33 deletions(-) diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index ef0fc44332d0..e0abd4a8ab6c 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -49,16 +49,6 @@ def register_decorator(klass, *, check_annotations=False): return register_decorator -def register_interface_if(predicate, iface): - def register_decorator(klass, *, check_annotations=False): - if predicate: - verify_interface(iface, klass, check_annotations=check_annotations) - iface.register(klass) - return klass - - return register_decorator - - def int_to_bytes(integer: int, length: typing.Optional[int] = None) -> bytes: return integer.to_bytes( length or (integer.bit_length() + 7) // 8 or 1, "big" diff --git a/tests/test_interfaces.py b/tests/test_interfaces.py index 89d802aed017..7736690cb536 100644 --- a/tests/test_interfaces.py +++ b/tests/test_interfaces.py @@ -8,33 +8,10 @@ from cryptography.utils import ( InterfaceNotImplemented, - register_interface_if, verify_interface, ) -def test_register_interface_if_true(): - class SimpleInterface(metaclass=abc.ABCMeta): - pass - - @register_interface_if(1 == 1, SimpleInterface) - class SimpleClass(object): - pass - - assert issubclass(SimpleClass, SimpleInterface) is True - - -def test_register_interface_if_false(): - class SimpleInterface(metaclass=abc.ABCMeta): - pass - - @register_interface_if(1 == 2, SimpleInterface) - class SimpleClass(object): - pass - - assert issubclass(SimpleClass, SimpleInterface) is False - - class TestVerifyInterface(object): def test_verify_missing_method(self): class SimpleInterface(metaclass=abc.ABCMeta): From a2d4ea3e1a0858f0f68ebf4724d37e0e4edf0660 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 1 Mar 2021 19:39:41 -0500 Subject: [PATCH 0171/2380] wycheproof_tests is not longer a fixture (#5886) --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 2c90d97ae06c..b2bf92caf086 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,5 +19,4 @@ addopts = "-r s" markers = [ "skip_fips: this test is not executed in FIPS mode", "supported: parametrized test requiring only_if and skip_message", - "wycheproof_tests: this test runs a wycheproof fixture", ] From 032a7f3cdca5207d3b1e2a5eed14897d88f78378 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 2 Mar 2021 11:48:03 -0600 Subject: [PATCH 0172/2380] more typing (#5887) * backend typing for twofactor package and more otp work * even more typing * style fixes * no generic typing for _get_backend * remove unneeded typing --- src/cryptography/fernet.py | 3 +- src/cryptography/hazmat/backends/__init__.py | 6 +- .../hazmat/backends/interfaces.py | 63 +++++++++++ .../hazmat/backends/openssl/backend.py | 32 +----- .../hazmat/primitives/asymmetric/dh.py | 23 ++-- .../hazmat/primitives/asymmetric/dsa.py | 27 +++-- .../hazmat/primitives/asymmetric/ec.py | 17 ++- .../hazmat/primitives/asymmetric/ed25519.py | 2 +- .../hazmat/primitives/asymmetric/ed448.py | 4 +- .../hazmat/primitives/asymmetric/rsa.py | 14 ++- .../hazmat/primitives/asymmetric/x448.py | 2 +- .../hazmat/primitives/ciphers/aead.py | 6 +- .../hazmat/primitives/ciphers/algorithms.py | 2 +- .../hazmat/primitives/ciphers/base.py | 6 +- .../hazmat/primitives/ciphers/modes.py | 8 +- src/cryptography/hazmat/primitives/cmac.py | 9 +- src/cryptography/hazmat/primitives/hashes.py | 9 +- src/cryptography/hazmat/primitives/hmac.py | 6 +- .../hazmat/primitives/kdf/concatkdf.py | 13 ++- .../hazmat/primitives/kdf/hkdf.py | 6 +- .../hazmat/primitives/kdf/kbkdf.py | 4 +- .../hazmat/primitives/kdf/pbkdf2.py | 6 +- .../hazmat/primitives/kdf/scrypt.py | 11 +- .../hazmat/primitives/kdf/x963kdf.py | 4 +- src/cryptography/hazmat/primitives/keywrap.py | 27 ++++- .../hazmat/primitives/serialization/base.py | 25 ++++- .../hazmat/primitives/serialization/pkcs12.py | 5 +- .../hazmat/primitives/serialization/pkcs7.py | 3 +- .../hazmat/primitives/serialization/ssh.py | 13 ++- .../hazmat/primitives/twofactor/hotp.py | 8 +- .../hazmat/primitives/twofactor/totp.py | 4 +- src/cryptography/utils.py | 4 +- src/cryptography/x509/base.py | 105 ++++++++++++------ src/cryptography/x509/name.py | 3 +- tests/hazmat/backends/test_no_backend.py | 2 +- tests/hazmat/primitives/test_ciphers.py | 6 +- tests/hazmat/primitives/test_cmac.py | 2 +- tests/hazmat/primitives/test_concatkdf.py | 15 ++- tests/hazmat/primitives/test_dh.py | 21 ++-- tests/hazmat/primitives/test_hashes.py | 2 +- tests/hazmat/primitives/test_hkdf.py | 12 +- tests/hazmat/primitives/test_hmac.py | 4 +- tests/hazmat/primitives/test_kbkdf.py | 2 +- tests/hazmat/primitives/test_pbkdf2hmac.py | 8 +- tests/hazmat/primitives/test_rsa.py | 4 +- tests/hazmat/primitives/test_scrypt.py | 2 +- tests/hazmat/primitives/test_x963kdf.py | 7 +- .../hazmat/primitives/twofactor/test_hotp.py | 4 +- .../hazmat/primitives/twofactor/test_totp.py | 8 +- tests/x509/test_x509.py | 36 +++++- tests/x509/test_x509_crlbuilder.py | 17 ++- 51 files changed, 448 insertions(+), 184 deletions(-) diff --git a/src/cryptography/fernet.py b/src/cryptography/fernet.py index 57772fee424a..bcf1c9848c6e 100644 --- a/src/cryptography/fernet.py +++ b/src/cryptography/fernet.py @@ -13,6 +13,7 @@ from cryptography import utils from cryptography.exceptions import InvalidSignature from cryptography.hazmat.backends import _get_backend +from cryptography.hazmat.backends.interfaces import Backend from cryptography.hazmat.primitives import hashes, padding from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives.hmac import HMAC @@ -26,7 +27,7 @@ class InvalidToken(Exception): class Fernet(object): - def __init__(self, key: bytes, backend=None): + def __init__(self, key: bytes, backend: typing.Optional[Backend] = None): backend = _get_backend(backend) key = base64.urlsafe_b64decode(key) diff --git a/src/cryptography/hazmat/backends/__init__.py b/src/cryptography/hazmat/backends/__init__.py index 72c65b197f09..7f74cba2c9b2 100644 --- a/src/cryptography/hazmat/backends/__init__.py +++ b/src/cryptography/hazmat/backends/__init__.py @@ -4,7 +4,9 @@ import typing -_default_backend: typing.Any = None +from cryptography.hazmat.backends.interfaces import Backend + +_default_backend: typing.Optional[Backend] = None def default_backend(): @@ -18,7 +20,7 @@ def default_backend(): return _default_backend -def _get_backend(backend): +def _get_backend(backend: typing.Optional[Backend]) -> Backend: if backend is None: return default_backend() else: diff --git a/src/cryptography/hazmat/backends/interfaces.py b/src/cryptography/hazmat/backends/interfaces.py index d5debb5426e0..d57289bb1dc2 100644 --- a/src/cryptography/hazmat/backends/interfaces.py +++ b/src/cryptography/hazmat/backends/interfaces.py @@ -317,6 +317,18 @@ def x509_name_bytes(self, name): Compute the DER encoded bytes of an X509 Name object. """ + @abc.abstractmethod + def load_pem_x509_crl(self, data): + """ + Load an X.509 CRL from PEM encoded data. + """ + + @abc.abstractmethod + def load_der_x509_crl(self, data): + """ + Load an X.509 CRL from DER encoded data. + """ + class DHBackend(metaclass=abc.ABCMeta): @abc.abstractmethod @@ -384,3 +396,54 @@ def scrypt_supported(self): """ Return True if Scrypt is supported. """ + + +# This is the catch-all for future backend methods and inherits all the +# other interfaces as well so we can just use Backend for typing. +class Backend( + CipherBackend, + CMACBackend, + DERSerializationBackend, + DHBackend, + DSABackend, + EllipticCurveBackend, + HashBackend, + HMACBackend, + PBKDF2HMACBackend, + RSABackend, + PEMSerializationBackend, + ScryptBackend, + X509Backend, + metaclass=abc.ABCMeta, +): + @abc.abstractmethod + def load_pem_pkcs7_certificates(self, data): + """ + Returns a list of x509.Certificate + """ + + @abc.abstractmethod + def load_der_pkcs7_certificates(self, data): + """ + Returns a list of x509.Certificate + """ + + @abc.abstractmethod + def pkcs7_sign(self, builder, encoding, options): + """ + Returns bytes + """ + + @abc.abstractmethod + def load_key_and_certificates_from_pkcs12(self, data, password): + """ + Returns a tuple of (key, cert, [certs]) + """ + + @abc.abstractmethod + def serialize_key_and_certificates_to_pkcs12( + self, name, key, cert, cas, encryption_algorithm + ): + """ + Returns bytes + """ diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index fb0070386505..c87a466c9307 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -18,21 +18,7 @@ encode_der, encode_der_integer, ) -from cryptography.hazmat.backends.interfaces import ( - CMACBackend, - CipherBackend, - DERSerializationBackend, - DHBackend, - DSABackend, - EllipticCurveBackend, - HMACBackend, - HashBackend, - PBKDF2HMACBackend, - PEMSerializationBackend, - RSABackend, - ScryptBackend, - X509Backend, -) +from cryptography.hazmat.backends.interfaces import Backend as BackendInterface from cryptography.hazmat.backends.openssl import aead from cryptography.hazmat.backends.openssl.ciphers import _CipherContext from cryptography.hazmat.backends.openssl.cmac import _CMACContext @@ -161,21 +147,7 @@ class _RC2(object): pass -class Backend( - CipherBackend, - CMACBackend, - DERSerializationBackend, - DHBackend, - DSABackend, - EllipticCurveBackend, - HashBackend, - HMACBackend, - PBKDF2HMACBackend, - RSABackend, - PEMSerializationBackend, - ScryptBackend, - X509Backend, -): +class Backend(BackendInterface): """ OpenSSL API binding interfaces. """ diff --git a/src/cryptography/hazmat/primitives/asymmetric/dh.py b/src/cryptography/hazmat/primitives/asymmetric/dh.py index 6867f5365510..8f1d093e400f 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dh.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dh.py @@ -7,19 +7,22 @@ import typing from cryptography.hazmat.backends import _get_backend +from cryptography.hazmat.backends.interfaces import Backend from cryptography.hazmat.primitives import serialization _MIN_MODULUS_SIZE = 512 -def generate_parameters(generator, key_size, backend=None) -> "DHParameters": +def generate_parameters( + generator: int, key_size: int, backend: typing.Optional[Backend] = None +) -> "DHParameters": backend = _get_backend(backend) return backend.generate_dh_parameters(generator, key_size) class DHParameterNumbers(object): - def __init__(self, p: int, g: int, q: typing.Optional[int] = None): + def __init__(self, p: int, g: int, q: typing.Optional[int] = None) -> None: if not isinstance(p, int) or not isinstance(g, int): raise TypeError("p and g must be integers") if q is not None and not isinstance(q, int): @@ -48,7 +51,9 @@ def __eq__(self, other): def __ne__(self, other): return not self == other - def parameters(self, backend=None): + def parameters( + self, backend: typing.Optional[Backend] = None + ) -> "DHParameters": backend = _get_backend(backend) return backend.load_dh_parameter_numbers(self) @@ -58,7 +63,7 @@ def parameters(self, backend=None): class DHPublicNumbers(object): - def __init__(self, y, parameter_numbers: DHParameterNumbers): + def __init__(self, y: int, parameter_numbers: DHParameterNumbers) -> None: if not isinstance(y, int): raise TypeError("y must be an integer.") @@ -82,7 +87,9 @@ def __eq__(self, other): def __ne__(self, other): return not self == other - def public_key(self, backend=None) -> "DHPublicKey": + def public_key( + self, backend: typing.Optional[Backend] = None + ) -> "DHPublicKey": backend = _get_backend(backend) return backend.load_dh_public_numbers(self) @@ -91,7 +98,7 @@ def public_key(self, backend=None) -> "DHPublicKey": class DHPrivateNumbers(object): - def __init__(self, x, public_numbers: DHPublicNumbers): + def __init__(self, x: int, public_numbers: DHPublicNumbers) -> None: if not isinstance(x, int): raise TypeError("x must be an integer.") @@ -115,7 +122,9 @@ def __eq__(self, other): def __ne__(self, other): return not self == other - def private_key(self, backend=None) -> "DHPrivateKey": + def private_key( + self, backend: typing.Optional[Backend] = None + ) -> "DHPrivateKey": backend = _get_backend(backend) return backend.load_dh_private_numbers(self) diff --git a/src/cryptography/hazmat/primitives/asymmetric/dsa.py b/src/cryptography/hazmat/primitives/asymmetric/dsa.py index 7946c02a7c60..8587ecf09a9c 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dsa.py @@ -7,6 +7,7 @@ import typing from cryptography.hazmat.backends import _get_backend +from cryptography.hazmat.backends.interfaces import Backend from cryptography.hazmat.primitives import _serialization, hashes from cryptography.hazmat.primitives.asymmetric import ( AsymmetricSignatureContext, @@ -136,7 +137,7 @@ def verify( signature: bytes, data: bytes, algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], - ): + ) -> None: """ Verifies the signature of the data. """ @@ -164,7 +165,9 @@ def __init__(self, p: int, q: int, g: int): q = property(lambda self: self._q) g = property(lambda self: self._g) - def parameters(self, backend=None) -> DSAParameters: + def parameters( + self, backend: typing.Optional[Backend] = None + ) -> DSAParameters: backend = _get_backend(backend) return backend.load_dsa_parameter_numbers(self) @@ -200,7 +203,9 @@ def __init__(self, y: int, parameter_numbers: DSAParameterNumbers): y = property(lambda self: self._y) parameter_numbers = property(lambda self: self._parameter_numbers) - def public_key(self, backend=None) -> DSAPublicKey: + def public_key( + self, backend: typing.Optional[Backend] = None + ) -> DSAPublicKey: backend = _get_backend(backend) return backend.load_dsa_public_numbers(self) @@ -238,7 +243,9 @@ def __init__(self, x: int, public_numbers: DSAPublicNumbers): x = property(lambda self: self._x) public_numbers = property(lambda self: self._public_numbers) - def private_key(self, backend=None) -> DSAPrivateKey: + def private_key( + self, backend: typing.Optional[Backend] = None + ) -> DSAPrivateKey: backend = _get_backend(backend) return backend.load_dsa_private_numbers(self) @@ -254,17 +261,21 @@ def __ne__(self, other): return not self == other -def generate_parameters(key_size: int, backend=None) -> DSAParameters: +def generate_parameters( + key_size: int, backend: typing.Optional[Backend] = None +) -> DSAParameters: backend = _get_backend(backend) return backend.generate_dsa_parameters(key_size) -def generate_private_key(key_size: int, backend=None) -> DSAPrivateKey: +def generate_private_key( + key_size: int, backend: typing.Optional[Backend] = None +) -> DSAPrivateKey: backend = _get_backend(backend) return backend.generate_dsa_private_key_and_parameters(key_size) -def _check_dsa_parameters(parameters: DSAParameterNumbers): +def _check_dsa_parameters(parameters: DSAParameterNumbers) -> None: if parameters.p.bit_length() not in [1024, 2048, 3072, 4096]: raise ValueError( "p must be exactly 1024, 2048, 3072, or 4096 bits long" @@ -276,7 +287,7 @@ def _check_dsa_parameters(parameters: DSAParameterNumbers): raise ValueError("g, p don't satisfy 1 < g < p.") -def _check_dsa_private_numbers(numbers: DSAPrivateNumbers): +def _check_dsa_private_numbers(numbers: DSAPrivateNumbers) -> None: parameters = numbers.public_numbers.parameter_numbers _check_dsa_parameters(parameters) if numbers.x <= 0 or numbers.x >= parameters.q: diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index 41dc5b58079c..c5bc27968d93 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -10,6 +10,7 @@ from cryptography import utils from cryptography.hazmat._oid import ObjectIdentifier from cryptography.hazmat.backends import _get_backend +from cryptography.hazmat.backends.interfaces import Backend from cryptography.hazmat.primitives import _serialization, hashes from cryptography.hazmat.primitives.asymmetric import ( AsymmetricSignatureContext, @@ -104,7 +105,7 @@ def key_size(self) -> int: @abc.abstractmethod def sign( self, - data, + data: bytes, signature_algorithm: EllipticCurveSignatureAlgorithm, ) -> bytes: """ @@ -340,14 +341,16 @@ def algorithm( def generate_private_key( - curve: EllipticCurve, backend=None + curve: EllipticCurve, backend: typing.Optional[Backend] = None ) -> EllipticCurvePrivateKey: backend = _get_backend(backend) return backend.generate_elliptic_curve_private_key(curve) def derive_private_key( - private_value: int, curve: EllipticCurve, backend=None + private_value: int, + curve: EllipticCurve, + backend: typing.Optional[Backend] = None, ) -> EllipticCurvePrivateKey: backend = _get_backend(backend) if not isinstance(private_value, int): @@ -374,7 +377,9 @@ def __init__(self, x: int, y: int, curve: EllipticCurve): self._x = x self._curve = curve - def public_key(self, backend=None) -> EllipticCurvePublicKey: + def public_key( + self, backend: typing.Optional[Backend] = None + ) -> EllipticCurvePublicKey: backend = _get_backend(backend) return backend.load_elliptic_curve_public_numbers(self) @@ -466,7 +471,9 @@ def __init__( self._private_value = private_value self._public_numbers = public_numbers - def private_key(self, backend=None) -> EllipticCurvePrivateKey: + def private_key( + self, backend: typing.Optional[Backend] = None + ) -> EllipticCurvePrivateKey: backend = _get_backend(backend) return backend.load_elliptic_curve_private_numbers(self) diff --git a/src/cryptography/hazmat/primitives/asymmetric/ed25519.py b/src/cryptography/hazmat/primitives/asymmetric/ed25519.py index 8e649bf04a7e..43277028338a 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ed25519.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ed25519.py @@ -80,7 +80,7 @@ def private_bytes( encoding: _serialization.Encoding, format: _serialization.PrivateFormat, encryption_algorithm: _serialization.KeySerializationEncryption, - ): + ) -> bytes: """ The serialized bytes of the private key. """ diff --git a/src/cryptography/hazmat/primitives/asymmetric/ed448.py b/src/cryptography/hazmat/primitives/asymmetric/ed448.py index 41985462142c..27bc27c69f31 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ed448.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ed448.py @@ -33,7 +33,7 @@ def public_bytes( """ @abc.abstractmethod - def verify(self, signature: bytes, data: bytes): + def verify(self, signature: bytes, data: bytes) -> None: """ Verify the signature. """ @@ -81,7 +81,7 @@ def private_bytes( encoding: _serialization.Encoding, format: _serialization.PrivateFormat, encryption_algorithm: _serialization.KeySerializationEncryption, - ): + ) -> bytes: """ The serialized bytes of the private key. """ diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py index 106e464bc49a..35b0e86a4a71 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py @@ -9,7 +9,7 @@ from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.backends import _get_backend -from cryptography.hazmat.backends.interfaces import RSABackend +from cryptography.hazmat.backends.interfaces import Backend, RSABackend from cryptography.hazmat.primitives import _serialization, hashes from cryptography.hazmat.primitives._asymmetric import AsymmetricPadding from cryptography.hazmat.primitives.asymmetric import ( @@ -146,7 +146,9 @@ def recover_data_from_signature( def generate_private_key( - public_exponent: int, key_size: int, backend=None + public_exponent: int, + key_size: int, + backend: typing.Optional[Backend] = None, ) -> RSAPrivateKey: backend = _get_backend(backend) if not isinstance(backend, RSABackend): @@ -361,7 +363,9 @@ def __init__( iqmp = property(lambda self: self._iqmp) public_numbers = property(lambda self: self._public_numbers) - def private_key(self, backend=None) -> RSAPrivateKey: + def private_key( + self, backend: typing.Optional[Backend] = None + ) -> RSAPrivateKey: backend = _get_backend(backend) return backend.load_rsa_private_numbers(self) @@ -407,7 +411,9 @@ def __init__(self, e: int, n: int): e = property(lambda self: self._e) n = property(lambda self: self._n) - def public_key(self, backend=None) -> RSAPublicKey: + def public_key( + self, backend: typing.Optional[Backend] = None + ) -> RSAPublicKey: backend = _get_backend(backend) return backend.load_rsa_public_numbers(self) diff --git a/src/cryptography/hazmat/primitives/asymmetric/x448.py b/src/cryptography/hazmat/primitives/asymmetric/x448.py index 4282543d92bc..7f71c2722a67 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/x448.py +++ b/src/cryptography/hazmat/primitives/asymmetric/x448.py @@ -11,7 +11,7 @@ class X448PublicKey(metaclass=abc.ABCMeta): @classmethod - def from_public_bytes(cls, data) -> "X448PublicKey": + def from_public_bytes(cls, data: bytes) -> "X448PublicKey": from cryptography.hazmat.backends.openssl.backend import backend if not backend.x448_supported(): diff --git a/src/cryptography/hazmat/primitives/ciphers/aead.py b/src/cryptography/hazmat/primitives/ciphers/aead.py index 5c7cdc25b0ac..d47bb445cd2f 100644 --- a/src/cryptography/hazmat/primitives/ciphers/aead.py +++ b/src/cryptography/hazmat/primitives/ciphers/aead.py @@ -136,14 +136,16 @@ def decrypt( backend, self, nonce, data, associated_data, self._tag_length ) - def _validate_lengths(self, nonce: bytes, data_len: int): + def _validate_lengths(self, nonce: bytes, data_len: int) -> None: # For information about computing this, see # https://tools.ietf.org/html/rfc3610#section-2.1 l_val = 15 - len(nonce) if 2 ** (8 * l_val) < data_len: raise ValueError("Data too long for nonce") - def _check_params(self, nonce: bytes, data: bytes, associated_data: bytes): + def _check_params( + self, nonce: bytes, data: bytes, associated_data: bytes + ) -> None: utils._check_byteslike("nonce", nonce) utils._check_bytes("data", data) utils._check_bytes("associated_data", associated_data) diff --git a/src/cryptography/hazmat/primitives/ciphers/algorithms.py b/src/cryptography/hazmat/primitives/ciphers/algorithms.py index 2fafa8ead883..ba3c968e0241 100644 --- a/src/cryptography/hazmat/primitives/ciphers/algorithms.py +++ b/src/cryptography/hazmat/primitives/ciphers/algorithms.py @@ -11,7 +11,7 @@ from cryptography.hazmat.primitives.ciphers.modes import ModeWithNonce -def _verify_key_size(algorithm: CipherAlgorithm, key: bytes): +def _verify_key_size(algorithm: CipherAlgorithm, key: bytes) -> bytes: # Verify that the key is instance of bytes utils._check_byteslike("key", key) diff --git a/src/cryptography/hazmat/primitives/ciphers/base.py b/src/cryptography/hazmat/primitives/ciphers/base.py index 6f02597a725b..7261a275b42e 100644 --- a/src/cryptography/hazmat/primitives/ciphers/base.py +++ b/src/cryptography/hazmat/primitives/ciphers/base.py @@ -15,7 +15,7 @@ _Reasons, ) from cryptography.hazmat.backends import _get_backend -from cryptography.hazmat.backends.interfaces import CipherBackend +from cryptography.hazmat.backends.interfaces import Backend, CipherBackend from cryptography.hazmat.primitives._cipheralgorithm import CipherAlgorithm from cryptography.hazmat.primitives.ciphers import modes @@ -81,7 +81,7 @@ def __init__( self, algorithm: CipherAlgorithm, mode: typing.Optional[modes.Mode], - backend=None, + backend: typing.Optional[Backend] = None, ): backend = _get_backend(backend) if not isinstance(backend, CipherBackend): @@ -161,7 +161,7 @@ def __init__(self, ctx): self._tag = None self._updated = False - def _check_limit(self, data_size: int): + def _check_limit(self, data_size: int) -> None: if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") self._updated = True diff --git a/src/cryptography/hazmat/primitives/ciphers/modes.py b/src/cryptography/hazmat/primitives/ciphers/modes.py index ec14412e53c4..43ddc6d24678 100644 --- a/src/cryptography/hazmat/primitives/ciphers/modes.py +++ b/src/cryptography/hazmat/primitives/ciphers/modes.py @@ -73,7 +73,7 @@ def _check_iv_length(self, algorithm): ) -def _check_nonce_length(nonce: bytes, name: str, algorithm): +def _check_nonce_length(nonce: bytes, name: str, algorithm) -> None: if len(nonce) * 8 != algorithm.block_size: raise ValueError( "Invalid nonce size ({}) for {}.".format(len(nonce), name) @@ -114,7 +114,7 @@ def __init__(self, tweak: bytes): def tweak(self) -> bytes: return self._tweak - def validate_for_algorithm(self, algorithm: CipherAlgorithm): + def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: if algorithm.key_size not in (256, 512): raise ValueError( "The XTS specification requires a 256-bit key for AES-128-XTS" @@ -181,7 +181,7 @@ def __init__(self, nonce: bytes): def nonce(self) -> bytes: return self._nonce - def validate_for_algorithm(self, algorithm: CipherAlgorithm): + def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: _check_aes_key_length(self, algorithm) _check_nonce_length(self.nonce, self.name, algorithm) @@ -227,5 +227,5 @@ def tag(self) -> typing.Optional[bytes]: def initialization_vector(self) -> bytes: return self._initialization_vector - def validate_for_algorithm(self, algorithm: CipherAlgorithm): + def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: _check_aes_key_length(self, algorithm) diff --git a/src/cryptography/hazmat/primitives/cmac.py b/src/cryptography/hazmat/primitives/cmac.py index 1ebdb052c69d..d6dc7cff6e7b 100644 --- a/src/cryptography/hazmat/primitives/cmac.py +++ b/src/cryptography/hazmat/primitives/cmac.py @@ -3,6 +3,8 @@ # for complete details. +import typing + from cryptography import utils from cryptography.exceptions import ( AlreadyFinalized, @@ -10,13 +12,16 @@ _Reasons, ) from cryptography.hazmat.backends import _get_backend -from cryptography.hazmat.backends.interfaces import CMACBackend +from cryptography.hazmat.backends.interfaces import Backend, CMACBackend from cryptography.hazmat.primitives import ciphers class CMAC(object): def __init__( - self, algorithm: ciphers.BlockCipherAlgorithm, backend=None, ctx=None + self, + algorithm: ciphers.BlockCipherAlgorithm, + backend: typing.Optional[Backend] = None, + ctx=None, ): backend = _get_backend(backend) if not isinstance(backend, CMACBackend): diff --git a/src/cryptography/hazmat/primitives/hashes.py b/src/cryptography/hazmat/primitives/hashes.py index 6552fb95de68..898017692eed 100644 --- a/src/cryptography/hazmat/primitives/hashes.py +++ b/src/cryptography/hazmat/primitives/hashes.py @@ -12,7 +12,7 @@ _Reasons, ) from cryptography.hazmat.backends import _get_backend -from cryptography.hazmat.backends.interfaces import HashBackend +from cryptography.hazmat.backends.interfaces import Backend, HashBackend class HashAlgorithm(metaclass=abc.ABCMeta): @@ -69,7 +69,12 @@ class ExtendableOutputFunction(metaclass=abc.ABCMeta): class Hash(HashContext): - def __init__(self, algorithm: HashAlgorithm, backend=None, ctx=None): + def __init__( + self, + algorithm: HashAlgorithm, + backend: typing.Optional[Backend] = None, + ctx: typing.Optional["HashContext"] = None, + ): backend = _get_backend(backend) if not isinstance(backend, HashBackend): raise UnsupportedAlgorithm( diff --git a/src/cryptography/hazmat/primitives/hmac.py b/src/cryptography/hazmat/primitives/hmac.py index 927fb87bdf53..540d6a24bfd9 100644 --- a/src/cryptography/hazmat/primitives/hmac.py +++ b/src/cryptography/hazmat/primitives/hmac.py @@ -3,6 +3,8 @@ # for complete details. +import typing + from cryptography import utils from cryptography.exceptions import ( AlreadyFinalized, @@ -10,7 +12,7 @@ _Reasons, ) from cryptography.hazmat.backends import _get_backend -from cryptography.hazmat.backends.interfaces import HMACBackend +from cryptography.hazmat.backends.interfaces import Backend, HMACBackend from cryptography.hazmat.primitives import hashes @@ -19,7 +21,7 @@ def __init__( self, key: bytes, algorithm: hashes.HashAlgorithm, - backend=None, + backend: typing.Optional[Backend] = None, ctx=None, ): backend = _get_backend(backend) diff --git a/src/cryptography/hazmat/primitives/kdf/concatkdf.py b/src/cryptography/hazmat/primitives/kdf/concatkdf.py index 6ec4cbd372b4..be86388d4652 100644 --- a/src/cryptography/hazmat/primitives/kdf/concatkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/concatkdf.py @@ -14,8 +14,11 @@ _Reasons, ) from cryptography.hazmat.backends import _get_backend -from cryptography.hazmat.backends.interfaces import HMACBackend -from cryptography.hazmat.backends.interfaces import HashBackend +from cryptography.hazmat.backends.interfaces import ( + Backend, + HMACBackend, + HashBackend, +) from cryptography.hazmat.primitives import constant_time, hashes, hmac from cryptography.hazmat.primitives.kdf import KeyDerivationFunction @@ -28,7 +31,7 @@ def _common_args_checks( algorithm: hashes.HashAlgorithm, length: int, otherinfo: typing.Optional[bytes], -): +) -> None: max_length = algorithm.digest_size * (2 ** 32 - 1) if length > max_length: raise ValueError( @@ -67,7 +70,7 @@ def __init__( algorithm: hashes.HashAlgorithm, length: int, otherinfo: typing.Optional[bytes], - backend=None, + backend: typing.Optional[Backend] = None, ): backend = _get_backend(backend) @@ -107,7 +110,7 @@ def __init__( length: int, salt: typing.Optional[bytes], otherinfo: typing.Optional[bytes], - backend=None, + backend: typing.Optional[Backend] = None, ): backend = _get_backend(backend) diff --git a/src/cryptography/hazmat/primitives/kdf/hkdf.py b/src/cryptography/hazmat/primitives/kdf/hkdf.py index 6b65b0c0717b..9f5cd5bc2c7d 100644 --- a/src/cryptography/hazmat/primitives/kdf/hkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/hkdf.py @@ -13,7 +13,7 @@ _Reasons, ) from cryptography.hazmat.backends import _get_backend -from cryptography.hazmat.backends.interfaces import HMACBackend +from cryptography.hazmat.backends.interfaces import Backend, HMACBackend from cryptography.hazmat.primitives import constant_time, hashes, hmac from cryptography.hazmat.primitives.kdf import KeyDerivationFunction @@ -25,7 +25,7 @@ def __init__( length: int, salt: typing.Optional[bytes], info: typing.Optional[bytes], - backend=None, + backend: typing.Optional[Backend] = None, ): backend = _get_backend(backend) if not isinstance(backend, HMACBackend): @@ -67,7 +67,7 @@ def __init__( algorithm: hashes.HashAlgorithm, length: int, info: typing.Optional[bytes], - backend=None, + backend: typing.Optional[Backend] = None, ): backend = _get_backend(backend) if not isinstance(backend, HMACBackend): diff --git a/src/cryptography/hazmat/primitives/kdf/kbkdf.py b/src/cryptography/hazmat/primitives/kdf/kbkdf.py index ac36474fd7ae..eee2200be4bf 100644 --- a/src/cryptography/hazmat/primitives/kdf/kbkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/kbkdf.py @@ -14,7 +14,7 @@ _Reasons, ) from cryptography.hazmat.backends import _get_backend -from cryptography.hazmat.backends.interfaces import HMACBackend +from cryptography.hazmat.backends.interfaces import Backend, HMACBackend from cryptography.hazmat.primitives import constant_time, hashes, hmac from cryptography.hazmat.primitives.kdf import KeyDerivationFunction @@ -40,7 +40,7 @@ def __init__( label: typing.Optional[bytes], context: typing.Optional[bytes], fixed: typing.Optional[bytes], - backend=None, + backend: typing.Optional[Backend] = None, ): backend = _get_backend(backend) if not isinstance(backend, HMACBackend): diff --git a/src/cryptography/hazmat/primitives/kdf/pbkdf2.py b/src/cryptography/hazmat/primitives/kdf/pbkdf2.py index d1c10af53591..f68cef43affd 100644 --- a/src/cryptography/hazmat/primitives/kdf/pbkdf2.py +++ b/src/cryptography/hazmat/primitives/kdf/pbkdf2.py @@ -3,6 +3,8 @@ # for complete details. +import typing + from cryptography import utils from cryptography.exceptions import ( AlreadyFinalized, @@ -11,7 +13,7 @@ _Reasons, ) from cryptography.hazmat.backends import _get_backend -from cryptography.hazmat.backends.interfaces import PBKDF2HMACBackend +from cryptography.hazmat.backends.interfaces import Backend, PBKDF2HMACBackend from cryptography.hazmat.primitives import constant_time, hashes from cryptography.hazmat.primitives.kdf import KeyDerivationFunction @@ -23,7 +25,7 @@ def __init__( length: int, salt: bytes, iterations: int, - backend=None, + backend: typing.Optional[Backend] = None, ): backend = _get_backend(backend) if not isinstance(backend, PBKDF2HMACBackend): diff --git a/src/cryptography/hazmat/primitives/kdf/scrypt.py b/src/cryptography/hazmat/primitives/kdf/scrypt.py index 7547dca5c095..9c3a9187da99 100644 --- a/src/cryptography/hazmat/primitives/kdf/scrypt.py +++ b/src/cryptography/hazmat/primitives/kdf/scrypt.py @@ -4,6 +4,7 @@ import sys +import typing from cryptography import utils from cryptography.exceptions import ( @@ -13,7 +14,7 @@ _Reasons, ) from cryptography.hazmat.backends import _get_backend -from cryptography.hazmat.backends.interfaces import ScryptBackend +from cryptography.hazmat.backends.interfaces import Backend, ScryptBackend from cryptography.hazmat.primitives import constant_time from cryptography.hazmat.primitives.kdf import KeyDerivationFunction @@ -25,7 +26,13 @@ class Scrypt(KeyDerivationFunction): def __init__( - self, salt: bytes, length: int, n: int, r: int, p: int, backend=None + self, + salt: bytes, + length: int, + n: int, + r: int, + p: int, + backend: typing.Optional[Backend] = None, ): backend = _get_backend(backend) if not isinstance(backend, ScryptBackend): diff --git a/src/cryptography/hazmat/primitives/kdf/x963kdf.py b/src/cryptography/hazmat/primitives/kdf/x963kdf.py index 1a67d3ee0c4f..d575d86adf12 100644 --- a/src/cryptography/hazmat/primitives/kdf/x963kdf.py +++ b/src/cryptography/hazmat/primitives/kdf/x963kdf.py @@ -14,7 +14,7 @@ _Reasons, ) from cryptography.hazmat.backends import _get_backend -from cryptography.hazmat.backends.interfaces import HashBackend +from cryptography.hazmat.backends.interfaces import Backend, HashBackend from cryptography.hazmat.primitives import constant_time, hashes from cryptography.hazmat.primitives.kdf import KeyDerivationFunction @@ -29,7 +29,7 @@ def __init__( algorithm: hashes.HashAlgorithm, length: int, sharedinfo: typing.Optional[bytes], - backend=None, + backend: typing.Optional[Backend] = None, ): backend = _get_backend(backend) diff --git a/src/cryptography/hazmat/primitives/keywrap.py b/src/cryptography/hazmat/primitives/keywrap.py index 52d49d35f2eb..b8de85dd434a 100644 --- a/src/cryptography/hazmat/primitives/keywrap.py +++ b/src/cryptography/hazmat/primitives/keywrap.py @@ -7,6 +7,7 @@ import typing from cryptography.hazmat.backends import _get_backend +from cryptography.hazmat.backends.interfaces import Backend from cryptography.hazmat.primitives.ciphers import Cipher from cryptography.hazmat.primitives.ciphers.algorithms import AES from cryptography.hazmat.primitives.ciphers.modes import ECB @@ -14,7 +15,10 @@ def _wrap_core( - wrapping_key: bytes, a: bytes, r: typing.List[bytes], backend + wrapping_key: bytes, + a: bytes, + r: typing.List[bytes], + backend: Backend, ) -> bytes: # RFC 3394 Key Wrap - 2.2.1 (index method) encryptor = Cipher(AES(wrapping_key), ECB(), backend).encryptor() @@ -37,7 +41,9 @@ def _wrap_core( def aes_key_wrap( - wrapping_key: bytes, key_to_wrap: bytes, backend=None + wrapping_key: bytes, + key_to_wrap: bytes, + backend: typing.Optional[Backend] = None, ) -> bytes: backend = _get_backend(backend) if len(wrapping_key) not in [16, 24, 32]: @@ -55,7 +61,10 @@ def aes_key_wrap( def _unwrap_core( - wrapping_key: bytes, a: bytes, r: typing.List[bytes], backend + wrapping_key: bytes, + a: bytes, + r: typing.List[bytes], + backend: Backend, ) -> typing.Tuple[bytes, typing.List[bytes]]: # Implement RFC 3394 Key Unwrap - 2.2.2 (index method) decryptor = Cipher(AES(wrapping_key), ECB(), backend).decryptor() @@ -80,7 +89,9 @@ def _unwrap_core( def aes_key_wrap_with_padding( - wrapping_key: bytes, key_to_wrap: bytes, backend=None + wrapping_key: bytes, + key_to_wrap: bytes, + backend: typing.Optional[Backend] = None, ) -> bytes: backend = _get_backend(backend) if len(wrapping_key) not in [16, 24, 32]: @@ -102,7 +113,9 @@ def aes_key_wrap_with_padding( def aes_key_unwrap_with_padding( - wrapping_key: bytes, wrapped_key: bytes, backend=None + wrapping_key: bytes, + wrapped_key: bytes, + backend: typing.Optional[Backend] = None, ) -> bytes: backend = _get_backend(backend) if len(wrapped_key) < 16: @@ -147,7 +160,9 @@ def aes_key_unwrap_with_padding( def aes_key_unwrap( - wrapping_key: bytes, wrapped_key: bytes, backend=None + wrapping_key: bytes, + wrapped_key: bytes, + backend: typing.Optional[Backend] = None, ) -> bytes: backend = _get_backend(backend) if len(wrapped_key) < 24: diff --git a/src/cryptography/hazmat/primitives/serialization/base.py b/src/cryptography/hazmat/primitives/serialization/base.py index 9f7531db2f7a..30679c87ef0c 100644 --- a/src/cryptography/hazmat/primitives/serialization/base.py +++ b/src/cryptography/hazmat/primitives/serialization/base.py @@ -10,38 +10,51 @@ _PUBLIC_KEY_TYPES, ) from cryptography.hazmat.backends import _get_backend +from cryptography.hazmat.backends.interfaces import Backend from cryptography.hazmat.primitives.asymmetric import dh def load_pem_private_key( - data: bytes, password: typing.Optional[bytes], backend=None + data: bytes, + password: typing.Optional[bytes], + backend: typing.Optional[Backend] = None, ) -> _PRIVATE_KEY_TYPES: backend = _get_backend(backend) return backend.load_pem_private_key(data, password) -def load_pem_public_key(data: bytes, backend=None) -> _PUBLIC_KEY_TYPES: +def load_pem_public_key( + data: bytes, backend: typing.Optional[Backend] = None +) -> _PUBLIC_KEY_TYPES: backend = _get_backend(backend) return backend.load_pem_public_key(data) -def load_pem_parameters(data: bytes, backend=None) -> "dh.DHParameters": +def load_pem_parameters( + data: bytes, backend: typing.Optional[Backend] = None +) -> "dh.DHParameters": backend = _get_backend(backend) return backend.load_pem_parameters(data) def load_der_private_key( - data: bytes, password: typing.Optional[bytes], backend=None + data: bytes, + password: typing.Optional[bytes], + backend: typing.Optional[Backend] = None, ) -> _PRIVATE_KEY_TYPES: backend = _get_backend(backend) return backend.load_der_private_key(data, password) -def load_der_public_key(data: bytes, backend=None) -> _PUBLIC_KEY_TYPES: +def load_der_public_key( + data: bytes, backend: typing.Optional[Backend] = None +) -> _PUBLIC_KEY_TYPES: backend = _get_backend(backend) return backend.load_der_public_key(data) -def load_der_parameters(data: bytes, backend=None) -> "dh.DHParameters": +def load_der_parameters( + data: bytes, backend: typing.Optional[Backend] = None +) -> "dh.DHParameters": backend = _get_backend(backend) return backend.load_der_parameters(data) diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs12.py b/src/cryptography/hazmat/primitives/serialization/pkcs12.py index 1dabfca5534a..215f601279aa 100644 --- a/src/cryptography/hazmat/primitives/serialization/pkcs12.py +++ b/src/cryptography/hazmat/primitives/serialization/pkcs12.py @@ -6,6 +6,7 @@ from cryptography import x509 from cryptography.hazmat.backends import _get_backend +from cryptography.hazmat.backends.interfaces import Backend from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa @@ -18,7 +19,9 @@ def load_key_and_certificates( - data: bytes, password: typing.Optional[bytes], backend=None + data: bytes, + password: typing.Optional[bytes], + backend: typing.Optional[Backend] = None, ) -> typing.Tuple[ typing.Optional[_ALLOWED_PKCS12_TYPES], typing.Optional[x509.Certificate], diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs7.py b/src/cryptography/hazmat/primitives/serialization/pkcs7.py index bcd9e330d58d..c6b2eec21092 100644 --- a/src/cryptography/hazmat/primitives/serialization/pkcs7.py +++ b/src/cryptography/hazmat/primitives/serialization/pkcs7.py @@ -7,6 +7,7 @@ from cryptography import x509 from cryptography.hazmat.backends import _get_backend +from cryptography.hazmat.backends.interfaces import Backend from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ec, rsa from cryptography.utils import _check_byteslike @@ -104,7 +105,7 @@ def sign( self, encoding: serialization.Encoding, options: typing.Iterable[PKCS7Options], - backend=None, + backend: typing.Optional[Backend] = None, ) -> bytes: if len(self._signers) == 0: raise ValueError("Must have at least one signer") diff --git a/src/cryptography/hazmat/primitives/serialization/ssh.py b/src/cryptography/hazmat/primitives/serialization/ssh.py index f276c1e84a2d..b36065dc7518 100644 --- a/src/cryptography/hazmat/primitives/serialization/ssh.py +++ b/src/cryptography/hazmat/primitives/serialization/ssh.py @@ -13,6 +13,7 @@ from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.backends import _get_backend +from cryptography.hazmat.backends.interfaces import Backend from cryptography.hazmat.primitives.asymmetric import dsa, ec, ed25519, rsa from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives.serialization import ( @@ -474,7 +475,9 @@ def _lookup_kformat(key_type): def load_ssh_private_key( - data: bytes, password: typing.Optional[bytes], backend=None + data: bytes, + password: typing.Optional[bytes], + backend: typing.Optional[Backend] = None, ) -> _SSH_PRIVATE_KEY_TYPES: """Load private key from OpenSSH custom encoding.""" utils._check_byteslike("data", data) @@ -552,7 +555,7 @@ def load_ssh_private_key( def serialize_ssh_private_key( private_key: _SSH_PRIVATE_KEY_TYPES, password: typing.Optional[bytes] = None, -): +) -> bytes: """Serialize private key with OpenSSH custom encoding.""" if password is not None: utils._check_bytes("password", password) @@ -584,7 +587,7 @@ def serialize_ssh_private_key( salt = os.urandom(16) f_kdfoptions.put_sshstr(salt) f_kdfoptions.put_u32(rounds) - backend = _get_backend(None) + backend: Backend = _get_backend(None) ciph = _init_cipher(ciphername, password, salt, rounds, backend) else: ciphername = kdfname = _NONE @@ -642,7 +645,9 @@ def serialize_ssh_private_key( ] -def load_ssh_public_key(data: bytes, backend=None) -> _SSH_PUBLIC_KEY_TYPES: +def load_ssh_public_key( + data: bytes, backend: typing.Optional[Backend] = None +) -> _SSH_PUBLIC_KEY_TYPES: """Load public key from OpenSSH one-line format.""" backend = _get_backend(backend) utils._check_byteslike("data", data) diff --git a/src/cryptography/hazmat/primitives/twofactor/hotp.py b/src/cryptography/hazmat/primitives/twofactor/hotp.py index 26e786fd4c37..b4b2b41d0ad9 100644 --- a/src/cryptography/hazmat/primitives/twofactor/hotp.py +++ b/src/cryptography/hazmat/primitives/twofactor/hotp.py @@ -10,7 +10,7 @@ from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.backends import _get_backend -from cryptography.hazmat.backends.interfaces import HMACBackend +from cryptography.hazmat.backends.interfaces import Backend, HMACBackend from cryptography.hazmat.primitives import constant_time, hmac from cryptography.hazmat.primitives.hashes import SHA1, SHA256, SHA512 from cryptography.hazmat.primitives.twofactor import InvalidToken @@ -24,7 +24,7 @@ def _generate_uri( type_name: str, account_name: str, issuer: typing.Optional[str], - extra_parameters, + extra_parameters: typing.List[typing.Tuple[str, int]], ) -> str: parameters = [ ("digits", hotp._length), @@ -55,9 +55,9 @@ def __init__( key: bytes, length: int, algorithm: _ALLOWED_HASH_TYPES, - backend=None, + backend: typing.Optional[Backend] = None, enforce_key_length: bool = True, - ): + ) -> None: backend = _get_backend(backend) if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( diff --git a/src/cryptography/hazmat/primitives/twofactor/totp.py b/src/cryptography/hazmat/primitives/twofactor/totp.py index 92bf6496867d..a88008209bf2 100644 --- a/src/cryptography/hazmat/primitives/twofactor/totp.py +++ b/src/cryptography/hazmat/primitives/twofactor/totp.py @@ -6,7 +6,7 @@ from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.backends import _get_backend -from cryptography.hazmat.backends.interfaces import HMACBackend +from cryptography.hazmat.backends.interfaces import Backend, HMACBackend from cryptography.hazmat.primitives import constant_time from cryptography.hazmat.primitives.twofactor import InvalidToken from cryptography.hazmat.primitives.twofactor.hotp import ( @@ -23,7 +23,7 @@ def __init__( length: int, algorithm: _ALLOWED_HASH_TYPES, time_step: int, - backend=None, + backend: typing.Optional[Backend] = None, enforce_key_length: bool = True, ): backend = _get_backend(backend) diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index e0abd4a8ab6c..a8fd7d01a7c9 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -24,12 +24,12 @@ class CryptographyDeprecationWarning(UserWarning): DeprecatedIn34 = CryptographyDeprecationWarning -def _check_bytes(name: str, value: bytes): +def _check_bytes(name: str, value: bytes) -> None: if not isinstance(value, bytes): raise TypeError("{} must be bytes".format(name)) -def _check_byteslike(name: str, value: bytes): +def _check_byteslike(name: str, value: bytes) -> None: try: memoryview(value) except TypeError: diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index 5505fa3b6d5e..1e98b469c1bb 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -11,6 +11,7 @@ from cryptography.hazmat._types import _PRIVATE_KEY_TYPES, _PUBLIC_KEY_TYPES from cryptography.hazmat.backends import _get_backend +from cryptography.hazmat.backends.interfaces import Backend from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ( dsa, @@ -35,7 +36,7 @@ def __init__(self, msg, oid): def _reject_duplicate_extension( extension: Extension, extensions: typing.List[Extension] -): +) -> None: # This is quadratic in the number of extensions for e in extensions: if e.oid == extension.oid: @@ -45,7 +46,7 @@ def _reject_duplicate_extension( def _reject_duplicate_attribute( oid: ObjectIdentifier, attributes: typing.List[typing.Tuple[ObjectIdentifier, bytes]], -): +) -> None: # This is quadratic in the number of attributes for attr_oid, _ in attributes: if attr_oid == oid: @@ -394,32 +395,44 @@ def get_attribute_for_oid(self, oid: ObjectIdentifier) -> bytes: """ -def load_pem_x509_certificate(data: bytes, backend=None) -> Certificate: +def load_pem_x509_certificate( + data: bytes, backend: typing.Optional[Backend] = None +) -> Certificate: backend = _get_backend(backend) return backend.load_pem_x509_certificate(data) -def load_der_x509_certificate(data: bytes, backend=None) -> Certificate: +def load_der_x509_certificate( + data: bytes, backend: typing.Optional[Backend] = None +) -> Certificate: backend = _get_backend(backend) return backend.load_der_x509_certificate(data) -def load_pem_x509_csr(data: bytes, backend=None) -> CertificateSigningRequest: +def load_pem_x509_csr( + data: bytes, backend: typing.Optional[Backend] = None +) -> CertificateSigningRequest: backend = _get_backend(backend) return backend.load_pem_x509_csr(data) -def load_der_x509_csr(data: bytes, backend=None) -> CertificateSigningRequest: +def load_der_x509_csr( + data: bytes, backend: typing.Optional[Backend] = None +) -> CertificateSigningRequest: backend = _get_backend(backend) return backend.load_der_x509_csr(data) -def load_pem_x509_crl(data: bytes, backend=None) -> CertificateRevocationList: +def load_pem_x509_crl( + data: bytes, backend: typing.Optional[Backend] = None +) -> CertificateRevocationList: backend = _get_backend(backend) return backend.load_pem_x509_crl(data) -def load_der_x509_crl(data: bytes, backend=None) -> CertificateRevocationList: +def load_der_x509_crl( + data: bytes, backend: typing.Optional[Backend] = None +) -> CertificateRevocationList: backend = _get_backend(backend) return backend.load_der_x509_crl(data) @@ -433,7 +446,7 @@ def __init__(self, subject_name=None, extensions=[], attributes=[]): self._extensions = extensions self._attributes = attributes - def subject_name(self, name: Name): + def subject_name(self, name: Name) -> "CertificateSigningRequestBuilder": """ Sets the certificate requestor's distinguished name. """ @@ -445,7 +458,9 @@ def subject_name(self, name: Name): name, self._extensions, self._attributes ) - def add_extension(self, extval: ExtensionType, critical: bool): + def add_extension( + self, extval: ExtensionType, critical: bool + ) -> "CertificateSigningRequestBuilder": """ Adds an X.509 extension to the certificate request. """ @@ -461,7 +476,9 @@ def add_extension(self, extval: ExtensionType, critical: bool): self._attributes, ) - def add_attribute(self, oid: ObjectIdentifier, value: bytes): + def add_attribute( + self, oid: ObjectIdentifier, value: bytes + ) -> "CertificateSigningRequestBuilder": """ Adds an X.509 attribute with an OID and associated value. """ @@ -482,8 +499,8 @@ def add_attribute(self, oid: ObjectIdentifier, value: bytes): def sign( self, private_key: _PRIVATE_KEY_TYPES, - algorithm: hashes.HashAlgorithm, - backend=None, + algorithm: typing.Optional[hashes.HashAlgorithm], + backend: typing.Optional[Backend] = None, ) -> CertificateSigningRequest: """ Signs the request using the requestor's private key. @@ -504,7 +521,7 @@ def __init__( not_valid_before=None, not_valid_after=None, extensions=[], - ): + ) -> None: self._version = Version.v3 self._issuer_name = issuer_name self._subject_name = subject_name @@ -514,7 +531,7 @@ def __init__( self._not_valid_after = not_valid_after self._extensions = extensions - def issuer_name(self, name: Name): + def issuer_name(self, name: Name) -> "CertificateBuilder": """ Sets the CA's distinguished name. """ @@ -532,7 +549,7 @@ def issuer_name(self, name: Name): self._extensions, ) - def subject_name(self, name: Name): + def subject_name(self, name: Name) -> "CertificateBuilder": """ Sets the requestor's distinguished name. """ @@ -553,7 +570,7 @@ def subject_name(self, name: Name): def public_key( self, key: _PUBLIC_KEY_TYPES, - ): + ) -> "CertificateBuilder": """ Sets the requestor's public key (as found in the signing request). """ @@ -584,7 +601,7 @@ def public_key( self._extensions, ) - def serial_number(self, number: int): + def serial_number(self, number: int) -> "CertificateBuilder": """ Sets the certificate serial number. """ @@ -611,7 +628,9 @@ def serial_number(self, number: int): self._extensions, ) - def not_valid_before(self, time: datetime.datetime): + def not_valid_before( + self, time: datetime.datetime + ) -> "CertificateBuilder": """ Sets the certificate activation time. """ @@ -640,7 +659,7 @@ def not_valid_before(self, time: datetime.datetime): self._extensions, ) - def not_valid_after(self, time: datetime.datetime): + def not_valid_after(self, time: datetime.datetime) -> "CertificateBuilder": """ Sets the certificate expiration time. """ @@ -672,7 +691,9 @@ def not_valid_after(self, time: datetime.datetime): self._extensions, ) - def add_extension(self, extval: ExtensionType, critical: bool): + def add_extension( + self, extval: ExtensionType, critical: bool + ) -> "CertificateBuilder": """ Adds an X.509 extension to the certificate. """ @@ -695,8 +716,8 @@ def add_extension(self, extval: ExtensionType, critical: bool): def sign( self, private_key: _PRIVATE_KEY_TYPES, - algorithm: hashes.HashAlgorithm, - backend=None, + algorithm: typing.Optional[hashes.HashAlgorithm], + backend: typing.Optional[Backend] = None, ) -> Certificate: """ Signs the certificate using the CA's private key. @@ -738,7 +759,9 @@ def __init__( self._extensions = extensions self._revoked_certificates = revoked_certificates - def issuer_name(self, issuer_name: Name): + def issuer_name( + self, issuer_name: Name + ) -> "CertificateRevocationListBuilder": if not isinstance(issuer_name, Name): raise TypeError("Expecting x509.Name object.") if self._issuer_name is not None: @@ -751,7 +774,9 @@ def issuer_name(self, issuer_name: Name): self._revoked_certificates, ) - def last_update(self, last_update: datetime.datetime): + def last_update( + self, last_update: datetime.datetime + ) -> "CertificateRevocationListBuilder": if not isinstance(last_update, datetime.datetime): raise TypeError("Expecting datetime object.") if self._last_update is not None: @@ -773,7 +798,9 @@ def last_update(self, last_update: datetime.datetime): self._revoked_certificates, ) - def next_update(self, next_update: datetime.datetime): + def next_update( + self, next_update: datetime.datetime + ) -> "CertificateRevocationListBuilder": if not isinstance(next_update, datetime.datetime): raise TypeError("Expecting datetime object.") if self._next_update is not None: @@ -795,7 +822,9 @@ def next_update(self, next_update: datetime.datetime): self._revoked_certificates, ) - def add_extension(self, extval: ExtensionType, critical: bool): + def add_extension( + self, extval: ExtensionType, critical: bool + ) -> "CertificateRevocationListBuilder": """ Adds an X.509 extension to the certificate revocation list. """ @@ -812,7 +841,9 @@ def add_extension(self, extval: ExtensionType, critical: bool): self._revoked_certificates, ) - def add_revoked_certificate(self, revoked_certificate: RevokedCertificate): + def add_revoked_certificate( + self, revoked_certificate: RevokedCertificate + ) -> "CertificateRevocationListBuilder": """ Adds a revoked certificate to the CRL. """ @@ -830,8 +861,8 @@ def add_revoked_certificate(self, revoked_certificate: RevokedCertificate): def sign( self, private_key: _PRIVATE_KEY_TYPES, - algorithm: hashes.HashAlgorithm, - backend=None, + algorithm: typing.Optional[hashes.HashAlgorithm], + backend: typing.Optional[Backend] = None, ) -> CertificateRevocationList: backend = _get_backend(backend) if self._issuer_name is None: @@ -854,7 +885,7 @@ def __init__( self._revocation_date = revocation_date self._extensions = extensions - def serial_number(self, number: int): + def serial_number(self, number: int) -> "RevokedCertificateBuilder": if not isinstance(number, int): raise TypeError("Serial number must be of integral type.") if self._serial_number is not None: @@ -872,7 +903,9 @@ def serial_number(self, number: int): number, self._revocation_date, self._extensions ) - def revocation_date(self, time: datetime.datetime): + def revocation_date( + self, time: datetime.datetime + ) -> "RevokedCertificateBuilder": if not isinstance(time, datetime.datetime): raise TypeError("Expecting datetime object.") if self._revocation_date is not None: @@ -886,7 +919,9 @@ def revocation_date(self, time: datetime.datetime): self._serial_number, time, self._extensions ) - def add_extension(self, extval: ExtensionType, critical: bool): + def add_extension( + self, extval: ExtensionType, critical: bool + ) -> "RevokedCertificateBuilder": if not isinstance(extval, ExtensionType): raise TypeError("extension must be an ExtensionType") @@ -898,7 +933,9 @@ def add_extension(self, extval: ExtensionType, critical: bool): self._extensions + [extension], ) - def build(self, backend=None) -> RevokedCertificate: + def build( + self, backend: typing.Optional[Backend] = None + ) -> RevokedCertificate: backend = _get_backend(backend) if self._serial_number is None: raise ValueError("A revoked certificate must have a serial number") diff --git a/src/cryptography/x509/name.py b/src/cryptography/x509/name.py index 5c171ad615c1..5f0b88e1794d 100644 --- a/src/cryptography/x509/name.py +++ b/src/cryptography/x509/name.py @@ -6,6 +6,7 @@ from enum import Enum from cryptography.hazmat.backends import _get_backend +from cryptography.hazmat.backends.interfaces import Backend from cryptography.x509.oid import NameOID, ObjectIdentifier @@ -233,7 +234,7 @@ def get_attributes_for_oid( def rdns(self) -> typing.List[RelativeDistinguishedName]: return self._attributes - def public_bytes(self, backend=None) -> bytes: + def public_bytes(self, backend: typing.Optional[Backend] = None) -> bytes: backend = _get_backend(backend) return backend.x509_name_bytes(self) diff --git a/tests/hazmat/backends/test_no_backend.py b/tests/hazmat/backends/test_no_backend.py index 9c01d1368227..282238d70843 100644 --- a/tests/hazmat/backends/test_no_backend.py +++ b/tests/hazmat/backends/test_no_backend.py @@ -12,4 +12,4 @@ def test_get_backend_no_backend(): def test_get_backend(): faux_backend = object() - assert _get_backend(faux_backend) is faux_backend + assert _get_backend(faux_backend) is faux_backend # type: ignore[arg-type] diff --git a/tests/hazmat/primitives/test_ciphers.py b/tests/hazmat/primitives/test_ciphers.py index f00282eccdeb..99aa4af3f919 100644 --- a/tests/hazmat/primitives/test_ciphers.py +++ b/tests/hazmat/primitives/test_ciphers.py @@ -202,7 +202,11 @@ def test_invalid_backend(): pretend_backend = object() with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE): - ciphers.Cipher(AES(b"AAAAAAAAAAAAAAAA"), modes.ECB(), pretend_backend) + ciphers.Cipher( + AES(b"AAAAAAAAAAAAAAAA"), + modes.ECB(), + pretend_backend, # type: ignore[arg-type] + ) @pytest.mark.supported( diff --git a/tests/hazmat/primitives/test_cmac.py b/tests/hazmat/primitives/test_cmac.py index 1c8841ac849e..1d6892540e47 100644 --- a/tests/hazmat/primitives/test_cmac.py +++ b/tests/hazmat/primitives/test_cmac.py @@ -217,4 +217,4 @@ def test_invalid_backend(): pretend_backend = object() with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE): - CMAC(AES(key), pretend_backend) + CMAC(AES(key), pretend_backend) # type: ignore[arg-type] diff --git a/tests/hazmat/primitives/test_concatkdf.py b/tests/hazmat/primitives/test_concatkdf.py index 18134eecac06..5da47ecc4e0a 100644 --- a/tests/hazmat/primitives/test_concatkdf.py +++ b/tests/hazmat/primitives/test_concatkdf.py @@ -298,6 +298,17 @@ def test_invalid_backend(): pretend_backend = object() with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE): - ConcatKDFHash(hashes.SHA256(), 16, None, pretend_backend) + ConcatKDFHash( + hashes.SHA256(), + 16, + None, + pretend_backend, # type: ignore[arg-type] + ) with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE): - ConcatKDFHMAC(hashes.SHA256(), 16, None, None, pretend_backend) + ConcatKDFHMAC( + hashes.SHA256(), + 16, + None, + None, + pretend_backend, # type: ignore[arg-type] + ) diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index b37eca4eba54..17d3a776e7a3 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -82,7 +82,7 @@ def test_dh_numbers(): dh.DHPublicNumbers(1, None) # type: ignore[arg-type] with pytest.raises(TypeError): - dh.DHPublicNumbers(None, params) + dh.DHPublicNumbers(None, params) # type:ignore[arg-type] private = dh.DHPrivateNumbers(1, public) @@ -93,7 +93,7 @@ def test_dh_numbers(): dh.DHPrivateNumbers(1, None) # type: ignore[arg-type] with pytest.raises(TypeError): - dh.DHPrivateNumbers(None, public) + dh.DHPrivateNumbers(None, public) # type:ignore[arg-type] def test_dh_parameter_numbers_equality(): @@ -585,7 +585,7 @@ def test_private_bytes_invalid_encoding(self, backend): key = parameters.generate_private_key() with pytest.raises(TypeError): key.private_bytes( - "notencoding", + "notencoding", # type:ignore[arg-type] serialization.PrivateFormat.PKCS8, serialization.NoEncryption(), ) @@ -596,7 +596,7 @@ def test_private_bytes_invalid_format(self, backend): with pytest.raises(ValueError): key.private_bytes( serialization.Encoding.PEM, - "invalidformat", + "invalidformat", # type:ignore[arg-type] serialization.NoEncryption(), ) @@ -607,7 +607,7 @@ def test_private_bytes_invalid_encryption_algorithm(self, backend): key.private_bytes( serialization.Encoding.PEM, serialization.PrivateFormat.PKCS8, - "notanencalg", + "notanencalg", # type:ignore[arg-type] ) def test_private_bytes_unsupported_encryption_type(self, backend): @@ -735,7 +735,8 @@ def test_public_bytes_invalid_encoding(self, backend): key = parameters.generate_private_key().public_key() with pytest.raises(TypeError): key.public_bytes( - "notencoding", serialization.PublicFormat.SubjectPublicKeyInfo + "notencoding", # type:ignore[arg-type] + serialization.PublicFormat.SubjectPublicKeyInfo, ) def test_public_bytes_pkcs1_unsupported(self, backend): @@ -888,13 +889,17 @@ def test_parameter_bytes_invalid_encoding(self, backend): parameters = FFDH3072_P.parameters(backend) with pytest.raises(TypeError): parameters.parameter_bytes( - "notencoding", serialization.ParameterFormat.PKCS3 + "notencoding", # type:ignore[arg-type] + serialization.ParameterFormat.PKCS3, ) def test_parameter_bytes_invalid_format(self, backend): parameters = FFDH3072_P.parameters(backend) with pytest.raises(ValueError): - parameters.parameter_bytes(serialization.Encoding.PEM, "notformat") + parameters.parameter_bytes( + serialization.Encoding.PEM, + "notformat", # type: ignore[arg-type] + ) def test_parameter_bytes_openssh_unsupported(self, backend): parameters = FFDH3072_P.parameters(backend) diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py index 67de7947bb25..e433d9c01900 100644 --- a/tests/hazmat/primitives/test_hashes.py +++ b/tests/hazmat/primitives/test_hashes.py @@ -159,7 +159,7 @@ def test_invalid_backend(): pretend_backend = object() with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE): - hashes.Hash(hashes.SHA1(), pretend_backend) + hashes.Hash(hashes.SHA1(), pretend_backend) # type:ignore[arg-type] def test_buffer_protocol_hash(backend): diff --git a/tests/hazmat/primitives/test_hkdf.py b/tests/hazmat/primitives/test_hkdf.py index 80b27b9a9150..e5218723c96d 100644 --- a/tests/hazmat/primitives/test_hkdf.py +++ b/tests/hazmat/primitives/test_hkdf.py @@ -217,7 +217,15 @@ def test_invalid_backend(): pretend_backend = object() with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE): - HKDF(hashes.SHA256(), 16, None, None, pretend_backend) + HKDF( + hashes.SHA256(), + 16, + None, + None, + pretend_backend, # type:ignore[arg-type] + ) with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE): - HKDFExpand(hashes.SHA256(), 16, None, pretend_backend) + HKDFExpand( + hashes.SHA256(), 16, None, pretend_backend # type:ignore[arg-type] + ) diff --git a/tests/hazmat/primitives/test_hmac.py b/tests/hazmat/primitives/test_hmac.py index 1cbd39c10538..44dd94e05aed 100644 --- a/tests/hazmat/primitives/test_hmac.py +++ b/tests/hazmat/primitives/test_hmac.py @@ -94,4 +94,6 @@ def test_invalid_backend(): pretend_backend = object() with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE): - hmac.HMAC(b"key", hashes.SHA1(), pretend_backend) + hmac.HMAC( + b"key", hashes.SHA1(), pretend_backend # type:ignore[arg-type] + ) diff --git a/tests/hazmat/primitives/test_kbkdf.py b/tests/hazmat/primitives/test_kbkdf.py index ddbf953b1323..ae9330807140 100644 --- a/tests/hazmat/primitives/test_kbkdf.py +++ b/tests/hazmat/primitives/test_kbkdf.py @@ -268,7 +268,7 @@ def test_invalid_backend(self, backend): b"label", b"context", None, - backend=object(), + backend=object(), # type: ignore[arg-type] ) def test_unicode_error_label(self, backend): diff --git a/tests/hazmat/primitives/test_pbkdf2hmac.py b/tests/hazmat/primitives/test_pbkdf2hmac.py index 8586debe4f1f..0c83c6a01754 100644 --- a/tests/hazmat/primitives/test_pbkdf2hmac.py +++ b/tests/hazmat/primitives/test_pbkdf2hmac.py @@ -67,4 +67,10 @@ def test_invalid_backend(): pretend_backend = object() with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE): - PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, pretend_backend) + PBKDF2HMAC( + hashes.SHA1(), + 20, + b"salt", + 10, + pretend_backend, # type:ignore[arg-type] + ) diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 9c98dbbab2e7..2c8715b24eb5 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -381,7 +381,9 @@ def test_rsa_generate_invalid_backend(): pretend_backend = object() with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE): - rsa.generate_private_key(65537, 2048, pretend_backend) + rsa.generate_private_key( + 65537, 2048, pretend_backend # type:ignore[arg-type] + ) class TestRSASignature(object): diff --git a/tests/hazmat/primitives/test_scrypt.py b/tests/hazmat/primitives/test_scrypt.py index 63e6b35ced1f..b87cb220a88f 100644 --- a/tests/hazmat/primitives/test_scrypt.py +++ b/tests/hazmat/primitives/test_scrypt.py @@ -84,7 +84,7 @@ def test_unsupported_backend(self): work_factor, block_size, parallelization_factor, - backend, + backend, # type: ignore[arg-type] ) def test_salt_not_bytes(self, backend): diff --git a/tests/hazmat/primitives/test_x963kdf.py b/tests/hazmat/primitives/test_x963kdf.py index 5254aa006cb3..c0c3c37d26d4 100644 --- a/tests/hazmat/primitives/test_x963kdf.py +++ b/tests/hazmat/primitives/test_x963kdf.py @@ -116,4 +116,9 @@ def test_invalid_backend(): pretend_backend = object() with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE): - X963KDF(hashes.SHA256(), 16, None, pretend_backend) + X963KDF( + hashes.SHA256(), + 16, + None, + pretend_backend, # type: ignore[arg-type] + ) diff --git a/tests/hazmat/primitives/twofactor/test_hotp.py b/tests/hazmat/primitives/twofactor/test_hotp.py index 979f3f004efc..3e983f83f431 100644 --- a/tests/hazmat/primitives/twofactor/test_hotp.py +++ b/tests/hazmat/primitives/twofactor/test_hotp.py @@ -120,4 +120,6 @@ def test_invalid_backend(): pretend_backend = object() with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE): - HOTP(secret, 8, hashes.SHA1(), pretend_backend) + HOTP( + secret, 8, hashes.SHA1(), pretend_backend # type: ignore[arg-type] + ) diff --git a/tests/hazmat/primitives/twofactor/test_totp.py b/tests/hazmat/primitives/twofactor/test_totp.py index 0159773399e2..2e7311ff88dd 100644 --- a/tests/hazmat/primitives/twofactor/test_totp.py +++ b/tests/hazmat/primitives/twofactor/test_totp.py @@ -155,4 +155,10 @@ def test_invalid_backend(): pretend_backend = object() with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE): - TOTP(secret, 8, hashes.SHA1(), 30, pretend_backend) + TOTP( + secret, + 8, + hashes.SHA1(), + 30, + pretend_backend, # type: ignore[arg-type] + ) diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 87b6b29e6fdb..5baa37861680 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -60,8 +60,7 @@ from ..utils import load_nist_vectors, load_vectors_from_file -@utils.register_interface(x509.ExtensionType) -class DummyExtension(object): +class DummyExtension(x509.ExtensionType): oid = x509.ObjectIdentifier("1.2.3.4") @@ -1683,11 +1682,15 @@ def test_build_cert(self, backend): basic_constraints = cert.extensions.get_extension_for_oid( ExtensionOID.BASIC_CONSTRAINTS ) + assert isinstance(basic_constraints.value, x509.BasicConstraints) assert basic_constraints.value.ca is False assert basic_constraints.value.path_length is None subject_alternative_name = cert.extensions.get_extension_for_oid( ExtensionOID.SUBJECT_ALTERNATIVE_NAME ) + assert isinstance( + subject_alternative_name.value, x509.SubjectAlternativeName + ) assert list(subject_alternative_name.value) == [ x509.DNSName("cryptography.io"), ] @@ -2498,11 +2501,15 @@ def test_build_cert_with_dsa_private_key(self, backend): basic_constraints = cert.extensions.get_extension_for_oid( ExtensionOID.BASIC_CONSTRAINTS ) + assert isinstance(basic_constraints.value, x509.BasicConstraints) assert basic_constraints.value.ca is False assert basic_constraints.value.path_length is None subject_alternative_name = cert.extensions.get_extension_for_oid( ExtensionOID.SUBJECT_ALTERNATIVE_NAME ) + assert isinstance( + subject_alternative_name.value, x509.SubjectAlternativeName + ) assert list(subject_alternative_name.value) == [ x509.DNSName("cryptography.io"), ] @@ -2545,11 +2552,15 @@ def test_build_cert_with_ec_private_key(self, backend): basic_constraints = cert.extensions.get_extension_for_oid( ExtensionOID.BASIC_CONSTRAINTS ) + assert isinstance(basic_constraints.value, x509.BasicConstraints) assert basic_constraints.value.ca is False assert basic_constraints.value.path_length is None subject_alternative_name = cert.extensions.get_extension_for_oid( ExtensionOID.SUBJECT_ALTERNATIVE_NAME ) + assert isinstance( + subject_alternative_name.value, x509.SubjectAlternativeName + ) assert list(subject_alternative_name.value) == [ x509.DNSName("cryptography.io"), ] @@ -2600,11 +2611,15 @@ def test_build_cert_with_ed25519(self, backend): basic_constraints = cert.extensions.get_extension_for_oid( ExtensionOID.BASIC_CONSTRAINTS ) + assert isinstance(basic_constraints.value, x509.BasicConstraints) assert basic_constraints.value.ca is False assert basic_constraints.value.path_length is None subject_alternative_name = cert.extensions.get_extension_for_oid( ExtensionOID.SUBJECT_ALTERNATIVE_NAME ) + assert isinstance( + subject_alternative_name.value, x509.SubjectAlternativeName + ) assert list(subject_alternative_name.value) == [ x509.DNSName("cryptography.io"), ] @@ -2635,6 +2650,7 @@ def test_build_cert_with_public_ed25519_rsa_sig(self, backend): ) cert = builder.sign(issuer_private_key, hashes.SHA256(), backend) + assert cert.signature_hash_algorithm is not None issuer_private_key.public_key().verify( cert.signature, cert.tbs_certificate_bytes, @@ -2693,11 +2709,15 @@ def test_build_cert_with_ed448(self, backend): basic_constraints = cert.extensions.get_extension_for_oid( ExtensionOID.BASIC_CONSTRAINTS ) + assert isinstance(basic_constraints.value, x509.BasicConstraints) assert basic_constraints.value.ca is False assert basic_constraints.value.path_length is None subject_alternative_name = cert.extensions.get_extension_for_oid( ExtensionOID.SUBJECT_ALTERNATIVE_NAME ) + assert isinstance( + subject_alternative_name.value, x509.SubjectAlternativeName + ) assert list(subject_alternative_name.value) == [ x509.DNSName("cryptography.io"), ] @@ -2728,6 +2748,7 @@ def test_build_cert_with_public_ed448_rsa_sig(self, backend): ) cert = builder.sign(issuer_private_key, hashes.SHA256(), backend) + assert cert.signature_hash_algorithm is not None issuer_private_key.public_key().verify( cert.signature, cert.tbs_certificate_bytes, @@ -3230,6 +3251,7 @@ def test_build_ca_request_with_path_length_none(self, backend): basic_constraints = request.extensions.get_extension_for_oid( ExtensionOID.BASIC_CONSTRAINTS ) + assert isinstance(basic_constraints.value, x509.BasicConstraints) assert basic_constraints.value.path_length is None @pytest.mark.parametrize( @@ -3273,7 +3295,9 @@ def test_sign_invalid_hash_algorithm(self, backend): x509.Name([]) ) with pytest.raises(TypeError): - builder.sign(private_key, "NotAHash", backend) + builder.sign( + private_key, "NotAHash", backend # type: ignore[arg-type] + ) @pytest.mark.supported( only_if=lambda backend: backend.ed25519_supported(), @@ -3373,6 +3397,7 @@ def test_build_ca_request_with_rsa(self, backend): basic_constraints = request.extensions.get_extension_for_oid( ExtensionOID.BASIC_CONSTRAINTS ) + assert isinstance(basic_constraints.value, x509.BasicConstraints) assert basic_constraints.value.ca is True assert basic_constraints.value.path_length == 2 @@ -3518,6 +3543,7 @@ def test_build_nonca_request_with_rsa(self, backend): basic_constraints = request.extensions.get_extension_for_oid( ExtensionOID.BASIC_CONSTRAINTS ) + assert isinstance(basic_constraints.value, x509.BasicConstraints) assert basic_constraints.value.ca is False assert basic_constraints.value.path_length is None @@ -3553,6 +3579,7 @@ def test_build_ca_request_with_ec(self, backend): basic_constraints = request.extensions.get_extension_for_oid( ExtensionOID.BASIC_CONSTRAINTS ) + assert isinstance(basic_constraints.value, x509.BasicConstraints) assert basic_constraints.value.ca is True assert basic_constraints.value.path_length == 2 @@ -3657,6 +3684,7 @@ def test_build_ca_request_with_dsa(self, backend): basic_constraints = request.extensions.get_extension_for_oid( ExtensionOID.BASIC_CONSTRAINTS ) + assert isinstance(basic_constraints.value, x509.BasicConstraints) assert basic_constraints.value.ca is True assert basic_constraints.value.path_length == 2 @@ -3800,11 +3828,13 @@ def test_add_two_extensions(self, backend): basic_constraints = request.extensions.get_extension_for_oid( ExtensionOID.BASIC_CONSTRAINTS ) + assert isinstance(basic_constraints.value, x509.BasicConstraints) assert basic_constraints.value.ca is True assert basic_constraints.value.path_length == 2 ext = request.extensions.get_extension_for_oid( ExtensionOID.SUBJECT_ALTERNATIVE_NAME ) + assert isinstance(ext.value, x509.SubjectAlternativeName) assert list(ext.value) == [x509.DNSName("cryptography.io")] def test_add_attributes(self, backend): diff --git a/tests/x509/test_x509_crlbuilder.py b/tests/x509/test_x509_crlbuilder.py index b32322f975e6..14fe2387107f 100644 --- a/tests/x509/test_x509_crlbuilder.py +++ b/tests/x509/test_x509_crlbuilder.py @@ -341,6 +341,7 @@ def test_freshestcrl_extension(self, backend): assert len(crl.extensions) == 1 ext1 = crl.extensions.get_extension_for_class(x509.FreshestCRL) assert ext1.critical is False + assert isinstance(ext1.value, x509.FreshestCRL) assert isinstance(ext1.value[0], x509.DistributionPoint) assert ext1.value[0].full_name is not None uri = ext1.value[0].full_name[0] @@ -411,7 +412,9 @@ def test_sign_with_invalid_hash(self, backend): ) with pytest.raises(TypeError): - builder.sign(private_key, object(), backend) + builder.sign( + private_key, object(), backend # type: ignore[arg-type] + ) @pytest.mark.supported( only_if=lambda backend: backend.ed25519_supported(), @@ -437,7 +440,11 @@ def test_sign_with_invalid_hash_ed25519(self, backend): ) with pytest.raises(ValueError): - builder.sign(private_key, object(), backend) + builder.sign( + private_key, + object(), # type:ignore[arg-type] + backend, + ) with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA256(), backend) @@ -465,7 +472,11 @@ def test_sign_with_invalid_hash_ed448(self, backend): ) with pytest.raises(ValueError): - builder.sign(private_key, object(), backend) + builder.sign( + private_key, + object(), # type:ignore[arg-type] + backend, + ) with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA256(), backend) From e09cd90f77a31832bdde1d3652c115be282cced9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Mar 2021 07:39:57 -0500 Subject: [PATCH 0173/2380] Bump libc from 0.2.86 to 0.2.87 in /src/rust (#5891) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.86 to 0.2.87. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.86...0.2.87) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 83fd7eb8f48b..a78ee8f67ab3 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" +checksum = "265d751d31d6780a3f956bb5b8022feba2d94eeee5a84ba64f4212eedca42213" [[package]] name = "lock_api" From 6539e3381e5da8329509d2546e0f6ce3e4ca8896 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Mar 2021 07:55:13 -0500 Subject: [PATCH 0174/2380] Bump syn from 1.0.60 to 1.0.61 in /src/rust (#5895) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.60 to 1.0.61. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.60...1.0.61) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index a78ee8f67ab3..275c34709476 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -239,9 +239,9 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "syn" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" +checksum = "ed22b90a0e734a23a7610f4283ac9e5acfb96cbb30dfefa540d66f866f1c09c5" dependencies = [ "proc-macro2", "quote", From 9ef995722153f7c59b378f4c56b8affbfa13ff54 Mon Sep 17 00:00:00 2001 From: Mathias Ertl Date: Sat, 6 Mar 2021 19:03:32 +0100 Subject: [PATCH 0175/2380] Generic extension value/typehint x509.Name (#5897) * make value property return the generic value * typehint x509.Name * also ignore overloaded functions --- .coveragerc | 1 + src/cryptography/x509/extensions.py | 2 +- src/cryptography/x509/name.py | 24 +++++++++++++++++++++--- tests/x509/test_x509.py | 2 +- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/.coveragerc b/.coveragerc index 62a0ff5fb763..0ee0cd107461 100644 --- a/.coveragerc +++ b/.coveragerc @@ -14,3 +14,4 @@ source = exclude_lines = @abc.abstractmethod @abc.abstractproperty + @typing.overload diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index d43f2b8d2a58..2f32d58d96a5 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -1350,7 +1350,7 @@ def critical(self) -> bool: return self._critical @property - def value(self) -> ExtensionType: + def value(self) -> ExtensionTypeVar: return self._value def __repr__(self) -> str: diff --git a/src/cryptography/x509/name.py b/src/cryptography/x509/name.py index 5f0b88e1794d..0bfc2d94d452 100644 --- a/src/cryptography/x509/name.py +++ b/src/cryptography/x509/name.py @@ -196,14 +196,32 @@ def __repr__(self) -> str: class Name(object): - def __init__(self, attributes): + @typing.overload + def __init__(self, attributes: typing.Iterable[NameAttribute]) -> None: + ... + + @typing.overload + def __init__( + self, attributes: typing.Iterable[RelativeDistinguishedName] + ) -> None: + ... + + def __init__( + self, + attributes: typing.Iterable[ + typing.Union[NameAttribute, RelativeDistinguishedName] + ], + ) -> None: attributes = list(attributes) if all(isinstance(x, NameAttribute) for x in attributes): self._attributes = [ - RelativeDistinguishedName([x]) for x in attributes + RelativeDistinguishedName([typing.cast(NameAttribute, x)]) + for x in attributes ] elif all(isinstance(x, RelativeDistinguishedName) for x in attributes): - self._attributes = attributes + self._attributes = typing.cast( + typing.List[RelativeDistinguishedName], attributes + ) else: raise TypeError( "attributes must be a list of NameAttribute" diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 5baa37861680..e47c109f414e 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -5019,7 +5019,7 @@ def test_rfc4514_string_empty_values(self): def test_not_nameattribute(self): with pytest.raises(TypeError): - x509.Name(["not-a-NameAttribute"]) + x509.Name(["not-a-NameAttribute"]) # type: ignore[list-item] def test_bytes(self, backend): name = x509.Name( From 6384cbb2fe25469ecfb6d6e431211a8426380893 Mon Sep 17 00:00:00 2001 From: Mathias Ertl Date: Sun, 7 Mar 2021 18:59:30 +0100 Subject: [PATCH 0176/2380] Bugfix/issue 5889 typehint get values for types (#5900) * add type alias for IP addresses * Re-export module attributes in cryptography.x509.oid Without exporting attributes via `__all__` mypy will consider typehints of classes imported from `cryptography.x509.oid` as type Any. Example: from cryptography.x509.oid import ObjectIdentifier oid = ObjectIdentifier("1.2.3") # Any, if we do not re-export Note that while the canonical location of ObjectIdentifier is in `crytography.x509`, it is imported many times from `crytography.x509.oid` instead * add return type annotiations to constructors * overload GeneralNames.get_values_for_type * overload all implementations --- src/cryptography/x509/extensions.py | 240 ++++++++++++++++++++++++-- src/cryptography/x509/general_name.py | 37 ++-- src/cryptography/x509/oid.py | 15 ++ 3 files changed, 258 insertions(+), 34 deletions(-) diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index 2f32d58d96a5..d9443106fa0c 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -23,8 +23,18 @@ from cryptography.x509.certificate_transparency import ( SignedCertificateTimestamp, ) -from cryptography.x509.general_name import GeneralName, IPAddress, OtherName -from cryptography.x509.name import RelativeDistinguishedName +from cryptography.x509.general_name import ( + DNSName, + DirectoryName, + GeneralName, + IPAddress, + OtherName, + RFC822Name, + RegisteredID, + UniformResourceIdentifier, + _IPADDRESS_TYPES, +) +from cryptography.x509.name import Name, RelativeDistinguishedName from cryptography.x509.oid import ( CRLEntryExtensionOID, ExtensionOID, @@ -1389,15 +1399,67 @@ def __init__(self, general_names: typing.Iterable[GeneralName]) -> None: __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") + @typing.overload + def get_values_for_type( + self, + type: typing.Union[ + typing.Type[DNSName], + typing.Type[UniformResourceIdentifier], + typing.Type[RFC822Name], + ], + ) -> typing.List[str]: + ... + + @typing.overload def get_values_for_type( - self, type: typing.Type[GeneralName] - ) -> typing.List[GeneralName]: + self, + type: typing.Type[DirectoryName], + ) -> typing.List[Name]: + ... + + @typing.overload + def get_values_for_type( + self, + type: typing.Type[RegisteredID], + ) -> typing.List[ObjectIdentifier]: + ... + + @typing.overload + def get_values_for_type( + self, type: typing.Type[IPAddress] + ) -> typing.List[_IPADDRESS_TYPES]: + ... + + @typing.overload + def get_values_for_type( + self, type: typing.Type[OtherName] + ) -> typing.List[OtherName]: + ... + + def get_values_for_type( + self, + type: typing.Union[ + typing.Type[DNSName], + typing.Type[DirectoryName], + typing.Type[IPAddress], + typing.Type[OtherName], + typing.Type[RFC822Name], + typing.Type[RegisteredID], + typing.Type[UniformResourceIdentifier], + ], + ) -> typing.Union[ + typing.List[_IPADDRESS_TYPES], + typing.List[str], + typing.List[OtherName], + typing.List[Name], + typing.List[ObjectIdentifier], + ]: # Return the value of each GeneralName, except for OtherName instances # which we return directly because it has two important properties not # just one value. objs = (i for i in self if isinstance(i, type)) if type != OtherName: - objs = (i.value for i in objs) + return [i.value for i in objs] return list(objs) def __repr__(self) -> str: @@ -1424,9 +1486,61 @@ def __init__(self, general_names: typing.Iterable[GeneralName]) -> None: __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") + @typing.overload def get_values_for_type( - self, type: typing.Type[GeneralName] - ) -> typing.List[GeneralName]: + self, + type: typing.Union[ + typing.Type[DNSName], + typing.Type[UniformResourceIdentifier], + typing.Type[RFC822Name], + ], + ) -> typing.List[str]: + ... + + @typing.overload + def get_values_for_type( + self, + type: typing.Type[DirectoryName], + ) -> typing.List[Name]: + ... + + @typing.overload + def get_values_for_type( + self, + type: typing.Type[RegisteredID], + ) -> typing.List[ObjectIdentifier]: + ... + + @typing.overload + def get_values_for_type( + self, type: typing.Type[IPAddress] + ) -> typing.List[_IPADDRESS_TYPES]: + ... + + @typing.overload + def get_values_for_type( + self, type: typing.Type[OtherName] + ) -> typing.List[OtherName]: + ... + + def get_values_for_type( + self, + type: typing.Union[ + typing.Type[DNSName], + typing.Type[DirectoryName], + typing.Type[IPAddress], + typing.Type[OtherName], + typing.Type[RFC822Name], + typing.Type[RegisteredID], + typing.Type[UniformResourceIdentifier], + ], + ) -> typing.Union[ + typing.List[_IPADDRESS_TYPES], + typing.List[str], + typing.List[OtherName], + typing.List[Name], + typing.List[ObjectIdentifier], + ]: return self._general_names.get_values_for_type(type) def __repr__(self) -> str: @@ -1453,9 +1567,61 @@ def __init__(self, general_names: typing.Iterable[GeneralName]) -> None: __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") + @typing.overload def get_values_for_type( - self, type: typing.Type[GeneralName] - ) -> typing.List[GeneralName]: + self, + type: typing.Union[ + typing.Type[DNSName], + typing.Type[UniformResourceIdentifier], + typing.Type[RFC822Name], + ], + ) -> typing.List[str]: + ... + + @typing.overload + def get_values_for_type( + self, + type: typing.Type[DirectoryName], + ) -> typing.List[Name]: + ... + + @typing.overload + def get_values_for_type( + self, + type: typing.Type[RegisteredID], + ) -> typing.List[ObjectIdentifier]: + ... + + @typing.overload + def get_values_for_type( + self, type: typing.Type[IPAddress] + ) -> typing.List[_IPADDRESS_TYPES]: + ... + + @typing.overload + def get_values_for_type( + self, type: typing.Type[OtherName] + ) -> typing.List[OtherName]: + ... + + def get_values_for_type( + self, + type: typing.Union[ + typing.Type[DNSName], + typing.Type[DirectoryName], + typing.Type[IPAddress], + typing.Type[OtherName], + typing.Type[RFC822Name], + typing.Type[RegisteredID], + typing.Type[UniformResourceIdentifier], + ], + ) -> typing.Union[ + typing.List[_IPADDRESS_TYPES], + typing.List[str], + typing.List[OtherName], + typing.List[Name], + typing.List[ObjectIdentifier], + ]: return self._general_names.get_values_for_type(type) def __repr__(self) -> str: @@ -1482,9 +1648,61 @@ def __init__(self, general_names: typing.Iterable[GeneralName]) -> None: __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") + @typing.overload def get_values_for_type( - self, type: typing.Type[GeneralName] - ) -> typing.List[GeneralName]: + self, + type: typing.Union[ + typing.Type[DNSName], + typing.Type[UniformResourceIdentifier], + typing.Type[RFC822Name], + ], + ) -> typing.List[str]: + ... + + @typing.overload + def get_values_for_type( + self, + type: typing.Type[DirectoryName], + ) -> typing.List[Name]: + ... + + @typing.overload + def get_values_for_type( + self, + type: typing.Type[RegisteredID], + ) -> typing.List[ObjectIdentifier]: + ... + + @typing.overload + def get_values_for_type( + self, type: typing.Type[IPAddress] + ) -> typing.List[_IPADDRESS_TYPES]: + ... + + @typing.overload + def get_values_for_type( + self, type: typing.Type[OtherName] + ) -> typing.List[OtherName]: + ... + + def get_values_for_type( + self, + type: typing.Union[ + typing.Type[DNSName], + typing.Type[DirectoryName], + typing.Type[IPAddress], + typing.Type[OtherName], + typing.Type[RFC822Name], + typing.Type[RegisteredID], + typing.Type[UniformResourceIdentifier], + ], + ) -> typing.Union[ + typing.List[_IPADDRESS_TYPES], + typing.List[str], + typing.List[OtherName], + typing.List[Name], + typing.List[ObjectIdentifier], + ]: return self._general_names.get_values_for_type(type) def __repr__(self) -> str: diff --git a/src/cryptography/x509/general_name.py b/src/cryptography/x509/general_name.py index f16aef85e15f..d49582c41e11 100644 --- a/src/cryptography/x509/general_name.py +++ b/src/cryptography/x509/general_name.py @@ -23,6 +23,12 @@ 7: "iPAddress", 8: "registeredID", } +_IPADDRESS_TYPES = typing.Union[ + ipaddress.IPv4Address, + ipaddress.IPv6Address, + ipaddress.IPv4Network, + ipaddress.IPv6Network, +] class UnsupportedGeneralNameType(Exception): @@ -40,7 +46,7 @@ def value(self) -> typing.Any: class RFC822Name(GeneralName): - def __init__(self, value: str): + def __init__(self, value: str) -> None: if isinstance(value, str): try: value.encode("ascii") @@ -88,7 +94,7 @@ def __hash__(self) -> int: class DNSName(GeneralName): - def __init__(self, value: str): + def __init__(self, value: str) -> None: if isinstance(value, str): try: value.encode("ascii") @@ -130,7 +136,7 @@ def __hash__(self) -> int: class UniformResourceIdentifier(GeneralName): - def __init__(self, value: str): + def __init__(self, value: str) -> None: if isinstance(value, str): try: value.encode("ascii") @@ -174,7 +180,7 @@ def __hash__(self) -> int: class DirectoryName(GeneralName): - def __init__(self, value: Name): + def __init__(self, value: Name) -> None: if not isinstance(value, Name): raise TypeError("value must be a Name") @@ -201,7 +207,7 @@ def __hash__(self) -> int: class RegisteredID(GeneralName): - def __init__(self, value: ObjectIdentifier): + def __init__(self, value: ObjectIdentifier) -> None: if not isinstance(value, ObjectIdentifier): raise TypeError("value must be an ObjectIdentifier") @@ -228,15 +234,7 @@ def __hash__(self) -> int: class IPAddress(GeneralName): - def __init__( - self, - value: typing.Union[ - ipaddress.IPv4Address, - ipaddress.IPv6Address, - ipaddress.IPv4Network, - ipaddress.IPv6Network, - ], - ): + def __init__(self, value: _IPADDRESS_TYPES) -> None: if not isinstance( value, ( @@ -255,14 +253,7 @@ def __init__( self._value = value @property - def value( - self, - ) -> typing.Union[ - ipaddress.IPv4Address, - ipaddress.IPv6Address, - ipaddress.IPv4Network, - ipaddress.IPv6Network, - ]: + def value(self) -> _IPADDRESS_TYPES: return self._value def __repr__(self) -> str: @@ -282,7 +273,7 @@ def __hash__(self) -> int: class OtherName(GeneralName): - def __init__(self, type_id: ObjectIdentifier, value: bytes): + def __init__(self, type_id: ObjectIdentifier, value: bytes) -> None: if not isinstance(type_id, ObjectIdentifier): raise TypeError("type_id must be an ObjectIdentifier") if not isinstance(value, bytes): diff --git a/src/cryptography/x509/oid.py b/src/cryptography/x509/oid.py index c7695bdb5397..228ac1155324 100644 --- a/src/cryptography/x509/oid.py +++ b/src/cryptography/x509/oid.py @@ -265,3 +265,18 @@ class AttributeOID(object): OCSPExtensionOID.NONCE: "OCSPNonce", AttributeOID.CHALLENGE_PASSWORD: "challengePassword", } + + +__all__ = [ + "AttributeOID", + "AuthorityInformationAccessOID", + "CRLEntryExtensionOID", + "CertificatePoliciesOID", + "ExtendedKeyUsageOID", + "ExtensionOID", + "NameOID", + "OCSPExtensionOID", + "ObjectIdentifier", + "SignatureAlgorithmOID", + "SubjectInformationAccessOID", +] From 8ca4d5a014191be8de10c3f46935bc7780eae444 Mon Sep 17 00:00:00 2001 From: "Ajitomi, Daisuke" Date: Mon, 8 Mar 2021 03:50:20 +0900 Subject: [PATCH 0177/2380] Add exceptions to Ed25519PrivateKey and Edd25519PublicKey methods. (#5898) --- docs/hazmat/primitives/asymmetric/ed25519.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/hazmat/primitives/asymmetric/ed25519.rst b/docs/hazmat/primitives/asymmetric/ed25519.rst index 47d95ec1b9da..152dcfe6f947 100644 --- a/docs/hazmat/primitives/asymmetric/ed25519.rst +++ b/docs/hazmat/primitives/asymmetric/ed25519.rst @@ -43,6 +43,11 @@ Key interfaces :returns: :class:`Ed25519PrivateKey` + :raises ValueError: This is raised if the private key is not 32 bytes long. + + :raises cryptography.exceptions.UnsupportedAlgorithm: If the private key + is of a type that is not supported by the backend. + .. doctest:: >>> from cryptography.hazmat.primitives import serialization @@ -108,6 +113,11 @@ Key interfaces :returns: :class:`Ed25519PublicKey` + :raises ValueError: This is raised if the public key is not 32 bytes long. + + :raises cryptography.exceptions.UnsupportedAlgorithm: If the public key + is of a type that is not supported by the backend. + .. doctest:: >>> from cryptography.hazmat.primitives import serialization From 7a9a9e15b8ebd250fa9d6b562f6ff657a8cfbd8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Mar 2021 07:49:42 -0500 Subject: [PATCH 0178/2380] Bump libc from 0.2.87 to 0.2.88 in /src/rust (#5902) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.87 to 0.2.88. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.87...0.2.88) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 275c34709476..ed8d6c0e8d6f 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "265d751d31d6780a3f956bb5b8022feba2d94eeee5a84ba64f4212eedca42213" +checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a" [[package]] name = "lock_api" From 8df153664a06e77e344566417426a5a31c0be69e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Mar 2021 07:57:35 -0500 Subject: [PATCH 0179/2380] Bump syn from 1.0.61 to 1.0.62 in /src/rust (#5903) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.61 to 1.0.62. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.61...1.0.62) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index ed8d6c0e8d6f..cb594157e509 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -239,9 +239,9 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "syn" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed22b90a0e734a23a7610f4283ac9e5acfb96cbb30dfefa540d66f866f1c09c5" +checksum = "123a78a3596b24fee53a6464ce52d8ecbf62241e6294c7e7fe12086cd161f512" dependencies = [ "proc-macro2", "quote", From c5cc44a313b5b90a710c40f213679900ab5783c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Mar 2021 07:28:12 -0500 Subject: [PATCH 0180/2380] Bump syn from 1.0.62 to 1.0.63 in /src/rust (#5909) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.62 to 1.0.63. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.62...1.0.63) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index cb594157e509..7f289ef10f15 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -239,9 +239,9 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "syn" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "123a78a3596b24fee53a6464ce52d8ecbf62241e6294c7e7fe12086cd161f512" +checksum = "8fd9bc7ccc2688b3344c2f48b9b546648b25ce0b20fc717ee7fa7981a8ca9717" dependencies = [ "proc-macro2", "quote", From 2428b11ab84bb796bfcc595cd48fc00e3195e6bb Mon Sep 17 00:00:00 2001 From: Mathias Ertl Date: Thu, 11 Mar 2021 21:35:48 +0100 Subject: [PATCH 0181/2380] Typehint x509.base (only) (#5904) * typehint x509.base * cast extension class * don't use string in typecast * use lists as default argument values (see #5904) * restore import since this is now re-exported * ignore linting errors * empty commit to trigger github actions * fix formatting issue --- .../hazmat/backends/openssl/backend.py | 7 +- src/cryptography/x509/base.py | 70 +++++++++++++------ tests/x509/test_x509.py | 15 ++-- 3 files changed, 65 insertions(+), 27 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index c87a466c9307..605af068d480 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -991,7 +991,8 @@ def create_x509_certificate(self, builder, private_key, algorithm): # Set the subject's public key. res = self._lib.X509_set_pubkey( - x509_cert, builder._public_key._evp_pkey + x509_cert, + builder._public_key._evp_pkey, # type: ignore[union-attr] ) self.openssl_assert(res == 1) @@ -1101,7 +1102,9 @@ def create_x509_crl(self, builder, private_key, algorithm): for revoked_cert in builder._revoked_certificates: # Duplicating because the X509_CRL takes ownership and will free # this memory when X509_CRL_free is called. - revoked = self._lib.X509_REVOKED_dup(revoked_cert._x509_revoked) + revoked = self._lib.X509_REVOKED_dup( + revoked_cert._x509_revoked # type: ignore[attr-defined] + ) self.openssl_assert(revoked != self._ffi.NULL) res = self._lib.X509_CRL_add0_revoked(x509_crl, revoked) self.openssl_assert(res == 1) diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index 1e98b469c1bb..9bbde978fda1 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -29,13 +29,14 @@ class AttributeNotFound(Exception): - def __init__(self, msg, oid): + def __init__(self, msg: str, oid: ObjectIdentifier) -> None: super(AttributeNotFound, self).__init__(msg) self.oid = oid def _reject_duplicate_extension( - extension: Extension, extensions: typing.List[Extension] + extension: Extension[ExtensionType], + extensions: typing.List[Extension[ExtensionType]], ) -> None: # This is quadratic in the number of extensions for e in extensions: @@ -73,7 +74,7 @@ class Version(Enum): class InvalidVersion(Exception): - def __init__(self, msg, parsed_version): + def __init__(self, msg: str, parsed_version: int) -> None: super(InvalidVersion, self).__init__(msg) self.parsed_version = parsed_version @@ -228,7 +229,9 @@ def get_revoked_certificate_by_serial_number( """ @abc.abstractproperty - def signature_hash_algorithm(self) -> hashes.HashAlgorithm: + def signature_hash_algorithm( + self, + ) -> typing.Optional[hashes.HashAlgorithm]: """ Returns a HashAlgorithm corresponding to the type of the digest signed in the certificate. @@ -294,14 +297,24 @@ def __len__(self) -> int: Number of revoked certificates in the CRL. """ + @typing.overload + def __getitem__(self, idx: int) -> RevokedCertificate: + ... + + @typing.overload + def __getitem__(self, idx: slice) -> typing.List[RevokedCertificate]: + ... + @abc.abstractmethod - def __getitem__(self, idx): + def __getitem__( + self, idx: typing.Union[int, slice] + ) -> typing.Union[RevokedCertificate, typing.List[RevokedCertificate]]: """ Returns a revoked certificate (or slice of revoked certificates). """ @abc.abstractmethod - def __iter__(self): + def __iter__(self) -> typing.Iterator[RevokedCertificate]: """ Iterator over the revoked certificates """ @@ -345,7 +358,9 @@ def subject(self) -> Name: """ @abc.abstractproperty - def signature_hash_algorithm(self) -> hashes.HashAlgorithm: + def signature_hash_algorithm( + self, + ) -> typing.Optional[hashes.HashAlgorithm]: """ Returns a HashAlgorithm corresponding to the type of the digest signed in the certificate. @@ -438,7 +453,12 @@ def load_der_x509_crl( class CertificateSigningRequestBuilder(object): - def __init__(self, subject_name=None, extensions=[], attributes=[]): + def __init__( + self, + subject_name: typing.Optional[Name] = None, + extensions: typing.List[Extension[ExtensionType]] = [], + attributes: typing.List[typing.Tuple[ObjectIdentifier, bytes]] = [], + ): """ Creates an empty X.509 certificate request (v1). """ @@ -512,15 +532,17 @@ def sign( class CertificateBuilder(object): + _extensions: typing.List[Extension[ExtensionType]] + def __init__( self, - issuer_name=None, - subject_name=None, - public_key=None, - serial_number=None, - not_valid_before=None, - not_valid_after=None, - extensions=[], + issuer_name: typing.Optional[Name] = None, + subject_name: typing.Optional[Name] = None, + public_key: typing.Optional[_PUBLIC_KEY_TYPES] = None, + serial_number: typing.Optional[int] = None, + not_valid_before: typing.Optional[datetime.datetime] = None, + not_valid_after: typing.Optional[datetime.datetime] = None, + extensions: typing.List[Extension[ExtensionType]] = [], ) -> None: self._version = Version.v3 self._issuer_name = issuer_name @@ -745,13 +767,16 @@ def sign( class CertificateRevocationListBuilder(object): + _extensions: typing.List[Extension[ExtensionType]] + _revoked_certificates: typing.List[RevokedCertificate] + def __init__( self, - issuer_name=None, - last_update=None, - next_update=None, - extensions=[], - revoked_certificates=[], + issuer_name: typing.Optional[Name] = None, + last_update: typing.Optional[datetime.datetime] = None, + next_update: typing.Optional[datetime.datetime] = None, + extensions: typing.List[Extension[ExtensionType]] = [], + revoked_certificates: typing.List[RevokedCertificate] = [], ): self._issuer_name = issuer_name self._last_update = last_update @@ -879,7 +904,10 @@ def sign( class RevokedCertificateBuilder(object): def __init__( - self, serial_number=None, revocation_date=None, extensions=[] + self, + serial_number: typing.Optional[int] = None, + revocation_date: typing.Optional[datetime.datetime] = None, + extensions: typing.List[Extension[ExtensionType]] = [], ): self._serial_number = serial_number self._revocation_date = revocation_date diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index e47c109f414e..b3bf78a6862e 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -10,6 +10,7 @@ import datetime import ipaddress import os +import typing import pytest @@ -3615,8 +3616,11 @@ def test_build_ca_request_with_ed25519(self, backend): assert list(subject) == [ x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Texas"), ] - basic_constraints = request.extensions.get_extension_for_oid( - ExtensionOID.BASIC_CONSTRAINTS + basic_constraints = typing.cast( + x509.Extension[x509.BasicConstraints], + request.extensions.get_extension_for_oid( + ExtensionOID.BASIC_CONSTRAINTS + ), ) assert basic_constraints.value.ca is True assert basic_constraints.value.path_length == 2 @@ -3653,8 +3657,11 @@ def test_build_ca_request_with_ed448(self, backend): assert list(subject) == [ x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Texas"), ] - basic_constraints = request.extensions.get_extension_for_oid( - ExtensionOID.BASIC_CONSTRAINTS + basic_constraints = typing.cast( + x509.Extension[x509.BasicConstraints], + request.extensions.get_extension_for_oid( + ExtensionOID.BASIC_CONSTRAINTS + ), ) assert basic_constraints.value.ca is True assert basic_constraints.value.path_length == 2 From 4ba7f21c01573641cb520c9d0476ab53ac14111c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Mar 2021 07:54:04 -0400 Subject: [PATCH 0182/2380] Bump syn from 1.0.63 to 1.0.64 in /src/rust (#5915) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.63 to 1.0.64. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.63...1.0.64) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 7f289ef10f15..7f59f413b425 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -239,9 +239,9 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "syn" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd9bc7ccc2688b3344c2f48b9b546648b25ce0b20fc717ee7fa7981a8ca9717" +checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f" dependencies = [ "proc-macro2", "quote", From cd2ab9ec6c14333e10fb161295d5ae355c4a8f96 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 15 Mar 2021 09:44:38 -0400 Subject: [PATCH 0183/2380] update java sdk download link (#5916) --- docs/development/custom-vectors/rsa-oaep-sha2.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/development/custom-vectors/rsa-oaep-sha2.rst b/docs/development/custom-vectors/rsa-oaep-sha2.rst index 36f256d7c68e..30c3e273505a 100644 --- a/docs/development/custom-vectors/rsa-oaep-sha2.rst +++ b/docs/development/custom-vectors/rsa-oaep-sha2.rst @@ -33,7 +33,7 @@ Download link: :download:`VerifyRSAOAEPSHA2.java Using the Verifier ------------------ -Download and install the `Java 8 SDK`_. Initial verification was performed +Download and install the `Java SDK`_. Initial verification was performed using ``jdk-8u77-macosx-x64.dmg``. Download the latest `Bouncy Castle`_ JAR. Initial verification was performed @@ -53,4 +53,4 @@ Finally, run the program with the path to the SHA-2 vectors: $ java -classpath ~/Downloads/bcprov-jdk15on-154.jar:./ VerifyRSAOAEPSHA2 .. _`Bouncy Castle`: https://www.bouncycastle.org/ -.. _`Java 8 SDK`: https://www.oracle.com/technetwork/java/javase/downloads/index.html +.. _`Java SDK`: https://www.oracle.com/java/technologies/javase-downloads.html From 8d41a94bba7674cfcb120ce7a76b7c3df5c2bb73 Mon Sep 17 00:00:00 2001 From: Mathias Ertl Date: Mon, 15 Mar 2021 23:44:02 +0100 Subject: [PATCH 0184/2380] typehint x509.base (#5899) * start typing x509.base * statically type x509.base * typehint X509Backend interface * typehint at least the X509Backend interface * make _CertificateRevocationList/_CertificateSigningRequest actual subclasses of the interface (as done before for Certificate in f16bff2cb) * tell mypy to ignore lines with deliberately wrong types * signature_hash_algorithm always returns a hash algorithm (it's not optional) * Revert "signature_hash_algorithm always returns a hash algorithm (it's not optional)" This reverts commit f6a5b172b416f8ddea561203c0cf03b55e4ec50e. * hash algorithm is actually optional * fix import style * typehint parsed_version to int, which it de facto always is * minimize changes * break import cycle with conditional imports * ignore access to private members of openssl implementation * reformat code with Black * test check for missing public key --- .coveragerc | 1 + src/cryptography/hazmat/backends/__init__.py | 2 +- .../hazmat/backends/interfaces.py | 56 +++++++++++++---- .../hazmat/backends/openssl/backend.py | 62 ++++++++++++++----- .../hazmat/backends/openssl/x509.py | 6 +- tests/hazmat/backends/test_openssl.py | 29 +++++++-- 6 files changed, 121 insertions(+), 35 deletions(-) diff --git a/.coveragerc b/.coveragerc index 0ee0cd107461..6579cf6c8d42 100644 --- a/.coveragerc +++ b/.coveragerc @@ -15,3 +15,4 @@ exclude_lines = @abc.abstractmethod @abc.abstractproperty @typing.overload + if typing.TYPE_CHECKING diff --git a/src/cryptography/hazmat/backends/__init__.py b/src/cryptography/hazmat/backends/__init__.py index 7f74cba2c9b2..64eedecb57e4 100644 --- a/src/cryptography/hazmat/backends/__init__.py +++ b/src/cryptography/hazmat/backends/__init__.py @@ -9,7 +9,7 @@ _default_backend: typing.Optional[Backend] = None -def default_backend(): +def default_backend() -> Backend: global _default_backend if _default_backend is None: diff --git a/src/cryptography/hazmat/backends/interfaces.py b/src/cryptography/hazmat/backends/interfaces.py index d57289bb1dc2..bb51060809f9 100644 --- a/src/cryptography/hazmat/backends/interfaces.py +++ b/src/cryptography/hazmat/backends/interfaces.py @@ -4,6 +4,23 @@ import abc +import typing + + +if typing.TYPE_CHECKING: + from cryptography.hazmat._types import _PRIVATE_KEY_TYPES + from cryptography.hazmat.primitives import hashes + from cryptography.x509.base import ( + Certificate, + CertificateBuilder, + CertificateRevocationList, + CertificateRevocationListBuilder, + CertificateSigningRequest, + CertificateSigningRequestBuilder, + RevokedCertificate, + RevokedCertificateBuilder, + ) + from cryptography.x509.name import Name class CipherBackend(metaclass=abc.ABCMeta): @@ -262,69 +279,86 @@ def load_der_parameters(self, data): class X509Backend(metaclass=abc.ABCMeta): @abc.abstractmethod - def load_pem_x509_certificate(self, data): + def load_pem_x509_certificate(self, data: bytes) -> "Certificate": """ Load an X.509 certificate from PEM encoded data. """ @abc.abstractmethod - def load_der_x509_certificate(self, data): + def load_der_x509_certificate(self, data: bytes) -> "Certificate": """ Load an X.509 certificate from DER encoded data. """ @abc.abstractmethod - def load_der_x509_csr(self, data): + def load_der_x509_csr(self, data: bytes) -> "CertificateSigningRequest": """ Load an X.509 CSR from DER encoded data. """ @abc.abstractmethod - def load_pem_x509_csr(self, data): + def load_pem_x509_csr(self, data: bytes) -> "CertificateSigningRequest": """ Load an X.509 CSR from PEM encoded data. """ @abc.abstractmethod - def create_x509_csr(self, builder, private_key, algorithm): + def create_x509_csr( + self, + builder: "CertificateSigningRequestBuilder", + private_key: "_PRIVATE_KEY_TYPES", + algorithm: typing.Optional["hashes.HashAlgorithm"], + ) -> "CertificateSigningRequest": """ Create and sign an X.509 CSR from a CSR builder object. """ @abc.abstractmethod - def create_x509_certificate(self, builder, private_key, algorithm): + def create_x509_certificate( + self, + builder: "CertificateBuilder", + private_key: "_PRIVATE_KEY_TYPES", + algorithm: typing.Optional["hashes.HashAlgorithm"], + ) -> "Certificate": """ Create and sign an X.509 certificate from a CertificateBuilder object. """ @abc.abstractmethod - def create_x509_crl(self, builder, private_key, algorithm): + def create_x509_crl( + self, + builder: "CertificateRevocationListBuilder", + private_key: "_PRIVATE_KEY_TYPES", + algorithm: typing.Optional["hashes.HashAlgorithm"], + ) -> "CertificateRevocationList": """ Create and sign an X.509 CertificateRevocationList from a CertificateRevocationListBuilder object. """ @abc.abstractmethod - def create_x509_revoked_certificate(self, builder): + def create_x509_revoked_certificate( + self, builder: "RevokedCertificateBuilder" + ) -> "RevokedCertificate": """ Create a RevokedCertificate object from a RevokedCertificateBuilder object. """ @abc.abstractmethod - def x509_name_bytes(self, name): + def x509_name_bytes(self, name: "Name") -> bytes: """ Compute the DER encoded bytes of an X509 Name object. """ @abc.abstractmethod - def load_pem_x509_crl(self, data): + def load_pem_x509_crl(self, data: bytes) -> "CertificateRevocationList": """ Load an X.509 CRL from PEM encoded data. """ @abc.abstractmethod - def load_der_x509_crl(self, data): + def load_der_x509_crl(self, data: bytes) -> "CertificateRevocationList": """ Load an X.509 CRL from DER encoded data. """ diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 605af068d480..90957324c462 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -6,6 +6,7 @@ import collections import contextlib import itertools +import typing import warnings from contextlib import contextmanager @@ -18,6 +19,7 @@ encode_der, encode_der_integer, ) +from cryptography.hazmat._types import _PRIVATE_KEY_TYPES from cryptography.hazmat.backends.interfaces import Backend as BackendInterface from cryptography.hazmat.backends.openssl import aead from cryptography.hazmat.backends.openssl.ciphers import _CipherContext @@ -137,6 +139,7 @@ from cryptography.hazmat.primitives.kdf import scrypt from cryptography.hazmat.primitives.serialization import pkcs7, ssh from cryptography.x509 import ocsp +from cryptography.x509.name import Name _MemoryBIO = collections.namedtuple("_MemoryBIO", ["bio", "char_ptr"]) @@ -895,7 +898,12 @@ def _x509_check_signature_params(self, private_key, algorithm): "MD5 hash algorithm is only supported with RSA keys" ) - def create_x509_csr(self, builder, private_key, algorithm): + def create_x509_csr( + self, + builder: x509.CertificateSigningRequestBuilder, + private_key: _PRIVATE_KEY_TYPES, + algorithm: typing.Optional[hashes.HashAlgorithm], + ) -> _CertificateSigningRequest: if not isinstance(builder, x509.CertificateSigningRequestBuilder): raise TypeError("Builder type mismatch.") self._x509_check_signature_params(private_key, algorithm) @@ -920,7 +928,9 @@ def create_x509_csr(self, builder, private_key, algorithm): # Set subject public key. public_key = private_key.public_key() - res = self._lib.X509_REQ_set_pubkey(x509_req, public_key._evp_pkey) + res = self._lib.X509_REQ_set_pubkey( + x509_req, public_key._evp_pkey # type: ignore[union-attr] + ) self.openssl_assert(res == 1) # Add extensions. @@ -960,16 +970,25 @@ def create_x509_csr(self, builder, private_key, algorithm): self.openssl_assert(res == 1) # Sign the request using the requester's private key. - res = self._lib.X509_REQ_sign(x509_req, private_key._evp_pkey, evp_md) + res = self._lib.X509_REQ_sign( + x509_req, private_key._evp_pkey, evp_md # type: ignore[union-attr] + ) if res == 0: errors = self._consume_errors_with_text() raise ValueError("Signing failed", errors) return _CertificateSigningRequest(self, x509_req) - def create_x509_certificate(self, builder, private_key, algorithm): + def create_x509_certificate( + self, + builder: x509.CertificateBuilder, + private_key: _PRIVATE_KEY_TYPES, + algorithm: typing.Optional[hashes.HashAlgorithm], + ) -> _Certificate: if not isinstance(builder, x509.CertificateBuilder): raise TypeError("Builder type mismatch.") + if builder._public_key is None: + raise TypeError("Builder has no public key.") self._x509_check_signature_params(private_key, algorithm) # Resolve the signature algorithm. @@ -1027,7 +1046,11 @@ def create_x509_certificate(self, builder, private_key, algorithm): self.openssl_assert(res == 1) # Sign the certificate with the issuer's private key. - res = self._lib.X509_sign(x509_cert, private_key._evp_pkey, evp_md) + res = self._lib.X509_sign( + x509_cert, + private_key._evp_pkey, # type: ignore[union-attr] + evp_md, + ) if res == 0: errors = self._consume_errors_with_text() raise ValueError("Signing failed", errors) @@ -1058,7 +1081,12 @@ def _create_asn1_time(self, time): self._set_asn1_time(asn1_time, time) return asn1_time - def create_x509_crl(self, builder, private_key, algorithm): + def create_x509_crl( + self, + builder: x509.CertificateRevocationListBuilder, + private_key: _PRIVATE_KEY_TYPES, + algorithm: typing.Optional[hashes.HashAlgorithm], + ) -> _CertificateRevocationList: if not isinstance(builder, x509.CertificateRevocationListBuilder): raise TypeError("Builder type mismatch.") self._x509_check_signature_params(private_key, algorithm) @@ -1109,7 +1137,9 @@ def create_x509_crl(self, builder, private_key, algorithm): res = self._lib.X509_CRL_add0_revoked(x509_crl, revoked) self.openssl_assert(res == 1) - res = self._lib.X509_CRL_sign(x509_crl, private_key._evp_pkey, evp_md) + res = self._lib.X509_CRL_sign( + x509_crl, private_key._evp_pkey, evp_md # type: ignore[union-attr] + ) if res == 0: errors = self._consume_errors_with_text() raise ValueError("Signing failed", errors) @@ -1170,7 +1200,9 @@ def _create_x509_extension(self, handlers, extension): nid, 1 if extension.critical else 0, ext_struct ) - def create_x509_revoked_certificate(self, builder): + def create_x509_revoked_certificate( + self, builder: x509.RevokedCertificateBuilder + ) -> _RevokedCertificate: if not isinstance(builder, x509.RevokedCertificateBuilder): raise TypeError("Builder type mismatch.") @@ -1316,7 +1348,7 @@ def load_der_parameters(self, data): self._handle_key_loading_error() - def load_pem_x509_certificate(self, data): + def load_pem_x509_certificate(self, data: bytes) -> _Certificate: mem_bio = self._bytes_to_bio(data) x509 = self._lib.PEM_read_bio_X509( mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL @@ -1332,7 +1364,7 @@ def load_pem_x509_certificate(self, data): x509 = self._ffi.gc(x509, self._lib.X509_free) return _Certificate(self, x509) - def load_der_x509_certificate(self, data): + def load_der_x509_certificate(self, data: bytes) -> _Certificate: mem_bio = self._bytes_to_bio(data) x509 = self._lib.d2i_X509_bio(mem_bio.bio, self._ffi.NULL) if x509 == self._ffi.NULL: @@ -1342,7 +1374,7 @@ def load_der_x509_certificate(self, data): x509 = self._ffi.gc(x509, self._lib.X509_free) return _Certificate(self, x509) - def load_pem_x509_crl(self, data): + def load_pem_x509_crl(self, data: bytes) -> _CertificateRevocationList: mem_bio = self._bytes_to_bio(data) x509_crl = self._lib.PEM_read_bio_X509_CRL( mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL @@ -1358,7 +1390,7 @@ def load_pem_x509_crl(self, data): x509_crl = self._ffi.gc(x509_crl, self._lib.X509_CRL_free) return _CertificateRevocationList(self, x509_crl) - def load_der_x509_crl(self, data): + def load_der_x509_crl(self, data: bytes) -> _CertificateRevocationList: mem_bio = self._bytes_to_bio(data) x509_crl = self._lib.d2i_X509_CRL_bio(mem_bio.bio, self._ffi.NULL) if x509_crl == self._ffi.NULL: @@ -1368,7 +1400,7 @@ def load_der_x509_crl(self, data): x509_crl = self._ffi.gc(x509_crl, self._lib.X509_CRL_free) return _CertificateRevocationList(self, x509_crl) - def load_pem_x509_csr(self, data): + def load_pem_x509_csr(self, data: bytes) -> _CertificateSigningRequest: mem_bio = self._bytes_to_bio(data) x509_req = self._lib.PEM_read_bio_X509_REQ( mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL @@ -1384,7 +1416,7 @@ def load_pem_x509_csr(self, data): x509_req = self._ffi.gc(x509_req, self._lib.X509_REQ_free) return _CertificateSigningRequest(self, x509_req) - def load_der_x509_csr(self, data): + def load_der_x509_csr(self, data: bytes) -> _CertificateSigningRequest: mem_bio = self._bytes_to_bio(data) x509_req = self._lib.d2i_X509_REQ_bio(mem_bio.bio, self._ffi.NULL) if x509_req == self._ffi.NULL: @@ -2200,7 +2232,7 @@ def dh_parameters_supported(self, p, g, q=None): def dh_x942_serialization_supported(self): return self._lib.Cryptography_HAS_EVP_PKEY_DHX == 1 - def x509_name_bytes(self, name): + def x509_name_bytes(self, name: Name) -> bytes: x509_name = _encode_name_gc(self, name) pp = self._ffi.new("unsigned char **") res = self._lib.i2d_X509_NAME(x509_name, pp) diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index 07a1dd8a4722..ea938a272389 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -204,8 +204,7 @@ def extensions(self) -> x509.Extensions: ) -@utils.register_interface(x509.CertificateRevocationList) -class _CertificateRevocationList(object): +class _CertificateRevocationList(x509.CertificateRevocationList): def __init__(self, backend, x509_crl): self._backend = backend self._x509_crl = x509_crl @@ -385,8 +384,7 @@ def is_signature_valid(self, public_key: _PUBLIC_KEY_TYPES) -> bool: return True -@utils.register_interface(x509.CertificateSigningRequest) -class _CertificateSigningRequest(object): +class _CertificateSigningRequest(x509.CertificateSigningRequest): def __init__(self, backend, x509_req): self._backend = backend self._x509_req = x509_req diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index e6abadbd099e..a559998f1699 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -478,7 +478,20 @@ def test_requires_certificate_builder(self): with pytest.raises(TypeError): backend.create_x509_certificate( - object(), private_key, DummyHashAlgorithm() + object(), # type: ignore[arg-type] + private_key, + DummyHashAlgorithm(), + ) + + def test_builder_requires_public_key(self): + builder = x509.CertificateBuilder() + private_key = RSA_KEY_2048.private_key(backend) + + with pytest.raises(TypeError): + backend.create_x509_certificate( + builder, + private_key, + DummyHashAlgorithm(), ) @@ -488,7 +501,9 @@ def test_requires_csr_builder(self): with pytest.raises(TypeError): backend.create_x509_csr( - object(), private_key, DummyHashAlgorithm() + object(), # type: ignore[arg-type] + private_key, + DummyHashAlgorithm(), ) @@ -497,13 +512,19 @@ def test_invalid_builder(self): private_key = RSA_KEY_2048.private_key(backend) with pytest.raises(TypeError): - backend.create_x509_crl(object(), private_key, hashes.SHA256()) + backend.create_x509_crl( + object(), # type: ignore[arg-type] + private_key, + hashes.SHA256(), + ) class TestOpenSSLCreateRevokedCertificate(object): def test_invalid_builder(self): with pytest.raises(TypeError): - backend.create_x509_revoked_certificate(object()) + backend.create_x509_revoked_certificate( + object() # type: ignore[arg-type] + ) class TestOpenSSLSerializationWithOpenSSL(object): From bd2fb1f09c603ba14c0b86fd89e39c5d70a46aef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Mar 2021 08:13:06 -0400 Subject: [PATCH 0185/2380] Bump libc from 0.2.88 to 0.2.89 in /src/rust (#5917) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.88 to 0.2.89. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.88...0.2.89) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 7f59f413b425..fd579e99287e 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.88" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a" +checksum = "538c092e5586f4cdd7dd8078c4a79220e3e168880218124dcbce860f0ea938c6" [[package]] name = "lock_api" From a141ebe694497cb649e15bfaeadc02c782f7417e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Mar 2021 19:53:42 -0400 Subject: [PATCH 0186/2380] Bump libc from 0.2.89 to 0.2.90 in /src/rust (#5922) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.89 to 0.2.90. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.89...0.2.90) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index fd579e99287e..0a20349aeb47 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "538c092e5586f4cdd7dd8078c4a79220e3e168880218124dcbce860f0ea938c6" +checksum = "ba4aede83fc3617411dc6993bc8c70919750c1c257c6ca6a502aed6e0e2394ae" [[package]] name = "lock_api" From d95bf3277b893ce64b979ce8da83521aeb80fce0 Mon Sep 17 00:00:00 2001 From: Mathias Ertl Date: Sat, 20 Mar 2021 15:26:14 +0100 Subject: [PATCH 0187/2380] make get_extension_for_class a generic function (#5923) --- src/cryptography/x509/extensions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index d9443106fa0c..296de95d81b6 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -130,8 +130,8 @@ def get_extension_for_oid( raise ExtensionNotFound("No {} extension was found".format(oid), oid) def get_extension_for_class( - self, extclass: typing.Type[ExtensionType] - ) -> "Extension[ExtensionType]": + self, extclass: typing.Type[ExtensionTypeVar] + ) -> "Extension[ExtensionTypeVar]": if extclass is UnrecognizedExtension: raise TypeError( "UnrecognizedExtension can't be used with " From bd63f3a1a4bbb23fa4b8f9e2549d609317808b95 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 21 Mar 2021 19:05:37 -0500 Subject: [PATCH 0188/2380] document that we support more keys in our asymmetric loaders. (#5926) fixes #5911 --- .../primitives/asymmetric/serialization.rst | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst index 07a7456e4992..15dfbfcb6331 100644 --- a/docs/hazmat/primitives/asymmetric/serialization.rst +++ b/docs/hazmat/primitives/asymmetric/serialization.rst @@ -143,6 +143,10 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END :class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`. :returns: One of + :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey`, + :class:`~cryptography.hazmat.primitives.asymmetric.x25519.X25519PrivateKey`, + :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`, + :class:`~cryptography.hazmat.primitives.asymmetric.x448.X448PrivateKey`, :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`, :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`, :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`, @@ -182,6 +186,10 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END :returns: One of + :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey`, + :class:`~cryptography.hazmat.primitives.asymmetric.x25519.X25519PublicKey`, + :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey`, + :class:`~cryptography.hazmat.primitives.asymmetric.x448.X448PublicKey`, :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`, :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`, :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey`, @@ -252,6 +260,10 @@ the rest. :class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`. :returns: One of + :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey`, + :class:`~cryptography.hazmat.primitives.asymmetric.x25519.X25519PrivateKey`, + :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`, + :class:`~cryptography.hazmat.primitives.asymmetric.x448.X448PrivateKey`, :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`, :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`, :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`, @@ -291,6 +303,10 @@ the rest. :class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`. :returns: One of + :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey`, + :class:`~cryptography.hazmat.primitives.asymmetric.x25519.X25519PublicKey`, + :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey`, + :class:`~cryptography.hazmat.primitives.asymmetric.x448.X448PublicKey`, :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`, :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`, :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey`, From 6f7a5fd9e9c133273063227e3ad80232899b4ca3 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 21 Mar 2021 19:05:57 -0500 Subject: [PATCH 0189/2380] properly document the return of load_ssh_private_key (#5927) fixes #5862 --- docs/hazmat/primitives/asymmetric/serialization.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst index 15dfbfcb6331..b23e7524db06 100644 --- a/docs/hazmat/primitives/asymmetric/serialization.rst +++ b/docs/hazmat/primitives/asymmetric/serialization.rst @@ -448,11 +448,11 @@ An example ECDSA key in OpenSSH format:: depending on the key's type. :returns: One of - :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`, - :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`, - :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey` + :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`, + :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`, + :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey` or - :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey`, + :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey`, depending on the contents of ``data``. :raises ValueError: If the OpenSSH data could not be properly decoded, From 3005e107a83b8fc22f3d2ee2caab72351bce0d7b Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 21 Mar 2021 19:14:00 -0500 Subject: [PATCH 0190/2380] fix XTS less than one block length. fixes #5885 (#5925) * fix XTS less than one block length. fixes #5885 * make XTS test key happy --- src/cryptography/hazmat/backends/openssl/ciphers.py | 8 +++++++- tests/hazmat/primitives/test_aes.py | 8 ++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py index 0f96795fdc73..50cbeb69a680 100644 --- a/src/cryptography/hazmat/backends/openssl/ciphers.py +++ b/src/cryptography/hazmat/backends/openssl/ciphers.py @@ -145,7 +145,13 @@ def update_into(self, data: bytes, buf) -> int: res = self._backend._lib.EVP_CipherUpdate( self._ctx, outbuf, outlen, inbuf, inlen ) - self._backend.openssl_assert(res != 0) + if res == 0 and isinstance(self._mode, modes.XTS): + raise ValueError( + "In XTS mode you must supply at least a full block in the " + "first update call. For AES this is 16 bytes." + ) + else: + self._backend.openssl_assert(res != 0) data_processed += inlen total_out += outlen[0] diff --git a/tests/hazmat/primitives/test_aes.py b/tests/hazmat/primitives/test_aes.py index 29a9404633fb..fd37b7696d96 100644 --- a/tests/hazmat/primitives/test_aes.py +++ b/tests/hazmat/primitives/test_aes.py @@ -52,6 +52,14 @@ def test_xts_vectors(self, backend, subtests): computed_pt = dec.update(ct) + dec.finalize() assert computed_pt == pt + def test_xts_too_short(self): + key = b"thirty_two_byte_keys_are_great!!" + tweak = b"\x00" * 16 + cipher = base.Cipher(algorithms.AES(key), modes.XTS(tweak)) + enc = cipher.encryptor() + with pytest.raises(ValueError): + enc.update(b"0" * 15) + @pytest.mark.supported( only_if=lambda backend: backend.cipher_supported( From 0ce239be02693fd80e9e6ed0e68c90e180915afe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Mar 2021 07:48:49 -0400 Subject: [PATCH 0191/2380] Bump ctor from 0.1.19 to 0.1.20 in /src/rust (#5930) Bumps [ctor](https://github.com/mmastrac/rust-ctor) from 0.1.19 to 0.1.20. - [Release notes](https://github.com/mmastrac/rust-ctor/releases) - [Commits](https://github.com/mmastrac/rust-ctor/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 0a20349aeb47..b691e86fc567 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -21,9 +21,9 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8f45d9ad417bcef4817d614a501ab55cdd96a6fdb24f49aab89a54acfd66b19" +checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d" dependencies = [ "quote", "syn", From fe5cb7551e989286daa1413e9f8d39c2402b8ec1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Mar 2021 08:39:39 -0400 Subject: [PATCH 0192/2380] Bump libc from 0.2.90 to 0.2.91 in /src/rust (#5929) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.90 to 0.2.91. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.90...0.2.91) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index b691e86fc567..40bcc7f2b983 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4aede83fc3617411dc6993bc8c70919750c1c257c6ca6a502aed6e0e2394ae" +checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7" [[package]] name = "lock_api" From 1bb7effbf70c55663c556ff497bf774984f07de8 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 25 Mar 2021 23:23:48 -0400 Subject: [PATCH 0193/2380] Backport the 3.4.7 changelog (#5934) --- CHANGELOG.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f2aaebb5c27a..a45502685bf5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,6 +14,14 @@ Changelog when using OpenSSL 1.1.1. These algorithms are provided for compatibility in regions where they may be required, and are not generally recommended. +.. _v3-4-7: + +3.4.7 - 2021-03-25 +~~~~~~~~~~~~~~~~~~ + +* Updated Windows, macOS, and ``manylinux`` wheels to be compiled with + OpenSSL 1.1.1k. + .. _v3-4-6: 3.4.6 - 2021-02-16 From 40b2ca7c4251b9fc90e9f7a50bf4abba9c9053cc Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 26 Mar 2021 13:35:13 -0400 Subject: [PATCH 0194/2380] bump to latest liberssl (#5937) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e68f089a73af..eb7f6ab658c0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "2.9.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.0.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.1.5"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.2.4"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.2.5"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.3.1"}} RUST: - stable From e6f5871ed9882b5567bc820f81d0578fdc4731c8 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 30 Mar 2021 20:45:58 -0400 Subject: [PATCH 0195/2380] Attempt to fix the cargo cache (#5942) --- .github/workflows/ci.yml | 7 +++++++ tox.ini | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eb7f6ab658c0..19486321457a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -90,6 +90,7 @@ jobs: tox -r -- --color=yes --wycheproof-root=wycheproof env: TOXENV: ${{ matrix.PYTHON.TOXENV }} + CARGO_TARGET_DIR: ${{ format('{0}/src/rust/target/', github.workspace) }} - uses: ./.github/actions/upload-coverage with: name: "tox -e ${{ matrix.PYTHON.TOXENV }} ${{ env.OSSL_INFO }}" @@ -133,6 +134,7 @@ jobs: env: TOXENV: ${{ matrix.IMAGE.TOXENV }} RUSTUP_HOME: /root/.rustup + CARGO_TARGET_DIR: ${{ format('{0}/src/rust/target/', github.workspace) }} - uses: ./.github/actions/upload-coverage with: name: "${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" @@ -178,6 +180,7 @@ jobs: tox -r -- --color=yes --wycheproof-root=wycheproof env: TOXENV: ${{ matrix.PYTHON.TOXENV }} + CARGO_TARGET_DIR: ${{ format('{0}/src/rust/target/', github.workspace) }} - uses: ./.github/actions/upload-coverage with: name: "${{ matrix.PYTHON.TOXENV }} with Rust ${{ matrix.RUST }}" @@ -232,6 +235,7 @@ jobs: env: TOXENV: ${{ matrix.PYTHON.TOXENV }} EXTRA_CFLAGS: ${{ matrix.PYTHON.EXTRA_CFLAGS }} + CARGO_TARGET_DIR: ${{ format('{0}/src/rust/target/', github.workspace) }} - uses: ./.github/actions/upload-coverage with: @@ -290,6 +294,7 @@ jobs: - run: tox -r -- --color=yes --wycheproof-root=wycheproof --num-shards=4 --shard-id=${{ matrix.JOB_NUMBER }} env: TOXENV: ${{ matrix.PYTHON.TOXENV }} + CARGO_TARGET_DIR: ${{ format('{0}/src/rust/target/', github.workspace) }} - uses: ./.github/actions/upload-coverage with: @@ -337,6 +342,8 @@ jobs: - run: ./.github/downstream.d/${{ matrix.DOWNSTREAM }}.sh install - run: pip uninstall -y enum34 - run: pip install . + env: + CARGO_TARGET_DIR: ${{ format('{0}/src/rust/target/', github.workspace) }} - run: ./.github/downstream.d/${{ matrix.DOWNSTREAM }}.sh run docs-linkcheck: diff --git a/tox.ini b/tox.ini index bdc4da283493..cccbf65efc73 100644 --- a/tox.ini +++ b/tox.ini @@ -8,7 +8,7 @@ extras = test ssh: ssh deps = - ./vectors + -e ./vectors pytest-shard>=0.1.2 randomorder: pytest-randomly passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH USERNAME PYTHONIOENCODING OPENSSL_FORCE_FIPS_MODE From a9de28df8c70be4b145f10ed9fa382dddecbf10a Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 30 Mar 2021 22:38:13 -0400 Subject: [PATCH 0196/2380] passenv CARGO_TARGET_DIR (#5943) --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index cccbf65efc73..6fccaed6be3d 100644 --- a/tox.ini +++ b/tox.ini @@ -11,7 +11,7 @@ deps = -e ./vectors pytest-shard>=0.1.2 randomorder: pytest-randomly -passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH USERNAME PYTHONIOENCODING OPENSSL_FORCE_FIPS_MODE +passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH USERNAME PYTHONIOENCODING CARGO_TARGET_DIR OPENSSL_FORCE_FIPS_MODE commands = pip list pytest -n auto --cov=cryptography --cov=tests --capture=no --strict-markers --durations=10 {posargs} From 395fce1704649a436152d50ba5f3dec49565d321 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Mar 2021 22:43:36 -0400 Subject: [PATCH 0197/2380] Bump syn from 1.0.64 to 1.0.67 in /src/rust (#5940) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.64 to 1.0.67. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.64...1.0.67) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 40bcc7f2b983..59992d167847 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -239,9 +239,9 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "syn" -version = "1.0.64" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f" +checksum = "6498a9efc342871f91cc2d0d694c674368b4ceb40f62b65a7a08c3792935e702" dependencies = [ "proc-macro2", "quote", From 2e4777b6d3a4fedbb339458fffa0622213688d5a Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 30 Mar 2021 23:43:52 -0400 Subject: [PATCH 0198/2380] dont reuse caches across different builds (#5945) --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 19486321457a..07de77115408 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,7 +39,7 @@ jobs: ~/.cargo/registry ~/.cargo/git src/rust/target/ - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + key: ${{ runner.os }}-${{ matrix.PYTHON.VERSION }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Setup python uses: actions/setup-python@v2.2.1 @@ -123,7 +123,7 @@ jobs: ~/.cargo/registry ~/.cargo/git src/rust/target/ - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + key: ${{ runner.os }}-${{ matrix.IMAGE.IMAGE }}-cargo-${{ hashFiles('**/Cargo.lock') }} - run: 'git clone --depth=1 https://github.com/google/wycheproof "$HOME/wycheproof"' - run: | @@ -204,7 +204,7 @@ jobs: ~/.cargo/registry ~/.cargo/git src/rust/target/ - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + key: ${{ runner.os }}-${{ matrix.PYTHON.VERSION }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Setup python uses: actions/setup-python@v2.2.1 @@ -264,7 +264,7 @@ jobs: ~/.cargo/registry ~/.cargo/git src/rust/target/ - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + key: ${{ runner.os }}-${{ matrix.WINDOWS.ARCH }}-${{ matrix.PYTHON.VERSION }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Setup python uses: actions/setup-python@v2.2.1 From dd63aca1ae8360429e5923bde7e60374c01e233e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 31 Mar 2021 01:02:24 -0400 Subject: [PATCH 0199/2380] Disable coverage on pypy again (#5944) --- .github/workflows/ci.yml | 4 ++-- tox.ini | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 07de77115408..a6f6ef65ff53 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,8 +16,8 @@ jobs: matrix: PYTHON: - {VERSION: "3.9", TOXENV: "flake,rust,docs", COVERAGE: "false"} - - {VERSION: "pypy-3.6", TOXENV: "pypy3"} - - {VERSION: "pypy-3.7", TOXENV: "pypy3"} + - {VERSION: "pypy-3.6", TOXENV: "pypy3-nocoverage"} + - {VERSION: "pypy-3.7", TOXENV: "pypy3-nocoverage"} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1j"}} - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1j"}} diff --git a/tox.ini b/tox.ini index 6fccaed6be3d..cf01d69de382 100644 --- a/tox.ini +++ b/tox.ini @@ -16,6 +16,14 @@ commands = pip list pytest -n auto --cov=cryptography --cov=tests --capture=no --strict-markers --durations=10 {posargs} +# This target disables coverage on pypy because of performance problems with +# coverage.py on pypy. +[testenv:pypy3-nocoverage] +basepython = pypy3 +commands = + pip list + pytest -n auto --capture=no --strict-markers --durations=10 {posargs} + [testenv:docs] extras = docs From f0b2269f7221f06aacf883b58577ffc9627e7522 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 31 Mar 2021 08:10:09 -0400 Subject: [PATCH 0200/2380] Bump libc from 0.2.91 to 0.2.92 in /src/rust (#5946) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.91 to 0.2.92. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.91...0.2.92) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 59992d167847..5a523c937f5f 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7" +checksum = "56d855069fafbb9b344c0f962150cd2c1187975cb1c22c1522c240d8c4986714" [[package]] name = "lock_api" From 2839b4b6a2e6c98023748ebccf58649afe6038e4 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Sun, 4 Apr 2021 00:02:22 +0100 Subject: [PATCH 0201/2380] Update annotation for key (#5951) * Update annotation for key * Update fernet.py * Update fernet.py --- src/cryptography/fernet.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cryptography/fernet.py b/src/cryptography/fernet.py index bcf1c9848c6e..64c12c69a84d 100644 --- a/src/cryptography/fernet.py +++ b/src/cryptography/fernet.py @@ -27,7 +27,11 @@ class InvalidToken(Exception): class Fernet(object): - def __init__(self, key: bytes, backend: typing.Optional[Backend] = None): + def __init__( + self, + key: typing.Union[bytes, str], + backend: typing.Optional[Backend] = None, + ): backend = _get_backend(backend) key = base64.urlsafe_b64decode(key) From 451dcce7fd98c9638247aeb131f186631b4281b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 3 Apr 2021 19:02:45 -0400 Subject: [PATCH 0202/2380] Bump syn from 1.0.67 to 1.0.68 in /src/rust (#5949) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.67 to 1.0.68. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.67...1.0.68) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 5a523c937f5f..8efa08ef8956 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -161,9 +161,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.24" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" dependencies = [ "unicode-xid", ] @@ -239,9 +239,9 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "syn" -version = "1.0.67" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6498a9efc342871f91cc2d0d694c674368b4ceb40f62b65a7a08c3792935e702" +checksum = "3ce15dd3ed8aa2f8eeac4716d6ef5ab58b6b9256db41d7e1a0224c2788e8fd87" dependencies = [ "proc-macro2", "quote", From 18bfc45d7150d804eb8fdc57c7f3d93fd09292d1 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 3 Apr 2021 19:15:32 -0400 Subject: [PATCH 0203/2380] Build manylinux_2_24 wheels (#5952) * Build manylinux_2_24 wheels * poke GHA * poke GHA * fix * poke GHA * fix --- .github/workflows/wheel-builder.yml | 1 + .zuul.d/jobs.yaml | 8 ++++++++ .../roles/build-wheel-manylinux/files/build-wheels.sh | 2 +- CHANGELOG.rst | 2 ++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 090a70d526a9..271bd4de46e2 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -18,6 +18,7 @@ jobs: MANYLINUX: - { NAME: "manylinux2010_x86_64", CONTAINER: "cryptography-manylinux2010:x86_64" } - { NAME: "manylinux2014_x86_64", CONTAINER: "cryptography-manylinux2014:x86_64" } + - { name: "manylinux_2_24_x86_64", CONTAINER: "cryptography-manylinux_2_24:x86_64"} name: "${{ matrix.PYTHON.VERSION }} for ${{ matrix.MANYLINUX.NAME }}" steps: - run: ${{ matrix.PYTHON.PATH }} -m venv .venv diff --git a/.zuul.d/jobs.yaml b/.zuul.d/jobs.yaml index 0a0982bab4bd..e9e1561c6fc4 100644 --- a/.zuul.d/jobs.yaml +++ b/.zuul.d/jobs.yaml @@ -42,6 +42,10 @@ image: ghcr.io/pyca/cryptography-manylinux2014_aarch64 pythons: - cp36-cp36m + - platform: manylinux_2_24_aarch64 + image: ghcr.io/pyca/cryptography-manylinux_2_24:aarch64 + pythons: + - cp36-cp36m - job: name: pyca-cryptography-build-wheel-x86_64 @@ -57,3 +61,7 @@ image: ghcr.io/pyca/cryptography-manylinux2014:x86_64 pythons: - cp36-cp36m + - platform: manylinux_2_24_x86_64 + image: ghcr.io/pyca/cryptography-manylinux_2_24:x86_64 + pythons: + - cp36-cp36m diff --git a/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/files/build-wheels.sh b/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/files/build-wheels.sh index d28ff4e7961a..41cd6bcaedf9 100644 --- a/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/files/build-wheels.sh +++ b/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/files/build-wheels.sh @@ -28,7 +28,7 @@ for P in ${PYTHONS}; do # NOTE(ianw) : no execstack on aarch64, comes from # prelink, which was never supported. CentOS 8 does # have it separate, skip for now. - if [[ "${PLAT}" != "manylinux2014_aarch64" ]]; then + if [[ ! "${PLAT}" =~ "aarch64" ]]; then for f in wheelhouse/*.whl; do unzip $f -d execstack.check diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a45502685bf5..2d9e6520697b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -13,6 +13,8 @@ Changelog :class:`~cryptography.hazmat.primitives.ciphers.algorithms.SM4`, when using OpenSSL 1.1.1. These algorithms are provided for compatibility in regions where they may be required, and are not generally recommended. +* We now ship ``manylinux_2_24`` wheels, in addition to our ``manylinux2010`` + and ``manylinux2014`` wheels. .. _v3-4-7: From 16a3227ccd76617e66f673c1c5acefcca5174ee5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Apr 2021 08:26:14 -0400 Subject: [PATCH 0204/2380] Bump lock_api from 0.4.2 to 0.4.3 in /src/rust (#5953) Bumps [lock_api](https://github.com/Amanieu/parking_lot) from 0.4.2 to 0.4.3. - [Release notes](https://github.com/Amanieu/parking_lot/releases) - [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md) - [Commits](https://github.com/Amanieu/parking_lot/compare/lock_api-0.4.2...lock_api-0.4.3) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 8efa08ef8956..a0043367b25f 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -102,9 +102,9 @@ checksum = "56d855069fafbb9b344c0f962150cd2c1187975cb1c22c1522c240d8c4986714" [[package]] name = "lock_api" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" +checksum = "5a3c91c24eae6777794bb1997ad98bbb87daf92890acab859f7eaa4320333176" dependencies = [ "scopeguard", ] From fb2246ed00a1f099036c96f6951369ff7e404825 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Apr 2021 08:04:04 -0400 Subject: [PATCH 0205/2380] Bump libc from 0.2.92 to 0.2.93 in /src/rust (#5955) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.92 to 0.2.93. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.92...0.2.93) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index a0043367b25f..6893477010bd 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56d855069fafbb9b344c0f962150cd2c1187975cb1c22c1522c240d8c4986714" +checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41" [[package]] name = "lock_api" From cac146f62aa92ea2ca137d3682d63624b35b6629 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 7 Apr 2021 11:43:14 -0400 Subject: [PATCH 0206/2380] Comment out centos arm64 builders so long as they're broken (#5956) --- .zuul.d/project.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.zuul.d/project.yaml b/.zuul.d/project.yaml index b05d6b56f164..6358bc344699 100644 --- a/.zuul.d/project.yaml +++ b/.zuul.d/project.yaml @@ -5,7 +5,8 @@ - pyca-cryptography-build-wheel-x86_64 - pyca-cryptography-ubuntu-focal-py38-arm64 - pyca-cryptography-ubuntu-bionic-py36-arm64 - - pyca-cryptography-centos-8-py36-arm64 + # Commented out because these builders currently do not boot + # - pyca-cryptography-centos-8-py36-arm64 release: jobs: - pyca-cryptography-build-wheel-arm64 From 58f0ad5b6b928677931c7ad44deee839a29ee9d3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Apr 2021 07:58:46 -0400 Subject: [PATCH 0207/2380] Bump syn from 1.0.68 to 1.0.69 in /src/rust (#5957) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.68 to 1.0.69. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.68...1.0.69) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 6893477010bd..2bd1b9f4639d 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -239,9 +239,9 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "syn" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ce15dd3ed8aa2f8eeac4716d6ef5ab58b6b9256db41d7e1a0224c2788e8fd87" +checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb" dependencies = [ "proc-macro2", "quote", From 19b96a04eb60d23e77824610b3237e9db22b0c06 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 9 Apr 2021 13:57:38 -0400 Subject: [PATCH 0208/2380] re-enable arm64 on centos (#5961) --- .zuul.d/project.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.zuul.d/project.yaml b/.zuul.d/project.yaml index 6358bc344699..b05d6b56f164 100644 --- a/.zuul.d/project.yaml +++ b/.zuul.d/project.yaml @@ -5,8 +5,7 @@ - pyca-cryptography-build-wheel-x86_64 - pyca-cryptography-ubuntu-focal-py38-arm64 - pyca-cryptography-ubuntu-bionic-py36-arm64 - # Commented out because these builders currently do not boot - # - pyca-cryptography-centos-8-py36-arm64 + - pyca-cryptography-centos-8-py36-arm64 release: jobs: - pyca-cryptography-build-wheel-arm64 From 851877e3e8dd7e6b6035c2e02d80690c4c8b9cf6 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 9 Apr 2021 15:57:06 -0400 Subject: [PATCH 0209/2380] pin to 3.9.2 due to bugs (#5962) https://github.com/actions/setup-python/issues/202 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a6f6ef65ff53..113e46d9d801 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -250,7 +250,7 @@ jobs: - {ARCH: 'x64', WINDOWS: 'win64', RUST_TRIPLE: 'x86_64-pc-windows-msvc'} PYTHON: - {VERSION: "3.6", TOXENV: "py36", MSVC_VERSION: "2019", CL_FLAGS: ""} - - {VERSION: "3.9", TOXENV: "py39", MSVC_VERSION: "2019", CL_FLAGS: "/D USE_OSRANDOM_RNG_FOR_TESTING"} + - {VERSION: "3.9.2", TOXENV: "py39", MSVC_VERSION: "2019", CL_FLAGS: "/D USE_OSRANDOM_RNG_FOR_TESTING"} RUST: - stable JOB_NUMBER: [0, 1, 2, 3] From ead82753899c4ad1d4096d718d65d4df64836ddd Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 11 Apr 2021 16:44:27 -0400 Subject: [PATCH 0210/2380] Port a tiny tiny bit of the ASN.1 parsing to Rust (#5357) --- .../hazmat/backends/openssl/decode_asn1.py | 23 ++---- src/rust/Cargo.lock | 47 ++++++++++++ src/rust/Cargo.toml | 1 + src/rust/src/asn1.rs | 75 +++++++++++++++++++ src/rust/src/lib.rs | 6 +- 5 files changed, 135 insertions(+), 17 deletions(-) create mode 100644 src/rust/src/asn1.rs diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index e62c25406b39..6e4dc0e939d1 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -8,8 +8,7 @@ import typing from cryptography import x509 -from cryptography.hazmat._der import DERReader, INTEGER, NULL, SEQUENCE -from cryptography.x509.extensions import _TLS_FEATURE_TYPE_TO_ENUM +from cryptography.hazmat.bindings._rust import asn1 from cryptography.x509.name import _ASN1_TYPE_TO_ENUM from cryptography.x509.oid import ( CRLEntryExtensionOID, @@ -211,25 +210,17 @@ def parse(self, x509_obj): # The extension contents are a SEQUENCE OF INTEGERs. data = self._backend._lib.X509_EXTENSION_get_data(ext) data_bytes = _asn1_string_to_bytes(self._backend, data) - features = DERReader(data_bytes).read_single_element(SEQUENCE) - parsed = [] - while not features.is_empty(): - parsed.append(features.read_element(INTEGER).as_integer()) - # Map the features to their enum value. - value = x509.TLSFeature( - [_TLS_FEATURE_TYPE_TO_ENUM[x] for x in parsed] - ) + value = asn1.parse_tls_feature(data_bytes) + extensions.append(x509.Extension(oid, critical, value)) seen_oids.add(oid) continue elif oid == ExtensionOID.PRECERT_POISON: data = self._backend._lib.X509_EXTENSION_get_data(ext) - # The contents of the extension must be an ASN.1 NULL. - reader = DERReader(_asn1_string_to_bytes(self._backend, data)) - reader.read_single_element(NULL).check_empty() - extensions.append( - x509.Extension(oid, critical, x509.PrecertPoison()) - ) + data_bytes = _asn1_string_to_bytes(self._backend, data) + value = asn1.parse_precert_poison(data_bytes) + + extensions.append(x509.Extension(oid, critical, value)) seen_oids.add(oid) continue diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 2bd1b9f4639d..8cd155ba8fbc 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -1,5 +1,22 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + +[[package]] +name = "asn1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d2efbfc907088c522a054db6e60277d3f3bf0cf73cd3e2676806f4d95f3b20" +dependencies = [ + "chrono", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + [[package]] name = "bitflags" version = "1.2.1" @@ -12,10 +29,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "num-integer", + "num-traits", +] + [[package]] name = "cryptography-rust" version = "0.1.0" dependencies = [ + "asn1", "pyo3", ] @@ -109,6 +137,25 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + [[package]] name = "parking_lot" version = "0.11.1" diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index bcb9add10020..b0dbc6f119f8 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -7,6 +7,7 @@ publish = false [dependencies] pyo3 = { version = "0.13.1", features = ["extension-module"] } +asn1 = { version = "0.3", default-features = false } [lib] name = "cryptography_rust" diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs new file mode 100644 index 000000000000..a2db23e12328 --- /dev/null +++ b/src/rust/src/asn1.rs @@ -0,0 +1,75 @@ +// 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. + +use pyo3::conversion::ToPyObject; + +enum PyAsn1Error { + Asn1(asn1::ParseError), + Py(pyo3::PyErr), +} + +impl From for PyAsn1Error { + fn from(e: asn1::ParseError) -> PyAsn1Error { + PyAsn1Error::Asn1(e) + } +} + +impl From for PyAsn1Error { + fn from(e: pyo3::PyErr) -> PyAsn1Error { + PyAsn1Error::Py(e) + } +} + +impl From for pyo3::PyErr { + fn from(e: PyAsn1Error) -> pyo3::PyErr { + match e { + PyAsn1Error::Asn1(asn1_error) => pyo3::exceptions::PyValueError::new_err(format!( + "error parsing asn1 value: {:?}", + asn1_error + )), + PyAsn1Error::Py(py_error) => py_error, + } + } +} + +#[pyo3::prelude::pyfunction] +fn parse_tls_feature(py: pyo3::Python<'_>, data: &[u8]) -> pyo3::PyResult { + let tls_feature_type_to_enum = py + .import("cryptography.x509.extensions")? + .getattr("_TLS_FEATURE_TYPE_TO_ENUM")?; + + let features = asn1::parse::<_, PyAsn1Error, _>(data, |p| { + let features = pyo3::types::PyList::empty(py); + for el in p.read_element::>()? { + let feature = el?; + let py_feature = tls_feature_type_to_enum.get_item(feature.to_object(py))?; + features.append(py_feature)?; + } + Ok(features) + })?; + + let x509_module = py.import("cryptography.x509")?; + x509_module + .call1("TLSFeature", (features,)) + .map(|o| o.to_object(py)) +} + +#[pyo3::prelude::pyfunction] +fn parse_precert_poison(py: pyo3::Python<'_>, data: &[u8]) -> pyo3::PyResult { + asn1::parse::<_, PyAsn1Error, _>(data, |p| { + p.read_element::<()>()?; + Ok(()) + })?; + + let x509_module = py.import("cryptography.x509")?; + x509_module.call0("PrecertPoison").map(|o| o.to_object(py)) +} + +pub(crate) fn create_submodule(py: pyo3::Python) -> pyo3::PyResult<&pyo3::prelude::PyModule> { + let submod = pyo3::prelude::PyModule::new(py, "asn1")?; + submod.add_wrapped(pyo3::wrap_pyfunction!(parse_tls_feature))?; + submod.add_wrapped(pyo3::wrap_pyfunction!(parse_precert_poison))?; + + Ok(submod) +} diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs index 3257b35e123f..a3b3fb715141 100644 --- a/src/rust/src/lib.rs +++ b/src/rust/src/lib.rs @@ -2,6 +2,8 @@ // 2.0, and the BSD License. See the LICENSE file in the root of this repository // for complete details. +mod asn1; + use std::convert::TryInto; /// Returns the value of the input with the most-significant-bit copied to all @@ -66,10 +68,12 @@ fn check_ansix923_padding(data: &[u8]) -> bool { } #[pyo3::prelude::pymodule] -fn _rust(_py: pyo3::Python<'_>, m: &pyo3::types::PyModule) -> pyo3::PyResult<()> { +fn _rust(py: pyo3::Python<'_>, m: &pyo3::types::PyModule) -> pyo3::PyResult<()> { m.add_function(pyo3::wrap_pyfunction!(check_pkcs7_padding, m)?)?; m.add_function(pyo3::wrap_pyfunction!(check_ansix923_padding, m)?)?; + m.add_submodule(asn1::create_submodule(py)?)?; + Ok(()) } From bc8df094247f703701667263818b3d57e77b6848 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 11 Apr 2021 23:43:58 -0400 Subject: [PATCH 0211/2380] Converted DER parsing of SPKIs to rust (#5963) --- src/cryptography/x509/extensions.py | 27 ++------------------------ src/rust/Cargo.lock | 4 ++-- src/rust/Cargo.toml | 2 +- src/rust/src/asn1.rs | 30 +++++++++++++++++++++++++++++ 4 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index 296de95d81b6..fb229d395070 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -10,13 +10,8 @@ import typing from enum import Enum -from cryptography.hazmat._der import ( - BIT_STRING, - DERReader, - OBJECT_IDENTIFIER, - SEQUENCE, -) from cryptography.hazmat._types import _PUBLIC_KEY_TYPES +from cryptography.hazmat.bindings._rust import asn1 from cryptography.hazmat.primitives import constant_time, serialization from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey @@ -62,25 +57,7 @@ def _key_identifier_from_public_key(public_key: _PUBLIC_KEY_TYPES) -> bytes: serialization.Encoding.DER, serialization.PublicFormat.SubjectPublicKeyInfo, ) - - reader = DERReader(serialized) - with reader.read_single_element(SEQUENCE) as public_key_info: - algorithm = public_key_info.read_element(SEQUENCE) - public_key_data = public_key_info.read_element(BIT_STRING) - - # Double-check the algorithm structure. - with algorithm: - algorithm.read_element(OBJECT_IDENTIFIER) - if not algorithm.is_empty(): - # Skip the optional parameters field. - algorithm.read_any_element() - - # BIT STRING contents begin with the number of padding bytes added. It - # must be zero for SubjectPublicKeyInfo structures. - if public_key_data.read_byte() != 0: - raise ValueError("Invalid public key encoding") - - data = public_key_data.data + data = asn1.parse_spki_for_data(serialized) return hashlib.sha1(data).digest() diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 8cd155ba8fbc..adb82e4e45e4 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "asn1" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d2efbfc907088c522a054db6e60277d3f3bf0cf73cd3e2676806f4d95f3b20" +checksum = "698c3b9621a1a2f9c98fceabba22e495a5f2604e773ec5fbd8a42cd797aa6d24" dependencies = [ "chrono", ] diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index b0dbc6f119f8..6d2a1e199c18 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] pyo3 = { version = "0.13.1", features = ["extension-module"] } -asn1 = { version = "0.3", default-features = false } +asn1 = { version = "0.3.1", default-features = false } [lib] name = "cryptography_rust" diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs index a2db23e12328..a5a9a856f092 100644 --- a/src/rust/src/asn1.rs +++ b/src/rust/src/asn1.rs @@ -66,10 +66,40 @@ fn parse_precert_poison(py: pyo3::Python<'_>, data: &[u8]) -> pyo3::PyResult, data: &[u8]) -> pyo3::PyResult { + let result = asn1::parse::<_, PyAsn1Error, _>(data, |p| { + p.read_element::()? + .parse::<_, PyAsn1Error, _>(|p| { + // AlgorithmIdentifier + p.read_element::()? + .parse::<_, PyAsn1Error, _>(|p| { + p.read_element::()?; + if !p.is_empty() { + p.read_element::()?; + } + Ok(()) + })?; + + let pubkey_data = p.read_element::()?; + if pubkey_data.padding_bits() != 0 { + return Err(pyo3::exceptions::PyValueError::new_err( + "Invalid public key encoding", + ) + .into()); + } + Ok(pubkey_data.as_bytes()) + }) + })?; + + Ok(pyo3::types::PyBytes::new(py, result).to_object(py)) +} + pub(crate) fn create_submodule(py: pyo3::Python) -> pyo3::PyResult<&pyo3::prelude::PyModule> { let submod = pyo3::prelude::PyModule::new(py, "asn1")?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_tls_feature))?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_precert_poison))?; + submod.add_wrapped(pyo3::wrap_pyfunction!(parse_spki_for_data))?; Ok(submod) } From 39966b2a22d3fcddb5c464baff19b11daf67ebdc Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Mon, 12 Apr 2021 17:33:40 +0200 Subject: [PATCH 0212/2380] Set `dirhtml` builder explicitly in the RTD config (#5964) After introducing the `.readthedocs.yml` config in the repo, it started overriding all of the settings set via the RTD UI unintentionally switching the URL scheme. This change reverts that switch resurrecting the old one. Fixes #5863 Refs: * https://github.com/pyca/cryptography/issues/5863#issuecomment-817828152 --- .readthedocs.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.readthedocs.yml b/.readthedocs.yml index ac4882422355..04d5d1a444d8 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -1,5 +1,10 @@ version: 2 +sphinx: + # The config file overrides the UI settings: + # https://github.com/pyca/cryptography/issues/5863#issuecomment-817828152 + builder: dirhtml + build: # First RTD build env which includes a rust toolchain image: "7.0" From 89679f64104f309938594e601dad9cf8e0930fc9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Apr 2021 07:45:25 -0400 Subject: [PATCH 0213/2380] Bump actions/cache from v2.1.4 to v2.1.5 (#5967) Bumps [actions/cache](https://github.com/actions/cache) from v2.1.4 to v2.1.5. - [Release notes](https://github.com/actions/cache/releases) - [Commits](https://github.com/actions/cache/compare/v2.1.4...1a9e2138d905efd099035b49d8b7a3888c653ca8) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 113e46d9d801..f9fe126cf41f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v2 - - uses: actions/cache@v2.1.4 + - uses: actions/cache@v2.1.5 with: path: | ~/.cargo/registry @@ -66,7 +66,7 @@ jobs: CONFIG_FLAGS: ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }} if: matrix.PYTHON.OPENSSL - name: Load cache - uses: actions/cache@v2.1.4 + uses: actions/cache@v2.1.5 id: ossl-cache with: path: ${{ github.workspace }}/osslcache @@ -117,7 +117,7 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v2 - - uses: actions/cache@v2.1.4 + - uses: actions/cache@v2.1.5 with: path: | ~/.cargo/registry @@ -155,7 +155,7 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v2 - - uses: actions/cache@v2.1.4 + - uses: actions/cache@v2.1.5 with: path: | ~/.cargo/registry @@ -198,7 +198,7 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v2 - - uses: actions/cache@v2.1.4 + - uses: actions/cache@v2.1.5 with: path: | ~/.cargo/registry @@ -258,7 +258,7 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v2 - - uses: actions/cache@v2.1.4 + - uses: actions/cache@v2.1.5 with: path: | ~/.cargo/registry @@ -320,7 +320,7 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v2 - - uses: actions/cache@v2.1.4 + - uses: actions/cache@v2.1.5 with: path: | ~/.cargo/registry From c5acddf1d4020073d0b0560991314d1b6d83ba80 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Apr 2021 07:46:43 -0400 Subject: [PATCH 0214/2380] Bump actions/setup-python from v2.2.1 to v2.2.2 (#5966) Bumps [actions/setup-python](https://github.com/actions/setup-python) from v2.2.1 to v2.2.2. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v2.2.1...dc73133d4da04e56a135ae2246682783cc7c7cb6) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 12 ++++++------ .github/workflows/wheel-builder.yml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f9fe126cf41f..3d9ac0a535ca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,7 +42,7 @@ jobs: key: ${{ runner.os }}-${{ matrix.PYTHON.VERSION }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Setup python - uses: actions/setup-python@v2.2.1 + uses: actions/setup-python@v2.2.2 with: python-version: ${{ matrix.PYTHON.VERSION }} - uses: actions-rs/toolchain@v1 @@ -164,7 +164,7 @@ jobs: key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}-${{ matrix.RUST }} - name: Setup python - uses: actions/setup-python@v2.2.1 + uses: actions/setup-python@v2.2.2 with: python-version: ${{ matrix.PYTHON.VERSION }} - uses: actions-rs/toolchain@v1 @@ -207,7 +207,7 @@ jobs: key: ${{ runner.os }}-${{ matrix.PYTHON.VERSION }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Setup python - uses: actions/setup-python@v2.2.1 + uses: actions/setup-python@v2.2.2 with: python-version: ${{ matrix.PYTHON.VERSION }} - uses: actions-rs/toolchain@v1 @@ -267,7 +267,7 @@ jobs: key: ${{ runner.os }}-${{ matrix.WINDOWS.ARCH }}-${{ matrix.PYTHON.VERSION }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Setup python - uses: actions/setup-python@v2.2.1 + uses: actions/setup-python@v2.2.2 with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} @@ -329,7 +329,7 @@ jobs: key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Setup python - uses: actions/setup-python@v2.2.1 + uses: actions/setup-python@v2.2.2 with: python-version: ${{ matrix.PYTHON }} - uses: actions-rs/toolchain@v1 @@ -354,7 +354,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Setup python - uses: actions/setup-python@v2.2.1 + uses: actions/setup-python@v2.2.2 with: python-version: 3.9 - uses: actions-rs/toolchain@v1 diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 271bd4de46e2..2b165041fa0b 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -122,7 +122,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Setup python - uses: actions/setup-python@v2.2.1 + uses: actions/setup-python@v2.2.2 with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} From db89e50033c1e41d0bd881785cdb096481ed7401 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Apr 2021 08:16:58 -0400 Subject: [PATCH 0215/2380] Bump asn1 from 0.3.1 to 0.3.3 in /src/rust (#5968) Bumps [asn1](https://github.com/alex/rust-asn1) from 0.3.1 to 0.3.3. - [Release notes](https://github.com/alex/rust-asn1/releases) - [Commits](https://github.com/alex/rust-asn1/compare/0.3.1...0.3.3) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- src/rust/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index adb82e4e45e4..af5e87fe0062 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "asn1" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "698c3b9621a1a2f9c98fceabba22e495a5f2604e773ec5fbd8a42cd797aa6d24" +checksum = "8c84b3b0c3c7051ba03423057b884aee14dc2c5b7741d58e6ad31d0908f0887a" dependencies = [ "chrono", ] diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 6d2a1e199c18..961356f051eb 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] pyo3 = { version = "0.13.1", features = ["extension-module"] } -asn1 = { version = "0.3.1", default-features = false } +asn1 = { version = "0.3.3", default-features = false } [lib] name = "cryptography_rust" From b2f9a0e1a546c3b10a6e96cd5e8423a7b04970c7 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Tue, 13 Apr 2021 20:45:01 +0200 Subject: [PATCH 0216/2380] Add x509.Name.rfc4514_attribute_name (#5969) * add x509.Name.rfc4514_attribute_name * tests++, docs++ * lint++ --- CHANGELOG.rst | 2 ++ docs/x509/reference.rst | 9 +++++++++ src/cryptography/x509/name.py | 14 ++++++++++++-- tests/x509/test_x509.py | 6 ++++++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2d9e6520697b..4f368b00f4a3 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -15,6 +15,8 @@ Changelog in regions where they may be required, and are not generally recommended. * We now ship ``manylinux_2_24`` wheels, in addition to our ``manylinux2010`` and ``manylinux2014`` wheels. +* Added ``rfc4514_attribute_name`` attribute to + :attr:`x509.NameAttribute `, .. _v3-4-7: diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst index 105f8e10686c..6c058f9f78d5 100644 --- a/docs/x509/reference.rst +++ b/docs/x509/reference.rst @@ -1333,6 +1333,15 @@ X.509 CSR (Certificate Signing Request) Builder Object The value of the attribute. + .. attribute:: rfc4514_attribute_name + + .. versionadded:: 35.0 + + :type: :term:`text` + + The :rfc:`4514` short attribute name (for example "CN"), + or the OID dotted string if a short name is unavailable. + .. method:: rfc4514_string() .. versionadded:: 2.5 diff --git a/src/cryptography/x509/name.py b/src/cryptography/x509/name.py index 0bfc2d94d452..e0ba6674d5b1 100644 --- a/src/cryptography/x509/name.py +++ b/src/cryptography/x509/name.py @@ -118,6 +118,14 @@ def oid(self) -> ObjectIdentifier: def value(self) -> str: return self._value + @property + def rfc4514_attribute_name(self) -> str: + """ + The short attribute name (for example "CN") if available, + otherwise the OID dotted string. + """ + return _NAMEOID_TO_NAME.get(self.oid, self.oid.dotted_string) + def rfc4514_string(self) -> str: """ Format as RFC4514 Distinguished Name string. @@ -125,8 +133,10 @@ def rfc4514_string(self) -> str: Use short attribute name if available, otherwise fall back to OID dotted string. """ - key = _NAMEOID_TO_NAME.get(self.oid, self.oid.dotted_string) - return "%s=%s" % (key, _escape_dn_value(self.value)) + return "%s=%s" % ( + self.rfc4514_attribute_name, + _escape_dn_value(self.value), + ) def __eq__(self, other: object) -> bool: if not isinstance(other, NameAttribute): diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index b3bf78a6862e..765beaebe1af 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -4991,6 +4991,12 @@ def test_repr(self, common_name, org_name, expected_repr): assert repr(name) == expected_repr + def test_rfc4514_attribute_name(self): + a = x509.NameAttribute(NameOID.COMMON_NAME, "cryptography.io") + assert a.rfc4514_attribute_name == "CN" + b = x509.NameAttribute(NameOID.PSEUDONYM, "cryptography.io") + assert b.rfc4514_attribute_name == "2.5.4.65" + def test_rfc4514_string(self): n = x509.Name( [ From 42884072d1f0851bdd50129b6831dbac6c072717 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Apr 2021 08:30:21 -0400 Subject: [PATCH 0217/2380] Bump redox_syscall from 0.2.5 to 0.2.6 in /src/rust (#5971) Bumps redox_syscall from 0.2.5 to 0.2.6. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index af5e87fe0062..8bfc5208b00a 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -265,9 +265,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" +checksum = "8270314b5ccceb518e7e578952f0b72b88222d02e8f77f5ecf7abbb673539041" dependencies = [ "bitflags", ] From af1465acaf32dbecea3716a1d427cb8b02a06fc0 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 14 Apr 2021 13:15:57 -0500 Subject: [PATCH 0218/2380] switch to using EVP_PKEY_derive instead of DH_compute_key in DH (#5972) * switch to using EVP_PKEY_derive instead of DH_compute_key in DH Where checks are occurring is changing in OpenSSL 3.0 and this makes it easier to be consistent (and is the API we should be using anyway). The tests change because EVP_PKEY_derive now verifies that we have shared parameters, which the test previously only verified by asserting that the derived keys didn't match * review feedback * type ignores required for typeerror tests. some day i will remember this --- src/_cffi_src/openssl/dh.py | 1 - .../hazmat/backends/openssl/dh.py | 57 ++++++++++++------- tests/hazmat/primitives/test_dh.py | 19 ++++--- 3 files changed, 45 insertions(+), 32 deletions(-) diff --git a/src/_cffi_src/openssl/dh.py b/src/_cffi_src/openssl/dh.py index 979dafa94253..50989e45343a 100644 --- a/src/_cffi_src/openssl/dh.py +++ b/src/_cffi_src/openssl/dh.py @@ -18,7 +18,6 @@ void DH_free(DH *); int DH_size(const DH *); int DH_generate_key(DH *); -int DH_compute_key(unsigned char *, const BIGNUM *, DH *); DH *DHparams_dup(DH *); /* added in 1.1.0 when the DH struct was opaqued */ diff --git a/src/cryptography/hazmat/backends/openssl/dh.py b/src/cryptography/hazmat/backends/openssl/dh.py index 65ddaeec5fe2..b928f024f56f 100644 --- a/src/cryptography/hazmat/backends/openssl/dh.py +++ b/src/cryptography/hazmat/backends/openssl/dh.py @@ -127,35 +127,48 @@ def private_numbers(self) -> dh.DHPrivateNumbers: ) def exchange(self, peer_public_key: dh.DHPublicKey) -> bytes: - buf = self._backend._ffi.new("unsigned char[]", self._key_size_bytes) - pub_key = self._backend._ffi.new("BIGNUM **") - self._backend._lib.DH_get0_key( - peer_public_key._dh_cdata, # type: ignore[attr-defined] - pub_key, - self._backend._ffi.NULL, + if not isinstance(peer_public_key, _DHPublicKey): + raise TypeError("peer_public_key must be a DHPublicKey") + + ctx = self._backend._lib.EVP_PKEY_CTX_new( + self._evp_pkey, self._backend._ffi.NULL ) - self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) - res = self._backend._lib.DH_compute_key( - buf, pub_key[0], self._dh_cdata + self._backend.openssl_assert(ctx != self._backend._ffi.NULL) + ctx = self._backend._ffi.gc(ctx, self._backend._lib.EVP_PKEY_CTX_free) + res = self._backend._lib.EVP_PKEY_derive_init(ctx) + self._backend.openssl_assert(res == 1) + res = self._backend._lib.EVP_PKEY_derive_set_peer( + ctx, peer_public_key._evp_pkey + ) + # Invalid kex errors here in OpenSSL 3.0 because checks were moved + # to EVP_PKEY_derive_set_peer + self._exchange_assert(res == 1) + keylen = self._backend._ffi.new("size_t *") + res = self._backend._lib.EVP_PKEY_derive( + ctx, self._backend._ffi.NULL, keylen ) + # Invalid kex errors here in OpenSSL < 3 + self._exchange_assert(res == 1) + self._backend.openssl_assert(keylen[0] > 0) + buf = self._backend._ffi.new("unsigned char[]", keylen[0]) + res = self._backend._lib.EVP_PKEY_derive(ctx, buf, keylen) + self._backend.openssl_assert(res == 1) - if res == -1: + key = self._backend._ffi.buffer(buf, keylen[0])[:] + pad = self._key_size_bytes - len(key) + + if pad > 0: + key = (b"\x00" * pad) + key + + return key + + def _exchange_assert(self, ok): + if not ok: errors_with_text = self._backend._consume_errors_with_text() raise ValueError( - "Error computing shared key. Public key is likely invalid " - "for this exchange.", + "Error computing shared key.", errors_with_text, ) - else: - self._backend.openssl_assert(res >= 1) - - key = self._backend._ffi.buffer(buf)[:res] - pad = self._key_size_bytes - len(key) - - if pad > 0: - key = (b"\x00" * pad) + key - - return key def public_key(self) -> dh.DHPublicKey: dh_cdata = _dh_params_dup(self._dh_cdata, self._backend) diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index 17d3a776e7a3..9e7f7f51d3d7 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -274,6 +274,12 @@ def test_generate_dh(self, backend, with_q): assert isinstance(key.private_numbers(), dh.DHPrivateNumbers) assert isinstance(key.parameters(), dh.DHParameters) + def test_exchange_wrong_type(self, backend): + parameters = FFDH3072_P.parameters(backend) + key1 = parameters.generate_private_key() + with pytest.raises(TypeError): + key1.exchange(b"invalidtype") # type: ignore[arg-type] + def test_exchange(self, backend): parameters = FFDH3072_P.parameters(backend) assert isinstance(parameters, dh.DHParameters) @@ -364,16 +370,11 @@ def test_bad_exchange(self, backend, vector): key2 = private2.private_key(backend) pub_key2 = key2.public_key() - if pub_key2.public_numbers().y >= parameters1.p: - with pytest.raises(ValueError): - key1.exchange(pub_key2) - else: - symkey1 = key1.exchange(pub_key2) - assert symkey1 - - symkey2 = key2.exchange(pub_key1) + with pytest.raises(ValueError): + key1.exchange(pub_key2) - assert symkey1 != symkey2 + with pytest.raises(ValueError): + key2.exchange(pub_key1) @pytest.mark.skip_fips(reason="key_size too small for FIPS") def test_load_256bit_key_from_pkcs8(self, backend): From 31564b8423a17913a374406782801b7372c98124 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 14 Apr 2021 20:21:04 -0400 Subject: [PATCH 0219/2380] Attempt to capture rust coverage and sent it to codecov (#5970) * Attempt to capture rust coverage and sent it to codecov * Allow this var in tox.ini * fix tox job * added llvm-tools-preview * Install cargo-binutils * Futz with paths * fix? * Make paths relative to repo base * Upload this so I can poke it * add format * A new testcase * typo * Do the workaround so we can have 100% coverage * typo * we don't need this --- .github/workflows/ci.yml | 56 +++++++++++++++++++++++++++++++++++++ src/rust/src/asn1.rs | 5 ++-- tests/x509/test_x509_ext.py | 11 ++++++++ tox.ini | 2 +- 4 files changed, 70 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d9ac0a535ca..ca049fc8fa69 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -185,6 +185,62 @@ jobs: with: name: "${{ matrix.PYTHON.TOXENV }} with Rust ${{ matrix.RUST }}" + linux-rust-coverage: + runs-on: ubuntu-latest + name: "Rust Coverage" + timeout-minutes: 30 + steps: + - uses: actions/checkout@v2 + - uses: actions/cache@v2.1.5 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + src/rust/target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}-rust-nightly-coverage + + - name: Setup python + uses: actions/setup-python@v2.2.2 + with: + python-version: 3.9 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly + override: true + default: true + components: llvm-tools-preview + - uses: actions-rs/install@v0.1 + with: + crate: cargo-binutils + version: latest + + - run: git clone --depth=1 https://github.com/google/wycheproof + - run: python -m pip install tox coverage + - name: Tests + run: | + tox -r -- --color=yes --wycheproof-root=wycheproof + env: + TOXENV: py39 + CARGO_TARGET_DIR: ${{ format('{0}/src/rust/target/', github.workspace) }} + RUSTFLAGS: "-Zinstrument-coverage" + LLVM_PROFILE_FILE: "rust-cov/cov-%p.profraw" + - name: Process coverage data + run: | + cd src/rust/ + cargo profdata -- merge -sparse ../../rust-cov/*.profraw -o rust-cov.profdata + cargo cov -- export ../../.tox/py39/lib/python3.9/site-packages/cryptography/hazmat/bindings/_rust.abi3.so \ + -instr-profile=rust-cov.profdata \ + --ignore-filename-regex='/.cargo/registry' \ + --ignore-filename-regex='/.rustup/toolchains/' --format=lcov > ../../rust-cov.lcov + + sed -E -i 's/SF:src\/(.*)/SF:src\/rust\/src\/\1/g' ../../rust-cov.lcov + + - uses: ./.github/actions/upload-coverage + with: + name: "Rust Coverage" + + macos: runs-on: macos-latest strategy: diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs index a5a9a856f092..0eac927553de 100644 --- a/src/rust/src/asn1.rs +++ b/src/rust/src/asn1.rs @@ -35,9 +35,8 @@ impl From for pyo3::PyErr { #[pyo3::prelude::pyfunction] fn parse_tls_feature(py: pyo3::Python<'_>, data: &[u8]) -> pyo3::PyResult { - let tls_feature_type_to_enum = py - .import("cryptography.x509.extensions")? - .getattr("_TLS_FEATURE_TYPE_TO_ENUM")?; + let x509_mod = py.import("cryptography.x509.extensions")?; + let tls_feature_type_to_enum = x509_mod.getattr("_TLS_FEATURE_TYPE_TO_ENUM")?; let features = asn1::parse::<_, PyAsn1Error, _>(data, |p| { let features = pyo3::types::PyList::empty(py); diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index 5fd3b527f5eb..480a8757dad9 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -1556,6 +1556,17 @@ def test_invalid_bit_string_padding_from_public_key(self, backend): with pytest.raises(ValueError): _key_identifier_from_public_key(pretend_key) + # The previous value is invalid for 2 reasons: a) it's got non-zero + # padding bits (i.e. the first byte of the value is not zero), b) the + # padding bits aren't all set to zero (i.e. the last bits of the value) + # Here we swap the last byte out with zeros so we can hit both error + # checks. + pretend_key = pretend.stub( + public_bytes=lambda x, y: data[:-1] + b"\x00" + ) + with pytest.raises(ValueError, match="Invalid public key encoding"): + _key_identifier_from_public_key(pretend_key) + def test_no_optional_params_allowed_from_public_key(self, backend): data = load_vectors_from_file( filename=os.path.join( diff --git a/tox.ini b/tox.ini index cf01d69de382..03cb89bf5bd3 100644 --- a/tox.ini +++ b/tox.ini @@ -11,7 +11,7 @@ deps = -e ./vectors pytest-shard>=0.1.2 randomorder: pytest-randomly -passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH USERNAME PYTHONIOENCODING CARGO_TARGET_DIR OPENSSL_FORCE_FIPS_MODE +passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH USERNAME PYTHONIOENCODING RUSTFLAGS CARGO_TARGET_DIR LLVM_PROFILE_FILE OPENSSL_FORCE_FIPS_MODE commands = pip list pytest -n auto --cov=cryptography --cov=tests --capture=no --strict-markers --durations=10 {posargs} From 6dc334feacf0b68bfcfdb720748369cce0630997 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 14 Apr 2021 22:15:00 -0500 Subject: [PATCH 0220/2380] switch to evp_pkey_derive for ECDH (#5973) remove unused lower level bindings, improve error msg --- src/_cffi_src/openssl/ec.py | 2 -- src/_cffi_src/openssl/ecdh.py | 2 -- src/cryptography/hazmat/backends/openssl/ec.py | 15 ++------------- src/cryptography/hazmat/backends/openssl/utils.py | 3 ++- 4 files changed, 4 insertions(+), 18 deletions(-) diff --git a/src/_cffi_src/openssl/ec.py b/src/_cffi_src/openssl/ec.py index 32d9b5843197..61d1cb3bb93d 100644 --- a/src/_cffi_src/openssl/ec.py +++ b/src/_cffi_src/openssl/ec.py @@ -33,8 +33,6 @@ EC_GROUP *EC_GROUP_new_by_curve_name(int); -int EC_GROUP_get_degree(const EC_GROUP *); - const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *); const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *); int EC_GROUP_get_curve_name(const EC_GROUP *); diff --git a/src/_cffi_src/openssl/ecdh.py b/src/_cffi_src/openssl/ecdh.py index 522642aafabc..d42c988b1e68 100644 --- a/src/_cffi_src/openssl/ecdh.py +++ b/src/_cffi_src/openssl/ecdh.py @@ -11,8 +11,6 @@ """ FUNCTIONS = """ -int ECDH_compute_key(void *, size_t, const EC_POINT *, EC_KEY *, - void *(*)(const void *, size_t, void *, size_t *)); long SSL_CTX_set_ecdh_auto(SSL_CTX *, int); """ diff --git a/src/cryptography/hazmat/backends/openssl/ec.py b/src/cryptography/hazmat/backends/openssl/ec.py index 3f54d72811e6..0199b5ea72e4 100644 --- a/src/cryptography/hazmat/backends/openssl/ec.py +++ b/src/cryptography/hazmat/backends/openssl/ec.py @@ -12,6 +12,7 @@ from cryptography.hazmat.backends.openssl.utils import ( _calculate_digest_and_algorithm, _check_not_prehashed, + _evp_pkey_derive, _warn_sign_verify_deprecated, ) from cryptography.hazmat.primitives import hashes, serialization @@ -195,19 +196,7 @@ def exchange( "peer_public_key and self are not on the same curve" ) - group = self._backend._lib.EC_KEY_get0_group(self._ec_key) - z_len = (self._backend._lib.EC_GROUP_get_degree(group) + 7) // 8 - self._backend.openssl_assert(z_len > 0) - z_buf = self._backend._ffi.new("uint8_t[]", z_len) - peer_key = self._backend._lib.EC_KEY_get0_public_key( - peer_public_key._ec_key # type: ignore[attr-defined] - ) - - r = self._backend._lib.ECDH_compute_key( - z_buf, z_len, peer_key, self._ec_key, self._backend._ffi.NULL - ) - self._backend.openssl_assert(r > 0) - return self._backend._ffi.buffer(z_buf)[:z_len] + return _evp_pkey_derive(self._backend, self._evp_pkey, peer_public_key) def public_key(self) -> ec.EllipticCurvePublicKey: group = self._backend._lib.EC_KEY_get0_group(self._ec_key) diff --git a/src/cryptography/hazmat/backends/openssl/utils.py b/src/cryptography/hazmat/backends/openssl/utils.py index 03e36f5b05f6..44945d30a9a0 100644 --- a/src/cryptography/hazmat/backends/openssl/utils.py +++ b/src/cryptography/hazmat/backends/openssl/utils.py @@ -25,7 +25,8 @@ def _evp_pkey_derive(backend, evp_pkey, peer_public_key): buf = backend._ffi.new("unsigned char[]", keylen[0]) res = backend._lib.EVP_PKEY_derive(ctx, buf, keylen) if res != 1: - raise ValueError("Null shared key derived from public/private pair.") + errors_with_text = backend._consume_errors_with_text() + raise ValueError("Error computing shared key.", errors_with_text) return backend._ffi.buffer(buf, keylen[0])[:] From 136a6f6baa42bb4d737b1c22ac68124c0af76368 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 14 Apr 2021 23:10:52 -0500 Subject: [PATCH 0221/2380] remove bionic and centos 8 arm64 jobs (#5974) * remove bionic and centos 8 arm64 jobs Reliability and speed is insufficient and we get almost the same CI bug finding value with just one arm64 job for now. * missed this --- .zuul.d/jobs.yaml | 14 -------------- .zuul.d/project.yaml | 2 -- 2 files changed, 16 deletions(-) diff --git a/.zuul.d/jobs.yaml b/.zuul.d/jobs.yaml index e9e1561c6fc4..8a61080ea537 100644 --- a/.zuul.d/jobs.yaml +++ b/.zuul.d/jobs.yaml @@ -12,20 +12,6 @@ vars: tox_envlist: py38 -- job: - name: pyca-cryptography-ubuntu-bionic-py36-arm64 - parent: pyca-cryptography-base - nodeset: ubuntu-bionic-arm64 - vars: - tox_envlist: py36 - -- job: - name: pyca-cryptography-centos-8-py36-arm64 - parent: pyca-cryptography-base - nodeset: centos-8-arm64 - vars: - tox_envlist: py36 - - job: name: pyca-cryptography-build-wheel abstract: true diff --git a/.zuul.d/project.yaml b/.zuul.d/project.yaml index b05d6b56f164..6d6d899d1ee9 100644 --- a/.zuul.d/project.yaml +++ b/.zuul.d/project.yaml @@ -4,8 +4,6 @@ - pyca-cryptography-build-wheel-arm64 - pyca-cryptography-build-wheel-x86_64 - pyca-cryptography-ubuntu-focal-py38-arm64 - - pyca-cryptography-ubuntu-bionic-py36-arm64 - - pyca-cryptography-centos-8-py36-arm64 release: jobs: - pyca-cryptography-build-wheel-arm64 From ae1368c9892c5472ecac905ca377fb6462ff3312 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 15 Apr 2021 00:35:22 -0400 Subject: [PATCH 0222/2380] Convert encode/decode of DSS signatures to Rust (#5965) * Convert encode/decode of DSS signatures to Rust * Add an additional test case * Refactor this code * Rewrite for readability --- .../hazmat/primitives/asymmetric/utils.py | 25 +------- src/rust/src/asn1.rs | 61 +++++++++++++++++++ tests/hazmat/primitives/test_asym_utils.py | 12 ++-- 3 files changed, 71 insertions(+), 27 deletions(-) diff --git a/src/cryptography/hazmat/primitives/asymmetric/utils.py b/src/cryptography/hazmat/primitives/asymmetric/utils.py index 931df018414b..b01a0dbcf565 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/utils.py +++ b/src/cryptography/hazmat/primitives/asymmetric/utils.py @@ -3,31 +3,12 @@ # for complete details. -import typing - -from cryptography.hazmat._der import ( - DERReader, - INTEGER, - SEQUENCE, - encode_der, - encode_der_integer, -) +from cryptography.hazmat.bindings._rust import asn1 from cryptography.hazmat.primitives import hashes -def decode_dss_signature(signature: bytes) -> typing.Tuple[int, int]: - with DERReader(signature).read_single_element(SEQUENCE) as seq: - r = seq.read_element(INTEGER).as_integer() - s = seq.read_element(INTEGER).as_integer() - return r, s - - -def encode_dss_signature(r: int, s: int) -> bytes: - return encode_der( - SEQUENCE, - encode_der(INTEGER, encode_der_integer(r)), - encode_der(INTEGER, encode_der_integer(s)), - ) +decode_dss_signature = asn1.decode_dss_signature +encode_dss_signature = asn1.encode_dss_signature class Prehashed(object): diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs index 0eac927553de..6cfe4f7878ea 100644 --- a/src/rust/src/asn1.rs +++ b/src/rust/src/asn1.rs @@ -2,6 +2,7 @@ // 2.0, and the BSD License. See the LICENSE file in the root of this repository // for complete details. +use pyo3::class::basic::CompareOp; use pyo3::conversion::ToPyObject; enum PyAsn1Error { @@ -94,11 +95,71 @@ fn parse_spki_for_data(py: pyo3::Python<'_>, data: &[u8]) -> pyo3::PyResult( + py: pyo3::Python<'p>, + v: asn1::BigUint, +) -> pyo3::PyResult<&'p pyo3::PyAny> { + let int_type = py.get_type::(); + int_type.call_method1("from_bytes", (v.as_bytes(), "big")) +} + +#[pyo3::prelude::pyfunction] +fn decode_dss_signature(py: pyo3::Python<'_>, data: &[u8]) -> pyo3::PyResult { + let (r, s) = asn1::parse::<_, PyAsn1Error, _>(data, |p| { + p.read_element::()?.parse(|p| { + let r = p.read_element::()?; + let s = p.read_element::()?; + Ok((r, s)) + }) + })?; + + Ok((big_asn1_uint_to_py(py, r)?, big_asn1_uint_to_py(py, s)?).to_object(py)) +} + +fn py_uint_to_big_endian_bytes<'p>( + py: pyo3::Python<'p>, + v: &'p pyo3::types::PyLong, +) -> pyo3::PyResult<&'p [u8]> { + let zero = (0).to_object(py); + if v.rich_compare(zero, CompareOp::Lt)?.is_true()? { + return Err(pyo3::exceptions::PyValueError::new_err( + "Negative integers are not supported", + )); + } + + // Round the length up so that we prefix an extra \x00. This ensures that + // integers that'd have the high bit set in their first octet are not + // encoded as negative in DER. + let n = v.call_method0("bit_length")?.extract::()? / 8 + 1; + v.call_method1("to_bytes", (n, "big"))?.extract() +} + +#[pyo3::prelude::pyfunction] +fn encode_dss_signature( + py: pyo3::Python<'_>, + r: &pyo3::types::PyLong, + s: &pyo3::types::PyLong, +) -> pyo3::PyResult { + let r = asn1::BigUint::new(py_uint_to_big_endian_bytes(py, r)?).unwrap(); + let s = asn1::BigUint::new(py_uint_to_big_endian_bytes(py, s)?).unwrap(); + let result = asn1::write(|w| { + w.write_element_with_type::(&|w| { + w.write_element(r); + w.write_element(s); + }); + }); + + Ok(pyo3::types::PyBytes::new(py, &result).to_object(py)) +} + pub(crate) fn create_submodule(py: pyo3::Python) -> pyo3::PyResult<&pyo3::prelude::PyModule> { let submod = pyo3::prelude::PyModule::new(py, "asn1")?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_tls_feature))?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_precert_poison))?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_spki_for_data))?; + submod.add_wrapped(pyo3::wrap_pyfunction!(decode_dss_signature))?; + submod.add_wrapped(pyo3::wrap_pyfunction!(encode_dss_signature))?; + Ok(submod) } diff --git a/tests/hazmat/primitives/test_asym_utils.py b/tests/hazmat/primitives/test_asym_utils.py index e4f22d7303e9..8ff5a65bdd75 100644 --- a/tests/hazmat/primitives/test_asym_utils.py +++ b/tests/hazmat/primitives/test_asym_utils.py @@ -35,25 +35,27 @@ def test_dss_signature(): def test_encode_dss_non_integer(): - with pytest.raises(ValueError): + with pytest.raises(TypeError): encode_dss_signature("h", 3) # type: ignore[arg-type] - with pytest.raises(ValueError): + with pytest.raises(TypeError): encode_dss_signature("3", "2") # type: ignore[arg-type] - with pytest.raises(ValueError): + with pytest.raises(TypeError): encode_dss_signature(3, "h") # type: ignore[arg-type] - with pytest.raises(ValueError): + with pytest.raises(TypeError): encode_dss_signature(3.3, 1.2) # type: ignore[arg-type] - with pytest.raises(ValueError): + with pytest.raises(TypeError): encode_dss_signature("hello", "world") # type: ignore[arg-type] def test_encode_dss_negative(): with pytest.raises(ValueError): encode_dss_signature(-1, 0) + with pytest.raises(ValueError): + encode_dss_signature(0, -1) def test_decode_dss_trailing_bytes(): From 1e1af7234a4598b6f4eb7677ebaa598e99ca4cd1 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 15 Apr 2021 11:02:09 -0400 Subject: [PATCH 0223/2380] fixes #5975 -- added typing stubs for rust module (#5976) --- MANIFEST.in | 2 +- mypy.ini | 2 -- .../hazmat/backends/openssl/decode_asn1.py | 10 ++++++---- src/cryptography/hazmat/bindings/_rust/__init__.pyi | 2 ++ src/cryptography/hazmat/bindings/_rust/asn1.pyi | 9 +++++++++ 5 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 src/cryptography/hazmat/bindings/_rust/__init__.pyi create mode 100644 src/cryptography/hazmat/bindings/_rust/asn1.pyi diff --git a/MANIFEST.in b/MANIFEST.in index 78889eaeb541..94f0a4f38d9c 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -7,7 +7,7 @@ include LICENSE.PSF include README.rst include pyproject.toml -recursive-include src py.typed +recursive-include src py.typed *.pyi recursive-include docs * recursive-include src/_cffi_src *.py *.c *.h diff --git a/mypy.ini b/mypy.ini index a1755b1fe0be..055619c090f6 100644 --- a/mypy.ini +++ b/mypy.ini @@ -4,8 +4,6 @@ check_untyped_defs = True [mypy-cryptography.hazmat.bindings._openssl] ignore_missing_imports = True -[mypy-cryptography.hazmat.bindings._rust] -ignore_missing_imports = True [mypy-iso8601] ignore_missing_imports = True diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 6e4dc0e939d1..72955a034732 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -210,17 +210,19 @@ def parse(self, x509_obj): # The extension contents are a SEQUENCE OF INTEGERs. data = self._backend._lib.X509_EXTENSION_get_data(ext) data_bytes = _asn1_string_to_bytes(self._backend, data) - value = asn1.parse_tls_feature(data_bytes) + tls_feature = asn1.parse_tls_feature(data_bytes) - extensions.append(x509.Extension(oid, critical, value)) + extensions.append(x509.Extension(oid, critical, tls_feature)) seen_oids.add(oid) continue elif oid == ExtensionOID.PRECERT_POISON: data = self._backend._lib.X509_EXTENSION_get_data(ext) data_bytes = _asn1_string_to_bytes(self._backend, data) - value = asn1.parse_precert_poison(data_bytes) + precert_poison = asn1.parse_precert_poison(data_bytes) - extensions.append(x509.Extension(oid, critical, value)) + extensions.append( + x509.Extension(oid, critical, precert_poison) + ) seen_oids.add(oid) continue diff --git a/src/cryptography/hazmat/bindings/_rust/__init__.pyi b/src/cryptography/hazmat/bindings/_rust/__init__.pyi new file mode 100644 index 000000000000..393ee7ab2b5c --- /dev/null +++ b/src/cryptography/hazmat/bindings/_rust/__init__.pyi @@ -0,0 +1,2 @@ +def check_pkcs7_padding(data: bytes) -> bool: ... +def check_ansix923_padding(data: bytes) -> bool: ... diff --git a/src/cryptography/hazmat/bindings/_rust/asn1.pyi b/src/cryptography/hazmat/bindings/_rust/asn1.pyi new file mode 100644 index 000000000000..dca9ce7efdea --- /dev/null +++ b/src/cryptography/hazmat/bindings/_rust/asn1.pyi @@ -0,0 +1,9 @@ +import typing + +from cryptography.x509 import TLSFeature, PrecertPoison + +def decode_dss_signature(signature: bytes) -> typing.Tuple[int, int]: ... +def encode_dss_signature(r: int, s: int) -> bytes: ... +def parse_tls_feature(data: bytes) -> TLSFeature: ... +def parse_precert_poison(data: bytes) -> PrecertPoison: ... +def parse_spki_for_data(data: bytes) -> bytes: ... From ed6f7a76591b7232744c2686fe7c2b39a0cf8d80 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 15 Apr 2021 21:04:48 -0400 Subject: [PATCH 0224/2380] Convert encoding two X.509 extensions to Rust (#5977) --- .../hazmat/backends/openssl/backend.py | 21 ++++---------- .../hazmat/bindings/_rust/asn1.pyi | 2 ++ src/rust/src/asn1.rs | 29 +++++++++++++++++++ 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 90957324c462..8afd1bdb38bc 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -12,13 +12,6 @@ from cryptography import utils, x509 from cryptography.exceptions import UnsupportedAlgorithm, _Reasons -from cryptography.hazmat._der import ( - INTEGER, - NULL, - SEQUENCE, - encode_der, - encode_der_integer, -) from cryptography.hazmat._types import _PRIVATE_KEY_TYPES from cryptography.hazmat.backends.interfaces import Backend as BackendInterface from cryptography.hazmat.backends.openssl import aead @@ -98,6 +91,7 @@ _CertificateSigningRequest, _RevokedCertificate, ) +from cryptography.hazmat.bindings._rust import asn1 from cryptography.hazmat.bindings.openssl import binding from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ( @@ -1171,17 +1165,14 @@ def _create_x509_extension(self, handlers, extension): value = _encode_asn1_str_gc(self, extension.value.value) return self._create_raw_x509_extension(extension, value) elif isinstance(extension.value, x509.TLSFeature): - asn1 = encode_der( - SEQUENCE, - *[ - encode_der(INTEGER, encode_der_integer(x.value)) - for x in extension.value - ], + value = _encode_asn1_str_gc( + self, asn1.encode_tls_feature(extension.value) ) - value = _encode_asn1_str_gc(self, asn1) return self._create_raw_x509_extension(extension, value) elif isinstance(extension.value, x509.PrecertPoison): - value = _encode_asn1_str_gc(self, encode_der(NULL)) + value = _encode_asn1_str_gc( + self, asn1.encode_precert_poison(extension.value) + ) return self._create_raw_x509_extension(extension, value) else: try: diff --git a/src/cryptography/hazmat/bindings/_rust/asn1.pyi b/src/cryptography/hazmat/bindings/_rust/asn1.pyi index dca9ce7efdea..207d76a71427 100644 --- a/src/cryptography/hazmat/bindings/_rust/asn1.pyi +++ b/src/cryptography/hazmat/bindings/_rust/asn1.pyi @@ -4,6 +4,8 @@ from cryptography.x509 import TLSFeature, PrecertPoison def decode_dss_signature(signature: bytes) -> typing.Tuple[int, int]: ... def encode_dss_signature(r: int, s: int) -> bytes: ... +def encode_tls_feature(ext: TLSFeature) -> bytes: ... def parse_tls_feature(data: bytes) -> TLSFeature: ... +def encode_precert_poison(ext: PrecertPoison) -> bytes: ... def parse_precert_poison(data: bytes) -> PrecertPoison: ... def parse_spki_for_data(data: bytes) -> bytes: ... diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs index 6cfe4f7878ea..640f0bda2038 100644 --- a/src/rust/src/asn1.rs +++ b/src/rust/src/asn1.rs @@ -34,6 +34,24 @@ impl From for pyo3::PyErr { } } +#[pyo3::prelude::pyfunction] +fn encode_tls_feature(py: pyo3::Python<'_>, ext: &pyo3::PyAny) -> pyo3::PyResult { + // Ideally we'd skip building up a vec and just write directly into the + // writer. This isn't possible at the moment because the callback to write + // an asn1::Sequence can't return an error, and we need to handle errors + // from Python. + let mut els = vec![]; + for el in ext.iter()? { + els.push(el?.getattr("value")?.extract::()?); + } + + let result = asn1::write(|w| { + w.write_element_with_type::>(&els); + }); + + Ok(pyo3::types::PyBytes::new(py, &result).to_object(py)) +} + #[pyo3::prelude::pyfunction] fn parse_tls_feature(py: pyo3::Python<'_>, data: &[u8]) -> pyo3::PyResult { let x509_mod = py.import("cryptography.x509.extensions")?; @@ -55,6 +73,15 @@ fn parse_tls_feature(py: pyo3::Python<'_>, data: &[u8]) -> pyo3::PyResult, _ext: &pyo3::PyAny) -> pyo3::PyObject { + let result = asn1::write(|w| { + w.write_element(()); + }); + + pyo3::types::PyBytes::new(py, &result).to_object(py) +} + #[pyo3::prelude::pyfunction] fn parse_precert_poison(py: pyo3::Python<'_>, data: &[u8]) -> pyo3::PyResult { asn1::parse::<_, PyAsn1Error, _>(data, |p| { @@ -154,7 +181,9 @@ fn encode_dss_signature( pub(crate) fn create_submodule(py: pyo3::Python) -> pyo3::PyResult<&pyo3::prelude::PyModule> { let submod = pyo3::prelude::PyModule::new(py, "asn1")?; + submod.add_wrapped(pyo3::wrap_pyfunction!(encode_tls_feature))?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_tls_feature))?; + submod.add_wrapped(pyo3::wrap_pyfunction!(encode_precert_poison))?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_precert_poison))?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_spki_for_data))?; From 6f36709588c243327080439f3c3dd898dbca17a7 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 16 Apr 2021 11:29:58 -0400 Subject: [PATCH 0225/2380] Corrected test parsing of certificates (#5978) RFC 5280 says these fields are both `IMPLICIT` tagging, and `IMPLICIT` tagging is only `CONSTRUCTED` if the inner type is, and the inner type is `BIT STRING` here, which is not `CONSTRUCTED`. In practice this is irrelevant since _no one_ ever uses these fields --- tests/x509/test_x509.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 765beaebe1af..c2dfdf250d2e 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -110,9 +110,9 @@ def _parse_cert(der): # Skip subjectPublicKeyInfo _ = tbs_cert.read_element(SEQUENCE) # Skip issuerUniqueID - _ = tbs_cert.read_optional_element(CONTEXT_SPECIFIC | CONSTRUCTED | 1) + _ = tbs_cert.read_optional_element(CONTEXT_SPECIFIC | 1) # Skip subjectUniqueID - _ = tbs_cert.read_optional_element(CONTEXT_SPECIFIC | CONSTRUCTED | 2) + _ = tbs_cert.read_optional_element(CONTEXT_SPECIFIC | 2) # Skip extensions _ = tbs_cert.read_optional_element(CONTEXT_SPECIFIC | CONSTRUCTED | 3) From f2a334cf6dec5a4931be843951057d2bb848e587 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Apr 2021 18:24:57 -0400 Subject: [PATCH 0226/2380] Bump asn1 from 0.3.3 to 0.3.5 in /src/rust (#5980) Bumps [asn1](https://github.com/alex/rust-asn1) from 0.3.3 to 0.3.5. - [Release notes](https://github.com/alex/rust-asn1/releases) - [Commits](https://github.com/alex/rust-asn1/compare/0.3.3...0.3.5) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- src/rust/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 8bfc5208b00a..0a319970507d 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "asn1" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c84b3b0c3c7051ba03423057b884aee14dc2c5b7741d58e6ad31d0908f0887a" +checksum = "fa8adeb6d7e2500bc2ee17c688f0e337ae6665a34d394adeaf9bf493f98acfd1" dependencies = [ "chrono", ] diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 961356f051eb..eff05b5f489e 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] pyo3 = { version = "0.13.1", features = ["extension-module"] } -asn1 = { version = "0.3.3", default-features = false } +asn1 = { version = "0.3.5", default-features = false } [lib] name = "cryptography_rust" From 19b29cddfe4802190a38b1a9650b165952195194 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 18 Apr 2021 20:56:49 -0400 Subject: [PATCH 0227/2380] properly mark pypy3-nocoverage jobs as no coverage (#5984) --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ca049fc8fa69..de24503ab812 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,8 +16,8 @@ jobs: matrix: PYTHON: - {VERSION: "3.9", TOXENV: "flake,rust,docs", COVERAGE: "false"} - - {VERSION: "pypy-3.6", TOXENV: "pypy3-nocoverage"} - - {VERSION: "pypy-3.7", TOXENV: "pypy3-nocoverage"} + - {VERSION: "pypy-3.6", TOXENV: "pypy3-nocoverage", COVERAGE: "false"} + - {VERSION: "pypy-3.7", TOXENV: "pypy3-nocoverage", COVERAGE: "false"} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1j"}} - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1j"}} From 79b0136cb26e3431cad2d250751ef334f97a641c Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 18 Apr 2021 20:57:19 -0400 Subject: [PATCH 0228/2380] Add another ignore path to rust coverage (#5985) --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de24503ab812..815b113a04a1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -232,6 +232,7 @@ jobs: cargo cov -- export ../../.tox/py39/lib/python3.9/site-packages/cryptography/hazmat/bindings/_rust.abi3.so \ -instr-profile=rust-cov.profdata \ --ignore-filename-regex='/.cargo/registry' \ + --ignore-filename-regex='/rustc/' \ --ignore-filename-regex='/.rustup/toolchains/' --format=lcov > ../../rust-cov.lcov sed -E -i 's/SF:src\/(.*)/SF:src\/rust\/src\/\1/g' ../../rust-cov.lcov From 89934a23950e79d3250668759d38bde60804e0ec Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 18 Apr 2021 22:06:51 -0400 Subject: [PATCH 0229/2380] Added more paths to coverage path combiner (#5983) * Added more paths to coverage path combiner * Update .coveragerc --- .coveragerc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.coveragerc b/.coveragerc index 6579cf6c8d42..ef820f0d4c6e 100644 --- a/.coveragerc +++ b/.coveragerc @@ -7,7 +7,8 @@ source = [paths] source = src/cryptography - .tox/*/lib/python*/site-packages/cryptography + .tox/*/lib*/python*/site-packages/cryptography + .tox\*\Lib\site-packages\cryptography .tox/pypy/site-packages/cryptography [report] From 6db4e0fb859c11106e1633988bda4341fc6f949b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Apr 2021 08:09:35 -0400 Subject: [PATCH 0230/2380] Bump asn1 from 0.3.5 to 0.3.6 in /src/rust (#5987) Bumps [asn1](https://github.com/alex/rust-asn1) from 0.3.5 to 0.3.6. - [Release notes](https://github.com/alex/rust-asn1/releases) - [Commits](https://github.com/alex/rust-asn1/compare/0.3.5...0.3.6) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- src/rust/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 0a319970507d..229c9cdb0139 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "asn1" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa8adeb6d7e2500bc2ee17c688f0e337ae6665a34d394adeaf9bf493f98acfd1" +checksum = "98ff0918103df4ea847a9a11dba5960b6e5743835560494c6ca3307c9063d931" dependencies = [ "chrono", ] diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index eff05b5f489e..57e94ae1b588 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] pyo3 = { version = "0.13.1", features = ["extension-module"] } -asn1 = { version = "0.3.5", default-features = false } +asn1 = { version = "0.3.6", default-features = false } [lib] name = "cryptography_rust" From 94590a9aecc9e5ef6fc8eda52bae43643a4c44bd Mon Sep 17 00:00:00 2001 From: Charlie Li Date: Mon, 19 Apr 2021 18:38:38 -0400 Subject: [PATCH 0231/2380] Fix build with LibreSSL 3.3.2 (#5988) * LibreSSL 3.3.2 supports SSL_OP_NO_DTLS* While here, bump CI * Fix preprocessor guards for LibreSSL's SSL_OP_NO_DTLS* DTLS_set_link_mtu and DTLS_get_link_min_mtu are not part of 3.3.2 * Switch to LESS_THAN context for LibreSSL 3.3.2 While here, fix indents * Remove extra C variable declaration The variable is not actually used from Python --- .github/workflows/ci.yml | 2 +- src/_cffi_src/openssl/cryptography.py | 7 +++++++ src/_cffi_src/openssl/ssl.py | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 815b113a04a1..1794d2fb190e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.0.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.1.5"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.2.5"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.3.1"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.3.2"}} RUST: - stable name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" diff --git a/src/_cffi_src/openssl/cryptography.py b/src/_cffi_src/openssl/cryptography.py index e2b5a13235ae..b9c7a793b3b6 100644 --- a/src/_cffi_src/openssl/cryptography.py +++ b/src/_cffi_src/openssl/cryptography.py @@ -32,6 +32,13 @@ #include #endif +#if CRYPTOGRAPHY_IS_LIBRESSL +#define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_332 \ + (LIBRESSL_VERSION_NUMBER < 0x3030200f) +#else +#define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_332 (0) +#endif + #define CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER \ (OPENSSL_VERSION_NUMBER >= 0x1010006f && !CRYPTOGRAPHY_IS_LIBRESSL) diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index 11a7d63a961a..081ef041fa33 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -586,8 +586,10 @@ #endif #if CRYPTOGRAPHY_IS_LIBRESSL +#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_332 static const long SSL_OP_NO_DTLSv1 = 0; static const long SSL_OP_NO_DTLSv1_2 = 0; +#endif long (*DTLS_set_link_mtu)(SSL *, long) = NULL; long (*DTLS_get_link_min_mtu)(SSL *) = NULL; #endif From 0c4caa295e28aec37b4d76702f9779451ec7927d Mon Sep 17 00:00:00 2001 From: Yang Yang Date: Tue, 20 Apr 2021 19:31:31 +0800 Subject: [PATCH 0232/2380] Fix typo: ANSI X.923 to ANSI X9.23 (#5989) --- docs/hazmat/primitives/padding.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/hazmat/primitives/padding.rst b/docs/hazmat/primitives/padding.rst index 99d500a05b68..ecd70e6d5084 100644 --- a/docs/hazmat/primitives/padding.rst +++ b/docs/hazmat/primitives/padding.rst @@ -58,7 +58,7 @@ multiple of the block size. .. versionadded:: 1.3 - `ANSI X.923`_ padding works by appending ``N-1`` bytes with the value of + `ANSI X9.23`_ padding works by appending ``N-1`` bytes with the value of ``0`` and a last byte with the value of ``chr(N)``, where ``N`` is the number of bytes required to make the final block of data the same size as the block size. A simple example of padding is: @@ -127,4 +127,4 @@ multiple of the block size. :raises ValueError: When trying to remove padding from incorrectly padded data. -.. _`ANSI X.923`: https://en.wikipedia.org/wiki/Padding_%28cryptography%29#ANSI_X9.23 +.. _`ANSI X9.23`: https://en.wikipedia.org/wiki/Padding_%28cryptography%29#ANSI_X9.23 From 09a5fb47ac2f423205edb1ff6dd07c34530c7e76 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 20 Apr 2021 09:19:10 -0400 Subject: [PATCH 0233/2380] Unpin 3.9 version on windows (#5990) * Unpin 3.9 version on windows And update cache key to include exact version instaled. * fix --- .github/workflows/ci.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1794d2fb190e..ec3b5d0dca0e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -307,7 +307,7 @@ jobs: - {ARCH: 'x64', WINDOWS: 'win64', RUST_TRIPLE: 'x86_64-pc-windows-msvc'} PYTHON: - {VERSION: "3.6", TOXENV: "py36", MSVC_VERSION: "2019", CL_FLAGS: ""} - - {VERSION: "3.9.2", TOXENV: "py39", MSVC_VERSION: "2019", CL_FLAGS: "/D USE_OSRANDOM_RNG_FOR_TESTING"} + - {VERSION: "3.9", TOXENV: "py39", MSVC_VERSION: "2019", CL_FLAGS: "/D USE_OSRANDOM_RNG_FOR_TESTING"} RUST: - stable JOB_NUMBER: [0, 1, 2, 3] @@ -315,19 +315,20 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v2 + - name: Setup python + id: setup-python + uses: actions/setup-python@v2.2.2 + with: + python-version: ${{ matrix.PYTHON.VERSION }} + architecture: ${{ matrix.WINDOWS.ARCH }} - uses: actions/cache@v2.1.5 with: path: | ~/.cargo/registry ~/.cargo/git src/rust/target/ - key: ${{ runner.os }}-${{ matrix.WINDOWS.ARCH }}-${{ matrix.PYTHON.VERSION }}-cargo-${{ hashFiles('**/Cargo.lock') }} + key: ${{ runner.os }}-${{ matrix.WINDOWS.ARCH }}-${{ steps.setup-python.outputs.python-version }}-cargo-${{ hashFiles('**/Cargo.lock') }} - - name: Setup python - uses: actions/setup-python@v2.2.2 - with: - python-version: ${{ matrix.PYTHON.VERSION }} - architecture: ${{ matrix.WINDOWS.ARCH }} - uses: actions-rs/toolchain@v1 with: profile: minimal From 4447e1b3d2d37125977315655d4c68465c6452b1 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 21 Apr 2021 21:51:29 -0400 Subject: [PATCH 0234/2380] Port X.509 test parser to Rust (#5979) --- .../hazmat/bindings/_rust/asn1.pyi | 7 ++ src/rust/Cargo.toml | 6 +- src/rust/src/asn1.rs | 89 +++++++++++++++ tests/x509/test_x509.py | 104 ++++-------------- tox.ini | 2 +- 5 files changed, 123 insertions(+), 85 deletions(-) diff --git a/src/cryptography/hazmat/bindings/_rust/asn1.pyi b/src/cryptography/hazmat/bindings/_rust/asn1.pyi index 207d76a71427..bd73221baf37 100644 --- a/src/cryptography/hazmat/bindings/_rust/asn1.pyi +++ b/src/cryptography/hazmat/bindings/_rust/asn1.pyi @@ -2,6 +2,12 @@ import typing from cryptography.x509 import TLSFeature, PrecertPoison +class TestCertificate: + not_after_tag: int + not_before_tag: int + issuer_value_tags: typing.List[int] + subject_value_tags: typing.List[int] + def decode_dss_signature(signature: bytes) -> typing.Tuple[int, int]: ... def encode_dss_signature(r: int, s: int) -> bytes: ... def encode_tls_feature(ext: TLSFeature) -> bytes: ... @@ -9,3 +15,4 @@ def parse_tls_feature(data: bytes) -> TLSFeature: ... def encode_precert_poison(ext: PrecertPoison) -> bytes: ... def parse_precert_poison(data: bytes) -> PrecertPoison: ... def parse_spki_for_data(data: bytes) -> bytes: ... +def test_parse_certificate(data: bytes) -> TestCertificate: ... diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 57e94ae1b588..b49c473a7418 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -6,9 +6,13 @@ edition = "2018" publish = false [dependencies] -pyo3 = { version = "0.13.1", features = ["extension-module"] } +pyo3 = { version = "0.13.1" } asn1 = { version = "0.3.6", default-features = false } +[features] +extension-module = ["pyo3/extension-module"] +default = ["extension-module"] + [lib] name = "cryptography_rust" crate-type = ["cdylib"] diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs index 640f0bda2038..9af05ca03a87 100644 --- a/src/rust/src/asn1.rs +++ b/src/rust/src/asn1.rs @@ -179,6 +179,93 @@ fn encode_dss_signature( Ok(pyo3::types::PyBytes::new(py, &result).to_object(py)) } +#[pyo3::prelude::pyclass] +struct TestCertificate { + #[pyo3(get)] + not_before_tag: u8, + #[pyo3(get)] + not_after_tag: u8, + #[pyo3(get)] + issuer_value_tags: Vec, + #[pyo3(get)] + subject_value_tags: Vec, +} + +fn parse_name_value_tags(p: &mut asn1::Parser) -> asn1::ParseResult> { + let mut tags = vec![]; + for rdn in p.read_element::>>()? { + let mut attributes = rdn?.collect::>>()?; + assert_eq!(attributes.len(), 1); + + let tag = attributes + .pop() + .unwrap() + .parse::<_, asn1::ParseError, _>(|p| { + p.read_element::()?; + let tlv = p.read_element::()?; + Ok(tlv.tag()) + })?; + tags.push(tag); + } + Ok(tags) +} + +#[pyo3::prelude::pyfunction] +fn test_parse_certificate(data: &[u8]) -> pyo3::PyResult { + let result = asn1::parse::<_, PyAsn1Error, _>(data, |p| { + // Outer SEQUENCE + p.read_element::()?.parse(|p| { + // TBS certificate + let result = p + .read_element::()? + .parse::<_, PyAsn1Error, _>(|p| { + // Version + p.read_optional_explicit_element::(0)?; + // Serial number + p.read_element::()?; + // Inner signature algorithm + p.read_element::()?; + + // Issuer + let issuer_value_tags = parse_name_value_tags(p)?; + // Validity + let (not_before_tag, not_after_tag) = p + .read_element::()? + .parse::<_, asn1::ParseError, _>(|p| { + let not_before_tag = p.read_element::()?.tag(); + let not_after_tag = p.read_element::()?.tag(); + Ok((not_before_tag, not_after_tag)) + })?; + // Subject + let subject_value_tags = parse_name_value_tags(p)?; + + // Subject public key info + p.read_element::()?; + // Issuer unique ID - never used in the real world + p.read_optional_implicit_element::(1)?; + // Subject unique ID - never used in the real world + p.read_optional_implicit_element::(2)?; + // Extensions + p.read_optional_explicit_element::(3)?; + + Ok(TestCertificate { + not_before_tag, + not_after_tag, + issuer_value_tags, + subject_value_tags, + }) + })?; + // Outer signature algorithm + p.read_element::()?; + // Signature + p.read_element::()?; + Ok(result) + }) + })?; + + Ok(result) +} + pub(crate) fn create_submodule(py: pyo3::Python) -> pyo3::PyResult<&pyo3::prelude::PyModule> { let submod = pyo3::prelude::PyModule::new(py, "asn1")?; submod.add_wrapped(pyo3::wrap_pyfunction!(encode_tls_feature))?; @@ -190,5 +277,7 @@ pub(crate) fn create_submodule(py: pyo3::Python) -> pyo3::PyResult<&pyo3::prelud submod.add_wrapped(pyo3::wrap_pyfunction!(decode_dss_signature))?; submod.add_wrapped(pyo3::wrap_pyfunction!(encode_dss_signature))?; + submod.add_wrapped(pyo3::wrap_pyfunction!(test_parse_certificate))?; + Ok(submod) } diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index c2dfdf250d2e..c6f758574e48 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -5,7 +5,6 @@ import binascii -import collections import copy import datetime import ipaddress @@ -18,19 +17,7 @@ from cryptography import utils, x509 from cryptography.exceptions import UnsupportedAlgorithm -from cryptography.hazmat._der import ( - BIT_STRING, - CONSTRUCTED, - CONTEXT_SPECIFIC, - DERReader, - GENERALIZED_TIME, - INTEGER, - OBJECT_IDENTIFIER, - PRINTABLE_STRING, - SEQUENCE, - SET, - UTC_TIME, -) +from cryptography.hazmat.bindings._rust import asn1 from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ( dh, @@ -82,52 +69,6 @@ def _load_cert(filename, loader, backend): return cert -ParsedCertificate = collections.namedtuple( - "ParsedCertificate", - ["not_before_tag", "not_after_tag", "issuer", "subject"], -) - - -def _parse_cert(der): - # See the Certificate structured, defined in RFC 5280. - with DERReader(der).read_single_element(SEQUENCE) as cert: - tbs_cert = cert.read_element(SEQUENCE) - # Skip outer signature algorithm - _ = cert.read_element(SEQUENCE) - # Skip signature - _ = cert.read_element(BIT_STRING) - - with tbs_cert: - # Skip version - _ = tbs_cert.read_optional_element(CONTEXT_SPECIFIC | CONSTRUCTED | 0) - # Skip serialNumber - _ = tbs_cert.read_element(INTEGER) - # Skip inner signature algorithm - _ = tbs_cert.read_element(SEQUENCE) - issuer = tbs_cert.read_element(SEQUENCE) - validity = tbs_cert.read_element(SEQUENCE) - subject = tbs_cert.read_element(SEQUENCE) - # Skip subjectPublicKeyInfo - _ = tbs_cert.read_element(SEQUENCE) - # Skip issuerUniqueID - _ = tbs_cert.read_optional_element(CONTEXT_SPECIFIC | 1) - # Skip subjectUniqueID - _ = tbs_cert.read_optional_element(CONTEXT_SPECIFIC | 2) - # Skip extensions - _ = tbs_cert.read_optional_element(CONTEXT_SPECIFIC | CONSTRUCTED | 3) - - with validity: - not_before_tag, _ = validity.read_any_element() - not_after_tag, _ = validity.read_any_element() - - return ParsedCertificate( - not_before_tag=not_before_tag, - not_after_tag=not_after_tag, - issuer=issuer, - subject=subject, - ) - - class TestCertificateRevocationList(object): def test_load_pem_crl(self, backend): crl = _load_cert( @@ -1788,29 +1729,19 @@ def test_build_cert_printable_string_country_name(self, backend): cert = builder.sign(issuer_private_key, hashes.SHA256(), backend) - parsed = _parse_cert(cert.public_bytes(serialization.Encoding.DER)) - subject = parsed.subject - issuer = parsed.issuer - - def read_next_rdn_value_tag(reader): - # Assume each RDN has a single attribute. - with reader.read_element(SET) as rdn: - attribute = rdn.read_element(SEQUENCE) - - with attribute: - _ = attribute.read_element(OBJECT_IDENTIFIER) - tag, value = attribute.read_any_element() - return tag + parsed = asn1.test_parse_certificate( + cert.public_bytes(serialization.Encoding.DER) + ) # Check that each value was encoded as an ASN.1 PRINTABLESTRING. - assert read_next_rdn_value_tag(subject) == PRINTABLE_STRING - assert read_next_rdn_value_tag(issuer) == PRINTABLE_STRING + assert parsed.issuer_value_tags[0] == 0x13 + assert parsed.subject_value_tags[0] == 0x13 if ( # This only works correctly in OpenSSL 1.1.0f+ backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER ): - assert read_next_rdn_value_tag(subject) == PRINTABLE_STRING - assert read_next_rdn_value_tag(issuer) == PRINTABLE_STRING + assert parsed.issuer_value_tags[1] == 0x13 + assert parsed.subject_value_tags[1] == 0x13 class TestCertificateBuilder(object): @@ -1971,9 +1902,13 @@ def test_extreme_times(self, not_valid_before, not_valid_after, backend): cert = builder.sign(private_key, hashes.SHA256(), backend) assert cert.not_valid_before == not_valid_before assert cert.not_valid_after == not_valid_after - parsed = _parse_cert(cert.public_bytes(serialization.Encoding.DER)) - assert parsed.not_before_tag == UTC_TIME - assert parsed.not_after_tag == GENERALIZED_TIME + parsed = asn1.test_parse_certificate( + cert.public_bytes(serialization.Encoding.DER) + ) + # UTC TIME + assert parsed.not_before_tag == 0x17 + # GENERALIZED TIME + assert parsed.not_after_tag == 0x18 def test_no_subject_name(self, backend): subject_private_key = RSA_KEY_2048.private_key(backend) @@ -2237,9 +2172,12 @@ def test_earliest_time(self, backend): cert = cert_builder.sign(private_key, hashes.SHA256(), backend) assert cert.not_valid_before == time assert cert.not_valid_after == time - parsed = _parse_cert(cert.public_bytes(serialization.Encoding.DER)) - assert parsed.not_before_tag == UTC_TIME - assert parsed.not_after_tag == UTC_TIME + parsed = asn1.test_parse_certificate( + cert.public_bytes(serialization.Encoding.DER) + ) + # UTC TIME + assert parsed.not_before_tag == 0x17 + assert parsed.not_after_tag == 0x17 def test_invalid_not_valid_after(self): with pytest.raises(TypeError): diff --git a/tox.ini b/tox.ini index 03cb89bf5bd3..19adafc2b28a 100644 --- a/tox.ini +++ b/tox.ini @@ -69,7 +69,7 @@ allowlist_externals = commands = cargo fmt --all -- --check cargo clippy -- -D warnings - cargo test + cargo test --no-default-features [flake8] ignore = E203,E211,W503,W504 From 57b9b1aa517fa97c9620ebd3155330b63db5742f Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 21 Apr 2021 22:46:17 -0400 Subject: [PATCH 0235/2380] Delete _der.py (#5992) --- src/cryptography/hazmat/_der.py | 156 --------------------- tests/hazmat/test_der.py | 232 -------------------------------- 2 files changed, 388 deletions(-) delete mode 100644 src/cryptography/hazmat/_der.py delete mode 100644 tests/hazmat/test_der.py diff --git a/src/cryptography/hazmat/_der.py b/src/cryptography/hazmat/_der.py deleted file mode 100644 index ba1db4caf682..000000000000 --- a/src/cryptography/hazmat/_der.py +++ /dev/null @@ -1,156 +0,0 @@ -# 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. - -import typing - -from cryptography.utils import int_to_bytes - - -# This module contains a lightweight DER encoder and decoder. See X.690 for the -# specification. This module intentionally does not implement the more complex -# BER encoding, only DER. -# -# Note this implementation treats an element's constructed bit as part of the -# tag. This is fine for DER, where the bit is always computable from the type. - - -CONSTRUCTED = 0x20 -CONTEXT_SPECIFIC = 0x80 - -INTEGER = 0x02 -BIT_STRING = 0x03 -OCTET_STRING = 0x04 -NULL = 0x05 -OBJECT_IDENTIFIER = 0x06 -SEQUENCE = 0x10 | CONSTRUCTED -SET = 0x11 | CONSTRUCTED -PRINTABLE_STRING = 0x13 -UTC_TIME = 0x17 -GENERALIZED_TIME = 0x18 - - -class DERReader(object): - def __init__(self, data: bytes) -> None: - self.data = memoryview(data) - - def __enter__(self) -> "DERReader": - return self - - def __exit__(self, exc_type, exc_value, tb): - if exc_value is None: - self.check_empty() - - def is_empty(self) -> bool: - return len(self.data) == 0 - - def check_empty(self) -> None: - if not self.is_empty(): - raise ValueError("Invalid DER input: trailing data") - - def read_byte(self) -> int: - if len(self.data) < 1: - raise ValueError("Invalid DER input: insufficient data") - ret = self.data[0] - self.data = self.data[1:] - return ret - - def read_bytes(self, n: int) -> memoryview: - if len(self.data) < n: - raise ValueError("Invalid DER input: insufficient data") - ret = self.data[:n] - self.data = self.data[n:] - return ret - - def read_any_element(self) -> typing.Tuple[int, "DERReader"]: - tag = self.read_byte() - # Tag numbers 31 or higher are stored in multiple bytes. No supported - # ASN.1 types use such tags, so reject these. - if tag & 0x1F == 0x1F: - raise ValueError("Invalid DER input: unexpected high tag number") - length_byte = self.read_byte() - if length_byte & 0x80 == 0: - # If the high bit is clear, the first length byte is the length. - length = length_byte - else: - # If the high bit is set, the first length byte encodes the length - # of the length. - length_byte &= 0x7F - if length_byte == 0: - raise ValueError( - "Invalid DER input: indefinite length form is not allowed " - "in DER" - ) - length = 0 - for i in range(length_byte): - length <<= 8 - length |= self.read_byte() - if length == 0: - raise ValueError( - "Invalid DER input: length was not minimally-encoded" - ) - if length < 0x80: - # If the length could have been encoded in short form, it must - # not use long form. - raise ValueError( - "Invalid DER input: length was not minimally-encoded" - ) - body = self.read_bytes(length) - return tag, DERReader(body) - - def read_element(self, expected_tag: int) -> "DERReader": - tag, body = self.read_any_element() - if tag != expected_tag: - raise ValueError("Invalid DER input: unexpected tag") - return body - - def read_single_element(self, expected_tag: int) -> "DERReader": - with self: - return self.read_element(expected_tag) - - def read_optional_element( - self, expected_tag: int - ) -> typing.Optional["DERReader"]: - if len(self.data) > 0 and self.data[0] == expected_tag: - return self.read_element(expected_tag) - return None - - def as_integer(self) -> int: - if len(self.data) == 0: - raise ValueError("Invalid DER input: empty integer contents") - first = self.data[0] - if first & 0x80 == 0x80: - raise ValueError("Negative DER integers are not supported") - # The first 9 bits must not all be zero or all be ones. Otherwise, the - # encoding should have been one byte shorter. - if len(self.data) > 1: - second = self.data[1] - if first == 0 and second & 0x80 == 0: - raise ValueError( - "Invalid DER input: integer not minimally-encoded" - ) - return int.from_bytes(self.data, "big") - - -def encode_der_integer(x: int) -> bytes: - if not isinstance(x, int): - raise ValueError("Value must be an integer") - if x < 0: - raise ValueError("Negative integers are not supported") - n = x.bit_length() // 8 + 1 - return int_to_bytes(x, n) - - -def encode_der(tag: int, *children: bytes) -> bytes: - length = 0 - for child in children: - length += len(child) - chunks = [bytes([tag])] - if length < 0x80: - chunks.append(bytes([length])) - else: - length_bytes = int_to_bytes(length) - chunks.append(bytes([0x80 | len(length_bytes)])) - chunks.append(length_bytes) - chunks.extend(children) - return b"".join(chunks) diff --git a/tests/hazmat/test_der.py b/tests/hazmat/test_der.py deleted file mode 100644 index aeae01db3f9f..000000000000 --- a/tests/hazmat/test_der.py +++ /dev/null @@ -1,232 +0,0 @@ -# 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. - - -import pytest - -from cryptography.hazmat._der import ( - DERReader, - INTEGER, - NULL, - OCTET_STRING, - SEQUENCE, - encode_der, - encode_der_integer, -) - - -def test_der_reader_basic(): - reader = DERReader(b"123456789") - assert reader.read_byte() == ord(b"1") - assert reader.read_bytes(1).tobytes() == b"2" - assert reader.read_bytes(4).tobytes() == b"3456" - - with pytest.raises(ValueError): - reader.read_bytes(4) - - assert reader.read_bytes(3).tobytes() == b"789" - - # The input is now empty. - with pytest.raises(ValueError): - reader.read_bytes(1) - with pytest.raises(ValueError): - reader.read_byte() - - -def test_der(): - # This input is the following structure, using - # https://github.com/google/der-ascii - # - # SEQUENCE { - # SEQUENCE { - # NULL {} - # INTEGER { 42 } - # OCTET_STRING { "hello" } - # } - # } - der = b"\x30\x0e\x30\x0c\x05\x00\x02\x01\x2a\x04\x05\x68\x65\x6c\x6c\x6f" - reader = DERReader(der) - with pytest.raises(ValueError): - reader.check_empty() - - with pytest.raises(ValueError): - with reader: - pass - - with pytest.raises(ZeroDivisionError): - with DERReader(der): - raise ZeroDivisionError - - # Parse the outer element. - outer = reader.read_element(SEQUENCE) - reader.check_empty() - assert outer.data.tobytes() == der[2:] - - # Parse the outer element with read_any_element. - reader = DERReader(der) - tag, outer2 = reader.read_any_element() - reader.check_empty() - assert tag == SEQUENCE - assert outer2.data.tobytes() == der[2:] - - # Parse the outer element with read_single_element. - outer3 = DERReader(der).read_single_element(SEQUENCE) - assert outer3.data.tobytes() == der[2:] - - # read_single_element rejects trailing data. - with pytest.raises(ValueError): - DERReader(der + der).read_single_element(SEQUENCE) - - # Continue parsing the structure. - inner = outer.read_element(SEQUENCE) - outer.check_empty() - - # Parsing a missing optional element should work. - assert inner.read_optional_element(INTEGER) is None - - null = inner.read_element(NULL) - null.check_empty() - - # Parsing a present optional element should work. - integer = inner.read_optional_element(INTEGER) - assert integer is not None - assert integer.as_integer() == 42 - - octet_string = inner.read_element(OCTET_STRING) - assert octet_string.data.tobytes() == b"hello" - - # Parsing a missing optional element should work when the input is empty. - inner.check_empty() - assert inner.read_optional_element(INTEGER) is None - - # Re-encode the same structure. - der2 = encode_der( - SEQUENCE, - encode_der( - SEQUENCE, - encode_der(NULL), - encode_der(INTEGER, encode_der_integer(42)), - encode_der(OCTET_STRING, b"hello"), - ), - ) - assert der2 == der - - -@pytest.mark.parametrize( - "length,header", - [ - # Single-byte lengths. - (0, b"\x04\x00"), - (1, b"\x04\x01"), - (2, b"\x04\x02"), - (127, b"\x04\x7f"), - # Long-form lengths. - (128, b"\x04\x81\x80"), - (129, b"\x04\x81\x81"), - (255, b"\x04\x81\xff"), - (0x100, b"\x04\x82\x01\x00"), - (0x101, b"\x04\x82\x01\x01"), - (0xFFFF, b"\x04\x82\xff\xff"), - (0x10000, b"\x04\x83\x01\x00\x00"), - ], -) -def test_der_lengths(length, header): - body = length * b"a" - der = header + body - - reader = DERReader(der) - element = reader.read_element(OCTET_STRING) - reader.check_empty() - assert element.data.tobytes() == body - - assert encode_der(OCTET_STRING, body) == der - - -@pytest.mark.parametrize( - "bad_input", - [ - # The input ended before the tag. - b"", - # The input ended before the length. - b"\x30", - # The input ended before the second byte of the length. - b"\x30\x81", - # The input ended before the body. - b"\x30\x01", - # The length used long form when it should be short form. - b"\x30\x81\x01\x00", - # The length was not minimally-encoded. - b"\x30\x82\x00\x80" + (0x80 * b"a"), - # Indefinite-length encoding is not valid DER. - b"\x30\x80\x00\x00" - # Tag number (the bottom 5 bits) 31 indicates long form tags, which we - # do not support. - b"\x1f\x00", - b"\x9f\x00", - b"\xbf\x00", - b"\xff\x00", - ], -) -def test_der_reader_bad_input(bad_input): - reader = DERReader(bad_input) - with pytest.raises(ValueError): - reader.read_any_element() - - -def test_der_reader_wrong_tag(): - reader = DERReader(b"\x04\x00") - with pytest.raises(ValueError): - reader.read_element(SEQUENCE) - - -@pytest.mark.parametrize( - "value,der", - [ - (0, b"\x00"), - (1, b"\x01"), - (2, b"\x02"), - (3, b"\x03"), - (127, b"\x7f"), - (128, b"\x00\x80"), - ( - 0x112233445566778899AABBCCDDEEFF, - b"\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff", - ), - ], -) -def test_integer(value, der): - assert encode_der_integer(value) == der - assert DERReader(der).as_integer() == value - - -@pytest.mark.parametrize( - "bad_input", - [ - # Zero is encoded as b"\x00", not the empty string. - b"", - # Too many leading zeros. - b"\x00\x00", - b"\x00\x7f", - # Too many leading ones. - b"\xff\xff", - b"\xff\x80", - # Negative integers are not supported. - b"\x80", - b"\x81", - b"\x80\x00\x00", - b"\xff", - ], -) -def test_invalid_integer(bad_input): - reader = DERReader(bad_input) - with pytest.raises(ValueError): - reader.as_integer() - - -def test_invalid_integer_encode(): - with pytest.raises(ValueError): - encode_der_integer(-1) - - with pytest.raises(ValueError): - encode_der_integer("not an integer") # type: ignore[arg-type] From 5ecb3d45b0c52f13888fcb9536526f463135e6a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Apr 2021 08:36:10 -0400 Subject: [PATCH 0236/2380] Bump syn from 1.0.69 to 1.0.70 in /src/rust (#5993) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.69 to 1.0.70. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.69...1.0.70) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 229c9cdb0139..c8ad2bfa4ec5 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -286,9 +286,9 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "syn" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb" +checksum = "b9505f307c872bab8eb46f77ae357c8eba1fdacead58ee5a850116b1d7f82883" dependencies = [ "proc-macro2", "quote", From 063a2048d1584ff6a74bbd4fa0ae4d9184bcab9b Mon Sep 17 00:00:00 2001 From: Mathias Ertl Date: Thu, 22 Apr 2021 16:00:43 +0200 Subject: [PATCH 0237/2380] add typehints to OCSPRequestBuilder() (#5994) --- src/cryptography/x509/ocsp.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/cryptography/x509/ocsp.py b/src/cryptography/x509/ocsp.py index 1c5de73e45b1..905ae745a8b5 100644 --- a/src/cryptography/x509/ocsp.py +++ b/src/cryptography/x509/ocsp.py @@ -312,7 +312,15 @@ def public_bytes(self, encoding: serialization.Encoding) -> bytes: class OCSPRequestBuilder(object): - def __init__(self, request=None, extensions=[]): + def __init__( + self, + request: typing.Optional[ + typing.Tuple[ + x509.Certificate, x509.Certificate, hashes.HashAlgorithm + ] + ] = None, + extensions: typing.List[x509.Extension[x509.ExtensionType]] = [], + ) -> None: self._request = request self._extensions = extensions From f08a7de651f9e6475c8c0a67d2a61ed8b669ddf6 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 22 Apr 2021 19:16:38 -0500 Subject: [PATCH 0238/2380] [WIP] 3.0.0 support (#5250) * 3.0.0 support * almost...there... * make mypy happy --- .github/workflows/ci.yml | 1 + src/_cffi_src/build_openssl.py | 1 + src/_cffi_src/openssl/cryptography.py | 3 ++ src/_cffi_src/openssl/err.py | 6 +++ src/_cffi_src/openssl/fips.py | 2 +- src/_cffi_src/openssl/provider.py | 40 +++++++++++++++++++ .../hazmat/backends/openssl/backend.py | 40 ++++++++++++++++--- .../hazmat/backends/openssl/ciphers.py | 8 ++++ .../hazmat/bindings/openssl/_conditional.py | 11 +++++ .../hazmat/bindings/openssl/binding.py | 20 ++++++++++ tests/hazmat/backends/test_openssl_memleak.py | 6 ++- tests/hazmat/bindings/test_openssl.py | 4 +- tests/hazmat/primitives/test_dh.py | 24 ++++++++++- 13 files changed, 156 insertions(+), 10 deletions(-) create mode 100644 src/_cffi_src/openssl/provider.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ec3b5d0dca0e..18b5bf2251ec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,6 +22,7 @@ jobs: - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1j"}} - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1j"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1j", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "3.0.0-alpha15"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "2.9.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.0.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.1.5"}} diff --git a/src/_cffi_src/build_openssl.py b/src/_cffi_src/build_openssl.py index 08499d66f629..557296ed5354 100644 --- a/src/_cffi_src/build_openssl.py +++ b/src/_cffi_src/build_openssl.py @@ -104,6 +104,7 @@ def _extra_compile_args(platform): "osrandom_engine", "pem", "pkcs12", + "provider", "rand", "rsa", "ssl", diff --git a/src/_cffi_src/openssl/cryptography.py b/src/_cffi_src/openssl/cryptography.py index b9c7a793b3b6..e9a9a522e8b6 100644 --- a/src/_cffi_src/openssl/cryptography.py +++ b/src/_cffi_src/openssl/cryptography.py @@ -41,6 +41,8 @@ #define CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER \ (OPENSSL_VERSION_NUMBER >= 0x1010006f && !CRYPTOGRAPHY_IS_LIBRESSL) +#define CRYPTOGRAPHY_OPENSSL_300_OR_GREATER \ + (OPENSSL_VERSION_NUMBER >= 0x30000000 && !CRYPTOGRAPHY_IS_LIBRESSL) #define CRYPTOGRAPHY_OPENSSL_LESS_THAN_110J \ (OPENSSL_VERSION_NUMBER < 0x101000af || CRYPTOGRAPHY_IS_LIBRESSL) @@ -60,6 +62,7 @@ TYPES = """ static const int CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER; +static const int CRYPTOGRAPHY_OPENSSL_300_OR_GREATER; static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_111; static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B; diff --git a/src/_cffi_src/openssl/err.py b/src/_cffi_src/openssl/err.py index 0634b656c0f4..8cfeaf5ba38a 100644 --- a/src/_cffi_src/openssl/err.py +++ b/src/_cffi_src/openssl/err.py @@ -18,6 +18,7 @@ static const int ERR_LIB_EVP; static const int ERR_LIB_PEM; +static const int ERR_LIB_PROV; static const int ERR_LIB_ASN1; static const int ERR_LIB_PKCS12; @@ -45,4 +46,9 @@ """ CUSTOMIZATIONS = """ +/* This define is tied to provider support and is conditionally + removed if Cryptography_HAS_PROVIDERS is false */ +#ifndef ERR_LIB_PROV +#define ERR_LIB_PROV 0 +#endif """ diff --git a/src/_cffi_src/openssl/fips.py b/src/_cffi_src/openssl/fips.py index b9d0d64d84fb..23c10af92209 100644 --- a/src/_cffi_src/openssl/fips.py +++ b/src/_cffi_src/openssl/fips.py @@ -17,7 +17,7 @@ """ CUSTOMIZATIONS = """ -#if CRYPTOGRAPHY_IS_LIBRESSL +#if CRYPTOGRAPHY_IS_LIBRESSL || CRYPTOGRAPHY_OPENSSL_300_OR_GREATER static const long Cryptography_HAS_FIPS = 0; int (*FIPS_mode_set)(int) = NULL; int (*FIPS_mode)(void) = NULL; diff --git a/src/_cffi_src/openssl/provider.py b/src/_cffi_src/openssl/provider.py new file mode 100644 index 000000000000..d7d659ea5ef4 --- /dev/null +++ b/src/_cffi_src/openssl/provider.py @@ -0,0 +1,40 @@ +# 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. + + +INCLUDES = """ +#if CRYPTOGRAPHY_OPENSSL_300_OR_GREATER +#include +#include +#endif +""" + +TYPES = """ +static const long Cryptography_HAS_PROVIDERS; + +typedef ... OSSL_PROVIDER; +typedef ... OSSL_LIB_CTX; + +static const long PROV_R_BAD_DECRYPT; +static const long PROV_R_WRONG_FINAL_BLOCK_LENGTH; +""" + +FUNCTIONS = """ +OSSL_PROVIDER *OSSL_PROVIDER_load(OSSL_LIB_CTX *, const char *); +int OSSL_PROVIDER_unload(OSSL_PROVIDER *prov); +""" + +CUSTOMIZATIONS = """ +#if CRYPTOGRAPHY_OPENSSL_300_OR_GREATER +static const long Cryptography_HAS_PROVIDERS = 1; +#else +static const long Cryptography_HAS_PROVIDERS = 0; +typedef void OSSL_PROVIDER; +typedef void OSSL_LIB_CTX; +static const long PROV_R_BAD_DECRYPT = 0; +static const long PROV_R_WRONG_FINAL_BLOCK_LENGTH = 0; +OSSL_PROVIDER *(*OSSL_PROVIDER_load)(OSSL_LIB_CTX *, const char *) = NULL; +int (*OSSL_PROVIDER_unload)(OSSL_PROVIDER *) = NULL; +#endif +""" diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 8afd1bdb38bc..28c49c151e33 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1285,6 +1285,11 @@ def load_der_private_key(self, data, password): def _evp_pkey_from_der_traditional_key(self, bio_data, password): key = self._lib.d2i_PrivateKey_bio(bio_data.bio, self._ffi.NULL) if key != self._ffi.NULL: + # In OpenSSL 3.0.0-alpha15 there exist scenarios where the key will + # successfully load but errors are still put on the stack. Tracked + # as https://github.com/openssl/openssl/issues/14996 + self._consume_errors() + key = self._ffi.gc(key, self._lib.EVP_PKEY_free) if password is not None: raise TypeError( @@ -1452,6 +1457,11 @@ def _load_key(self, openssl_read_func, convert_func, data, password): else: self._handle_key_loading_error() + # In OpenSSL 3.0.0-alpha15 there exist scenarios where the key will + # successfully load but errors are still put on the stack. Tracked + # as https://github.com/openssl/openssl/issues/14996 + self._consume_errors() + evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) if password is not None and userdata.called == 0: @@ -1474,11 +1484,22 @@ def _handle_key_loading_error(self): "incorrect format or it may be encrypted with an unsupported " "algorithm." ) - elif errors[0]._lib_reason_match( - self._lib.ERR_LIB_EVP, self._lib.EVP_R_BAD_DECRYPT - ) or errors[0]._lib_reason_match( - self._lib.ERR_LIB_PKCS12, - self._lib.PKCS12_R_PKCS12_CIPHERFINAL_ERROR, + + elif ( + errors[0]._lib_reason_match( + self._lib.ERR_LIB_EVP, self._lib.EVP_R_BAD_DECRYPT + ) + or errors[0]._lib_reason_match( + self._lib.ERR_LIB_PKCS12, + self._lib.PKCS12_R_PKCS12_CIPHERFINAL_ERROR, + ) + or ( + self._lib.Cryptography_HAS_PROVIDERS + and errors[0]._lib_reason_match( + self._lib.ERR_LIB_PROV, + self._lib.PROV_R_BAD_DECRYPT, + ) + ) ): raise ValueError("Bad decrypt. Incorrect password?") @@ -2524,9 +2545,16 @@ def load_key_and_certificates_from_pkcs12(self, data, password): if sk_x509_ptr[0] != self._ffi.NULL: sk_x509 = self._ffi.gc(sk_x509_ptr[0], self._lib.sk_X509_free) num = self._lib.sk_X509_num(sk_x509_ptr[0]) + # In OpenSSL < 3.0.0 PKCS12 parsing reverses the order of the # certificates. - for i in reversed(range(num)): + indices: typing.Iterable[int] + if self._lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER: + indices = range(num) + else: + indices = reversed(range(num)) + + for i in indices: x509 = self._lib.sk_X509_value(sk_x509, i) self.openssl_assert(x509 != self._ffi.NULL) x509 = self._ffi.gc(x509, self._lib.X509_free) diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py index 50cbeb69a680..eb302e44f9eb 100644 --- a/src/cryptography/hazmat/backends/openssl/ciphers.py +++ b/src/cryptography/hazmat/backends/openssl/ciphers.py @@ -146,6 +146,7 @@ def update_into(self, data: bytes, buf) -> int: self._ctx, outbuf, outlen, inbuf, inlen ) if res == 0 and isinstance(self._mode, modes.XTS): + self._backend._consume_errors() raise ValueError( "In XTS mode you must supply at least a full block in the " "first update call. For AES this is 16 bytes." @@ -180,6 +181,13 @@ def finalize(self) -> bytes: errors[0]._lib_reason_match( self._backend._lib.ERR_LIB_EVP, self._backend._lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH, + ) + or ( + self._backend._lib.Cryptography_HAS_PROVIDERS + and errors[0]._lib_reason_match( + self._backend._lib.ERR_LIB_PROV, + self._backend._lib.PROV_R_WRONG_FINAL_BLOCK_LENGTH, + ) ), errors=errors, ) diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index aaa7d1392028..55b2117cd53b 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -256,6 +256,16 @@ def cryptography_has_get_proto_version(): ] +def cryptography_has_providers(): + return [ + "OSSL_PROVIDER_load", + "OSSL_PROVIDER_unload", + "ERR_LIB_PROV", + "PROV_R_WRONG_FINAL_BLOCK_LENGTH", + "PROV_R_BAD_DECRYPT", + ] + + # This is a mapping of # {condition: function-returning-names-dependent-on-that-condition} so we can # loop over them and delete unsupported names at runtime. It will be removed @@ -303,4 +313,5 @@ def cryptography_has_get_proto_version(): "Cryptography_HAS_VERIFIED_CHAIN": cryptography_has_verified_chain, "Cryptography_HAS_SRTP": cryptography_has_srtp, "Cryptography_HAS_GET_PROTO_VERSION": cryptography_has_get_proto_version, + "Cryptography_HAS_PROVIDERS": cryptography_has_providers, } diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py index a2bc36a83a71..6dcec26ab8a3 100644 --- a/src/cryptography/hazmat/bindings/openssl/binding.py +++ b/src/cryptography/hazmat/bindings/openssl/binding.py @@ -113,6 +113,8 @@ class Binding(object): ffi = ffi _lib_loaded = False _init_lock = threading.Lock() + _legacy_provider: typing.Any = None + _default_provider: typing.Any = None def __init__(self): self._ensure_ffi_initialized() @@ -140,6 +142,24 @@ def _ensure_ffi_initialized(cls): # adds all ciphers/digests for EVP cls.lib.OpenSSL_add_all_algorithms() cls._register_osrandom_engine() + # As of OpenSSL 3.0.0 we must register a legacy cipher provider + # to get RC2 (needed for junk asymmetric private key + # serialization), RC4, Blowfish, IDEA, SEED, etc. These things + # are ugly legacy, but we aren't going to get rid of them + # any time soon. + if cls.lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER: + cls._legacy_provider = cls.lib.OSSL_PROVIDER_load( + cls.ffi.NULL, b"legacy" + ) + _openssl_assert( + cls.lib, cls._legacy_provider != cls.ffi.NULL + ) + cls._default_provider = cls.lib.OSSL_PROVIDER_load( + cls.ffi.NULL, b"default" + ) + _openssl_assert( + cls.lib, cls._default_provider != cls.ffi.NULL + ) @classmethod def init_static_locks(cls): diff --git a/tests/hazmat/backends/test_openssl_memleak.py b/tests/hazmat/backends/test_openssl_memleak.py index 0c96516fa19f..0316b5d9602e 100644 --- a/tests/hazmat/backends/test_openssl_memleak.py +++ b/tests/hazmat/backends/test_openssl_memleak.py @@ -82,7 +82,7 @@ def free(ptr, path, line): assert result == 1 # Trigger a bunch of initialization stuff. - import cryptography.hazmat.backends.openssl + from cryptography.hazmat.backends.openssl.backend import backend start_heap = set(heap) @@ -91,6 +91,10 @@ def free(ptr, path, line): gc.collect() gc.collect() + if lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER: + lib.OSSL_PROVIDER_unload(backend._binding._legacy_provider) + lib.OSSL_PROVIDER_unload(backend._binding._default_provider) + if lib.Cryptography_HAS_OPENSSL_CLEANUP: lib.OPENSSL_cleanup() diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py index fb9a1e363742..4d1e3b5566d5 100644 --- a/tests/hazmat/bindings/test_openssl.py +++ b/tests/hazmat/bindings/test_openssl.py @@ -91,7 +91,9 @@ def test_openssl_assert_error_on_stack(self): _openssl_assert(b.lib, False) error = exc_info.value.err_code[0] - assert error.code == 101183626 + # As of 3.0.0 OpenSSL sets func codes to 0, so the combined + # code is a different value + assert error.code in (101183626, 50331786) assert error.lib == b.lib.ERR_LIB_EVP assert error.func == b.lib.EVP_F_EVP_ENCRYPTFINAL_EX assert error.reason == b.lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index 9e7f7f51d3d7..7efc09456e6d 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -174,7 +174,23 @@ def test_dh_parameters_allows_rfc3526_groups(self, backend, vector): params = dh.DHParameterNumbers(p, int(vector["g"])) param = params.parameters(backend) key = param.generate_private_key() - assert key.private_numbers().public_numbers.parameter_numbers == params + # In OpenSSL 3.0.0 OpenSSL maps to known groups. This results in + # a scenario where loading a known group with p and g returns a + # re-serialized form that has q as well (the Sophie Germain prime of + # that group). This makes a naive comparison of the parameter numbers + # objects fail, so we have to be a bit smarter + serialized_params = ( + key.private_numbers().public_numbers.parameter_numbers + ) + if serialized_params.q is None: + # This is the path OpenSSL < 3.0 takes + assert serialized_params == params + else: + assert serialized_params.p == params.p + assert serialized_params.g == params.g + # p = 2q + 1 since it is a Sophie Germain prime, so we can compute + # what we expect OpenSSL to have done here. + assert serialized_params.q == (params.p - 1) // 2 @pytest.mark.skip_fips(reason="non-FIPS parameters") @pytest.mark.parametrize( @@ -377,6 +393,12 @@ def test_bad_exchange(self, backend, vector): key2.exchange(pub_key1) @pytest.mark.skip_fips(reason="key_size too small for FIPS") + @pytest.mark.supported( + only_if=lambda backend: ( + not backend._lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER + ), + skip_message="256-bit DH keys are not supported in OpenSSL 3.0.0+", + ) def test_load_256bit_key_from_pkcs8(self, backend): data = load_vectors_from_file( os.path.join("asymmetric", "DH", "dh_key_256.pem"), From 4dd2d988ca18afcb8eb789bc3cdb9f8f79ff2123 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Apr 2021 08:20:21 -0400 Subject: [PATCH 0239/2380] Bump asn1 from 0.3.6 to 0.3.7 in /src/rust (#5999) Bumps [asn1](https://github.com/alex/rust-asn1) from 0.3.6 to 0.3.7. - [Release notes](https://github.com/alex/rust-asn1/releases) - [Commits](https://github.com/alex/rust-asn1/compare/0.3.6...0.3.7) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- src/rust/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index c8ad2bfa4ec5..21f5f3b18d0d 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "asn1" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98ff0918103df4ea847a9a11dba5960b6e5743835560494c6ca3307c9063d931" +checksum = "6e73776acd44522682c2f4f7a2a316c038e318796bf5a720679a21b892e3c7a8" dependencies = [ "chrono", ] diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index b49c473a7418..e337ac592dbf 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] pyo3 = { version = "0.13.1" } -asn1 = { version = "0.3.6", default-features = false } +asn1 = { version = "0.3.7", default-features = false } [features] extension-module = ["pyo3/extension-module"] From fdb69922493d1e64cf7f807b85d198abe2200aeb Mon Sep 17 00:00:00 2001 From: Mathias Ertl Date: Fri, 23 Apr 2021 14:56:54 +0200 Subject: [PATCH 0240/2380] typehint OCSPResponseBuilder builder (#6002) * typehint response builder * change to list as suggested by @alex --- src/cryptography/x509/ocsp.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/cryptography/x509/ocsp.py b/src/cryptography/x509/ocsp.py index 905ae745a8b5..1d136e7f9be3 100644 --- a/src/cryptography/x509/ocsp.py +++ b/src/cryptography/x509/ocsp.py @@ -365,7 +365,13 @@ def build(self) -> OCSPRequest: class OCSPResponseBuilder(object): def __init__( - self, response=None, responder_id=None, certs=None, extensions=[] + self, + response: typing.Optional[_SingleResponse] = None, + responder_id: typing.Optional[ + typing.Tuple[x509.Certificate, OCSPResponderEncoding] + ] = None, + certs: typing.Optional[typing.List[x509.Certificate]] = None, + extensions: typing.List[x509.Extension[x509.ExtensionType]] = [], ): self._response = response self._responder_id = responder_id From 58bddfd7e9588a8bdfc32baa1ea2fb93c121571d Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 23 Apr 2021 09:02:49 -0400 Subject: [PATCH 0241/2380] removed paragraph in docs that was very out of date (#6003) --- docs/development/getting-started.rst | 7 ------- 1 file changed, 7 deletions(-) diff --git a/docs/development/getting-started.rst b/docs/development/getting-started.rst index e230fc30d405..b52a4fd0cd45 100644 --- a/docs/development/getting-started.rst +++ b/docs/development/getting-started.rst @@ -26,12 +26,6 @@ install them manually by using ``pip`` on each directory. You will also need to install ``enchant`` using your system's package manager to check spelling in the documentation. -.. note:: - There is an upstream bug in ``enchant`` that prevents its installation on - Windows with 64-bit Python. See `this Github issue`_ for more information. - The easiest workaround is to use 32-bit Python for ``cryptography`` - development, even on 64-bit Windows. - You are now ready to run the tests and build the documentation. OpenSSL on macOS @@ -115,4 +109,3 @@ The HTML documentation index can now be found at .. _`pip`: https://pypi.org/project/pip/ .. _`sphinx`: https://pypi.org/project/Sphinx/ .. _`reStructured Text`: https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html -.. _`this Github issue`: https://github.com/rfk/pyenchant/issues/42 From 62124e673aa3b37a1b3652bfed7bdcb9ac8d33a2 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 24 Apr 2021 15:33:47 -0400 Subject: [PATCH 0242/2380] Port OCSP Request extension parsing to Rust (#6005) * Port OCSP Request extension parsing to Rust * Added test for rando oid * Update src/rust/src/asn1.rs Co-authored-by: Paul Kehrer Co-authored-by: Paul Kehrer --- docs/development/test-vectors.rst | 2 ++ src/_cffi_src/openssl/objects.py | 20 +++++++++++ .../hazmat/backends/openssl/backend.py | 3 +- .../hazmat/backends/openssl/decode_asn1.py | 23 +++++++++--- .../hazmat/bindings/_rust/asn1.pyi | 5 ++- src/rust/Cargo.lock | 11 ++++-- src/rust/Cargo.toml | 3 +- src/rust/src/asn1.rs | 33 ++++++++++++++++++ tests/x509/test_ocsp.py | 13 +++++++ .../x509/ocsp/req-ext-unknown-oid.der | Bin 0 -> 121 bytes 10 files changed, 102 insertions(+), 11 deletions(-) create mode 100644 vectors/cryptography_vectors/x509/ocsp/req-ext-unknown-oid.der diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index f952337e2347..e8e466d4a999 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -551,6 +551,8 @@ Custom X.509 OCSP Test Vectors invalid hash algorithm OID. * ``x509/ocsp/req-ext-nonce.der`` - An OCSP request containing a nonce extension. +* ``x509/ocsp/req-ext-unknown-oid.der`` - An OCSP request containing an + extension with an unknown OID. Custom PKCS12 Test Vectors ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/_cffi_src/openssl/objects.py b/src/_cffi_src/openssl/objects.py index bddaa84284ea..10ceb2b1493b 100644 --- a/src/_cffi_src/openssl/objects.py +++ b/src/_cffi_src/openssl/objects.py @@ -26,7 +26,27 @@ int OBJ_txt2nid(const char *); ASN1_OBJECT *OBJ_txt2obj(const char *, int); int OBJ_obj2txt(char *, int, const ASN1_OBJECT *, int); + +const unsigned char *Cryptography_OBJ_get0_data(const ASN1_OBJECT *); +size_t Cryptography_OBJ_length(const ASN1_OBJECT *); """ CUSTOMIZATIONS = """ +#if CRYPTOGRAPHY_IS_LIBRESSL +const unsigned char *Cryptography_OBJ_get0_data(const ASN1_OBJECT *a) { + return a->data; +} + +size_t Cryptography_OBJ_length(const ASN1_OBJECT *a) { + return a->length; +} +#else +const unsigned char *Cryptography_OBJ_get0_data(const ASN1_OBJECT *a) { + return OBJ_get0_data(a); +} + +size_t Cryptography_OBJ_length(const ASN1_OBJECT *a) { + return OBJ_length(a); +} +#endif """ diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 28c49c151e33..4cc8b63f1f3f 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -23,7 +23,6 @@ _EXTENSION_HANDLERS_BASE, _EXTENSION_HANDLERS_SCT, _OCSP_BASICRESP_EXTENSION_HANDLERS, - _OCSP_REQ_EXTENSION_HANDLERS, _OCSP_SINGLERESP_EXTENSION_HANDLERS_SCT, _REVOKED_EXTENSION_HANDLERS, _X509ExtensionParser, @@ -426,7 +425,7 @@ def _register_x509_ext_parsers(self): self, ext_count=self._lib.OCSP_REQUEST_get_ext_count, get_ext=self._lib.OCSP_REQUEST_get_ext, - handlers=_OCSP_REQ_EXTENSION_HANDLERS, + rust_callback=asn1.parse_ocsp_req_extension, ) self._ocsp_basicresp_ext_parser = _X509ExtensionParser( self, diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 72955a034732..9a85e9464dce 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -178,10 +178,14 @@ def _decode_delta_crl_indicator(backend, ext): class _X509ExtensionParser(object): - def __init__(self, backend, ext_count, get_ext, handlers): + def __init__( + self, backend, ext_count, get_ext, handlers=None, rust_callback=None + ): + assert handlers or rust_callback self.ext_count = ext_count self.get_ext = get_ext self.handlers = handlers + self.rust_callback = rust_callback self._backend = backend def parse(self, x509_obj): @@ -203,6 +207,19 @@ def parse(self, x509_obj): "Duplicate {} extension found".format(oid), oid ) + if self.rust_callback is not None: + oid_ptr = self._backend._lib.X509_EXTENSION_get_object(ext) + oid_der_bytes = self._backend._ffi.buffer( + self._backend._lib.Cryptography_OBJ_get0_data(oid_ptr), + self._backend._lib.Cryptography_OBJ_length(oid_ptr), + )[:] + data = self._backend._lib.X509_EXTENSION_get_data(ext) + data_bytes = _asn1_string_to_bytes(self._backend, data) + ext = self.rust_callback(oid_der_bytes, data_bytes) + extensions.append(x509.Extension(oid, critical, ext)) + seen_oids.add(oid) + continue + # These OIDs are only supported in OpenSSL 1.1.0+ but we want # to support them in all versions of OpenSSL so we decode them # ourselves. @@ -854,10 +871,6 @@ def _decode_nonce(backend, nonce): ExtensionOID.FRESHEST_CRL: _decode_freshest_crl, } -_OCSP_REQ_EXTENSION_HANDLERS = { - OCSPExtensionOID.NONCE: _decode_nonce, -} - _OCSP_BASICRESP_EXTENSION_HANDLERS = { OCSPExtensionOID.NONCE: _decode_nonce, } diff --git a/src/cryptography/hazmat/bindings/_rust/asn1.pyi b/src/cryptography/hazmat/bindings/_rust/asn1.pyi index bd73221baf37..5f4afc92f1cf 100644 --- a/src/cryptography/hazmat/bindings/_rust/asn1.pyi +++ b/src/cryptography/hazmat/bindings/_rust/asn1.pyi @@ -1,6 +1,6 @@ import typing -from cryptography.x509 import TLSFeature, PrecertPoison +from cryptography.x509 import ExtensionType, TLSFeature, PrecertPoison class TestCertificate: not_after_tag: int @@ -14,5 +14,8 @@ def encode_tls_feature(ext: TLSFeature) -> bytes: ... def parse_tls_feature(data: bytes) -> TLSFeature: ... def encode_precert_poison(ext: PrecertPoison) -> bytes: ... def parse_precert_poison(data: bytes) -> PrecertPoison: ... +def parse_ocsp_req_extension( + der_oid: bytes, ext_data: bytes +) -> ExtensionType: ... def parse_spki_for_data(data: bytes) -> bytes: ... def test_parse_certificate(data: bytes) -> TestCertificate: ... diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 21f5f3b18d0d..b5ceed20b367 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "asn1" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e73776acd44522682c2f4f7a2a316c038e318796bf5a720679a21b892e3c7a8" +checksum = "842b2cc51640a5737c94248d328936d11f53ea8080e3fdba6ba523b41fa6ea15" dependencies = [ "chrono", ] @@ -44,6 +44,7 @@ name = "cryptography-rust" version = "0.1.0" dependencies = [ "asn1", + "lazy_static", "pyo3", ] @@ -122,6 +123,12 @@ dependencies = [ "syn", ] +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.93" diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index e337ac592dbf..144f34106cbe 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -6,8 +6,9 @@ edition = "2018" publish = false [dependencies] +lazy_static = "1" pyo3 = { version = "0.13.1" } -asn1 = { version = "0.3.7", default-features = false } +asn1 = { version = "0.3.8", default-features = false } [features] extension-module = ["pyo3/extension-module"] diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs index 9af05ca03a87..5d63bac65d82 100644 --- a/src/rust/src/asn1.rs +++ b/src/rust/src/asn1.rs @@ -122,6 +122,37 @@ fn parse_spki_for_data(py: pyo3::Python<'_>, data: &[u8]) -> pyo3::PyResult = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.48.1.2").unwrap(); +} + +#[pyo3::prelude::pyfunction] +fn parse_ocsp_req_extension( + py: pyo3::Python<'_>, + der_oid: &[u8], + ext_data: &[u8], +) -> pyo3::PyResult { + let oid = asn1::ObjectIdentifier::from_der(der_oid).unwrap(); + + let x509_module = py.import("cryptography.x509")?; + if oid == *NONCE_OID { + // This is a disaster. RFC 2560 says that the contents of the nonce is + // just the raw extension value. This is nonsense, since they're always + // supposed to be ASN.1 TLVs. RFC 6960 correctly specifies that the + // nonce is an OCTET STRING, and so you should unwrap the TLV to get + // the nonce. For now we just implement the old behavior, even though + // it's deranged. + Ok(x509_module + .call_method1("OCSPNonce", (ext_data,))? + .to_object(py)) + } else { + let oid_obj = x509_module.call_method1("ObjectIdentifier", (oid.to_string(),))?; + Ok(x509_module + .call_method1("UnrecognizedExtension", (oid_obj, ext_data))? + .to_object(py)) + } +} + fn big_asn1_uint_to_py<'p>( py: pyo3::Python<'p>, v: asn1::BigUint, @@ -274,6 +305,8 @@ pub(crate) fn create_submodule(py: pyo3::Python) -> pyo3::PyResult<&pyo3::prelud submod.add_wrapped(pyo3::wrap_pyfunction!(parse_precert_poison))?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_spki_for_data))?; + submod.add_wrapped(pyo3::wrap_pyfunction!(parse_ocsp_req_extension))?; + submod.add_wrapped(pyo3::wrap_pyfunction!(decode_dss_signature))?; submod.add_wrapped(pyo3::wrap_pyfunction!(encode_dss_signature))?; diff --git a/tests/x509/test_ocsp.py b/tests/x509/test_ocsp.py index 5d9da790af9f..6b839b3d048f 100644 --- a/tests/x509/test_ocsp.py +++ b/tests/x509/test_ocsp.py @@ -106,6 +106,19 @@ def test_load_request_with_extensions(self): b"\x04\x10{\x80Z\x1d7&\xb8\xb8OH\xd2\xf8\xbf\xd7-\xfd" ) + def test_load_request_with_unknown_extension(self): + req = _load_data( + os.path.join("x509", "ocsp", "req-ext-unknown-oid.der"), + ocsp.load_der_ocsp_request, + ) + assert len(req.extensions) == 1 + ext = req.extensions[0] + assert ext.critical is False + assert ext.value == x509.UnrecognizedExtension( + x509.ObjectIdentifier("1.3.6.1.5.5.7.48.1.2213"), + b"\x04\x10{\x80Z\x1d7&\xb8\xb8OH\xd2\xf8\xbf\xd7-\xfd", + ) + def test_load_request_two_requests(self): with pytest.raises(NotImplementedError): _load_data( diff --git a/vectors/cryptography_vectors/x509/ocsp/req-ext-unknown-oid.der b/vectors/cryptography_vectors/x509/ocsp/req-ext-unknown-oid.der new file mode 100644 index 0000000000000000000000000000000000000000..2283aae03494bd8139147cde2ab34a619558be8b GIT binary patch literal 121 zcmV-<0EYiCcQAD@O)yI^NiYcp1uG5%0vZJX1QZZorh0$~owX;QHO_+zLx`TE#|;D& z4}f7Df-zy$FDU1YMmV%A;l|nG0uTYO9{b&1t_e~y3ncz)RcN9lFd{G@1_~<%0R;sI bFaePz1QG-gdw^OUHzv5aPe{`Ezt=7OxoIbX literal 0 HcmV?d00001 From 3b6c09ba86f4c2d7f4e8fc720f038ec824de1846 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 24 Apr 2021 17:30:49 -0400 Subject: [PATCH 0243/2380] Update link (#6007) --- docs/installation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.rst b/docs/installation.rst index 278e680ce1f5..a9f40bf9afa4 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -348,5 +348,5 @@ build ``cryptography``, but not afterwards. .. _`a binary distribution`: https://wiki.openssl.org/index.php/Binaries .. _virtualenv: https://virtualenv.pypa.io/en/latest/ .. _openssl.org: https://www.openssl.org/source/ -.. _`wheel cache`: https://pip.pypa.io/en/stable/reference/pip_install/#caching +.. _`wheel cache`: https://pip.pypa.io/en/stable/cli/pip_install/#caching .. _`the Rust Project's website`: https://www.rust-lang.org/tools/install From e9f842545b96922d1ef38494eebcd85710ccae85 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 24 Apr 2021 21:30:20 -0500 Subject: [PATCH 0244/2380] update the tests to use sha2 in more places (#6008) --- tests/hazmat/primitives/test_ec.py | 8 +++---- tests/x509/test_x509.py | 36 +++++++++++++++--------------- tests/x509/test_x509_ext.py | 4 ++-- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index 708395867b6b..0bc0952ee81e 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -1188,7 +1188,7 @@ def test_key_exchange_with_vectors(self, backend, subtests): for vector in vectors: with subtests.test(): _skip_exchange_algorithm_unsupported( - backend, ec.ECDH(), ec._CURVE_TYPES[vector["curve"]] + backend, ec.ECDH(), ec._CURVE_TYPES[vector["curve"]]() ) key_numbers = vector["IUT"] @@ -1243,18 +1243,18 @@ def test_key_exchange_with_vectors(self, backend, subtests): ), ) def test_brainpool_kex(self, backend, vector): - curve = ec._CURVE_TYPES[vector["curve"].decode("ascii")] + curve = ec._CURVE_TYPES[vector["curve"].decode("ascii")]() _skip_exchange_algorithm_unsupported(backend, ec.ECDH(), curve) key = ec.EllipticCurvePrivateNumbers( int(vector["da"], 16), ec.EllipticCurvePublicNumbers( - int(vector["x_qa"], 16), int(vector["y_qa"], 16), curve() + int(vector["x_qa"], 16), int(vector["y_qa"], 16), curve ), ).private_key(backend) peer = ec.EllipticCurvePrivateNumbers( int(vector["db"], 16), ec.EllipticCurvePublicNumbers( - int(vector["x_qb"], 16), int(vector["y_qb"], 16), curve() + int(vector["x_qb"], 16), int(vector["y_qb"], 16), curve ), ).private_key(backend) shared_secret = key.exchange(ec.ECDH(), peer.public_key()) diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index c6f758574e48..9e0a6fbaaa6e 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -1616,7 +1616,7 @@ def test_build_cert(self, backend): .not_valid_after(not_valid_after) ) - cert = builder.sign(issuer_private_key, hashes.SHA1(), backend) + cert = builder.sign(issuer_private_key, hashes.SHA256(), backend) assert cert.version is x509.Version.v3 assert cert.not_valid_before == not_valid_before @@ -2432,7 +2432,7 @@ def test_build_cert_with_dsa_private_key(self, backend): .not_valid_after(not_valid_after) ) - cert = builder.sign(issuer_private_key, hashes.SHA1(), backend) + cert = builder.sign(issuer_private_key, hashes.SHA256(), backend) assert cert.version is x509.Version.v3 assert cert.not_valid_before == not_valid_before @@ -2483,7 +2483,7 @@ def test_build_cert_with_ec_private_key(self, backend): .not_valid_after(not_valid_after) ) - cert = builder.sign(issuer_private_key, hashes.SHA1(), backend) + cert = builder.sign(issuer_private_key, hashes.SHA256(), backend) assert cert.version is x509.Version.v3 assert cert.not_valid_before == not_valid_before @@ -3179,7 +3179,7 @@ def test_build_ca_request_with_path_length_none(self, backend): .add_extension( x509.BasicConstraints(ca=True, path_length=None), critical=True ) - .sign(private_key, hashes.SHA1(), backend) + .sign(private_key, hashes.SHA256(), backend) ) loaded_request = x509.load_pem_x509_csr( @@ -3322,10 +3322,10 @@ def test_build_ca_request_with_rsa(self, backend): .add_extension( x509.BasicConstraints(ca=True, path_length=2), critical=True ) - .sign(private_key, hashes.SHA1(), backend) + .sign(private_key, hashes.SHA256(), backend) ) - assert isinstance(request.signature_hash_algorithm, hashes.SHA1) + assert isinstance(request.signature_hash_algorithm, hashes.SHA256) public_key = request.public_key() assert isinstance(public_key, rsa.RSAPublicKey) subject = request.subject @@ -3357,7 +3357,7 @@ def test_build_ca_request_with_unicode(self, backend): .add_extension( x509.BasicConstraints(ca=True, path_length=2), critical=True ) - .sign(private_key, hashes.SHA1(), backend) + .sign(private_key, hashes.SHA256(), backend) ) loaded_request = x509.load_pem_x509_csr( @@ -3447,7 +3447,7 @@ def test_build_ca_request_with_multivalue_rdns(self, backend): request = ( x509.CertificateSigningRequestBuilder() .subject_name(subject) - .sign(private_key, hashes.SHA1(), backend) + .sign(private_key, hashes.SHA256(), backend) ) loaded_request = x509.load_pem_x509_csr( @@ -3468,10 +3468,10 @@ def test_build_nonca_request_with_rsa(self, backend): x509.BasicConstraints(ca=False, path_length=None), critical=True, ) - .sign(private_key, hashes.SHA1(), backend) + .sign(private_key, hashes.SHA256(), backend) ) - assert isinstance(request.signature_hash_algorithm, hashes.SHA1) + assert isinstance(request.signature_hash_algorithm, hashes.SHA256) public_key = request.public_key() assert isinstance(public_key, rsa.RSAPublicKey) subject = request.subject @@ -3504,10 +3504,10 @@ def test_build_ca_request_with_ec(self, backend): .add_extension( x509.BasicConstraints(ca=True, path_length=2), critical=True ) - .sign(private_key, hashes.SHA1(), backend) + .sign(private_key, hashes.SHA256(), backend) ) - assert isinstance(request.signature_hash_algorithm, hashes.SHA1) + assert isinstance(request.signature_hash_algorithm, hashes.SHA256) public_key = request.public_key() assert isinstance(public_key, ec.EllipticCurvePublicKey) subject = request.subject @@ -3615,10 +3615,10 @@ def test_build_ca_request_with_dsa(self, backend): .add_extension( x509.BasicConstraints(ca=True, path_length=2), critical=True ) - .sign(private_key, hashes.SHA1(), backend) + .sign(private_key, hashes.SHA256(), backend) ) - assert isinstance(request.signature_hash_algorithm, hashes.SHA1) + assert isinstance(request.signature_hash_algorithm, hashes.SHA256) public_key = request.public_key() assert isinstance(public_key, dsa.DSAPublicKey) subject = request.subject @@ -3764,10 +3764,10 @@ def test_add_two_extensions(self, backend): .add_extension( x509.BasicConstraints(ca=True, path_length=2), critical=True ) - .sign(private_key, hashes.SHA1(), backend) + .sign(private_key, hashes.SHA256(), backend) ) - assert isinstance(request.signature_hash_algorithm, hashes.SHA1) + assert isinstance(request.signature_hash_algorithm, hashes.SHA256) public_key = request.public_key() assert isinstance(public_key, rsa.RSAPublicKey) basic_constraints = request.extensions.get_extension_for_oid( @@ -4028,7 +4028,7 @@ def test_build_cert_with_aia(self, backend): .not_valid_after(not_valid_after) ) - cert = builder.sign(issuer_private_key, hashes.SHA1(), backend) + cert = builder.sign(issuer_private_key, hashes.SHA256(), backend) ext = cert.extensions.get_extension_for_oid( ExtensionOID.AUTHORITY_INFORMATION_ACCESS @@ -4099,7 +4099,7 @@ def test_build_cert_with_ski(self, backend): .not_valid_after(not_valid_after) ) - cert = builder.sign(issuer_private_key, hashes.SHA1(), backend) + cert = builder.sign(issuer_private_key, hashes.SHA256(), backend) ext = cert.extensions.get_extension_for_oid( ExtensionOID.SUBJECT_KEY_IDENTIFIER diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index 480a8757dad9..9d2585c9ef5e 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -2517,7 +2517,7 @@ def test_certbuilder(self, backend): SubjectAlternativeName(list(map(DNSName, sans))), True ) - cert = builder.sign(private_key, hashes.SHA1(), backend) + cert = builder.sign(private_key, hashes.SHA256(), backend) result = [ x.value for x in cert.extensions.get_extension_for_class( @@ -3597,7 +3597,7 @@ def test_certbuilder(self, backend): True, ) - cert = builder.sign(private_key, hashes.SHA1(), backend) + cert = builder.sign(private_key, hashes.SHA256(), backend) result = [ x.value for x in cert.extensions.get_extension_for_class( From 4d066d62141adbcc201f14e5d77ae41df1a228c2 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 24 Apr 2021 21:30:39 -0500 Subject: [PATCH 0245/2380] correct type mistake in DSA skip logic (#6009) --- tests/hazmat/primitives/test_dsa.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py index 066f83c4eca1..0192e413dc82 100644 --- a/tests/hazmat/primitives/test_dsa.py +++ b/tests/hazmat/primitives/test_dsa.py @@ -10,6 +10,7 @@ import pytest from cryptography.exceptions import AlreadyFinalized, InvalidSignature +from cryptography.hazmat.backends.interfaces import Backend from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import dsa from cryptography.hazmat.primitives.asymmetric.utils import ( @@ -36,12 +37,20 @@ } -def _skip_if_dsa_not_supported(backend, algorithm, p, q, g): +def _skip_if_dsa_not_supported( + backend: Backend, + algorithm: hashes.HashAlgorithm, + p: int, + q: int, + g: int, +) -> None: if not backend.dsa_parameters_supported( p, q, g ) or not backend.dsa_hash_supported(algorithm): pytest.skip( - "{} does not support the provided parameters".format(backend) + "{} does not support the provided args. p: {}, hash: {}".format( + backend, p.bit_length(), algorithm.name + ) ) @@ -388,7 +397,7 @@ def test_dsa_verification(self, backend, subtests): for vector in vectors: with subtests.test(): digest_algorithm = vector["digest_algorithm"].replace("-", "") - algorithm = _ALGORITHMS_DICT[digest_algorithm] + algorithm = _ALGORITHMS_DICT[digest_algorithm]() _skip_if_dsa_not_supported( backend, algorithm, vector["p"], vector["q"], vector["g"] @@ -404,9 +413,9 @@ def test_dsa_verification(self, backend, subtests): if vector["result"] == "F": with pytest.raises(InvalidSignature): - public_key.verify(sig, vector["msg"], algorithm()) + public_key.verify(sig, vector["msg"], algorithm) else: - public_key.verify(sig, vector["msg"], algorithm()) + public_key.verify(sig, vector["msg"], algorithm) def test_dsa_verify_invalid_asn1(self, backend): public_key = DSA_KEY_1024.public_numbers.public_key(backend) @@ -490,7 +499,7 @@ def test_dsa_signing(self, backend, subtests): for vector in vectors: with subtests.test(): digest_algorithm = vector["digest_algorithm"].replace("-", "") - algorithm = _ALGORITHMS_DICT[digest_algorithm] + algorithm = _ALGORITHMS_DICT[digest_algorithm]() _skip_if_dsa_not_supported( backend, algorithm, vector["p"], vector["q"], vector["g"] @@ -505,11 +514,11 @@ def test_dsa_signing(self, backend, subtests): ), x=vector["x"], ).private_key(backend) - signature = private_key.sign(vector["msg"], algorithm()) + signature = private_key.sign(vector["msg"], algorithm) assert signature private_key.public_key().verify( - signature, vector["msg"], algorithm() + signature, vector["msg"], algorithm ) def test_use_after_finalize(self, backend): From d1686fc0229b36cec18a9eac1f71b7c8641daf0e Mon Sep 17 00:00:00 2001 From: Mathias Ertl Date: Sun, 25 Apr 2021 06:40:25 +0200 Subject: [PATCH 0246/2380] make PRIVATE/PUBLIC_KEY_TYPES a public API (#6001) --- .../hazmat/backends/interfaces.py | 10 +++++---- .../hazmat/backends/openssl/backend.py | 8 +++---- .../hazmat/backends/openssl/x509.py | 8 +++---- .../asymmetric/types.py} | 4 ++-- .../hazmat/primitives/serialization/base.py | 16 +++++++------- src/cryptography/x509/base.py | 21 +++++++++++-------- src/cryptography/x509/extensions.py | 8 +++---- src/cryptography/x509/ocsp.py | 4 ++-- 8 files changed, 42 insertions(+), 37 deletions(-) rename src/cryptography/hazmat/{_types.py => primitives/asymmetric/types.py} (89%) diff --git a/src/cryptography/hazmat/backends/interfaces.py b/src/cryptography/hazmat/backends/interfaces.py index bb51060809f9..2aeee4927b3d 100644 --- a/src/cryptography/hazmat/backends/interfaces.py +++ b/src/cryptography/hazmat/backends/interfaces.py @@ -8,7 +8,9 @@ if typing.TYPE_CHECKING: - from cryptography.hazmat._types import _PRIVATE_KEY_TYPES + from cryptography.hazmat.primitives.asymmetric.types import ( + PRIVATE_KEY_TYPES, + ) from cryptography.hazmat.primitives import hashes from cryptography.x509.base import ( Certificate, @@ -306,7 +308,7 @@ def load_pem_x509_csr(self, data: bytes) -> "CertificateSigningRequest": def create_x509_csr( self, builder: "CertificateSigningRequestBuilder", - private_key: "_PRIVATE_KEY_TYPES", + private_key: "PRIVATE_KEY_TYPES", algorithm: typing.Optional["hashes.HashAlgorithm"], ) -> "CertificateSigningRequest": """ @@ -317,7 +319,7 @@ def create_x509_csr( def create_x509_certificate( self, builder: "CertificateBuilder", - private_key: "_PRIVATE_KEY_TYPES", + private_key: "PRIVATE_KEY_TYPES", algorithm: typing.Optional["hashes.HashAlgorithm"], ) -> "Certificate": """ @@ -328,7 +330,7 @@ def create_x509_certificate( def create_x509_crl( self, builder: "CertificateRevocationListBuilder", - private_key: "_PRIVATE_KEY_TYPES", + private_key: "PRIVATE_KEY_TYPES", algorithm: typing.Optional["hashes.HashAlgorithm"], ) -> "CertificateRevocationList": """ diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 4cc8b63f1f3f..29f353db3292 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -12,7 +12,6 @@ from cryptography import utils, x509 from cryptography.exceptions import UnsupportedAlgorithm, _Reasons -from cryptography.hazmat._types import _PRIVATE_KEY_TYPES from cryptography.hazmat.backends.interfaces import Backend as BackendInterface from cryptography.hazmat.backends.openssl import aead from cryptography.hazmat.backends.openssl.ciphers import _CipherContext @@ -107,6 +106,7 @@ PKCS1v15, PSS, ) +from cryptography.hazmat.primitives.asymmetric.types import PRIVATE_KEY_TYPES from cryptography.hazmat.primitives.ciphers.algorithms import ( AES, ARC4, @@ -894,7 +894,7 @@ def _x509_check_signature_params(self, private_key, algorithm): def create_x509_csr( self, builder: x509.CertificateSigningRequestBuilder, - private_key: _PRIVATE_KEY_TYPES, + private_key: PRIVATE_KEY_TYPES, algorithm: typing.Optional[hashes.HashAlgorithm], ) -> _CertificateSigningRequest: if not isinstance(builder, x509.CertificateSigningRequestBuilder): @@ -975,7 +975,7 @@ def create_x509_csr( def create_x509_certificate( self, builder: x509.CertificateBuilder, - private_key: _PRIVATE_KEY_TYPES, + private_key: PRIVATE_KEY_TYPES, algorithm: typing.Optional[hashes.HashAlgorithm], ) -> _Certificate: if not isinstance(builder, x509.CertificateBuilder): @@ -1077,7 +1077,7 @@ def _create_asn1_time(self, time): def create_x509_crl( self, builder: x509.CertificateRevocationListBuilder, - private_key: _PRIVATE_KEY_TYPES, + private_key: PRIVATE_KEY_TYPES, algorithm: typing.Optional[hashes.HashAlgorithm], ) -> _CertificateRevocationList: if not isinstance(builder, x509.CertificateRevocationListBuilder): diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index ea938a272389..54daddb08eea 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -22,7 +22,7 @@ _txt2obj_gc, ) from cryptography.hazmat.primitives import hashes, serialization -from cryptography.x509.base import _PUBLIC_KEY_TYPES +from cryptography.x509.base import PUBLIC_KEY_TYPES from cryptography.x509.name import _ASN1Type @@ -76,7 +76,7 @@ def serial_number(self) -> int: self._backend.openssl_assert(asn1_int != self._backend._ffi.NULL) return _asn1_integer_to_int(self._backend, asn1_int) - def public_key(self) -> _PUBLIC_KEY_TYPES: + def public_key(self) -> PUBLIC_KEY_TYPES: pkey = self._backend._lib.X509_get_pubkey(self._x509) if pkey == self._backend._ffi.NULL: # Remove errors from the stack. @@ -360,7 +360,7 @@ def __len__(self) -> int: def extensions(self) -> x509.Extensions: return self._backend._crl_extension_parser.parse(self._x509_crl) - def is_signature_valid(self, public_key: _PUBLIC_KEY_TYPES) -> bool: + def is_signature_valid(self, public_key: PUBLIC_KEY_TYPES) -> bool: if not isinstance( public_key, ( @@ -403,7 +403,7 @@ def __ne__(self, other: object) -> bool: def __hash__(self) -> int: return hash(self.public_bytes(serialization.Encoding.DER)) - def public_key(self) -> _PUBLIC_KEY_TYPES: + def public_key(self) -> PUBLIC_KEY_TYPES: pkey = self._backend._lib.X509_REQ_get_pubkey(self._x509_req) self._backend.openssl_assert(pkey != self._backend._ffi.NULL) pkey = self._backend._ffi.gc(pkey, self._backend._lib.EVP_PKEY_free) diff --git a/src/cryptography/hazmat/_types.py b/src/cryptography/hazmat/primitives/asymmetric/types.py similarity index 89% rename from src/cryptography/hazmat/_types.py rename to src/cryptography/hazmat/primitives/asymmetric/types.py index ba29baf28b2c..ef946cf4b75f 100644 --- a/src/cryptography/hazmat/_types.py +++ b/src/cryptography/hazmat/primitives/asymmetric/types.py @@ -13,14 +13,14 @@ ) -_PUBLIC_KEY_TYPES = typing.Union[ +PUBLIC_KEY_TYPES = typing.Union[ dsa.DSAPublicKey, rsa.RSAPublicKey, ec.EllipticCurvePublicKey, ed25519.Ed25519PublicKey, ed448.Ed448PublicKey, ] -_PRIVATE_KEY_TYPES = typing.Union[ +PRIVATE_KEY_TYPES = typing.Union[ ed25519.Ed25519PrivateKey, ed448.Ed448PrivateKey, rsa.RSAPrivateKey, diff --git a/src/cryptography/hazmat/primitives/serialization/base.py b/src/cryptography/hazmat/primitives/serialization/base.py index 30679c87ef0c..d0f304757626 100644 --- a/src/cryptography/hazmat/primitives/serialization/base.py +++ b/src/cryptography/hazmat/primitives/serialization/base.py @@ -5,27 +5,27 @@ import typing -from cryptography.hazmat._types import ( - _PRIVATE_KEY_TYPES, - _PUBLIC_KEY_TYPES, -) from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.backends.interfaces import Backend from cryptography.hazmat.primitives.asymmetric import dh +from cryptography.hazmat.primitives.asymmetric.types import ( + PRIVATE_KEY_TYPES, + PUBLIC_KEY_TYPES, +) def load_pem_private_key( data: bytes, password: typing.Optional[bytes], backend: typing.Optional[Backend] = None, -) -> _PRIVATE_KEY_TYPES: +) -> PRIVATE_KEY_TYPES: backend = _get_backend(backend) return backend.load_pem_private_key(data, password) def load_pem_public_key( data: bytes, backend: typing.Optional[Backend] = None -) -> _PUBLIC_KEY_TYPES: +) -> PUBLIC_KEY_TYPES: backend = _get_backend(backend) return backend.load_pem_public_key(data) @@ -41,14 +41,14 @@ def load_der_private_key( data: bytes, password: typing.Optional[bytes], backend: typing.Optional[Backend] = None, -) -> _PRIVATE_KEY_TYPES: +) -> PRIVATE_KEY_TYPES: backend = _get_backend(backend) return backend.load_der_private_key(data, password) def load_der_public_key( data: bytes, backend: typing.Optional[Backend] = None -) -> _PUBLIC_KEY_TYPES: +) -> PUBLIC_KEY_TYPES: backend = _get_backend(backend) return backend.load_der_public_key(data) diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index 9bbde978fda1..e97c32cb9167 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -9,7 +9,6 @@ import typing from enum import Enum -from cryptography.hazmat._types import _PRIVATE_KEY_TYPES, _PUBLIC_KEY_TYPES from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.backends.interfaces import Backend from cryptography.hazmat.primitives import hashes, serialization @@ -20,6 +19,10 @@ ed448, rsa, ) +from cryptography.hazmat.primitives.asymmetric.types import ( + PRIVATE_KEY_TYPES, + PUBLIC_KEY_TYPES, +) from cryptography.x509.extensions import Extension, ExtensionType, Extensions from cryptography.x509.name import Name from cryptography.x509.oid import ObjectIdentifier @@ -99,7 +102,7 @@ def version(self) -> Version: """ @abc.abstractmethod - def public_key(self) -> _PUBLIC_KEY_TYPES: + def public_key(self) -> PUBLIC_KEY_TYPES: """ Returns the public key """ @@ -320,7 +323,7 @@ def __iter__(self) -> typing.Iterator[RevokedCertificate]: """ @abc.abstractmethod - def is_signature_valid(self, public_key: _PUBLIC_KEY_TYPES) -> bool: + def is_signature_valid(self, public_key: PUBLIC_KEY_TYPES) -> bool: """ Verifies signature of revocation list against given public key. """ @@ -346,7 +349,7 @@ def __hash__(self) -> int: """ @abc.abstractmethod - def public_key(self) -> _PUBLIC_KEY_TYPES: + def public_key(self) -> PUBLIC_KEY_TYPES: """ Returns the public key """ @@ -518,7 +521,7 @@ def add_attribute( def sign( self, - private_key: _PRIVATE_KEY_TYPES, + private_key: PRIVATE_KEY_TYPES, algorithm: typing.Optional[hashes.HashAlgorithm], backend: typing.Optional[Backend] = None, ) -> CertificateSigningRequest: @@ -538,7 +541,7 @@ def __init__( self, issuer_name: typing.Optional[Name] = None, subject_name: typing.Optional[Name] = None, - public_key: typing.Optional[_PUBLIC_KEY_TYPES] = None, + public_key: typing.Optional[PUBLIC_KEY_TYPES] = None, serial_number: typing.Optional[int] = None, not_valid_before: typing.Optional[datetime.datetime] = None, not_valid_after: typing.Optional[datetime.datetime] = None, @@ -591,7 +594,7 @@ def subject_name(self, name: Name) -> "CertificateBuilder": def public_key( self, - key: _PUBLIC_KEY_TYPES, + key: PUBLIC_KEY_TYPES, ) -> "CertificateBuilder": """ Sets the requestor's public key (as found in the signing request). @@ -737,7 +740,7 @@ def add_extension( def sign( self, - private_key: _PRIVATE_KEY_TYPES, + private_key: PRIVATE_KEY_TYPES, algorithm: typing.Optional[hashes.HashAlgorithm], backend: typing.Optional[Backend] = None, ) -> Certificate: @@ -885,7 +888,7 @@ def add_revoked_certificate( def sign( self, - private_key: _PRIVATE_KEY_TYPES, + private_key: PRIVATE_KEY_TYPES, algorithm: typing.Optional[hashes.HashAlgorithm], backend: typing.Optional[Backend] = None, ) -> CertificateRevocationList: diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index fb229d395070..35ed776b7932 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -10,11 +10,11 @@ import typing from enum import Enum -from cryptography.hazmat._types import _PUBLIC_KEY_TYPES from cryptography.hazmat.bindings._rust import asn1 from cryptography.hazmat.primitives import constant_time, serialization from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey +from cryptography.hazmat.primitives.asymmetric.types import PUBLIC_KEY_TYPES from cryptography.x509.certificate_transparency import ( SignedCertificateTimestamp, ) @@ -40,7 +40,7 @@ ExtensionTypeVar = typing.TypeVar("ExtensionTypeVar", bound="ExtensionType") -def _key_identifier_from_public_key(public_key: _PUBLIC_KEY_TYPES) -> bytes: +def _key_identifier_from_public_key(public_key: PUBLIC_KEY_TYPES) -> bytes: if isinstance(public_key, RSAPublicKey): data = public_key.public_bytes( serialization.Encoding.DER, @@ -197,7 +197,7 @@ def __init__( @classmethod def from_issuer_public_key( - cls, public_key: _PUBLIC_KEY_TYPES + cls, public_key: PUBLIC_KEY_TYPES ) -> "AuthorityKeyIdentifier": digest = _key_identifier_from_public_key(public_key) return cls( @@ -270,7 +270,7 @@ def __init__(self, digest: bytes) -> None: @classmethod def from_public_key( - cls, public_key: _PUBLIC_KEY_TYPES + cls, public_key: PUBLIC_KEY_TYPES ) -> "SubjectKeyIdentifier": return cls(_key_identifier_from_public_key(public_key)) diff --git a/src/cryptography/x509/ocsp.py b/src/cryptography/x509/ocsp.py index 1d136e7f9be3..f35e25f8a6d1 100644 --- a/src/cryptography/x509/ocsp.py +++ b/src/cryptography/x509/ocsp.py @@ -11,8 +11,8 @@ from cryptography import x509 from cryptography.hazmat.primitives import hashes, serialization from cryptography.x509.base import ( + PRIVATE_KEY_TYPES, _EARLIEST_UTC_TIME, - _PRIVATE_KEY_TYPES, _convert_to_naive_utc_time, _reject_duplicate_extension, ) @@ -463,7 +463,7 @@ def add_extension( def sign( self, - private_key: _PRIVATE_KEY_TYPES, + private_key: PRIVATE_KEY_TYPES, algorithm: typing.Optional[hashes.HashAlgorithm], ) -> OCSPResponse: from cryptography.hazmat.backends.openssl.backend import backend From ffb425f6dca4f6eb8c8a04a887c9c8ec7745e900 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 25 Apr 2021 08:22:49 -0500 Subject: [PATCH 0247/2380] update RSA tests with larger key sizes, better hash funcs (#6010) and some more FIPS skips. This also removes some unneeded fixtures now. --- tests/hazmat/primitives/fixtures_rsa.py | 74 ------------ tests/hazmat/primitives/test_rsa.py | 143 ++++++++++++++---------- 2 files changed, 84 insertions(+), 133 deletions(-) diff --git a/tests/hazmat/primitives/fixtures_rsa.py b/tests/hazmat/primitives/fixtures_rsa.py index bfb11bc8710a..f6b5c3b9fa78 100644 --- a/tests/hazmat/primitives/fixtures_rsa.py +++ b/tests/hazmat/primitives/fixtures_rsa.py @@ -40,37 +40,6 @@ ), ) -RSA_KEY_512_ALT = RSAPrivateNumbers( - p=int( - "febe19c29a0b50fefa4f7b1832f84df1caf9be8242da25c9d689e18226e67ce5", 16 - ), - q=int( - "eb616c639dd999feda26517e1c77b6878f363fe828c4e6670ec1787f28b1e731", 16 - ), - d=int( - "80edecfde704a806445a4cc782b85d3f36f17558f385654ea767f006470fdfcbda5e2" - "206839289d3f419b4e4fb8e1acee1b4fb9c591f69b64ec83937f5829241", - 16, - ), - dmp1=int( - "7f4fa06e2a3077a54691cc5216bf13ad40a4b9fa3dd0ea4bca259487484baea5", 16 - ), - dmq1=int( - "35eaa70d5a8711c352ed1c15ab27b0e3f46614d575214535ae279b166597fac1", 16 - ), - iqmp=int( - "cc1f272de6846851ec80cb89a02dbac78f44b47bc08f53b67b4651a3acde8b19", 16 - ), - public_numbers=RSAPublicNumbers( - e=65537, - n=int( - "ea397388b999ef0f7e7416fa000367efd9a0ba0deddd3f8160d1c36d62267f210" - "fbd9c97abeb6654450ff03e7601b8caa6c6f4cba18f0b52c179d17e8f258ad5", - 16, - ), - ), -) - RSA_KEY_522 = RSAPrivateNumbers( p=int( "1a8aab9a069f92b52fdf05824f2846223dc27adfc806716a247a77d4c36885e4bf", @@ -192,49 +161,6 @@ ), ) -RSA_KEY_768 = RSAPrivateNumbers( - p=int( - "f80c0061b607f93206b68e208906498d68c6e396faf457150cf975c8f849848465869" - "7ecd402313397088044c4c2071b", - 16, - ), - q=int( - "e5b5dbecc93c6d306fc14e6aa9737f9be2728bc1a326a8713d2849b34c1cb54c63468" - "3a68abb1d345dbf15a3c492cf55", - 16, - ), - d=int( - "d44601442255ffa331212c60385b5e898555c75c0272632ff42d57c4b16ca97dbca9f" - "d6d99cd2c9fd298df155ed5141b4be06c651934076133331d4564d73faed7ce98e283" - "2f7ce3949bc183be7e7ca34f6dd04a9098b6c73649394b0a76c541", - 16, - ), - dmp1=int( - "a5763406fa0b65929661ce7b2b8c73220e43a5ebbfe99ff15ddf464fd238105ad4f2a" - "c83818518d70627d8908703bb03", - 16, - ), - dmq1=int( - "cb467a9ef899a39a685aecd4d0ad27b0bfdc53b68075363c373d8eb2bed8eccaf3533" - "42f4db735a9e087b7539c21ba9d", - 16, - ), - iqmp=int( - "5fe86bd3aee0c4d09ef11e0530a78a4534c9b833422813b5c934a450c8e564d8097a0" - "6fd74f1ebe2d5573782093f587a", - 16, - ), - public_numbers=RSAPublicNumbers( - e=65537, - n=int( - "de92f1eb5f4abf426b6cac9dd1e9bf57132a4988b4ed3f8aecc15e251028bd6df" - "46eb97c711624af7db15e6430894d1b640c13929329241ee094f5a4fe1a20bc9b" - "75232320a72bc567207ec54d6b48dccb19737cf63acc1021abb337f19130f7", - 16, - ), - ), -) - RSA_KEY_1024 = RSAPrivateNumbers( p=int( "ea4d9d9a1a068be44b9a5f8f6de0512b2c5ba1fb804a4655babba688e6e890b347c1a" diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 2c8715b24eb5..2666fdfc1787 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -39,11 +39,9 @@ RSA_KEY_2048, RSA_KEY_2048_ALT, RSA_KEY_512, - RSA_KEY_512_ALT, RSA_KEY_522, RSA_KEY_599, RSA_KEY_745, - RSA_KEY_768, RSA_KEY_CORRUPTED, ) from .utils import ( @@ -69,6 +67,16 @@ class DummyMGF(object): _salt_length = 0 +def _check_fips_key_length(backend, private_key): + if ( + backend._fips_enabled + and private_key.key_size < backend._fips_rsa_min_key_size + ): + pytest.skip( + "Key size not FIPS compliant: {}".format(private_key.key_size) + ) + + def _check_rsa_private_numbers_if_serializable(key): if isinstance(key, rsa.RSAPrivateKey): _check_rsa_private_numbers(key.private_numbers()) @@ -393,6 +401,7 @@ class TestRSASignature(object): ), skip_message="Does not support PKCS1v1.5.", ) + @pytest.mark.skip_fips(reason="SHA1 signing not supported in FIPS mode.") def test_pkcs1v15_signing(self, backend, subtests): vectors = _flatten_pkcs1_examples( load_vectors_from_file( @@ -440,6 +449,7 @@ def test_pkcs1v15_signing(self, backend, subtests): ) ), ) + @pytest.mark.skip_fips(reason="SHA1 signing not supported in FIPS mode.") def test_pss_signing(self, pkcs1_example, backend): private, public, example = pkcs1_example private_key = rsa.RSAPrivateNumbers( @@ -484,7 +494,7 @@ def test_pss_signing(self, pkcs1_example, backend): ) def test_pss_signing_sha2(self, hash_alg, backend): _skip_pss_hash_algorithm_unsupported(backend, hash_alg) - private_key = RSA_KEY_768.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) public_key = private_key.public_key() pss = padding.PSS( mgf=padding.MGF1(hash_alg), salt_length=padding.PSS.MAX_LENGTH @@ -505,6 +515,7 @@ def test_pss_signing_sha2(self, hash_alg, backend): ), skip_message="Does not support SHA512.", ) + @pytest.mark.skip_fips(reason="Unsupported key size in FIPS mode.") def test_pss_minimum_key_size_for_digest(self, backend): private_key = RSA_KEY_522.private_key(backend) private_key.sign( @@ -529,6 +540,7 @@ def test_pss_minimum_key_size_for_digest(self, backend): only_if=lambda backend: backend.hash_supported(hashes.SHA512()), skip_message="Does not support SHA512.", ) + @pytest.mark.skip_fips(reason="Unsupported key size in FIPS mode.") def test_pss_signing_digest_too_large_for_key_size(self, backend): private_key = RSA_KEY_512.private_key(backend) with pytest.raises(ValueError): @@ -551,14 +563,14 @@ def test_pss_signing_digest_too_large_for_key_size(self, backend): skip_message="Does not support PSS.", ) def test_pss_signing_salt_length_too_long(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) with pytest.raises(ValueError): private_key.sign( b"failure coming", padding.PSS( mgf=padding.MGF1(hashes.SHA1()), salt_length=1000000 ), - hashes.SHA1(), + hashes.SHA256(), ) @pytest.mark.supported( @@ -568,9 +580,9 @@ def test_pss_signing_salt_length_too_long(self, backend): skip_message="Does not support PKCS1v1.5.", ) def test_use_after_finalize(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) with pytest.warns(CryptographyDeprecationWarning): - signer = private_key.signer(padding.PKCS1v15(), hashes.SHA1()) + signer = private_key.signer(padding.PKCS1v15(), hashes.SHA256()) signer.update(b"sign me") signer.finalize() with pytest.raises(AlreadyFinalized): @@ -579,12 +591,12 @@ def test_use_after_finalize(self, backend): signer.update(b"more data") def test_unsupported_padding(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING): private_key.sign(b"msg", DummyAsymmetricPadding(), hashes.SHA1()) def test_padding_incorrect_type(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) with pytest.raises(TypeError): private_key.sign( b"msg", @@ -616,6 +628,7 @@ def test_unsupported_pss_mgf(self, backend): ), skip_message="Does not support PKCS1v1.5.", ) + @pytest.mark.skip_fips(reason="Unsupported key size in FIPS mode.") def test_pkcs1_digest_too_large_for_key_size(self, backend): private_key = RSA_KEY_599.private_key(backend) with pytest.raises(ValueError): @@ -629,15 +642,16 @@ def test_pkcs1_digest_too_large_for_key_size(self, backend): ), skip_message="Does not support PKCS1v1.5.", ) + @pytest.mark.skip_fips(reason="Unsupported key size in FIPS mode.") def test_pkcs1_minimum_key_size(self, backend): private_key = RSA_KEY_745.private_key(backend) private_key.sign(b"no failure", padding.PKCS1v15(), hashes.SHA512()) def test_sign(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) message = b"one little message" pkcs = padding.PKCS1v15() - algorithm = hashes.SHA1() + algorithm = hashes.SHA256() signature = private_key.sign(message, pkcs, algorithm) public_key = private_key.public_key() public_key.verify(signature, message, pkcs, algorithm) @@ -649,16 +663,16 @@ def test_sign(self, backend): skip_message="Does not support PSS.", ) def test_prehashed_sign(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) message = b"one little message" - h = hashes.Hash(hashes.SHA1(), backend) + h = hashes.Hash(hashes.SHA256(), backend) h.update(message) digest = h.finalize() pss = padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=0) - prehashed_alg = asym_utils.Prehashed(hashes.SHA1()) + prehashed_alg = asym_utils.Prehashed(hashes.SHA256()) signature = private_key.sign(digest, pss, prehashed_alg) public_key = private_key.public_key() - public_key.verify(signature, message, pss, hashes.SHA1()) + public_key.verify(signature, message, pss, hashes.SHA256()) @pytest.mark.supported( only_if=lambda backend: backend.hash_supported( @@ -730,12 +744,12 @@ def test_prehashed_unsupported_in_verifier_ctx(self, backend): ) def test_prehashed_unsupported_in_signature_recover(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) public_key = private_key.public_key() signature = private_key.sign( - b"sign me", padding.PKCS1v15(), hashes.SHA1() + b"sign me", padding.PKCS1v15(), hashes.SHA256() ) - prehashed_alg = asym_utils.Prehashed(hashes.SHA1()) + prehashed_alg = asym_utils.Prehashed(hashes.SHA256()) with pytest.raises(TypeError): public_key.recover_data_from_signature( signature, @@ -799,25 +813,28 @@ def test_pkcs1v15_verification(self, backend, subtests): skip_message="Does not support PKCS1v1.5.", ) def test_invalid_pkcs1v15_signature_wrong_data(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) public_key = private_key.public_key() signature = private_key.sign( - b"sign me", padding.PKCS1v15(), hashes.SHA1() + b"sign me", padding.PKCS1v15(), hashes.SHA256() ) with pytest.raises(InvalidSignature): public_key.verify( - signature, b"incorrect data", padding.PKCS1v15(), hashes.SHA1() + signature, + b"incorrect data", + padding.PKCS1v15(), + hashes.SHA256(), ) def test_invalid_pkcs1v15_signature_recover_wrong_hash_alg(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) public_key = private_key.public_key() signature = private_key.sign( - b"sign me", padding.PKCS1v15(), hashes.SHA1() + b"sign me", padding.PKCS1v15(), hashes.SHA256() ) with pytest.raises(InvalidSignature): public_key.recover_data_from_signature( - signature, padding.PKCS1v15(), hashes.SHA256() + signature, padding.PKCS1v15(), hashes.SHA512() ) def test_invalid_signature_sequence_removed(self, backend): @@ -863,14 +880,14 @@ def test_invalid_signature_sequence_removed(self, backend): skip_message="Does not support PKCS1v1.5.", ) def test_invalid_pkcs1v15_signature_wrong_key(self, backend): - private_key = RSA_KEY_512.private_key(backend) - private_key2 = RSA_KEY_512_ALT.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) + private_key2 = RSA_KEY_2048_ALT.private_key(backend) public_key = private_key2.public_key() msg = b"sign me" - signature = private_key.sign(msg, padding.PKCS1v15(), hashes.SHA1()) + signature = private_key.sign(msg, padding.PKCS1v15(), hashes.SHA256()) with pytest.raises(InvalidSignature): public_key.verify( - signature, msg, padding.PKCS1v15(), hashes.SHA1() + signature, msg, padding.PKCS1v15(), hashes.SHA256() ) @pytest.mark.supported( @@ -913,6 +930,7 @@ def test_pss_verification(self, pkcs1_example, backend): ), skip_message="Does not support PSS.", ) + @pytest.mark.skip_fips(reason="Unsupported key size in FIPS mode.") def test_invalid_pss_signature_wrong_data(self, backend): public_key = rsa.RSAPublicNumbers( n=int( @@ -947,6 +965,7 @@ def test_invalid_pss_signature_wrong_data(self, backend): ), skip_message="Does not support PSS.", ) + @pytest.mark.skip_fips(reason="Unsupported key size in FIPS mode.") def test_invalid_pss_signature_wrong_key(self, backend): signature = binascii.unhexlify( b"3a1880165014ba6eb53cc1449d13e5132ebcc0cfd9ade6d7a2494a0503bd0826" @@ -983,6 +1002,7 @@ def test_invalid_pss_signature_wrong_key(self, backend): ), skip_message="Does not support PSS.", ) + @pytest.mark.skip_fips(reason="Unsupported key size in FIPS mode.") def test_invalid_pss_signature_data_too_large_for_modulus(self, backend): # 2048 bit PSS signature signature = binascii.unhexlify( @@ -1009,13 +1029,13 @@ def test_invalid_pss_signature_data_too_large_for_modulus(self, backend): ) def test_invalid_pss_signature_recover(self, backend): - private_key = RSA_KEY_1024.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) public_key = private_key.public_key() pss_padding = padding.PSS( mgf=padding.MGF1(algorithm=hashes.SHA1()), salt_length=padding.PSS.MAX_LENGTH, ) - signature = private_key.sign(b"sign me", pss_padding, hashes.SHA1()) + signature = private_key.sign(b"sign me", pss_padding, hashes.SHA256()) # Hash algorithm cannot be absent for PSS padding with pytest.raises(TypeError): @@ -1026,7 +1046,7 @@ def test_invalid_pss_signature_recover(self, backend): # Signature data recovery not supported with PSS with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING): public_key.recover_data_from_signature( - signature, pss_padding, hashes.SHA1() + signature, pss_padding, hashes.SHA256() ) @pytest.mark.supported( @@ -1036,15 +1056,15 @@ def test_invalid_pss_signature_recover(self, backend): skip_message="Does not support PKCS1v1.5.", ) def test_use_after_finalize(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) public_key = private_key.public_key() signature = private_key.sign( - b"sign me", padding.PKCS1v15(), hashes.SHA1() + b"sign me", padding.PKCS1v15(), hashes.SHA256() ) with pytest.warns(CryptographyDeprecationWarning): verifier = public_key.verifier( - signature, padding.PKCS1v15(), hashes.SHA1() + signature, padding.PKCS1v15(), hashes.SHA256() ) verifier.update(b"sign me") verifier.verify() @@ -1054,7 +1074,7 @@ def test_use_after_finalize(self, backend): verifier.update(b"more data") def test_unsupported_padding(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) public_key = private_key.public_key() with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING): public_key.verify( @@ -1068,7 +1088,7 @@ def test_unsupported_padding(self, backend): skip_message="Does not support PKCS1v1.5.", ) def test_signature_not_bytes(self, backend): - public_key = RSA_KEY_512.public_numbers.public_key(backend) + public_key = RSA_KEY_2048.public_numbers.public_key(backend) signature = 1234 with pytest.raises(TypeError), pytest.warns( @@ -1077,7 +1097,7 @@ def test_signature_not_bytes(self, backend): public_key.verifier(signature, padding.PKCS1v15(), hashes.SHA1()) def test_padding_incorrect_type(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) public_key = private_key.public_key() with pytest.raises(TypeError): public_key.verify( @@ -1094,7 +1114,7 @@ def test_padding_incorrect_type(self, backend): skip_message="Does not support PSS.", ) def test_unsupported_pss_mgf(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) public_key = private_key.public_key() with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_MGF): public_key.verify( @@ -1119,6 +1139,7 @@ def test_unsupported_pss_mgf(self, backend): only_if=lambda backend: backend.hash_supported(hashes.SHA512()), skip_message="Does not support SHA512.", ) + @pytest.mark.skip_fips(reason="Unsupported key size in FIPS mode.") def test_pss_verify_digest_too_large_for_key_size(self, backend): private_key = RSA_KEY_512.private_key(backend) signature = binascii.unhexlify( @@ -1146,6 +1167,7 @@ def test_pss_verify_digest_too_large_for_key_size(self, backend): ), skip_message="Does not support PSS.", ) + @pytest.mark.skip_fips(reason="Unsupported key size in FIPS mode.") def test_pss_verify_salt_length_too_long(self, backend): signature = binascii.unhexlify( b"8b9a3ae9fb3b64158f3476dd8d8a1f1425444e98940e0926378baa9944d219d8" @@ -1174,30 +1196,30 @@ def test_pss_verify_salt_length_too_long(self, backend): ) def test_verify(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) message = b"one little message" pkcs = padding.PKCS1v15() - algorithm = hashes.SHA1() + algorithm = hashes.SHA256() signature = private_key.sign(message, pkcs, algorithm) public_key = private_key.public_key() public_key.verify(signature, message, pkcs, algorithm) def test_prehashed_verify(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) message = b"one little message" - h = hashes.Hash(hashes.SHA1(), backend) + h = hashes.Hash(hashes.SHA256(), backend) h.update(message) digest = h.finalize() - prehashed_alg = asym_utils.Prehashed(hashes.SHA1()) + prehashed_alg = asym_utils.Prehashed(hashes.SHA256()) pkcs = padding.PKCS1v15() - signature = private_key.sign(message, pkcs, hashes.SHA1()) + signature = private_key.sign(message, pkcs, hashes.SHA256()) public_key = private_key.public_key() public_key.verify(signature, digest, pkcs, prehashed_alg) def test_prehashed_digest_mismatch(self, backend): - public_key = RSA_KEY_512.private_key(backend).public_key() + public_key = RSA_KEY_2048.private_key(backend).public_key() message = b"one little message" - h = hashes.Hash(hashes.SHA1(), backend) + h = hashes.Hash(hashes.SHA256(), backend) h.update(message) data = h.finalize() prehashed_alg = asym_utils.Prehashed(hashes.SHA512()) @@ -1531,9 +1553,9 @@ def test_decrypt_pkcs1v15_vectors(self, backend, subtests): assert message == binascii.unhexlify(example["message"]) def test_unsupported_padding(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING): - private_key.decrypt(b"0" * 64, DummyAsymmetricPadding()) + private_key.decrypt(b"0" * 256, DummyAsymmetricPadding()) @pytest.mark.supported( only_if=lambda backend: backend.rsa_padding_supported( @@ -1542,9 +1564,9 @@ def test_unsupported_padding(self, backend): skip_message="Does not support PKCS1v1.5.", ) def test_decrypt_invalid_decrypt(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) with pytest.raises(ValueError): - private_key.decrypt(b"\x00" * 64, padding.PKCS1v15()) + private_key.decrypt(b"\x00" * 256, padding.PKCS1v15()) @pytest.mark.supported( only_if=lambda backend: backend.rsa_padding_supported( @@ -1553,9 +1575,9 @@ def test_decrypt_invalid_decrypt(self, backend): skip_message="Does not support PKCS1v1.5.", ) def test_decrypt_ciphertext_too_large(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) with pytest.raises(ValueError): - private_key.decrypt(b"\x00" * 65, padding.PKCS1v15()) + private_key.decrypt(b"\x00" * 257, padding.PKCS1v15()) @pytest.mark.supported( only_if=lambda backend: backend.rsa_padding_supported( @@ -1564,7 +1586,7 @@ def test_decrypt_ciphertext_too_large(self, backend): skip_message="Does not support PKCS1v1.5.", ) def test_decrypt_ciphertext_too_small(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) ct = binascii.unhexlify( b"50b4c14136bd198c2f3c3ed243fce036e168d56517984a263cd66492b80804f1" b"69d210f2b9bdfb48b12f9ea05009c77da257cc600ccefe3a6283789d8ea0" @@ -1667,7 +1689,7 @@ def test_invalid_oaep_decryption(self, backend): # More recent versions of OpenSSL may raise different errors. # This test triggers a failure and confirms that we properly handle # it. - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) ciphertext = private_key.public_key().encrypt( b"secure data", @@ -1678,7 +1700,7 @@ def test_invalid_oaep_decryption(self, backend): ), ) - private_key_alt = RSA_KEY_512_ALT.private_key(backend) + private_key_alt = RSA_KEY_2048_ALT.private_key(backend) with pytest.raises(ValueError): private_key_alt.decrypt( @@ -1729,10 +1751,10 @@ def test_invalid_oaep_decryption_data_to_large_for_modulus(self, backend): ) def test_unsupported_oaep_mgf(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_MGF): private_key.decrypt( - b"0" * 64, + b"0" * 256, padding.OAEP( mgf=DummyMGF(), # type: ignore[arg-type] algorithm=hashes.SHA1(), @@ -1778,6 +1800,7 @@ class TestRSAEncryption(object): ) def test_rsa_encrypt_oaep(self, key_data, pad, backend): private_key = key_data.private_key(backend) + _check_fips_key_length(backend, private_key) pt = b"encrypt me!" public_key = private_key.public_key() ct = public_key.encrypt(pt, pad) @@ -1858,6 +1881,7 @@ def test_rsa_encrypt_oaep_sha2(self, mgf1hash, oaephash, backend): ) def test_rsa_encrypt_pkcs1v15(self, key_data, pad, backend): private_key = key_data.private_key(backend) + _check_fips_key_length(backend, private_key) pt = b"encrypt me!" public_key = private_key.public_key() ct = public_key.encrypt(pt, pad) @@ -1893,6 +1917,7 @@ def test_rsa_encrypt_pkcs1v15(self, key_data, pad, backend): ) def test_rsa_encrypt_key_too_small(self, key_data, pad, backend): private_key = key_data.private_key(backend) + _check_fips_key_length(backend, private_key) public_key = private_key.public_key() # Slightly smaller than the key size but not enough for padding. with pytest.raises(ValueError): @@ -1903,7 +1928,7 @@ def test_rsa_encrypt_key_too_small(self, key_data, pad, backend): public_key.encrypt(b"\x00" * (private_key.key_size // 8 + 5), pad) def test_unsupported_padding(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) public_key = private_key.public_key() with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING): @@ -1914,7 +1939,7 @@ def test_unsupported_padding(self, backend): ) def test_unsupported_oaep_mgf(self, backend): - private_key = RSA_KEY_512.private_key(backend) + private_key = RSA_KEY_2048.private_key(backend) public_key = private_key.public_key() with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_MGF): From b1c3e2f2836ea668ea9e36623bef353e4a6daca8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Apr 2021 08:39:16 -0400 Subject: [PATCH 0248/2380] Bump libc from 0.2.93 to 0.2.94 in /src/rust (#6014) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.93 to 0.2.94. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.93...0.2.94) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index b5ceed20b367..252a760133d3 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -131,9 +131,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.93" +version = "0.2.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41" +checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e" [[package]] name = "lock_api" From bc03d94a930786580bbe016309973e0cb8052548 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 27 Apr 2021 10:01:34 -0400 Subject: [PATCH 0249/2380] reduce timeout time for CI jobs (#6016) * reduce timeout time for CI jobs * ubuntu rolling is py39 now --- .github/workflows/ci.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 18b5bf2251ec..76d5e0b71a5b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: RUST: - stable name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" - timeout-minutes: 30 + timeout-minutes: 20 steps: - uses: actions/checkout@v2 - uses: actions/cache@v2.1.5 @@ -110,12 +110,12 @@ jobs: - {IMAGE: "sid", TOXENV: "py39"} - {IMAGE: "ubuntu-bionic", TOXENV: "py36"} - {IMAGE: "ubuntu-focal", TOXENV: "py38"} - - {IMAGE: "ubuntu-rolling", TOXENV: "py38"} - - {IMAGE: "ubuntu-rolling", TOXENV: "py38-randomorder"} + - {IMAGE: "ubuntu-rolling", TOXENV: "py39"} + - {IMAGE: "ubuntu-rolling", TOXENV: "py39-randomorder"} - {IMAGE: "fedora", TOXENV: "py39"} - {IMAGE: "alpine", TOXENV: "py38"} name: "${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" - timeout-minutes: 30 + timeout-minutes: 20 steps: - uses: actions/checkout@v2 - uses: actions/cache@v2.1.5 @@ -153,7 +153,7 @@ jobs: - beta - nightly name: "${{ matrix.PYTHON.TOXENV }} with Rust ${{ matrix.RUST }}" - timeout-minutes: 30 + timeout-minutes: 20 steps: - uses: actions/checkout@v2 - uses: actions/cache@v2.1.5 @@ -189,7 +189,7 @@ jobs: linux-rust-coverage: runs-on: ubuntu-latest name: "Rust Coverage" - timeout-minutes: 30 + timeout-minutes: 20 steps: - uses: actions/checkout@v2 - uses: actions/cache@v2.1.5 @@ -253,7 +253,7 @@ jobs: RUST: - stable name: "${{ matrix.PYTHON.TOXENV }} on macOS" - timeout-minutes: 30 + timeout-minutes: 20 steps: - uses: actions/checkout@v2 - uses: actions/cache@v2.1.5 @@ -313,7 +313,7 @@ jobs: - stable JOB_NUMBER: [0, 1, 2, 3] name: "${{ matrix.PYTHON.TOXENV }} on ${{ matrix.WINDOWS.WINDOWS }} (part ${{ matrix.JOB_NUMBER }})" - timeout-minutes: 30 + timeout-minutes: 20 steps: - uses: actions/checkout@v2 - name: Setup python @@ -376,7 +376,7 @@ jobs: PYTHON: - 3.7 name: "Downstream tests for ${{ matrix.DOWNSTREAM }}" - timeout-minutes: 30 + timeout-minutes: 20 steps: - uses: actions/checkout@v2 - uses: actions/cache@v2.1.5 @@ -409,7 +409,7 @@ jobs: if: github.event_name == 'push' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest name: "linkcheck" - timeout-minutes: 30 + timeout-minutes: 20 steps: - uses: actions/checkout@v2 - name: Setup python From 9720335e76cb457e380faa67f49c5d4b8cd9f3d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Apr 2021 08:37:48 -0400 Subject: [PATCH 0250/2380] Bump syn from 1.0.70 to 1.0.71 in /src/rust (#6019) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.70 to 1.0.71. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.70...1.0.71) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 252a760133d3..6db17973d78a 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -293,9 +293,9 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "syn" -version = "1.0.70" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9505f307c872bab8eb46f77ae357c8eba1fdacead58ee5a850116b1d7f82883" +checksum = "ad184cc9470f9117b2ac6817bfe297307418819ba40552f9b3846f05c33d5373" dependencies = [ "proc-macro2", "quote", From 33bc4fd2394b0168508cff1e8a0c6645528d47de Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 28 Apr 2021 13:48:03 -0400 Subject: [PATCH 0251/2380] Set up more github actions permissioning stuff (#6020) --- .github/workflows/ci.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 76d5e0b71a5b..4c0cbaa9234e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,6 +9,8 @@ on: - '*.*' - '*.*.*' +permissions: read-all + jobs: linux: runs-on: ubuntu-latest @@ -34,6 +36,8 @@ jobs: timeout-minutes: 20 steps: - uses: actions/checkout@v2 + with: + persist-credentials: false - uses: actions/cache@v2.1.5 with: path: | @@ -118,6 +122,8 @@ jobs: timeout-minutes: 20 steps: - uses: actions/checkout@v2 + with: + persist-credentials: false - uses: actions/cache@v2.1.5 with: path: | @@ -156,6 +162,8 @@ jobs: timeout-minutes: 20 steps: - uses: actions/checkout@v2 + with: + persist-credentials: false - uses: actions/cache@v2.1.5 with: path: | @@ -192,6 +200,8 @@ jobs: timeout-minutes: 20 steps: - uses: actions/checkout@v2 + with: + persist-credentials: false - uses: actions/cache@v2.1.5 with: path: | @@ -256,6 +266,8 @@ jobs: timeout-minutes: 20 steps: - uses: actions/checkout@v2 + with: + persist-credentials: false - uses: actions/cache@v2.1.5 with: path: | @@ -316,6 +328,8 @@ jobs: timeout-minutes: 20 steps: - uses: actions/checkout@v2 + with: + persist-credentials: false - name: Setup python id: setup-python uses: actions/setup-python@v2.2.2 @@ -379,6 +393,8 @@ jobs: timeout-minutes: 20 steps: - uses: actions/checkout@v2 + with: + persist-credentials: false - uses: actions/cache@v2.1.5 with: path: | @@ -412,6 +428,8 @@ jobs: timeout-minutes: 20 steps: - uses: actions/checkout@v2 + with: + persist-credentials: false - name: Setup python uses: actions/setup-python@v2.2.2 with: From 4b31b1d7ff83cafba5da6ae71007774b85cabd89 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Apr 2021 07:45:35 -0400 Subject: [PATCH 0252/2380] Bump redox_syscall from 0.2.6 to 0.2.7 in /src/rust (#6021) Bumps redox_syscall from 0.2.6 to 0.2.7. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 6db17973d78a..cb8986de2d49 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -272,9 +272,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8270314b5ccceb518e7e578952f0b72b88222d02e8f77f5ecf7abbb673539041" +checksum = "85dd92e586f7355c633911e11f77f3d12f04b1b1bd76a198bd34ae3af8341ef2" dependencies = [ "bitflags", ] From 073fc7ba4e1236cbcd9aba795e5ba26e0e379f13 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 29 Apr 2021 13:25:03 -0400 Subject: [PATCH 0253/2380] lock down lock-issues github token permissions (#6022) --- .github/workflows/lock.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index 7356bd4af3f9..6cd1b72d8e26 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -3,6 +3,9 @@ on: schedule: - cron: '0 0 * * *' +permissions: + issues: "write" + jobs: lock: runs-on: ubuntu-latest From 056d52980a3519b6a9814ab6ca91a8e99ed5b9b0 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 29 Apr 2021 14:05:30 -0400 Subject: [PATCH 0254/2380] Make running lock by hand possible (#6023) --- .github/workflows/lock.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index 6cd1b72d8e26..5f55eb2cec49 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -1,5 +1,6 @@ name: Lock Issues on: + workflow_dispatch: schedule: - cron: '0 0 * * *' From 233579d4be0b5969836659d91f5ed6f861e415ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Apr 2021 07:03:31 -0400 Subject: [PATCH 0255/2380] Bump unicode-xid from 0.2.1 to 0.2.2 in /src/rust (#6025) Bumps [unicode-xid](https://github.com/unicode-rs/unicode-xid) from 0.2.1 to 0.2.2. - [Release notes](https://github.com/unicode-rs/unicode-xid/releases) - [Commits](https://github.com/unicode-rs/unicode-xid/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index cb8986de2d49..85221fdf7d0d 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -304,9 +304,9 @@ dependencies = [ [[package]] name = "unicode-xid" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "unindent" From 5900414e855fd7b642f577f8486e84e116fc9e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastien=20G=C3=A9rard?= Date: Sat, 1 May 2021 17:21:57 +0200 Subject: [PATCH 0256/2380] Update changelog to document the version scheme to avoid possible confusion (#6027) --- CHANGELOG.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4f368b00f4a3..f6548de81989 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,7 @@ Changelog .. note:: This version is not yet released and is under active development. +* Changed the `version scheme `_. * Added support for :class:`~cryptography.hazmat.primitives.hashes.SM3` and :class:`~cryptography.hazmat.primitives.ciphers.algorithms.SM4`, From 04ac16bce0380c0103548d69a542f8bda2795695 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 1 May 2021 12:06:20 -0400 Subject: [PATCH 0257/2380] Use a relative URL and add a sentence (#6028) * Use a relative URL and add a sentence * Update CHANGELOG.rst Co-authored-by: Paul Kehrer Co-authored-by: Paul Kehrer --- CHANGELOG.rst | 4 +++- docs/spelling_wordlist.txt | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f6548de81989..6760ba76979e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,7 +8,9 @@ Changelog .. note:: This version is not yet released and is under active development. -* Changed the `version scheme `_. +* Changed the :ref:`version scheme `. This will + result in us incrementing the major version more frequently, but does not + change our existing backwards compatibility policy. * Added support for :class:`~cryptography.hazmat.primitives.hashes.SM3` and :class:`~cryptography.hazmat.primitives.ciphers.algorithms.SM4`, diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt index cad47e53677a..c74cfa469b6a 100644 --- a/docs/spelling_wordlist.txt +++ b/docs/spelling_wordlist.txt @@ -57,6 +57,7 @@ Google hazmat Homebrew hostname +incrementing indistinguishability initialisms interoperability From a67f3066dca697af07caf88aab560086f75aa6ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 May 2021 07:55:56 -0400 Subject: [PATCH 0258/2380] Bump lock_api from 0.4.3 to 0.4.4 in /src/rust (#6032) Bumps [lock_api](https://github.com/Amanieu/parking_lot) from 0.4.3 to 0.4.4. - [Release notes](https://github.com/Amanieu/parking_lot/releases) - [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md) - [Commits](https://github.com/Amanieu/parking_lot/compare/lock_api-0.4.3...lock_api-0.4.4) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 85221fdf7d0d..2376a07f9f2e 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -137,9 +137,9 @@ checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e" [[package]] name = "lock_api" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3c91c24eae6777794bb1997ad98bbb87daf92890acab859f7eaa4320333176" +checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" dependencies = [ "scopeguard", ] From 5c434bb07365483bc1eb0115fa76ee0fd917eef5 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 3 May 2021 12:10:32 -0400 Subject: [PATCH 0259/2380] update for rust-asn1 0.4 (#6030) --- src/rust/Cargo.lock | 16 ++- src/rust/Cargo.toml | 2 +- src/rust/src/asn1.rs | 240 +++++++++++++++++++------------------------ 3 files changed, 119 insertions(+), 139 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 2376a07f9f2e..7347fda5d102 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -4,13 +4,25 @@ version = 3 [[package]] name = "asn1" -version = "0.3.8" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "842b2cc51640a5737c94248d328936d11f53ea8080e3fdba6ba523b41fa6ea15" +checksum = "85bdcc33cd1ec0ebfee9cc2d1f6497454f984c1f5c6550ad27af4b7bd7731442" dependencies = [ + "asn1_derive", "chrono", ] +[[package]] +name = "asn1_derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce75fd5d9c4402a45fdec13c4701db332b4dfd307a3220494d6888c86edfff4b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "autocfg" version = "1.0.1" diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 144f34106cbe..3c2e79b8f85c 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] lazy_static = "1" pyo3 = { version = "0.13.1" } -asn1 = { version = "0.3.8", default-features = false } +asn1 = { version = "0.4.1", default-features = false, features = ["derive"] } [features] extension-module = ["pyo3/extension-module"] diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs index 5d63bac65d82..683b4a09fbee 100644 --- a/src/rust/src/asn1.rs +++ b/src/rust/src/asn1.rs @@ -45,81 +45,60 @@ fn encode_tls_feature(py: pyo3::Python<'_>, ext: &pyo3::PyAny) -> pyo3::PyResult els.push(el?.getattr("value")?.extract::()?); } - let result = asn1::write(|w| { - w.write_element_with_type::>(&els); - }); - + let result = asn1::write_single(&asn1::SequenceOfWriter::new(&els)); Ok(pyo3::types::PyBytes::new(py, &result).to_object(py)) } #[pyo3::prelude::pyfunction] -fn parse_tls_feature(py: pyo3::Python<'_>, data: &[u8]) -> pyo3::PyResult { +fn parse_tls_feature(py: pyo3::Python<'_>, data: &[u8]) -> Result { let x509_mod = py.import("cryptography.x509.extensions")?; let tls_feature_type_to_enum = x509_mod.getattr("_TLS_FEATURE_TYPE_TO_ENUM")?; - let features = asn1::parse::<_, PyAsn1Error, _>(data, |p| { - let features = pyo3::types::PyList::empty(py); - for el in p.read_element::>()? { - let feature = el?; - let py_feature = tls_feature_type_to_enum.get_item(feature.to_object(py))?; - features.append(py_feature)?; - } - Ok(features) - })?; + let features = pyo3::types::PyList::empty(py); + for el in asn1::parse_single::>(data)? { + let feature = el?; + let py_feature = tls_feature_type_to_enum.get_item(feature.to_object(py))?; + features.append(py_feature)?; + } let x509_module = py.import("cryptography.x509")?; - x509_module - .call1("TLSFeature", (features,)) - .map(|o| o.to_object(py)) + Ok(x509_module.call1("TLSFeature", (features,))?.to_object(py)) } #[pyo3::prelude::pyfunction] fn encode_precert_poison(py: pyo3::Python<'_>, _ext: &pyo3::PyAny) -> pyo3::PyObject { - let result = asn1::write(|w| { - w.write_element(()); - }); - + let result = asn1::write_single(&()); pyo3::types::PyBytes::new(py, &result).to_object(py) } #[pyo3::prelude::pyfunction] -fn parse_precert_poison(py: pyo3::Python<'_>, data: &[u8]) -> pyo3::PyResult { - asn1::parse::<_, PyAsn1Error, _>(data, |p| { - p.read_element::<()>()?; - Ok(()) - })?; +fn parse_precert_poison(py: pyo3::Python<'_>, data: &[u8]) -> Result { + asn1::parse_single::<()>(data)?; let x509_module = py.import("cryptography.x509")?; - x509_module.call0("PrecertPoison").map(|o| o.to_object(py)) + Ok(x509_module.call0("PrecertPoison")?.to_object(py)) +} + +#[derive(asn1::Asn1Read)] +struct AlgorithmIdentifier<'a> { + _oid: asn1::ObjectIdentifier<'a>, + _params: Option>, +} + +#[derive(asn1::Asn1Read)] +struct Spki<'a> { + _algorithm: AlgorithmIdentifier<'a>, + data: asn1::BitString<'a>, } #[pyo3::prelude::pyfunction] -fn parse_spki_for_data(py: pyo3::Python<'_>, data: &[u8]) -> pyo3::PyResult { - let result = asn1::parse::<_, PyAsn1Error, _>(data, |p| { - p.read_element::()? - .parse::<_, PyAsn1Error, _>(|p| { - // AlgorithmIdentifier - p.read_element::()? - .parse::<_, PyAsn1Error, _>(|p| { - p.read_element::()?; - if !p.is_empty() { - p.read_element::()?; - } - Ok(()) - })?; - - let pubkey_data = p.read_element::()?; - if pubkey_data.padding_bits() != 0 { - return Err(pyo3::exceptions::PyValueError::new_err( - "Invalid public key encoding", - ) - .into()); - } - Ok(pubkey_data.as_bytes()) - }) - })?; - - Ok(pyo3::types::PyBytes::new(py, result).to_object(py)) +fn parse_spki_for_data(py: pyo3::Python<'_>, data: &[u8]) -> Result { + let spki = asn1::parse_single::(data)?; + if spki.data.padding_bits() != 0 { + return Err(pyo3::exceptions::PyValueError::new_err("Invalid public key encoding").into()); + } + + Ok(pyo3::types::PyBytes::new(py, spki.data.as_bytes()).to_object(py)) } lazy_static::lazy_static! { @@ -153,6 +132,12 @@ fn parse_ocsp_req_extension( } } +#[derive(asn1::Asn1Read, asn1::Asn1Write)] +struct DssSignature<'a> { + r: asn1::BigUint<'a>, + s: asn1::BigUint<'a>, +} + fn big_asn1_uint_to_py<'p>( py: pyo3::Python<'p>, v: asn1::BigUint, @@ -162,16 +147,14 @@ fn big_asn1_uint_to_py<'p>( } #[pyo3::prelude::pyfunction] -fn decode_dss_signature(py: pyo3::Python<'_>, data: &[u8]) -> pyo3::PyResult { - let (r, s) = asn1::parse::<_, PyAsn1Error, _>(data, |p| { - p.read_element::()?.parse(|p| { - let r = p.read_element::()?; - let s = p.read_element::()?; - Ok((r, s)) - }) - })?; - - Ok((big_asn1_uint_to_py(py, r)?, big_asn1_uint_to_py(py, s)?).to_object(py)) +fn decode_dss_signature(py: pyo3::Python<'_>, data: &[u8]) -> Result { + let sig = asn1::parse_single::(data)?; + + Ok(( + big_asn1_uint_to_py(py, sig.r)?, + big_asn1_uint_to_py(py, sig.s)?, + ) + .to_object(py)) } fn py_uint_to_big_endian_bytes<'p>( @@ -198,15 +181,11 @@ fn encode_dss_signature( r: &pyo3::types::PyLong, s: &pyo3::types::PyLong, ) -> pyo3::PyResult { - let r = asn1::BigUint::new(py_uint_to_big_endian_bytes(py, r)?).unwrap(); - let s = asn1::BigUint::new(py_uint_to_big_endian_bytes(py, s)?).unwrap(); - let result = asn1::write(|w| { - w.write_element_with_type::(&|w| { - w.write_element(r); - w.write_element(s); - }); - }); - + let sig = DssSignature { + r: asn1::BigUint::new(py_uint_to_big_endian_bytes(py, r)?).unwrap(), + s: asn1::BigUint::new(py_uint_to_big_endian_bytes(py, s)?).unwrap(), + }; + let result = asn1::write_single(&sig); Ok(pyo3::types::PyBytes::new(py, &result).to_object(py)) } @@ -222,79 +201,68 @@ struct TestCertificate { subject_value_tags: Vec, } -fn parse_name_value_tags(p: &mut asn1::Parser) -> asn1::ParseResult> { +#[derive(asn1::Asn1Read)] +struct Asn1Certificate<'a> { + tbs_cert: TbsCertificate<'a>, + _signature_alg: asn1::Sequence<'a>, + _signature: asn1::BitString<'a>, +} + +#[derive(asn1::Asn1Read)] +struct TbsCertificate<'a> { + #[explicit(0)] + _version: Option, + _serial: asn1::BigUint<'a>, + _signature_alg: asn1::Sequence<'a>, + + issuer: Name<'a>, + validity: Validity<'a>, + subject: Name<'a>, + + _spki: asn1::Sequence<'a>, + #[implicit(1)] + _issuer_unique_id: Option>, + #[implicit(2)] + _subject_unique_id: Option>, + #[explicit(3)] + _extensions: Option>, +} + +type Name<'a> = asn1::SequenceOf<'a, asn1::SetOf<'a, AttributeTypeValue<'a>>>; + +#[derive(asn1::Asn1Read)] +struct AttributeTypeValue<'a> { + _type: asn1::ObjectIdentifier<'a>, + value: asn1::Tlv<'a>, +} + +#[derive(asn1::Asn1Read)] +struct Validity<'a> { + not_before: asn1::Tlv<'a>, + not_after: asn1::Tlv<'a>, +} + +fn parse_name_value_tags(rdns: &mut Name<'_>) -> Result, PyAsn1Error> { let mut tags = vec![]; - for rdn in p.read_element::>>()? { + for rdn in rdns { let mut attributes = rdn?.collect::>>()?; assert_eq!(attributes.len(), 1); - let tag = attributes - .pop() - .unwrap() - .parse::<_, asn1::ParseError, _>(|p| { - p.read_element::()?; - let tlv = p.read_element::()?; - Ok(tlv.tag()) - })?; - tags.push(tag); + tags.push(attributes.pop().unwrap().value.tag()); } Ok(tags) } #[pyo3::prelude::pyfunction] -fn test_parse_certificate(data: &[u8]) -> pyo3::PyResult { - let result = asn1::parse::<_, PyAsn1Error, _>(data, |p| { - // Outer SEQUENCE - p.read_element::()?.parse(|p| { - // TBS certificate - let result = p - .read_element::()? - .parse::<_, PyAsn1Error, _>(|p| { - // Version - p.read_optional_explicit_element::(0)?; - // Serial number - p.read_element::()?; - // Inner signature algorithm - p.read_element::()?; - - // Issuer - let issuer_value_tags = parse_name_value_tags(p)?; - // Validity - let (not_before_tag, not_after_tag) = p - .read_element::()? - .parse::<_, asn1::ParseError, _>(|p| { - let not_before_tag = p.read_element::()?.tag(); - let not_after_tag = p.read_element::()?.tag(); - Ok((not_before_tag, not_after_tag)) - })?; - // Subject - let subject_value_tags = parse_name_value_tags(p)?; - - // Subject public key info - p.read_element::()?; - // Issuer unique ID - never used in the real world - p.read_optional_implicit_element::(1)?; - // Subject unique ID - never used in the real world - p.read_optional_implicit_element::(2)?; - // Extensions - p.read_optional_explicit_element::(3)?; - - Ok(TestCertificate { - not_before_tag, - not_after_tag, - issuer_value_tags, - subject_value_tags, - }) - })?; - // Outer signature algorithm - p.read_element::()?; - // Signature - p.read_element::()?; - Ok(result) - }) - })?; - - Ok(result) +fn test_parse_certificate(data: &[u8]) -> Result { + let mut asn1_cert = asn1::parse_single::(data)?; + + Ok(TestCertificate { + not_before_tag: asn1_cert.tbs_cert.validity.not_before.tag(), + not_after_tag: asn1_cert.tbs_cert.validity.not_after.tag(), + issuer_value_tags: parse_name_value_tags(&mut asn1_cert.tbs_cert.issuer)?, + subject_value_tags: parse_name_value_tags(&mut asn1_cert.tbs_cert.subject)?, + }) } pub(crate) fn create_submodule(py: pyo3::Python) -> pyo3::PyResult<&pyo3::prelude::PyModule> { From 70a8d6e8999c1d4327faac83bbadca418093a8f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 May 2021 08:18:20 -0400 Subject: [PATCH 0260/2380] Bump syn from 1.0.71 to 1.0.72 in /src/rust (#6033) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.71 to 1.0.72. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.71...1.0.72) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 7347fda5d102..0df83d8f778f 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -305,9 +305,9 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "syn" -version = "1.0.71" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad184cc9470f9117b2ac6817bfe297307418819ba40552f9b3846f05c33d5373" +checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82" dependencies = [ "proc-macro2", "quote", From 46b3be6fd7687ce7d0d01eaad1d16e1f644d16a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 May 2021 07:52:18 -0400 Subject: [PATCH 0261/2380] Bump redox_syscall from 0.2.7 to 0.2.8 in /src/rust (#6036) Bumps redox_syscall from 0.2.7 to 0.2.8. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 0df83d8f778f..2a82b0aeae43 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -284,9 +284,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85dd92e586f7355c633911e11f77f3d12f04b1b1bd76a198bd34ae3af8341ef2" +checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc" dependencies = [ "bitflags", ] From bbaeaccea48c731ad0067f6d3d85bd7523dc7aa4 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 6 May 2021 09:18:44 -0400 Subject: [PATCH 0262/2380] bump to latest openssl3 alpha (#6037) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c0cbaa9234e..5b41b39b3a8b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1j"}} - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1j"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1j", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "3.0.0-alpha15"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "3.0.0-alpha16"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "2.9.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.0.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.1.5"}} From 79416cdfe707592033de633b3e69aa8624bf4534 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 7 May 2021 00:20:31 -0500 Subject: [PATCH 0263/2380] test against 1.1.1k on our 1.1.1 jobs (#6038) --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5b41b39b3a8b..43447c4e08dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,9 +21,9 @@ jobs: - {VERSION: "pypy-3.6", TOXENV: "pypy3-nocoverage", COVERAGE: "false"} - {VERSION: "pypy-3.7", TOXENV: "pypy3-nocoverage", COVERAGE: "false"} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1j"}} - - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1j"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1j", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1k"}} + - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1k"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1k", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "3.0.0-alpha16"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "2.9.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.0.2"}} From b1416562fb9c6d1dbf527d7dbe1a8a47c8fd0955 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 7 May 2021 09:41:05 -0400 Subject: [PATCH 0264/2380] revert stylistic change now that rust coverage handles it (#6039) this was written this way to work around https://github.com/rust-lang/rust/issues/84180, which is fixed --- src/rust/src/asn1.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs index 683b4a09fbee..93a6899c5fd5 100644 --- a/src/rust/src/asn1.rs +++ b/src/rust/src/asn1.rs @@ -51,8 +51,9 @@ fn encode_tls_feature(py: pyo3::Python<'_>, ext: &pyo3::PyAny) -> pyo3::PyResult #[pyo3::prelude::pyfunction] fn parse_tls_feature(py: pyo3::Python<'_>, data: &[u8]) -> Result { - let x509_mod = py.import("cryptography.x509.extensions")?; - let tls_feature_type_to_enum = x509_mod.getattr("_TLS_FEATURE_TYPE_TO_ENUM")?; + let tls_feature_type_to_enum = py + .import("cryptography.x509.extensions")? + .getattr("_TLS_FEATURE_TYPE_TO_ENUM")?; let features = pyo3::types::PyList::empty(py); for el in asn1::parse_single::>(data)? { From 920574069ab74de9aa1b35c9ece2a1ed4a9a178f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 9 May 2021 20:56:07 -0400 Subject: [PATCH 0265/2380] Bump asn1 from 0.4.1 to 0.4.2 in /src/rust (#6041) Bumps [asn1](https://github.com/alex/rust-asn1) from 0.4.1 to 0.4.2. - [Release notes](https://github.com/alex/rust-asn1/releases) - [Commits](https://github.com/alex/rust-asn1/compare/0.4.1...0.4.2) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 8 ++++---- src/rust/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 2a82b0aeae43..a27a949e53d3 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "asn1" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bdcc33cd1ec0ebfee9cc2d1f6497454f984c1f5c6550ad27af4b7bd7731442" +checksum = "150eef712394a4e814c83771b4027c5b4e9f9cb8f5ed30e8556c8e7bdeca5864" dependencies = [ "asn1_derive", "chrono", @@ -14,9 +14,9 @@ dependencies = [ [[package]] name = "asn1_derive" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce75fd5d9c4402a45fdec13c4701db332b4dfd307a3220494d6888c86edfff4b" +checksum = "511fd42f2524a4771b3d51149b9af8c196e6ab479795ab7ef6d743f5696fd141" dependencies = [ "proc-macro2", "quote", diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 3c2e79b8f85c..38e21e57dba8 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] lazy_static = "1" pyo3 = { version = "0.13.1" } -asn1 = { version = "0.4.1", default-features = false, features = ["derive"] } +asn1 = { version = "0.4.2", default-features = false, features = ["derive"] } [features] extension-module = ["pyo3/extension-module"] From bdc0389d3bafcd796c5f2d3dd3b483cd07e851c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 May 2021 08:17:35 -0400 Subject: [PATCH 0266/2380] Bump dessant/lock-threads from 2 to 2.0.3 (#6044) Bumps [dessant/lock-threads](https://github.com/dessant/lock-threads) from 2 to 2.0.3. - [Release notes](https://github.com/dessant/lock-threads/releases) - [Changelog](https://github.com/dessant/lock-threads/blob/master/CHANGELOG.md) - [Commits](https://github.com/dessant/lock-threads/compare/v2...v2.0.3) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/lock.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index 5f55eb2cec49..cc4bc369a99f 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -11,7 +11,7 @@ jobs: lock: runs-on: ubuntu-latest steps: - - uses: dessant/lock-threads@v2 + - uses: dessant/lock-threads@v2.0.3 with: github-token: ${{ secrets.GITHUB_TOKEN }} issue-lock-inactive-days: 90 From 5c609881e063f1cc68dda3fa9b7cd114e181bbcd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 May 2021 08:20:27 -0400 Subject: [PATCH 0267/2380] Bump actions/checkout from 2 to 2.3.4 (#6047) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 2.3.4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v2.3.4) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 16 ++++++++-------- .github/workflows/wheel-builder.yml | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 43447c4e08dc..74ef2e1b22cc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 20 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2.3.4 with: persist-credentials: false - uses: actions/cache@v2.1.5 @@ -121,7 +121,7 @@ jobs: name: "${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" timeout-minutes: 20 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2.3.4 with: persist-credentials: false - uses: actions/cache@v2.1.5 @@ -161,7 +161,7 @@ jobs: name: "${{ matrix.PYTHON.TOXENV }} with Rust ${{ matrix.RUST }}" timeout-minutes: 20 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2.3.4 with: persist-credentials: false - uses: actions/cache@v2.1.5 @@ -199,7 +199,7 @@ jobs: name: "Rust Coverage" timeout-minutes: 20 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2.3.4 with: persist-credentials: false - uses: actions/cache@v2.1.5 @@ -265,7 +265,7 @@ jobs: name: "${{ matrix.PYTHON.TOXENV }} on macOS" timeout-minutes: 20 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2.3.4 with: persist-credentials: false - uses: actions/cache@v2.1.5 @@ -327,7 +327,7 @@ jobs: name: "${{ matrix.PYTHON.TOXENV }} on ${{ matrix.WINDOWS.WINDOWS }} (part ${{ matrix.JOB_NUMBER }})" timeout-minutes: 20 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2.3.4 with: persist-credentials: false - name: Setup python @@ -392,7 +392,7 @@ jobs: name: "Downstream tests for ${{ matrix.DOWNSTREAM }}" timeout-minutes: 20 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2.3.4 with: persist-credentials: false - uses: actions/cache@v2.1.5 @@ -427,7 +427,7 @@ jobs: name: "linkcheck" timeout-minutes: 20 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2.3.4 with: persist-credentials: false - name: Setup python diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 2b165041fa0b..cba2e01485de 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -67,7 +67,7 @@ jobs: BIN_PATH: '/Library/Frameworks/Python.framework/Versions/3.8/bin/python3' name: "${{ matrix.PYTHON.VERSION }} ABI ${{ matrix.PYTHON.ABI_VERSION }} macOS" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2.3.4 - run: | curl "$PYTHON_DOWNLOAD_URL" -o python.pkg sudo installer -pkg python.pkg -target / @@ -120,7 +120,7 @@ jobs: - {VERSION: "3.8", MSVC_VERSION: "2019", "ABI_VERSION": "cp36"} name: "${{ matrix.PYTHON.VERSION }} ${{ matrix.WINDOWS.WINDOWS }} ${{ matrix.PYTHON.ABI_VERSION }}" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2.3.4 - name: Setup python uses: actions/setup-python@v2.2.2 with: From faaa077c9f4beba71746a6f62d0d2b5434019a89 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 May 2021 08:25:52 -0400 Subject: [PATCH 0268/2380] Bump actions-rs/toolchain from 1 to 1.0.7 (#6043) Bumps [actions-rs/toolchain](https://github.com/actions-rs/toolchain) from 1 to 1.0.7. - [Release notes](https://github.com/actions-rs/toolchain/releases) - [Changelog](https://github.com/actions-rs/toolchain/blob/master/CHANGELOG.md) - [Commits](https://github.com/actions-rs/toolchain/compare/v1...v1.0.7) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 14 +++++++------- .github/workflows/wheel-builder.yml | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 74ef2e1b22cc..4909b2c96105 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: uses: actions/setup-python@v2.2.2 with: python-version: ${{ matrix.PYTHON.VERSION }} - - uses: actions-rs/toolchain@v1 + - uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: ${{ matrix.RUST }} @@ -176,7 +176,7 @@ jobs: uses: actions/setup-python@v2.2.2 with: python-version: ${{ matrix.PYTHON.VERSION }} - - uses: actions-rs/toolchain@v1 + - uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: ${{ matrix.RUST }} @@ -214,7 +214,7 @@ jobs: uses: actions/setup-python@v2.2.2 with: python-version: 3.9 - - uses: actions-rs/toolchain@v1 + - uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: nightly @@ -280,7 +280,7 @@ jobs: uses: actions/setup-python@v2.2.2 with: python-version: ${{ matrix.PYTHON.VERSION }} - - uses: actions-rs/toolchain@v1 + - uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: ${{ matrix.RUST }} @@ -344,7 +344,7 @@ jobs: src/rust/target/ key: ${{ runner.os }}-${{ matrix.WINDOWS.ARCH }}-${{ steps.setup-python.outputs.python-version }}-cargo-${{ hashFiles('**/Cargo.lock') }} - - uses: actions-rs/toolchain@v1 + - uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: ${{ matrix.RUST }} @@ -407,7 +407,7 @@ jobs: uses: actions/setup-python@v2.2.2 with: python-version: ${{ matrix.PYTHON }} - - uses: actions-rs/toolchain@v1 + - uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: ${{ matrix.RUST }} @@ -434,7 +434,7 @@ jobs: uses: actions/setup-python@v2.2.2 with: python-version: 3.9 - - uses: actions-rs/toolchain@v1 + - uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: stable diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index cba2e01485de..160ba8f0e6ca 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -79,7 +79,7 @@ jobs: ${{ matrix.PYTHON.BIN_PATH }} .github/workflows/download_openssl.py macos openssl-macos-x86-64 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - uses: actions-rs/toolchain@v1 + - uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: stable @@ -126,7 +126,7 @@ jobs: with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} - - uses: actions-rs/toolchain@v1 + - uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: stable From 44d042c27b7c22541f0ee2e9fe1174fa9154e5ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 May 2021 08:49:20 -0400 Subject: [PATCH 0269/2380] Bump actions-rs/install from 0.1 to 0.1.2 (#6045) Bumps [actions-rs/install](https://github.com/actions-rs/install) from 0.1 to 0.1.2. - [Release notes](https://github.com/actions-rs/install/releases) - [Changelog](https://github.com/actions-rs/install/blob/master/CHANGELOG.md) - [Commits](https://github.com/actions-rs/install/compare/v0.1...v0.1.2) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4909b2c96105..9a9886a055a6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -221,7 +221,7 @@ jobs: override: true default: true components: llvm-tools-preview - - uses: actions-rs/install@v0.1 + - uses: actions-rs/install@v0.1.2 with: crate: cargo-binutils version: latest From 1b922ed1dee0cd7e165a868639ce6d0869c8b2f5 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Wed, 12 May 2021 14:54:23 +0200 Subject: [PATCH 0270/2380] Use well-defined enum representation (#6042) Python 3.10 changed enum's object and string representation. PyCA cryptography now uses a custom subclass of enum.Enum() will well-defined __repr__ and __str__ from Python 3.9. Related: https://bugs.python.org/issue40066 Fixes: https://github.com/pyca/cryptography/issues/5995 Signed-off-by: Christian Heimes --- .github/workflows/ci.yml | 1 + src/cryptography/exceptions.py | 4 ++-- src/cryptography/hazmat/primitives/_serialization.py | 11 ++++++----- src/cryptography/hazmat/primitives/kdf/kbkdf.py | 5 ++--- .../hazmat/primitives/serialization/pkcs7.py | 4 ++-- src/cryptography/utils.py | 11 +++++++++++ src/cryptography/x509/base.py | 4 ++-- src/cryptography/x509/certificate_transparency.py | 7 ++++--- src/cryptography/x509/extensions.py | 6 +++--- src/cryptography/x509/name.py | 4 ++-- src/cryptography/x509/ocsp.py | 8 ++++---- tests/test_cryptography_utils.py | 11 +++++++++++ 12 files changed, 50 insertions(+), 26 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9a9886a055a6..49b41971ab5b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,7 @@ jobs: - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.1.5"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.2.5"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.3.2"}} + - {VERSION: "3.10-dev", TOXENV: "py310"} RUST: - stable name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" diff --git a/src/cryptography/exceptions.py b/src/cryptography/exceptions.py index f5860590571b..3bd98d8252ad 100644 --- a/src/cryptography/exceptions.py +++ b/src/cryptography/exceptions.py @@ -3,10 +3,10 @@ # for complete details. -from enum import Enum +from cryptography import utils -class _Reasons(Enum): +class _Reasons(utils.Enum): BACKEND_MISSING_INTERFACE = 0 UNSUPPORTED_HASH = 1 UNSUPPORTED_CIPHER = 2 diff --git a/src/cryptography/hazmat/primitives/_serialization.py b/src/cryptography/hazmat/primitives/_serialization.py index 96a5ed9b75d9..160a6b89c089 100644 --- a/src/cryptography/hazmat/primitives/_serialization.py +++ b/src/cryptography/hazmat/primitives/_serialization.py @@ -3,13 +3,14 @@ # for complete details. import abc -from enum import Enum + +from cryptography import utils # This exists to break an import cycle. These classes are normally accessible # from the serialization module. -class Encoding(Enum): +class Encoding(utils.Enum): PEM = "PEM" DER = "DER" OpenSSH = "OpenSSH" @@ -18,14 +19,14 @@ class Encoding(Enum): SMIME = "S/MIME" -class PrivateFormat(Enum): +class PrivateFormat(utils.Enum): PKCS8 = "PKCS8" TraditionalOpenSSL = "TraditionalOpenSSL" Raw = "Raw" OpenSSH = "OpenSSH" -class PublicFormat(Enum): +class PublicFormat(utils.Enum): SubjectPublicKeyInfo = "X.509 subjectPublicKeyInfo with PKCS#1" PKCS1 = "Raw PKCS#1" OpenSSH = "OpenSSH" @@ -34,7 +35,7 @@ class PublicFormat(Enum): UncompressedPoint = "X9.62 Uncompressed Point" -class ParameterFormat(Enum): +class ParameterFormat(utils.Enum): PKCS3 = "PKCS3" diff --git a/src/cryptography/hazmat/primitives/kdf/kbkdf.py b/src/cryptography/hazmat/primitives/kdf/kbkdf.py index eee2200be4bf..1d106d1e5dec 100644 --- a/src/cryptography/hazmat/primitives/kdf/kbkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/kbkdf.py @@ -4,7 +4,6 @@ import typing -from enum import Enum from cryptography import utils from cryptography.exceptions import ( @@ -19,11 +18,11 @@ from cryptography.hazmat.primitives.kdf import KeyDerivationFunction -class Mode(Enum): +class Mode(utils.Enum): CounterMode = "ctr" -class CounterLocation(Enum): +class CounterLocation(utils.Enum): BeforeFixed = "before_fixed" AfterFixed = "after_fixed" diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs7.py b/src/cryptography/hazmat/primitives/serialization/pkcs7.py index c6b2eec21092..79e9b64da800 100644 --- a/src/cryptography/hazmat/primitives/serialization/pkcs7.py +++ b/src/cryptography/hazmat/primitives/serialization/pkcs7.py @@ -3,8 +3,8 @@ # for complete details. import typing -from enum import Enum +from cryptography import utils from cryptography import x509 from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.backends.interfaces import Backend @@ -36,7 +36,7 @@ def load_der_pkcs7_certificates(data: bytes) -> typing.List[x509.Certificate]: ] -class PKCS7Options(Enum): +class PKCS7Options(utils.Enum): Text = "Add text/plain MIME type" Binary = "Don't translate input data into canonical MIME format" DetachedSignature = "Don't embed data in the PKCS7 structure" diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index a8fd7d01a7c9..f07d5fdad249 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -4,6 +4,7 @@ import abc +import enum import inspect import sys import typing @@ -152,3 +153,13 @@ def inner(instance): "int_from_bytes is deprecated, use int.from_bytes instead", DeprecatedIn34, ) + + +# Python 3.10 changed representation of enums. We use well-defined object +# representation and string representation from Python 3.9. +class Enum(enum.Enum): + def __repr__(self): + return f"<{self.__class__.__name__}.{self._name_}: {self._value_!r}>" + + def __str__(self): + return f"{self.__class__.__name__}.{self._name_}" diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index e97c32cb9167..4e8b4a844a41 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -7,8 +7,8 @@ import datetime import os import typing -from enum import Enum +from cryptography import utils from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.backends.interfaces import Backend from cryptography.hazmat.primitives import hashes, serialization @@ -71,7 +71,7 @@ def _convert_to_naive_utc_time(time: datetime.datetime) -> datetime.datetime: return time -class Version(Enum): +class Version(utils.Enum): v1 = 0 v3 = 2 diff --git a/src/cryptography/x509/certificate_transparency.py b/src/cryptography/x509/certificate_transparency.py index d51bee92effc..d80f051a68ae 100644 --- a/src/cryptography/x509/certificate_transparency.py +++ b/src/cryptography/x509/certificate_transparency.py @@ -5,15 +5,16 @@ import abc import datetime -from enum import Enum +from cryptography import utils -class LogEntryType(Enum): + +class LogEntryType(utils.Enum): X509_CERTIFICATE = 0 PRE_CERTIFICATE = 1 -class Version(Enum): +class Version(utils.Enum): v1 = 0 diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index 35ed776b7932..58e7ea7f5a5d 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -8,8 +8,8 @@ import hashlib import ipaddress import typing -from enum import Enum +from cryptography import utils from cryptography.hazmat.bindings._rust import asn1 from cryptography.hazmat.primitives import constant_time, serialization from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey @@ -671,7 +671,7 @@ def crl_issuer(self) -> typing.Optional[typing.List[GeneralName]]: return self._crl_issuer -class ReasonFlags(Enum): +class ReasonFlags(utils.Enum): unspecified = "unspecified" key_compromise = "keyCompromise" ca_compromise = "cACompromise" @@ -1035,7 +1035,7 @@ def __hash__(self) -> int: return hash(tuple(self._features)) -class TLSFeatureType(Enum): +class TLSFeatureType(utils.Enum): # status_request is defined in RFC 6066 and is used for what is commonly # called OCSP Must-Staple when present in the TLS Feature extension in an # X.509 certificate. diff --git a/src/cryptography/x509/name.py b/src/cryptography/x509/name.py index e0ba6674d5b1..d1a3e3331fb1 100644 --- a/src/cryptography/x509/name.py +++ b/src/cryptography/x509/name.py @@ -3,14 +3,14 @@ # for complete details. import typing -from enum import Enum +from cryptography import utils from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.backends.interfaces import Backend from cryptography.x509.oid import NameOID, ObjectIdentifier -class _ASN1Type(Enum): +class _ASN1Type(utils.Enum): UTF8String = 12 NumericString = 18 PrintableString = 19 diff --git a/src/cryptography/x509/ocsp.py b/src/cryptography/x509/ocsp.py index f35e25f8a6d1..7f8711b79d2d 100644 --- a/src/cryptography/x509/ocsp.py +++ b/src/cryptography/x509/ocsp.py @@ -6,8 +6,8 @@ import abc import datetime import typing -from enum import Enum +from cryptography import utils from cryptography import x509 from cryptography.hazmat.primitives import hashes, serialization from cryptography.x509.base import ( @@ -27,12 +27,12 @@ } -class OCSPResponderEncoding(Enum): +class OCSPResponderEncoding(utils.Enum): HASH = "By Hash" NAME = "By Name" -class OCSPResponseStatus(Enum): +class OCSPResponseStatus(utils.Enum): SUCCESSFUL = 0 MALFORMED_REQUEST = 1 INTERNAL_ERROR = 2 @@ -58,7 +58,7 @@ def _verify_algorithm(algorithm): ) -class OCSPCertStatus(Enum): +class OCSPCertStatus(utils.Enum): GOOD = 0 REVOKED = 1 UNKNOWN = 2 diff --git a/tests/test_cryptography_utils.py b/tests/test_cryptography_utils.py index 6b795e0c683a..803997ac06ea 100644 --- a/tests/test_cryptography_utils.py +++ b/tests/test_cryptography_utils.py @@ -2,6 +2,7 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. +import enum import typing import pytest @@ -51,3 +52,13 @@ def t(self): assert len(accesses) == 1 assert t.t == 14 assert len(accesses) == 1 + + +def test_enum(): + class TestEnum(utils.Enum): + value = "something" + + assert issubclass(TestEnum, enum.Enum) + assert isinstance(TestEnum.value, enum.Enum) + assert repr(TestEnum.value) == "" + assert str(TestEnum.value) == "TestEnum.value" From 3465cb88245022afe68602f3610e8c553660521d Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 18 May 2021 09:05:56 -0400 Subject: [PATCH 0271/2380] libressl 3.3.3 (#6052) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 49b41971ab5b..5b71f13294f3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.0.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.1.5"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.2.5"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.3.2"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.3.3"}} - {VERSION: "3.10-dev", TOXENV: "py310"} RUST: - stable From f19b0f41f552b606e8860a80f1184b733212c733 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 19 May 2021 15:56:36 -0400 Subject: [PATCH 0272/2380] Point folks towards irc.libera.chat (#6054) * Point folks towards irc.libera.chat * Update community.rst --- docs/community.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/community.rst b/docs/community.rst index da6376531ab3..7feb476e61be 100644 --- a/docs/community.rst +++ b/docs/community.rst @@ -7,7 +7,7 @@ You can find ``cryptography`` all over the web: * `Source code`_ * `Issue tracker`_ * `Documentation`_ -* IRC: ``#cryptography-dev`` on ``irc.freenode.net`` +* IRC: ``#pyca`` on ``irc.libera.chat`` Wherever we interact, we adhere to the `Python Community Code of Conduct`_. From 996b6934d544e036ec8fbdb57785c727bbf5b879 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 19 May 2021 16:26:15 -0400 Subject: [PATCH 0273/2380] Update IRC in the README as well (#6055) --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index bb5f6f300666..1a4e65a0fc9d 100644 --- a/README.rst +++ b/README.rst @@ -54,7 +54,7 @@ If you run into bugs, you can file them in our `issue tracker`_. We maintain a `cryptography-dev`_ mailing list for development discussion. -You can also join ``#cryptography-dev`` on Freenode to ask questions or get +You can also join ``#pyca`` on ``irc.libera.chat`` to ask questions or get involved. Security From 84beab1921a3734e9f9e27b051eccdc2858354c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 May 2021 07:36:44 -0400 Subject: [PATCH 0274/2380] Bump proc-macro2 from 1.0.26 to 1.0.27 in /src/rust (#6058) Bumps [proc-macro2](https://github.com/alexcrichton/proc-macro2) from 1.0.26 to 1.0.27. - [Release notes](https://github.com/alexcrichton/proc-macro2/releases) - [Commits](https://github.com/alexcrichton/proc-macro2/compare/1.0.26...1.0.27) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index a27a949e53d3..0732f7cea8f9 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -227,9 +227,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" +checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" dependencies = [ "unicode-xid", ] From ec05c55c206b2839903732b19bee780092f0b497 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 20 May 2021 10:23:54 -0400 Subject: [PATCH 0275/2380] Bump to latest openssl 3 alpha (#6060) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5b71f13294f3..94d3cb20c82f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1k"}} - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1k"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1k", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "3.0.0-alpha16"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "3.0.0-alpha17"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "2.9.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.0.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.1.5"}} From 596d30d04083e69446ebe1a94febea29e8c5029f Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 23 May 2021 13:56:55 -0400 Subject: [PATCH 0276/2380] Use Rust extension parser for OCSP basicresp (#6062) --- src/cryptography/hazmat/backends/openssl/backend.py | 4 ++-- .../hazmat/backends/openssl/decode_asn1.py | 11 ----------- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 29f353db3292..ce9b3dc63e82 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -21,7 +21,6 @@ _CRL_EXTENSION_HANDLERS, _EXTENSION_HANDLERS_BASE, _EXTENSION_HANDLERS_SCT, - _OCSP_BASICRESP_EXTENSION_HANDLERS, _OCSP_SINGLERESP_EXTENSION_HANDLERS_SCT, _REVOKED_EXTENSION_HANDLERS, _X509ExtensionParser, @@ -431,7 +430,8 @@ def _register_x509_ext_parsers(self): self, ext_count=self._lib.OCSP_BASICRESP_get_ext_count, get_ext=self._lib.OCSP_BASICRESP_get_ext, - handlers=_OCSP_BASICRESP_EXTENSION_HANDLERS, + # OCSP basic resp has the same extensions as req. + rust_callback=asn1.parse_ocsp_req_extension, ) self._ocsp_singleresp_ext_parser = _X509ExtensionParser( self, diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 9a85e9464dce..eb384263d6de 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -14,7 +14,6 @@ CRLEntryExtensionOID, CertificatePoliciesOID, ExtensionOID, - OCSPExtensionOID, ) @@ -819,12 +818,6 @@ def _parse_asn1_generalized_time(backend, generalized_time): return datetime.datetime.strptime(time, "%Y%m%d%H%M%SZ") -def _decode_nonce(backend, nonce): - nonce = backend._ffi.cast("ASN1_OCTET_STRING *", nonce) - nonce = backend._ffi.gc(nonce, backend._lib.ASN1_OCTET_STRING_free) - return x509.OCSPNonce(_asn1_string_to_bytes(backend, nonce)) - - _EXTENSION_HANDLERS_BASE = { ExtensionOID.BASIC_CONSTRAINTS: _decode_basic_constraints, ExtensionOID.SUBJECT_KEY_IDENTIFIER: _decode_subject_key_identifier, @@ -871,10 +864,6 @@ def _decode_nonce(backend, nonce): ExtensionOID.FRESHEST_CRL: _decode_freshest_crl, } -_OCSP_BASICRESP_EXTENSION_HANDLERS = { - OCSPExtensionOID.NONCE: _decode_nonce, -} - _OCSP_SINGLERESP_EXTENSION_HANDLERS_SCT = { ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS: ( _decode_signed_certificate_timestamps From fa2f68dd35da79a52ef05713bfb5f0ed1d380c8a Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 24 May 2021 00:53:33 -0400 Subject: [PATCH 0277/2380] Added a test vector for OCSP with an unknown extension (#6063) --- docs/development/test-vectors.rst | 2 ++ tests/x509/test_ocsp.py | 13 +++++++++++++ .../x509/ocsp/resp-unknown-extension.der | Bin 0 -> 1894 bytes 3 files changed, 15 insertions(+) create mode 100644 vectors/cryptography_vectors/x509/ocsp/resp-unknown-extension.der diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index e8e466d4a999..b1ae00c08c59 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -540,6 +540,8 @@ X.509 OCSP Test Vectors ``CT Certificate SCTs`` single extension, from the SwissSign OCSP responder. * ``x509/ocsp/ocsp-army.deps.mil-resp.der`` - An OCSP response containing multiple ``SINGLERESP`` values. +* ``x509/ocsp/resp-unknown-extension.der`` - An OCSP response containing an + extension with an unknown OID. Custom X.509 OCSP Test Vectors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/x509/test_ocsp.py b/tests/x509/test_ocsp.py index 6b839b3d048f..9772c9bf3a7d 100644 --- a/tests/x509/test_ocsp.py +++ b/tests/x509/test_ocsp.py @@ -1005,6 +1005,19 @@ def test_response_extensions(self): b'\x04\x105\x957\x9fa\x03\x83\x87\x89rW\x8f\xae\x99\xf7"' ) + def test_response_unknown_extension(self): + resp = _load_data( + os.path.join("x509", "ocsp", "resp-unknown-extension.der"), + ocsp.load_der_ocsp_response, + ) + assert len(resp.extensions) == 1 + ext = resp.extensions[0] + assert ext.critical is False + assert ext.value == x509.UnrecognizedExtension( + x509.ObjectIdentifier("1.3.6.1.5.5.7.48.1.2.200"), + b'\x04\x105\x957\x9fa\x03\x83\x87\x89rW\x8f\xae\x99\xf7"', + ) + def test_serialize_reponse(self): resp_bytes = load_vectors_from_file( filename=os.path.join("x509", "ocsp", "resp-revoked.der"), diff --git a/vectors/cryptography_vectors/x509/ocsp/resp-unknown-extension.der b/vectors/cryptography_vectors/x509/ocsp/resp-unknown-extension.der new file mode 100644 index 0000000000000000000000000000000000000000..2d127d74ae39d6ed5595728d85f3ef8f06cdc705 GIT binary patch literal 1894 zcmXqLVo%~?WLVI|9&OOX9?r(8&Bn;e%5K2O$kN2_0TgmEXkxTlm~W74$Zf#M#vIDR zCd}mIYba?T4&rbL3j~(thb5+D7AyE<=4O_prWlGFh=QcJh57uQg98+TQi}`n^HNfa z47Ch2KoZQtif}z(6^^AP8Tmz-C6x-nndy0nC8b5F68uI6h86~v28M=~CKiU~Q3j2D z294bYzCbsyYV$EONwG4ph-9tfEnLZdF3Eg?T>D#}-e1!fv0q{l*(}t#b)~oI9#Mu5 z4KHt0w0{(?DPt1hknNr^Z_=-4ond#LX>}TLF5IJXd7&889y23zLnC7Y1H-5V%v_8t z7`87EgbNu%9kfu@K-oZ%jT;tTOpP8aLM#HNQ_bfmGB>w(7KQh(oB3VIfR~L^tIebB zJ1-+6H!A~k6C)!-Nali@Dl=KiJ^r6hW)MDl;dMOA)h!10hb(eupDnqye$T~?JGf33 zZ=WF;cIx)SN1~c@?(ZxxdhfV_*HvKMf}@AbbrQEl`t*FamtS+trkY>5tyPgZ=kBf+ zo%)|k{=ewdUG4HCbYf8Rfw)%F$lGpOPESh?mRRzu-eo1 ziBQ}t_RCA{@9EtTn(*x3Gj2}do1dO|9ZCID-?Z`Bs^Y^3J@#q_EqgGt<|6-xTbGZ< z-|yJ`QPfE;D2oCm9@N{-ma5pxP6X!KF zGc+_XHZ(P{FtCUc=QT0{a?K1)Oo7QSiq451nA1?w3nMta@G}6#xtKr+XK6%JfpMLu z_Y2RZp6s4s*2O!l!lZo?=g-V|R6KpTgY0tm(AW#?_YQnq;%IvN?+J(LW_z99tP0=8 zXUnjCU6J}8(;4|+ZFbdupQ;(ps3`8S*tR8$^(-S>#$ScT>untWTe_AlN_!|WJO9j~ zu2bIs`j?2_va?(Mx#COb_x;B&Z@JZJ*_ShQ!P&jpt5fb5HGD2jUU09XRaQAS{g!C1 zsg-(&+JmKA@AK}ubhy6tIm`BI7mH08=ecFOSoI!Q*EnS463L#r$L(kFhC>(5_Y zUCqSI$iTR`ajrq*EO1#QE6l=Vz+k|SD79Ewm{=LWMU$)oi+};20S_A&Fo&`*?u%e- z(lOuzCJ9-7M#ldvEX+*o4FzA6ik0T&wwBqK9(8pwkLm02VV#2T=cB?ht}1$-=G zEFz2(WSHl_ihk+P{`2uEHb#GS%YQ4;k}Pu*6C(r5dX)$F4hDbUAy*@+yeGcO_ogpr z;HmwsOl}p{Mwfb;84q}Vyz%^J%%fhNyB~DaUUHhfc~RZh-kR_yd&{4HKfb$r+)`9q z5x1V%Yhv15#bq72Mwiz-XLS>6J(3;0CU57|BW*{W)Ol7e(Q*scbzv@TOQ?FZ z@y+a9!@cGv=WYasoOZfdc`}t(Z&S1e|GmBLChCh1dz@MjwqNz|mzFRiF5x#@V@^)n zZFBwE1MXKR?ieg-cfVJ0w^dDG)AAqB_6g;gFhBGw;=H7AR@YVdz(Q-Wh<@cW_F0$z z%&)wB#`2%^$|r`l4Rh~4oV@O~i)y~sUFJWRwr1ShyUM_^CU5QmmEVPjrd&w7sL6kz z)qqVcN#y0z;{Q+LeX=AnKUIuA;=Ra8bw@7Mwzof)Um3zbEGps8rqFJB>gMh0Rpz&aZqB_ewQ_ICyI;?ouiWK{;4p&>I ze%fQ_EY~)#GbQyUTYMMKvbZu&-}*AA=#J`A-K(NToadi8a?5eP_e{KI9CPFMiN$^Z DXnWaY literal 0 HcmV?d00001 From f94ce1271516de7e3cc94b5da4bf81ca1b6064e4 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 24 May 2021 20:58:33 -0400 Subject: [PATCH 0278/2380] Added a test vector for duplicate extensions in OCSP requests (#6064) --- docs/development/test-vectors.rst | 6 ++++-- tests/x509/test_ocsp.py | 8 ++++++++ .../x509/ocsp/req-duplicate-ext.der | Bin 0 -> 155 bytes 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 vectors/cryptography_vectors/x509/ocsp/req-duplicate-ext.der diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index b1ae00c08c59..8799786031a6 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -540,8 +540,6 @@ X.509 OCSP Test Vectors ``CT Certificate SCTs`` single extension, from the SwissSign OCSP responder. * ``x509/ocsp/ocsp-army.deps.mil-resp.der`` - An OCSP response containing multiple ``SINGLERESP`` values. -* ``x509/ocsp/resp-unknown-extension.der`` - An OCSP response containing an - extension with an unknown OID. Custom X.509 OCSP Test Vectors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -555,6 +553,10 @@ Custom X.509 OCSP Test Vectors extension. * ``x509/ocsp/req-ext-unknown-oid.der`` - An OCSP request containing an extension with an unknown OID. +* ``x509/ocsp/req-duplicate-ext.der`` - An OCSP request with duplicate + extensions. +* ``x509/ocsp/resp-unknown-extension.der`` - An OCSP response containing an + extension with an unknown OID. Custom PKCS12 Test Vectors ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/x509/test_ocsp.py b/tests/x509/test_ocsp.py index 9772c9bf3a7d..af05b83fa923 100644 --- a/tests/x509/test_ocsp.py +++ b/tests/x509/test_ocsp.py @@ -119,6 +119,14 @@ def test_load_request_with_unknown_extension(self): b"\x04\x10{\x80Z\x1d7&\xb8\xb8OH\xd2\xf8\xbf\xd7-\xfd", ) + def test_load_request_with_duplicate_extension(self): + req = _load_data( + os.path.join("x509", "ocsp", "req-duplicate-ext.der"), + ocsp.load_der_ocsp_request, + ) + with pytest.raises(x509.DuplicateExtension): + req.extensions + def test_load_request_two_requests(self): with pytest.raises(NotImplementedError): _load_data( diff --git a/vectors/cryptography_vectors/x509/ocsp/req-duplicate-ext.der b/vectors/cryptography_vectors/x509/ocsp/req-duplicate-ext.der new file mode 100644 index 0000000000000000000000000000000000000000..d92324dfe9b21713bb3dc80827b1e73111c6ce2a GIT binary patch literal 155 zcmXqLoMF&7)xg)l+rZO+lZ{oIkC{n|m4QV>Abwd@1IOI0>hn#{HFG<6%v*e%mqmoX zAyKBuF!8Fs#`9h`i!C}2kKKI4B*3^{?)Tleb(}#)+$#UFLo*h+7&sZovvF#(F|x9< f8!$4l2(buMH$=&rtL@m~?{VqJ{_DDb2`T^pwR Date: Mon, 24 May 2021 21:54:13 -0400 Subject: [PATCH 0279/2380] Retry in more cases (#6066) --- .github/workflows/download_openssl.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/download_openssl.py b/.github/workflows/download_openssl.py index 496e05385b0e..1c192cf2539b 100644 --- a/.github/workflows/download_openssl.py +++ b/.github/workflows/download_openssl.py @@ -12,9 +12,14 @@ def get_response(session, url, token): # Retry on non-502s for i in range(5): - response = session.get( - url, headers={"Authorization": "token " + token} - ) + try: + response = session.get( + url, headers={"Authorization": "token " + token} + ) + except requests.exceptions.ChunkedEncodingError as e: + print("Exception ({}) fetching {}, retrying".format(e, url)) + time.sleep(2) + continue if response.status_code != 200: print( "HTTP error ({}) fetching {}, retrying".format( From b937d25173b9b6bae6586d9298e91457786710c2 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 24 May 2021 21:55:41 -0400 Subject: [PATCH 0280/2380] Added a test vector for an OCSP response with an unknown hash algorithm (#6065) --- docs/development/test-vectors.rst | 2 ++ tests/x509/test_ocsp.py | 8 ++++++++ .../x509/ocsp/resp-unknown-hash-alg.der | Bin 0 -> 491 bytes 3 files changed, 10 insertions(+) create mode 100644 vectors/cryptography_vectors/x509/ocsp/resp-unknown-hash-alg.der diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index 8799786031a6..edd2c609f430 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -557,6 +557,8 @@ Custom X.509 OCSP Test Vectors extensions. * ``x509/ocsp/resp-unknown-extension.der`` - An OCSP response containing an extension with an unknown OID. +* ``x509/ocsp/resp-unknown-hash-alg.der`` - AN OCSP response containing an + invalid hash algorithm OID. Custom PKCS12 Test Vectors ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/x509/test_ocsp.py b/tests/x509/test_ocsp.py index af05b83fa923..e1ea7590a33b 100644 --- a/tests/x509/test_ocsp.py +++ b/tests/x509/test_ocsp.py @@ -976,6 +976,14 @@ def test_load_invalid_signature_oid(self): with pytest.raises(UnsupportedAlgorithm): resp.signature_hash_algorithm + def test_unknown_hash_algorithm(self): + resp = _load_data( + os.path.join("x509", "ocsp", "resp-unknown-hash-alg.der"), + ocsp.load_der_ocsp_response, + ) + with pytest.raises(UnsupportedAlgorithm): + resp.hash_algorithm + def test_load_responder_key_hash(self): resp = _load_data( os.path.join("x509", "ocsp", "resp-responder-key-hash.der"), diff --git a/vectors/cryptography_vectors/x509/ocsp/resp-unknown-hash-alg.der b/vectors/cryptography_vectors/x509/ocsp/resp-unknown-hash-alg.der new file mode 100644 index 0000000000000000000000000000000000000000..aad0cb5ad33e7ab268653e1bbeba7e5ffb6a4b4a GIT binary patch literal 491 zcmXqLVtmfU$grS^@qs}T;~h3mZ8k<$R(1nMMwTYVvp}Jf2928*iLr?AHzdk5875xU z*LdFRX0b)*;jx>KB>0UC3@r>S4Gay9O-zjpq6`|_3>upaybQS5*tGeWnWO|+8CXOF z;+Iu5aLnDRKHv0QGq-ccyv4_Pu^Y%Fz`tOToaiC$eX<#^`kxo1nJyGWSYlveXlQB@ zg%E(+x&WcZ!qC{j0OSx}HcqWJkGAi;jEvl@49rc8j11-_|Am;pe6CEt(JSVVRXE{- z-zLw{1t<@awVv(iD`qmEU6w?BXP^RV@C{NuSS`Ur0*`};3dzXZ-MzgNG3 z>rj+M2XE|E>obXS^`^~Qv+c(B`3Kni-W=0C)2@23FrqVKRe;Rx9}XX5!h4(UyirTd zT-B$j5*aS@=4G)*8^^)<%a-$c@;e=V;rWjBzt5dB^?dy=W#+^SO#BsYUlS!!c&PL1 xAeunKkp;kLY@SouiQZ5&&h($36f6 literal 0 HcmV?d00001 From 37103b3b65c5a41a7d4dd8cc00b09684f136c2d0 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 25 May 2021 13:16:36 -0500 Subject: [PATCH 0281/2380] Remove straddling jargon "text". (#6067) --- docs/glossary.rst | 4 ---- docs/hazmat/primitives/twofactor.rst | 8 ++++---- docs/x509/reference.rst | 25 ++++++++++++------------- src/cryptography/x509/name.py | 2 +- 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/docs/glossary.rst b/docs/glossary.rst index 95b893c8fee6..b85a61091e38 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -61,10 +61,6 @@ Glossary aren't distinguishable without knowing the encryption key. This is considered a basic, necessary property for a working encryption system. - text - This type corresponds to ``unicode`` on Python 2 and ``str`` on Python - 3. This is equivalent to ``six.text_type``. - nonce A nonce is a **n**\ umber used **once**. Nonces are used in many cryptographic protocols. Generally, a nonce does not have to be secret diff --git a/docs/hazmat/primitives/twofactor.rst b/docs/hazmat/primitives/twofactor.rst index 1d2ab452ce0a..dcbc7bb76aec 100644 --- a/docs/hazmat/primitives/twofactor.rst +++ b/docs/hazmat/primitives/twofactor.rst @@ -91,11 +91,11 @@ codes (HMAC). :param account_name: The display name of account, such as ``'Alice Smith'`` or ``'alice@example.com'``. - :type account_name: :term:`text` + :type account_name: str :param issuer: The optional display name of issuer. This is typically the provider or service the user wants to access using the OTP token. - :type issuer: :term:`text` or `None` + :type issuer: ``str`` or ``None`` :param int counter: The current value of counter. :return: A URI string. @@ -212,11 +212,11 @@ similar to the following code. :param account_name: The display name of account, such as ``'Alice Smith'`` or ``'alice@example.com'``. - :type account_name: :term:`text` + :type account_name: str :param issuer: The optional display name of issuer. This is typically the provider or service the user wants to access using the OTP token. - :type issuer: :term:`text` or `None` + :type issuer: ``str`` or ``None`` :return: A URI string. Provisioning URI diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst index 6c058f9f78d5..eb4d07b54508 100644 --- a/docs/x509/reference.rst +++ b/docs/x509/reference.rst @@ -1329,7 +1329,7 @@ X.509 CSR (Certificate Signing Request) Builder Object .. attribute:: value - :type: :term:`text` + :type: str The value of the attribute. @@ -1337,7 +1337,7 @@ X.509 CSR (Certificate Signing Request) Builder Object .. versionadded:: 35.0 - :type: :term:`text` + :type: str The :rfc:`4514` short attribute name (for example "CN"), or the OID dotted string if a short name is unavailable. @@ -1418,7 +1418,7 @@ General Name Classes .. attribute:: value - :type: :term:`text` + :type: str .. class:: DNSName(value) @@ -1437,11 +1437,11 @@ General Name Classes :raises ValueError: If the provided string is not an :term:`A-label`. - :type: :term:`text` + :type: str .. attribute:: value - :type: :term:`text` + :type: str .. class:: DirectoryName(value) @@ -1473,7 +1473,7 @@ General Name Classes .. attribute:: value - :type: :term:`text` + :type: str .. class:: IPAddress(value) @@ -2592,11 +2592,10 @@ These classes may be present within a :class:`CertificatePolicies` instance. :type: list - A list consisting of :term:`text` and/or :class:`UserNotice` objects. - If the value is text it is a pointer to the practice statement - published by the certificate authority. If it is a user notice it is - meant for display to the relying party when the certificate is - used. + A list consisting of ``str`` and/or :class:`UserNotice` objects. If the + value is ``str`` it is a pointer to the practice statement published by + the certificate authority. If it is a user notice it is meant for + display to the relying party when the certificate is used. .. class:: UserNotice(notice_reference, explicit_text) @@ -2618,7 +2617,7 @@ These classes may be present within a :class:`CertificatePolicies` instance. This field includes an arbitrary textual statement directly in the certificate. - :type: :term:`text` + :type: str .. class:: NoticeReference(organization, notice_numbers) @@ -2633,7 +2632,7 @@ These classes may be present within a :class:`CertificatePolicies` instance. .. attribute:: organization - :type: :term:`text` + :type: str .. attribute:: notice_numbers diff --git a/src/cryptography/x509/name.py b/src/cryptography/x509/name.py index d1a3e3331fb1..b02fda9cfe67 100644 --- a/src/cryptography/x509/name.py +++ b/src/cryptography/x509/name.py @@ -83,7 +83,7 @@ def __init__( ) if not isinstance(value, str): - raise TypeError("value argument must be a text type.") + raise TypeError("value argument must be a str.") if ( oid == NameOID.COUNTRY_NAME From d119c40afcf576ce4e3b37f26fb6bc9248963fb4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 May 2021 08:11:46 -0400 Subject: [PATCH 0282/2380] Bump libc from 0.2.94 to 0.2.95 in /src/rust (#6068) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.94 to 0.2.95. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.94...0.2.95) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 0732f7cea8f9..9352ad1899cd 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -143,9 +143,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.94" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e" +checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36" [[package]] name = "lock_api" From d8653ccf8e12bb216f08e1b6411e78ffb7353ba5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 May 2021 06:47:21 -0400 Subject: [PATCH 0283/2380] Bump actions/cache from 2.1.5 to 2.1.6 (#6070) Bumps [actions/cache](https://github.com/actions/cache) from 2.1.5 to 2.1.6. - [Release notes](https://github.com/actions/cache/releases) - [Commits](https://github.com/actions/cache/compare/v2.1.5...v2.1.6) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 94d3cb20c82f..748e7057834e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,7 +39,7 @@ jobs: - uses: actions/checkout@v2.3.4 with: persist-credentials: false - - uses: actions/cache@v2.1.5 + - uses: actions/cache@v2.1.6 with: path: | ~/.cargo/registry @@ -72,7 +72,7 @@ jobs: CONFIG_FLAGS: ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }} if: matrix.PYTHON.OPENSSL - name: Load cache - uses: actions/cache@v2.1.5 + uses: actions/cache@v2.1.6 id: ossl-cache with: path: ${{ github.workspace }}/osslcache @@ -125,7 +125,7 @@ jobs: - uses: actions/checkout@v2.3.4 with: persist-credentials: false - - uses: actions/cache@v2.1.5 + - uses: actions/cache@v2.1.6 with: path: | ~/.cargo/registry @@ -165,7 +165,7 @@ jobs: - uses: actions/checkout@v2.3.4 with: persist-credentials: false - - uses: actions/cache@v2.1.5 + - uses: actions/cache@v2.1.6 with: path: | ~/.cargo/registry @@ -203,7 +203,7 @@ jobs: - uses: actions/checkout@v2.3.4 with: persist-credentials: false - - uses: actions/cache@v2.1.5 + - uses: actions/cache@v2.1.6 with: path: | ~/.cargo/registry @@ -269,7 +269,7 @@ jobs: - uses: actions/checkout@v2.3.4 with: persist-credentials: false - - uses: actions/cache@v2.1.5 + - uses: actions/cache@v2.1.6 with: path: | ~/.cargo/registry @@ -337,7 +337,7 @@ jobs: with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} - - uses: actions/cache@v2.1.5 + - uses: actions/cache@v2.1.6 with: path: | ~/.cargo/registry @@ -396,7 +396,7 @@ jobs: - uses: actions/checkout@v2.3.4 with: persist-credentials: false - - uses: actions/cache@v2.1.5 + - uses: actions/cache@v2.1.6 with: path: | ~/.cargo/registry From 5fc7556f9a607fcd1717c87ad160bf5b7f1f6c30 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 28 May 2021 09:45:57 -0400 Subject: [PATCH 0284/2380] Update cargh cache dirs in CI to match recommendtions (#6071) --- .github/workflows/ci.yml | 56 +++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 748e7057834e..9347f7e07675 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,10 +42,12 @@ jobs: - uses: actions/cache@v2.1.6 with: path: | - ~/.cargo/registry - ~/.cargo/git + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ src/rust/target/ - key: ${{ runner.os }}-${{ matrix.PYTHON.VERSION }}-cargo-${{ hashFiles('**/Cargo.lock') }} + key: ${{ runner.os }}-${{ matrix.PYTHON.VERSION }}-cargo-2-${{ hashFiles('**/Cargo.lock') }} - name: Setup python uses: actions/setup-python@v2.2.2 @@ -128,10 +130,12 @@ jobs: - uses: actions/cache@v2.1.6 with: path: | - ~/.cargo/registry - ~/.cargo/git + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ src/rust/target/ - key: ${{ runner.os }}-${{ matrix.IMAGE.IMAGE }}-cargo-${{ hashFiles('**/Cargo.lock') }} + key: ${{ runner.os }}-${{ matrix.IMAGE.IMAGE }}-cargo-2-${{ hashFiles('**/Cargo.lock') }} - run: 'git clone --depth=1 https://github.com/google/wycheproof "$HOME/wycheproof"' - run: | @@ -168,10 +172,12 @@ jobs: - uses: actions/cache@v2.1.6 with: path: | - ~/.cargo/registry - ~/.cargo/git + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ src/rust/target/ - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}-${{ matrix.RUST }} + key: ${{ runner.os }}-cargo-2-${{ hashFiles('**/Cargo.lock') }}-${{ matrix.RUST }} - name: Setup python uses: actions/setup-python@v2.2.2 @@ -206,10 +212,12 @@ jobs: - uses: actions/cache@v2.1.6 with: path: | - ~/.cargo/registry - ~/.cargo/git + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ src/rust/target/ - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}-rust-nightly-coverage + key: ${{ runner.os }}-cargo-2-${{ hashFiles('**/Cargo.lock') }}-rust-nightly-coverage - name: Setup python uses: actions/setup-python@v2.2.2 @@ -272,10 +280,12 @@ jobs: - uses: actions/cache@v2.1.6 with: path: | - ~/.cargo/registry - ~/.cargo/git + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ src/rust/target/ - key: ${{ runner.os }}-${{ matrix.PYTHON.VERSION }}-cargo-${{ hashFiles('**/Cargo.lock') }} + key: ${{ runner.os }}-${{ matrix.PYTHON.VERSION }}-cargo-2-${{ hashFiles('**/Cargo.lock') }} - name: Setup python uses: actions/setup-python@v2.2.2 @@ -340,10 +350,12 @@ jobs: - uses: actions/cache@v2.1.6 with: path: | - ~/.cargo/registry - ~/.cargo/git + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ src/rust/target/ - key: ${{ runner.os }}-${{ matrix.WINDOWS.ARCH }}-${{ steps.setup-python.outputs.python-version }}-cargo-${{ hashFiles('**/Cargo.lock') }} + key: ${{ runner.os }}-${{ matrix.WINDOWS.ARCH }}-${{ steps.setup-python.outputs.python-version }}-cargo-2-${{ hashFiles('**/Cargo.lock') }} - uses: actions-rs/toolchain@v1.0.7 with: @@ -399,10 +411,12 @@ jobs: - uses: actions/cache@v2.1.6 with: path: | - ~/.cargo/registry - ~/.cargo/git + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ src/rust/target/ - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + key: ${{ runner.os }}-cargo-2-${{ hashFiles('**/Cargo.lock') }} - name: Setup python uses: actions/setup-python@v2.2.2 From dde3586efce9efa2c42690588248be71a52172eb Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 29 May 2021 11:39:58 -0400 Subject: [PATCH 0285/2380] don't install cargo-binutils if we had a cargo cache hit (#6073) --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9347f7e07675..d1d1d1e42a1e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -210,6 +210,7 @@ jobs: with: persist-credentials: false - uses: actions/cache@v2.1.6 + id: cargo-cache with: path: | ~/.cargo/bin/ @@ -234,6 +235,7 @@ jobs: with: crate: cargo-binutils version: latest + if: steps.cargo-cache.outputs.cache-hit != 'true' - run: git clone --depth=1 https://github.com/google/wycheproof - run: python -m pip install tox coverage From e22242f28090f6636debc7bc1e9e31b7d9f26faf Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 30 May 2021 19:34:11 -0400 Subject: [PATCH 0286/2380] Bump to rust-asn1 0.5.0 (#6074) --- src/rust/Cargo.lock | 8 ++++---- src/rust/Cargo.toml | 2 +- src/rust/src/asn1.rs | 5 ++--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 9352ad1899cd..9422bc7a71bf 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "asn1" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "150eef712394a4e814c83771b4027c5b4e9f9cb8f5ed30e8556c8e7bdeca5864" +checksum = "2b0b5d36e3f25768cc488c4aff0e38c645b34d30552e5739aed33ebdd02b2c31" dependencies = [ "asn1_derive", "chrono", @@ -14,9 +14,9 @@ dependencies = [ [[package]] name = "asn1_derive" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "511fd42f2524a4771b3d51149b9af8c196e6ab479795ab7ef6d743f5696fd141" +checksum = "4be4b1a957d65a39deba1154b39d0ee6806705ed293c43dcb2ec9ab71a95c889" dependencies = [ "proc-macro2", "quote", diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 38e21e57dba8..1b95deb09d0f 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] lazy_static = "1" pyo3 = { version = "0.13.1" } -asn1 = { version = "0.4.2", default-features = false, features = ["derive"] } +asn1 = { version = "0.5.0", default-features = false, features = ["derive"] } [features] extension-module = ["pyo3/extension-module"] diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs index 93a6899c5fd5..2921200af1f1 100644 --- a/src/rust/src/asn1.rs +++ b/src/rust/src/asn1.rs @@ -56,8 +56,7 @@ fn parse_tls_feature(py: pyo3::Python<'_>, data: &[u8]) -> Result>(data)? { - let feature = el?; + for feature in asn1::parse_single::>(data)? { let py_feature = tls_feature_type_to_enum.get_item(feature.to_object(py))?; features.append(py_feature)?; } @@ -246,7 +245,7 @@ struct Validity<'a> { fn parse_name_value_tags(rdns: &mut Name<'_>) -> Result, PyAsn1Error> { let mut tags = vec![]; for rdn in rdns { - let mut attributes = rdn?.collect::>>()?; + let mut attributes = rdn.collect::>(); assert_eq!(attributes.len(), 1); tags.push(attributes.pop().unwrap().value.tag()); From 2cdbaff2d127a313ca49e84841c0828fface2796 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 30 May 2021 20:09:34 -0400 Subject: [PATCH 0287/2380] Move OCSPRequest implementation to Rust (#6059) * Move OCSPRequest implementation to Rust --- .../hazmat/backends/openssl/backend.py | 32 +- .../hazmat/backends/openssl/ocsp.py | 46 --- .../hazmat/bindings/_rust/asn1.pyi | 5 +- .../hazmat/bindings/_rust/ocsp.pyi | 7 + src/cryptography/x509/ocsp.py | 5 +- src/rust/Cargo.lock | 66 ++++ src/rust/Cargo.toml | 1 + src/rust/src/asn1.rs | 37 +-- src/rust/src/lib.rs | 2 + src/rust/src/ocsp.rs | 298 ++++++++++++++++++ 10 files changed, 387 insertions(+), 112 deletions(-) create mode 100644 src/cryptography/hazmat/bindings/_rust/ocsp.pyi create mode 100644 src/rust/src/ocsp.rs diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index ce9b3dc63e82..448bd68241d4 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -62,10 +62,7 @@ ) from cryptography.hazmat.backends.openssl.hashes import _HashContext from cryptography.hazmat.backends.openssl.hmac import _HMACContext -from cryptography.hazmat.backends.openssl.ocsp import ( - _OCSPRequest, - _OCSPResponse, -) +from cryptography.hazmat.backends.openssl.ocsp import _OCSPResponse from cryptography.hazmat.backends.openssl.poly1305 import ( _POLY1305_KEY_SIZE, _Poly1305Context, @@ -88,7 +85,7 @@ _CertificateSigningRequest, _RevokedCertificate, ) -from cryptography.hazmat.bindings._rust import asn1 +from cryptography.hazmat.bindings._rust import asn1, ocsp as rust_ocsp from cryptography.hazmat.bindings.openssl import binding from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ( @@ -420,18 +417,11 @@ def _register_x509_ext_parsers(self): get_ext=self._lib.X509_CRL_get_ext, handlers=_CRL_EXTENSION_HANDLERS, ) - self._ocsp_req_ext_parser = _X509ExtensionParser( - self, - ext_count=self._lib.OCSP_REQUEST_get_ext_count, - get_ext=self._lib.OCSP_REQUEST_get_ext, - rust_callback=asn1.parse_ocsp_req_extension, - ) self._ocsp_basicresp_ext_parser = _X509ExtensionParser( self, ext_count=self._lib.OCSP_BASICRESP_get_ext_count, get_ext=self._lib.OCSP_BASICRESP_get_ext, - # OCSP basic resp has the same extensions as req. - rust_callback=asn1.parse_ocsp_req_extension, + rust_callback=rust_ocsp.parse_ocsp_resp_extension, ) self._ocsp_singleresp_ext_parser = _X509ExtensionParser( self, @@ -1655,16 +1645,6 @@ def _ec_key_new_by_curve_nid(self, curve_nid): self.openssl_assert(ec_cdata != self._ffi.NULL) return self._ffi.gc(ec_cdata, self._lib.EC_KEY_free) - def load_der_ocsp_request(self, data): - mem_bio = self._bytes_to_bio(data) - request = self._lib.d2i_OCSP_REQUEST_bio(mem_bio.bio, self._ffi.NULL) - if request == self._ffi.NULL: - self._consume_errors() - raise ValueError("Unable to load OCSP request") - - request = self._ffi.gc(request, self._lib.OCSP_REQUEST_free) - return _OCSPRequest(self, request) - def load_der_ocsp_response(self, data): mem_bio = self._bytes_to_bio(data) response = self._lib.d2i_OCSP_RESPONSE_bio(mem_bio.bio, self._ffi.NULL) @@ -1692,7 +1672,11 @@ def create_ocsp_request(self, builder): add_func=self._lib.OCSP_REQUEST_add_ext, gc=True, ) - return _OCSPRequest(self, ocsp_req) + + bio = self._create_mem_bio_gc() + res = self._lib.i2d_OCSP_REQUEST_bio(bio, ocsp_req) + self.openssl_assert(res > 0) + return ocsp.load_der_ocsp_request(self._read_mem_bio(bio)) def _create_ocsp_basic_response(self, builder, private_key, algorithm): self._x509_check_signature_params(private_key, algorithm) diff --git a/src/cryptography/hazmat/backends/openssl/ocsp.py b/src/cryptography/hazmat/backends/openssl/ocsp.py index 9138e78dba62..6ef9316e975e 100644 --- a/src/cryptography/hazmat/backends/openssl/ocsp.py +++ b/src/cryptography/hazmat/backends/openssl/ocsp.py @@ -19,7 +19,6 @@ from cryptography.hazmat.primitives import hashes, serialization from cryptography.x509.ocsp import ( OCSPCertStatus, - OCSPRequest, OCSPResponse, OCSPResponseStatus, _CERT_STATUS_TO_ENUM, @@ -346,48 +345,3 @@ def public_bytes(self, encoding: serialization.Encoding) -> bytes: ) self._backend.openssl_assert(res > 0) return self._backend._read_mem_bio(bio) - - -class _OCSPRequest(OCSPRequest): - def __init__(self, backend, ocsp_request): - if backend._lib.OCSP_request_onereq_count(ocsp_request) > 1: - raise NotImplementedError( - "OCSP request contains more than one request" - ) - self._backend = backend - self._ocsp_request = ocsp_request - self._request = self._backend._lib.OCSP_request_onereq_get0( - self._ocsp_request, 0 - ) - self._backend.openssl_assert(self._request != self._backend._ffi.NULL) - self._cert_id = self._backend._lib.OCSP_onereq_get0_id(self._request) - self._backend.openssl_assert(self._cert_id != self._backend._ffi.NULL) - - @property - def issuer_key_hash(self) -> bytes: - return _issuer_key_hash(self._backend, self._cert_id) - - @property - def issuer_name_hash(self) -> bytes: - return _issuer_name_hash(self._backend, self._cert_id) - - @property - def serial_number(self) -> int: - return _serial_number(self._backend, self._cert_id) - - @property - def hash_algorithm(self) -> hashes.HashAlgorithm: - return _hash_algorithm(self._backend, self._cert_id) - - @utils.cached_property - def extensions(self) -> x509.Extensions: - return self._backend._ocsp_req_ext_parser.parse(self._ocsp_request) - - def public_bytes(self, encoding: serialization.Encoding) -> bytes: - if encoding is not serialization.Encoding.DER: - raise ValueError("The only allowed encoding value is Encoding.DER") - - bio = self._backend._create_mem_bio_gc() - res = self._backend._lib.i2d_OCSP_REQUEST_bio(bio, self._ocsp_request) - self._backend.openssl_assert(res > 0) - return self._backend._read_mem_bio(bio) diff --git a/src/cryptography/hazmat/bindings/_rust/asn1.pyi b/src/cryptography/hazmat/bindings/_rust/asn1.pyi index 5f4afc92f1cf..bd73221baf37 100644 --- a/src/cryptography/hazmat/bindings/_rust/asn1.pyi +++ b/src/cryptography/hazmat/bindings/_rust/asn1.pyi @@ -1,6 +1,6 @@ import typing -from cryptography.x509 import ExtensionType, TLSFeature, PrecertPoison +from cryptography.x509 import TLSFeature, PrecertPoison class TestCertificate: not_after_tag: int @@ -14,8 +14,5 @@ def encode_tls_feature(ext: TLSFeature) -> bytes: ... def parse_tls_feature(data: bytes) -> TLSFeature: ... def encode_precert_poison(ext: PrecertPoison) -> bytes: ... def parse_precert_poison(data: bytes) -> PrecertPoison: ... -def parse_ocsp_req_extension( - der_oid: bytes, ext_data: bytes -) -> ExtensionType: ... def parse_spki_for_data(data: bytes) -> bytes: ... def test_parse_certificate(data: bytes) -> TestCertificate: ... diff --git a/src/cryptography/hazmat/bindings/_rust/ocsp.pyi b/src/cryptography/hazmat/bindings/_rust/ocsp.pyi new file mode 100644 index 000000000000..2d8c04fc31ea --- /dev/null +++ b/src/cryptography/hazmat/bindings/_rust/ocsp.pyi @@ -0,0 +1,7 @@ +from cryptography.x509 import ExtensionType +from cryptography.x509.ocsp import OCSPRequest + +def load_der_ocsp_request(data: bytes) -> OCSPRequest: ... +def parse_ocsp_resp_extension( + der_oid: bytes, ext_data: bytes +) -> ExtensionType: ... diff --git a/src/cryptography/x509/ocsp.py b/src/cryptography/x509/ocsp.py index 7f8711b79d2d..2c6a450a1d62 100644 --- a/src/cryptography/x509/ocsp.py +++ b/src/cryptography/x509/ocsp.py @@ -9,6 +9,7 @@ from cryptography import utils from cryptography import x509 +from cryptography.hazmat.bindings._rust import ocsp from cryptography.hazmat.primitives import hashes, serialization from cryptography.x509.base import ( PRIVATE_KEY_TYPES, @@ -494,9 +495,7 @@ def build_unsuccessful( def load_der_ocsp_request(data: bytes) -> OCSPRequest: - from cryptography.hazmat.backends.openssl.backend import backend - - return backend.load_der_ocsp_request(data) + return ocsp.load_der_ocsp_request(data) def load_der_ocsp_response(data: bytes) -> OCSPResponse: diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 9422bc7a71bf..c1a44b7e3077 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" + [[package]] name = "asn1" version = "0.5.0" @@ -57,6 +63,7 @@ version = "0.1.0" dependencies = [ "asn1", "lazy_static", + "ouroboros", "pyo3", ] @@ -175,6 +182,29 @@ dependencies = [ "autocfg", ] +[[package]] +name = "ouroboros" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc1f52300b81ac4eeeb6c00c20f7e86556c427d9fb2d92b68fc73c22f331cd15" +dependencies = [ + "ouroboros_macro", + "stable_deref_trait", +] + +[[package]] +name = "ouroboros_macro" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41db02c8f8731cdd7a72b433c7900cce4bf245465b452c364bfd21f4566ab055" +dependencies = [ + "Inflector", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "parking_lot" version = "0.11.1" @@ -219,6 +249,30 @@ dependencies = [ "proc-macro-hack", ] +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro-hack" version = "0.5.19" @@ -303,6 +357,12 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "syn" version = "1.0.72" @@ -326,6 +386,12 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7" +[[package]] +name = "version_check" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" + [[package]] name = "winapi" version = "0.3.9" diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 1b95deb09d0f..824fe1cf2a2a 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -9,6 +9,7 @@ publish = false lazy_static = "1" pyo3 = { version = "0.13.1" } asn1 = { version = "0.5.0", default-features = false, features = ["derive"] } +ouroboros = "0.9" [features] extension-module = ["pyo3/extension-module"] diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs index 2921200af1f1..8f7bb486aaea 100644 --- a/src/rust/src/asn1.rs +++ b/src/rust/src/asn1.rs @@ -5,7 +5,7 @@ use pyo3::class::basic::CompareOp; use pyo3::conversion::ToPyObject; -enum PyAsn1Error { +pub(crate) enum PyAsn1Error { Asn1(asn1::ParseError), Py(pyo3::PyErr), } @@ -101,44 +101,13 @@ fn parse_spki_for_data(py: pyo3::Python<'_>, data: &[u8]) -> Result = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.48.1.2").unwrap(); -} - -#[pyo3::prelude::pyfunction] -fn parse_ocsp_req_extension( - py: pyo3::Python<'_>, - der_oid: &[u8], - ext_data: &[u8], -) -> pyo3::PyResult { - let oid = asn1::ObjectIdentifier::from_der(der_oid).unwrap(); - - let x509_module = py.import("cryptography.x509")?; - if oid == *NONCE_OID { - // This is a disaster. RFC 2560 says that the contents of the nonce is - // just the raw extension value. This is nonsense, since they're always - // supposed to be ASN.1 TLVs. RFC 6960 correctly specifies that the - // nonce is an OCTET STRING, and so you should unwrap the TLV to get - // the nonce. For now we just implement the old behavior, even though - // it's deranged. - Ok(x509_module - .call_method1("OCSPNonce", (ext_data,))? - .to_object(py)) - } else { - let oid_obj = x509_module.call_method1("ObjectIdentifier", (oid.to_string(),))?; - Ok(x509_module - .call_method1("UnrecognizedExtension", (oid_obj, ext_data))? - .to_object(py)) - } -} - #[derive(asn1::Asn1Read, asn1::Asn1Write)] struct DssSignature<'a> { r: asn1::BigUint<'a>, s: asn1::BigUint<'a>, } -fn big_asn1_uint_to_py<'p>( +pub(crate) fn big_asn1_uint_to_py<'p>( py: pyo3::Python<'p>, v: asn1::BigUint, ) -> pyo3::PyResult<&'p pyo3::PyAny> { @@ -273,8 +242,6 @@ pub(crate) fn create_submodule(py: pyo3::Python) -> pyo3::PyResult<&pyo3::prelud submod.add_wrapped(pyo3::wrap_pyfunction!(parse_precert_poison))?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_spki_for_data))?; - submod.add_wrapped(pyo3::wrap_pyfunction!(parse_ocsp_req_extension))?; - submod.add_wrapped(pyo3::wrap_pyfunction!(decode_dss_signature))?; submod.add_wrapped(pyo3::wrap_pyfunction!(encode_dss_signature))?; diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs index a3b3fb715141..3f5236267992 100644 --- a/src/rust/src/lib.rs +++ b/src/rust/src/lib.rs @@ -3,6 +3,7 @@ // for complete details. mod asn1; +mod ocsp; use std::convert::TryInto; @@ -73,6 +74,7 @@ fn _rust(py: pyo3::Python<'_>, m: &pyo3::types::PyModule) -> pyo3::PyResult<()> m.add_function(pyo3::wrap_pyfunction!(check_ansix923_padding, m)?)?; m.add_submodule(asn1::create_submodule(py)?)?; + m.add_submodule(ocsp::create_submodule(py)?)?; Ok(()) } diff --git a/src/rust/src/ocsp.rs b/src/rust/src/ocsp.rs new file mode 100644 index 000000000000..d551e3f3c2cd --- /dev/null +++ b/src/rust/src/ocsp.rs @@ -0,0 +1,298 @@ +// 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. + +use crate::asn1::{big_asn1_uint_to_py, PyAsn1Error}; +use pyo3::conversion::ToPyObject; +use pyo3::exceptions; +use std::collections::{HashMap, HashSet}; + +lazy_static::lazy_static! { + static ref SHA1_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.14.3.2.26").unwrap(); + static ref SHA224_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.16.840.1.101.3.4.2.4").unwrap(); + static ref SHA256_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.16.840.1.101.3.4.2.1").unwrap(); + static ref SHA384_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.16.840.1.101.3.4.2.2").unwrap(); + static ref SHA512_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.16.840.1.101.3.4.2.3").unwrap(); + + static ref OIDS_TO_HASH: HashMap<&'static asn1::ObjectIdentifier<'static>, &'static str> = { + let mut h = HashMap::new(); + h.insert(&*SHA1_OID, "SHA1"); + h.insert(&*SHA224_OID, "SHA224"); + h.insert(&*SHA256_OID, "SHA256"); + h.insert(&*SHA384_OID, "SHA384"); + h.insert(&*SHA512_OID, "SHA512"); + h + }; + + static ref NONCE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.48.1.2").unwrap(); +} + +#[ouroboros::self_referencing] +struct OwnedRawOCSPRequest { + data: Vec, + #[borrows(data)] + #[covariant] + value: RawOCSPRequest<'this>, +} + +#[pyo3::prelude::pyfunction] +fn load_der_ocsp_request(_py: pyo3::Python<'_>, data: &[u8]) -> Result { + let raw = OwnedRawOCSPRequest::try_new(data.to_vec(), |data| asn1::parse_single(data))?; + + if raw.borrow_value().tbs_request.request_list.clone().count() != 1 { + return Err(PyAsn1Error::from( + exceptions::PyNotImplementedError::new_err( + "OCSP request contains more than one request", + ), + )); + } + + Ok(OCSPRequest { + raw, + cached_extensions: None, + }) +} + +#[pyo3::prelude::pyclass] +struct OCSPRequest { + raw: OwnedRawOCSPRequest, + + cached_extensions: Option, +} + +impl OCSPRequest { + fn cert_id(&self) -> Result { + Ok(self + .raw + .borrow_value() + .tbs_request + .request_list + .clone() + .next() + .unwrap() + .req_cert) + } +} + +fn parse_and_cache_extensions< + 'p, + F: Fn(&asn1::ObjectIdentifier, &[u8]) -> Result, PyAsn1Error>, +>( + py: pyo3::Python<'p>, + cached_extensions: &mut Option, + raw_exts: &Option, + parse_ext: F, +) -> Result { + if let Some(cached) = cached_extensions { + return Ok(cached.clone_ref(py)); + } + + let x509_module = py.import("cryptography.x509")?; + let exts = pyo3::types::PyList::empty(py); + let mut seen_oids = HashSet::new(); + if let Some(raw_exts) = raw_exts { + for raw_ext in raw_exts.clone() { + let oid_obj = + x509_module.call_method1("ObjectIdentifier", (raw_ext.extn_id.to_string(),))?; + + if seen_oids.contains(&raw_ext.extn_id) { + return Err(PyAsn1Error::from(pyo3::PyErr::from_instance( + x509_module.call_method1( + "DuplicateExtension", + ( + format!("Duplicate {} extension found", raw_ext.extn_id), + oid_obj, + ), + )?, + ))); + } + + let extn_value = match parse_ext(&raw_ext.extn_id, raw_ext.extn_value)? { + Some(e) => e, + None => x509_module + .call_method1("UnrecognizedExtension", (oid_obj, raw_ext.extn_value))?, + }; + let ext_obj = + x509_module.call_method1("Extension", (oid_obj, raw_ext.critical, extn_value))?; + exts.append(ext_obj)?; + seen_oids.insert(raw_ext.extn_id); + } + } + let extensions = x509_module + .call_method1("Extensions", (exts,))? + .to_object(py); + *cached_extensions = Some(extensions.clone_ref(py)); + Ok(extensions) +} + +#[pyo3::prelude::pymethods] +impl OCSPRequest { + #[getter] + fn issuer_name_hash(&self) -> Result<&[u8], PyAsn1Error> { + Ok(self.cert_id()?.issuer_name_hash) + } + + #[getter] + fn issuer_key_hash(&self) -> Result<&[u8], PyAsn1Error> { + Ok(self.cert_id()?.issuer_key_hash) + } + + #[getter] + fn hash_algorithm<'p>(&self, py: pyo3::Python<'p>) -> Result<&'p pyo3::PyAny, PyAsn1Error> { + let cert_id = self.cert_id()?; + + let hashes = py.import("cryptography.hazmat.primitives.hashes")?; + match OIDS_TO_HASH.get(&cert_id.hash_algorithm.oid) { + Some(alg_name) => Ok(hashes.call0(alg_name)?), + None => { + let exceptions = py.import("cryptography.exceptions")?; + Err(PyAsn1Error::from(pyo3::PyErr::from_instance( + exceptions.call1( + "UnsupportedAlgorithm", + (format!( + "Signature algorithm OID: {} not recognized", + cert_id.hash_algorithm.oid + ),), + )?, + ))) + } + } + } + + #[getter] + fn serial_number<'p>(&self, py: pyo3::Python<'p>) -> Result<&'p pyo3::PyAny, PyAsn1Error> { + Ok(big_asn1_uint_to_py(py, self.cert_id()?.serial_number)?) + } + + #[getter] + fn extensions(&mut self, py: pyo3::Python) -> Result { + let x509_module = py.import("cryptography.x509")?; + parse_and_cache_extensions( + py, + &mut self.cached_extensions, + &self.raw.borrow_value().tbs_request.request_extensions, + |oid, value| { + if oid == &*NONCE_OID { + // This is a disaster. RFC 2560 says that the contents of the nonce is + // just the raw extension value. This is nonsense, since they're always + // supposed to be ASN.1 TLVs. RFC 6960 correctly specifies that the + // nonce is an OCTET STRING, and so you should unwrap the TLV to get + // the nonce. For now we just implement the old behavior, even though + // it's deranged. + Ok(Some(x509_module.call_method1("OCSPNonce", (value,))?)) + } else { + Ok(None) + } + }, + ) + } + + fn public_bytes<'p>( + &self, + py: pyo3::Python<'p>, + encoding: &pyo3::PyAny, + ) -> Result<&'p pyo3::types::PyBytes, PyAsn1Error> { + let der = py + .import("cryptography.hazmat.primitives.serialization")? + .getattr("Encoding")? + .getattr("DER")?; + if encoding != der { + return Err(PyAsn1Error::from(exceptions::PyValueError::new_err( + "The only allowed encoding value is Encoding.DER", + ))); + } + let result = asn1::write_single(self.raw.borrow_value()); + Ok(pyo3::types::PyBytes::new(py, &result)) + } +} + +#[derive(asn1::Asn1Read, asn1::Asn1Write)] +struct RawOCSPRequest<'a> { + tbs_request: TBSRequest<'a>, + // Parsing out the full structure, which includes the entirety of a + // certificate is more trouble than it's worth, since it's not in the + // Python API. + #[explicit(0)] + _optional_signature: Option>, +} + +#[derive(asn1::Asn1Read, asn1::Asn1Write)] +struct TBSRequest<'a> { + #[explicit(0)] + #[default(0)] + version: u8, + // This is virtually unused, not supported until GeneralName is implemented + // and used elsewhere. + // #[explicit(1)] + // _requestor_name: Option>, + request_list: asn1::SequenceOf<'a, Request<'a>>, + #[explicit(2)] + request_extensions: Option>, +} + +#[derive(asn1::Asn1Read, asn1::Asn1Write)] +struct Request<'a> { + req_cert: CertID<'a>, + #[explicit(0)] + _single_request_extensions: Option>, +} + +#[derive(asn1::Asn1Read, asn1::Asn1Write)] +struct CertID<'a> { + hash_algorithm: AlgorithmIdentifier<'a>, + issuer_name_hash: &'a [u8], + issuer_key_hash: &'a [u8], + serial_number: asn1::BigUint<'a>, +} + +type Extensions<'a> = asn1::SequenceOf<'a, Extension<'a>>; + +#[derive(asn1::Asn1Read, asn1::Asn1Write)] +struct AlgorithmIdentifier<'a> { + oid: asn1::ObjectIdentifier<'a>, + _params: Option>, +} + +#[derive(asn1::Asn1Read, asn1::Asn1Write)] +struct Extension<'a> { + extn_id: asn1::ObjectIdentifier<'a>, + #[default(false)] + critical: bool, + extn_value: &'a [u8], +} + +#[pyo3::prelude::pyfunction] +fn parse_ocsp_resp_extension( + py: pyo3::Python<'_>, + der_oid: &[u8], + ext_data: &[u8], +) -> pyo3::PyResult { + let oid = asn1::ObjectIdentifier::from_der(der_oid).unwrap(); + + let x509_module = py.import("cryptography.x509")?; + if oid == *NONCE_OID { + // This is a disaster. RFC 2560 says that the contents of the nonce is + // just the raw extension value. This is nonsense, since they're always + // supposed to be ASN.1 TLVs. RFC 6960 correctly specifies that the + // nonce is an OCTET STRING, and so you should unwrap the TLV to get + // the nonce. For now we just implement the old behavior, even though + // it's deranged. + Ok(x509_module + .call_method1("OCSPNonce", (ext_data,))? + .to_object(py)) + } else { + let oid_obj = x509_module.call_method1("ObjectIdentifier", (oid.to_string(),))?; + Ok(x509_module + .call_method1("UnrecognizedExtension", (oid_obj, ext_data))? + .to_object(py)) + } +} + +pub(crate) fn create_submodule(py: pyo3::Python) -> pyo3::PyResult<&pyo3::prelude::PyModule> { + let submod = pyo3::prelude::PyModule::new(py, "ocsp")?; + + submod.add_wrapped(pyo3::wrap_pyfunction!(load_der_ocsp_request))?; + submod.add_wrapped(pyo3::wrap_pyfunction!(parse_ocsp_resp_extension))?; + + Ok(submod) +} From 42332b725ff1a995a55532e773befa65a884cf6a Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 31 May 2021 10:09:45 -0400 Subject: [PATCH 0288/2380] Simplify delegation of rust for extension parsing (#6075) Also now supports part openssl/part rust setups --- .../hazmat/backends/openssl/backend.py | 7 ++- .../hazmat/backends/openssl/decode_asn1.py | 35 +++----------- .../hazmat/bindings/_rust/asn1.pyi | 2 - .../hazmat/bindings/_rust/x509.pyi | 3 ++ src/rust/src/asn1.rs | 26 ---------- src/rust/src/lib.rs | 2 + src/rust/src/ocsp.rs | 5 +- src/rust/src/x509.rs | 47 +++++++++++++++++++ 8 files changed, 65 insertions(+), 62 deletions(-) create mode 100644 src/cryptography/hazmat/bindings/_rust/x509.pyi create mode 100644 src/rust/src/x509.rs diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 448bd68241d4..8ab05ffb1067 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -85,7 +85,11 @@ _CertificateSigningRequest, _RevokedCertificate, ) -from cryptography.hazmat.bindings._rust import asn1, ocsp as rust_ocsp +from cryptography.hazmat.bindings._rust import ( + asn1, + ocsp as rust_ocsp, + x509 as rust_x509, +) from cryptography.hazmat.bindings.openssl import binding from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ( @@ -398,6 +402,7 @@ def _register_x509_ext_parsers(self): ext_count=self._lib.X509_get_ext_count, get_ext=self._lib.X509_get_ext, handlers=ext_handlers, + rust_callback=rust_x509.parse_x509_extension, ) self._csr_extension_parser = _X509ExtensionParser( self, diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index eb384263d6de..efa4dd14f7f0 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -8,7 +8,6 @@ import typing from cryptography import x509 -from cryptography.hazmat.bindings._rust import asn1 from cryptography.x509.name import _ASN1_TYPE_TO_ENUM from cryptography.x509.oid import ( CRLEntryExtensionOID, @@ -178,7 +177,7 @@ def _decode_delta_crl_indicator(backend, ext): class _X509ExtensionParser(object): def __init__( - self, backend, ext_count, get_ext, handlers=None, rust_callback=None + self, backend, ext_count, get_ext, handlers={}, rust_callback=None ): assert handlers or rust_callback self.ext_count = ext_count @@ -214,33 +213,11 @@ def parse(self, x509_obj): )[:] data = self._backend._lib.X509_EXTENSION_get_data(ext) data_bytes = _asn1_string_to_bytes(self._backend, data) - ext = self.rust_callback(oid_der_bytes, data_bytes) - extensions.append(x509.Extension(oid, critical, ext)) - seen_oids.add(oid) - continue - - # These OIDs are only supported in OpenSSL 1.1.0+ but we want - # to support them in all versions of OpenSSL so we decode them - # ourselves. - if oid == ExtensionOID.TLS_FEATURE: - # The extension contents are a SEQUENCE OF INTEGERs. - data = self._backend._lib.X509_EXTENSION_get_data(ext) - data_bytes = _asn1_string_to_bytes(self._backend, data) - tls_feature = asn1.parse_tls_feature(data_bytes) - - extensions.append(x509.Extension(oid, critical, tls_feature)) - seen_oids.add(oid) - continue - elif oid == ExtensionOID.PRECERT_POISON: - data = self._backend._lib.X509_EXTENSION_get_data(ext) - data_bytes = _asn1_string_to_bytes(self._backend, data) - precert_poison = asn1.parse_precert_poison(data_bytes) - - extensions.append( - x509.Extension(oid, critical, precert_poison) - ) - seen_oids.add(oid) - continue + ext_obj = self.rust_callback(oid_der_bytes, data_bytes) + if ext_obj is not None: + extensions.append(x509.Extension(oid, critical, ext_obj)) + seen_oids.add(oid) + continue try: handler = self.handlers[oid] diff --git a/src/cryptography/hazmat/bindings/_rust/asn1.pyi b/src/cryptography/hazmat/bindings/_rust/asn1.pyi index bd73221baf37..6809271014f7 100644 --- a/src/cryptography/hazmat/bindings/_rust/asn1.pyi +++ b/src/cryptography/hazmat/bindings/_rust/asn1.pyi @@ -11,8 +11,6 @@ class TestCertificate: def decode_dss_signature(signature: bytes) -> typing.Tuple[int, int]: ... def encode_dss_signature(r: int, s: int) -> bytes: ... def encode_tls_feature(ext: TLSFeature) -> bytes: ... -def parse_tls_feature(data: bytes) -> TLSFeature: ... def encode_precert_poison(ext: PrecertPoison) -> bytes: ... -def parse_precert_poison(data: bytes) -> PrecertPoison: ... def parse_spki_for_data(data: bytes) -> bytes: ... def test_parse_certificate(data: bytes) -> TestCertificate: ... diff --git a/src/cryptography/hazmat/bindings/_rust/x509.pyi b/src/cryptography/hazmat/bindings/_rust/x509.pyi new file mode 100644 index 000000000000..d1e26e0b15b5 --- /dev/null +++ b/src/cryptography/hazmat/bindings/_rust/x509.pyi @@ -0,0 +1,3 @@ +from cryptography.x509 import ExtensionType + +def parse_x509_extension(der_oid: bytes, ext_data: bytes) -> ExtensionType: ... diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs index 8f7bb486aaea..08c22790506b 100644 --- a/src/rust/src/asn1.rs +++ b/src/rust/src/asn1.rs @@ -49,36 +49,12 @@ fn encode_tls_feature(py: pyo3::Python<'_>, ext: &pyo3::PyAny) -> pyo3::PyResult Ok(pyo3::types::PyBytes::new(py, &result).to_object(py)) } -#[pyo3::prelude::pyfunction] -fn parse_tls_feature(py: pyo3::Python<'_>, data: &[u8]) -> Result { - let tls_feature_type_to_enum = py - .import("cryptography.x509.extensions")? - .getattr("_TLS_FEATURE_TYPE_TO_ENUM")?; - - let features = pyo3::types::PyList::empty(py); - for feature in asn1::parse_single::>(data)? { - let py_feature = tls_feature_type_to_enum.get_item(feature.to_object(py))?; - features.append(py_feature)?; - } - - let x509_module = py.import("cryptography.x509")?; - Ok(x509_module.call1("TLSFeature", (features,))?.to_object(py)) -} - #[pyo3::prelude::pyfunction] fn encode_precert_poison(py: pyo3::Python<'_>, _ext: &pyo3::PyAny) -> pyo3::PyObject { let result = asn1::write_single(&()); pyo3::types::PyBytes::new(py, &result).to_object(py) } -#[pyo3::prelude::pyfunction] -fn parse_precert_poison(py: pyo3::Python<'_>, data: &[u8]) -> Result { - asn1::parse_single::<()>(data)?; - - let x509_module = py.import("cryptography.x509")?; - Ok(x509_module.call0("PrecertPoison")?.to_object(py)) -} - #[derive(asn1::Asn1Read)] struct AlgorithmIdentifier<'a> { _oid: asn1::ObjectIdentifier<'a>, @@ -237,9 +213,7 @@ fn test_parse_certificate(data: &[u8]) -> Result { pub(crate) fn create_submodule(py: pyo3::Python) -> pyo3::PyResult<&pyo3::prelude::PyModule> { let submod = pyo3::prelude::PyModule::new(py, "asn1")?; submod.add_wrapped(pyo3::wrap_pyfunction!(encode_tls_feature))?; - submod.add_wrapped(pyo3::wrap_pyfunction!(parse_tls_feature))?; submod.add_wrapped(pyo3::wrap_pyfunction!(encode_precert_poison))?; - submod.add_wrapped(pyo3::wrap_pyfunction!(parse_precert_poison))?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_spki_for_data))?; submod.add_wrapped(pyo3::wrap_pyfunction!(decode_dss_signature))?; diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs index 3f5236267992..dbde1d9de22a 100644 --- a/src/rust/src/lib.rs +++ b/src/rust/src/lib.rs @@ -4,6 +4,7 @@ mod asn1; mod ocsp; +mod x509; use std::convert::TryInto; @@ -75,6 +76,7 @@ fn _rust(py: pyo3::Python<'_>, m: &pyo3::types::PyModule) -> pyo3::PyResult<()> m.add_submodule(asn1::create_submodule(py)?)?; m.add_submodule(ocsp::create_submodule(py)?)?; + m.add_submodule(x509::create_submodule(py)?)?; Ok(()) } diff --git a/src/rust/src/ocsp.rs b/src/rust/src/ocsp.rs index d551e3f3c2cd..ddbe4f0503c0 100644 --- a/src/rust/src/ocsp.rs +++ b/src/rust/src/ocsp.rs @@ -281,10 +281,7 @@ fn parse_ocsp_resp_extension( .call_method1("OCSPNonce", (ext_data,))? .to_object(py)) } else { - let oid_obj = x509_module.call_method1("ObjectIdentifier", (oid.to_string(),))?; - Ok(x509_module - .call_method1("UnrecognizedExtension", (oid_obj, ext_data))? - .to_object(py)) + Ok(py.None()) } } diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs new file mode 100644 index 000000000000..845423d033e3 --- /dev/null +++ b/src/rust/src/x509.rs @@ -0,0 +1,47 @@ +// 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. + +use crate::asn1::PyAsn1Error; +use pyo3::conversion::ToPyObject; + +lazy_static::lazy_static! { + static ref TLS_FEATURE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.1.24").unwrap(); + static ref PRECERT_POISON_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.4.1.11129.2.4.3").unwrap(); +} + +#[pyo3::prelude::pyfunction] +fn parse_x509_extension( + py: pyo3::Python<'_>, + der_oid: &[u8], + ext_data: &[u8], +) -> Result { + let oid = asn1::ObjectIdentifier::from_der(der_oid).unwrap(); + + let x509_module = py.import("cryptography.x509")?; + if oid == *TLS_FEATURE_OID { + let tls_feature_type_to_enum = py + .import("cryptography.x509.extensions")? + .getattr("_TLS_FEATURE_TYPE_TO_ENUM")?; + + let features = pyo3::types::PyList::empty(py); + for feature in asn1::parse_single::>(ext_data)? { + let py_feature = tls_feature_type_to_enum.get_item(feature.to_object(py))?; + features.append(py_feature)?; + } + Ok(x509_module.call1("TLSFeature", (features,))?.to_object(py)) + } else if oid == *PRECERT_POISON_OID { + asn1::parse_single::<()>(ext_data)?; + Ok(x509_module.call0("PrecertPoison")?.to_object(py)) + } else { + Ok(py.None()) + } +} + +pub(crate) fn create_submodule(py: pyo3::Python) -> pyo3::PyResult<&pyo3::prelude::PyModule> { + let submod = pyo3::prelude::PyModule::new(py, "x509")?; + + submod.add_wrapped(pyo3::wrap_pyfunction!(parse_x509_extension))?; + + Ok(submod) +} From 8969f918cbad20acb505850913c1c58a9e92e4c9 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 31 May 2021 11:36:05 -0400 Subject: [PATCH 0289/2380] Burn down now unused OCSP request bindings (#6078) --- src/_cffi_src/openssl/ocsp.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/_cffi_src/openssl/ocsp.py b/src/_cffi_src/openssl/ocsp.py index 9b939f0f85f9..03d2f3d1fde1 100644 --- a/src/_cffi_src/openssl/ocsp.py +++ b/src/_cffi_src/openssl/ocsp.py @@ -41,11 +41,6 @@ int OCSP_single_get0_status(OCSP_SINGLERESP *, int *, ASN1_GENERALIZEDTIME **, ASN1_GENERALIZEDTIME **, ASN1_GENERALIZEDTIME **); -int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *); -X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *, int); -int OCSP_request_onereq_count(OCSP_REQUEST *); -OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *, int); -OCSP_CERTID *OCSP_onereq_get0_id(OCSP_ONEREQ *); OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *, OCSP_CERTID *); OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *, const X509 *, const X509 *); void OCSP_CERTID_free(OCSP_CERTID *); @@ -68,7 +63,6 @@ int OCSP_REQUEST_add_ext(OCSP_REQUEST *, X509_EXTENSION *, int); int OCSP_id_get0_info(ASN1_OCTET_STRING **, ASN1_OBJECT **, ASN1_OCTET_STRING **, ASN1_INTEGER **, OCSP_CERTID *); -OCSP_REQUEST *d2i_OCSP_REQUEST_bio(BIO *, OCSP_REQUEST **); OCSP_RESPONSE *d2i_OCSP_RESPONSE_bio(BIO *, OCSP_RESPONSE **); int i2d_OCSP_REQUEST_bio(BIO *, OCSP_REQUEST *); int i2d_OCSP_RESPONSE_bio(BIO *, OCSP_RESPONSE *); From 1557201ab3d565355618f4c4feae1cd47fda41d9 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 31 May 2021 11:38:31 -0400 Subject: [PATCH 0290/2380] Convert CRLReason parsing to rust (#6076) --- .../hazmat/backends/openssl/backend.py | 2 + .../hazmat/backends/openssl/decode_asn1.py | 12 ------ .../hazmat/bindings/_rust/x509.pyi | 3 ++ src/rust/src/x509.rs | 37 +++++++++++++++++++ 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 8ab05ffb1067..219b7e1e14eb 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -415,6 +415,7 @@ def _register_x509_ext_parsers(self): ext_count=self._lib.X509_REVOKED_get_ext_count, get_ext=self._lib.X509_REVOKED_get_ext, handlers=_REVOKED_EXTENSION_HANDLERS, + rust_callback=rust_x509.parse_crl_entry_extension, ) self._crl_extension_parser = _X509ExtensionParser( self, @@ -433,6 +434,7 @@ def _register_x509_ext_parsers(self): ext_count=self._lib.OCSP_SINGLERESP_get_ext_count, get_ext=self._lib.OCSP_SINGLERESP_get_ext, handlers=singleresp_handlers, + rust_callback=rust_x509.parse_crl_entry_extension, ) def _register_x509_encoders(self): diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index efa4dd14f7f0..abfbf6cfafcd 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -694,17 +694,6 @@ def _decode_signed_certificate_timestamps(backend, asn1_scts): } -def _decode_crl_reason(backend, enum): - enum = backend._ffi.cast("ASN1_ENUMERATED *", enum) - enum = backend._ffi.gc(enum, backend._lib.ASN1_ENUMERATED_free) - code = backend._lib.ASN1_ENUMERATED_get(enum) - - try: - return x509.CRLReason(_CRL_ENTRY_REASON_CODE_TO_ENUM[code]) - except KeyError: - raise ValueError("Unsupported reason code: {}".format(code)) - - def _decode_invalidity_date(backend, inv_date): generalized_time = backend._ffi.cast("ASN1_GENERALIZEDTIME *", inv_date) generalized_time = backend._ffi.gc( @@ -824,7 +813,6 @@ def _parse_asn1_generalized_time(backend, generalized_time): } _REVOKED_EXTENSION_HANDLERS = { - CRLEntryExtensionOID.CRL_REASON: _decode_crl_reason, CRLEntryExtensionOID.INVALIDITY_DATE: _decode_invalidity_date, CRLEntryExtensionOID.CERTIFICATE_ISSUER: _decode_cert_issuer, } diff --git a/src/cryptography/hazmat/bindings/_rust/x509.pyi b/src/cryptography/hazmat/bindings/_rust/x509.pyi index d1e26e0b15b5..aad2b0e0ce9a 100644 --- a/src/cryptography/hazmat/bindings/_rust/x509.pyi +++ b/src/cryptography/hazmat/bindings/_rust/x509.pyi @@ -1,3 +1,6 @@ from cryptography.x509 import ExtensionType def parse_x509_extension(der_oid: bytes, ext_data: bytes) -> ExtensionType: ... +def parse_crl_entry_extension( + der_oid: bytes, ext_data: bytes +) -> ExtensionType: ... diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index 845423d033e3..359a4b38a126 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -8,6 +8,8 @@ use pyo3::conversion::ToPyObject; lazy_static::lazy_static! { static ref TLS_FEATURE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.1.24").unwrap(); static ref PRECERT_POISON_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.4.1.11129.2.4.3").unwrap(); + + static ref CRL_REASON_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.21").unwrap(); } #[pyo3::prelude::pyfunction] @@ -38,10 +40,45 @@ fn parse_x509_extension( } } +#[pyo3::prelude::pyfunction] +fn parse_crl_entry_extension( + py: pyo3::Python<'_>, + der_oid: &[u8], + ext_data: &[u8], +) -> Result { + let oid = asn1::ObjectIdentifier::from_der(der_oid).unwrap(); + + let x509_module = py.import("cryptography.x509")?; + if oid == *CRL_REASON_OID { + let flag_name = match asn1::parse_single::(ext_data)?.value() { + 0 => "unspecified", + 1 => "key_compromise", + 2 => "ca_compromise", + 3 => "affiliation_changed", + 4 => "superseded", + 5 => "cessation_of_operation", + 6 => "certificate_hold", + 8 => "remove_from_crl", + 9 => "privilege_withdrawn", + 10 => "aa_compromise", + value => { + return Err(PyAsn1Error::from(pyo3::exceptions::PyValueError::new_err( + format!("Unsupported reason code: {}", value), + ))) + } + }; + let flag = x509_module.getattr("ReasonFlags")?.getattr(flag_name)?; + Ok(x509_module.call1("CRLReason", (flag,))?.to_object(py)) + } else { + Ok(py.None()) + } +} + pub(crate) fn create_submodule(py: pyo3::Python) -> pyo3::PyResult<&pyo3::prelude::PyModule> { let submod = pyo3::prelude::PyModule::new(py, "x509")?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_x509_extension))?; + submod.add_wrapped(pyo3::wrap_pyfunction!(parse_crl_entry_extension))?; Ok(submod) } From 8397d8a181915e79b319da176d4892296154fedd Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 31 May 2021 12:00:43 -0500 Subject: [PATCH 0291/2380] oxidize crlnumber (#6079) * oxidize crlnumber * cargo fmt --- .../hazmat/backends/openssl/backend.py | 1 + .../hazmat/backends/openssl/decode_asn1.py | 7 ------ .../hazmat/bindings/_rust/x509.pyi | 1 + src/rust/src/x509.rs | 22 ++++++++++++++++++- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 219b7e1e14eb..2efc386f01ae 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -422,6 +422,7 @@ def _register_x509_ext_parsers(self): ext_count=self._lib.X509_CRL_get_ext_count, get_ext=self._lib.X509_CRL_get_ext, handlers=_CRL_EXTENSION_HANDLERS, + rust_callback=rust_x509.parse_crl_extension, ) self._ocsp_basicresp_ext_parser = _X509ExtensionParser( self, diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index abfbf6cfafcd..4b45fbce5f28 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -163,12 +163,6 @@ def _decode_ocsp_no_check(backend, ext): return x509.OCSPNoCheck() -def _decode_crl_number(backend, ext): - asn1_int = backend._ffi.cast("ASN1_INTEGER *", ext) - asn1_int = backend._ffi.gc(asn1_int, backend._lib.ASN1_INTEGER_free) - return x509.CRLNumber(_asn1_integer_to_int(backend, asn1_int)) - - def _decode_delta_crl_indicator(backend, ext): asn1_int = backend._ffi.cast("ASN1_INTEGER *", ext) asn1_int = backend._ffi.gc(asn1_int, backend._lib.ASN1_INTEGER_free) @@ -818,7 +812,6 @@ def _parse_asn1_generalized_time(backend, generalized_time): } _CRL_EXTENSION_HANDLERS = { - ExtensionOID.CRL_NUMBER: _decode_crl_number, ExtensionOID.DELTA_CRL_INDICATOR: _decode_delta_crl_indicator, ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _decode_authority_key_identifier, ExtensionOID.ISSUER_ALTERNATIVE_NAME: _decode_issuer_alt_name, diff --git a/src/cryptography/hazmat/bindings/_rust/x509.pyi b/src/cryptography/hazmat/bindings/_rust/x509.pyi index aad2b0e0ce9a..2d41f9e91f5f 100644 --- a/src/cryptography/hazmat/bindings/_rust/x509.pyi +++ b/src/cryptography/hazmat/bindings/_rust/x509.pyi @@ -4,3 +4,4 @@ def parse_x509_extension(der_oid: bytes, ext_data: bytes) -> ExtensionType: ... def parse_crl_entry_extension( der_oid: bytes, ext_data: bytes ) -> ExtensionType: ... +def parse_crl_extension(der_oid: bytes, ext_data: bytes) -> ExtensionType: ... diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index 359a4b38a126..9c996f3b8426 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -2,7 +2,7 @@ // 2.0, and the BSD License. See the LICENSE file in the root of this repository // for complete details. -use crate::asn1::PyAsn1Error; +use crate::asn1::{big_asn1_uint_to_py, PyAsn1Error}; use pyo3::conversion::ToPyObject; lazy_static::lazy_static! { @@ -10,6 +10,7 @@ lazy_static::lazy_static! { static ref PRECERT_POISON_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.4.1.11129.2.4.3").unwrap(); static ref CRL_REASON_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.21").unwrap(); + static ref CRL_NUMBER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.20").unwrap(); } #[pyo3::prelude::pyfunction] @@ -74,11 +75,30 @@ fn parse_crl_entry_extension( } } +#[pyo3::prelude::pyfunction] +fn parse_crl_extension( + py: pyo3::Python<'_>, + der_oid: &[u8], + ext_data: &[u8], +) -> Result { + let oid = asn1::ObjectIdentifier::from_der(der_oid).unwrap(); + + let x509_module = py.import("cryptography.x509")?; + if oid == *CRL_NUMBER_OID { + let bignum = asn1::parse_single::(ext_data)?; + let pynum = big_asn1_uint_to_py(py, bignum)?; + Ok(x509_module.call1("CRLNumber", (pynum,))?.to_object(py)) + } else { + Ok(py.None()) + } +} + pub(crate) fn create_submodule(py: pyo3::Python) -> pyo3::PyResult<&pyo3::prelude::PyModule> { let submod = pyo3::prelude::PyModule::new(py, "x509")?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_x509_extension))?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_crl_entry_extension))?; + submod.add_wrapped(pyo3::wrap_pyfunction!(parse_crl_extension))?; Ok(submod) } From 52ccb8eb1efbd820c7fd29b6196c70d40f443315 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 31 May 2021 13:40:16 -0500 Subject: [PATCH 0292/2380] oxidize basic constraints (#6080) --- .../hazmat/backends/openssl/backend.py | 1 + .../hazmat/backends/openssl/decode_asn1.py | 17 ----------------- src/rust/src/x509.rs | 13 +++++++++++++ 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 2efc386f01ae..83a4cca69b4a 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -409,6 +409,7 @@ def _register_x509_ext_parsers(self): ext_count=self._lib.sk_X509_EXTENSION_num, get_ext=self._lib.sk_X509_EXTENSION_value, handlers=ext_handlers, + rust_callback=rust_x509.parse_x509_extension, ) self._revoked_cert_extension_parser = _X509ExtensionParser( self, diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 4b45fbce5f28..7be2b2789166 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -296,22 +296,6 @@ def _decode_user_notice(backend, un): return x509.UserNotice(notice_reference, explicit_text) -def _decode_basic_constraints(backend, bc_st): - basic_constraints = backend._ffi.cast("BASIC_CONSTRAINTS *", bc_st) - basic_constraints = backend._ffi.gc( - basic_constraints, backend._lib.BASIC_CONSTRAINTS_free - ) - # The byte representation of an ASN.1 boolean true is \xff. OpenSSL - # chooses to just map this to its ordinal value, so true is 255 and - # false is 0. - ca = basic_constraints.ca == 255 - path_length = _asn1_integer_to_int_or_none( - backend, basic_constraints.pathlen - ) - - return x509.BasicConstraints(ca, path_length) - - def _decode_subject_key_identifier(backend, asn1_string): asn1_string = backend._ffi.cast("ASN1_OCTET_STRING *", asn1_string) asn1_string = backend._ffi.gc( @@ -779,7 +763,6 @@ def _parse_asn1_generalized_time(backend, generalized_time): _EXTENSION_HANDLERS_BASE = { - ExtensionOID.BASIC_CONSTRAINTS: _decode_basic_constraints, ExtensionOID.SUBJECT_KEY_IDENTIFIER: _decode_subject_key_identifier, ExtensionOID.KEY_USAGE: _decode_key_usage, ExtensionOID.SUBJECT_ALTERNATIVE_NAME: _decode_subject_alt_name, diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index 9c996f3b8426..a8be601aedd5 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -9,10 +9,18 @@ lazy_static::lazy_static! { static ref TLS_FEATURE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.1.24").unwrap(); static ref PRECERT_POISON_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.4.1.11129.2.4.3").unwrap(); + static ref BASIC_CONSTRAINTS_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.19").unwrap(); static ref CRL_REASON_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.21").unwrap(); static ref CRL_NUMBER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.20").unwrap(); } +#[derive(asn1::Asn1Read)] +struct BasicConstraints { + #[default(false)] + ca: bool, + path_length: Option, +} + #[pyo3::prelude::pyfunction] fn parse_x509_extension( py: pyo3::Python<'_>, @@ -36,6 +44,11 @@ fn parse_x509_extension( } else if oid == *PRECERT_POISON_OID { asn1::parse_single::<()>(ext_data)?; Ok(x509_module.call0("PrecertPoison")?.to_object(py)) + } else if oid == *BASIC_CONSTRAINTS_OID { + let bc = asn1::parse_single::(ext_data)?; + Ok(x509_module + .call1("BasicConstraints", (bc.ca, bc.path_length))? + .to_object(py)) } else { Ok(py.None()) } From 0ffabb02a9c749afbc6d063797b019652fd1d973 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 31 May 2021 15:14:35 -0500 Subject: [PATCH 0293/2380] oxidize EKU and KU (#6081) * oxidize EKU and KU * we always pass a rust_callback now. refactor for that --- .../hazmat/backends/openssl/backend.py | 10 +-- .../hazmat/backends/openssl/decode_asn1.py | 76 +++++-------------- src/rust/src/x509.rs | 48 ++++++++++++ 3 files changed, 70 insertions(+), 64 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 83a4cca69b4a..0376843d15d2 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -401,29 +401,29 @@ def _register_x509_ext_parsers(self): self, ext_count=self._lib.X509_get_ext_count, get_ext=self._lib.X509_get_ext, - handlers=ext_handlers, rust_callback=rust_x509.parse_x509_extension, + handlers=ext_handlers, ) self._csr_extension_parser = _X509ExtensionParser( self, ext_count=self._lib.sk_X509_EXTENSION_num, get_ext=self._lib.sk_X509_EXTENSION_value, - handlers=ext_handlers, rust_callback=rust_x509.parse_x509_extension, + handlers=ext_handlers, ) self._revoked_cert_extension_parser = _X509ExtensionParser( self, ext_count=self._lib.X509_REVOKED_get_ext_count, get_ext=self._lib.X509_REVOKED_get_ext, - handlers=_REVOKED_EXTENSION_HANDLERS, rust_callback=rust_x509.parse_crl_entry_extension, + handlers=_REVOKED_EXTENSION_HANDLERS, ) self._crl_extension_parser = _X509ExtensionParser( self, ext_count=self._lib.X509_CRL_get_ext_count, get_ext=self._lib.X509_CRL_get_ext, - handlers=_CRL_EXTENSION_HANDLERS, rust_callback=rust_x509.parse_crl_extension, + handlers=_CRL_EXTENSION_HANDLERS, ) self._ocsp_basicresp_ext_parser = _X509ExtensionParser( self, @@ -435,8 +435,8 @@ def _register_x509_ext_parsers(self): self, ext_count=self._lib.OCSP_SINGLERESP_get_ext_count, get_ext=self._lib.OCSP_SINGLERESP_get_ext, - handlers=singleresp_handlers, rust_callback=rust_x509.parse_crl_entry_extension, + handlers=singleresp_handlers, ) def _register_x509_encoders(self): diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 7be2b2789166..706baace55f4 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -171,9 +171,8 @@ def _decode_delta_crl_indicator(backend, ext): class _X509ExtensionParser(object): def __init__( - self, backend, ext_count, get_ext, handlers={}, rust_callback=None + self, backend, ext_count, get_ext, rust_callback, handlers={} ): - assert handlers or rust_callback self.ext_count = ext_count self.get_ext = get_ext self.handlers = handlers @@ -199,20 +198,22 @@ def parse(self, x509_obj): "Duplicate {} extension found".format(oid), oid ) - if self.rust_callback is not None: - oid_ptr = self._backend._lib.X509_EXTENSION_get_object(ext) - oid_der_bytes = self._backend._ffi.buffer( - self._backend._lib.Cryptography_OBJ_get0_data(oid_ptr), - self._backend._lib.Cryptography_OBJ_length(oid_ptr), - )[:] - data = self._backend._lib.X509_EXTENSION_get_data(ext) - data_bytes = _asn1_string_to_bytes(self._backend, data) - ext_obj = self.rust_callback(oid_der_bytes, data_bytes) - if ext_obj is not None: - extensions.append(x509.Extension(oid, critical, ext_obj)) - seen_oids.add(oid) - continue - + # Try to parse this with the rust callback first + oid_ptr = self._backend._lib.X509_EXTENSION_get_object(ext) + oid_der_bytes = self._backend._ffi.buffer( + self._backend._lib.Cryptography_OBJ_get0_data(oid_ptr), + self._backend._lib.Cryptography_OBJ_length(oid_ptr), + )[:] + data = self._backend._lib.X509_EXTENSION_get_data(ext) + data_bytes = _asn1_string_to_bytes(self._backend, data) + ext_obj = self.rust_callback(oid_der_bytes, data_bytes) + if ext_obj is not None: + extensions.append(x509.Extension(oid, critical, ext_obj)) + seen_oids.add(oid) + continue + + # Fallback to our older parsing because the rust code doesn't + # know how to parse this. try: handler = self.handlers[oid] except KeyError: @@ -363,32 +364,6 @@ def _decode_subject_information_access(backend, aia): return x509.SubjectInformationAccess(access_descriptions) -def _decode_key_usage(backend, bit_string): - bit_string = backend._ffi.cast("ASN1_BIT_STRING *", bit_string) - bit_string = backend._ffi.gc(bit_string, backend._lib.ASN1_BIT_STRING_free) - get_bit = backend._lib.ASN1_BIT_STRING_get_bit - digital_signature = get_bit(bit_string, 0) == 1 - content_commitment = get_bit(bit_string, 1) == 1 - key_encipherment = get_bit(bit_string, 2) == 1 - data_encipherment = get_bit(bit_string, 3) == 1 - key_agreement = get_bit(bit_string, 4) == 1 - key_cert_sign = get_bit(bit_string, 5) == 1 - crl_sign = get_bit(bit_string, 6) == 1 - encipher_only = get_bit(bit_string, 7) == 1 - decipher_only = get_bit(bit_string, 8) == 1 - return x509.KeyUsage( - digital_signature, - content_commitment, - key_encipherment, - data_encipherment, - key_agreement, - key_cert_sign, - crl_sign, - encipher_only, - decipher_only, - ) - - def _decode_general_names_extension(backend, gns): gns = backend._ffi.cast("GENERAL_NAMES *", gns) gns = backend._ffi.gc(gns, backend._lib.GENERAL_NAMES_free) @@ -479,21 +454,6 @@ def _decode_policy_constraints(backend, pc): ) -def _decode_extended_key_usage(backend, sk): - sk = backend._ffi.cast("Cryptography_STACK_OF_ASN1_OBJECT *", sk) - sk = backend._ffi.gc(sk, backend._lib.sk_ASN1_OBJECT_free) - num = backend._lib.sk_ASN1_OBJECT_num(sk) - ekus = [] - - for i in range(num): - obj = backend._lib.sk_ASN1_OBJECT_value(sk, i) - backend.openssl_assert(obj != backend._ffi.NULL) - oid = x509.ObjectIdentifier(_obj2txt(backend, obj)) - ekus.append(oid) - - return x509.ExtendedKeyUsage(ekus) - - _DISTPOINT_TYPE_FULLNAME = 0 _DISTPOINT_TYPE_RELATIVENAME = 1 @@ -764,9 +724,7 @@ def _parse_asn1_generalized_time(backend, generalized_time): _EXTENSION_HANDLERS_BASE = { ExtensionOID.SUBJECT_KEY_IDENTIFIER: _decode_subject_key_identifier, - ExtensionOID.KEY_USAGE: _decode_key_usage, ExtensionOID.SUBJECT_ALTERNATIVE_NAME: _decode_subject_alt_name, - ExtensionOID.EXTENDED_KEY_USAGE: _decode_extended_key_usage, ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _decode_authority_key_identifier, ExtensionOID.AUTHORITY_INFORMATION_ACCESS: ( _decode_authority_information_access diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index a8be601aedd5..a89c25e483c0 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -9,6 +9,8 @@ lazy_static::lazy_static! { static ref TLS_FEATURE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.1.24").unwrap(); static ref PRECERT_POISON_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.4.1.11129.2.4.3").unwrap(); + static ref KEY_USAGE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.15").unwrap(); + static ref EXTENDED_KEY_USAGE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.37").unwrap(); static ref BASIC_CONSTRAINTS_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.19").unwrap(); static ref CRL_REASON_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.21").unwrap(); static ref CRL_NUMBER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.20").unwrap(); @@ -21,6 +23,16 @@ struct BasicConstraints { path_length: Option, } +fn get_bit(input: &[u8], n: usize) -> bool { + let idx = n / 8; + let v = 1 << (7 - (n & 0x07)); + if input.len() < (idx + 1) { + false + } else { + input[idx] & v != 0 + } +} + #[pyo3::prelude::pyfunction] fn parse_x509_extension( py: pyo3::Python<'_>, @@ -41,6 +53,42 @@ fn parse_x509_extension( features.append(py_feature)?; } Ok(x509_module.call1("TLSFeature", (features,))?.to_object(py)) + } else if oid == *EXTENDED_KEY_USAGE_OID { + let ekus = pyo3::types::PyList::empty(py); + for oid in asn1::parse_single::>(ext_data)? { + let oid_obj = x509_module.call_method1("ObjectIdentifier", (oid.to_string(),))?; + ekus.append(oid_obj)?; + } + Ok(x509_module + .call1("ExtendedKeyUsage", (ekus,))? + .to_object(py)) + } else if oid == *KEY_USAGE_OID { + let kus = asn1::parse_single::(ext_data)?.as_bytes(); + let digital_signature = get_bit(kus, 0); + let content_comitment = get_bit(kus, 1); + let key_encipherment = get_bit(kus, 2); + let data_encipherment = get_bit(kus, 3); + let key_agreement = get_bit(kus, 4); + let key_cert_sign = get_bit(kus, 5); + let crl_sign = get_bit(kus, 6); + let encipher_only = get_bit(kus, 7); + let decipher_only = get_bit(kus, 8); + Ok(x509_module + .call1( + "KeyUsage", + ( + digital_signature, + content_comitment, + key_encipherment, + data_encipherment, + key_agreement, + key_cert_sign, + crl_sign, + encipher_only, + decipher_only, + ), + )? + .to_object(py)) } else if oid == *PRECERT_POISON_OID { asn1::parse_single::<()>(ext_data)?; Ok(x509_module.call0("PrecertPoison")?.to_object(py)) From 686185003b03c9611fd31ba409d90d8080130f36 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 31 May 2021 15:33:25 -0500 Subject: [PATCH 0294/2380] oxidize OCSPNoCheck, DeltaCRLIndicator, InhibitAnyPolicy, and SubjectKeyIdentifier (#6082) * oxidize OCSPNoCheck * oxidize delta CRL indicator * oxidize inhibitanypolicy * oxidize SKI, cargo fmt --- .../hazmat/backends/openssl/decode_asn1.py | 31 ------------------- src/rust/src/x509.rs | 24 ++++++++++++++ 2 files changed, 24 insertions(+), 31 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 706baace55f4..9a566bf77b0f 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -159,16 +159,6 @@ def _decode_general_name(backend, gn): ) -def _decode_ocsp_no_check(backend, ext): - return x509.OCSPNoCheck() - - -def _decode_delta_crl_indicator(backend, ext): - asn1_int = backend._ffi.cast("ASN1_INTEGER *", ext) - asn1_int = backend._ffi.gc(asn1_int, backend._lib.ASN1_INTEGER_free) - return x509.DeltaCRLIndicator(_asn1_integer_to_int(backend, asn1_int)) - - class _X509ExtensionParser(object): def __init__( self, backend, ext_count, get_ext, rust_callback, handlers={} @@ -297,16 +287,6 @@ def _decode_user_notice(backend, un): return x509.UserNotice(notice_reference, explicit_text) -def _decode_subject_key_identifier(backend, asn1_string): - asn1_string = backend._ffi.cast("ASN1_OCTET_STRING *", asn1_string) - asn1_string = backend._ffi.gc( - asn1_string, backend._lib.ASN1_OCTET_STRING_free - ) - return x509.SubjectKeyIdentifier( - backend._ffi.buffer(asn1_string.data, asn1_string.length)[:] - ) - - def _decode_authority_key_identifier(backend, akid): akid = backend._ffi.cast("AUTHORITY_KEYID *", akid) akid = backend._ffi.gc(akid, backend._lib.AUTHORITY_KEYID_free) @@ -559,13 +539,6 @@ def _decode_freshest_crl(backend, cdps): return x509.FreshestCRL(dist_points) -def _decode_inhibit_any_policy(backend, asn1_int): - asn1_int = backend._ffi.cast("ASN1_INTEGER *", asn1_int) - asn1_int = backend._ffi.gc(asn1_int, backend._lib.ASN1_INTEGER_free) - skip_certs = _asn1_integer_to_int(backend, asn1_int) - return x509.InhibitAnyPolicy(skip_certs) - - def _decode_scts(backend, asn1_scts): from cryptography.hazmat.backends.openssl.x509 import ( _SignedCertificateTimestamp, @@ -723,7 +696,6 @@ def _parse_asn1_generalized_time(backend, generalized_time): _EXTENSION_HANDLERS_BASE = { - ExtensionOID.SUBJECT_KEY_IDENTIFIER: _decode_subject_key_identifier, ExtensionOID.SUBJECT_ALTERNATIVE_NAME: _decode_subject_alt_name, ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _decode_authority_key_identifier, ExtensionOID.AUTHORITY_INFORMATION_ACCESS: ( @@ -735,8 +707,6 @@ def _parse_asn1_generalized_time(backend, generalized_time): ExtensionOID.CERTIFICATE_POLICIES: _decode_certificate_policies, ExtensionOID.CRL_DISTRIBUTION_POINTS: _decode_crl_distribution_points, ExtensionOID.FRESHEST_CRL: _decode_freshest_crl, - ExtensionOID.OCSP_NO_CHECK: _decode_ocsp_no_check, - ExtensionOID.INHIBIT_ANY_POLICY: _decode_inhibit_any_policy, ExtensionOID.ISSUER_ALTERNATIVE_NAME: _decode_issuer_alt_name, ExtensionOID.NAME_CONSTRAINTS: _decode_name_constraints, ExtensionOID.POLICY_CONSTRAINTS: _decode_policy_constraints, @@ -753,7 +723,6 @@ def _parse_asn1_generalized_time(backend, generalized_time): } _CRL_EXTENSION_HANDLERS = { - ExtensionOID.DELTA_CRL_INDICATOR: _decode_delta_crl_indicator, ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _decode_authority_key_identifier, ExtensionOID.ISSUER_ALTERNATIVE_NAME: _decode_issuer_alt_name, ExtensionOID.AUTHORITY_INFORMATION_ACCESS: ( diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index a89c25e483c0..bcefde675c0d 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -8,12 +8,16 @@ use pyo3::conversion::ToPyObject; lazy_static::lazy_static! { static ref TLS_FEATURE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.1.24").unwrap(); static ref PRECERT_POISON_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.4.1.11129.2.4.3").unwrap(); + static ref OCSP_NO_CHECK_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.48.1.5").unwrap(); static ref KEY_USAGE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.15").unwrap(); static ref EXTENDED_KEY_USAGE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.37").unwrap(); static ref BASIC_CONSTRAINTS_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.19").unwrap(); + static ref SUBJECT_KEY_IDENTIFIER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.14").unwrap(); + static ref INHIBIT_ANY_POLICY_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.54").unwrap(); static ref CRL_REASON_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.21").unwrap(); static ref CRL_NUMBER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.20").unwrap(); + static ref DELTA_CRL_INDICATOR_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.27").unwrap(); } #[derive(asn1::Asn1Read)] @@ -53,6 +57,11 @@ fn parse_x509_extension( features.append(py_feature)?; } Ok(x509_module.call1("TLSFeature", (features,))?.to_object(py)) + } else if oid == *SUBJECT_KEY_IDENTIFIER_OID { + let identifier = asn1::parse_single::<&[u8]>(ext_data)?; + Ok(x509_module + .call1("SubjectKeyIdentifier", (identifier,))? + .to_object(py)) } else if oid == *EXTENDED_KEY_USAGE_OID { let ekus = pyo3::types::PyList::empty(py); for oid in asn1::parse_single::>(ext_data)? { @@ -92,6 +101,15 @@ fn parse_x509_extension( } else if oid == *PRECERT_POISON_OID { asn1::parse_single::<()>(ext_data)?; Ok(x509_module.call0("PrecertPoison")?.to_object(py)) + } else if oid == *OCSP_NO_CHECK_OID { + asn1::parse_single::<()>(ext_data)?; + Ok(x509_module.call0("OCSPNoCheck")?.to_object(py)) + } else if oid == *INHIBIT_ANY_POLICY_OID { + let bignum = asn1::parse_single::(ext_data)?; + let pynum = big_asn1_uint_to_py(py, bignum)?; + Ok(x509_module + .call1("InhibitAnyPolicy", (pynum,))? + .to_object(py)) } else if oid == *BASIC_CONSTRAINTS_OID { let bc = asn1::parse_single::(ext_data)?; Ok(x509_module @@ -149,6 +167,12 @@ fn parse_crl_extension( let bignum = asn1::parse_single::(ext_data)?; let pynum = big_asn1_uint_to_py(py, bignum)?; Ok(x509_module.call1("CRLNumber", (pynum,))?.to_object(py)) + } else if oid == *DELTA_CRL_INDICATOR_OID { + let bignum = asn1::parse_single::(ext_data)?; + let pynum = big_asn1_uint_to_py(py, bignum)?; + Ok(x509_module + .call1("DeltaCRLIndicator", (pynum,))? + .to_object(py)) } else { Ok(py.None()) } From 144a39cfbe86b18e5f48548decd42e39a8d3437a Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 4 Jun 2021 22:15:25 -0500 Subject: [PATCH 0295/2380] oxidize policy constraints (#6087) * oxidize policy constraints * cargo fmt --- .../hazmat/backends/openssl/decode_asn1.py | 17 ----------------- src/rust/src/x509.rs | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 9a566bf77b0f..6a805e580957 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -418,22 +418,6 @@ def _decode_issuing_dist_point(backend, idp): ) -def _decode_policy_constraints(backend, pc): - pc = backend._ffi.cast("POLICY_CONSTRAINTS *", pc) - pc = backend._ffi.gc(pc, backend._lib.POLICY_CONSTRAINTS_free) - - require_explicit_policy = _asn1_integer_to_int_or_none( - backend, pc.requireExplicitPolicy - ) - inhibit_policy_mapping = _asn1_integer_to_int_or_none( - backend, pc.inhibitPolicyMapping - ) - - return x509.PolicyConstraints( - require_explicit_policy, inhibit_policy_mapping - ) - - _DISTPOINT_TYPE_FULLNAME = 0 _DISTPOINT_TYPE_RELATIVENAME = 1 @@ -709,7 +693,6 @@ def _parse_asn1_generalized_time(backend, generalized_time): ExtensionOID.FRESHEST_CRL: _decode_freshest_crl, ExtensionOID.ISSUER_ALTERNATIVE_NAME: _decode_issuer_alt_name, ExtensionOID.NAME_CONSTRAINTS: _decode_name_constraints, - ExtensionOID.POLICY_CONSTRAINTS: _decode_policy_constraints, } _EXTENSION_HANDLERS_SCT = { ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: ( diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index bcefde675c0d..21f2a2d7fa25 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -11,6 +11,7 @@ lazy_static::lazy_static! { static ref OCSP_NO_CHECK_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.48.1.5").unwrap(); static ref KEY_USAGE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.15").unwrap(); + static ref POLICY_CONSTRAINTS_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.36").unwrap(); static ref EXTENDED_KEY_USAGE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.37").unwrap(); static ref BASIC_CONSTRAINTS_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.19").unwrap(); static ref SUBJECT_KEY_IDENTIFIER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.14").unwrap(); @@ -27,6 +28,14 @@ struct BasicConstraints { path_length: Option, } +#[derive(asn1::Asn1Read)] +struct PolicyConstraints { + #[implicit(0)] + require_explicit_policy: Option, + #[implicit(1)] + inhibit_policy_mapping: Option, +} + fn get_bit(input: &[u8], n: usize) -> bool { let idx = n / 8; let v = 1 << (7 - (n & 0x07)); @@ -98,6 +107,14 @@ fn parse_x509_extension( ), )? .to_object(py)) + } else if oid == *POLICY_CONSTRAINTS_OID { + let pc = asn1::parse_single::(ext_data)?; + Ok(x509_module + .call1( + "PolicyConstraints", + (pc.require_explicit_policy, pc.inhibit_policy_mapping), + )? + .to_object(py)) } else if oid == *PRECERT_POISON_OID { asn1::parse_single::<()>(ext_data)?; Ok(x509_module.call0("PrecertPoison")?.to_object(py)) From a85e7c6fb7734734de16925749bb51b3ce842c39 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 6 Jun 2021 19:51:53 -0400 Subject: [PATCH 0296/2380] Bump asn1 from 0.5.0 to 0.5.1 in /src/rust (#6091) Bumps [asn1](https://github.com/alex/rust-asn1) from 0.5.0 to 0.5.1. - [Release notes](https://github.com/alex/rust-asn1/releases) - [Commits](https://github.com/alex/rust-asn1/compare/0.5.0...0.5.1) --- updated-dependencies: - dependency-name: asn1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 8 ++++---- src/rust/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index c1a44b7e3077..240d2b1c124a 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -10,9 +10,9 @@ checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" [[package]] name = "asn1" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0b5d36e3f25768cc488c4aff0e38c645b34d30552e5739aed33ebdd02b2c31" +checksum = "f4e2ec2f073674e49321449dbfd51accb77effab6ade9f311f0f631903d20c39" dependencies = [ "asn1_derive", "chrono", @@ -20,9 +20,9 @@ dependencies = [ [[package]] name = "asn1_derive" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be4b1a957d65a39deba1154b39d0ee6806705ed293c43dcb2ec9ab71a95c889" +checksum = "18175ce37dddb6ef19f30996c31f63b38571fea8351f321088181cd089efd203" dependencies = [ "proc-macro2", "quote", diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 824fe1cf2a2a..e70b20865346 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] lazy_static = "1" pyo3 = { version = "0.13.1" } -asn1 = { version = "0.5.0", default-features = false, features = ["derive"] } +asn1 = { version = "0.5.1", default-features = false, features = ["derive"] } ouroboros = "0.9" [features] From 60f5f9ff9beb41f662b23be243aba7a327883af4 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 7 Jun 2021 08:55:36 -0400 Subject: [PATCH 0297/2380] Use the new BitString::has_bit_set API (#6092) * Use the new BitString::has_bit_set API * poke GHA --- src/rust/src/x509.rs | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index 21f2a2d7fa25..8d1221187673 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -36,16 +36,6 @@ struct PolicyConstraints { inhibit_policy_mapping: Option, } -fn get_bit(input: &[u8], n: usize) -> bool { - let idx = n / 8; - let v = 1 << (7 - (n & 0x07)); - if input.len() < (idx + 1) { - false - } else { - input[idx] & v != 0 - } -} - #[pyo3::prelude::pyfunction] fn parse_x509_extension( py: pyo3::Python<'_>, @@ -81,16 +71,16 @@ fn parse_x509_extension( .call1("ExtendedKeyUsage", (ekus,))? .to_object(py)) } else if oid == *KEY_USAGE_OID { - let kus = asn1::parse_single::(ext_data)?.as_bytes(); - let digital_signature = get_bit(kus, 0); - let content_comitment = get_bit(kus, 1); - let key_encipherment = get_bit(kus, 2); - let data_encipherment = get_bit(kus, 3); - let key_agreement = get_bit(kus, 4); - let key_cert_sign = get_bit(kus, 5); - let crl_sign = get_bit(kus, 6); - let encipher_only = get_bit(kus, 7); - let decipher_only = get_bit(kus, 8); + let kus = asn1::parse_single::(ext_data)?; + let digital_signature = kus.has_bit_set(0); + let content_comitment = kus.has_bit_set(1); + let key_encipherment = kus.has_bit_set(2); + let data_encipherment = kus.has_bit_set(3); + let key_agreement = kus.has_bit_set(4); + let key_cert_sign = kus.has_bit_set(5); + let crl_sign = kus.has_bit_set(6); + let encipher_only = kus.has_bit_set(7); + let decipher_only = kus.has_bit_set(8); Ok(x509_module .call1( "KeyUsage", From c2ba1fe7b0e446fa6a0191032723fac15bdf2ac8 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 7 Jun 2021 10:23:32 -0500 Subject: [PATCH 0298/2380] oxidize SubjectAltName (#6089) * oxidize SubjectAltName This encompasses oxidizing parsing of GeneralName, which most of the remaining extensions need * empty commit for codecov --- .../hazmat/backends/openssl/decode_asn1.py | 82 +++------ src/cryptography/x509/general_name.py | 4 +- src/rust/src/asn1.rs | 8 +- src/rust/src/x509.rs | 162 +++++++++++++++++- tests/x509/test_x509_ext.py | 4 +- 5 files changed, 192 insertions(+), 68 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 6a805e580957..0248585556bd 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -81,6 +81,10 @@ def _decode_general_names(backend, gns): return names +# This is now a hacked up decoder where we progressively remove chunks as +# we port more and more to rust. SAN exercised every branch in this, but +# other extensions (which are still in Python/OpenSSL) don't so we'll remove +# anything that isn't covered progressively until we remove the entire function def _decode_general_name(backend, gn): if gn.type == backend._lib.GEN_DNS: # Convert to bytes and then decode to utf8. We don't use @@ -102,41 +106,37 @@ def _decode_general_name(backend, gn): # This allows us to create URI objects that have unicode chars # when a certificate (against the RFC) contains them. return x509.UniformResourceIdentifier._init_without_validation(data) - elif gn.type == backend._lib.GEN_RID: - oid = _obj2txt(backend, gn.d.registeredID) - return x509.RegisteredID(x509.ObjectIdentifier(oid)) elif gn.type == backend._lib.GEN_IPADD: data = _asn1_string_to_bytes(backend, gn.d.iPAddress) data_len = len(data) - if data_len == 8 or data_len == 32: - # This is an IPv4 or IPv6 Network and not a single IP. This - # type of data appears in Name Constraints. Unfortunately, - # ipaddress doesn't support packed bytes + netmask. Additionally, - # IPv6Network can only handle CIDR rather than the full 16 byte - # netmask. To handle this we convert the netmask to integer, then - # find the first 0 bit, which will be the prefix. If another 1 - # bit is present after that the netmask is invalid. - base = ipaddress.ip_address(data[: data_len // 2]) - netmask = ipaddress.ip_address(data[data_len // 2 :]) - bits = bin(int(netmask))[2:] - prefix = bits.find("0") - # If no 0 bits are found it is a /32 or /128 - if prefix == -1: - prefix = len(bits) - - if "1" in bits[prefix:]: - raise ValueError("Invalid netmask") - - ip = ipaddress.ip_network(base.exploded + "/{}".format(prefix)) - else: - ip = ipaddress.ip_address(data) + assert data_len == 8 or data_len == 32 + # This is an IPv4 or IPv6 Network and not a single IP. This + # type of data appears in Name Constraints. Unfortunately, + # ipaddress doesn't support packed bytes + netmask. Additionally, + # IPv6Network can only handle CIDR rather than the full 16 byte + # netmask. To handle this we convert the netmask to integer, then + # find the first 0 bit, which will be the prefix. If another 1 + # bit is present after that the netmask is invalid. + base = ipaddress.ip_address(data[: data_len // 2]) + netmask = ipaddress.ip_address(data[data_len // 2 :]) + bits = bin(int(netmask))[2:] + prefix = bits.find("0") + # If no 0 bits are found it is a /32 or /128 + if prefix == -1: + prefix = len(bits) + + if "1" in bits[prefix:]: + raise ValueError("Invalid netmask") + + ip = ipaddress.ip_network(base.exploded + "/{}".format(prefix)) return x509.IPAddress(ip) elif gn.type == backend._lib.GEN_DIRNAME: return x509.DirectoryName( _decode_x509_name(backend, gn.d.directoryName) ) - elif gn.type == backend._lib.GEN_EMAIL: + else: + assert gn.type == backend._lib.GEN_EMAIL # Convert to bytes and then decode to utf8. We don't use # asn1_string_to_utf8 here because it doesn't properly convert # utf8 from ia5strings. @@ -145,18 +145,6 @@ def _decode_general_name(backend, gn): # validation. This allows us to create RFC822Name objects that have # unicode chars when a certificate (against the RFC) contains them. return x509.RFC822Name._init_without_validation(data) - elif gn.type == backend._lib.GEN_OTHERNAME: - type_id = _obj2txt(backend, gn.d.otherName.type_id) - value = _asn1_to_der(backend, gn.d.otherName.value) - return x509.OtherName(x509.ObjectIdentifier(type_id), value) - else: - # x400Address or ediPartyName - raise x509.UnsupportedGeneralNameType( - "{} is not a supported type".format( - x509._GENERAL_NAMES.get(gn.type, gn.type) - ), - gn.type, - ) class _X509ExtensionParser(object): @@ -351,12 +339,6 @@ def _decode_general_names_extension(backend, gns): return general_names -def _decode_subject_alt_name(backend, ext): - return x509.SubjectAlternativeName( - _decode_general_names_extension(backend, ext) - ) - - def _decode_issuer_alt_name(backend, ext): return x509.IssuerAlternativeName( _decode_general_names_extension(backend, ext) @@ -606,17 +588,6 @@ def _decode_cert_issuer(backend, gns): return x509.CertificateIssuer(general_names) -def _asn1_to_der(backend, asn1_type): - buf = backend._ffi.new("unsigned char **") - res = backend._lib.i2d_ASN1_TYPE(asn1_type, buf) - backend.openssl_assert(res >= 0) - backend.openssl_assert(buf[0] != backend._ffi.NULL) - buf = backend._ffi.gc( - buf, lambda buffer: backend._lib.OPENSSL_free(buffer[0]) - ) - return backend._ffi.buffer(buf[0], res)[:] - - def _asn1_integer_to_int(backend, asn1_int): bn = backend._lib.ASN1_INTEGER_to_BN(asn1_int, backend._ffi.NULL) backend.openssl_assert(bn != backend._ffi.NULL) @@ -680,7 +651,6 @@ def _parse_asn1_generalized_time(backend, generalized_time): _EXTENSION_HANDLERS_BASE = { - ExtensionOID.SUBJECT_ALTERNATIVE_NAME: _decode_subject_alt_name, ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _decode_authority_key_identifier, ExtensionOID.AUTHORITY_INFORMATION_ACCESS: ( _decode_authority_information_access diff --git a/src/cryptography/x509/general_name.py b/src/cryptography/x509/general_name.py index d49582c41e11..66890550d073 100644 --- a/src/cryptography/x509/general_name.py +++ b/src/cryptography/x509/general_name.py @@ -32,9 +32,7 @@ class UnsupportedGeneralNameType(Exception): - def __init__(self, msg: str, type: int) -> None: - super(UnsupportedGeneralNameType, self).__init__(msg) - self.type = type + pass class GeneralName(metaclass=abc.ABCMeta): diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs index 08c22790506b..706ced54d9b3 100644 --- a/src/rust/src/asn1.rs +++ b/src/rust/src/asn1.rs @@ -173,12 +173,12 @@ struct TbsCertificate<'a> { _extensions: Option>, } -type Name<'a> = asn1::SequenceOf<'a, asn1::SetOf<'a, AttributeTypeValue<'a>>>; +pub(crate) type Name<'a> = asn1::SequenceOf<'a, asn1::SetOf<'a, AttributeTypeValue<'a>>>; #[derive(asn1::Asn1Read)] -struct AttributeTypeValue<'a> { - _type: asn1::ObjectIdentifier<'a>, - value: asn1::Tlv<'a>, +pub(crate) struct AttributeTypeValue<'a> { + pub(crate) type_id: asn1::ObjectIdentifier<'a>, + pub(crate) value: asn1::Tlv<'a>, } #[derive(asn1::Asn1Read)] diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index 8d1221187673..588c45d2a610 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -2,7 +2,7 @@ // 2.0, and the BSD License. See the LICENSE file in the root of this repository // for complete details. -use crate::asn1::{big_asn1_uint_to_py, PyAsn1Error}; +use crate::asn1::{big_asn1_uint_to_py, AttributeTypeValue, Name, PyAsn1Error}; use pyo3::conversion::ToPyObject; lazy_static::lazy_static! { @@ -19,6 +19,51 @@ lazy_static::lazy_static! { static ref CRL_REASON_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.21").unwrap(); static ref CRL_NUMBER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.20").unwrap(); static ref DELTA_CRL_INDICATOR_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.27").unwrap(); + static ref SUBJECT_ALTERNATIVE_NAME_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.17").unwrap(); +} + +struct UnvalidatedIA5String<'a>(&'a str); + +impl<'a> asn1::SimpleAsn1Readable<'a> for UnvalidatedIA5String<'a> { + const TAG: u8 = 0x16; + fn parse_data(data: &'a [u8]) -> asn1::ParseResult { + Ok(UnvalidatedIA5String( + std::str::from_utf8(data).map_err(|_| asn1::ParseError::InvalidValue)?, + )) + } +} + +#[derive(asn1::Asn1Read)] +enum GeneralName<'a> { + #[implicit(0)] + OtherName(AttributeTypeValue<'a>), + + #[implicit(1)] + RFC822Name(UnvalidatedIA5String<'a>), + + #[implicit(2)] + DNSName(UnvalidatedIA5String<'a>), + + #[implicit(3)] + // unsupported + X400Address(asn1::Sequence<'a>), + + // Name is explicit per RFC 5280 Appendix A.1. + #[explicit(4)] + DirectoryName(Name<'a>), + + #[implicit(5)] + // unsupported + EDIPartyName(asn1::Sequence<'a>), + + #[implicit(6)] + UniformResourceIdentifier(UnvalidatedIA5String<'a>), + + #[implicit(7)] + IPAddress(&'a [u8]), + + #[implicit(8)] + RegisteredID(asn1::ObjectIdentifier<'a>), } #[derive(asn1::Asn1Read)] @@ -36,6 +81,114 @@ struct PolicyConstraints { inhibit_policy_mapping: Option, } +fn parse_name_attribute( + py: pyo3::Python<'_>, + attribute: AttributeTypeValue, +) -> Result { + let x509_module = py.import("cryptography.x509")?; + let oid = x509_module + .call_method1("ObjectIdentifier", (attribute.type_id.to_string(),))? + .to_object(py); + let tag_enum = py + .import("cryptography.x509.name")? + .getattr("_ASN1_TYPE_TO_ENUM")?; + let py_tag = tag_enum.get_item(attribute.value.tag().to_object(py))?; + let py_data = + std::str::from_utf8(attribute.value.data()).map_err(|_| asn1::ParseError::InvalidValue)?; + Ok(x509_module + .call_method1("NameAttribute", (oid, py_data, py_tag))? + .to_object(py)) +} + +fn parse_name(py: pyo3::Python<'_>, name: Name) -> Result { + let x509_module = py.import("cryptography.x509")?; + let py_rdns = pyo3::types::PyList::empty(py); + for rdn in name { + let py_attrs = pyo3::types::PySet::empty(py)?; + for attribute in rdn { + let na = parse_name_attribute(py, attribute)?; + py_attrs.add(na)?; + } + let py_rdn = x509_module + .call_method1("RelativeDistinguishedName", (py_attrs,))? + .to_object(py); + py_rdns.append(py_rdn)?; + } + let py_name = x509_module.call_method1("Name", (py_rdns,))?.to_object(py); + Ok(py_name) +} + +fn parse_general_name( + py: pyo3::Python<'_>, + gn: GeneralName, +) -> Result { + let x509_module = py.import("cryptography.x509")?; + let py_gn = match gn { + GeneralName::OtherName(data) => { + let oid = x509_module + .call_method1("ObjectIdentifier", (data.type_id.to_string(),))? + .to_object(py); + x509_module + .call_method1("OtherName", (oid, data.value.data()))? + .to_object(py) + } + GeneralName::RFC822Name(data) => x509_module + .getattr("RFC822Name")? + .call_method1("_init_without_validation", (data.0,))? + .to_object(py), + GeneralName::DNSName(data) => x509_module + .getattr("DNSName")? + .call_method1("_init_without_validation", (data.0,))? + .to_object(py), + GeneralName::DirectoryName(data) => { + let py_name = parse_name(py, data)?; + x509_module + .call_method1("DirectoryName", (py_name,))? + .to_object(py) + } + GeneralName::UniformResourceIdentifier(data) => x509_module + .getattr("UniformResourceIdentifier")? + .call_method1("_init_without_validation", (data.0,))? + .to_object(py), + GeneralName::IPAddress(data) => { + let ip_module = py.import("ipaddress")?; + let ip_addr = ip_module.call_method1("ip_address", (data,))?.to_object(py); + x509_module + .call_method1("IPAddress", (ip_addr,))? + .to_object(py) + } + GeneralName::RegisteredID(data) => { + let oid = x509_module + .call_method1("ObjectIdentifier", (data.to_string(),))? + .to_object(py); + x509_module + .call_method1("RegisteredID", (oid,))? + .to_object(py) + } + _ => { + return Err(PyAsn1Error::from(pyo3::PyErr::from_instance( + x509_module.call_method1( + "UnsupportedGeneralNameType", + ("x400Address/EDIPartyName are not supported types",), + )?, + ))) + } + }; + Ok(py_gn) +} + +fn parse_general_names( + py: pyo3::Python<'_>, + ext_data: &[u8], +) -> Result { + let gns = pyo3::types::PyList::empty(py); + for gn in asn1::parse_single::>(ext_data)? { + let py_gn = parse_general_name(py, gn)?; + gns.append(py_gn)?; + } + Ok(gns.to_object(py)) +} + #[pyo3::prelude::pyfunction] fn parse_x509_extension( py: pyo3::Python<'_>, @@ -45,7 +198,12 @@ fn parse_x509_extension( let oid = asn1::ObjectIdentifier::from_der(der_oid).unwrap(); let x509_module = py.import("cryptography.x509")?; - if oid == *TLS_FEATURE_OID { + if oid == *SUBJECT_ALTERNATIVE_NAME_OID { + let sans = parse_general_names(py, ext_data)?; + Ok(x509_module + .call1("SubjectAlternativeName", (sans,))? + .to_object(py)) + } else if oid == *TLS_FEATURE_OID { let tls_feature_type_to_enum = py .import("cryptography.x509.extensions")? .getattr("_TLS_FEATURE_TYPE_TO_ENUM")?; diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index 9d2585c9ef5e..67011d09cd10 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -2296,11 +2296,9 @@ def test_unsupported_gn(self, backend): x509.load_der_x509_certificate, backend, ) - with pytest.raises(x509.UnsupportedGeneralNameType) as exc: + with pytest.raises(x509.UnsupportedGeneralNameType): cert.extensions - assert exc.value.type == 3 - def test_registered_id(self, backend): cert = _load_cert( os.path.join("x509", "custom", "san_registered_id.pem"), From 8f433233e844da1befa201d8e1634d3829a1d31b Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 7 Jun 2021 11:15:00 -0500 Subject: [PATCH 0299/2380] oxidize cert issuer, IAN, AIA, SIA (#6093) * oxidize cert issuer * WIP: oxidize IAN (needs vector for CRL) * oxidize authorityinfoaccess and subjectinfoaccess * no longer need email path in SAN parser * cargo fmt --- .../hazmat/backends/openssl/decode_asn1.py | 72 +------------------ src/rust/src/x509.rs | 59 +++++++++++++++ 2 files changed, 61 insertions(+), 70 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 0248585556bd..035f084a817d 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -131,20 +131,11 @@ def _decode_general_name(backend, gn): ip = ipaddress.ip_network(base.exploded + "/{}".format(prefix)) return x509.IPAddress(ip) - elif gn.type == backend._lib.GEN_DIRNAME: + else: + assert gn.type == backend._lib.GEN_DIRNAME return x509.DirectoryName( _decode_x509_name(backend, gn.d.directoryName) ) - else: - assert gn.type == backend._lib.GEN_EMAIL - # Convert to bytes and then decode to utf8. We don't use - # asn1_string_to_utf8 here because it doesn't properly convert - # utf8 from ia5strings. - data = _asn1_string_to_bytes(backend, gn.d.rfc822Name).decode("utf8") - # We don't use the constructor for RFC822Name so we can bypass - # validation. This allows us to create RFC822Name objects that have - # unicode chars when a certificate (against the RFC) contains them. - return x509.RFC822Name._init_without_validation(data) class _X509ExtensionParser(object): @@ -298,40 +289,6 @@ def _decode_authority_key_identifier(backend, akid): ) -def _decode_information_access(backend, ia): - ia = backend._ffi.cast("Cryptography_STACK_OF_ACCESS_DESCRIPTION *", ia) - ia = backend._ffi.gc( - ia, - lambda x: backend._lib.sk_ACCESS_DESCRIPTION_pop_free( - x, - backend._ffi.addressof( - backend._lib._original_lib, "ACCESS_DESCRIPTION_free" - ), - ), - ) - num = backend._lib.sk_ACCESS_DESCRIPTION_num(ia) - access_descriptions = [] - for i in range(num): - ad = backend._lib.sk_ACCESS_DESCRIPTION_value(ia, i) - backend.openssl_assert(ad.method != backend._ffi.NULL) - oid = x509.ObjectIdentifier(_obj2txt(backend, ad.method)) - backend.openssl_assert(ad.location != backend._ffi.NULL) - gn = _decode_general_name(backend, ad.location) - access_descriptions.append(x509.AccessDescription(oid, gn)) - - return access_descriptions - - -def _decode_authority_information_access(backend, aia): - access_descriptions = _decode_information_access(backend, aia) - return x509.AuthorityInformationAccess(access_descriptions) - - -def _decode_subject_information_access(backend, aia): - access_descriptions = _decode_information_access(backend, aia) - return x509.SubjectInformationAccess(access_descriptions) - - def _decode_general_names_extension(backend, gns): gns = backend._ffi.cast("GENERAL_NAMES *", gns) gns = backend._ffi.gc(gns, backend._lib.GENERAL_NAMES_free) @@ -339,12 +296,6 @@ def _decode_general_names_extension(backend, gns): return general_names -def _decode_issuer_alt_name(backend, ext): - return x509.IssuerAlternativeName( - _decode_general_names_extension(backend, ext) - ) - - def _decode_name_constraints(backend, nc): nc = backend._ffi.cast("NAME_CONSTRAINTS *", nc) nc = backend._ffi.gc(nc, backend._lib.NAME_CONSTRAINTS_free) @@ -581,13 +532,6 @@ def _decode_invalidity_date(backend, inv_date): ) -def _decode_cert_issuer(backend, gns): - gns = backend._ffi.cast("GENERAL_NAMES *", gns) - gns = backend._ffi.gc(gns, backend._lib.GENERAL_NAMES_free) - general_names = _decode_general_names(backend, gns) - return x509.CertificateIssuer(general_names) - - def _asn1_integer_to_int(backend, asn1_int): bn = backend._lib.ASN1_INTEGER_to_BN(asn1_int, backend._ffi.NULL) backend.openssl_assert(bn != backend._ffi.NULL) @@ -652,16 +596,9 @@ def _parse_asn1_generalized_time(backend, generalized_time): _EXTENSION_HANDLERS_BASE = { ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _decode_authority_key_identifier, - ExtensionOID.AUTHORITY_INFORMATION_ACCESS: ( - _decode_authority_information_access - ), - ExtensionOID.SUBJECT_INFORMATION_ACCESS: ( - _decode_subject_information_access - ), ExtensionOID.CERTIFICATE_POLICIES: _decode_certificate_policies, ExtensionOID.CRL_DISTRIBUTION_POINTS: _decode_crl_distribution_points, ExtensionOID.FRESHEST_CRL: _decode_freshest_crl, - ExtensionOID.ISSUER_ALTERNATIVE_NAME: _decode_issuer_alt_name, ExtensionOID.NAME_CONSTRAINTS: _decode_name_constraints, } _EXTENSION_HANDLERS_SCT = { @@ -672,15 +609,10 @@ def _parse_asn1_generalized_time(backend, generalized_time): _REVOKED_EXTENSION_HANDLERS = { CRLEntryExtensionOID.INVALIDITY_DATE: _decode_invalidity_date, - CRLEntryExtensionOID.CERTIFICATE_ISSUER: _decode_cert_issuer, } _CRL_EXTENSION_HANDLERS = { ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _decode_authority_key_identifier, - ExtensionOID.ISSUER_ALTERNATIVE_NAME: _decode_issuer_alt_name, - ExtensionOID.AUTHORITY_INFORMATION_ACCESS: ( - _decode_authority_information_access - ), ExtensionOID.ISSUING_DISTRIBUTION_POINT: _decode_issuing_dist_point, ExtensionOID.FRESHEST_CRL: _decode_freshest_crl, } diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index 588c45d2a610..6db28400e119 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -9,6 +9,8 @@ lazy_static::lazy_static! { static ref TLS_FEATURE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.1.24").unwrap(); static ref PRECERT_POISON_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.4.1.11129.2.4.3").unwrap(); static ref OCSP_NO_CHECK_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.48.1.5").unwrap(); + static ref AUTHORITY_INFORMATION_ACCESS_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.1.1").unwrap(); + static ref SUBJECT_INFORMATION_ACCESS_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.1.11").unwrap(); static ref KEY_USAGE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.15").unwrap(); static ref POLICY_CONSTRAINTS_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.36").unwrap(); @@ -17,9 +19,11 @@ lazy_static::lazy_static! { static ref SUBJECT_KEY_IDENTIFIER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.14").unwrap(); static ref INHIBIT_ANY_POLICY_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.54").unwrap(); static ref CRL_REASON_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.21").unwrap(); + static ref CERTIFICATE_ISSUER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.29").unwrap(); static ref CRL_NUMBER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.20").unwrap(); static ref DELTA_CRL_INDICATOR_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.27").unwrap(); static ref SUBJECT_ALTERNATIVE_NAME_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.17").unwrap(); + static ref ISSUER_ALTERNATIVE_NAME_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.18").unwrap(); } struct UnvalidatedIA5String<'a>(&'a str); @@ -81,6 +85,12 @@ struct PolicyConstraints { inhibit_policy_mapping: Option, } +#[derive(asn1::Asn1Read)] +struct AccessDescription<'a> { + access_method: asn1::ObjectIdentifier<'a>, + access_location: GeneralName<'a>, +} + fn parse_name_attribute( py: pyo3::Python<'_>, attribute: AttributeTypeValue, @@ -189,6 +199,25 @@ fn parse_general_names( Ok(gns.to_object(py)) } +fn parse_access_descriptions( + py: pyo3::Python<'_>, + ext_data: &[u8], +) -> Result { + let x509_module = py.import("cryptography.x509")?; + let ads = pyo3::types::PyList::empty(py); + for access in asn1::parse_single::>(ext_data)? { + let py_oid = x509_module + .call_method1("ObjectIdentifier", (access.access_method.to_string(),))? + .to_object(py); + let gn = parse_general_name(py, access.access_location)?; + let ad = x509_module + .call1("AccessDescription", (py_oid, gn))? + .to_object(py); + ads.append(ad)?; + } + Ok(ads.to_object(py)) +} + #[pyo3::prelude::pyfunction] fn parse_x509_extension( py: pyo3::Python<'_>, @@ -203,6 +232,11 @@ fn parse_x509_extension( Ok(x509_module .call1("SubjectAlternativeName", (sans,))? .to_object(py)) + } else if oid == *ISSUER_ALTERNATIVE_NAME_OID { + let ians = parse_general_names(py, ext_data)?; + Ok(x509_module + .call1("IssuerAlternativeName", (ians,))? + .to_object(py)) } else if oid == *TLS_FEATURE_OID { let tls_feature_type_to_enum = py .import("cryptography.x509.extensions")? @@ -255,6 +289,16 @@ fn parse_x509_extension( ), )? .to_object(py)) + } else if oid == *AUTHORITY_INFORMATION_ACCESS_OID { + let ads = parse_access_descriptions(py, ext_data)?; + Ok(x509_module + .call1("AuthorityInformationAccess", (ads,))? + .to_object(py)) + } else if oid == *SUBJECT_INFORMATION_ACCESS_OID { + let ads = parse_access_descriptions(py, ext_data)?; + Ok(x509_module + .call1("SubjectInformationAccess", (ads,))? + .to_object(py)) } else if oid == *POLICY_CONSTRAINTS_OID { let pc = asn1::parse_single::(ext_data)?; Ok(x509_module @@ -314,6 +358,11 @@ fn parse_crl_entry_extension( }; let flag = x509_module.getattr("ReasonFlags")?.getattr(flag_name)?; Ok(x509_module.call1("CRLReason", (flag,))?.to_object(py)) + } else if oid == *CERTIFICATE_ISSUER_OID { + let gns = parse_general_names(py, ext_data)?; + Ok(x509_module + .call1("CertificateIssuer", (gns,))? + .to_object(py)) } else { Ok(py.None()) } @@ -338,6 +387,16 @@ fn parse_crl_extension( Ok(x509_module .call1("DeltaCRLIndicator", (pynum,))? .to_object(py)) + } else if oid == *ISSUER_ALTERNATIVE_NAME_OID { + let ians = parse_general_names(py, ext_data)?; + Ok(x509_module + .call1("IssuerAlternativeName", (ians,))? + .to_object(py)) + } else if oid == *AUTHORITY_INFORMATION_ACCESS_OID { + let ads = parse_access_descriptions(py, ext_data)?; + Ok(x509_module + .call1("AuthorityInformationAccess", (ads,))? + .to_object(py)) } else { Ok(py.None()) } From 63bfe529da518dbf8a2de0fa45c4fb6c5e410b9a Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 7 Jun 2021 13:24:41 -0400 Subject: [PATCH 0300/2380] remove dead function (#6094) --- src/cryptography/hazmat/backends/openssl/decode_asn1.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 035f084a817d..c947de11d88a 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -289,13 +289,6 @@ def _decode_authority_key_identifier(backend, akid): ) -def _decode_general_names_extension(backend, gns): - gns = backend._ffi.cast("GENERAL_NAMES *", gns) - gns = backend._ffi.gc(gns, backend._lib.GENERAL_NAMES_free) - general_names = _decode_general_names(backend, gns) - return general_names - - def _decode_name_constraints(backend, nc): nc = backend._ffi.cast("NAME_CONSTRAINTS *", nc) nc = backend._ffi.gc(nc, backend._lib.NAME_CONSTRAINTS_free) From 69bafedf7d3d16af9c75e3929c728b7353af30e3 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 7 Jun 2021 22:05:43 -0500 Subject: [PATCH 0301/2380] oxidize authoritykeyidentifier (#6096) * oxidize authoritykeyidentifier * cargo fmt * Apply suggestions from code review Co-authored-by: Alex Gaynor * coverage Co-authored-by: Alex Gaynor --- .../hazmat/backends/openssl/decode_asn1.py | 32 ----------- src/rust/src/x509.rs | 55 ++++++++++++++++--- 2 files changed, 48 insertions(+), 39 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index c947de11d88a..8b2bc6aa46c6 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -266,29 +266,6 @@ def _decode_user_notice(backend, un): return x509.UserNotice(notice_reference, explicit_text) -def _decode_authority_key_identifier(backend, akid): - akid = backend._ffi.cast("AUTHORITY_KEYID *", akid) - akid = backend._ffi.gc(akid, backend._lib.AUTHORITY_KEYID_free) - key_identifier = None - authority_cert_issuer = None - - if akid.keyid != backend._ffi.NULL: - key_identifier = backend._ffi.buffer( - akid.keyid.data, akid.keyid.length - )[:] - - if akid.issuer != backend._ffi.NULL: - authority_cert_issuer = _decode_general_names(backend, akid.issuer) - - authority_cert_serial_number = _asn1_integer_to_int_or_none( - backend, akid.serial - ) - - return x509.AuthorityKeyIdentifier( - key_identifier, authority_cert_issuer, authority_cert_serial_number - ) - - def _decode_name_constraints(backend, nc): nc = backend._ffi.cast("NAME_CONSTRAINTS *", nc) nc = backend._ffi.gc(nc, backend._lib.NAME_CONSTRAINTS_free) @@ -532,13 +509,6 @@ def _asn1_integer_to_int(backend, asn1_int): return backend._bn_to_int(bn) -def _asn1_integer_to_int_or_none(backend, asn1_int): - if asn1_int == backend._ffi.NULL: - return None - else: - return _asn1_integer_to_int(backend, asn1_int) - - def _asn1_string_to_bytes(backend, asn1_string): return backend._ffi.buffer(asn1_string.data, asn1_string.length)[:] @@ -588,7 +558,6 @@ def _parse_asn1_generalized_time(backend, generalized_time): _EXTENSION_HANDLERS_BASE = { - ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _decode_authority_key_identifier, ExtensionOID.CERTIFICATE_POLICIES: _decode_certificate_policies, ExtensionOID.CRL_DISTRIBUTION_POINTS: _decode_crl_distribution_points, ExtensionOID.FRESHEST_CRL: _decode_freshest_crl, @@ -605,7 +574,6 @@ def _parse_asn1_generalized_time(backend, generalized_time): } _CRL_EXTENSION_HANDLERS = { - ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _decode_authority_key_identifier, ExtensionOID.ISSUING_DISTRIBUTION_POINT: _decode_issuing_dist_point, ExtensionOID.FRESHEST_CRL: _decode_freshest_crl, } diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index 6db28400e119..3e64e1e2e524 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -14,6 +14,7 @@ lazy_static::lazy_static! { static ref KEY_USAGE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.15").unwrap(); static ref POLICY_CONSTRAINTS_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.36").unwrap(); + static ref AUTHORITY_KEY_IDENTIFIER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.35").unwrap(); static ref EXTENDED_KEY_USAGE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.37").unwrap(); static ref BASIC_CONSTRAINTS_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.19").unwrap(); static ref SUBJECT_KEY_IDENTIFIER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.14").unwrap(); @@ -37,6 +38,16 @@ impl<'a> asn1::SimpleAsn1Readable<'a> for UnvalidatedIA5String<'a> { } } +#[derive(asn1::Asn1Read)] +struct AuthorityKeyIdentifier<'a> { + #[implicit(0)] + key_identifier: Option<&'a [u8]>, + #[implicit(1)] + authority_cert_issuer: Option>>, + #[implicit(2)] + authority_cert_serial_number: Option>, +} + #[derive(asn1::Asn1Read)] enum GeneralName<'a> { #[implicit(0)] @@ -91,6 +102,28 @@ struct AccessDescription<'a> { access_location: GeneralName<'a>, } +fn parse_authority_key_identifier( + py: pyo3::Python<'_>, + ext_data: &[u8], +) -> Result { + let x509_module = py.import("cryptography.x509")?; + let aki = asn1::parse_single::(ext_data)?; + let serial = match aki.authority_cert_serial_number { + Some(biguint) => big_asn1_uint_to_py(py, biguint)?.to_object(py), + None => py.None(), + }; + let issuer = match aki.authority_cert_issuer { + Some(aci) => parse_general_names(py, aci)?, + None => py.None(), + }; + Ok(x509_module + .call1( + "AuthorityKeyIdentifier", + (aki.key_identifier, issuer, serial), + )? + .to_object(py)) +} + fn parse_name_attribute( py: pyo3::Python<'_>, attribute: AttributeTypeValue, @@ -187,12 +220,12 @@ fn parse_general_name( Ok(py_gn) } -fn parse_general_names( +fn parse_general_names<'a>( py: pyo3::Python<'_>, - ext_data: &[u8], + gn_seq: asn1::SequenceOf<'a, GeneralName<'a>>, ) -> Result { let gns = pyo3::types::PyList::empty(py); - for gn in asn1::parse_single::>(ext_data)? { + for gn in gn_seq { let py_gn = parse_general_name(py, gn)?; gns.append(py_gn)?; } @@ -228,12 +261,14 @@ fn parse_x509_extension( let x509_module = py.import("cryptography.x509")?; if oid == *SUBJECT_ALTERNATIVE_NAME_OID { - let sans = parse_general_names(py, ext_data)?; + let gn_seq = asn1::parse_single::>(ext_data)?; + let sans = parse_general_names(py, gn_seq)?; Ok(x509_module .call1("SubjectAlternativeName", (sans,))? .to_object(py)) } else if oid == *ISSUER_ALTERNATIVE_NAME_OID { - let ians = parse_general_names(py, ext_data)?; + let gn_seq = asn1::parse_single::>(ext_data)?; + let ians = parse_general_names(py, gn_seq)?; Ok(x509_module .call1("IssuerAlternativeName", (ians,))? .to_object(py)) @@ -324,6 +359,8 @@ fn parse_x509_extension( Ok(x509_module .call1("BasicConstraints", (bc.ca, bc.path_length))? .to_object(py)) + } else if oid == *AUTHORITY_KEY_IDENTIFIER_OID { + Ok(parse_authority_key_identifier(py, ext_data)?) } else { Ok(py.None()) } @@ -359,7 +396,8 @@ fn parse_crl_entry_extension( let flag = x509_module.getattr("ReasonFlags")?.getattr(flag_name)?; Ok(x509_module.call1("CRLReason", (flag,))?.to_object(py)) } else if oid == *CERTIFICATE_ISSUER_OID { - let gns = parse_general_names(py, ext_data)?; + let gn_seq = asn1::parse_single::>(ext_data)?; + let gns = parse_general_names(py, gn_seq)?; Ok(x509_module .call1("CertificateIssuer", (gns,))? .to_object(py)) @@ -388,7 +426,8 @@ fn parse_crl_extension( .call1("DeltaCRLIndicator", (pynum,))? .to_object(py)) } else if oid == *ISSUER_ALTERNATIVE_NAME_OID { - let ians = parse_general_names(py, ext_data)?; + let gn_seq = asn1::parse_single::>(ext_data)?; + let ians = parse_general_names(py, gn_seq)?; Ok(x509_module .call1("IssuerAlternativeName", (ians,))? .to_object(py)) @@ -397,6 +436,8 @@ fn parse_crl_extension( Ok(x509_module .call1("AuthorityInformationAccess", (ads,))? .to_object(py)) + } else if oid == *AUTHORITY_KEY_IDENTIFIER_OID { + Ok(parse_authority_key_identifier(py, ext_data)?) } else { Ok(py.None()) } From 0ce8f3a25120fbba775b6a7c8cc344a32c55afbf Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 7 Jun 2021 23:28:18 -0400 Subject: [PATCH 0302/2380] Enable the Rust 2018 idioms warning and fix them (#6095) --- src/rust/src/asn1.rs | 10 +++++----- src/rust/src/lib.rs | 2 ++ src/rust/src/ocsp.rs | 10 +++++----- src/rust/src/x509.rs | 33 +++++++++++++++++---------------- 4 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs index 706ced54d9b3..28f458e49c0c 100644 --- a/src/rust/src/asn1.rs +++ b/src/rust/src/asn1.rs @@ -69,7 +69,7 @@ struct Spki<'a> { #[pyo3::prelude::pyfunction] fn parse_spki_for_data(py: pyo3::Python<'_>, data: &[u8]) -> Result { - let spki = asn1::parse_single::(data)?; + let spki = asn1::parse_single::>(data)?; if spki.data.padding_bits() != 0 { return Err(pyo3::exceptions::PyValueError::new_err("Invalid public key encoding").into()); } @@ -85,7 +85,7 @@ struct DssSignature<'a> { pub(crate) fn big_asn1_uint_to_py<'p>( py: pyo3::Python<'p>, - v: asn1::BigUint, + v: asn1::BigUint<'_>, ) -> pyo3::PyResult<&'p pyo3::PyAny> { let int_type = py.get_type::(); int_type.call_method1("from_bytes", (v.as_bytes(), "big")) @@ -93,7 +93,7 @@ pub(crate) fn big_asn1_uint_to_py<'p>( #[pyo3::prelude::pyfunction] fn decode_dss_signature(py: pyo3::Python<'_>, data: &[u8]) -> Result { - let sig = asn1::parse_single::(data)?; + let sig = asn1::parse_single::>(data)?; Ok(( big_asn1_uint_to_py(py, sig.r)?, @@ -200,7 +200,7 @@ fn parse_name_value_tags(rdns: &mut Name<'_>) -> Result, PyAsn1Error> { #[pyo3::prelude::pyfunction] fn test_parse_certificate(data: &[u8]) -> Result { - let mut asn1_cert = asn1::parse_single::(data)?; + let mut asn1_cert = asn1::parse_single::>(data)?; Ok(TestCertificate { not_before_tag: asn1_cert.tbs_cert.validity.not_before.tag(), @@ -210,7 +210,7 @@ fn test_parse_certificate(data: &[u8]) -> Result { }) } -pub(crate) fn create_submodule(py: pyo3::Python) -> pyo3::PyResult<&pyo3::prelude::PyModule> { +pub(crate) fn create_submodule(py: pyo3::Python<'_>) -> pyo3::PyResult<&pyo3::prelude::PyModule> { let submod = pyo3::prelude::PyModule::new(py, "asn1")?; submod.add_wrapped(pyo3::wrap_pyfunction!(encode_tls_feature))?; submod.add_wrapped(pyo3::wrap_pyfunction!(encode_precert_poison))?; diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs index dbde1d9de22a..9e7315c40ff5 100644 --- a/src/rust/src/lib.rs +++ b/src/rust/src/lib.rs @@ -2,6 +2,8 @@ // 2.0, and the BSD License. See the LICENSE file in the root of this repository // for complete details. +#![deny(rust_2018_idioms)] + mod asn1; mod ocsp; mod x509; diff --git a/src/rust/src/ocsp.rs b/src/rust/src/ocsp.rs index ddbe4f0503c0..6068e72116a8 100644 --- a/src/rust/src/ocsp.rs +++ b/src/rust/src/ocsp.rs @@ -61,7 +61,7 @@ struct OCSPRequest { } impl OCSPRequest { - fn cert_id(&self) -> Result { + fn cert_id(&self) -> Result, PyAsn1Error> { Ok(self .raw .borrow_value() @@ -76,11 +76,11 @@ impl OCSPRequest { fn parse_and_cache_extensions< 'p, - F: Fn(&asn1::ObjectIdentifier, &[u8]) -> Result, PyAsn1Error>, + F: Fn(&asn1::ObjectIdentifier<'_>, &[u8]) -> Result, PyAsn1Error>, >( py: pyo3::Python<'p>, cached_extensions: &mut Option, - raw_exts: &Option, + raw_exts: &Option>, parse_ext: F, ) -> Result { if let Some(cached) = cached_extensions { @@ -165,7 +165,7 @@ impl OCSPRequest { } #[getter] - fn extensions(&mut self, py: pyo3::Python) -> Result { + fn extensions(&mut self, py: pyo3::Python<'_>) -> Result { let x509_module = py.import("cryptography.x509")?; parse_and_cache_extensions( py, @@ -285,7 +285,7 @@ fn parse_ocsp_resp_extension( } } -pub(crate) fn create_submodule(py: pyo3::Python) -> pyo3::PyResult<&pyo3::prelude::PyModule> { +pub(crate) fn create_submodule(py: pyo3::Python<'_>) -> pyo3::PyResult<&pyo3::prelude::PyModule> { let submod = pyo3::prelude::PyModule::new(py, "ocsp")?; submod.add_wrapped(pyo3::wrap_pyfunction!(load_der_ocsp_request))?; diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index 3e64e1e2e524..e2480013c7c0 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -107,7 +107,7 @@ fn parse_authority_key_identifier( ext_data: &[u8], ) -> Result { let x509_module = py.import("cryptography.x509")?; - let aki = asn1::parse_single::(ext_data)?; + let aki = asn1::parse_single::>(ext_data)?; let serial = match aki.authority_cert_serial_number { Some(biguint) => big_asn1_uint_to_py(py, biguint)?.to_object(py), None => py.None(), @@ -126,7 +126,7 @@ fn parse_authority_key_identifier( fn parse_name_attribute( py: pyo3::Python<'_>, - attribute: AttributeTypeValue, + attribute: AttributeTypeValue<'_>, ) -> Result { let x509_module = py.import("cryptography.x509")?; let oid = x509_module @@ -143,7 +143,7 @@ fn parse_name_attribute( .to_object(py)) } -fn parse_name(py: pyo3::Python<'_>, name: Name) -> Result { +fn parse_name(py: pyo3::Python<'_>, name: Name<'_>) -> Result { let x509_module = py.import("cryptography.x509")?; let py_rdns = pyo3::types::PyList::empty(py); for rdn in name { @@ -163,7 +163,7 @@ fn parse_name(py: pyo3::Python<'_>, name: Name) -> Result, - gn: GeneralName, + gn: GeneralName<'_>, ) -> Result { let x509_module = py.import("cryptography.x509")?; let py_gn = match gn { @@ -238,7 +238,7 @@ fn parse_access_descriptions( ) -> Result { let x509_module = py.import("cryptography.x509")?; let ads = pyo3::types::PyList::empty(py); - for access in asn1::parse_single::>(ext_data)? { + for access in asn1::parse_single::>>(ext_data)? { let py_oid = x509_module .call_method1("ObjectIdentifier", (access.access_method.to_string(),))? .to_object(py); @@ -261,13 +261,13 @@ fn parse_x509_extension( let x509_module = py.import("cryptography.x509")?; if oid == *SUBJECT_ALTERNATIVE_NAME_OID { - let gn_seq = asn1::parse_single::>(ext_data)?; + let gn_seq = asn1::parse_single::>>(ext_data)?; let sans = parse_general_names(py, gn_seq)?; Ok(x509_module .call1("SubjectAlternativeName", (sans,))? .to_object(py)) } else if oid == *ISSUER_ALTERNATIVE_NAME_OID { - let gn_seq = asn1::parse_single::>(ext_data)?; + let gn_seq = asn1::parse_single::>>(ext_data)?; let ians = parse_general_names(py, gn_seq)?; Ok(x509_module .call1("IssuerAlternativeName", (ians,))? @@ -278,7 +278,7 @@ fn parse_x509_extension( .getattr("_TLS_FEATURE_TYPE_TO_ENUM")?; let features = pyo3::types::PyList::empty(py); - for feature in asn1::parse_single::>(ext_data)? { + for feature in asn1::parse_single::>(ext_data)? { let py_feature = tls_feature_type_to_enum.get_item(feature.to_object(py))?; features.append(py_feature)?; } @@ -290,7 +290,8 @@ fn parse_x509_extension( .to_object(py)) } else if oid == *EXTENDED_KEY_USAGE_OID { let ekus = pyo3::types::PyList::empty(py); - for oid in asn1::parse_single::>(ext_data)? { + for oid in asn1::parse_single::>>(ext_data)? + { let oid_obj = x509_module.call_method1("ObjectIdentifier", (oid.to_string(),))?; ekus.append(oid_obj)?; } @@ -298,7 +299,7 @@ fn parse_x509_extension( .call1("ExtendedKeyUsage", (ekus,))? .to_object(py)) } else if oid == *KEY_USAGE_OID { - let kus = asn1::parse_single::(ext_data)?; + let kus = asn1::parse_single::>(ext_data)?; let digital_signature = kus.has_bit_set(0); let content_comitment = kus.has_bit_set(1); let key_encipherment = kus.has_bit_set(2); @@ -349,7 +350,7 @@ fn parse_x509_extension( asn1::parse_single::<()>(ext_data)?; Ok(x509_module.call0("OCSPNoCheck")?.to_object(py)) } else if oid == *INHIBIT_ANY_POLICY_OID { - let bignum = asn1::parse_single::(ext_data)?; + let bignum = asn1::parse_single::>(ext_data)?; let pynum = big_asn1_uint_to_py(py, bignum)?; Ok(x509_module .call1("InhibitAnyPolicy", (pynum,))? @@ -396,7 +397,7 @@ fn parse_crl_entry_extension( let flag = x509_module.getattr("ReasonFlags")?.getattr(flag_name)?; Ok(x509_module.call1("CRLReason", (flag,))?.to_object(py)) } else if oid == *CERTIFICATE_ISSUER_OID { - let gn_seq = asn1::parse_single::>(ext_data)?; + let gn_seq = asn1::parse_single::>>(ext_data)?; let gns = parse_general_names(py, gn_seq)?; Ok(x509_module .call1("CertificateIssuer", (gns,))? @@ -416,17 +417,17 @@ fn parse_crl_extension( let x509_module = py.import("cryptography.x509")?; if oid == *CRL_NUMBER_OID { - let bignum = asn1::parse_single::(ext_data)?; + let bignum = asn1::parse_single::>(ext_data)?; let pynum = big_asn1_uint_to_py(py, bignum)?; Ok(x509_module.call1("CRLNumber", (pynum,))?.to_object(py)) } else if oid == *DELTA_CRL_INDICATOR_OID { - let bignum = asn1::parse_single::(ext_data)?; + let bignum = asn1::parse_single::>(ext_data)?; let pynum = big_asn1_uint_to_py(py, bignum)?; Ok(x509_module .call1("DeltaCRLIndicator", (pynum,))? .to_object(py)) } else if oid == *ISSUER_ALTERNATIVE_NAME_OID { - let gn_seq = asn1::parse_single::>(ext_data)?; + let gn_seq = asn1::parse_single::>>(ext_data)?; let ians = parse_general_names(py, gn_seq)?; Ok(x509_module .call1("IssuerAlternativeName", (ians,))? @@ -443,7 +444,7 @@ fn parse_crl_extension( } } -pub(crate) fn create_submodule(py: pyo3::Python) -> pyo3::PyResult<&pyo3::prelude::PyModule> { +pub(crate) fn create_submodule(py: pyo3::Python<'_>) -> pyo3::PyResult<&pyo3::prelude::PyModule> { let submod = pyo3::prelude::PyModule::new(py, "x509")?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_x509_extension))?; From 6a843c42e2a2f0f278238e3a91242d41dc40388d Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 8 Jun 2021 20:57:02 -0400 Subject: [PATCH 0303/2380] fix mypy build for latest release (#6099) --- tox.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/tox.ini b/tox.ini index 19adafc2b28a..1f7debd4ed5a 100644 --- a/tox.ini +++ b/tox.ini @@ -54,6 +54,7 @@ extras = ssh deps = mypy + types-pytz check-manifest commands = flake8 . From 5565587b0b03e067a0c2f701884504cfae384886 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 8 Jun 2021 23:25:07 -0500 Subject: [PATCH 0304/2380] oxidize invaliditydate (#6101) * oxidize invaliditydate * linters win every time * prettier --- .../hazmat/backends/openssl/backend.py | 4 +--- .../hazmat/backends/openssl/decode_asn1.py | 15 --------------- src/rust/Cargo.lock | 1 + src/rust/Cargo.toml | 1 + src/rust/src/x509.rs | 18 ++++++++++++++++++ 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 0376843d15d2..53ba826a726a 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -22,7 +22,6 @@ _EXTENSION_HANDLERS_BASE, _EXTENSION_HANDLERS_SCT, _OCSP_SINGLERESP_EXTENSION_HANDLERS_SCT, - _REVOKED_EXTENSION_HANDLERS, _X509ExtensionParser, ) from cryptography.hazmat.backends.openssl.dh import ( @@ -391,7 +390,7 @@ def _register_x509_ext_parsers(self): ext_handlers = _EXTENSION_HANDLERS_BASE.copy() # All revoked extensions are valid single response extensions, see: # https://tools.ietf.org/html/rfc6960#section-4.4.5 - singleresp_handlers = _REVOKED_EXTENSION_HANDLERS.copy() + singleresp_handlers = {} if self._lib.Cryptography_HAS_SCT: ext_handlers.update(_EXTENSION_HANDLERS_SCT) @@ -416,7 +415,6 @@ def _register_x509_ext_parsers(self): ext_count=self._lib.X509_REVOKED_get_ext_count, get_ext=self._lib.X509_REVOKED_get_ext, rust_callback=rust_x509.parse_crl_entry_extension, - handlers=_REVOKED_EXTENSION_HANDLERS, ) self._crl_extension_parser = _X509ExtensionParser( self, diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 8b2bc6aa46c6..3cdd5345fe1f 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -10,7 +10,6 @@ from cryptography import x509 from cryptography.x509.name import _ASN1_TYPE_TO_ENUM from cryptography.x509.oid import ( - CRLEntryExtensionOID, CertificatePoliciesOID, ExtensionOID, ) @@ -492,16 +491,6 @@ def _decode_signed_certificate_timestamps(backend, asn1_scts): } -def _decode_invalidity_date(backend, inv_date): - generalized_time = backend._ffi.cast("ASN1_GENERALIZEDTIME *", inv_date) - generalized_time = backend._ffi.gc( - generalized_time, backend._lib.ASN1_GENERALIZEDTIME_free - ) - return x509.InvalidityDate( - _parse_asn1_generalized_time(backend, generalized_time) - ) - - def _asn1_integer_to_int(backend, asn1_int): bn = backend._lib.ASN1_INTEGER_to_BN(asn1_int, backend._ffi.NULL) backend.openssl_assert(bn != backend._ffi.NULL) @@ -569,10 +558,6 @@ def _parse_asn1_generalized_time(backend, generalized_time): ) } -_REVOKED_EXTENSION_HANDLERS = { - CRLEntryExtensionOID.INVALIDITY_DATE: _decode_invalidity_date, -} - _CRL_EXTENSION_HANDLERS = { ExtensionOID.ISSUING_DISTRIBUTION_POINT: _decode_issuing_dist_point, ExtensionOID.FRESHEST_CRL: _decode_freshest_crl, diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 240d2b1c124a..70f01f1895a0 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -62,6 +62,7 @@ name = "cryptography-rust" version = "0.1.0" dependencies = [ "asn1", + "chrono", "lazy_static", "ouroboros", "pyo3", diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index e70b20865346..dd535181f95c 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -9,6 +9,7 @@ publish = false lazy_static = "1" pyo3 = { version = "0.13.1" } asn1 = { version = "0.5.1", default-features = false, features = ["derive"] } +chrono = { version = "0.4", default-features = false, features = ["alloc"] } ouroboros = "0.9" [features] diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index e2480013c7c0..977f4e8edc53 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -3,6 +3,7 @@ // for complete details. use crate::asn1::{big_asn1_uint_to_py, AttributeTypeValue, Name, PyAsn1Error}; +use chrono::{Datelike, Timelike}; use pyo3::conversion::ToPyObject; lazy_static::lazy_static! { @@ -22,6 +23,7 @@ lazy_static::lazy_static! { static ref CRL_REASON_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.21").unwrap(); static ref CERTIFICATE_ISSUER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.29").unwrap(); static ref CRL_NUMBER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.20").unwrap(); + static ref INVALIDITY_DATE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.24").unwrap(); static ref DELTA_CRL_INDICATOR_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.27").unwrap(); static ref SUBJECT_ALTERNATIVE_NAME_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.17").unwrap(); static ref ISSUER_ALTERNATIVE_NAME_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.18").unwrap(); @@ -402,6 +404,22 @@ fn parse_crl_entry_extension( Ok(x509_module .call1("CertificateIssuer", (gns,))? .to_object(py)) + } else if oid == *INVALIDITY_DATE_OID { + let time = asn1::parse_single::(ext_data)?; + let time_chrono = time.as_chrono(); + let datetime_module = py.import("datetime")?; + let py_dt = datetime_module.call1( + "datetime", + ( + time_chrono.year(), + time_chrono.month(), + time_chrono.day(), + time_chrono.hour(), + time_chrono.minute(), + time_chrono.second(), + ), + )?; + Ok(x509_module.call1("InvalidityDate", (py_dt,))?.to_object(py)) } else { Ok(py.None()) } From 1eeee2b8431b81b52a006881d2381ef97c2d1914 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jun 2021 07:23:56 -0400 Subject: [PATCH 0305/2380] Bump libc from 0.2.95 to 0.2.96 in /src/rust (#6102) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.95 to 0.2.96. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.95...0.2.96) --- updated-dependencies: - dependency-name: libc dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 70f01f1895a0..7622e6587187 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -151,9 +151,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.95" +version = "0.2.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36" +checksum = "5600b4e6efc5421841a2138a6b082e07fe12f9aaa12783d50e5d13325b26b4fc" [[package]] name = "lock_api" From f0715b835ed5d71cf0b38f165ac6d28e003b4bb5 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 9 Jun 2021 21:41:36 +1000 Subject: [PATCH 0306/2380] Added handling for OpenSSL "xts duplicated keys" error. (#6085) * Added handling for OpenSSL "xts duplicated keys" error. Closes #5998 This error value was added pre-OpenSSL 1.1.1d here: https://github.com/openssl/openssl/commit/2a5f63c9a61be7582620c4b5da202bb3fd7e4138 and refined to only cover encryption shortly after: https://github.com/openssl/openssl/commit/58ae5a47da1e4843b0cd1846eb297b341d0e7201 * test_aes: Remove unnecessary assignment * xts: Update duplicated keys check for OpenSSL 3 providers Also, change the exception message slightly: - Now matches the tense used by openssl - Turns out decryption *is* checked for duplicate keys by OpenSSL 3 when in FIPS mode --- src/_cffi_src/openssl/cryptography.py | 3 +++ src/_cffi_src/openssl/err.py | 5 ++++ src/_cffi_src/openssl/provider.py | 2 ++ .../hazmat/backends/openssl/ciphers.py | 23 ++++++++++++++++++- tests/hazmat/primitives/test_aes.py | 13 +++++++++++ 5 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/_cffi_src/openssl/cryptography.py b/src/_cffi_src/openssl/cryptography.py index e9a9a522e8b6..802a72acbf58 100644 --- a/src/_cffi_src/openssl/cryptography.py +++ b/src/_cffi_src/openssl/cryptography.py @@ -41,6 +41,8 @@ #define CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER \ (OPENSSL_VERSION_NUMBER >= 0x1010006f && !CRYPTOGRAPHY_IS_LIBRESSL) +#define CRYPTOGRAPHY_OPENSSL_111D_OR_GREATER \ + (OPENSSL_VERSION_NUMBER >= 0x10101040 && !CRYPTOGRAPHY_IS_LIBRESSL) #define CRYPTOGRAPHY_OPENSSL_300_OR_GREATER \ (OPENSSL_VERSION_NUMBER >= 0x30000000 && !CRYPTOGRAPHY_IS_LIBRESSL) @@ -62,6 +64,7 @@ TYPES = """ static const int CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER; +static const int CRYPTOGRAPHY_OPENSSL_111D_OR_GREATER; static const int CRYPTOGRAPHY_OPENSSL_300_OR_GREATER; static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_111; diff --git a/src/_cffi_src/openssl/err.py b/src/_cffi_src/openssl/err.py index 8cfeaf5ba38a..54dd1e44c43d 100644 --- a/src/_cffi_src/openssl/err.py +++ b/src/_cffi_src/openssl/err.py @@ -15,6 +15,7 @@ static const int PKCS12_R_PKCS12_CIPHERFINAL_ERROR; static const int PEM_R_UNSUPPORTED_ENCRYPTION; static const int EVP_R_UNKNOWN_PBE_ALGORITHM; +static const int EVP_R_XTS_DUPLICATED_KEYS; static const int ERR_LIB_EVP; static const int ERR_LIB_PEM; @@ -51,4 +52,8 @@ #ifndef ERR_LIB_PROV #define ERR_LIB_PROV 0 #endif + +#if !CRYPTOGRAPHY_OPENSSL_111D_OR_GREATER +static const int EVP_R_XTS_DUPLICATED_KEYS = 0; +#endif """ diff --git a/src/_cffi_src/openssl/provider.py b/src/_cffi_src/openssl/provider.py index d7d659ea5ef4..d741ad7e4f55 100644 --- a/src/_cffi_src/openssl/provider.py +++ b/src/_cffi_src/openssl/provider.py @@ -17,6 +17,7 @@ typedef ... OSSL_LIB_CTX; static const long PROV_R_BAD_DECRYPT; +static const long PROV_R_XTS_DUPLICATED_KEYS; static const long PROV_R_WRONG_FINAL_BLOCK_LENGTH; """ @@ -33,6 +34,7 @@ typedef void OSSL_PROVIDER; typedef void OSSL_LIB_CTX; static const long PROV_R_BAD_DECRYPT = 0; +static const long PROV_R_XTS_DUPLICATED_KEYS = 0; static const long PROV_R_WRONG_FINAL_BLOCK_LENGTH = 0; OSSL_PROVIDER *(*OSSL_PROVIDER_load)(OSSL_LIB_CTX *, const char *) = NULL; int (*OSSL_PROVIDER_unload)(OSSL_PROVIDER *) = NULL; diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py index eb302e44f9eb..ec272e04d4f4 100644 --- a/src/cryptography/hazmat/backends/openssl/ciphers.py +++ b/src/cryptography/hazmat/backends/openssl/ciphers.py @@ -112,7 +112,28 @@ def __init__(self, backend, cipher, mode, operation): iv_nonce, operation, ) - self._backend.openssl_assert(res != 0) + + # Check for XTS mode duplicate keys error + errors = self._backend._consume_errors() + lib = self._backend._lib + if res == 0 and ( + ( + lib.CRYPTOGRAPHY_OPENSSL_111D_OR_GREATER + and errors[0]._lib_reason_match( + lib.ERR_LIB_EVP, lib.EVP_R_XTS_DUPLICATED_KEYS + ) + ) + or ( + lib.Cryptography_HAS_PROVIDERS + and errors[0]._lib_reason_match( + lib.ERR_LIB_PROV, lib.PROV_R_XTS_DUPLICATED_KEYS + ) + ) + ): + raise ValueError("In XTS mode duplicated keys are not allowed") + + self._backend.openssl_assert(res != 0, errors=errors) + # We purposely disable padding here as it's handled higher up in the # API. self._backend._lib.EVP_CIPHER_CTX_set_padding(ctx, 0) diff --git a/tests/hazmat/primitives/test_aes.py b/tests/hazmat/primitives/test_aes.py index fd37b7696d96..eb6f74b92d5a 100644 --- a/tests/hazmat/primitives/test_aes.py +++ b/tests/hazmat/primitives/test_aes.py @@ -60,6 +60,19 @@ def test_xts_too_short(self): with pytest.raises(ValueError): enc.update(b"0" * 15) + @pytest.mark.supported( + only_if=lambda backend: ( + backend._lib.CRYPTOGRAPHY_OPENSSL_111D_OR_GREATER + ), + skip_message="duplicate key encryption error added in OpenSSL 1.1.1d", + ) + def test_xts_no_duplicate_keys_encryption(self, backend): + key = bytes(range(16)) * 2 + tweak = b"\x00" * 16 + cipher = base.Cipher(algorithms.AES(key), modes.XTS(tweak)) + with pytest.raises(ValueError, match="duplicated keys"): + cipher.encryptor() + @pytest.mark.supported( only_if=lambda backend: backend.cipher_supported( From acf5db529ce5ab6f0f8dc492b11afaa3c3b7adf3 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 9 Jun 2021 23:26:58 -0400 Subject: [PATCH 0307/2380] Added more testcases for invalid SCTs (#6103) --- docs/development/test-vectors.rst | 4 ++ .../hazmat/backends/openssl/x509.py | 5 +- tests/x509/test_x509_ext.py | 56 ++++++++++++++++++ .../x509/custom/invalid-sct-length.der | Bin 0 -> 958 bytes .../x509/custom/invalid-sct-version.der | Bin 0 -> 1028 bytes 5 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 vectors/cryptography_vectors/x509/custom/invalid-sct-length.der create mode 100644 vectors/cryptography_vectors/x509/custom/invalid-sct-version.der diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index edd2c609f430..3420fce8e2a8 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -420,6 +420,10 @@ Custom X.509 Vectors using ``ed448-pkcs8.pem`` as key. * ``ca/rsa_ca.pem`` - A self-signed RSA certificate with ``basicConstraints`` set to true. Its private key is ``ca/rsa_key.pem``. +* ``invalid-sct-version.der`` - A certificate with an SCT with an unknown + version. +* ``invalid-sct-length.der`` - A certificate with an SCT with an internal + length greater than the amount of data. Custom X.509 Request Vectors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index 54daddb08eea..820b5f1f49bb 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -549,10 +549,11 @@ def __init__(self, backend, sct_list, sct): self._sct_list = sct_list self._sct = sct + if backend._lib.SCT_get_version(sct) != backend._lib.SCT_VERSION_V1: + raise ValueError("Invalid SCT version") + @property def version(self) -> x509.certificate_transparency.Version: - version = self._backend._lib.SCT_get_version(self._sct) - assert version == self._backend._lib.SCT_VERSION_V1 return x509.certificate_transparency.Version.v1 @property diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index 67011d09cd10..89e4502bb381 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -5460,6 +5460,36 @@ def test_ne(self, backend): assert psct1 != psct2 assert psct1 != object() + @pytest.mark.supported( + only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), + skip_message="Requires CT support", + ) + def test_ordering(self, backend): + psct1 = ( + _load_cert( + os.path.join("x509", "cryptography-scts.pem"), + x509.load_pem_x509_certificate, + backend, + ) + .extensions.get_extension_for_class( + x509.PrecertificateSignedCertificateTimestamps + ) + .value + ) + psct2 = ( + _load_cert( + os.path.join("x509", "badssl-sct.pem"), + x509.load_pem_x509_certificate, + backend, + ) + .extensions.get_extension_for_class( + x509.PrecertificateSignedCertificateTimestamps + ) + .value + ) + with pytest.raises(TypeError): + psct1[0] < psct2[0] + @pytest.mark.supported( only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), skip_message="Requires CT support", @@ -5578,6 +5608,32 @@ def test_skips_scts_if_unsupported(self, backend): ) assert isinstance(ext.value, x509.UnrecognizedExtension) + @pytest.mark.supported( + only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), + skip_message="Requires CT support", + ) + def test_invalid_version(self, backend): + cert = _load_cert( + os.path.join("x509", "custom", "invalid-sct-version.der"), + x509.load_der_x509_certificate, + backend, + ) + with pytest.raises(ValueError): + cert.extensions + + @pytest.mark.supported( + only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), + skip_message="Requires CT support", + ) + def test_invalid_length(self, backend): + cert = _load_cert( + os.path.join("x509", "custom", "invalid-sct-length.der"), + x509.load_der_x509_certificate, + backend, + ) + with pytest.raises(ValueError): + cert.extensions + class TestInvalidExtension(object): def test_invalid_certificate_policies_data(self, backend): diff --git a/vectors/cryptography_vectors/x509/custom/invalid-sct-length.der b/vectors/cryptography_vectors/x509/custom/invalid-sct-length.der new file mode 100644 index 0000000000000000000000000000000000000000..3b3b92d4ac8eb83905c3bcb18446376399a0f5ab GIT binary patch literal 958 zcmXqLV%}xY#I$GuGZP~dlMwS|6u^^*T zFEihuiBSpJX^gB4%uS5^3_x)%rY1&4hDFXxl>UA(&G=kb^XAmm9Df9e&lo(bF)>;-f5p3HQpTC(odhq+UyO}}tx;ksAr zugQid%oA;J=RGD66vkIyFj>Gs+@EQ=MQDb{zmD}&w*Pf!V~#kq$l{&crPZ(2U&viG zDI_%LBF|+r!AgxWbf`NfCO?TecS$juTS%v+Mkdb@0m((1(iQ)zu#_H}rxLg9T>@9e^NR_G`lGvNM1AiSz1Ydm z@>@f^ee<2^!t8NJGZsF}pCEB;VUv@_iq(+|uAJxpnwNGgt-yXuPGhMv&k38m@0P2x zHk?za7dcsFdQy4Dsrxzd&Ydyh&yF)b@sd7#HS8l-@?@TA4@C~xuf4i#W4zSg8O;EE CrHP^d literal 0 HcmV?d00001 diff --git a/vectors/cryptography_vectors/x509/custom/invalid-sct-version.der b/vectors/cryptography_vectors/x509/custom/invalid-sct-version.der new file mode 100644 index 0000000000000000000000000000000000000000..96cce1d524e56224a45a885c67377ecc942c1f9e GIT binary patch literal 1028 zcmXqLVqq|7VtTQFnTe5!Nr?HfanXwBhPH1vn4Y?`>(iqr9tON@oLX%jZQpqr8M#>* z47?1v4LI4DLs{5_nL>jN#SBD194=vApVSidVg=W{*aTJJaXk=sx72@ zns%~O{PLAfzje=}|JE&A`|0as{i#>HdM0pJuoukHdot6ZYRS4+ALdS-HvPh(h3j6e zza|@=Fi*6>o%fhPP#9l*!DImkaet=e7NHp)|2o!B+5Xp^jXC1bB8zu&msY=8e<63( zq>#{{i#(Uj1UJp!^ndlEz1NQF1%LP$HgD}NPxA`yZBu;<5}BA885kEgG4g>z1c=$# zxU|_ASs1TXGO;kRG=67k{KD{wp`20ECU9EF3Cq-7s{;N+uwU7pzdxc%v*^x}!#rP} zy1IXA4j(0eOWzYL7j3f8jpJSNg)Y_L)_;uUuUx zSJAB{4nQUMR(`y2IQY+H^M}!e@eLZSr46y(SzWID*8$=17xW0v_%VTi@v1xOYzdT{e!@)VIDd(U3~Hh05>t2-vK zZ)rH*b?E33J~O#Vio9P&^_U$c?$qTl*uJ&C!yUwpTZjV{XV_CZ-VGUjvm((>|3g2@=N^HaTgmSRJ|G%6a~; zd1=Se3hcM!G?qH^oUpn3Zn-*Z!#Ra|k&{)XCzWTMx}PKO+!-VO>^S2SFX_Wq!#;8) WPv)8SP~?F9+N;Yp#!LO3(F_22BdhQL literal 0 HcmV?d00001 From b9ce2292a4480f9b9bc85680b8f557247ce47c30 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Jun 2021 08:37:51 -0400 Subject: [PATCH 0308/2380] Bump syn from 1.0.72 to 1.0.73 in /src/rust (#6105) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.72 to 1.0.73. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.72...1.0.73) --- updated-dependencies: - dependency-name: syn dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 7622e6587187..a017dae9f325 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -366,9 +366,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "syn" -version = "1.0.72" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82" +checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" dependencies = [ "proc-macro2", "quote", From ae4ed8d4375a765f69cfc8e1bfbe4021655171f4 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 10 Jun 2021 23:10:10 -0400 Subject: [PATCH 0309/2380] Move SCT encoding/decoding to Rust (#6098) --- .../hazmat/backends/openssl/backend.py | 28 ++- .../hazmat/backends/openssl/decode_asn1.py | 37 ---- .../hazmat/backends/openssl/encode_asn1.py | 13 -- .../hazmat/backends/openssl/x509.py | 61 ------ .../hazmat/bindings/_rust/ocsp.pyi | 3 + .../hazmat/bindings/_rust/x509.pyi | 10 +- .../x509/certificate_transparency.py | 4 + src/rust/src/ocsp.rs | 23 +++ src/rust/src/x509.rs | 182 +++++++++++++++++- tests/x509/test_ocsp.py | 37 ---- tests/x509/test_x509_ext.py | 65 ------- 11 files changed, 233 insertions(+), 230 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 53ba826a726a..b6481f224088 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -20,8 +20,6 @@ _CRL_ENTRY_REASON_ENUM_TO_CODE, _CRL_EXTENSION_HANDLERS, _EXTENSION_HANDLERS_BASE, - _EXTENSION_HANDLERS_SCT, - _OCSP_SINGLERESP_EXTENSION_HANDLERS_SCT, _X509ExtensionParser, ) from cryptography.hazmat.backends.openssl.dh import ( @@ -387,28 +385,19 @@ def _register_default_ciphers(self): ) def _register_x509_ext_parsers(self): - ext_handlers = _EXTENSION_HANDLERS_BASE.copy() - # All revoked extensions are valid single response extensions, see: - # https://tools.ietf.org/html/rfc6960#section-4.4.5 - singleresp_handlers = {} - - if self._lib.Cryptography_HAS_SCT: - ext_handlers.update(_EXTENSION_HANDLERS_SCT) - singleresp_handlers.update(_OCSP_SINGLERESP_EXTENSION_HANDLERS_SCT) - self._certificate_extension_parser = _X509ExtensionParser( self, ext_count=self._lib.X509_get_ext_count, get_ext=self._lib.X509_get_ext, rust_callback=rust_x509.parse_x509_extension, - handlers=ext_handlers, + handlers=_EXTENSION_HANDLERS_BASE, ) self._csr_extension_parser = _X509ExtensionParser( self, ext_count=self._lib.sk_X509_EXTENSION_num, get_ext=self._lib.sk_X509_EXTENSION_value, rust_callback=rust_x509.parse_x509_extension, - handlers=ext_handlers, + handlers=_EXTENSION_HANDLERS_BASE, ) self._revoked_cert_extension_parser = _X509ExtensionParser( self, @@ -433,8 +422,7 @@ def _register_x509_ext_parsers(self): self, ext_count=self._lib.OCSP_SINGLERESP_get_ext_count, get_ext=self._lib.OCSP_SINGLERESP_get_ext, - rust_callback=rust_x509.parse_crl_entry_extension, - handlers=singleresp_handlers, + rust_callback=rust_ocsp.parse_ocsp_singleresp_extension, ) def _register_x509_encoders(self): @@ -1170,6 +1158,16 @@ def _create_x509_extension(self, handlers, extension): self, asn1.encode_precert_poison(extension.value) ) return self._create_raw_x509_extension(extension, value) + elif isinstance( + extension.value, x509.PrecertificateSignedCertificateTimestamps + ): + value = _encode_asn1_str_gc( + self, + rust_x509.encode_precertificate_signed_certificate_timestamps( + extension.value + ), + ) + return self._create_raw_x509_extension(extension, value) else: try: encode = handlers[extension.oid] diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 3cdd5345fe1f..e0d7505f8390 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -425,32 +425,6 @@ def _decode_freshest_crl(backend, cdps): return x509.FreshestCRL(dist_points) -def _decode_scts(backend, asn1_scts): - from cryptography.hazmat.backends.openssl.x509 import ( - _SignedCertificateTimestamp, - ) - - asn1_scts = backend._ffi.cast("Cryptography_STACK_OF_SCT *", asn1_scts) - asn1_scts = backend._ffi.gc(asn1_scts, backend._lib.SCT_LIST_free) - - scts = [] - for i in range(backend._lib.sk_SCT_num(asn1_scts)): - sct = backend._lib.sk_SCT_value(asn1_scts, i) - - scts.append(_SignedCertificateTimestamp(backend, asn1_scts, sct)) - return scts - - -def _decode_precert_signed_certificate_timestamps(backend, asn1_scts): - return x509.PrecertificateSignedCertificateTimestamps( - _decode_scts(backend, asn1_scts) - ) - - -def _decode_signed_certificate_timestamps(backend, asn1_scts): - return x509.SignedCertificateTimestamps(_decode_scts(backend, asn1_scts)) - - # CRLReason ::= ENUMERATED { # unspecified (0), # keyCompromise (1), @@ -552,19 +526,8 @@ def _parse_asn1_generalized_time(backend, generalized_time): ExtensionOID.FRESHEST_CRL: _decode_freshest_crl, ExtensionOID.NAME_CONSTRAINTS: _decode_name_constraints, } -_EXTENSION_HANDLERS_SCT = { - ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: ( - _decode_precert_signed_certificate_timestamps - ) -} _CRL_EXTENSION_HANDLERS = { ExtensionOID.ISSUING_DISTRIBUTION_POINT: _decode_issuing_dist_point, ExtensionOID.FRESHEST_CRL: _decode_freshest_crl, } - -_OCSP_SINGLERESP_EXTENSION_HANDLERS_SCT = { - ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS: ( - _decode_signed_certificate_timestamps - ) -} diff --git a/src/cryptography/hazmat/backends/openssl/encode_asn1.py b/src/cryptography/hazmat/backends/openssl/encode_asn1.py index 0daae661367a..97080abea1ee 100644 --- a/src/cryptography/hazmat/backends/openssl/encode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/encode_asn1.py @@ -606,16 +606,6 @@ def _encode_general_subtree(backend, subtrees): return general_subtrees -def _encode_precert_signed_certificate_timestamps(backend, scts): - sct_stack = backend._lib.sk_SCT_new_null() - backend.openssl_assert(sct_stack != backend._ffi.NULL) - sct_stack = backend._ffi.gc(sct_stack, backend._lib.sk_SCT_free) - for sct in scts: - res = backend._lib.sk_SCT_push(sct_stack, sct._sct) - backend.openssl_assert(res >= 1) - return sct_stack - - def _encode_nonce(backend, nonce): return _encode_asn1_str_gc(backend, nonce.nonce) @@ -637,9 +627,6 @@ def _encode_nonce(backend, nonce): ExtensionOID.OCSP_NO_CHECK: _encode_ocsp_nocheck, ExtensionOID.NAME_CONSTRAINTS: _encode_name_constraints, ExtensionOID.POLICY_CONSTRAINTS: _encode_policy_constraints, - ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: ( - _encode_precert_signed_certificate_timestamps - ), } _CRL_EXTENSION_ENCODE_HANDLERS = { diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index 820b5f1f49bb..edbc7c6d5f0c 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -537,64 +537,3 @@ def get_attribute_for_oid(self, oid: x509.ObjectIdentifier) -> bytes: # that it is always a type of ASN1_STRING data = self._backend._ffi.cast("ASN1_STRING *", data) return _asn1_string_to_bytes(self._backend, data) - - -@utils.register_interface( - x509.certificate_transparency.SignedCertificateTimestamp -) -class _SignedCertificateTimestamp(object): - def __init__(self, backend, sct_list, sct): - self._backend = backend - # Keep the SCT_LIST that this SCT came from alive. - self._sct_list = sct_list - self._sct = sct - - if backend._lib.SCT_get_version(sct) != backend._lib.SCT_VERSION_V1: - raise ValueError("Invalid SCT version") - - @property - def version(self) -> x509.certificate_transparency.Version: - return x509.certificate_transparency.Version.v1 - - @property - def log_id(self) -> bytes: - out = self._backend._ffi.new("unsigned char **") - log_id_length = self._backend._lib.SCT_get0_log_id(self._sct, out) - assert log_id_length >= 0 - return self._backend._ffi.buffer(out[0], log_id_length)[:] - - @property - def timestamp(self) -> datetime.datetime: - timestamp = self._backend._lib.SCT_get_timestamp(self._sct) - milliseconds = timestamp % 1000 - return datetime.datetime.utcfromtimestamp(timestamp // 1000).replace( - microsecond=milliseconds * 1000 - ) - - @property - def entry_type(self) -> x509.certificate_transparency.LogEntryType: - entry_type = self._backend._lib.SCT_get_log_entry_type(self._sct) - # We currently only support loading SCTs from the X.509 extension, so - # we only have precerts. - assert entry_type == self._backend._lib.CT_LOG_ENTRY_TYPE_PRECERT - return x509.certificate_transparency.LogEntryType.PRE_CERTIFICATE - - @property - def _signature(self): - ptrptr = self._backend._ffi.new("unsigned char **") - res = self._backend._lib.SCT_get0_signature(self._sct, ptrptr) - self._backend.openssl_assert(res > 0) - self._backend.openssl_assert(ptrptr[0] != self._backend._ffi.NULL) - return self._backend._ffi.buffer(ptrptr[0], res)[:] - - def __hash__(self) -> int: - return hash(self._signature) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, _SignedCertificateTimestamp): - return NotImplemented - - return self._signature == other._signature - - def __ne__(self, other: object) -> bool: - return not self == other diff --git a/src/cryptography/hazmat/bindings/_rust/ocsp.pyi b/src/cryptography/hazmat/bindings/_rust/ocsp.pyi index 2d8c04fc31ea..14f5eaf88f31 100644 --- a/src/cryptography/hazmat/bindings/_rust/ocsp.pyi +++ b/src/cryptography/hazmat/bindings/_rust/ocsp.pyi @@ -5,3 +5,6 @@ def load_der_ocsp_request(data: bytes) -> OCSPRequest: ... def parse_ocsp_resp_extension( der_oid: bytes, ext_data: bytes ) -> ExtensionType: ... +def parse_ocsp_singleresp_extension( + der_oid: bytes, ext_data: bytes +) -> ExtensionType: ... diff --git a/src/cryptography/hazmat/bindings/_rust/x509.pyi b/src/cryptography/hazmat/bindings/_rust/x509.pyi index 2d41f9e91f5f..a2ed70282e17 100644 --- a/src/cryptography/hazmat/bindings/_rust/x509.pyi +++ b/src/cryptography/hazmat/bindings/_rust/x509.pyi @@ -1,7 +1,15 @@ -from cryptography.x509 import ExtensionType +from cryptography.x509 import ( + ExtensionType, + PrecertificateSignedCertificateTimestamps, +) def parse_x509_extension(der_oid: bytes, ext_data: bytes) -> ExtensionType: ... def parse_crl_entry_extension( der_oid: bytes, ext_data: bytes ) -> ExtensionType: ... def parse_crl_extension(der_oid: bytes, ext_data: bytes) -> ExtensionType: ... +def encode_precertificate_signed_certificate_timestamps( + extension: PrecertificateSignedCertificateTimestamps, +) -> bytes: ... + +class Sct: ... diff --git a/src/cryptography/x509/certificate_transparency.py b/src/cryptography/x509/certificate_transparency.py index d80f051a68ae..8c198a1c0823 100644 --- a/src/cryptography/x509/certificate_transparency.py +++ b/src/cryptography/x509/certificate_transparency.py @@ -7,6 +7,7 @@ import datetime from cryptography import utils +from cryptography.hazmat.bindings._rust import x509 as rust_x509 class LogEntryType(utils.Enum): @@ -42,3 +43,6 @@ def entry_type(self) -> LogEntryType: """ Returns whether this is an SCT for a certificate or pre-certificate. """ + + +SignedCertificateTimestamp.register(rust_x509.Sct) diff --git a/src/rust/src/ocsp.rs b/src/rust/src/ocsp.rs index 6068e72116a8..fbac6c389213 100644 --- a/src/rust/src/ocsp.rs +++ b/src/rust/src/ocsp.rs @@ -3,6 +3,7 @@ // for complete details. use crate::asn1::{big_asn1_uint_to_py, PyAsn1Error}; +use crate::x509; use pyo3::conversion::ToPyObject; use pyo3::exceptions; use std::collections::{HashMap, HashSet}; @@ -25,6 +26,7 @@ lazy_static::lazy_static! { }; static ref NONCE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.48.1.2").unwrap(); + static ref SIGNED_CERTIFICATE_TIMESTAMPS_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.4.1.11129.2.4.5").unwrap(); } #[ouroboros::self_referencing] @@ -285,11 +287,32 @@ fn parse_ocsp_resp_extension( } } +#[pyo3::prelude::pyfunction] +fn parse_ocsp_singleresp_extension( + py: pyo3::Python<'_>, + der_oid: &[u8], + ext_data: &[u8], +) -> Result { + let oid = asn1::ObjectIdentifier::from_der(der_oid).unwrap(); + + let x509_module = py.import("cryptography.x509")?; + if oid == *SIGNED_CERTIFICATE_TIMESTAMPS_OID { + let contents = asn1::parse_single::<&[u8]>(ext_data)?; + let scts = x509::parse_scts(py, contents, x509::LogEntryType::Certificate)?; + Ok(x509_module + .call1("SignedCertificateTimestamps", (scts,))? + .to_object(py)) + } else { + x509::parse_crl_entry_extension(py, der_oid, ext_data) + } +} + pub(crate) fn create_submodule(py: pyo3::Python<'_>) -> pyo3::PyResult<&pyo3::prelude::PyModule> { let submod = pyo3::prelude::PyModule::new(py, "ocsp")?; submod.add_wrapped(pyo3::wrap_pyfunction!(load_der_ocsp_request))?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_ocsp_resp_extension))?; + submod.add_wrapped(pyo3::wrap_pyfunction!(parse_ocsp_singleresp_extension))?; Ok(submod) } diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index 977f4e8edc53..902aa6969652 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -5,6 +5,10 @@ use crate::asn1::{big_asn1_uint_to_py, AttributeTypeValue, Name, PyAsn1Error}; use chrono::{Datelike, Timelike}; use pyo3::conversion::ToPyObject; +use pyo3::types::IntoPyDict; +use std::collections::hash_map::DefaultHasher; +use std::convert::TryInto; +use std::hash::{Hash, Hasher}; lazy_static::lazy_static! { static ref TLS_FEATURE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.1.24").unwrap(); @@ -27,6 +31,7 @@ lazy_static::lazy_static! { static ref DELTA_CRL_INDICATOR_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.27").unwrap(); static ref SUBJECT_ALTERNATIVE_NAME_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.17").unwrap(); static ref ISSUER_ALTERNATIVE_NAME_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.18").unwrap(); + static ref PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.4.1.11129.2.4.2").unwrap(); } struct UnvalidatedIA5String<'a>(&'a str); @@ -253,6 +258,171 @@ fn parse_access_descriptions( Ok(ads.to_object(py)) } +struct TLSReader<'a> { + data: &'a [u8], +} + +impl<'a> TLSReader<'a> { + fn new(data: &'a [u8]) -> TLSReader<'a> { + TLSReader { data } + } + + fn is_empty(&self) -> bool { + self.data.is_empty() + } + + fn read_byte(&mut self) -> Result { + Ok(self.read_exact(1)?[0]) + } + + fn read_exact(&mut self, length: usize) -> Result<&'a [u8], PyAsn1Error> { + if length > self.data.len() { + return Err(PyAsn1Error::from(pyo3::exceptions::PyValueError::new_err( + "Invalid SCT length", + ))); + } + let (result, data) = self.data.split_at(length); + self.data = data; + Ok(result) + } + + fn read_length_prefixed(&mut self) -> Result, PyAsn1Error> { + let length = u16::from_be_bytes(self.read_exact(2)?.try_into().unwrap()); + Ok(TLSReader::new(self.read_exact(length.into())?)) + } +} + +#[derive(Clone)] +pub(crate) enum LogEntryType { + Certificate, + PreCertificate, +} + +#[pyo3::prelude::pyclass] +struct Sct { + log_id: [u8; 32], + timestamp: u64, + entry_type: LogEntryType, + sct_data: Vec, +} + +#[pyo3::prelude::pymethods] +impl Sct { + #[getter] + fn version<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> { + py.import("cryptography.x509.certificate_transparency")? + .getattr("Version")? + .getattr("v1") + } + + #[getter] + fn log_id(&self) -> &[u8] { + &self.log_id + } + + #[getter] + fn timestamp<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> { + let datetime_class = py.import("datetime")?.getattr("datetime")?; + datetime_class + .call_method1("utcfromtimestamp", (self.timestamp / 1000,))? + .call_method( + "replace", + (), + Some(vec![("microsecond", self.timestamp % 1000 * 1000)].into_py_dict(py)), + ) + } + + #[getter] + fn entry_type<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> { + let et_class = py + .import("cryptography.x509.certificate_transparency")? + .getattr("LogEntryType")?; + let attr_name = match self.entry_type { + LogEntryType::Certificate => "X509_CERTIFICATE", + LogEntryType::PreCertificate => "PRE_CERTIFICATE", + }; + et_class.getattr(attr_name) + } +} + +#[pyo3::prelude::pyproto] +impl pyo3::class::basic::PyObjectProtocol for Sct { + fn __richcmp__( + &self, + other: pyo3::pycell::PyRef, + op: pyo3::class::basic::CompareOp, + ) -> pyo3::PyResult { + match op { + pyo3::class::basic::CompareOp::Eq => Ok(self.sct_data == other.sct_data), + pyo3::class::basic::CompareOp::Ne => Ok(self.sct_data != other.sct_data), + _ => Err(pyo3::exceptions::PyTypeError::new_err( + "SCTs cannot be ordered", + )), + } + } + + fn __hash__(&self) -> u64 { + let mut hasher = DefaultHasher::new(); + self.sct_data.hash(&mut hasher); + hasher.finish() + } +} + +#[pyo3::prelude::pyfunction] +fn encode_precertificate_signed_certificate_timestamps( + py: pyo3::Python<'_>, + extension: &pyo3::PyAny, +) -> pyo3::PyResult { + let mut length = 0; + for sct in extension.iter()? { + let sct = sct?.downcast::>()?; + length += sct.borrow().sct_data.len() + 2; + } + + let mut result = vec![]; + result.extend_from_slice(&(length as u16).to_be_bytes()); + for sct in extension.iter()? { + let sct = sct?.downcast::>()?; + result.extend_from_slice(&(sct.borrow().sct_data.len() as u16).to_be_bytes()); + result.extend_from_slice(&sct.borrow().sct_data); + } + Ok(pyo3::types::PyBytes::new(py, &asn1::write_single(&result.as_slice())).to_object(py)) +} + +pub(crate) fn parse_scts( + py: pyo3::Python<'_>, + data: &[u8], + entry_type: LogEntryType, +) -> Result { + let mut reader = TLSReader::new(data).read_length_prefixed()?; + + let py_scts = pyo3::types::PyList::empty(py); + while !reader.is_empty() { + let mut sct_data = reader.read_length_prefixed()?; + let raw_sct_data = sct_data.data.to_vec(); + let version = sct_data.read_byte()?; + if version != 0 { + return Err(PyAsn1Error::from(pyo3::exceptions::PyValueError::new_err( + "Invalid SCT version", + ))); + } + let log_id = sct_data.read_exact(32)?.try_into().unwrap(); + let timestamp = u64::from_be_bytes(sct_data.read_exact(8)?.try_into().unwrap()); + let _extensions = sct_data.read_length_prefixed()?; + let _sig_alg = sct_data.read_exact(2)?; + let _signature = sct_data.read_length_prefixed()?; + + let sct = Sct { + log_id, + timestamp, + entry_type: entry_type.clone(), + sct_data: raw_sct_data, + }; + py_scts.append(pyo3::PyCell::new(py, sct)?)?; + } + Ok(py_scts.to_object(py)) +} + #[pyo3::prelude::pyfunction] fn parse_x509_extension( py: pyo3::Python<'_>, @@ -364,13 +534,19 @@ fn parse_x509_extension( .to_object(py)) } else if oid == *AUTHORITY_KEY_IDENTIFIER_OID { Ok(parse_authority_key_identifier(py, ext_data)?) + } else if oid == *PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS_OID { + let contents = asn1::parse_single::<&[u8]>(ext_data)?; + let scts = parse_scts(py, contents, LogEntryType::PreCertificate)?; + Ok(x509_module + .call1("PrecertificateSignedCertificateTimestamps", (scts,))? + .to_object(py)) } else { Ok(py.None()) } } #[pyo3::prelude::pyfunction] -fn parse_crl_entry_extension( +pub(crate) fn parse_crl_entry_extension( py: pyo3::Python<'_>, der_oid: &[u8], ext_data: &[u8], @@ -468,6 +644,10 @@ pub(crate) fn create_submodule(py: pyo3::Python<'_>) -> pyo3::PyResult<&pyo3::pr submod.add_wrapped(pyo3::wrap_pyfunction!(parse_x509_extension))?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_crl_entry_extension))?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_crl_extension))?; + submod.add_wrapped(pyo3::wrap_pyfunction!( + encode_precertificate_signed_certificate_timestamps + ))?; + submod.add_class::()?; Ok(submod) } diff --git a/tests/x509/test_ocsp.py b/tests/x509/test_ocsp.py index e1ea7590a33b..0b8e49074cba 100644 --- a/tests/x509/test_ocsp.py +++ b/tests/x509/test_ocsp.py @@ -756,10 +756,6 @@ def test_repr(self): "" ) - @pytest.mark.supported( - only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), - skip_message="Requires CT support", - ) def test_eq(self, backend): sct1 = ( _load_data( @@ -783,10 +779,6 @@ def test_eq(self, backend): ) assert sct1 == sct2 - @pytest.mark.supported( - only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), - skip_message="Requires CT support", - ) def test_ne(self, backend): sct1 = ( _load_data( @@ -802,10 +794,6 @@ def test_ne(self, backend): assert sct1 != sct2 assert sct1 != object() - @pytest.mark.supported( - only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), - skip_message="Requires CT support", - ) def test_hash(self, backend): sct1 = ( _load_data( @@ -1053,10 +1041,6 @@ def test_invalid_serialize_encoding(self): with pytest.raises(ValueError): resp.public_bytes(serialization.Encoding.PEM) - @pytest.mark.supported( - only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), - skip_message="Requires CT support", - ) def test_single_extensions_sct(self, backend): resp = _load_data( os.path.join("x509", "ocsp", "resp-sct-extension.der"), @@ -1074,27 +1058,6 @@ def test_single_extensions_sct(self, backend): b"7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/cs=", ] - @pytest.mark.supported( - only_if=lambda backend: ( - not backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER - ), - skip_message="Requires OpenSSL < 1.1.0f", - ) - def test_skips_single_extensions_scts_if_unsupported(self, backend): - resp = _load_data( - os.path.join("x509", "ocsp", "resp-sct-extension.der"), - ocsp.load_der_ocsp_response, - ) - with pytest.raises(x509.ExtensionNotFound): - resp.single_extensions.get_extension_for_class( - x509.SignedCertificateTimestamps - ) - - ext = resp.single_extensions.get_extension_for_oid( - x509.ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS - ) - assert isinstance(ext.value, x509.UnrecognizedExtension) - def test_single_extensions(self, backend): resp = _load_data( os.path.join("x509", "ocsp", "resp-single-extension-reason.der"), diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index 89e4502bb381..6741def2a8c0 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -5288,10 +5288,6 @@ def test_repr(self): class TestSignedCertificateTimestamps(object): - @pytest.mark.supported( - only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), - skip_message="Requires CT support", - ) def test_eq(self, backend): sct = ( _load_cert( @@ -5317,10 +5313,6 @@ def test_eq(self, backend): ) assert sct == sct2 - @pytest.mark.supported( - only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), - skip_message="Requires CT support", - ) def test_ne(self, backend): sct = ( _load_cert( @@ -5347,10 +5339,6 @@ def test_ne(self, backend): assert sct != sct2 assert sct != object() - @pytest.mark.supported( - only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), - skip_message="Requires CT support", - ) def test_hash(self, backend): sct = ( _load_cert( @@ -5401,10 +5389,6 @@ def test_repr(self): "" ) - @pytest.mark.supported( - only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), - skip_message="Requires CT support", - ) def test_eq(self, backend): psct1 = ( _load_cert( @@ -5430,10 +5414,6 @@ def test_eq(self, backend): ) assert psct1 == psct2 - @pytest.mark.supported( - only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), - skip_message="Requires CT support", - ) def test_ne(self, backend): psct1 = ( _load_cert( @@ -5460,10 +5440,6 @@ def test_ne(self, backend): assert psct1 != psct2 assert psct1 != object() - @pytest.mark.supported( - only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), - skip_message="Requires CT support", - ) def test_ordering(self, backend): psct1 = ( _load_cert( @@ -5490,10 +5466,6 @@ def test_ordering(self, backend): with pytest.raises(TypeError): psct1[0] < psct2[0] - @pytest.mark.supported( - only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), - skip_message="Requires CT support", - ) def test_hash(self, backend): psct1 = ( _load_cert( @@ -5531,10 +5503,6 @@ def test_hash(self, backend): assert hash(psct1) == hash(psct2) assert hash(psct1) != hash(psct3) - @pytest.mark.supported( - only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), - skip_message="Requires CT support", - ) def test_simple(self, backend): cert = _load_cert( os.path.join("x509", "badssl-sct.pem"), @@ -5560,10 +5528,6 @@ def test_simple(self, backend): == x509.certificate_transparency.LogEntryType.PRE_CERTIFICATE ) - @pytest.mark.supported( - only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), - skip_message="Requires CT support", - ) def test_generate(self, backend): cert = _load_cert( os.path.join("x509", "badssl-sct.pem"), @@ -5587,31 +5551,6 @@ def test_generate(self, backend): ).value assert list(ext) == [sct] - @pytest.mark.supported( - only_if=lambda backend: backend._lib.CRYPTOGRAPHY_IS_LIBRESSL, - skip_message="Requires LibreSSL", - ) - def test_skips_scts_if_unsupported(self, backend): - cert = _load_cert( - os.path.join("x509", "badssl-sct.pem"), - x509.load_pem_x509_certificate, - backend, - ) - assert len(cert.extensions) == 10 - with pytest.raises(x509.ExtensionNotFound): - cert.extensions.get_extension_for_class( - x509.PrecertificateSignedCertificateTimestamps - ) - - ext = cert.extensions.get_extension_for_oid( - x509.ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS - ) - assert isinstance(ext.value, x509.UnrecognizedExtension) - - @pytest.mark.supported( - only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), - skip_message="Requires CT support", - ) def test_invalid_version(self, backend): cert = _load_cert( os.path.join("x509", "custom", "invalid-sct-version.der"), @@ -5621,10 +5560,6 @@ def test_invalid_version(self, backend): with pytest.raises(ValueError): cert.extensions - @pytest.mark.supported( - only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), - skip_message="Requires CT support", - ) def test_invalid_length(self, backend): cert = _load_cert( os.path.join("x509", "custom", "invalid-sct-length.der"), From d036964b3c45c80fc39e1d56444ca734496cc0a8 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 11 Jun 2021 08:15:51 -0500 Subject: [PATCH 0310/2380] oxidize issuing distribution point (#6108) * oxidize issuing distribution point * cleanup * clippy --- .../hazmat/backends/openssl/decode_asn1.py | 30 ----- src/cryptography/x509/extensions.py | 24 ++++ src/rust/src/x509.rs | 104 ++++++++++++++++-- 3 files changed, 120 insertions(+), 38 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index e0d7505f8390..244c517ce42c 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -291,35 +291,6 @@ def _decode_general_subtrees(backend, stack_subtrees): return subtrees -def _decode_issuing_dist_point(backend, idp): - idp = backend._ffi.cast("ISSUING_DIST_POINT *", idp) - idp = backend._ffi.gc(idp, backend._lib.ISSUING_DIST_POINT_free) - if idp.distpoint != backend._ffi.NULL: - full_name, relative_name = _decode_distpoint(backend, idp.distpoint) - else: - full_name = None - relative_name = None - - only_user = idp.onlyuser == 255 - only_ca = idp.onlyCA == 255 - indirect_crl = idp.indirectCRL == 255 - only_attr = idp.onlyattr == 255 - if idp.onlysomereasons != backend._ffi.NULL: - only_some_reasons = _decode_reasons(backend, idp.onlysomereasons) - else: - only_some_reasons = None - - return x509.IssuingDistributionPoint( - full_name, - relative_name, - only_user, - only_ca, - only_some_reasons, - indirect_crl, - only_attr, - ) - - _DISTPOINT_TYPE_FULLNAME = 0 _DISTPOINT_TYPE_RELATIVENAME = 1 @@ -528,6 +499,5 @@ def _parse_asn1_generalized_time(backend, generalized_time): } _CRL_EXTENSION_HANDLERS = { - ExtensionOID.ISSUING_DISTRIBUTION_POINT: _decode_issuing_dist_point, ExtensionOID.FRESHEST_CRL: _decode_freshest_crl, } diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index 58e7ea7f5a5d..bbcb128723cd 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -684,6 +684,30 @@ class ReasonFlags(utils.Enum): remove_from_crl = "removeFromCRL" +# These are distribution point bit string mappings. Not to be confused with +# CRLReason reason flags bit string mappings. +# ReasonFlags ::= BIT STRING { +# unused (0), +# keyCompromise (1), +# cACompromise (2), +# affiliationChanged (3), +# superseded (4), +# cessationOfOperation (5), +# certificateHold (6), +# privilegeWithdrawn (7), +# aACompromise (8) } +_REASON_BIT_MAPPING = { + 1: ReasonFlags.key_compromise, + 2: ReasonFlags.ca_compromise, + 3: ReasonFlags.affiliation_changed, + 4: ReasonFlags.superseded, + 5: ReasonFlags.cessation_of_operation, + 6: ReasonFlags.certificate_hold, + 7: ReasonFlags.privilege_withdrawn, + 8: ReasonFlags.aa_compromise, +} + + class PolicyConstraints(ExtensionType): oid = ExtensionOID.POLICY_CONSTRAINTS diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index 902aa6969652..a0d1b4ab0d5d 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -25,6 +25,7 @@ lazy_static::lazy_static! { static ref SUBJECT_KEY_IDENTIFIER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.14").unwrap(); static ref INHIBIT_ANY_POLICY_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.54").unwrap(); static ref CRL_REASON_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.21").unwrap(); + static ref ISSUING_DISTRIBUTION_POINT_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.28").unwrap(); static ref CERTIFICATE_ISSUER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.29").unwrap(); static ref CRL_NUMBER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.20").unwrap(); static ref INVALIDITY_DATE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.24").unwrap(); @@ -45,6 +46,40 @@ impl<'a> asn1::SimpleAsn1Readable<'a> for UnvalidatedIA5String<'a> { } } +#[derive(asn1::Asn1Read)] +struct IssuingDistributionPoint<'a> { + #[explicit(0)] + distribution_point: Option>, + + #[implicit(1)] + #[default(false)] + only_contains_user_certs: bool, + + #[implicit(2)] + #[default(false)] + only_contains_ca_certs: bool, + + #[implicit(3)] + only_some_reasons: Option>, + + #[implicit(4)] + #[default(false)] + indirect_crl: bool, + + #[implicit(5)] + #[default(false)] + only_contains_attribute_certs: bool, +} + +#[derive(asn1::Asn1Read)] +enum DistributionPointName<'a> { + #[implicit(0)] + FullName(asn1::SequenceOf<'a, GeneralName<'a>>), + + #[implicit(1)] + NameRelativeToCRLIssuer(asn1::SetOf<'a, AttributeTypeValue<'a>>), +} + #[derive(asn1::Asn1Read)] struct AuthorityKeyIdentifier<'a> { #[implicit(0)] @@ -55,6 +90,16 @@ struct AuthorityKeyIdentifier<'a> { authority_cert_serial_number: Option>, } +fn parse_distribution_point( + py: pyo3::Python<'_>, + dp: DistributionPointName<'_>, +) -> Result<(pyo3::PyObject, pyo3::PyObject), PyAsn1Error> { + Ok(match dp { + DistributionPointName::FullName(data) => (parse_general_names(py, data)?, py.None()), + DistributionPointName::NameRelativeToCRLIssuer(data) => (py.None(), parse_rdn(py, data)?), + }) +} + #[derive(asn1::Asn1Read)] enum GeneralName<'a> { #[implicit(0)] @@ -150,18 +195,26 @@ fn parse_name_attribute( .to_object(py)) } +fn parse_rdn<'a>( + py: pyo3::Python<'_>, + rdn: asn1::SetOf<'a, AttributeTypeValue<'a>>, +) -> Result { + let x509_module = py.import("cryptography.x509")?; + let py_attrs = pyo3::types::PySet::empty(py)?; + for attribute in rdn { + let na = parse_name_attribute(py, attribute)?; + py_attrs.add(na)?; + } + Ok(x509_module + .call_method1("RelativeDistinguishedName", (py_attrs,))? + .to_object(py)) +} + fn parse_name(py: pyo3::Python<'_>, name: Name<'_>) -> Result { let x509_module = py.import("cryptography.x509")?; let py_rdns = pyo3::types::PyList::empty(py); for rdn in name { - let py_attrs = pyo3::types::PySet::empty(py)?; - for attribute in rdn { - let na = parse_name_attribute(py, attribute)?; - py_attrs.add(na)?; - } - let py_rdn = x509_module - .call_method1("RelativeDistinguishedName", (py_attrs,))? - .to_object(py); + let py_rdn = parse_rdn(py, rdn)?; py_rdns.append(py_rdn)?; } let py_name = x509_module.call_method1("Name", (py_rdns,))?.to_object(py); @@ -633,6 +686,41 @@ fn parse_crl_extension( .to_object(py)) } else if oid == *AUTHORITY_KEY_IDENTIFIER_OID { Ok(parse_authority_key_identifier(py, ext_data)?) + } else if oid == *ISSUING_DISTRIBUTION_POINT_OID { + let reason_bit_mapping = py + .import("cryptography.x509.extensions")? + .getattr("_REASON_BIT_MAPPING")?; + let idp = asn1::parse_single::>(ext_data)?; + let (full_name, relative_name) = match idp.distribution_point { + Some(data) => parse_distribution_point(py, data)?, + None => (py.None(), py.None()), + }; + let reasons = match idp.only_some_reasons { + Some(bs) => { + let mut vec = Vec::new(); + for i in 1..=8 { + if bs.has_bit_set(i) { + vec.push(reason_bit_mapping.get_item(i)?); + } + } + pyo3::types::PyFrozenSet::new(py, &vec)?.to_object(py) + } + None => py.None(), + }; + Ok(x509_module + .call1( + "IssuingDistributionPoint", + ( + full_name, + relative_name, + idp.only_contains_user_certs, + idp.only_contains_ca_certs, + reasons, + idp.indirect_crl, + idp.only_contains_attribute_certs, + ), + )? + .to_object(py)) } else { Ok(py.None()) } From 6f0260b766458f5c5c49af784413795de14be94a Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 11 Jun 2021 16:12:29 -0500 Subject: [PATCH 0311/2380] fix certbot downstream (#6110) --- .github/downstream.d/certbot.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/downstream.d/certbot.sh b/.github/downstream.d/certbot.sh index e2890a3a100c..2479d0c25b86 100755 --- a/.github/downstream.d/certbot.sh +++ b/.github/downstream.d/certbot.sh @@ -5,8 +5,8 @@ case "${1}" in git clone --depth=1 https://github.com/certbot/certbot cd certbot git rev-parse HEAD - tools/pip_install_editable.py ./acme[dev] - tools/pip_install_editable.py ./certbot[dev] + tools/pip_install_editable.py ./acme[test] + tools/pip_install_editable.py ./certbot[test] ;; run) cd certbot From 11d9622995a4ff70ac0d1feb1bf2ce1f2df389ea Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 12 Jun 2021 08:41:34 -0500 Subject: [PATCH 0312/2380] add unrecognized extension CRL vector (#6111) * add unrecognized extension CRL vector * sigh * add test * always a linter --- docs/development/test-vectors.rst | 3 +++ tests/x509/test_x509.py | 13 +++++++++++++ .../x509/custom/crl_unrecognized_extension.der | Bin 0 -> 381 bytes 3 files changed, 16 insertions(+) create mode 100644 vectors/cryptography_vectors/x509/custom/crl_unrecognized_extension.der diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index 3420fce8e2a8..e41cdf1712d7 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -517,6 +517,9 @@ Custom X.509 Certificate Revocation List Vectors * ``crl_idp_relativename_only.pem`` - Contains a CRL with an ``IssuingDistributionPoints`` extension with only a ``relativename`` for the distribution point. +* ``crl_unrecognized_extension.der`` - Contains a CRL containing an + unsupported extension type. The OID was encoded as "1.2.3.4.5" with an + ``extnValue`` of ``abcdef``. X.509 OCSP Test Vectors ~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 9e0a6fbaaa6e..306fbe246219 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -173,6 +173,19 @@ def test_update_dates(self, backend): assert crl.next_update.isoformat() == "2016-01-01T00:00:00" assert crl.last_update.isoformat() == "2015-01-01T00:00:00" + def test_unrecognized_extension(self, backend): + crl = _load_cert( + os.path.join("x509", "custom", "crl_unrecognized_extension.der"), + x509.load_der_x509_crl, + backend, + ) + unrecognized = x509.UnrecognizedExtension( + x509.ObjectIdentifier("1.2.3.4.5"), + b"abcdef", + ) + ext = crl.extensions.get_extension_for_oid(unrecognized.oid) + assert ext.value == unrecognized + def test_revoked_cert_retrieval(self, backend): crl = _load_cert( os.path.join("x509", "custom", "crl_all_reasons.pem"), diff --git a/vectors/cryptography_vectors/x509/custom/crl_unrecognized_extension.der b/vectors/cryptography_vectors/x509/custom/crl_unrecognized_extension.der new file mode 100644 index 0000000000000000000000000000000000000000..a29fe2025c3d4df53c569adfa5f62759a59f1442 GIT binary patch literal 381 zcmXqLVyrYsW@2PC;AP{~YV&CO&dbQi&B|aPYbb3X$;KSY!ptL-TvS<5lAm6bSddYv zmzl5N>?qD_U}RuuU}y*;4Wh((jSY~v3xo^=4EWesw3t~~S=bVjl2cOC(9CCUVq|2f zwy$~DYZuRS;lR!<%)4VN&5avm*(UVADJZ^_^!#9COX<{D9zKyT1+FV~*KN`N5MjFZ zhphi6@s~ZO1^3r)a+&!1t%3FX2X7K?mARW#=bRDfxy61jSaMnV{jZXnyeB_1^yhG^ zK7U6|$9gA=-?40tzRxax?cS%3Rka77;l5n6zoP1&<%;ro&Z>uAU2Ix#^nJX$n46*D z+A|+tN3e)o-QnL~jM(yxLvYZN$E?bUmx@I&ZN$r|%rJD$&ow-#CA z6)|Dk Date: Sat, 12 Jun 2021 08:42:03 -0500 Subject: [PATCH 0313/2380] add nameconstraints vector with invalid length for IPv6 + netmask (#6112) --- docs/development/test-vectors.rst | 4 ++++ tests/x509/test_x509_ext.py | 12 ++++++++++++ .../x509/custom/nc_ip_invalid_length.pem | 19 +++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 vectors/cryptography_vectors/x509/custom/nc_ip_invalid_length.pem diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index e41cdf1712d7..6fae15ce2d9f 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -377,6 +377,10 @@ Custom X.509 Vectors * ``nc_single_ip_netmask.pem`` - An RSA 2048 bit self-signed certificate containing a name constraints extension with a permitted element that has two IPs with ``/32`` and ``/128`` network masks. +* ``nc_ip_invalid_length.pem`` - An RSA 2048 bit self-signed certificate + containing a name constraints extension with a permitted element that has an + invalid length (33 bytes instead of 32) for an ``IPv6`` address with + network mask. The signature on this certificate is invalid. * ``cp_user_notice_with_notice_reference.pem`` - An RSA 2048 bit self-signed certificate containing a certificate policies extension with a notice reference in the user notice. diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index 6741def2a8c0..a3db196efe28 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -3568,6 +3568,18 @@ def test_single_ip_netmask(self, backend): excluded_subtrees=None, ) + def test_ip_invalid_length(self, backend): + cert = _load_cert( + os.path.join("x509", "custom", "nc_ip_invalid_length.pem"), + x509.load_pem_x509_certificate, + backend, + ) + # NOTE: This will change to ValueError upon oxidization. + with pytest.raises(AssertionError): + cert.extensions.get_extension_for_oid( + ExtensionOID.NAME_CONSTRAINTS + ) + def test_invalid_netmask(self, backend): cert = _load_cert( os.path.join("x509", "custom", "nc_invalid_ip_netmask.pem"), diff --git a/vectors/cryptography_vectors/x509/custom/nc_ip_invalid_length.pem b/vectors/cryptography_vectors/x509/custom/nc_ip_invalid_length.pem new file mode 100644 index 000000000000..e4df5184d19f --- /dev/null +++ b/vectors/cryptography_vectors/x509/custom/nc_ip_invalid_length.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIC/jCCAeagAwIBAgITBnA4pkis5m3OGusBaihd9qH0hzANBgkqhkiG9w0BAQsF +ADAXMRUwEwYDVQQDDAxjcnlwdG9ncmFwaHkwHhcNMTUwNzAxMjAxNDAwWhcNMTYw +NjMwMjAxNDAwWjAXMRUwEwYDVQQDDAxjcnlwdG9ncmFwaHkwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCYyaGtu90vcm+jN+SoQHXxWMQyplY1neL9KjfE ++TsKKcy8TKJEqlT8qZr6bIL3KVbTIiYO8bCW9fHSMgHWrmtr37LlFoQ3emcLfDbM +kybmOolAxA78im0L2BIW1wT2iSHh1p/ZO5QLdt+e8zP5AkZAnXCZk912RcJYyGUW +7JQzzRfEANSLE9Gmh78NsxWNI1Ipc3dhyuk3+YHwePGCzLCeXCiF4FHGNMg8Drtr +rENNHZjHJCbMLfK9irHV5Xh1FHTK8xlqEq+YecpqboUyqgWVOOvpxUxiKagfp//Z ++iFDC1+GgpuupzFUiHPSVCZGMnE3bHvIBOkoHkNu7kNK7VX3AgMBAAGjQzBBMD8G +A1UdHgEB/wQ1MDOgMTAjhyEA/wAAAAAAAAAAAAAAAAAA//////////////////// +//8wCocIwKgAAf////8wDQYJKoZIhvcNAQELBQADggEBAF0g5qJ5waYr7FvzShPO +XNYaOOPSvfPtXBVA+dVXiuNqD1HdBkUAlNxE2CeWMiuzjKEKnuC07TQ8emQhfus/ +67WXLX3acEZqodnmxp96g7NRQHJJMMEgkbZCU3YM55rTuvNC7ORr3jRa4GCZGHxY +4zlqcwsqbHv9497lYEmpJowUUuATrMl+KO7azfpNTJkDqzKVhLS5Zq2SaTOurID9 +I1qSPeZeKWiDKZBWq8AgkHyQjQaZe1KJfgQ+Lyb3/ye3+2cMUDBFggT52JNxCjJy +mmgrJqkTFdVu0s8S9O3RzM1p7AvyOaCTY+B3bYRnCCX9SbrfQPShVaHTiQMSjs4s +9mk= +-----END CERTIFICATE----- From 7a06e8a47c1d45057a43b190fdcb27e7477afb31 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 12 Jun 2021 10:16:09 -0500 Subject: [PATCH 0314/2380] oxidize CRLDP and FreshestCRL (#6109) * oxidize CRLDP * oxidize freshestcrl * coverage fixes * remove more functions --- .../hazmat/backends/openssl/backend.py | 2 - .../hazmat/backends/openssl/decode_asn1.py | 118 ------------------ src/rust/src/x509.rs | 103 ++++++++++++--- 3 files changed, 86 insertions(+), 137 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index b6481f224088..bfc9dd07a7a3 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -18,7 +18,6 @@ from cryptography.hazmat.backends.openssl.cmac import _CMACContext from cryptography.hazmat.backends.openssl.decode_asn1 import ( _CRL_ENTRY_REASON_ENUM_TO_CODE, - _CRL_EXTENSION_HANDLERS, _EXTENSION_HANDLERS_BASE, _X509ExtensionParser, ) @@ -410,7 +409,6 @@ def _register_x509_ext_parsers(self): ext_count=self._lib.X509_CRL_get_ext_count, get_ext=self._lib.X509_CRL_get_ext, rust_callback=rust_x509.parse_crl_extension, - handlers=_CRL_EXTENSION_HANDLERS, ) self._ocsp_basicresp_ext_parser = _X509ExtensionParser( self, diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 244c517ce42c..0e1f19fc6f3c 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -69,17 +69,6 @@ def _decode_x509_name(backend, x509_name): return x509.Name(x509.RelativeDistinguishedName(rdn) for rdn in attributes) -def _decode_general_names(backend, gns): - num = backend._lib.sk_GENERAL_NAME_num(gns) - names = [] - for i in range(num): - gn = backend._lib.sk_GENERAL_NAME_value(gns, i) - backend.openssl_assert(gn != backend._ffi.NULL) - names.append(_decode_general_name(backend, gn)) - - return names - - # This is now a hacked up decoder where we progressively remove chunks as # we port more and more to rust. SAN exercised every branch in this, but # other extensions (which are still in Python/OpenSSL) don't so we'll remove @@ -295,107 +284,6 @@ def _decode_general_subtrees(backend, stack_subtrees): _DISTPOINT_TYPE_RELATIVENAME = 1 -def _decode_dist_points(backend, cdps): - cdps = backend._ffi.cast("Cryptography_STACK_OF_DIST_POINT *", cdps) - cdps = backend._ffi.gc(cdps, backend._lib.CRL_DIST_POINTS_free) - - num = backend._lib.sk_DIST_POINT_num(cdps) - dist_points = [] - for i in range(num): - full_name = None - relative_name = None - crl_issuer = None - reasons = None - cdp = backend._lib.sk_DIST_POINT_value(cdps, i) - if cdp.reasons != backend._ffi.NULL: - reasons = _decode_reasons(backend, cdp.reasons) - - if cdp.CRLissuer != backend._ffi.NULL: - crl_issuer = _decode_general_names(backend, cdp.CRLissuer) - - # Certificates may have a crl_issuer/reasons and no distribution - # point so make sure it's not null. - if cdp.distpoint != backend._ffi.NULL: - full_name, relative_name = _decode_distpoint( - backend, cdp.distpoint - ) - - dist_points.append( - x509.DistributionPoint( - full_name, relative_name, reasons, crl_issuer - ) - ) - - return dist_points - - -# ReasonFlags ::= BIT STRING { -# unused (0), -# keyCompromise (1), -# cACompromise (2), -# affiliationChanged (3), -# superseded (4), -# cessationOfOperation (5), -# certificateHold (6), -# privilegeWithdrawn (7), -# aACompromise (8) } -_REASON_BIT_MAPPING = { - 1: x509.ReasonFlags.key_compromise, - 2: x509.ReasonFlags.ca_compromise, - 3: x509.ReasonFlags.affiliation_changed, - 4: x509.ReasonFlags.superseded, - 5: x509.ReasonFlags.cessation_of_operation, - 6: x509.ReasonFlags.certificate_hold, - 7: x509.ReasonFlags.privilege_withdrawn, - 8: x509.ReasonFlags.aa_compromise, -} - - -def _decode_reasons(backend, reasons): - # We will check each bit from RFC 5280 - enum_reasons = [] - for bit_position, reason in _REASON_BIT_MAPPING.items(): - if backend._lib.ASN1_BIT_STRING_get_bit(reasons, bit_position): - enum_reasons.append(reason) - - return frozenset(enum_reasons) - - -def _decode_distpoint(backend, distpoint): - if distpoint.type == _DISTPOINT_TYPE_FULLNAME: - full_name = _decode_general_names(backend, distpoint.name.fullname) - return full_name, None - - # OpenSSL code doesn't test for a specific type for - # relativename, everything that isn't fullname is considered - # relativename. Per RFC 5280: - # - # DistributionPointName ::= CHOICE { - # fullName [0] GeneralNames, - # nameRelativeToCRLIssuer [1] RelativeDistinguishedName } - rns = distpoint.name.relativename - rnum = backend._lib.sk_X509_NAME_ENTRY_num(rns) - attributes = set() - for i in range(rnum): - rn = backend._lib.sk_X509_NAME_ENTRY_value(rns, i) - backend.openssl_assert(rn != backend._ffi.NULL) - attributes.add(_decode_x509_name_entry(backend, rn)) - - relative_name = x509.RelativeDistinguishedName(attributes) - - return None, relative_name - - -def _decode_crl_distribution_points(backend, cdps): - dist_points = _decode_dist_points(backend, cdps) - return x509.CRLDistributionPoints(dist_points) - - -def _decode_freshest_crl(backend, cdps): - dist_points = _decode_dist_points(backend, cdps) - return x509.FreshestCRL(dist_points) - - # CRLReason ::= ENUMERATED { # unspecified (0), # keyCompromise (1), @@ -493,11 +381,5 @@ def _parse_asn1_generalized_time(backend, generalized_time): _EXTENSION_HANDLERS_BASE = { ExtensionOID.CERTIFICATE_POLICIES: _decode_certificate_policies, - ExtensionOID.CRL_DISTRIBUTION_POINTS: _decode_crl_distribution_points, - ExtensionOID.FRESHEST_CRL: _decode_freshest_crl, ExtensionOID.NAME_CONSTRAINTS: _decode_name_constraints, } - -_CRL_EXTENSION_HANDLERS = { - ExtensionOID.FRESHEST_CRL: _decode_freshest_crl, -} diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index a0d1b4ab0d5d..e38b9671b091 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -27,6 +27,8 @@ lazy_static::lazy_static! { static ref CRL_REASON_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.21").unwrap(); static ref ISSUING_DISTRIBUTION_POINT_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.28").unwrap(); static ref CERTIFICATE_ISSUER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.29").unwrap(); + static ref CRL_DISTRIBUTION_POINTS_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.31").unwrap(); + static ref FRESHEST_CRL_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.46").unwrap(); static ref CRL_NUMBER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.20").unwrap(); static ref INVALIDITY_DATE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.24").unwrap(); static ref DELTA_CRL_INDICATOR_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.27").unwrap(); @@ -71,6 +73,18 @@ struct IssuingDistributionPoint<'a> { only_contains_attribute_certs: bool, } +#[derive(asn1::Asn1Read)] +struct DistributionPoint<'a> { + #[explicit(0)] + distribution_point: Option>, + + #[implicit(1)] + reasons: Option>, + + #[implicit(2)] + crl_issuer: Option>>, +} + #[derive(asn1::Asn1Read)] enum DistributionPointName<'a> { #[implicit(0)] @@ -90,7 +104,7 @@ struct AuthorityKeyIdentifier<'a> { authority_cert_serial_number: Option>, } -fn parse_distribution_point( +fn parse_distribution_point_name( py: pyo3::Python<'_>, dp: DistributionPointName<'_>, ) -> Result<(pyo3::PyObject, pyo3::PyObject), PyAsn1Error> { @@ -100,6 +114,62 @@ fn parse_distribution_point( }) } +fn parse_distribution_point( + py: pyo3::Python<'_>, + dp: DistributionPoint<'_>, +) -> Result { + let (full_name, relative_name) = match dp.distribution_point { + Some(data) => parse_distribution_point_name(py, data)?, + None => (py.None(), py.None()), + }; + let reasons = parse_distribution_point_reasons(py, dp.reasons)?; + let crl_issuer = match dp.crl_issuer { + Some(aci) => parse_general_names(py, aci)?, + None => py.None(), + }; + let x509_module = py.import("cryptography.x509")?; + Ok(x509_module + .call1( + "DistributionPoint", + (full_name, relative_name, reasons, crl_issuer), + )? + .to_object(py)) +} + +fn parse_distribution_points( + py: pyo3::Python<'_>, + data: &[u8], +) -> Result { + let dps = asn1::parse_single::>>(data)?; + let py_dps = pyo3::types::PyList::empty(py); + for dp in dps { + let py_dp = parse_distribution_point(py, dp)?; + py_dps.append(py_dp)?; + } + Ok(py_dps.to_object(py)) +} + +fn parse_distribution_point_reasons( + py: pyo3::Python<'_>, + reasons: Option>, +) -> Result { + let reason_bit_mapping = py + .import("cryptography.x509.extensions")? + .getattr("_REASON_BIT_MAPPING")?; + Ok(match reasons { + Some(bs) => { + let mut vec = Vec::new(); + for i in 1..=8 { + if bs.has_bit_set(i) { + vec.push(reason_bit_mapping.get_item(i)?); + } + } + pyo3::types::PyFrozenSet::new(py, &vec)?.to_object(py) + } + None => py.None(), + }) +} + #[derive(asn1::Asn1Read)] enum GeneralName<'a> { #[implicit(0)] @@ -587,6 +657,15 @@ fn parse_x509_extension( .to_object(py)) } else if oid == *AUTHORITY_KEY_IDENTIFIER_OID { Ok(parse_authority_key_identifier(py, ext_data)?) + } else if oid == *CRL_DISTRIBUTION_POINTS_OID { + let dp = parse_distribution_points(py, ext_data)?; + Ok(x509_module + .call1("CRLDistributionPoints", (dp,))? + .to_object(py)) + } else if oid == *FRESHEST_CRL_OID { + Ok(x509_module + .call1("FreshestCRL", (parse_distribution_points(py, ext_data)?,))? + .to_object(py)) } else if oid == *PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS_OID { let contents = asn1::parse_single::<&[u8]>(ext_data)?; let scts = parse_scts(py, contents, LogEntryType::PreCertificate)?; @@ -687,26 +766,12 @@ fn parse_crl_extension( } else if oid == *AUTHORITY_KEY_IDENTIFIER_OID { Ok(parse_authority_key_identifier(py, ext_data)?) } else if oid == *ISSUING_DISTRIBUTION_POINT_OID { - let reason_bit_mapping = py - .import("cryptography.x509.extensions")? - .getattr("_REASON_BIT_MAPPING")?; let idp = asn1::parse_single::>(ext_data)?; let (full_name, relative_name) = match idp.distribution_point { - Some(data) => parse_distribution_point(py, data)?, + Some(data) => parse_distribution_point_name(py, data)?, None => (py.None(), py.None()), }; - let reasons = match idp.only_some_reasons { - Some(bs) => { - let mut vec = Vec::new(); - for i in 1..=8 { - if bs.has_bit_set(i) { - vec.push(reason_bit_mapping.get_item(i)?); - } - } - pyo3::types::PyFrozenSet::new(py, &vec)?.to_object(py) - } - None => py.None(), - }; + let reasons = parse_distribution_point_reasons(py, idp.only_some_reasons)?; Ok(x509_module .call1( "IssuingDistributionPoint", @@ -721,6 +786,10 @@ fn parse_crl_extension( ), )? .to_object(py)) + } else if oid == *FRESHEST_CRL_OID { + Ok(x509_module + .call1("FreshestCRL", (parse_distribution_points(py, ext_data)?,))? + .to_object(py)) } else { Ok(py.None()) } From f3612c8585cf6320b325e58fde4ff7f14d4dcc80 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 12 Jun 2021 15:29:22 -0500 Subject: [PATCH 0315/2380] name constraint vector with invalid IPv4 netmask (#6114) --- docs/development/test-vectors.rst | 4 ++++ tests/x509/test_x509_ext.py | 13 ++++++++++++- .../x509/custom/nc_invalid_ip4_netmask.der | Bin 0 -> 733 bytes 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 vectors/cryptography_vectors/x509/custom/nc_invalid_ip4_netmask.der diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index 6fae15ce2d9f..0aed4313b0e9 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -374,6 +374,10 @@ Custom X.509 Vectors * ``nc_invalid_ip_netmask.pem`` - An RSA 2048 bit self-signed certificate containing a name constraints extension with a permitted element that has an ``IPv6`` IP and an invalid network mask. +* ``nc_invalid_ip4_netmask.der`` - An RSA 2048 bit self-signed certificate + containing a name constraints extension with a permitted element that has an + ``IPv4`` IP and an invalid network mask. The signature on this certificate + is invalid. * ``nc_single_ip_netmask.pem`` - An RSA 2048 bit self-signed certificate containing a name constraints extension with a permitted element that has two IPs with ``/32`` and ``/128`` network masks. diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index a3db196efe28..166ab256b896 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -3580,7 +3580,7 @@ def test_ip_invalid_length(self, backend): ExtensionOID.NAME_CONSTRAINTS ) - def test_invalid_netmask(self, backend): + def test_invalid_ipv6_netmask(self, backend): cert = _load_cert( os.path.join("x509", "custom", "nc_invalid_ip_netmask.pem"), x509.load_pem_x509_certificate, @@ -3591,6 +3591,17 @@ def test_invalid_netmask(self, backend): ExtensionOID.NAME_CONSTRAINTS ) + def test_invalid_ipv4_netmask(self, backend): + cert = _load_cert( + os.path.join("x509", "custom", "nc_invalid_ip4_netmask.der"), + x509.load_der_x509_certificate, + backend, + ) + with pytest.raises(ValueError): + cert.extensions.get_extension_for_oid( + ExtensionOID.NAME_CONSTRAINTS + ) + def test_certbuilder(self, backend): permitted = [ ".example.org", diff --git a/vectors/cryptography_vectors/x509/custom/nc_invalid_ip4_netmask.der b/vectors/cryptography_vectors/x509/custom/nc_invalid_ip4_netmask.der new file mode 100644 index 0000000000000000000000000000000000000000..ea3e3515b5c437065a947191d9832d8741770c83 GIT binary patch literal 733 zcmXqLV!CP2#CUK4GZP~dlQ3I>#WIgI&vMU6y=KhPi2b(kOS=It8>d#AN85K^Mn-N{ z1_N-99-ic)%7T*o^rFOqj7kGJab81H19JmIBLhPd1A{0a*UZ4o*Z|7K zt+9zw3E2`xRtDxKMt%mMv$&X=7#SI6oLsne_g(#>{Ke)^RydS?j5uPnEX;K7qrY0_ zM}As!X`b2Rv&dyt$e)$7e&sZM*9^O?q{jDg!?dp-FBvgjTbG@Ef74U37W1lf?i#Z* zlhvMCbvhj3`_q-neM3m>I?K0C#fR7C-?W~>U3P!oXXBqtZVqz`W=_6a=6WdNM5@@E zDaL2Tk1$;67QVQweLwGJ(O%^s&EoRJQ!mYbHh!r1*mP#Yycmtv2Z6^-PT276&R*l} zD?8)3irN|7PkXyIUVU0oDpGRlvt*Xg`Wcm{vhrGuRVIIPm<;e`Q`s_{!(=2 zj&Ez4y>7W-NJsId5H&ZWLi3#J6D%(^nRC#cj_M7O>Uc%>Mu1Q%uzO?uA z+Za)YpI5`X9%u0f-eq%Tm~zMEhWa!k?ae(4x#m6C^47$rDn+sGwf*a@({*ca6}V+B zy!q_d{Ho^7feuBU1_u=;ZgUDQ<9R;o@~+QLZ=Ph|Gl_bTFjJx?;<05`F}GGu_20+$ zo+fy%RO=B5dLX>!WSz#lTW5dy`pjfrZ8WuI%g(g5lQNCht!enH95u=IS)67@v*v`b z)dv(N)J*7Qn^_&yS;u0hulD`F`u5-HJOKu-O)NieOfKXyDw>s{t+rBF^lILv^Fm+V rUOaO)^9}bW%LS8@AC%{|q;shL_1tye;mg9%g_k>-h5F9ve9Hs?4VyUW literal 0 HcmV?d00001 From a0075afb7b65331b7c1d2a9b667ece933321edd8 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 12 Jun 2021 16:42:02 -0500 Subject: [PATCH 0316/2380] oxidize nameconstraints (#6113) * oxidize nameconstraints * cargo fmt * fix logic * make clippy happy * make it work with rust 1.46.0 * missed these * coverage * review comments --- .../hazmat/backends/openssl/decode_asn1.py | 86 ------------- src/rust/src/x509.rs | 113 +++++++++++++++++- tests/x509/test_x509_ext.py | 3 +- 3 files changed, 110 insertions(+), 92 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 0e1f19fc6f3c..843e0e3ca1ec 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -4,7 +4,6 @@ import datetime -import ipaddress import typing from cryptography import x509 @@ -69,63 +68,6 @@ def _decode_x509_name(backend, x509_name): return x509.Name(x509.RelativeDistinguishedName(rdn) for rdn in attributes) -# This is now a hacked up decoder where we progressively remove chunks as -# we port more and more to rust. SAN exercised every branch in this, but -# other extensions (which are still in Python/OpenSSL) don't so we'll remove -# anything that isn't covered progressively until we remove the entire function -def _decode_general_name(backend, gn): - if gn.type == backend._lib.GEN_DNS: - # Convert to bytes and then decode to utf8. We don't use - # asn1_string_to_utf8 here because it doesn't properly convert - # utf8 from ia5strings. - data = _asn1_string_to_bytes(backend, gn.d.dNSName).decode("utf8") - # We don't use the constructor for DNSName so we can bypass validation - # This allows us to create DNSName objects that have unicode chars - # when a certificate (against the RFC) contains them. - return x509.DNSName._init_without_validation(data) - elif gn.type == backend._lib.GEN_URI: - # Convert to bytes and then decode to utf8. We don't use - # asn1_string_to_utf8 here because it doesn't properly convert - # utf8 from ia5strings. - data = _asn1_string_to_bytes( - backend, gn.d.uniformResourceIdentifier - ).decode("utf8") - # We don't use the constructor for URI so we can bypass validation - # This allows us to create URI objects that have unicode chars - # when a certificate (against the RFC) contains them. - return x509.UniformResourceIdentifier._init_without_validation(data) - elif gn.type == backend._lib.GEN_IPADD: - data = _asn1_string_to_bytes(backend, gn.d.iPAddress) - data_len = len(data) - assert data_len == 8 or data_len == 32 - # This is an IPv4 or IPv6 Network and not a single IP. This - # type of data appears in Name Constraints. Unfortunately, - # ipaddress doesn't support packed bytes + netmask. Additionally, - # IPv6Network can only handle CIDR rather than the full 16 byte - # netmask. To handle this we convert the netmask to integer, then - # find the first 0 bit, which will be the prefix. If another 1 - # bit is present after that the netmask is invalid. - base = ipaddress.ip_address(data[: data_len // 2]) - netmask = ipaddress.ip_address(data[data_len // 2 :]) - bits = bin(int(netmask))[2:] - prefix = bits.find("0") - # If no 0 bits are found it is a /32 or /128 - if prefix == -1: - prefix = len(bits) - - if "1" in bits[prefix:]: - raise ValueError("Invalid netmask") - - ip = ipaddress.ip_network(base.exploded + "/{}".format(prefix)) - - return x509.IPAddress(ip) - else: - assert gn.type == backend._lib.GEN_DIRNAME - return x509.DirectoryName( - _decode_x509_name(backend, gn.d.directoryName) - ) - - class _X509ExtensionParser(object): def __init__( self, backend, ext_count, get_ext, rust_callback, handlers={} @@ -254,36 +196,9 @@ def _decode_user_notice(backend, un): return x509.UserNotice(notice_reference, explicit_text) -def _decode_name_constraints(backend, nc): - nc = backend._ffi.cast("NAME_CONSTRAINTS *", nc) - nc = backend._ffi.gc(nc, backend._lib.NAME_CONSTRAINTS_free) - permitted = _decode_general_subtrees(backend, nc.permittedSubtrees) - excluded = _decode_general_subtrees(backend, nc.excludedSubtrees) - return x509.NameConstraints( - permitted_subtrees=permitted, excluded_subtrees=excluded - ) - - -def _decode_general_subtrees(backend, stack_subtrees): - if stack_subtrees == backend._ffi.NULL: - return None - - num = backend._lib.sk_GENERAL_SUBTREE_num(stack_subtrees) - subtrees = [] - - for i in range(num): - obj = backend._lib.sk_GENERAL_SUBTREE_value(stack_subtrees, i) - backend.openssl_assert(obj != backend._ffi.NULL) - name = _decode_general_name(backend, obj.base) - subtrees.append(name) - - return subtrees - - _DISTPOINT_TYPE_FULLNAME = 0 _DISTPOINT_TYPE_RELATIVENAME = 1 - # CRLReason ::= ENUMERATED { # unspecified (0), # keyCompromise (1), @@ -381,5 +296,4 @@ def _parse_asn1_generalized_time(backend, generalized_time): _EXTENSION_HANDLERS_BASE = { ExtensionOID.CERTIFICATE_POLICIES: _decode_certificate_policies, - ExtensionOID.NAME_CONSTRAINTS: _decode_name_constraints, } diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index e38b9671b091..161562cabab1 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -27,6 +27,7 @@ lazy_static::lazy_static! { static ref CRL_REASON_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.21").unwrap(); static ref ISSUING_DISTRIBUTION_POINT_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.28").unwrap(); static ref CERTIFICATE_ISSUER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.29").unwrap(); + static ref NAME_CONSTRAINTS_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.30").unwrap(); static ref CRL_DISTRIBUTION_POINTS_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.31").unwrap(); static ref FRESHEST_CRL_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.46").unwrap(); static ref CRL_NUMBER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.20").unwrap(); @@ -48,6 +49,38 @@ impl<'a> asn1::SimpleAsn1Readable<'a> for UnvalidatedIA5String<'a> { } } +#[derive(asn1::Asn1Read)] +struct NameConstraints<'a> { + #[implicit(0)] + permitted_subtrees: Option>>, + + #[implicit(1)] + excluded_subtrees: Option>>, +} + +#[derive(asn1::Asn1Read)] +struct GeneralSubtree<'a> { + base: GeneralName<'a>, + + #[implicit(0)] + #[default(0u64)] + _minimum: u64, + + #[implicit(1)] + _maximum: Option, +} + +fn parse_general_subtrees<'a>( + py: pyo3::Python<'_>, + subtrees: asn1::SequenceOf<'a, GeneralSubtree<'a>>, +) -> Result { + let gns = pyo3::types::PyList::empty(py); + for gs in subtrees { + gns.append(parse_general_name(py, gs.base)?)?; + } + Ok(gns.to_object(py)) +} + #[derive(asn1::Asn1Read)] struct IssuingDistributionPoint<'a> { #[explicit(0)] @@ -291,6 +324,59 @@ fn parse_name(py: pyo3::Python<'_>, name: Name<'_>) -> Result Result { + // we invert and check leading zeros because leading_ones wasn't stabilized + // until 1.46.0. When we raise our MSRV we should change this + if (!num).leading_zeros() + num.trailing_zeros() != 32 { + return Err(PyAsn1Error::from(pyo3::exceptions::PyValueError::new_err( + "Invalid netmask", + ))); + } + Ok((!num).leading_zeros()) +} + +fn ipv6_netmask(num: u128) -> Result { + // we invert and check leading zeros because leading_ones wasn't stabilized + // until 1.46.0. When we raise our MSRV we should change this + if (!num).leading_zeros() + num.trailing_zeros() != 128 { + return Err(PyAsn1Error::from(pyo3::exceptions::PyValueError::new_err( + "Invalid netmask", + ))); + } + Ok((!num).leading_zeros()) +} + +fn create_ip_network(py: pyo3::Python<'_>, data: &[u8]) -> Result { + let ip_module = py.import("ipaddress")?; + let x509_module = py.import("cryptography.x509")?; + let prefix = match data.len() { + 8 => { + let num = u32::from_be_bytes(data[4..].try_into().unwrap()); + ipv4_netmask(num) + } + 32 => { + let num = u128::from_be_bytes(data[16..].try_into().unwrap()); + ipv6_netmask(num) + } + _ => Err(PyAsn1Error::from(pyo3::exceptions::PyValueError::new_err( + format!("Invalid IPNetwork, must be 8 bytes for IPv4 and 32 bytes for IPv6. Found length: {}", data.len()), + ))), + }; + let base = ip_module.call_method1( + "ip_address", + (pyo3::types::PyBytes::new(py, &data[..data.len() / 2]),), + )?; + let net = format!( + "{}/{}", + base.getattr("exploded")?.extract::<&str>()?, + prefix? + ); + let addr = ip_module.call_method1("ip_network", (net,))?.to_object(py); + Ok(x509_module + .call_method1("IPAddress", (addr,))? + .to_object(py)) +} + fn parse_general_name( py: pyo3::Python<'_>, gn: GeneralName<'_>, @@ -325,10 +411,16 @@ fn parse_general_name( .to_object(py), GeneralName::IPAddress(data) => { let ip_module = py.import("ipaddress")?; - let ip_addr = ip_module.call_method1("ip_address", (data,))?.to_object(py); - x509_module - .call_method1("IPAddress", (ip_addr,))? - .to_object(py) + if data.len() == 4 || data.len() == 16 { + let addr = ip_module.call_method1("ip_address", (data,))?.to_object(py); + x509_module + .call_method1("IPAddress", (addr,))? + .to_object(py) + } else { + // if it's not an IPv4 or IPv6 we assume it's an IPNetwork and + // verify length in this function. + create_ip_network(py, data)? + } } GeneralName::RegisteredID(data) => { let oid = x509_module @@ -672,6 +764,19 @@ fn parse_x509_extension( Ok(x509_module .call1("PrecertificateSignedCertificateTimestamps", (scts,))? .to_object(py)) + } else if oid == *NAME_CONSTRAINTS_OID { + let nc = asn1::parse_single::>(ext_data)?; + let permitted_subtrees = match nc.permitted_subtrees { + Some(data) => parse_general_subtrees(py, data)?, + None => py.None(), + }; + let excluded_subtrees = match nc.excluded_subtrees { + Some(data) => parse_general_subtrees(py, data)?, + None => py.None(), + }; + Ok(x509_module + .call1("NameConstraints", (permitted_subtrees, excluded_subtrees))? + .to_object(py)) } else { Ok(py.None()) } diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index 166ab256b896..a69f40d4e43d 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -3574,8 +3574,7 @@ def test_ip_invalid_length(self, backend): x509.load_pem_x509_certificate, backend, ) - # NOTE: This will change to ValueError upon oxidization. - with pytest.raises(AssertionError): + with pytest.raises(ValueError): cert.extensions.get_extension_for_oid( ExtensionOID.NAME_CONSTRAINTS ) From 13839c36b8dffd2794d612b1b0d9306c90a25d83 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 12 Jun 2021 18:13:30 -0400 Subject: [PATCH 0317/2380] Remove OpenSSL ct.h usage (#6115) --- src/_cffi_src/build_openssl.py | 1 - src/_cffi_src/openssl/ct.py | 117 ------------------ .../hazmat/bindings/openssl/_conditional.py | 23 ---- 3 files changed, 141 deletions(-) delete mode 100644 src/_cffi_src/openssl/ct.py diff --git a/src/_cffi_src/build_openssl.py b/src/_cffi_src/build_openssl.py index 557296ed5354..df11130371d1 100644 --- a/src/_cffi_src/build_openssl.py +++ b/src/_cffi_src/build_openssl.py @@ -86,7 +86,6 @@ def _extra_compile_args(platform): "cmac", "conf", "crypto", - "ct", "dh", "dsa", "ec", diff --git a/src/_cffi_src/openssl/ct.py b/src/_cffi_src/openssl/ct.py deleted file mode 100644 index 6271497625db..000000000000 --- a/src/_cffi_src/openssl/ct.py +++ /dev/null @@ -1,117 +0,0 @@ -# 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. - - -INCLUDES = """ -#if CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER && !defined(OPENSSL_NO_CT) -#include - -typedef STACK_OF(SCT) Cryptography_STACK_OF_SCT; -#endif -""" - -TYPES = """ -static const long Cryptography_HAS_SCT; - -typedef enum { - SCT_VERSION_NOT_SET, - SCT_VERSION_V1 -} sct_version_t; - -typedef enum { - CT_LOG_ENTRY_TYPE_NOT_SET, - CT_LOG_ENTRY_TYPE_X509, - CT_LOG_ENTRY_TYPE_PRECERT -} ct_log_entry_type_t; - -typedef enum { - SCT_SOURCE_UNKNOWN, - SCT_SOURCE_TLS_EXTENSION, - SCT_SOURCE_X509V3_EXTENSION, - SCT_SOURCE_OCSP_STAPLED_RESPONSE -} sct_source_t; - -typedef ... SCT; -typedef ... Cryptography_STACK_OF_SCT; -""" - -FUNCTIONS = """ -sct_version_t SCT_get_version(const SCT *); - -ct_log_entry_type_t SCT_get_log_entry_type(const SCT *); - -size_t SCT_get0_log_id(const SCT *, unsigned char **); - -size_t SCT_get0_signature(const SCT *, unsigned char **); - -uint64_t SCT_get_timestamp(const SCT *); - -int SCT_set_source(SCT *, sct_source_t); - -Cryptography_STACK_OF_SCT *sk_SCT_new_null(void); -void sk_SCT_free(Cryptography_STACK_OF_SCT *); -int sk_SCT_num(const Cryptography_STACK_OF_SCT *); -SCT *sk_SCT_value(const Cryptography_STACK_OF_SCT *, int); -int sk_SCT_push(Cryptography_STACK_OF_SCT *, SCT *); - -void SCT_LIST_free(Cryptography_STACK_OF_SCT *); - -SCT *SCT_new(void); -int SCT_set1_log_id(SCT *, unsigned char *, size_t); -void SCT_set_timestamp(SCT *, uint64_t); -int SCT_set_version(SCT *, sct_version_t); -int SCT_set_log_entry_type(SCT *, ct_log_entry_type_t); -""" - -CUSTOMIZATIONS = """ -#if CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER && !defined(OPENSSL_NO_CT) -static const long Cryptography_HAS_SCT = 1; -#else -static const long Cryptography_HAS_SCT = 0; - -typedef enum { - SCT_VERSION_NOT_SET, - SCT_VERSION_V1 -} sct_version_t; -typedef enum { - CT_LOG_ENTRY_TYPE_NOT_SET, - CT_LOG_ENTRY_TYPE_X509, - CT_LOG_ENTRY_TYPE_PRECERT -} ct_log_entry_type_t; -typedef enum { - SCT_SOURCE_UNKNOWN, - SCT_SOURCE_TLS_EXTENSION, - SCT_SOURCE_X509V3_EXTENSION, - SCT_SOURCE_OCSP_STAPLED_RESPONSE -} sct_source_t; - -/* OpenSSL compiled with `no-ct` still defines the `SCT` struct. */ -#if !defined(OPENSSL_NO_CT) -typedef void SCT; -#endif - -typedef void Cryptography_STACK_OF_SCT; - -sct_version_t (*SCT_get_version)(const SCT *) = NULL; -ct_log_entry_type_t (*SCT_get_log_entry_type)(const SCT *) = NULL; -size_t (*SCT_get0_log_id)(const SCT *, unsigned char **) = NULL; -size_t (*SCT_get0_signature)(const SCT *, unsigned char **) = NULL; -uint64_t (*SCT_get_timestamp)(const SCT *) = NULL; - -int (*SCT_set_source)(SCT *, sct_source_t) = NULL; - -Cryptography_STACK_OF_SCT *(*sk_SCT_new_null)(void) = NULL; -void (*sk_SCT_free)(Cryptography_STACK_OF_SCT *) = NULL; -int (*sk_SCT_num)(const Cryptography_STACK_OF_SCT *) = NULL; -SCT *(*sk_SCT_value)(const Cryptography_STACK_OF_SCT *, int) = NULL; -int (*sk_SCT_push)(Cryptography_STACK_OF_SCT *, SCT *) = NULL; - -void (*SCT_LIST_free)(Cryptography_STACK_OF_SCT *) = NULL; -SCT *(*SCT_new)(void) = NULL; -int (*SCT_set1_log_id)(SCT *, unsigned char *, size_t) = NULL; -void (*SCT_set_timestamp)(SCT *, uint64_t) = NULL; -int (*SCT_set_version)(SCT *, sct_version_t) = NULL; -int (*SCT_set_log_entry_type)(SCT *, ct_log_entry_type_t) = NULL; -#endif -""" diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index 55b2117cd53b..ba01169f1e10 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -76,28 +76,6 @@ def cryptography_has_mem_functions(): ] -def cryptography_has_sct(): - return [ - "SCT_get_version", - "SCT_get_log_entry_type", - "SCT_get0_log_id", - "SCT_get0_signature", - "SCT_get_timestamp", - "SCT_set_source", - "sk_SCT_new_null", - "sk_SCT_free", - "sk_SCT_num", - "sk_SCT_value", - "sk_SCT_push", - "SCT_LIST_free", - "SCT_new", - "SCT_set1_log_id", - "SCT_set_timestamp", - "SCT_set_version", - "SCT_set_log_entry_type", - ] - - def cryptography_has_x509_store_ctx_get_issuer(): return [ "X509_STORE_get_get_issuer", @@ -285,7 +263,6 @@ def cryptography_has_providers(): "Cryptography_HAS_SCRYPT": cryptography_has_scrypt, "Cryptography_HAS_EVP_PKEY_DHX": cryptography_has_evp_pkey_dhx, "Cryptography_HAS_MEM_FUNCTIONS": cryptography_has_mem_functions, - "Cryptography_HAS_SCT": cryptography_has_sct, "Cryptography_HAS_X509_STORE_CTX_GET_ISSUER": ( cryptography_has_x509_store_ctx_get_issuer ), From 52dd0e55e3dc05b5458a2877fe0af938b5cf8ccd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Jun 2021 07:57:13 -0400 Subject: [PATCH 0318/2380] Bump libc from 0.2.96 to 0.2.97 in /src/rust (#6117) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.96 to 0.2.97. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.96...0.2.97) --- updated-dependencies: - dependency-name: libc dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index a017dae9f325..f100b8c39cdc 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -151,9 +151,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.96" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5600b4e6efc5421841a2138a6b082e07fe12f9aaa12783d50e5d13325b26b4fc" +checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" [[package]] name = "lock_api" From a6499679eb898f6b36804b325ea0a055904ddcd9 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 14 Jun 2021 22:36:55 -0500 Subject: [PATCH 0319/2380] add certificate policies test vector (#6118) --- docs/development/test-vectors.rst | 7 ++++++- tests/x509/test_x509_ext.py | 10 ++++++++++ .../x509/custom/cp_invalid2.der | Bin 0 -> 761 bytes 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 vectors/cryptography_vectors/x509/custom/cp_invalid2.der diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index 0aed4313b0e9..db897f79fbac 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -397,7 +397,12 @@ Custom X.509 Vectors certificate containing a certificate policies extension with a user notice with no explicit text. * ``cp_invalid.pem`` - An RSA 2048 bit self-signed certificate containing a - certificate policies extension with invalid data. + certificate policies extension with invalid data. The ``policyQualifierId`` + is for ``id-qt-unotice`` but the value is an ``id-qt-cps`` ASN.1 structure. +* ``cp_invalid2.der`` - An RSA 2048 bit self-signed certificate containing a + certificate policies extension with invalid data. The ``policyQualifierId`` + is for ``id-qt-cps`` but the value is an ``id-qt-unotice`` ASN.1 structure. + The signature on this certificate is invalid. * ``ian_uri.pem`` - An RSA 2048 bit certificate containing an issuer alternative name extension with a ``URI`` general name. * ``ocsp_nocheck.pem`` - An RSA 2048 bit self-signed certificate containing diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index a69f40d4e43d..bc3688bd0d8f 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -5594,6 +5594,7 @@ def test_invalid_length(self, backend): class TestInvalidExtension(object): def test_invalid_certificate_policies_data(self, backend): + # UserNotice OID but CPSURI structure cert = _load_cert( os.path.join("x509", "custom", "cp_invalid.pem"), x509.load_pem_x509_certificate, @@ -5602,6 +5603,15 @@ def test_invalid_certificate_policies_data(self, backend): with pytest.raises(ValueError): cert.extensions + # CPSURI OID but UserNotice structure + cert = _load_cert( + os.path.join("x509", "custom", "cp_invalid2.der"), + x509.load_der_x509_certificate, + backend, + ) + with pytest.raises(ValueError): + cert.extensions + class TestOCSPNonce(object): def test_non_bytes(self): diff --git a/vectors/cryptography_vectors/x509/custom/cp_invalid2.der b/vectors/cryptography_vectors/x509/custom/cp_invalid2.der new file mode 100644 index 0000000000000000000000000000000000000000..08d31db26b4f732dc10815554a6900a6bbe07eef GIT binary patch literal 761 zcmXqLV)|;(#CUfBGZP~dlQ3Jh?Yx)qZkfg+DVn-7+Fn>5TW-M1#;Mij(e|B}k&%^^ z!9d7Rz<`g9Ih2K&hdrRu*-^pS(Lhd|*U;3!)X)e>8W|Zy0l8*Ct|63*RZkP660*^Z ztPIRejQk8h$8a$M;e!&>>Z5!bJrKeBe8{MUCYYIKu=FP^ad zsk70=+sA0)U(s8+&Ozyad)fB7uYJrqr%pe`KR%>5 z@3LY)-4bNraJFYFb2CqM`X{ejFK$arc(7wj9^1i3>wFi!7Ckakb>pf>&GCG^b5|O$ zt*V)@BH*^jrO2A7oLe~`0ve6Gnckn^YIt09FYHE1VebEgkjDxCa&+yJO3fojr6VX5D`9&^7AEk=oajp0%}yD4O>)y8eB$;_v|lkywjGck+u? zURU|L?~c>13H_&^XC~gY+&Z_YelPpETVlQ2GUrdb^j1?y>8kQ0T_ctWbI(^^P?)r? zqFH$2Bj+E-=2Tx}779AQA*!hJ{I$lVPOf*;19CWC9M66}tA;yqc`<{2M! Date: Wed, 16 Jun 2021 07:38:09 -0400 Subject: [PATCH 0320/2380] Bump asn1 from 0.5.1 to 0.5.2 in /src/rust (#6121) Bumps [asn1](https://github.com/alex/rust-asn1) from 0.5.1 to 0.5.2. - [Release notes](https://github.com/alex/rust-asn1/releases) - [Commits](https://github.com/alex/rust-asn1/compare/0.5.1...0.5.2) --- updated-dependencies: - dependency-name: asn1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 8 ++++---- src/rust/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index f100b8c39cdc..f8c78afcc547 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -10,9 +10,9 @@ checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" [[package]] name = "asn1" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4e2ec2f073674e49321449dbfd51accb77effab6ade9f311f0f631903d20c39" +checksum = "f8ed4a28082a1239ef1f2de61139d9421958e92e044190f052021c4b952ee75a" dependencies = [ "asn1_derive", "chrono", @@ -20,9 +20,9 @@ dependencies = [ [[package]] name = "asn1_derive" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18175ce37dddb6ef19f30996c31f63b38571fea8351f321088181cd089efd203" +checksum = "40b1bb20092bbe014fe3b06d23d86c4d42a422cb42632101231b19092b402536" dependencies = [ "proc-macro2", "quote", diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index dd535181f95c..b5729a38b6b2 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] lazy_static = "1" pyo3 = { version = "0.13.1" } -asn1 = { version = "0.5.1", default-features = false, features = ["derive"] } +asn1 = { version = "0.5.2", default-features = false, features = ["derive"] } chrono = { version = "0.4", default-features = false, features = ["alloc"] } ouroboros = "0.9" From 45e9599848a9fa1000f314319607e15a4820bc95 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 16 Jun 2021 09:12:25 -0500 Subject: [PATCH 0321/2380] oxidize certificate policies (#6119) --- .../hazmat/backends/openssl/backend.py | 3 - .../hazmat/backends/openssl/decode_asn1.py | 101 +------------ src/rust/src/x509.rs | 136 ++++++++++++++++++ tests/hazmat/backends/test_openssl.py | 11 ++ 4 files changed, 151 insertions(+), 100 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index bfc9dd07a7a3..ab9f2ce80f8b 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -18,7 +18,6 @@ from cryptography.hazmat.backends.openssl.cmac import _CMACContext from cryptography.hazmat.backends.openssl.decode_asn1 import ( _CRL_ENTRY_REASON_ENUM_TO_CODE, - _EXTENSION_HANDLERS_BASE, _X509ExtensionParser, ) from cryptography.hazmat.backends.openssl.dh import ( @@ -389,14 +388,12 @@ def _register_x509_ext_parsers(self): ext_count=self._lib.X509_get_ext_count, get_ext=self._lib.X509_get_ext, rust_callback=rust_x509.parse_x509_extension, - handlers=_EXTENSION_HANDLERS_BASE, ) self._csr_extension_parser = _X509ExtensionParser( self, ext_count=self._lib.sk_X509_EXTENSION_num, get_ext=self._lib.sk_X509_EXTENSION_value, rust_callback=rust_x509.parse_x509_extension, - handlers=_EXTENSION_HANDLERS_BASE, ) self._revoked_cert_extension_parser = _X509ExtensionParser( self, diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 843e0e3ca1ec..228d3e008392 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -8,10 +8,6 @@ from cryptography import x509 from cryptography.x509.name import _ASN1_TYPE_TO_ENUM -from cryptography.x509.oid import ( - CertificatePoliciesOID, - ExtensionOID, -) def _obj2txt(backend, obj): @@ -69,12 +65,9 @@ def _decode_x509_name(backend, x509_name): class _X509ExtensionParser(object): - def __init__( - self, backend, ext_count, get_ext, rust_callback, handlers={} - ): + def __init__(self, backend, ext_count, get_ext, rust_callback): self.ext_count = ext_count self.get_ext = get_ext - self.handlers = handlers self.rust_callback = rust_callback self._backend = backend @@ -106,96 +99,15 @@ def parse(self, x509_obj): data = self._backend._lib.X509_EXTENSION_get_data(ext) data_bytes = _asn1_string_to_bytes(self._backend, data) ext_obj = self.rust_callback(oid_der_bytes, data_bytes) - if ext_obj is not None: - extensions.append(x509.Extension(oid, critical, ext_obj)) - seen_oids.add(oid) - continue - - # Fallback to our older parsing because the rust code doesn't - # know how to parse this. - try: - handler = self.handlers[oid] - except KeyError: - # Dump the DER payload into an UnrecognizedExtension object - data = self._backend._lib.X509_EXTENSION_get_data(ext) - self._backend.openssl_assert(data != self._backend._ffi.NULL) - der = self._backend._ffi.buffer(data.data, data.length)[:] - unrecognized = x509.UnrecognizedExtension(oid, der) - extensions.append(x509.Extension(oid, critical, unrecognized)) - else: - ext_data = self._backend._lib.X509V3_EXT_d2i(ext) - if ext_data == self._backend._ffi.NULL: - self._backend._consume_errors() - raise ValueError( - "The {} extension is invalid and can't be " - "parsed".format(oid) - ) - - value = handler(self._backend, ext_data) - extensions.append(x509.Extension(oid, critical, value)) + if ext_obj is None: + ext_obj = x509.UnrecognizedExtension(oid, data_bytes) + extensions.append(x509.Extension(oid, critical, ext_obj)) seen_oids.add(oid) return x509.Extensions(extensions) -def _decode_certificate_policies(backend, cp): - cp = backend._ffi.cast("Cryptography_STACK_OF_POLICYINFO *", cp) - cp = backend._ffi.gc(cp, backend._lib.CERTIFICATEPOLICIES_free) - - num = backend._lib.sk_POLICYINFO_num(cp) - certificate_policies = [] - for i in range(num): - qualifiers = None - pi = backend._lib.sk_POLICYINFO_value(cp, i) - oid = x509.ObjectIdentifier(_obj2txt(backend, pi.policyid)) - if pi.qualifiers != backend._ffi.NULL: - qnum = backend._lib.sk_POLICYQUALINFO_num(pi.qualifiers) - qualifiers = [] - for j in range(qnum): - pqi = backend._lib.sk_POLICYQUALINFO_value(pi.qualifiers, j) - pqualid = x509.ObjectIdentifier(_obj2txt(backend, pqi.pqualid)) - if pqualid == CertificatePoliciesOID.CPS_QUALIFIER: - cpsuri = backend._ffi.buffer( - pqi.d.cpsuri.data, pqi.d.cpsuri.length - )[:].decode("ascii") - qualifiers.append(cpsuri) - else: - assert pqualid == CertificatePoliciesOID.CPS_USER_NOTICE - user_notice = _decode_user_notice( - backend, pqi.d.usernotice - ) - qualifiers.append(user_notice) - - certificate_policies.append(x509.PolicyInformation(oid, qualifiers)) - - return x509.CertificatePolicies(certificate_policies) - - -def _decode_user_notice(backend, un): - explicit_text = None - notice_reference = None - - if un.exptext != backend._ffi.NULL: - explicit_text = _asn1_string_to_utf8(backend, un.exptext) - - if un.noticeref != backend._ffi.NULL: - organization = _asn1_string_to_utf8(backend, un.noticeref.organization) - - num = backend._lib.sk_ASN1_INTEGER_num(un.noticeref.noticenos) - notice_numbers = [] - for i in range(num): - asn1_int = backend._lib.sk_ASN1_INTEGER_value( - un.noticeref.noticenos, i - ) - notice_num = _asn1_integer_to_int(backend, asn1_int) - notice_numbers.append(notice_num) - - notice_reference = x509.NoticeReference(organization, notice_numbers) - - return x509.UserNotice(notice_reference, explicit_text) - - _DISTPOINT_TYPE_FULLNAME = 0 _DISTPOINT_TYPE_RELATIVENAME = 1 @@ -292,8 +204,3 @@ def _parse_asn1_generalized_time(backend, generalized_time): backend, backend._ffi.cast("ASN1_STRING *", generalized_time) ) return datetime.datetime.strptime(time, "%Y%m%d%H%M%SZ") - - -_EXTENSION_HANDLERS_BASE = { - ExtensionOID.CERTIFICATE_POLICIES: _decode_certificate_policies, -} diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index 161562cabab1..45518aebbd5b 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -29,6 +29,7 @@ lazy_static::lazy_static! { static ref CERTIFICATE_ISSUER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.29").unwrap(); static ref NAME_CONSTRAINTS_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.30").unwrap(); static ref CRL_DISTRIBUTION_POINTS_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.31").unwrap(); + static ref CERTIFICATE_POLICIES_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.32").unwrap(); static ref FRESHEST_CRL_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.46").unwrap(); static ref CRL_NUMBER_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.20").unwrap(); static ref INVALIDITY_DATE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.24").unwrap(); @@ -36,6 +37,136 @@ lazy_static::lazy_static! { static ref SUBJECT_ALTERNATIVE_NAME_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.17").unwrap(); static ref ISSUER_ALTERNATIVE_NAME_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("2.5.29.18").unwrap(); static ref PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.4.1.11129.2.4.2").unwrap(); + + static ref CP_CPS_URI_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.2.1").unwrap(); + static ref CP_USER_NOTICE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.2.2").unwrap(); +} + +#[derive(asn1::Asn1Read)] +struct PolicyInformation<'a> { + policy_identifier: asn1::ObjectIdentifier<'a>, + policy_qualifiers: Option>>, +} + +#[derive(asn1::Asn1Read)] +struct PolicyQualifierInfo<'a> { + policy_qualifier_id: asn1::ObjectIdentifier<'a>, + qualifier: Qualifier<'a>, +} + +#[derive(asn1::Asn1Read)] +enum Qualifier<'a> { + CpsUri(asn1::IA5String<'a>), + UserNotice(UserNotice<'a>), +} + +#[derive(asn1::Asn1Read)] +struct UserNotice<'a> { + notice_ref: Option>, + explicit_text: Option>, +} + +#[derive(asn1::Asn1Read)] +struct NoticeReference<'a> { + organization: DisplayText<'a>, + notice_numbers: asn1::SequenceOf<'a, asn1::BigUint<'a>>, +} + +// DisplayText also allows BMPString, which we currently do not support. +#[allow(clippy::enum_variant_names)] +#[derive(asn1::Asn1Read)] +enum DisplayText<'a> { + IA5String(asn1::IA5String<'a>), + Utf8String(asn1::Utf8String<'a>), + VisibleString(asn1::VisibleString<'a>), +} + +fn parse_display_text(py: pyo3::Python<'_>, text: DisplayText<'_>) -> pyo3::PyObject { + match text { + DisplayText::IA5String(o) => pyo3::types::PyString::new(py, o.as_str()).to_object(py), + DisplayText::Utf8String(o) => pyo3::types::PyString::new(py, o.as_str()).to_object(py), + DisplayText::VisibleString(o) => pyo3::types::PyString::new(py, o.as_str()).to_object(py), + } +} + +fn parse_user_notice( + py: pyo3::Python<'_>, + un: UserNotice<'_>, +) -> Result { + let x509_module = py.import("cryptography.x509")?; + let et = match un.explicit_text { + Some(data) => parse_display_text(py, data), + None => py.None(), + }; + let nr = match un.notice_ref { + Some(data) => { + let org = parse_display_text(py, data.organization); + let numbers = pyo3::types::PyList::empty(py); + for num in data.notice_numbers { + numbers.append(big_asn1_uint_to_py(py, num)?.to_object(py))?; + } + x509_module + .call_method1("NoticeReference", (org, numbers))? + .to_object(py) + } + None => py.None(), + }; + Ok(x509_module + .call_method1("UserNotice", (nr, et))? + .to_object(py)) +} + +fn parse_policy_qualifiers<'a>( + py: pyo3::Python<'_>, + policy_qualifiers: asn1::SequenceOf<'a, PolicyQualifierInfo<'a>>, +) -> Result { + let py_pq = pyo3::types::PyList::empty(py); + for pqi in policy_qualifiers { + let qualifier = match pqi.qualifier { + Qualifier::CpsUri(data) => { + if pqi.policy_qualifier_id == *CP_CPS_URI_OID { + pyo3::types::PyString::new(py, data.as_str()).to_object(py) + } else { + return Err(PyAsn1Error::from(pyo3::exceptions::PyValueError::new_err( + "CpsUri ASN.1 structure found but OID did not match", + ))); + } + } + Qualifier::UserNotice(un) => { + if pqi.policy_qualifier_id != *CP_USER_NOTICE_OID { + return Err(PyAsn1Error::from(pyo3::exceptions::PyValueError::new_err( + "UserNotice ASN.1 structure found but OID did not match", + ))); + } + parse_user_notice(py, un)? + } + }; + py_pq.append(qualifier)?; + } + Ok(py_pq.to_object(py)) +} + +fn parse_cp(py: pyo3::Python<'_>, ext_data: &[u8]) -> Result { + let cp = asn1::parse_single::>>(ext_data)?; + let x509_module = py.import("cryptography.x509")?; + let certificate_policies = pyo3::types::PyList::empty(py); + for policyinfo in cp { + let pi_oid = x509_module + .call_method1( + "ObjectIdentifier", + (policyinfo.policy_identifier.to_string(),), + )? + .to_object(py); + let py_pqis = match policyinfo.policy_qualifiers { + Some(policy_qualifiers) => parse_policy_qualifiers(py, policy_qualifiers)?, + None => py.None(), + }; + let pi = x509_module + .call_method1("PolicyInformation", (pi_oid, py_pqis))? + .to_object(py); + certificate_policies.append(pi)?; + } + Ok(certificate_policies.to_object(py)) } struct UnvalidatedIA5String<'a>(&'a str); @@ -722,6 +853,11 @@ fn parse_x509_extension( Ok(x509_module .call1("SubjectInformationAccess", (ads,))? .to_object(py)) + } else if oid == *CERTIFICATE_POLICIES_OID { + let cp = parse_cp(py, ext_data)?; + Ok(x509_module + .call_method1("CertificatePolicies", (cp,))? + .to_object(py)) } else if oid == *POLICY_CONSTRAINTS_OID { let pc = asn1::parse_single::(ext_data)?; Ok(x509_module diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index a559998f1699..a59aa09f31bd 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -13,6 +13,7 @@ from cryptography import x509 from cryptography.exceptions import InternalError, _Reasons +from cryptography.hazmat.backends.openssl import decode_asn1, encode_asn1 from cryptography.hazmat.backends.openssl.backend import Backend, backend from cryptography.hazmat.backends.openssl.ec import _sn_to_elliptic_curve from cryptography.hazmat.primitives import hashes, serialization @@ -164,6 +165,16 @@ def test_bn_to_int(self): bn = backend._int_to_bn(0) assert backend._bn_to_int(bn) == 0 + def test_obj2txt_buffer_sizing(self): + # This test exercises a branch for larger than default buffer sizing + # in _obj2txt + oid_str = ( + "1.2.3.182382138123818.1293813123.12381238123.3434834834888" + ".383488234284.2348234.234819299576434.23482434203" + ) + obj = encode_asn1._txt2obj_gc(backend, oid_str) + assert decode_asn1._obj2txt(backend, obj) == oid_str + @pytest.mark.skipif( not backend._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE, From 6e8106f73d639d3a95c96ab041e96418121bf5bc Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Thu, 17 Jun 2021 12:54:05 +0100 Subject: [PATCH 0322/2380] type annotate cryptography.utils:register_interface (#6123) --- src/cryptography/utils.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index f07d5fdad249..8611d95c8e74 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -41,8 +41,22 @@ def read_only_property(name: str): return property(lambda self: getattr(self, name)) -def register_interface(iface): - def register_decorator(klass, *, check_annotations=False): +if typing.TYPE_CHECKING: + from typing_extensions import Protocol + + _T_class = typing.TypeVar("_T_class", bound=type) + + class _RegisterDecoratorType(Protocol): + def __call__( + self, klass: _T_class, *, check_annotations: bool = False + ) -> _T_class: + ... + + +def register_interface(iface: abc.ABCMeta) -> "_RegisterDecoratorType": + def register_decorator( + klass: "_T_class", *, check_annotations: bool = False + ) -> "_T_class": verify_interface(iface, klass, check_annotations=check_annotations) iface.register(klass) return klass From 1e3eab5d178ce94e903f9131d011efe68e1da97b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Jun 2021 08:29:28 -0400 Subject: [PATCH 0323/2380] Bump redox_syscall from 0.2.8 to 0.2.9 in /src/rust (#6126) Bumps redox_syscall from 0.2.8 to 0.2.9. --- updated-dependencies: - dependency-name: redox_syscall dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index f8c78afcc547..1bcce8a65d6c 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -339,9 +339,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc" +checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" dependencies = [ "bitflags", ] From 60eeb4eb7a981fd9d8b18b06391592f06a0a1a41 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 17 Jun 2021 10:23:24 -0500 Subject: [PATCH 0324/2380] bump CI to 3.0.0-beta1 (#6127) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d1d1d1e42a1e..cedaa32e44a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1k"}} - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1k"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1k", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "3.0.0-alpha17"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "3.0.0-beta1"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "2.9.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.0.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.1.5"}} From b2db8579f3a71ca1c57b652f4e7f98bcba872780 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 18 Jun 2021 15:05:23 -0400 Subject: [PATCH 0325/2380] Move some X.509 types from the OCSP module (#6128) --- src/rust/src/ocsp.rs | 77 +++----------------------------------------- src/rust/src/x509.rs | 68 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 72 deletions(-) diff --git a/src/rust/src/ocsp.rs b/src/rust/src/ocsp.rs index fbac6c389213..8bba14b11673 100644 --- a/src/rust/src/ocsp.rs +++ b/src/rust/src/ocsp.rs @@ -6,7 +6,7 @@ use crate::asn1::{big_asn1_uint_to_py, PyAsn1Error}; use crate::x509; use pyo3::conversion::ToPyObject; use pyo3::exceptions; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; lazy_static::lazy_static! { static ref SHA1_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.14.3.2.26").unwrap(); @@ -76,57 +76,6 @@ impl OCSPRequest { } } -fn parse_and_cache_extensions< - 'p, - F: Fn(&asn1::ObjectIdentifier<'_>, &[u8]) -> Result, PyAsn1Error>, ->( - py: pyo3::Python<'p>, - cached_extensions: &mut Option, - raw_exts: &Option>, - parse_ext: F, -) -> Result { - if let Some(cached) = cached_extensions { - return Ok(cached.clone_ref(py)); - } - - let x509_module = py.import("cryptography.x509")?; - let exts = pyo3::types::PyList::empty(py); - let mut seen_oids = HashSet::new(); - if let Some(raw_exts) = raw_exts { - for raw_ext in raw_exts.clone() { - let oid_obj = - x509_module.call_method1("ObjectIdentifier", (raw_ext.extn_id.to_string(),))?; - - if seen_oids.contains(&raw_ext.extn_id) { - return Err(PyAsn1Error::from(pyo3::PyErr::from_instance( - x509_module.call_method1( - "DuplicateExtension", - ( - format!("Duplicate {} extension found", raw_ext.extn_id), - oid_obj, - ), - )?, - ))); - } - - let extn_value = match parse_ext(&raw_ext.extn_id, raw_ext.extn_value)? { - Some(e) => e, - None => x509_module - .call_method1("UnrecognizedExtension", (oid_obj, raw_ext.extn_value))?, - }; - let ext_obj = - x509_module.call_method1("Extension", (oid_obj, raw_ext.critical, extn_value))?; - exts.append(ext_obj)?; - seen_oids.insert(raw_ext.extn_id); - } - } - let extensions = x509_module - .call_method1("Extensions", (exts,))? - .to_object(py); - *cached_extensions = Some(extensions.clone_ref(py)); - Ok(extensions) -} - #[pyo3::prelude::pymethods] impl OCSPRequest { #[getter] @@ -169,7 +118,7 @@ impl OCSPRequest { #[getter] fn extensions(&mut self, py: pyo3::Python<'_>) -> Result { let x509_module = py.import("cryptography.x509")?; - parse_and_cache_extensions( + x509::parse_and_cache_extensions( py, &mut self.cached_extensions, &self.raw.borrow_value().tbs_request.request_extensions, @@ -229,40 +178,24 @@ struct TBSRequest<'a> { // _requestor_name: Option>, request_list: asn1::SequenceOf<'a, Request<'a>>, #[explicit(2)] - request_extensions: Option>, + request_extensions: Option>, } #[derive(asn1::Asn1Read, asn1::Asn1Write)] struct Request<'a> { req_cert: CertID<'a>, #[explicit(0)] - _single_request_extensions: Option>, + _single_request_extensions: Option>, } #[derive(asn1::Asn1Read, asn1::Asn1Write)] struct CertID<'a> { - hash_algorithm: AlgorithmIdentifier<'a>, + hash_algorithm: x509::AlgorithmIdentifier<'a>, issuer_name_hash: &'a [u8], issuer_key_hash: &'a [u8], serial_number: asn1::BigUint<'a>, } -type Extensions<'a> = asn1::SequenceOf<'a, Extension<'a>>; - -#[derive(asn1::Asn1Read, asn1::Asn1Write)] -struct AlgorithmIdentifier<'a> { - oid: asn1::ObjectIdentifier<'a>, - _params: Option>, -} - -#[derive(asn1::Asn1Read, asn1::Asn1Write)] -struct Extension<'a> { - extn_id: asn1::ObjectIdentifier<'a>, - #[default(false)] - critical: bool, - extn_value: &'a [u8], -} - #[pyo3::prelude::pyfunction] fn parse_ocsp_resp_extension( py: pyo3::Python<'_>, diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index 45518aebbd5b..36bc590d7863 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -7,6 +7,7 @@ use chrono::{Datelike, Timelike}; use pyo3::conversion::ToPyObject; use pyo3::types::IntoPyDict; use std::collections::hash_map::DefaultHasher; +use std::collections::HashSet; use std::convert::TryInto; use std::hash::{Hash, Hasher}; @@ -42,6 +43,73 @@ lazy_static::lazy_static! { static ref CP_USER_NOTICE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.2.2").unwrap(); } +pub(crate) fn parse_and_cache_extensions< + 'p, + F: Fn(&asn1::ObjectIdentifier<'_>, &[u8]) -> Result, PyAsn1Error>, +>( + py: pyo3::Python<'p>, + cached_extensions: &mut Option, + raw_exts: &Option>, + parse_ext: F, +) -> Result { + if let Some(cached) = cached_extensions { + return Ok(cached.clone_ref(py)); + } + + let x509_module = py.import("cryptography.x509")?; + let exts = pyo3::types::PyList::empty(py); + let mut seen_oids = HashSet::new(); + if let Some(raw_exts) = raw_exts { + for raw_ext in raw_exts.clone() { + let oid_obj = + x509_module.call_method1("ObjectIdentifier", (raw_ext.extn_id.to_string(),))?; + + if seen_oids.contains(&raw_ext.extn_id) { + return Err(PyAsn1Error::from(pyo3::PyErr::from_instance( + x509_module.call_method1( + "DuplicateExtension", + ( + format!("Duplicate {} extension found", raw_ext.extn_id), + oid_obj, + ), + )?, + ))); + } + + let extn_value = match parse_ext(&raw_ext.extn_id, raw_ext.extn_value)? { + Some(e) => e, + None => x509_module + .call_method1("UnrecognizedExtension", (oid_obj, raw_ext.extn_value))?, + }; + let ext_obj = + x509_module.call_method1("Extension", (oid_obj, raw_ext.critical, extn_value))?; + exts.append(ext_obj)?; + seen_oids.insert(raw_ext.extn_id); + } + } + let extensions = x509_module + .call_method1("Extensions", (exts,))? + .to_object(py); + *cached_extensions = Some(extensions.clone_ref(py)); + Ok(extensions) +} + +pub(crate) type Extensions<'a> = asn1::SequenceOf<'a, Extension<'a>>; + +#[derive(asn1::Asn1Read, asn1::Asn1Write)] +pub(crate) struct AlgorithmIdentifier<'a> { + pub(crate) oid: asn1::ObjectIdentifier<'a>, + pub(crate) _params: Option>, +} + +#[derive(asn1::Asn1Read, asn1::Asn1Write)] +pub(crate) struct Extension<'a> { + pub(crate) extn_id: asn1::ObjectIdentifier<'a>, + #[default(false)] + pub(crate) critical: bool, + pub(crate) extn_value: &'a [u8], +} + #[derive(asn1::Asn1Read)] struct PolicyInformation<'a> { policy_identifier: asn1::ObjectIdentifier<'a>, From a4aa852a17f8f097c46d16a58fc66ebfcf5e121e Mon Sep 17 00:00:00 2001 From: Tanvi Moharir <74228962+tanvimoharir@users.noreply.github.com> Date: Sat, 19 Jun 2021 23:09:00 +0530 Subject: [PATCH 0326/2380] Adding mypy configuration to pyproject (#6116) * Adding mypy configuration to pytproject * Correcting specifications for pyproject.toml --- mypy.ini | 11 ----------- pyproject.toml | 13 +++++++++++++ 2 files changed, 13 insertions(+), 11 deletions(-) delete mode 100644 mypy.ini diff --git a/mypy.ini b/mypy.ini deleted file mode 100644 index 055619c090f6..000000000000 --- a/mypy.ini +++ /dev/null @@ -1,11 +0,0 @@ -[mypy] -show_error_codes = True -check_untyped_defs = True - -[mypy-cryptography.hazmat.bindings._openssl] -ignore_missing_imports = True - -[mypy-iso8601] -ignore_missing_imports = True -[mypy-pretend] -ignore_missing_imports = True diff --git a/pyproject.toml b/pyproject.toml index b2bf92caf086..0b692437096a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,3 +20,16 @@ markers = [ "skip_fips: this test is not executed in FIPS mode", "supported: parametrized test requiring only_if and skip_message", ] + +[tool.mypy] +show_error_codes = true +check_untyped_defs = true + +[[tool.mypy.overrides]] +module = [ + "cryptography.hazmat.bindings._openssl", + "iso8601", + "pretend" +] +ignore_missing_imports = true + From ce80be2d26b76563cd2e495ab13f09f9ce0da4dd Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 19 Jun 2021 15:10:50 -0400 Subject: [PATCH 0327/2380] Add another linkcheck ignore (#6129) --- docs/conf.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/conf.py b/docs/conf.py index 0db9dd8b842d..f3b84c4111d6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -198,6 +198,8 @@ r"https://info.isl.ntt.co.jp/crypt/eng/camellia/", # Inconsistent small DH params they seem incapable of fixing r"https://www.secg.org/sec1-v2.pdf", + # Incomplete cert chain + r"https://e-trust.gosuslugi.ru", ] autosectionlabel_prefix_document = True From 5ad2488a72c1c2e32b1ab942995cddae4e675aed Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 19 Jun 2021 19:00:16 -0400 Subject: [PATCH 0328/2380] Make whitespcae in pyproject.toml normal (#6130) --- pyproject.toml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0b692437096a..913a4e46d1c1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,9 +27,8 @@ check_untyped_defs = true [[tool.mypy.overrides]] module = [ - "cryptography.hazmat.bindings._openssl", - "iso8601", - "pretend" + "cryptography.hazmat.bindings._openssl", + "iso8601", + "pretend" ] ignore_missing_imports = true - From 06e279228295cebea115e3decbf99d27b5315e63 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 20 Jun 2021 11:27:34 -0400 Subject: [PATCH 0329/2380] Bump asn1 from 0.5.2 to 0.5.3 in /src/rust (#6132) Bumps [asn1](https://github.com/alex/rust-asn1) from 0.5.2 to 0.5.3. - [Release notes](https://github.com/alex/rust-asn1/releases) - [Commits](https://github.com/alex/rust-asn1/compare/0.5.2...0.5.3) --- updated-dependencies: - dependency-name: asn1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 8 ++++---- src/rust/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 1bcce8a65d6c..499f57427da9 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -10,9 +10,9 @@ checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" [[package]] name = "asn1" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed4a28082a1239ef1f2de61139d9421958e92e044190f052021c4b952ee75a" +checksum = "5f56417796de18d5398ee1ba4058d061a9be1bcfdef9a46f73e96e94f5bb21e0" dependencies = [ "asn1_derive", "chrono", @@ -20,9 +20,9 @@ dependencies = [ [[package]] name = "asn1_derive" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b1bb20092bbe014fe3b06d23d86c4d42a422cb42632101231b19092b402536" +checksum = "be3a3360bd6e363428f7ce00ccd251efcd2639b6942ab22e5f322a452aa6f079" dependencies = [ "proc-macro2", "quote", diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index b5729a38b6b2..6ea95be09f67 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] lazy_static = "1" pyo3 = { version = "0.13.1" } -asn1 = { version = "0.5.2", default-features = false, features = ["derive"] } +asn1 = { version = "0.5.3", default-features = false, features = ["derive"] } chrono = { version = "0.4", default-features = false, features = ["alloc"] } ouroboros = "0.9" From 5db5158f3829cd37e12b82c9ca9a4d74cca69a42 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 26 Jun 2021 05:46:35 -0400 Subject: [PATCH 0330/2380] moar linkcheck ignores (#6137) * moar linkcheck ignores * new alpine new python --- .github/workflows/ci.yml | 2 +- docs/conf.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cedaa32e44a5..f52a9faab5f0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -120,7 +120,7 @@ jobs: - {IMAGE: "ubuntu-rolling", TOXENV: "py39"} - {IMAGE: "ubuntu-rolling", TOXENV: "py39-randomorder"} - {IMAGE: "fedora", TOXENV: "py39"} - - {IMAGE: "alpine", TOXENV: "py38"} + - {IMAGE: "alpine", TOXENV: "py39"} name: "${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" timeout-minutes: 20 steps: diff --git a/docs/conf.py b/docs/conf.py index f3b84c4111d6..f79db277abfa 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -200,6 +200,8 @@ r"https://www.secg.org/sec1-v2.pdf", # Incomplete cert chain r"https://e-trust.gosuslugi.ru", + # Expired cert (1 week at time of writing) + r"https://www.cosic.esat.kuleuven.be", ] autosectionlabel_prefix_document = True From 1dfb72a6c29b42dcfb38f0b7ef960a189200ede0 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 26 Jun 2021 13:46:31 -0400 Subject: [PATCH 0331/2380] This is a property (#6139) --- tests/x509/test_x509.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 306fbe246219..f9f0d2fe6091 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -116,7 +116,7 @@ def test_unknown_signature_algorithm(self, backend): ) with pytest.raises(UnsupportedAlgorithm): - crl.signature_hash_algorithm() + crl.signature_hash_algorithm def test_issuer(self, backend): crl = _load_cert( From a6c8b2d9d916bf04d5f873690e9b46062a0df24e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 26 Jun 2021 15:06:41 -0400 Subject: [PATCH 0332/2380] Various cleanups and refactorings from my CRL work (#6140) --- src/rust/src/ocsp.rs | 2 +- src/rust/src/x509.rs | 79 ++++++++++++++++++++++---------------------- 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/src/rust/src/ocsp.rs b/src/rust/src/ocsp.rs index 8bba14b11673..0ef58c34f648 100644 --- a/src/rust/src/ocsp.rs +++ b/src/rust/src/ocsp.rs @@ -116,7 +116,7 @@ impl OCSPRequest { } #[getter] - fn extensions(&mut self, py: pyo3::Python<'_>) -> Result { + fn extensions(&mut self, py: pyo3::Python<'_>) -> pyo3::PyResult { let x509_module = py.import("cryptography.x509")?; x509::parse_and_cache_extensions( py, diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index 36bc590d7863..f9bb51861b79 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -51,7 +51,7 @@ pub(crate) fn parse_and_cache_extensions< cached_extensions: &mut Option, raw_exts: &Option>, parse_ext: F, -) -> Result { +) -> pyo3::PyResult { if let Some(cached) = cached_extensions { return Ok(cached.clone_ref(py)); } @@ -65,15 +65,13 @@ pub(crate) fn parse_and_cache_extensions< x509_module.call_method1("ObjectIdentifier", (raw_ext.extn_id.to_string(),))?; if seen_oids.contains(&raw_ext.extn_id) { - return Err(PyAsn1Error::from(pyo3::PyErr::from_instance( - x509_module.call_method1( - "DuplicateExtension", - ( - format!("Duplicate {} extension found", raw_ext.extn_id), - oid_obj, - ), - )?, - ))); + return Err(pyo3::PyErr::from_instance(x509_module.call_method1( + "DuplicateExtension", + ( + format!("Duplicate {} extension found", raw_ext.extn_id), + oid_obj, + ), + )?)); } let extn_value = match parse_ext(&raw_ext.extn_id, raw_ext.extn_value)? { @@ -237,6 +235,24 @@ fn parse_cp(py: pyo3::Python<'_>, ext_data: &[u8]) -> Result( + py: pyo3::Python<'p>, + dt: &chrono::DateTime, +) -> pyo3::PyResult<&'p pyo3::PyAny> { + let datetime_module = py.import("datetime")?; + datetime_module.call1( + "datetime", + ( + dt.year(), + dt.month(), + dt.day(), + dt.hour(), + dt.minute(), + dt.second(), + ), + ) +} + struct UnvalidatedIA5String<'a>(&'a str); impl<'a> asn1::SimpleAsn1Readable<'a> for UnvalidatedIA5String<'a> { @@ -456,10 +472,10 @@ struct AccessDescription<'a> { access_location: GeneralName<'a>, } -fn parse_authority_key_identifier( - py: pyo3::Python<'_>, +fn parse_authority_key_identifier<'p>( + py: pyo3::Python<'p>, ext_data: &[u8], -) -> Result { +) -> Result<&'p pyo3::PyAny, PyAsn1Error> { let x509_module = py.import("cryptography.x509")?; let aki = asn1::parse_single::>(ext_data)?; let serial = match aki.authority_cert_serial_number { @@ -470,12 +486,10 @@ fn parse_authority_key_identifier( Some(aci) => parse_general_names(py, aci)?, None => py.None(), }; - Ok(x509_module - .call1( - "AuthorityKeyIdentifier", - (aki.key_identifier, issuer, serial), - )? - .to_object(py)) + Ok(x509_module.call1( + "AuthorityKeyIdentifier", + (aki.key_identifier, issuer, serial), + )?) } fn parse_name_attribute( @@ -512,15 +526,14 @@ fn parse_rdn<'a>( .to_object(py)) } -fn parse_name(py: pyo3::Python<'_>, name: Name<'_>) -> Result { +fn parse_name<'p>(py: pyo3::Python<'p>, name: &Name<'_>) -> pyo3::PyResult<&'p pyo3::PyAny> { let x509_module = py.import("cryptography.x509")?; let py_rdns = pyo3::types::PyList::empty(py); - for rdn in name { + for rdn in name.clone() { let py_rdn = parse_rdn(py, rdn)?; py_rdns.append(py_rdn)?; } - let py_name = x509_module.call_method1("Name", (py_rdns,))?.to_object(py); - Ok(py_name) + x509_module.call_method1("Name", (py_rdns,)) } fn ipv4_netmask(num: u32) -> Result { @@ -599,7 +612,7 @@ fn parse_general_name( .call_method1("_init_without_validation", (data.0,))? .to_object(py), GeneralName::DirectoryName(data) => { - let py_name = parse_name(py, data)?; + let py_name = parse_name(py, &data)?; x509_module .call_method1("DirectoryName", (py_name,))? .to_object(py) @@ -952,7 +965,7 @@ fn parse_x509_extension( .call1("BasicConstraints", (bc.ca, bc.path_length))? .to_object(py)) } else if oid == *AUTHORITY_KEY_IDENTIFIER_OID { - Ok(parse_authority_key_identifier(py, ext_data)?) + Ok(parse_authority_key_identifier(py, ext_data)?.to_object(py)) } else if oid == *CRL_DISTRIBUTION_POINTS_OID { let dp = parse_distribution_points(py, ext_data)?; Ok(x509_module @@ -1023,19 +1036,7 @@ pub(crate) fn parse_crl_entry_extension( .to_object(py)) } else if oid == *INVALIDITY_DATE_OID { let time = asn1::parse_single::(ext_data)?; - let time_chrono = time.as_chrono(); - let datetime_module = py.import("datetime")?; - let py_dt = datetime_module.call1( - "datetime", - ( - time_chrono.year(), - time_chrono.month(), - time_chrono.day(), - time_chrono.hour(), - time_chrono.minute(), - time_chrono.second(), - ), - )?; + let py_dt = chrono_to_py(py, time.as_chrono())?; Ok(x509_module.call1("InvalidityDate", (py_dt,))?.to_object(py)) } else { Ok(py.None()) @@ -1073,7 +1074,7 @@ fn parse_crl_extension( .call1("AuthorityInformationAccess", (ads,))? .to_object(py)) } else if oid == *AUTHORITY_KEY_IDENTIFIER_OID { - Ok(parse_authority_key_identifier(py, ext_data)?) + Ok(parse_authority_key_identifier(py, ext_data)?.to_object(py)) } else if oid == *ISSUING_DISTRIBUTION_POINT_OID { let idp = asn1::parse_single::>(ext_data)?; let (full_name, relative_name) = match idp.distribution_point { From c2efb00be2fcce202ca0eaca2dca294e043e49b1 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 26 Jun 2021 16:19:58 -0400 Subject: [PATCH 0333/2380] Simplify public_bytes (#6141) --- src/rust/src/ocsp.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rust/src/ocsp.rs b/src/rust/src/ocsp.rs index 0ef58c34f648..e6436631950f 100644 --- a/src/rust/src/ocsp.rs +++ b/src/rust/src/ocsp.rs @@ -142,15 +142,15 @@ impl OCSPRequest { &self, py: pyo3::Python<'p>, encoding: &pyo3::PyAny, - ) -> Result<&'p pyo3::types::PyBytes, PyAsn1Error> { + ) -> pyo3::PyResult<&'p pyo3::types::PyBytes> { let der = py .import("cryptography.hazmat.primitives.serialization")? .getattr("Encoding")? .getattr("DER")?; if encoding != der { - return Err(PyAsn1Error::from(exceptions::PyValueError::new_err( + return Err(exceptions::PyValueError::new_err( "The only allowed encoding value is Encoding.DER", - ))); + )); } let result = asn1::write_single(self.raw.borrow_value()); Ok(pyo3::types::PyBytes::new(py, &result)) From 8328cea9b4a9b2d41356e9c0c1179be5d063456c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 26 Jun 2021 16:50:57 -0400 Subject: [PATCH 0334/2380] Bump ouroboros from 0.9.3 to 0.9.5 in /src/rust (#6143) Bumps [ouroboros](https://github.com/joshua-maros/ouroboros) from 0.9.3 to 0.9.5. - [Release notes](https://github.com/joshua-maros/ouroboros/releases) - [Commits](https://github.com/joshua-maros/ouroboros/commits) --- updated-dependencies: - dependency-name: ouroboros dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 499f57427da9..6453ed9c698b 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -185,9 +185,9 @@ dependencies = [ [[package]] name = "ouroboros" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f52300b81ac4eeeb6c00c20f7e86556c427d9fb2d92b68fc73c22f331cd15" +checksum = "fbeff60e3e37407a80ead3e9458145b456e978c4068cddbfea6afb48572962ca" dependencies = [ "ouroboros_macro", "stable_deref_trait", @@ -195,9 +195,9 @@ dependencies = [ [[package]] name = "ouroboros_macro" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41db02c8f8731cdd7a72b433c7900cce4bf245465b452c364bfd21f4566ab055" +checksum = "03f2cb802b5bdfdf52f1ffa0b54ce105e4d346e91990dd571f86c91321ad49e2" dependencies = [ "Inflector", "proc-macro-error", From 4161898e59b5acb35cd1c1047c51a7e2d2c75024 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 26 Jun 2021 21:37:37 -0400 Subject: [PATCH 0335/2380] Remove unused gf2m bindings (#6144) * Remove unused gf2m bindings * Update ec.py --- src/_cffi_src/openssl/ec.py | 14 -------------- .../hazmat/bindings/openssl/_conditional.py | 2 -- 2 files changed, 16 deletions(-) diff --git a/src/_cffi_src/openssl/ec.py b/src/_cffi_src/openssl/ec.py index 61d1cb3bb93d..d9c3074cc06e 100644 --- a/src/_cffi_src/openssl/ec.py +++ b/src/_cffi_src/openssl/ec.py @@ -65,18 +65,9 @@ int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *, const EC_POINT *, BIGNUM *, BIGNUM *, BN_CTX *); -int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *, EC_POINT *, - const BIGNUM *, int, BN_CTX *); - -int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *, EC_POINT *, - const BIGNUM *, const BIGNUM *, BN_CTX *); - int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *, const EC_POINT *, BIGNUM *, BIGNUM *, BN_CTX *); -int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *, EC_POINT *, - const BIGNUM *, int, BN_CTX *); - size_t EC_POINT_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t, unsigned char *, size_t, BN_CTX *); @@ -109,14 +100,9 @@ #if defined(OPENSSL_NO_EC2M) static const long Cryptography_HAS_EC2M = 0; -int (*EC_POINT_set_affine_coordinates_GF2m)(const EC_GROUP *, EC_POINT *, - const BIGNUM *, const BIGNUM *, BN_CTX *) = NULL; - int (*EC_POINT_get_affine_coordinates_GF2m)(const EC_GROUP *, const EC_POINT *, BIGNUM *, BIGNUM *, BN_CTX *) = NULL; -int (*EC_POINT_set_compressed_coordinates_GF2m)(const EC_GROUP *, EC_POINT *, - const BIGNUM *, int, BN_CTX *) = NULL; #else static const long Cryptography_HAS_EC2M = 1; #endif diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index ba01169f1e10..124c12d5bfef 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -5,9 +5,7 @@ def cryptography_has_ec2m(): return [ - "EC_POINT_set_affine_coordinates_GF2m", "EC_POINT_get_affine_coordinates_GF2m", - "EC_POINT_set_compressed_coordinates_GF2m", ] From a1dc9f2347de6a99aaa1316b075e669211579019 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 27 Jun 2021 16:33:39 -0400 Subject: [PATCH 0336/2380] separate test vectors (#6145) * separate test vectors * be correct --- docs/development/test-vectors.rst | 14 +++++++++----- tests/x509/test_x509.py | 10 +++++----- ...id_signature.pem => invalid_signature_cert.pem} | 11 ----------- .../x509/custom/invalid_signature_crl.pem | 11 +++++++++++ ...alid_signature.pem => valid_signature_cert.pem} | 11 ----------- .../x509/custom/valid_signature_crl.pem | 11 +++++++++++ 6 files changed, 36 insertions(+), 32 deletions(-) rename vectors/cryptography_vectors/x509/custom/{invalid_signature.pem => invalid_signature_cert.pem} (64%) create mode 100644 vectors/cryptography_vectors/x509/custom/invalid_signature_crl.pem rename vectors/cryptography_vectors/x509/custom/{valid_signature.pem => valid_signature_cert.pem} (64%) create mode 100644 vectors/cryptography_vectors/x509/custom/valid_signature_crl.pem diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index db897f79fbac..c5fc4d4857e8 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -499,11 +499,15 @@ Custom X.509 Certificate Revocation List Vectors * ``crl_ian_aia_aki.pem`` - Contains a CRL with ``IssuerAlternativeName``, ``AuthorityInformationAccess``, ``AuthorityKeyIdentifier`` and ``CRLNumber`` extensions. -* ``valid_signature.pem`` - Contains a CRL with the public key which was used - to generate it. -* ``invalid_signature.pem`` - Contains a CRL with the last signature byte - incremented by 1 to produce an invalid signature, and the public key which - was used to generate it. +* ``valid_signature_crl.pem`` - Contains a CRL with a valid signature. +* ``valid_signature_cert.pem`` - Contains a cert whose public key corresponds + to the private key that produced the signature for + ``valid_signature_crl.pem``. +* ``invalid_signature_crl.pem`` - Contains a CRL with the last signature byte + incremented by 1 to produce an invalid signature. +* ``invalid_signature_cert.pem`` - Contains a cert whose public key corresponds + to the private key that produced the signature for + ``invalid_signature_crl.pem``. * ``crl_delta_crl_indicator.pem`` - Contains a CRL with the ``DeltaCRLIndicator`` extension. * ``crl_idp_fullname_only.pem`` - Contains a CRL with an diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index f9f0d2fe6091..7e4e63e5ae86 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -391,12 +391,12 @@ def test_public_bytes_invalid_encoding(self, backend): def test_verify_bad(self, backend): crl = _load_cert( - os.path.join("x509", "custom", "invalid_signature.pem"), + os.path.join("x509", "custom", "invalid_signature_crl.pem"), x509.load_pem_x509_crl, backend, ) crt = _load_cert( - os.path.join("x509", "custom", "invalid_signature.pem"), + os.path.join("x509", "custom", "invalid_signature_cert.pem"), x509.load_pem_x509_certificate, backend, ) @@ -405,12 +405,12 @@ def test_verify_bad(self, backend): def test_verify_good(self, backend): crl = _load_cert( - os.path.join("x509", "custom", "valid_signature.pem"), + os.path.join("x509", "custom", "valid_signature_crl.pem"), x509.load_pem_x509_crl, backend, ) crt = _load_cert( - os.path.join("x509", "custom", "valid_signature.pem"), + os.path.join("x509", "custom", "valid_signature_cert.pem"), x509.load_pem_x509_certificate, backend, ) @@ -419,7 +419,7 @@ def test_verify_good(self, backend): def test_verify_argument_must_be_a_public_key(self, backend): crl = _load_cert( - os.path.join("x509", "custom", "valid_signature.pem"), + os.path.join("x509", "custom", "valid_signature_crl.pem"), x509.load_pem_x509_crl, backend, ) diff --git a/vectors/cryptography_vectors/x509/custom/invalid_signature.pem b/vectors/cryptography_vectors/x509/custom/invalid_signature_cert.pem similarity index 64% rename from vectors/cryptography_vectors/x509/custom/invalid_signature.pem rename to vectors/cryptography_vectors/x509/custom/invalid_signature_cert.pem index 2fc483d95b5e..0c9589fe174a 100644 --- a/vectors/cryptography_vectors/x509/custom/invalid_signature.pem +++ b/vectors/cryptography_vectors/x509/custom/invalid_signature_cert.pem @@ -1,14 +1,3 @@ ------BEGIN X509 CRL----- -MIIBfTBnAgEBMA0GCSqGSIb3DQEBCwUAMCUxIzAhBgNVBAMMGmludmFsaWRfc2ln -bmF0dXJlIENSTCB0ZXN0Fw0xNzA4MDYwMTQ4MjVaFw0xNzA5MDUwMTQ4MjVaoA4w -DDAKBgNVHRQEAwIBAzANBgkqhkiG9w0BAQsFAAOCAQEAFgGnFwwqviPvA0bfmnvI -c6oGIlq9Bmx/vSH6gwLCuGWn2BrKCWCIJNEtK4hrTfQRASb/uywHvhnByAE2lQlY -9FiefdvXgF5zEah/gV/2A0azvqfvOlPBLzreeoW3Q1fizmip3XN1fXiq8cXBpEYt -SRTJPzgbHvIu50EB2J0hs+rGo1hPTDtZn/r63hcQzUhIWQVmwP+NOzhpUcdnQj3/ -pn6BAJcxyYO2xDoUIncq586k8XVqshEl9xVwJMKhDDk84m/WQZg8i8szgI/muFsm -3vilMgIISrTMYeFIZWAy8rYfKLDMlmAtPRXYqyqOdTsLqz2X3RDMRHMXf1Vf8V31 -vA== ------END X509 CRL----- -----BEGIN CERTIFICATE----- MIICxjCCAa4CCQCETsDmKRzISDANBgkqhkiG9w0BAQsFADAlMSMwIQYDVQQDDBpp bnZhbGlkX3NpZ25hdHVyZSBDUkwgdGVzdDAeFw0xNzA4MDYwMTM5MzRaFw0xNzA5 diff --git a/vectors/cryptography_vectors/x509/custom/invalid_signature_crl.pem b/vectors/cryptography_vectors/x509/custom/invalid_signature_crl.pem new file mode 100644 index 000000000000..54f77382d0be --- /dev/null +++ b/vectors/cryptography_vectors/x509/custom/invalid_signature_crl.pem @@ -0,0 +1,11 @@ +-----BEGIN X509 CRL----- +MIIBfTBnAgEBMA0GCSqGSIb3DQEBCwUAMCUxIzAhBgNVBAMMGmludmFsaWRfc2ln +bmF0dXJlIENSTCB0ZXN0Fw0xNzA4MDYwMTQ4MjVaFw0xNzA5MDUwMTQ4MjVaoA4w +DDAKBgNVHRQEAwIBAzANBgkqhkiG9w0BAQsFAAOCAQEAFgGnFwwqviPvA0bfmnvI +c6oGIlq9Bmx/vSH6gwLCuGWn2BrKCWCIJNEtK4hrTfQRASb/uywHvhnByAE2lQlY +9FiefdvXgF5zEah/gV/2A0azvqfvOlPBLzreeoW3Q1fizmip3XN1fXiq8cXBpEYt +SRTJPzgbHvIu50EB2J0hs+rGo1hPTDtZn/r63hcQzUhIWQVmwP+NOzhpUcdnQj3/ +pn6BAJcxyYO2xDoUIncq586k8XVqshEl9xVwJMKhDDk84m/WQZg8i8szgI/muFsm +3vilMgIISrTMYeFIZWAy8rYfKLDMlmAtPRXYqyqOdTsLqz2X3RDMRHMXf1Vf8V31 +vA== +-----END X509 CRL----- diff --git a/vectors/cryptography_vectors/x509/custom/valid_signature.pem b/vectors/cryptography_vectors/x509/custom/valid_signature_cert.pem similarity index 64% rename from vectors/cryptography_vectors/x509/custom/valid_signature.pem rename to vectors/cryptography_vectors/x509/custom/valid_signature_cert.pem index 9c2180985001..0c9589fe174a 100644 --- a/vectors/cryptography_vectors/x509/custom/valid_signature.pem +++ b/vectors/cryptography_vectors/x509/custom/valid_signature_cert.pem @@ -1,14 +1,3 @@ ------BEGIN X509 CRL----- -MIIBfTBnAgEBMA0GCSqGSIb3DQEBCwUAMCUxIzAhBgNVBAMMGmludmFsaWRfc2ln -bmF0dXJlIENSTCB0ZXN0Fw0xNzA4MDYwMTQ4MjVaFw0xNzA5MDUwMTQ4MjVaoA4w -DDAKBgNVHRQEAwIBAzANBgkqhkiG9w0BAQsFAAOCAQEAFgGnFwwqviPvA0bfmnvI -c6oGIlq9Bmx/vSH6gwLCuGWn2BrKCWCIJNEtK4hrTfQRASb/uywHvhnByAE2lQlY -9FiefdvXgF5zEah/gV/2A0azvqfvOlPBLzreeoW3Q1fizmip3XN1fXiq8cXBpEYt -SRTJPzgbHvIu50EB2J0hs+rGo1hPTDtZn/r63hcQzUhIWQVmwP+NOzhpUcdnQj3/ -pn6BAJcxyYO2xDoUIncq586k8XVqshEl9xVwJMKhDDk84m/WQZg8i8szgI/muFsm -3vilMgIISrTMYeFIZWAy8rYfKLDMlmAtPRXYqyqOdTsLqz2X3RDMRHMXf1Vf8V31 -ug== ------END X509 CRL----- -----BEGIN CERTIFICATE----- MIICxjCCAa4CCQCETsDmKRzISDANBgkqhkiG9w0BAQsFADAlMSMwIQYDVQQDDBpp bnZhbGlkX3NpZ25hdHVyZSBDUkwgdGVzdDAeFw0xNzA4MDYwMTM5MzRaFw0xNzA5 diff --git a/vectors/cryptography_vectors/x509/custom/valid_signature_crl.pem b/vectors/cryptography_vectors/x509/custom/valid_signature_crl.pem new file mode 100644 index 000000000000..3aba91308bf8 --- /dev/null +++ b/vectors/cryptography_vectors/x509/custom/valid_signature_crl.pem @@ -0,0 +1,11 @@ +-----BEGIN X509 CRL----- +MIIBfTBnAgEBMA0GCSqGSIb3DQEBCwUAMCUxIzAhBgNVBAMMGmludmFsaWRfc2ln +bmF0dXJlIENSTCB0ZXN0Fw0xNzA4MDYwMTQ4MjVaFw0xNzA5MDUwMTQ4MjVaoA4w +DDAKBgNVHRQEAwIBAzANBgkqhkiG9w0BAQsFAAOCAQEAFgGnFwwqviPvA0bfmnvI +c6oGIlq9Bmx/vSH6gwLCuGWn2BrKCWCIJNEtK4hrTfQRASb/uywHvhnByAE2lQlY +9FiefdvXgF5zEah/gV/2A0azvqfvOlPBLzreeoW3Q1fizmip3XN1fXiq8cXBpEYt +SRTJPzgbHvIu50EB2J0hs+rGo1hPTDtZn/r63hcQzUhIWQVmwP+NOzhpUcdnQj3/ +pn6BAJcxyYO2xDoUIncq586k8XVqshEl9xVwJMKhDDk84m/WQZg8i8szgI/muFsm +3vilMgIISrTMYeFIZWAy8rYfKLDMlmAtPRXYqyqOdTsLqz2X3RDMRHMXf1Vf8V31 +ug== +-----END X509 CRL----- From fe1f078673dd99da5e2d9cfc9473b243d0013bc7 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 27 Jun 2021 17:45:10 -0400 Subject: [PATCH 0337/2380] modify alternate-rsa-sha1-oid to not contain a negative serial number (#6146) --- docs/development/test-vectors.rst | 5 ++--- tests/x509/test_x509.py | 4 ++-- .../x509/alternate-rsa-sha1-oid.pem | 12 ------------ .../x509/custom/alternate-rsa-sha1-oid.der | Bin 0 -> 455 bytes 4 files changed, 4 insertions(+), 17 deletions(-) delete mode 100644 vectors/cryptography_vectors/x509/alternate-rsa-sha1-oid.pem create mode 100644 vectors/cryptography_vectors/x509/custom/alternate-rsa-sha1-oid.der diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index c5fc4d4857e8..512dfb63799e 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -220,9 +220,8 @@ X.509 * ``e-trust.ru.der`` - A certificate from a `Russian CA`_ signed using the GOST cipher and containing numerous unusual encodings such as NUMERICSTRING in the subject DN. -* ``alternate-rsa-sha1-oid.pem`` - A certificate from an - `unknown signature OID`_ Mozilla bug that uses an alternate signature OID for - RSA with SHA1. +* ``alternate-rsa-sha1-oid.der`` - A certificate that uses an alternate + signature OID for RSA with SHA1. This certificate has an invalid signature. * ``badssl-sct.pem`` - A certificate with the certificate transparency signed certificate timestamp extension. * ``bigoid.pem`` - A certificate with a rather long OID in the diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 7e4e63e5ae86..61aefc6a59b6 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -644,8 +644,8 @@ def test_negative_serial_number(self, backend): def test_alternate_rsa_with_sha1_oid(self, backend): cert = _load_cert( - os.path.join("x509", "alternate-rsa-sha1-oid.pem"), - x509.load_pem_x509_certificate, + os.path.join("x509", "custom", "alternate-rsa-sha1-oid.der"), + x509.load_der_x509_certificate, backend, ) assert isinstance(cert.signature_hash_algorithm, hashes.SHA1) diff --git a/vectors/cryptography_vectors/x509/alternate-rsa-sha1-oid.pem b/vectors/cryptography_vectors/x509/alternate-rsa-sha1-oid.pem deleted file mode 100644 index 807a28b5547f..000000000000 --- a/vectors/cryptography_vectors/x509/alternate-rsa-sha1-oid.pem +++ /dev/null @@ -1,12 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIBwjCCAS+gAwIBAgIQj2d4hVEz0L1DYFVhA9CxCzAJBgUrDgMCHQUAMA8xDTAL -BgNVBAMTBFZQUzEwHhcNMDcwODE4MDkyODUzWhcNMDgwODE3MDkyODUzWjAPMQ0w -CwYDVQQDEwRWUFMxMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaqKn40uaU -DbFL1NXXZ8/b4ZqDJ6eSI5lysMZHfZDs60G3ocbNKofBvURIutabrFuBCB2S5f/z -ICan0LR4uFpGuZ2I/PuVaU8X5fT8gBh7L636cWzHPPScYts00OyywEq381UB7XwX -YuWpM5kUW5rkbq1JV3ystTR/4YnLl48YtQIDAQABoycwJTATBgNVHSUEDDAKBggr -BgEFBQcDATAOBgNVHQ8EBwMFALAAAAAwCQYFKw4DAh0FAAOBgQBuUrU+J2Z5WKcO -VNjJHFUKo8qpbn8jKQZDl2nvVaXCTXQZblz/qxOm4FaGGzJ/m3GybVZNVfdyHg+U -lmDpFpOITkvcyNc3xjJCf2GVBo/VvdtVt7Myq0IQtAi/CXRK22BRNhSt9uu2EcRu -HIXdFWHEzi6eD4PpNw/0X3ID6Gxk4A== ------END CERTIFICATE----- diff --git a/vectors/cryptography_vectors/x509/custom/alternate-rsa-sha1-oid.der b/vectors/cryptography_vectors/x509/custom/alternate-rsa-sha1-oid.der new file mode 100644 index 0000000000000000000000000000000000000000..e8f4d4ca6c7db49708f1bd3938aed0704eec7ffc GIT binary patch literal 455 zcmXqLVmxfn#AvX9nTe5!NsysGy`nYH_`+W2gwRCh3mdr&IN4aW`IwnxSs4uY4S5Z? z*_cCFn1xxw0)h<<KB7iOU2^Mbb8si##& zEawZkaZ)CfYw@X-dG*SgY|hg&--j+ei^1n;$cBs!yEC)_-;H?a=L;jaEAeY~k3?S>km&A<#@@?YGz41drs& bwB8j>JaSHN9)I&obN(;!Ma(a9QXT*RpuMNg literal 0 HcmV?d00001 From 77fb53c75e47f50e09b1b3be3a4d10c7e4e34dc2 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 30 Jun 2021 06:14:42 -0500 Subject: [PATCH 0338/2380] 3.0.0 deprecated func and it isn't useful to us in general (#6148) remove it everywhere and assert on the code/lib/reason --- src/cryptography/hazmat/bindings/openssl/binding.py | 11 ++++------- tests/hazmat/bindings/test_openssl.py | 5 ++--- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py index 6dcec26ab8a3..f651ab672383 100644 --- a/src/cryptography/hazmat/bindings/openssl/binding.py +++ b/src/cryptography/hazmat/bindings/openssl/binding.py @@ -15,15 +15,14 @@ from cryptography.hazmat.bindings.openssl._conditional import CONDITIONAL_NAMES _OpenSSLErrorWithText = collections.namedtuple( - "_OpenSSLErrorWithText", ["code", "lib", "func", "reason", "reason_text"] + "_OpenSSLErrorWithText", ["code", "lib", "reason", "reason_text"] ) class _OpenSSLError(object): - def __init__(self, code, lib, func, reason): + def __init__(self, code, lib, reason): self._code = code self._lib = lib - self._func = func self._reason = reason def _lib_reason_match(self, lib, reason): @@ -31,7 +30,6 @@ def _lib_reason_match(self, lib, reason): code = utils.read_only_property("_code") lib = utils.read_only_property("_lib") - func = utils.read_only_property("_func") reason = utils.read_only_property("_reason") @@ -43,10 +41,9 @@ def _consume_errors(lib): break err_lib = lib.ERR_GET_LIB(code) - err_func = lib.ERR_GET_FUNC(code) err_reason = lib.ERR_GET_REASON(code) - errors.append(_OpenSSLError(code, err_lib, err_func, err_reason)) + errors.append(_OpenSSLError(code, err_lib, err_reason)) return errors @@ -60,7 +57,7 @@ def _errors_with_text(errors): errors_with_text.append( _OpenSSLErrorWithText( - err.code, err.lib, err.func, err.reason, err_text_reason + err.code, err.lib, err.reason, err_text_reason ) ) diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py index 4d1e3b5566d5..1d9b87bad52f 100644 --- a/tests/hazmat/bindings/test_openssl.py +++ b/tests/hazmat/bindings/test_openssl.py @@ -91,11 +91,10 @@ def test_openssl_assert_error_on_stack(self): _openssl_assert(b.lib, False) error = exc_info.value.err_code[0] - # As of 3.0.0 OpenSSL sets func codes to 0, so the combined - # code is a different value + # As of 3.0.0 OpenSSL no longer sets func codes (which we now also + # ignore), so the combined code is a different value assert error.code in (101183626, 50331786) assert error.lib == b.lib.ERR_LIB_EVP - assert error.func == b.lib.EVP_F_EVP_ENCRYPTFINAL_EX assert error.reason == b.lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH assert b"data not multiple of block length" in error.reason_text From 1b281ba52517572af0dc0c81388f8d9189914b98 Mon Sep 17 00:00:00 2001 From: "Nathaniel J. Smith" Date: Wed, 30 Jun 2021 11:25:39 -0700 Subject: [PATCH 0339/2380] Expose a few more OpenSSL functions that are useful for DTLS support (#6138) * Expose a few more OpenSSL functions that are useful for DTLS support * Move BIO_ADDR gunk to proper place * const correct * Throw more #ifdefs at the wall and see if they stick * njsmith used "think about what he's doing" it's probably not very effective * LibreSSL is not my favorite library * Attempt to hide my new undefined symbols * deflake * Give up on trying to check function pointers for NULLness AFAICT it works fine in CFFI's ABI mode, but I can't figure out how to do it in the API mode. --- src/_cffi_src/openssl/bio.py | 17 +++++++++++ src/_cffi_src/openssl/ssl.py | 28 +++++++++++++++++++ .../hazmat/bindings/openssl/_conditional.py | 16 +++++++++++ 3 files changed, 61 insertions(+) diff --git a/src/_cffi_src/openssl/bio.py b/src/_cffi_src/openssl/bio.py index 9310c1beb0f9..248a01e50e60 100644 --- a/src/_cffi_src/openssl/bio.py +++ b/src/_cffi_src/openssl/bio.py @@ -10,6 +10,7 @@ TYPES = """ typedef ... BIO; typedef ... BIO_METHOD; +typedef ... BIO_ADDR; """ FUNCTIONS = """ @@ -37,7 +38,23 @@ int BIO_reset(BIO *); void BIO_set_retry_read(BIO *); void BIO_clear_retry_flags(BIO *); + +BIO_ADDR *BIO_ADDR_new(void); +void BIO_ADDR_free(BIO_ADDR *); """ CUSTOMIZATIONS = """ +#if CRYPTOGRAPHY_IS_LIBRESSL +#include +#include +typedef struct sockaddr BIO_ADDR; + +BIO_ADDR *BIO_ADDR_new(void) { + return malloc(sizeof(struct sockaddr_storage)); +} + +void BIO_ADDR_free(BIO_ADDR *ptr) { + free(ptr); +} +#endif """ diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index 081ef041fa33..34d0283894f3 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -35,6 +35,7 @@ * supported */ static const long Cryptography_HAS_OP_NO_COMPRESSION; +static const long Cryptography_HAS_OP_NO_RENEGOTIATION; static const long Cryptography_HAS_SSL_OP_MSIE_SSLV2_RSA_PADDING; static const long Cryptography_HAS_SSL_SET_SSL_CTX; static const long Cryptography_HAS_SSL_OP_NO_TICKET; @@ -43,6 +44,7 @@ static const long Cryptography_HAS_SET_CERT_CB; static const long Cryptography_HAS_CUSTOM_EXT; static const long Cryptography_HAS_SRTP; +static const long Cryptography_HAS_DTLS_GET_DATA_MTU; static const long SSL_FILETYPE_PEM; static const long SSL_FILETYPE_ASN1; @@ -64,6 +66,7 @@ static const long SSL_OP_NO_TLSv1_3; static const long SSL_OP_NO_DTLSv1; static const long SSL_OP_NO_DTLSv1_2; +static const long SSL_OP_NO_RENEGOTIATION; static const long SSL_OP_NO_COMPRESSION; static const long SSL_OP_SINGLE_DH_USE; static const long SSL_OP_EPHEMERAL_RSA; @@ -225,6 +228,13 @@ unsigned char *, unsigned int * )); +void SSL_CTX_set_cookie_verify_cb(SSL_CTX *, + int (*)( + SSL *, + const unsigned char *, + unsigned int + )); + long SSL_CTX_get_read_ahead(SSL_CTX *); long SSL_CTX_set_read_ahead(SSL_CTX *, long); @@ -468,6 +478,10 @@ long DTLSv1_handle_timeout(SSL *); long DTLS_set_link_mtu(SSL *, long); long DTLS_get_link_min_mtu(SSL *); +long SSL_set_mtu(SSL *, long); +int DTLSv1_listen(SSL *, BIO_ADDR *); +size_t DTLS_get_data_mtu(SSL *); + /* Custom extensions. */ typedef int (*custom_ext_add_cb)(SSL *, unsigned int, @@ -556,6 +570,13 @@ static const long Cryptography_HAS_NEXTPROTONEG = 0; static const long Cryptography_HAS_ALPN = 1; +#ifdef SSL_OP_NO_RENEGOTIATION +static const long Cryptography_HAS_OP_NO_RENEGOTIATION = 1; +#else +static const long Cryptography_HAS_OP_NO_RENEGOTIATION = 0; +static const long SSL_OP_NO_RENEGOTIATION = 0; +#endif + #if CRYPTOGRAPHY_IS_LIBRESSL void (*SSL_CTX_set_cert_cb)(SSL_CTX *, int (*)(SSL *, void *), void *) = NULL; void (*SSL_set_cert_cb)(SSL *, int (*)(SSL *, void *), void *) = NULL; @@ -594,6 +615,13 @@ long (*DTLS_get_link_min_mtu)(SSL *) = NULL; #endif +#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 +static const long Cryptography_HAS_DTLS_GET_DATA_MTU = 0; +size_t (*DTLS_get_data_mtu)(SSL *) = NULL; +#else +static const long Cryptography_HAS_DTLS_GET_DATA_MTU = 1; +#endif + static const long Cryptography_HAS_DTLS = 1; /* Wrap DTLSv1_get_timeout to avoid cffi to handle a 'struct timeval'. */ long Cryptography_DTLSv1_get_timeout(SSL *ssl, time_t *ptv_sec, diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index 124c12d5bfef..912aff302607 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -242,6 +242,18 @@ def cryptography_has_providers(): ] +def cryptography_has_op_no_renegotiation(): + return [ + "SSL_OP_NO_RENEGOTIATION", + ] + + +def cryptography_has_dtls_get_data_mtu(): + return [ + "DTLS_get_data_mtu", + ] + + # This is a mapping of # {condition: function-returning-names-dependent-on-that-condition} so we can # loop over them and delete unsupported names at runtime. It will be removed @@ -289,4 +301,8 @@ def cryptography_has_providers(): "Cryptography_HAS_SRTP": cryptography_has_srtp, "Cryptography_HAS_GET_PROTO_VERSION": cryptography_has_get_proto_version, "Cryptography_HAS_PROVIDERS": cryptography_has_providers, + "Cryptography_HAS_OP_NO_RENEGOTIATION": ( + cryptography_has_op_no_renegotiation + ), + "Cryptography_HAS_DTLS_GET_DATA_MTU": cryptography_has_dtls_get_data_mtu, } From 50ec692749b7e2e62685b443f5e629627b03987e Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 30 Jun 2021 21:12:46 -0500 Subject: [PATCH 0340/2380] remove unneeded binding (#6150) --- src/_cffi_src/openssl/err.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/_cffi_src/openssl/err.py b/src/_cffi_src/openssl/err.py index 54dd1e44c43d..b81247ac7ed4 100644 --- a/src/_cffi_src/openssl/err.py +++ b/src/_cffi_src/openssl/err.py @@ -41,7 +41,6 @@ void ERR_put_error(int, int, int, const char *, int); int ERR_GET_LIB(unsigned long); -int ERR_GET_FUNC(unsigned long); int ERR_GET_REASON(unsigned long); """ From 95ba73be85c3887d5d4388891fc68839a828e02f Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 30 Jun 2021 21:43:45 -0500 Subject: [PATCH 0341/2380] reduce test duplication (#6151) --- tests/x509/test_x509.py | 568 +++++++++++----------------------------- 1 file changed, 159 insertions(+), 409 deletions(-) diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 61aefc6a59b6..1a185ffddd0d 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -3100,15 +3100,100 @@ def test_build_cert_with_rsa_key_too_small(self, backend): ) ] ), + x509.AuthorityInformationAccess( + [ + x509.AccessDescription( + AuthorityInformationAccessOID.OCSP, + x509.UniformResourceIdentifier( + "http://ocsp.domain.com" + ), + ), + x509.AccessDescription( + AuthorityInformationAccessOID.CA_ISSUERS, + x509.UniformResourceIdentifier( + "http://domain.com/ca.crt" + ), + ), + ] + ), + x509.SubjectInformationAccess( + [ + x509.AccessDescription( + SubjectInformationAccessOID.CA_REPOSITORY, + x509.UniformResourceIdentifier("http://ca.domain.com"), + ), + ] + ), + x509.AuthorityKeyIdentifier( + b"\xc3\x9c\xf3\xfc\xd3F\x084\xbb\xceF\x7f\xa0|[\xf3\xe2\x08" + b"\xcbY", + None, + None, + ), + x509.AuthorityKeyIdentifier( + b"\xc3\x9c\xf3\xfc\xd3F\x084\xbb\xceF\x7f\xa0|[\xf3\xe2\x08" + b"\xcbY", + [ + x509.DirectoryName( + x509.Name( + [ + x509.NameAttribute( + NameOID.ORGANIZATION_NAME, "PyCA" + ), + x509.NameAttribute( + NameOID.COMMON_NAME, "cryptography CA" + ), + ] + ) + ) + ], + 333, + ), + x509.AuthorityKeyIdentifier( + None, + [ + x509.DirectoryName( + x509.Name( + [ + x509.NameAttribute( + NameOID.ORGANIZATION_NAME, "PyCA" + ), + x509.NameAttribute( + NameOID.COMMON_NAME, "cryptography CA" + ), + ] + ) + ) + ], + 333, + ), + x509.KeyUsage( + digital_signature=True, + content_commitment=True, + key_encipherment=False, + data_encipherment=False, + key_agreement=False, + key_cert_sign=True, + crl_sign=False, + encipher_only=False, + decipher_only=False, + ), + x509.OCSPNoCheck(), + x509.SubjectKeyIdentifier, ], ) - def test_ext(self, add_ext, backend): + def test_extensions(self, add_ext, backend): issuer_private_key = RSA_KEY_2048.private_key(backend) subject_private_key = RSA_KEY_2048.private_key(backend) not_valid_before = datetime.datetime(2002, 1, 1, 12, 1) not_valid_after = datetime.datetime(2030, 12, 31, 8, 30) + if add_ext is x509.SubjectKeyIdentifier: + add_ext = x509.SubjectKeyIdentifier.from_public_key( + subject_private_key.public_key() + ) + cert = ( x509.CertificateBuilder() .subject_name( @@ -3129,56 +3214,6 @@ def test_ext(self, add_ext, backend): assert ext.critical is False assert ext.value == add_ext - def test_key_usage(self, backend): - issuer_private_key = RSA_KEY_2048.private_key(backend) - subject_private_key = RSA_KEY_2048.private_key(backend) - - not_valid_before = datetime.datetime(2002, 1, 1, 12, 1) - not_valid_after = datetime.datetime(2030, 12, 31, 8, 30) - - cert = ( - x509.CertificateBuilder() - .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) - ) - .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) - ) - .not_valid_before(not_valid_before) - .not_valid_after(not_valid_after) - .public_key(subject_private_key.public_key()) - .serial_number(123) - .add_extension( - x509.KeyUsage( - digital_signature=True, - content_commitment=True, - key_encipherment=False, - data_encipherment=False, - key_agreement=False, - key_cert_sign=True, - crl_sign=False, - encipher_only=False, - decipher_only=False, - ), - critical=False, - ) - .sign(issuer_private_key, hashes.SHA256(), backend) - ) - - ext = cert.extensions.get_extension_for_oid(ExtensionOID.KEY_USAGE) - assert ext.critical is False - assert ext.value == x509.KeyUsage( - digital_signature=True, - content_commitment=True, - key_encipherment=False, - data_encipherment=False, - key_agreement=False, - key_cert_sign=True, - crl_sign=False, - encipher_only=False, - decipher_only=False, - ) - def test_build_ca_request_with_path_length_none(self, backend): private_key = RSA_KEY_2048.private_key(backend) @@ -3687,82 +3722,6 @@ def test_add_unsupported_extension(self, backend): with pytest.raises(NotImplementedError): builder.sign(private_key, hashes.SHA256(), backend) - def test_key_usage(self, backend): - private_key = RSA_KEY_2048.private_key(backend) - builder = x509.CertificateSigningRequestBuilder() - request = ( - builder.subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) - ) - .add_extension( - x509.KeyUsage( - digital_signature=True, - content_commitment=True, - key_encipherment=False, - data_encipherment=False, - key_agreement=False, - key_cert_sign=True, - crl_sign=False, - encipher_only=False, - decipher_only=False, - ), - critical=False, - ) - .sign(private_key, hashes.SHA256(), backend) - ) - assert len(request.extensions) == 1 - ext = request.extensions.get_extension_for_oid(ExtensionOID.KEY_USAGE) - assert ext.critical is False - assert ext.value == x509.KeyUsage( - digital_signature=True, - content_commitment=True, - key_encipherment=False, - data_encipherment=False, - key_agreement=False, - key_cert_sign=True, - crl_sign=False, - encipher_only=False, - decipher_only=False, - ) - - def test_key_usage_key_agreement_bit(self, backend): - private_key = RSA_KEY_2048.private_key(backend) - builder = x509.CertificateSigningRequestBuilder() - request = ( - builder.subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) - ) - .add_extension( - x509.KeyUsage( - digital_signature=False, - content_commitment=False, - key_encipherment=False, - data_encipherment=False, - key_agreement=True, - key_cert_sign=True, - crl_sign=False, - encipher_only=False, - decipher_only=True, - ), - critical=False, - ) - .sign(private_key, hashes.SHA256(), backend) - ) - assert len(request.extensions) == 1 - ext = request.extensions.get_extension_for_oid(ExtensionOID.KEY_USAGE) - assert ext.critical is False - assert ext.value == x509.KeyUsage( - digital_signature=False, - content_commitment=False, - key_encipherment=False, - data_encipherment=False, - key_agreement=True, - key_cert_sign=True, - crl_sign=False, - encipher_only=False, - decipher_only=True, - ) - def test_add_two_extensions(self, backend): private_key = RSA_KEY_2048.private_key(backend) builder = x509.CertificateSigningRequestBuilder() @@ -3873,62 +3832,94 @@ def test_set_subject_twice(self): x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) ) - def test_subject_alt_names(self, backend): + @pytest.mark.parametrize( + "add_ext", + [ + x509.KeyUsage( + digital_signature=True, + content_commitment=True, + key_encipherment=False, + data_encipherment=False, + key_agreement=False, + key_cert_sign=True, + crl_sign=False, + encipher_only=False, + decipher_only=False, + ), + x509.KeyUsage( + digital_signature=False, + content_commitment=False, + key_encipherment=False, + data_encipherment=False, + key_agreement=True, + key_cert_sign=True, + crl_sign=False, + encipher_only=False, + decipher_only=True, + ), + x509.SubjectAlternativeName( + [ + x509.DNSName("example.com"), + x509.DNSName("*.example.com"), + x509.RegisteredID(x509.ObjectIdentifier("1.2.3.4.5.6.7")), + x509.DirectoryName( + x509.Name( + [ + x509.NameAttribute( + NameOID.COMMON_NAME, "PyCA" + ), + x509.NameAttribute( + NameOID.ORGANIZATION_NAME, + "We heart UTF8!\u2122", + ), + ] + ) + ), + x509.IPAddress(ipaddress.ip_address("127.0.0.1")), + x509.IPAddress(ipaddress.ip_address("ff::")), + x509.OtherName( + type_id=x509.ObjectIdentifier("1.2.3.3.3.3"), + value=b"0\x03\x02\x01\x05", + ), + x509.RFC822Name("test@example.com"), + x509.RFC822Name("email"), + x509.RFC822Name("email@xn--eml-vla4c.com"), + x509.UniformResourceIdentifier( + "https://xn--80ato2c.cryptography" + ), + x509.UniformResourceIdentifier( + "gopher://cryptography:70/some/path" + ), + ] + ), + x509.ExtendedKeyUsage( + [ + ExtendedKeyUsageOID.CLIENT_AUTH, + ExtendedKeyUsageOID.SERVER_AUTH, + ExtendedKeyUsageOID.CODE_SIGNING, + ] + ), + ], + ) + def test_extensions(self, add_ext, backend): private_key = RSA_KEY_2048.private_key(backend) - san = x509.SubjectAlternativeName( - [ - x509.DNSName("example.com"), - x509.DNSName("*.example.com"), - x509.RegisteredID(x509.ObjectIdentifier("1.2.3.4.5.6.7")), - x509.DirectoryName( - x509.Name( - [ - x509.NameAttribute(NameOID.COMMON_NAME, "PyCA"), - x509.NameAttribute( - NameOID.ORGANIZATION_NAME, - "We heart UTF8!\u2122", - ), - ] - ) - ), - x509.IPAddress(ipaddress.ip_address("127.0.0.1")), - x509.IPAddress(ipaddress.ip_address("ff::")), - x509.OtherName( - type_id=x509.ObjectIdentifier("1.2.3.3.3.3"), - value=b"0\x03\x02\x01\x05", - ), - x509.RFC822Name("test@example.com"), - x509.RFC822Name("email"), - x509.RFC822Name("email@xn--eml-vla4c.com"), - x509.UniformResourceIdentifier( - "https://xn--80ato2c.cryptography" - ), - x509.UniformResourceIdentifier( - "gopher://cryptography:70/some/path" - ), - ] - ) - csr = ( x509.CertificateSigningRequestBuilder() .subject_name( x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, "SAN")]) ) .add_extension( - san, + add_ext, critical=False, ) .sign(private_key, hashes.SHA256(), backend) ) assert len(csr.extensions) == 1 - ext = csr.extensions.get_extension_for_oid( - ExtensionOID.SUBJECT_ALTERNATIVE_NAME - ) + ext = csr.extensions.get_extension_for_class(type(add_ext)) assert not ext.critical - assert ext.oid == ExtensionOID.SUBJECT_ALTERNATIVE_NAME - assert ext.value == san + assert ext.value == add_ext def test_invalid_asn1_othername(self, backend): private_key = RSA_KEY_2048.private_key(backend) @@ -3972,30 +3963,6 @@ def test_subject_alt_name_unsupported_general_name(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA256(), backend) - def test_extended_key_usage(self, backend): - private_key = RSA_KEY_2048.private_key(backend) - eku = x509.ExtendedKeyUsage( - [ - ExtendedKeyUsageOID.CLIENT_AUTH, - ExtendedKeyUsageOID.SERVER_AUTH, - ExtendedKeyUsageOID.CODE_SIGNING, - ] - ) - builder = x509.CertificateSigningRequestBuilder() - request = ( - builder.subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) - ) - .add_extension(eku, critical=False) - .sign(private_key, hashes.SHA256(), backend) - ) - - ext = request.extensions.get_extension_for_oid( - ExtensionOID.EXTENDED_KEY_USAGE - ) - assert ext.critical is False - assert ext.value == eku - def test_rsa_key_too_small(self, backend): private_key = RSA_KEY_512.private_key(backend) builder = x509.CertificateSigningRequestBuilder() @@ -4006,223 +3973,6 @@ def test_rsa_key_too_small(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA512(), backend) - def test_build_cert_with_aia(self, backend): - issuer_private_key = RSA_KEY_2048.private_key(backend) - subject_private_key = RSA_KEY_2048.private_key(backend) - - not_valid_before = datetime.datetime(2002, 1, 1, 12, 1) - not_valid_after = datetime.datetime(2030, 12, 31, 8, 30) - - aia = x509.AuthorityInformationAccess( - [ - x509.AccessDescription( - AuthorityInformationAccessOID.OCSP, - x509.UniformResourceIdentifier("http://ocsp.domain.com"), - ), - x509.AccessDescription( - AuthorityInformationAccessOID.CA_ISSUERS, - x509.UniformResourceIdentifier("http://domain.com/ca.crt"), - ), - ] - ) - - builder = ( - x509.CertificateBuilder() - .serial_number(777) - .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) - ) - .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) - ) - .public_key(subject_private_key.public_key()) - .add_extension(aia, critical=False) - .not_valid_before(not_valid_before) - .not_valid_after(not_valid_after) - ) - - cert = builder.sign(issuer_private_key, hashes.SHA256(), backend) - - ext = cert.extensions.get_extension_for_oid( - ExtensionOID.AUTHORITY_INFORMATION_ACCESS - ) - assert ext.value == aia - - def test_build_cert_with_sia(self, backend): - issuer_private_key = RSA_KEY_2048.private_key(backend) - subject_private_key = RSA_KEY_2048.private_key(backend) - - not_valid_before = datetime.datetime(2002, 1, 1, 12, 1) - not_valid_after = datetime.datetime(2030, 12, 31, 8, 30) - - sia = x509.SubjectInformationAccess( - [ - x509.AccessDescription( - SubjectInformationAccessOID.CA_REPOSITORY, - x509.UniformResourceIdentifier("http://ca.domain.com"), - ), - ] - ) - - builder = ( - x509.CertificateBuilder() - .serial_number(777) - .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) - ) - .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) - ) - .public_key(subject_private_key.public_key()) - .add_extension(sia, critical=False) - .not_valid_before(not_valid_before) - .not_valid_after(not_valid_after) - ) - - cert = builder.sign(issuer_private_key, hashes.SHA256(), backend) - - ext = cert.extensions.get_extension_for_oid( - ExtensionOID.SUBJECT_INFORMATION_ACCESS - ) - assert ext.value == sia - - def test_build_cert_with_ski(self, backend): - issuer_private_key = RSA_KEY_2048.private_key(backend) - subject_private_key = RSA_KEY_2048.private_key(backend) - - not_valid_before = datetime.datetime(2002, 1, 1, 12, 1) - not_valid_after = datetime.datetime(2030, 12, 31, 8, 30) - - ski = x509.SubjectKeyIdentifier.from_public_key( - subject_private_key.public_key() - ) - - builder = ( - x509.CertificateBuilder() - .serial_number(777) - .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) - ) - .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) - ) - .public_key(subject_private_key.public_key()) - .add_extension(ski, critical=False) - .not_valid_before(not_valid_before) - .not_valid_after(not_valid_after) - ) - - cert = builder.sign(issuer_private_key, hashes.SHA256(), backend) - - ext = cert.extensions.get_extension_for_oid( - ExtensionOID.SUBJECT_KEY_IDENTIFIER - ) - assert ext.value == ski - - @pytest.mark.parametrize( - "aki", - [ - x509.AuthorityKeyIdentifier( - b"\xc3\x9c\xf3\xfc\xd3F\x084\xbb\xceF\x7f\xa0|[\xf3\xe2\x08" - b"\xcbY", - None, - None, - ), - x509.AuthorityKeyIdentifier( - b"\xc3\x9c\xf3\xfc\xd3F\x084\xbb\xceF\x7f\xa0|[\xf3\xe2\x08" - b"\xcbY", - [ - x509.DirectoryName( - x509.Name( - [ - x509.NameAttribute( - NameOID.ORGANIZATION_NAME, "PyCA" - ), - x509.NameAttribute( - NameOID.COMMON_NAME, "cryptography CA" - ), - ] - ) - ) - ], - 333, - ), - x509.AuthorityKeyIdentifier( - None, - [ - x509.DirectoryName( - x509.Name( - [ - x509.NameAttribute( - NameOID.ORGANIZATION_NAME, "PyCA" - ), - x509.NameAttribute( - NameOID.COMMON_NAME, "cryptography CA" - ), - ] - ) - ) - ], - 333, - ), - ], - ) - def test_build_cert_with_aki(self, aki, backend): - issuer_private_key = RSA_KEY_2048.private_key(backend) - subject_private_key = RSA_KEY_2048.private_key(backend) - - not_valid_before = datetime.datetime(2002, 1, 1, 12, 1) - not_valid_after = datetime.datetime(2030, 12, 31, 8, 30) - - builder = ( - x509.CertificateBuilder() - .serial_number(777) - .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) - ) - .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) - ) - .public_key(subject_private_key.public_key()) - .add_extension(aki, critical=False) - .not_valid_before(not_valid_before) - .not_valid_after(not_valid_after) - ) - - cert = builder.sign(issuer_private_key, hashes.SHA256(), backend) - - ext = cert.extensions.get_extension_for_oid( - ExtensionOID.AUTHORITY_KEY_IDENTIFIER - ) - assert ext.value == aki - - def test_ocsp_nocheck(self, backend): - issuer_private_key = RSA_KEY_2048.private_key(backend) - subject_private_key = RSA_KEY_2048.private_key(backend) - - not_valid_before = datetime.datetime(2002, 1, 1, 12, 1) - not_valid_after = datetime.datetime(2030, 12, 31, 8, 30) - - builder = ( - x509.CertificateBuilder() - .serial_number(777) - .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) - ) - .subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) - ) - .public_key(subject_private_key.public_key()) - .add_extension(x509.OCSPNoCheck(), critical=False) - .not_valid_before(not_valid_before) - .not_valid_after(not_valid_after) - ) - - cert = builder.sign(issuer_private_key, hashes.SHA256(), backend) - - ext = cert.extensions.get_extension_for_oid(ExtensionOID.OCSP_NO_CHECK) - assert isinstance(ext.value, x509.OCSPNoCheck) - class TestDSACertificate(object): def test_load_dsa_cert(self, backend): From 0034926f2cca02258f50e9faccb90ec344790159 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 1 Jul 2021 05:51:55 -0500 Subject: [PATCH 0342/2380] add invalid time CRL vector (#6152) * add invalid time CRL vector * more words --- docs/development/test-vectors.rst | 2 ++ tests/x509/test_x509.py | 10 ++++++++++ .../x509/custom/crl_invalid_time.der | Bin 0 -> 388 bytes 3 files changed, 12 insertions(+) create mode 100644 vectors/cryptography_vectors/x509/custom/crl_invalid_time.der diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index 512dfb63799e..ee8e617edd4d 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -536,6 +536,8 @@ Custom X.509 Certificate Revocation List Vectors * ``crl_unrecognized_extension.der`` - Contains a CRL containing an unsupported extension type. The OID was encoded as "1.2.3.4.5" with an ``extnValue`` of ``abcdef``. +* ``crl_invalid_time.der`` - Contains a CRL with an invalid ``GeneralizedTime`` + value in ``thisUpdate``. The signature on this CRL is invalid. X.509 OCSP Test Vectors ~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 1a185ffddd0d..fc36d5f4111b 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -106,6 +106,16 @@ def test_invalid_der(self, backend): with pytest.raises(ValueError): x509.load_der_x509_crl(b"notacrl", backend) + def test_invalid_time(self, backend): + crl = _load_cert( + os.path.join("x509", "custom", "crl_invalid_time.der"), + x509.load_der_x509_crl, + backend, + ) + + with pytest.raises(ValueError, match="18102813516Z"): + crl.last_update + def test_unknown_signature_algorithm(self, backend): crl = _load_cert( os.path.join( diff --git a/vectors/cryptography_vectors/x509/custom/crl_invalid_time.der b/vectors/cryptography_vectors/x509/custom/crl_invalid_time.der new file mode 100644 index 0000000000000000000000000000000000000000..a0122954944728fe8c91a805763830d706433bc3 GIT binary patch literal 388 zcmXqLVr($TVq#=8;AP{~YV&CO&dbQi&B|aPY$#~J&&C|e!py_rS(KTVsNn1<&SPj{ zXkcVvXl!a|7A4LL719>3s0u=)#0|lTCSs6yg|14q#A`AEz@)~f1%;4f-38-{- zY-0S6W({)_BO}B5h|~$!XC`?Yx|^)AWRsg=^5dgF^S8Mt1=f7sf!VjLv006AJm(KtI literal 0 HcmV?d00001 From 665126dd2b78c46f622389dfe6fb4c2d19f006b4 Mon Sep 17 00:00:00 2001 From: James Hilliard Date: Sat, 3 Jul 2021 18:26:36 -0600 Subject: [PATCH 0343/2380] Disable fail-fast in tests. (#6155) This makes it easier to isolate regressions by running all tests even if one fails. --- .github/workflows/ci.yml | 6 ++++++ .github/workflows/wheel-builder.yml | 3 +++ 2 files changed, 9 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f52a9faab5f0..46450d94d0c7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,7 @@ jobs: linux: runs-on: ubuntu-latest strategy: + fail-fast: false matrix: PYTHON: - {VERSION: "3.9", TOXENV: "flake,rust,docs", COVERAGE: "false"} @@ -108,6 +109,7 @@ jobs: runs-on: ubuntu-latest container: ghcr.io/pyca/cryptography-runner-${{ matrix.IMAGE.IMAGE }} strategy: + fail-fast: false matrix: IMAGE: - {IMAGE: "centos8", TOXENV: "py36"} @@ -154,6 +156,7 @@ jobs: linux-rust: runs-on: ubuntu-latest strategy: + fail-fast: false matrix: PYTHON: - {VERSION: "3.9", TOXENV: "py39"} @@ -267,6 +270,7 @@ jobs: macos: runs-on: macos-latest strategy: + fail-fast: false matrix: PYTHON: - {VERSION: "3.6", TOXENV: "py36", EXTRA_CFLAGS: ""} @@ -327,6 +331,7 @@ jobs: windows: runs-on: windows-latest strategy: + fail-fast: false matrix: WINDOWS: - {ARCH: 'x86', WINDOWS: 'win32', RUST_TRIPLE: 'i686-pc-windows-msvc'} @@ -391,6 +396,7 @@ jobs: linux-downstream: runs-on: ubuntu-latest strategy: + fail-fast: false matrix: DOWNSTREAM: - paramiko diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 160ba8f0e6ca..29a1e154f473 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -10,6 +10,7 @@ jobs: runs-on: ubuntu-latest container: ghcr.io/pyca/${{ matrix.MANYLINUX.CONTAINER }} strategy: + fail-fast: false matrix: PYTHON: - { VERSION: "cp36-cp36m", PATH: "/opt/python/cp36-cp36m/bin/python", ABI_VERSION: 'cp36' } @@ -59,6 +60,7 @@ jobs: macos: runs-on: macos-latest strategy: + fail-fast: false matrix: PYTHON: - VERSION: '3.8' @@ -112,6 +114,7 @@ jobs: windows: runs-on: windows-latest strategy: + fail-fast: false matrix: WINDOWS: - {ARCH: 'x86', WINDOWS: 'win32', RUST_TRIPLE: 'i686-pc-windows-msvc'} From 120e804d8a36b4adfa71b2e5700a773ff9cfd19a Mon Sep 17 00:00:00 2001 From: James Hilliard Date: Sun, 4 Jul 2021 17:01:10 -0600 Subject: [PATCH 0344/2380] pyo3: bump to version 0.14.1 (#6154) --- src/rust/Cargo.lock | 74 ++++++------------- src/rust/Cargo.toml | 2 +- src/rust/src/ocsp.rs | 16 ++--- src/rust/src/x509.rs | 166 ++++++++++++++++++++++++------------------- 4 files changed, 124 insertions(+), 134 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 6453ed9c698b..8ebd9ff10d26 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -68,27 +68,6 @@ dependencies = [ "pyo3", ] -[[package]] -name = "ctor" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "ghost" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5bcf1bbeab73aa4cf2fde60a846858dc036163c7c33bec309f8d17de785479" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "indoc" version = "0.3.6" @@ -121,28 +100,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "inventory" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f0f7efb804ec95e33db9ad49e4252f049e37e8b0a4652e3cd61f7999f2eff7f" -dependencies = [ - "ctor", - "ghost", - "inventory-impl", -] - -[[package]] -name = "inventory-impl" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75c094e94816723ab936484666968f5b58060492e880f3c8d00489a1e244fa51" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -183,6 +140,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "once_cell" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" + [[package]] name = "ouroboros" version = "0.9.5" @@ -291,26 +254,34 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.13.2" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4837b8e8e18a102c23f79d1e9a110b597ea3b684c95e874eb1ad88f8683109c3" +checksum = "338f7f3701e11fd7f76508c91fbcaabc982564bcaf4d1ca7e1574ff2b4778aec" dependencies = [ "cfg-if", - "ctor", "indoc", - "inventory", "libc", "parking_lot", "paste", + "pyo3-build-config", "pyo3-macros", "unindent", ] +[[package]] +name = "pyo3-build-config" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb2e98cc9ccc83d4f7115c8f925e0057e88c8d324b1bc4c2db4a7270c06ac9d" +dependencies = [ + "once_cell", +] + [[package]] name = "pyo3-macros" -version = "0.13.2" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47f2c300ceec3e58064fd5f8f5b61230f2ffd64bde4970c81fdd0563a2db1bb" +checksum = "cfb8671a42d0ecc4bec8cc107ae96d49292ca20cd1968e09b98af4aafd516adf" dependencies = [ "pyo3-macros-backend", "quote", @@ -319,11 +290,12 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.13.2" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87b097e5d84fcbe3e167f400fbedd657820a375b034c78bd852050749a575d66" +checksum = "9addf6dc422f05d4949cc0990195ee74fa43e3c3780cc9a1972fe9e7b68a9f48" dependencies = [ "proc-macro2", + "pyo3-build-config", "quote", "syn", ] diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 6ea95be09f67..f402456859ea 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] lazy_static = "1" -pyo3 = { version = "0.13.1" } +pyo3 = { version = "0.14.1" } asn1 = { version = "0.5.3", default-features = false, features = ["derive"] } chrono = { version = "0.4", default-features = false, features = ["alloc"] } ouroboros = "0.9" diff --git a/src/rust/src/ocsp.rs b/src/rust/src/ocsp.rs index e6436631950f..e097aacc852e 100644 --- a/src/rust/src/ocsp.rs +++ b/src/rust/src/ocsp.rs @@ -94,17 +94,14 @@ impl OCSPRequest { let hashes = py.import("cryptography.hazmat.primitives.hashes")?; match OIDS_TO_HASH.get(&cert_id.hash_algorithm.oid) { - Some(alg_name) => Ok(hashes.call0(alg_name)?), + Some(alg_name) => Ok(hashes.getattr(alg_name)?.call0()?), None => { let exceptions = py.import("cryptography.exceptions")?; Err(PyAsn1Error::from(pyo3::PyErr::from_instance( - exceptions.call1( - "UnsupportedAlgorithm", - (format!( - "Signature algorithm OID: {} not recognized", - cert_id.hash_algorithm.oid - ),), - )?, + exceptions.getattr("UnsupportedAlgorithm")?.call1((format!( + "Signature algorithm OID: {} not recognized", + cert_id.hash_algorithm.oid + ),))?, ))) } } @@ -233,7 +230,8 @@ fn parse_ocsp_singleresp_extension( let contents = asn1::parse_single::<&[u8]>(ext_data)?; let scts = x509::parse_scts(py, contents, x509::LogEntryType::Certificate)?; Ok(x509_module - .call1("SignedCertificateTimestamps", (scts,))? + .getattr("SignedCertificateTimestamps")? + .call1((scts,))? .to_object(py)) } else { x509::parse_crl_entry_extension(py, der_oid, ext_data) diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index f9bb51861b79..f23ae7dd7e81 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -240,17 +240,14 @@ fn chrono_to_py<'p>( dt: &chrono::DateTime, ) -> pyo3::PyResult<&'p pyo3::PyAny> { let datetime_module = py.import("datetime")?; - datetime_module.call1( - "datetime", - ( - dt.year(), - dt.month(), - dt.day(), - dt.hour(), - dt.minute(), - dt.second(), - ), - ) + datetime_module.getattr("datetime")?.call1(( + dt.year(), + dt.month(), + dt.day(), + dt.hour(), + dt.minute(), + dt.second(), + )) } struct UnvalidatedIA5String<'a>(&'a str); @@ -377,10 +374,8 @@ fn parse_distribution_point( }; let x509_module = py.import("cryptography.x509")?; Ok(x509_module - .call1( - "DistributionPoint", - (full_name, relative_name, reasons, crl_issuer), - )? + .getattr("DistributionPoint")? + .call1((full_name, relative_name, reasons, crl_issuer))? .to_object(py)) } @@ -486,10 +481,11 @@ fn parse_authority_key_identifier<'p>( Some(aci) => parse_general_names(py, aci)?, None => py.None(), }; - Ok(x509_module.call1( - "AuthorityKeyIdentifier", - (aki.key_identifier, issuer, serial), - )?) + Ok(x509_module.getattr("AuthorityKeyIdentifier")?.call1(( + aki.key_identifier, + issuer, + serial, + ))?) } fn parse_name_attribute( @@ -678,7 +674,8 @@ fn parse_access_descriptions( .to_object(py); let gn = parse_general_name(py, access.access_location)?; let ad = x509_module - .call1("AccessDescription", (py_oid, gn))? + .getattr("AccessDescription")? + .call1((py_oid, gn))? .to_object(py); ads.append(ad)?; } @@ -863,13 +860,15 @@ fn parse_x509_extension( let gn_seq = asn1::parse_single::>>(ext_data)?; let sans = parse_general_names(py, gn_seq)?; Ok(x509_module - .call1("SubjectAlternativeName", (sans,))? + .getattr("SubjectAlternativeName")? + .call1((sans,))? .to_object(py)) } else if oid == *ISSUER_ALTERNATIVE_NAME_OID { let gn_seq = asn1::parse_single::>>(ext_data)?; let ians = parse_general_names(py, gn_seq)?; Ok(x509_module - .call1("IssuerAlternativeName", (ians,))? + .getattr("IssuerAlternativeName")? + .call1((ians,))? .to_object(py)) } else if oid == *TLS_FEATURE_OID { let tls_feature_type_to_enum = py @@ -881,11 +880,15 @@ fn parse_x509_extension( let py_feature = tls_feature_type_to_enum.get_item(feature.to_object(py))?; features.append(py_feature)?; } - Ok(x509_module.call1("TLSFeature", (features,))?.to_object(py)) + Ok(x509_module + .getattr("TLSFeature")? + .call1((features,))? + .to_object(py)) } else if oid == *SUBJECT_KEY_IDENTIFIER_OID { let identifier = asn1::parse_single::<&[u8]>(ext_data)?; Ok(x509_module - .call1("SubjectKeyIdentifier", (identifier,))? + .getattr("SubjectKeyIdentifier")? + .call1((identifier,))? .to_object(py)) } else if oid == *EXTENDED_KEY_USAGE_OID { let ekus = pyo3::types::PyList::empty(py); @@ -895,7 +898,8 @@ fn parse_x509_extension( ekus.append(oid_obj)?; } Ok(x509_module - .call1("ExtendedKeyUsage", (ekus,))? + .getattr("ExtendedKeyUsage")? + .call1((ekus,))? .to_object(py)) } else if oid == *KEY_USAGE_OID { let kus = asn1::parse_single::>(ext_data)?; @@ -909,30 +913,30 @@ fn parse_x509_extension( let encipher_only = kus.has_bit_set(7); let decipher_only = kus.has_bit_set(8); Ok(x509_module - .call1( - "KeyUsage", - ( - digital_signature, - content_comitment, - key_encipherment, - data_encipherment, - key_agreement, - key_cert_sign, - crl_sign, - encipher_only, - decipher_only, - ), - )? + .getattr("KeyUsage")? + .call1(( + digital_signature, + content_comitment, + key_encipherment, + data_encipherment, + key_agreement, + key_cert_sign, + crl_sign, + encipher_only, + decipher_only, + ))? .to_object(py)) } else if oid == *AUTHORITY_INFORMATION_ACCESS_OID { let ads = parse_access_descriptions(py, ext_data)?; Ok(x509_module - .call1("AuthorityInformationAccess", (ads,))? + .getattr("AuthorityInformationAccess")? + .call1((ads,))? .to_object(py)) } else if oid == *SUBJECT_INFORMATION_ACCESS_OID { let ads = parse_access_descriptions(py, ext_data)?; Ok(x509_module - .call1("SubjectInformationAccess", (ads,))? + .getattr("SubjectInformationAccess")? + .call1((ads,))? .to_object(py)) } else if oid == *CERTIFICATE_POLICIES_OID { let cp = parse_cp(py, ext_data)?; @@ -942,44 +946,47 @@ fn parse_x509_extension( } else if oid == *POLICY_CONSTRAINTS_OID { let pc = asn1::parse_single::(ext_data)?; Ok(x509_module - .call1( - "PolicyConstraints", - (pc.require_explicit_policy, pc.inhibit_policy_mapping), - )? + .getattr("PolicyConstraints")? + .call1((pc.require_explicit_policy, pc.inhibit_policy_mapping))? .to_object(py)) } else if oid == *PRECERT_POISON_OID { asn1::parse_single::<()>(ext_data)?; - Ok(x509_module.call0("PrecertPoison")?.to_object(py)) + Ok(x509_module.getattr("PrecertPoison")?.call0()?.to_object(py)) } else if oid == *OCSP_NO_CHECK_OID { asn1::parse_single::<()>(ext_data)?; - Ok(x509_module.call0("OCSPNoCheck")?.to_object(py)) + Ok(x509_module.getattr("OCSPNoCheck")?.call0()?.to_object(py)) } else if oid == *INHIBIT_ANY_POLICY_OID { let bignum = asn1::parse_single::>(ext_data)?; let pynum = big_asn1_uint_to_py(py, bignum)?; Ok(x509_module - .call1("InhibitAnyPolicy", (pynum,))? + .getattr("InhibitAnyPolicy")? + .call1((pynum,))? .to_object(py)) } else if oid == *BASIC_CONSTRAINTS_OID { let bc = asn1::parse_single::(ext_data)?; Ok(x509_module - .call1("BasicConstraints", (bc.ca, bc.path_length))? + .getattr("BasicConstraints")? + .call1((bc.ca, bc.path_length))? .to_object(py)) } else if oid == *AUTHORITY_KEY_IDENTIFIER_OID { Ok(parse_authority_key_identifier(py, ext_data)?.to_object(py)) } else if oid == *CRL_DISTRIBUTION_POINTS_OID { let dp = parse_distribution_points(py, ext_data)?; Ok(x509_module - .call1("CRLDistributionPoints", (dp,))? + .getattr("CRLDistributionPoints")? + .call1((dp,))? .to_object(py)) } else if oid == *FRESHEST_CRL_OID { Ok(x509_module - .call1("FreshestCRL", (parse_distribution_points(py, ext_data)?,))? + .getattr("FreshestCRL")? + .call1((parse_distribution_points(py, ext_data)?,))? .to_object(py)) } else if oid == *PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS_OID { let contents = asn1::parse_single::<&[u8]>(ext_data)?; let scts = parse_scts(py, contents, LogEntryType::PreCertificate)?; Ok(x509_module - .call1("PrecertificateSignedCertificateTimestamps", (scts,))? + .getattr("PrecertificateSignedCertificateTimestamps")? + .call1((scts,))? .to_object(py)) } else if oid == *NAME_CONSTRAINTS_OID { let nc = asn1::parse_single::>(ext_data)?; @@ -992,7 +999,8 @@ fn parse_x509_extension( None => py.None(), }; Ok(x509_module - .call1("NameConstraints", (permitted_subtrees, excluded_subtrees))? + .getattr("NameConstraints")? + .call1((permitted_subtrees, excluded_subtrees))? .to_object(py)) } else { Ok(py.None()) @@ -1027,17 +1035,24 @@ pub(crate) fn parse_crl_entry_extension( } }; let flag = x509_module.getattr("ReasonFlags")?.getattr(flag_name)?; - Ok(x509_module.call1("CRLReason", (flag,))?.to_object(py)) + Ok(x509_module + .getattr("CRLReason")? + .call1((flag,))? + .to_object(py)) } else if oid == *CERTIFICATE_ISSUER_OID { let gn_seq = asn1::parse_single::>>(ext_data)?; let gns = parse_general_names(py, gn_seq)?; Ok(x509_module - .call1("CertificateIssuer", (gns,))? + .getattr("CertificateIssuer")? + .call1((gns,))? .to_object(py)) } else if oid == *INVALIDITY_DATE_OID { let time = asn1::parse_single::(ext_data)?; let py_dt = chrono_to_py(py, time.as_chrono())?; - Ok(x509_module.call1("InvalidityDate", (py_dt,))?.to_object(py)) + Ok(x509_module + .getattr("InvalidityDate")? + .call1((py_dt,))? + .to_object(py)) } else { Ok(py.None()) } @@ -1055,23 +1070,29 @@ fn parse_crl_extension( if oid == *CRL_NUMBER_OID { let bignum = asn1::parse_single::>(ext_data)?; let pynum = big_asn1_uint_to_py(py, bignum)?; - Ok(x509_module.call1("CRLNumber", (pynum,))?.to_object(py)) + Ok(x509_module + .getattr("CRLNumber")? + .call1((pynum,))? + .to_object(py)) } else if oid == *DELTA_CRL_INDICATOR_OID { let bignum = asn1::parse_single::>(ext_data)?; let pynum = big_asn1_uint_to_py(py, bignum)?; Ok(x509_module - .call1("DeltaCRLIndicator", (pynum,))? + .getattr("DeltaCRLIndicator")? + .call1((pynum,))? .to_object(py)) } else if oid == *ISSUER_ALTERNATIVE_NAME_OID { let gn_seq = asn1::parse_single::>>(ext_data)?; let ians = parse_general_names(py, gn_seq)?; Ok(x509_module - .call1("IssuerAlternativeName", (ians,))? + .getattr("IssuerAlternativeName")? + .call1((ians,))? .to_object(py)) } else if oid == *AUTHORITY_INFORMATION_ACCESS_OID { let ads = parse_access_descriptions(py, ext_data)?; Ok(x509_module - .call1("AuthorityInformationAccess", (ads,))? + .getattr("AuthorityInformationAccess")? + .call1((ads,))? .to_object(py)) } else if oid == *AUTHORITY_KEY_IDENTIFIER_OID { Ok(parse_authority_key_identifier(py, ext_data)?.to_object(py)) @@ -1083,22 +1104,21 @@ fn parse_crl_extension( }; let reasons = parse_distribution_point_reasons(py, idp.only_some_reasons)?; Ok(x509_module - .call1( - "IssuingDistributionPoint", - ( - full_name, - relative_name, - idp.only_contains_user_certs, - idp.only_contains_ca_certs, - reasons, - idp.indirect_crl, - idp.only_contains_attribute_certs, - ), - )? + .getattr("IssuingDistributionPoint")? + .call1(( + full_name, + relative_name, + idp.only_contains_user_certs, + idp.only_contains_ca_certs, + reasons, + idp.indirect_crl, + idp.only_contains_attribute_certs, + ))? .to_object(py)) } else if oid == *FRESHEST_CRL_OID { Ok(x509_module - .call1("FreshestCRL", (parse_distribution_points(py, ext_data)?,))? + .getattr("FreshestCRL")? + .call1((parse_distribution_points(py, ext_data)?,))? .to_object(py)) } else { Ok(py.None()) From cdb79af0ecafadd44f845440646461b6da89e23b Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 8 Jul 2021 22:25:23 -0400 Subject: [PATCH 0345/2380] Silence overly zealous flake8 warning (#6163) --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 1f7debd4ed5a..73ff96785c6a 100644 --- a/tox.ini +++ b/tox.ini @@ -73,7 +73,7 @@ commands = cargo test --no-default-features [flake8] -ignore = E203,E211,W503,W504 +ignore = E203,E211,W503,W504,N818 exclude = .tox,*.egg,.git,_build,.hypothesis select = E,W,F,N,I application-import-names = cryptography,cryptography_vectors,tests From 6150eaaa91f2cdc73437f94f4bb4a8c82865d3c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jul 2021 08:21:30 -0400 Subject: [PATCH 0346/2380] Bump dessant/lock-threads from 2.0.3 to 2.1.1 (#6168) Bumps [dessant/lock-threads](https://github.com/dessant/lock-threads) from 2.0.3 to 2.1.1. - [Release notes](https://github.com/dessant/lock-threads/releases) - [Changelog](https://github.com/dessant/lock-threads/blob/master/CHANGELOG.md) - [Commits](https://github.com/dessant/lock-threads/compare/v2.0.3...v2.1.1) --- updated-dependencies: - dependency-name: dessant/lock-threads dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/lock.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index cc4bc369a99f..2e19c82c41f5 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -11,7 +11,7 @@ jobs: lock: runs-on: ubuntu-latest steps: - - uses: dessant/lock-threads@v2.0.3 + - uses: dessant/lock-threads@v2.1.1 with: github-token: ${{ secrets.GITHUB_TOKEN }} issue-lock-inactive-days: 90 From f770e453dbf5f307b8cafb19568cd489595f12a6 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 14 Jul 2021 19:03:58 -0400 Subject: [PATCH 0347/2380] [hack] see if putting this on one line fixes coverage (#6173) * Attempt to fix coverage by shortening lines * Comment --- .../hazmat/backends/openssl/backend.py | 4 +-- .../hazmat/bindings/_rust/ocsp.pyi | 6 ++-- .../hazmat/bindings/_rust/x509.pyi | 4 +-- src/rust/src/asn1.rs | 7 ++++- src/rust/src/ocsp.rs | 22 +++++---------- src/rust/src/x509.rs | 28 ++++++------------- 6 files changed, 27 insertions(+), 44 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index ab9f2ce80f8b..621a7df53523 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -399,7 +399,7 @@ def _register_x509_ext_parsers(self): self, ext_count=self._lib.X509_REVOKED_get_ext_count, get_ext=self._lib.X509_REVOKED_get_ext, - rust_callback=rust_x509.parse_crl_entry_extension, + rust_callback=rust_x509.parse_crl_entry_ext, ) self._crl_extension_parser = _X509ExtensionParser( self, @@ -417,7 +417,7 @@ def _register_x509_ext_parsers(self): self, ext_count=self._lib.OCSP_SINGLERESP_get_ext_count, get_ext=self._lib.OCSP_SINGLERESP_get_ext, - rust_callback=rust_ocsp.parse_ocsp_singleresp_extension, + rust_callback=rust_ocsp.parse_ocsp_singleresp_ext, ) def _register_x509_encoders(self): diff --git a/src/cryptography/hazmat/bindings/_rust/ocsp.pyi b/src/cryptography/hazmat/bindings/_rust/ocsp.pyi index 14f5eaf88f31..7e318fdace0c 100644 --- a/src/cryptography/hazmat/bindings/_rust/ocsp.pyi +++ b/src/cryptography/hazmat/bindings/_rust/ocsp.pyi @@ -3,8 +3,8 @@ from cryptography.x509.ocsp import OCSPRequest def load_der_ocsp_request(data: bytes) -> OCSPRequest: ... def parse_ocsp_resp_extension( - der_oid: bytes, ext_data: bytes + der_oid: bytes, data: bytes ) -> ExtensionType: ... -def parse_ocsp_singleresp_extension( - der_oid: bytes, ext_data: bytes +def parse_ocsp_singleresp_ext( + der_oid: bytes, data: bytes ) -> ExtensionType: ... diff --git a/src/cryptography/hazmat/bindings/_rust/x509.pyi b/src/cryptography/hazmat/bindings/_rust/x509.pyi index a2ed70282e17..53f99a554797 100644 --- a/src/cryptography/hazmat/bindings/_rust/x509.pyi +++ b/src/cryptography/hazmat/bindings/_rust/x509.pyi @@ -4,9 +4,7 @@ from cryptography.x509 import ( ) def parse_x509_extension(der_oid: bytes, ext_data: bytes) -> ExtensionType: ... -def parse_crl_entry_extension( - der_oid: bytes, ext_data: bytes -) -> ExtensionType: ... +def parse_crl_entry_ext(der_oid: bytes, data: bytes) -> ExtensionType: ... def parse_crl_extension(der_oid: bytes, ext_data: bytes) -> ExtensionType: ... def encode_precertificate_signed_certificate_timestamps( extension: PrecertificateSignedCertificateTimestamps, diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs index 28f458e49c0c..ac511ab5d6c2 100644 --- a/src/rust/src/asn1.rs +++ b/src/rust/src/asn1.rs @@ -5,7 +5,7 @@ use pyo3::class::basic::CompareOp; use pyo3::conversion::ToPyObject; -pub(crate) enum PyAsn1Error { +pub enum PyAsn1Error { Asn1(asn1::ParseError), Py(pyo3::PyErr), } @@ -34,6 +34,11 @@ impl From for pyo3::PyErr { } } +// The primary purpose of this alias is for brevity to keep function signatures +// to a single-line as a work around for coverage issues. See +// https://github.com/pyca/cryptography/pull/6173 +pub(crate) type PyAsn1Result = Result; + #[pyo3::prelude::pyfunction] fn encode_tls_feature(py: pyo3::Python<'_>, ext: &pyo3::PyAny) -> pyo3::PyResult { // Ideally we'd skip building up a vec and just write directly into the diff --git a/src/rust/src/ocsp.rs b/src/rust/src/ocsp.rs index e097aacc852e..97dda1144e3f 100644 --- a/src/rust/src/ocsp.rs +++ b/src/rust/src/ocsp.rs @@ -2,7 +2,7 @@ // 2.0, and the BSD License. See the LICENSE file in the root of this repository // for complete details. -use crate::asn1::{big_asn1_uint_to_py, PyAsn1Error}; +use crate::asn1::{big_asn1_uint_to_py, PyAsn1Error, PyAsn1Result}; use crate::x509; use pyo3::conversion::ToPyObject; use pyo3::exceptions; @@ -194,11 +194,7 @@ struct CertID<'a> { } #[pyo3::prelude::pyfunction] -fn parse_ocsp_resp_extension( - py: pyo3::Python<'_>, - der_oid: &[u8], - ext_data: &[u8], -) -> pyo3::PyResult { +fn parse_ocsp_resp_extension(py: pyo3::Python<'_>, der_oid: &[u8], data: &[u8]) -> PyAsn1Result { let oid = asn1::ObjectIdentifier::from_der(der_oid).unwrap(); let x509_module = py.import("cryptography.x509")?; @@ -210,7 +206,7 @@ fn parse_ocsp_resp_extension( // the nonce. For now we just implement the old behavior, even though // it's deranged. Ok(x509_module - .call_method1("OCSPNonce", (ext_data,))? + .call_method1("OCSPNonce", (data,))? .to_object(py)) } else { Ok(py.None()) @@ -218,23 +214,19 @@ fn parse_ocsp_resp_extension( } #[pyo3::prelude::pyfunction] -fn parse_ocsp_singleresp_extension( - py: pyo3::Python<'_>, - der_oid: &[u8], - ext_data: &[u8], -) -> Result { +fn parse_ocsp_singleresp_ext(py: pyo3::Python<'_>, der_oid: &[u8], data: &[u8]) -> PyAsn1Result { let oid = asn1::ObjectIdentifier::from_der(der_oid).unwrap(); let x509_module = py.import("cryptography.x509")?; if oid == *SIGNED_CERTIFICATE_TIMESTAMPS_OID { - let contents = asn1::parse_single::<&[u8]>(ext_data)?; + let contents = asn1::parse_single::<&[u8]>(data)?; let scts = x509::parse_scts(py, contents, x509::LogEntryType::Certificate)?; Ok(x509_module .getattr("SignedCertificateTimestamps")? .call1((scts,))? .to_object(py)) } else { - x509::parse_crl_entry_extension(py, der_oid, ext_data) + x509::parse_crl_entry_ext(py, der_oid, data) } } @@ -243,7 +235,7 @@ pub(crate) fn create_submodule(py: pyo3::Python<'_>) -> pyo3::PyResult<&pyo3::pr submod.add_wrapped(pyo3::wrap_pyfunction!(load_der_ocsp_request))?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_ocsp_resp_extension))?; - submod.add_wrapped(pyo3::wrap_pyfunction!(parse_ocsp_singleresp_extension))?; + submod.add_wrapped(pyo3::wrap_pyfunction!(parse_ocsp_singleresp_ext))?; Ok(submod) } diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index f23ae7dd7e81..b2ef945ef82a 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -2,7 +2,7 @@ // 2.0, and the BSD License. See the LICENSE file in the root of this repository // for complete details. -use crate::asn1::{big_asn1_uint_to_py, AttributeTypeValue, Name, PyAsn1Error}; +use crate::asn1::{big_asn1_uint_to_py, AttributeTypeValue, Name, PyAsn1Error, PyAsn1Result}; use chrono::{Datelike, Timelike}; use pyo3::conversion::ToPyObject; use pyo3::types::IntoPyDict; @@ -848,11 +848,7 @@ pub(crate) fn parse_scts( } #[pyo3::prelude::pyfunction] -fn parse_x509_extension( - py: pyo3::Python<'_>, - der_oid: &[u8], - ext_data: &[u8], -) -> Result { +fn parse_x509_extension(py: pyo3::Python<'_>, der_oid: &[u8], ext_data: &[u8]) -> PyAsn1Result { let oid = asn1::ObjectIdentifier::from_der(der_oid).unwrap(); let x509_module = py.import("cryptography.x509")?; @@ -1008,16 +1004,12 @@ fn parse_x509_extension( } #[pyo3::prelude::pyfunction] -pub(crate) fn parse_crl_entry_extension( - py: pyo3::Python<'_>, - der_oid: &[u8], - ext_data: &[u8], -) -> Result { +pub fn parse_crl_entry_ext(py: pyo3::Python<'_>, der_oid: &[u8], data: &[u8]) -> PyAsn1Result { let oid = asn1::ObjectIdentifier::from_der(der_oid).unwrap(); let x509_module = py.import("cryptography.x509")?; if oid == *CRL_REASON_OID { - let flag_name = match asn1::parse_single::(ext_data)?.value() { + let flag_name = match asn1::parse_single::(data)?.value() { 0 => "unspecified", 1 => "key_compromise", 2 => "ca_compromise", @@ -1040,14 +1032,14 @@ pub(crate) fn parse_crl_entry_extension( .call1((flag,))? .to_object(py)) } else if oid == *CERTIFICATE_ISSUER_OID { - let gn_seq = asn1::parse_single::>>(ext_data)?; + let gn_seq = asn1::parse_single::>>(data)?; let gns = parse_general_names(py, gn_seq)?; Ok(x509_module .getattr("CertificateIssuer")? .call1((gns,))? .to_object(py)) } else if oid == *INVALIDITY_DATE_OID { - let time = asn1::parse_single::(ext_data)?; + let time = asn1::parse_single::(data)?; let py_dt = chrono_to_py(py, time.as_chrono())?; Ok(x509_module .getattr("InvalidityDate")? @@ -1059,11 +1051,7 @@ pub(crate) fn parse_crl_entry_extension( } #[pyo3::prelude::pyfunction] -fn parse_crl_extension( - py: pyo3::Python<'_>, - der_oid: &[u8], - ext_data: &[u8], -) -> Result { +fn parse_crl_extension(py: pyo3::Python<'_>, der_oid: &[u8], ext_data: &[u8]) -> PyAsn1Result { let oid = asn1::ObjectIdentifier::from_der(der_oid).unwrap(); let x509_module = py.import("cryptography.x509")?; @@ -1129,7 +1117,7 @@ pub(crate) fn create_submodule(py: pyo3::Python<'_>) -> pyo3::PyResult<&pyo3::pr let submod = pyo3::prelude::PyModule::new(py, "x509")?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_x509_extension))?; - submod.add_wrapped(pyo3::wrap_pyfunction!(parse_crl_entry_extension))?; + submod.add_wrapped(pyo3::wrap_pyfunction!(parse_crl_entry_ext))?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_crl_extension))?; submod.add_wrapped(pyo3::wrap_pyfunction!( encode_precertificate_signed_certificate_timestamps From 4baa220d5a6d02f57dcef135338c082e14996922 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Jul 2021 19:29:44 -0400 Subject: [PATCH 0348/2380] Bump ouroboros from 0.9.5 to 0.10.1 in /src/rust (#6172) Bumps [ouroboros](https://github.com/joshua-maros/ouroboros) from 0.9.5 to 0.10.1. - [Release notes](https://github.com/joshua-maros/ouroboros/releases) - [Commits](https://github.com/joshua-maros/ouroboros/commits) --- updated-dependencies: - dependency-name: ouroboros dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 15 +++++++++++---- src/rust/Cargo.toml | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 8ebd9ff10d26..4d3d15b5ea6d 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -8,6 +8,12 @@ version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +[[package]] +name = "aliasable" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" + [[package]] name = "asn1" version = "0.5.3" @@ -148,19 +154,20 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "ouroboros" -version = "0.9.5" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeff60e3e37407a80ead3e9458145b456e978c4068cddbfea6afb48572962ca" +checksum = "84236d64f1718c387232287cf036eb6632a5ecff226f4ff9dccb8c2b79ba0bde" dependencies = [ + "aliasable", "ouroboros_macro", "stable_deref_trait", ] [[package]] name = "ouroboros_macro" -version = "0.9.5" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03f2cb802b5bdfdf52f1ffa0b54ce105e4d346e91990dd571f86c91321ad49e2" +checksum = "f463857a6eb96c0136b1d56e56c718350cef30412ec065b48294799a088bca68" dependencies = [ "Inflector", "proc-macro-error", diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index f402456859ea..0d0f66f26f53 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -10,7 +10,7 @@ lazy_static = "1" pyo3 = { version = "0.14.1" } asn1 = { version = "0.5.3", default-features = false, features = ["derive"] } chrono = { version = "0.4", default-features = false, features = ["alloc"] } -ouroboros = "0.9" +ouroboros = "0.10" [features] extension-module = ["pyo3/extension-module"] From 646d8ee99b45c3b2d28d5f281024521f8b6784c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Jul 2021 19:31:08 -0400 Subject: [PATCH 0349/2380] Bump libc from 0.2.97 to 0.2.98 in /src/rust (#6162) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.97 to 0.2.98. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.97...0.2.98) --- updated-dependencies: - dependency-name: libc dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 4d3d15b5ea6d..2d6a2bd40aee 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -114,9 +114,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.97" +version = "0.2.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" +checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" [[package]] name = "lock_api" From 69f9a412de436e2e7a0520bade56751ca5cbe47a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Jul 2021 19:53:27 -0400 Subject: [PATCH 0350/2380] Bump instant from 0.1.9 to 0.1.10 in /src/rust (#6170) Bumps [instant](https://github.com/sebcrozet/instant) from 0.1.9 to 0.1.10. - [Release notes](https://github.com/sebcrozet/instant/releases) - [Commits](https://github.com/sebcrozet/instant/commits) --- updated-dependencies: - dependency-name: instant dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 2d6a2bd40aee..6f9af66f872d 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -99,9 +99,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" +checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d" dependencies = [ "cfg-if", ] From b681f3cbe96784a97b84a26c10db89e4dc742d35 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 17 Jul 2021 11:31:40 -0400 Subject: [PATCH 0351/2380] Bump to rust-asn1 0.6.0 (#6175) --- src/rust/Cargo.lock | 8 ++++---- src/rust/Cargo.toml | 2 +- src/rust/src/x509.rs | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 6f9af66f872d..973d86535114 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -16,9 +16,9 @@ checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" [[package]] name = "asn1" -version = "0.5.3" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f56417796de18d5398ee1ba4058d061a9be1bcfdef9a46f73e96e94f5bb21e0" +checksum = "9680a48fea09cb1af33dc233179b9723674ca43ad9e5c9d01ab6ad1c3c58c0dc" dependencies = [ "asn1_derive", "chrono", @@ -26,9 +26,9 @@ dependencies = [ [[package]] name = "asn1_derive" -version = "0.5.3" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be3a3360bd6e363428f7ce00ccd251efcd2639b6942ab22e5f322a452aa6f079" +checksum = "f828598cd99548327735aae5db2852e3d78d1508ed81543f204b8ca3cf3ba859" dependencies = [ "proc-macro2", "quote", diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 0d0f66f26f53..df187bfa4e2b 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] lazy_static = "1" pyo3 = { version = "0.14.1" } -asn1 = { version = "0.5.3", default-features = false, features = ["derive"] } +asn1 = { version = "0.6", default-features = false, features = ["derive"] } chrono = { version = "0.4", default-features = false, features = ["alloc"] } ouroboros = "0.10" diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index b2ef945ef82a..0dae8b72706a 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -255,9 +255,9 @@ struct UnvalidatedIA5String<'a>(&'a str); impl<'a> asn1::SimpleAsn1Readable<'a> for UnvalidatedIA5String<'a> { const TAG: u8 = 0x16; fn parse_data(data: &'a [u8]) -> asn1::ParseResult { - Ok(UnvalidatedIA5String( - std::str::from_utf8(data).map_err(|_| asn1::ParseError::InvalidValue)?, - )) + Ok(UnvalidatedIA5String(std::str::from_utf8(data).map_err( + |_| asn1::ParseError::new(asn1::ParseErrorKind::InvalidValue), + )?)) } } @@ -500,8 +500,8 @@ fn parse_name_attribute( .import("cryptography.x509.name")? .getattr("_ASN1_TYPE_TO_ENUM")?; let py_tag = tag_enum.get_item(attribute.value.tag().to_object(py))?; - let py_data = - std::str::from_utf8(attribute.value.data()).map_err(|_| asn1::ParseError::InvalidValue)?; + let py_data = std::str::from_utf8(attribute.value.data()) + .map_err(|_| asn1::ParseError::new(asn1::ParseErrorKind::InvalidValue))?; Ok(x509_module .call_method1("NameAttribute", (oid, py_data, py_tag))? .to_object(py)) From d20e4a67045edb5e0b1289c12ad93293779919b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Jul 2021 09:27:52 -0400 Subject: [PATCH 0352/2380] Bump syn from 1.0.73 to 1.0.74 in /src/rust (#6176) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.73 to 1.0.74. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.73...1.0.74) --- updated-dependencies: - dependency-name: syn dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 973d86535114..8241c803f9b6 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -345,9 +345,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "syn" -version = "1.0.73" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" +checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" dependencies = [ "proc-macro2", "quote", From 603018110973ded97cd586b55901fabf59101c1c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Jul 2021 21:23:59 -0400 Subject: [PATCH 0353/2380] Bump proc-macro2 from 1.0.27 to 1.0.28 in /src/rust (#6177) Bumps [proc-macro2](https://github.com/alexcrichton/proc-macro2) from 1.0.27 to 1.0.28. - [Release notes](https://github.com/alexcrichton/proc-macro2/releases) - [Commits](https://github.com/alexcrichton/proc-macro2/compare/1.0.27...1.0.28) --- updated-dependencies: - dependency-name: proc-macro2 dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 8241c803f9b6..aa62697a09cb 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -252,9 +252,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" +checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" dependencies = [ "unicode-xid", ] From 87f43fb77e7f1c56471d3233a56000a51dc4a311 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 25 Jul 2021 15:03:14 -0700 Subject: [PATCH 0354/2380] parse certificates with pure rust (#6147) * parse certificates with pure rust * fix coverage * various review comments * save the buffer * more feedback --- CHANGELOG.rst | 7 + docs/hazmat/backends/interfaces.rst | 12 - .../hazmat/backends/interfaces.py | 12 - .../hazmat/backends/openssl/backend.py | 96 ++-- .../hazmat/backends/openssl/decode_asn1.py | 6 +- .../hazmat/backends/openssl/ocsp.py | 7 +- .../hazmat/backends/openssl/x509.py | 149 +---- .../hazmat/bindings/_rust/x509.pyi | 23 +- src/cryptography/utils.py | 1 + src/cryptography/x509/base.py | 17 +- src/rust/Cargo.lock | 33 ++ src/rust/Cargo.toml | 1 + src/rust/src/asn1.rs | 18 +- src/rust/src/x509.rs | 515 +++++++++++++++++- tests/hazmat/backends/test_openssl.py | 42 +- tests/hazmat/primitives/test_pkcs7.py | 6 +- tests/x509/test_x509.py | 86 ++- 17 files changed, 730 insertions(+), 301 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6760ba76979e..429b3af61e8b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -11,6 +11,13 @@ Changelog * Changed the :ref:`version scheme `. This will result in us incrementing the major version more frequently, but does not change our existing backwards compatibility policy. +* **BACKWARDS INCOMPATIBLE:** The X.509 certificate parser no longer allows + negative serial numbers. :rfc:`5280` has always prohibited these. +* **BACKWARDS INCOMPATIBLE:** Invalid ASN.1 found during certificate parsing + will raise an error on initial parse rather than when the invalid field is + accessed. +* **BACKWARDS INCOMPATIBLE:** Values passed to the X.509 PEM parser must be + a single PEM payload and will error on extraneous data. * Added support for :class:`~cryptography.hazmat.primitives.hashes.SM3` and :class:`~cryptography.hazmat.primitives.ciphers.algorithms.SM4`, diff --git a/docs/hazmat/backends/interfaces.rst b/docs/hazmat/backends/interfaces.rst index 36dd3a7a5a1e..664710181eef 100644 --- a/docs/hazmat/backends/interfaces.rst +++ b/docs/hazmat/backends/interfaces.rst @@ -500,18 +500,6 @@ A specific ``backend`` may provide one or more of these interfaces. A backend with methods for working with X.509 objects. - .. method:: load_pem_x509_certificate(data) - - :param bytes data: PEM formatted certificate data. - - :returns: An instance of :class:`~cryptography.x509.Certificate`. - - .. method:: load_der_x509_certificate(data) - - :param bytes data: DER formatted certificate data. - - :returns: An instance of :class:`~cryptography.x509.Certificate`. - .. method:: load_pem_x509_csr(data) .. versionadded:: 0.9 diff --git a/src/cryptography/hazmat/backends/interfaces.py b/src/cryptography/hazmat/backends/interfaces.py index 2aeee4927b3d..4b2d80a7770a 100644 --- a/src/cryptography/hazmat/backends/interfaces.py +++ b/src/cryptography/hazmat/backends/interfaces.py @@ -280,18 +280,6 @@ def load_der_parameters(self, data): class X509Backend(metaclass=abc.ABCMeta): - @abc.abstractmethod - def load_pem_x509_certificate(self, data: bytes) -> "Certificate": - """ - Load an X.509 certificate from PEM encoded data. - """ - - @abc.abstractmethod - def load_der_x509_certificate(self, data: bytes) -> "Certificate": - """ - Load an X.509 certificate from DER encoded data. - """ - @abc.abstractmethod def load_der_x509_csr(self, data: bytes) -> "CertificateSigningRequest": """ diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 621a7df53523..349205b13340 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -75,7 +75,6 @@ _X448PublicKey, ) from cryptography.hazmat.backends.openssl.x509 import ( - _Certificate, _CertificateRevocationList, _CertificateSigningRequest, _RevokedCertificate, @@ -383,17 +382,11 @@ def _register_default_ciphers(self): ) def _register_x509_ext_parsers(self): - self._certificate_extension_parser = _X509ExtensionParser( - self, - ext_count=self._lib.X509_get_ext_count, - get_ext=self._lib.X509_get_ext, - rust_callback=rust_x509.parse_x509_extension, - ) self._csr_extension_parser = _X509ExtensionParser( self, ext_count=self._lib.sk_X509_EXTENSION_num, get_ext=self._lib.sk_X509_EXTENSION_value, - rust_callback=rust_x509.parse_x509_extension, + rust_callback=rust_x509.parse_csr_extension, ) self._revoked_cert_extension_parser = _X509ExtensionParser( self, @@ -471,6 +464,7 @@ def _consume_errors_with_text(self): def _bn_to_int(self, bn): assert bn != self._ffi.NULL + self.openssl_assert(not self._lib.BN_is_negative(bn)) bn_num_bytes = self._lib.BN_num_bytes(bn) bin_ptr = self._ffi.new("unsigned char[]", bn_num_bytes) @@ -478,8 +472,6 @@ def _bn_to_int(self, bn): # A zero length means the BN has value 0 self.openssl_assert(bin_len >= 0) val = int.from_bytes(self._ffi.buffer(bin_ptr)[:bin_len], "big") - if self._lib.BN_is_negative(bn): - val = -val return val def _int_to_bn(self, num, bn=None): @@ -957,7 +949,7 @@ def create_x509_certificate( builder: x509.CertificateBuilder, private_key: PRIVATE_KEY_TYPES, algorithm: typing.Optional[hashes.HashAlgorithm], - ) -> _Certificate: + ) -> x509.Certificate: if not isinstance(builder, x509.CertificateBuilder): raise TypeError("Builder type mismatch.") if builder._public_key is None: @@ -1028,7 +1020,7 @@ def create_x509_certificate( errors = self._consume_errors_with_text() raise ValueError("Signing failed", errors) - return _Certificate(self, x509_cert) + return self._ossl2cert(x509_cert) def _evp_md_x509_null_if_eddsa(self, private_key, algorithm): if isinstance( @@ -1333,31 +1325,19 @@ def load_der_parameters(self, data): self._handle_key_loading_error() - def load_pem_x509_certificate(self, data: bytes) -> _Certificate: - mem_bio = self._bytes_to_bio(data) - x509 = self._lib.PEM_read_bio_X509( - mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL - ) - if x509 == self._ffi.NULL: - self._consume_errors() - raise ValueError( - "Unable to load certificate. See https://cryptography.io/en/" - "latest/faq.html#why-can-t-i-import-my-pem-file for more" - " details." - ) - - x509 = self._ffi.gc(x509, self._lib.X509_free) - return _Certificate(self, x509) - - def load_der_x509_certificate(self, data: bytes) -> _Certificate: + def _cert2ossl(self, cert: x509.Certificate) -> typing.Any: + data = cert.public_bytes(serialization.Encoding.DER) mem_bio = self._bytes_to_bio(data) x509 = self._lib.d2i_X509_bio(mem_bio.bio, self._ffi.NULL) - if x509 == self._ffi.NULL: - self._consume_errors() - raise ValueError("Unable to load certificate") - + self.openssl_assert(x509 != self._ffi.NULL) x509 = self._ffi.gc(x509, self._lib.X509_free) - return _Certificate(self, x509) + return x509 + + def _ossl2cert(self, x509: typing.Any) -> x509.Certificate: + bio = self._create_mem_bio_gc() + res = self._lib.i2d_X509_bio(bio, x509) + self.openssl_assert(res == 1) + return rust_x509.load_der_x509_certificate(self._read_mem_bio(bio)) def load_pem_x509_crl(self, data: bytes) -> _CertificateRevocationList: mem_bio = self._bytes_to_bio(data) @@ -1661,7 +1641,9 @@ def create_ocsp_request(self, builder): ocsp_req = self._ffi.gc(ocsp_req, self._lib.OCSP_REQUEST_free) cert, issuer, algorithm = builder._request evp_md = self._evp_md_non_null_from_algorithm(algorithm) - certid = self._lib.OCSP_cert_to_id(evp_md, cert._x509, issuer._x509) + ossl_cert = self._cert2ossl(cert) + ossl_issuer = self._cert2ossl(issuer) + certid = self._lib.OCSP_cert_to_id(evp_md, ossl_cert, ossl_issuer) self.openssl_assert(certid != self._ffi.NULL) onereq = self._lib.OCSP_request_add0_id(ocsp_req, certid) self.openssl_assert(onereq != self._ffi.NULL) @@ -1687,10 +1669,12 @@ def _create_ocsp_basic_response(self, builder, private_key, algorithm): evp_md = self._evp_md_non_null_from_algorithm( builder._response._algorithm ) + ossl_cert = self._cert2ossl(builder._response._cert) + ossl_issuer = self._cert2ossl(builder._response._issuer) certid = self._lib.OCSP_cert_to_id( evp_md, - builder._response._cert._x509, - builder._response._issuer._x509, + ossl_cert, + ossl_issuer, ) self.openssl_assert(certid != self._ffi.NULL) certid = self._ffi.gc(certid, self._lib.OCSP_CERTID_free) @@ -1732,9 +1716,13 @@ def _create_ocsp_basic_response(self, builder, private_key, algorithm): if responder_encoding is ocsp.OCSPResponderEncoding.HASH: flags |= self._lib.OCSP_RESPID_KEY + # This list is to keep the x509 values alive until end of function + ossl_certs = [] if builder._certs is not None: for cert in builder._certs: - res = self._lib.OCSP_basic_add1_cert(basic, cert._x509) + ossl_cert = self._cert2ossl(cert) + ossl_certs.append(ossl_cert) + res = self._lib.OCSP_basic_add1_cert(basic, ossl_cert) self.openssl_assert(res == 1) self._create_x509_extensions( @@ -1745,9 +1733,10 @@ def _create_ocsp_basic_response(self, builder, private_key, algorithm): gc=True, ) + ossl_cert = self._cert2ossl(responder_cert) res = self._lib.OCSP_basic_sign( basic, - responder_cert._x509, + ossl_cert, private_key._evp_pkey, evp_md, self._ffi.NULL, @@ -2523,7 +2512,7 @@ def load_key_and_certificates_from_pkcs12(self, data, password): if x509_ptr[0] != self._ffi.NULL: x509 = self._ffi.gc(x509_ptr[0], self._lib.X509_free) - cert = _Certificate(self, x509) + cert = self._ossl2cert(x509) if sk_x509_ptr[0] != self._ffi.NULL: sk_x509 = self._ffi.gc(sk_x509_ptr[0], self._lib.sk_X509_free) @@ -2541,7 +2530,8 @@ def load_key_and_certificates_from_pkcs12(self, data, password): x509 = self._lib.sk_X509_value(sk_x509, i) self.openssl_assert(x509 != self._ffi.NULL) x509 = self._ffi.gc(x509, self._lib.X509_free) - additional_certificates.append(_Certificate(self, x509)) + addl_cert = self._ossl2cert(x509) + additional_certificates.append(addl_cert) return (key, cert, additional_certificates) @@ -2580,17 +2570,23 @@ def serialize_key_and_certificates_to_pkcs12( sk_x509 = self._lib.sk_X509_new_null() sk_x509 = self._ffi.gc(sk_x509, self._lib.sk_X509_free) + # This list is to keep the x509 values alive until end of function + ossl_cas = [] for ca in cas: - res = self._lib.sk_X509_push(sk_x509, ca._x509) + ossl_ca = self._cert2ossl(ca) + ossl_cas.append(ossl_ca) + res = self._lib.sk_X509_push(sk_x509, ossl_ca) backend.openssl_assert(res >= 1) with self._zeroed_null_terminated_buf(password) as password_buf: with self._zeroed_null_terminated_buf(name) as name_buf: + ossl_cert = self._cert2ossl(cert) if cert else self._ffi.NULL + evp_pkey = key._evp_pkey if key else self._ffi.NULL p12 = self._lib.PKCS12_create( password_buf, name_buf, - key._evp_pkey if key else self._ffi.NULL, - cert._x509 if cert else self._ffi.NULL, + evp_pkey, + ossl_cert, sk_x509, nid_key, nid_cert, @@ -2664,7 +2660,8 @@ def _load_pkcs7_certificates(self, p7): # refcount. On 1.1.0+ it returns 1 for success. self.openssl_assert(res >= 1) x509 = self._ffi.gc(x509, self._lib.X509_free) - certs.append(_Certificate(self, x509)) + cert = self._ossl2cert(x509) + certs.append(cert) return certs @@ -2678,8 +2675,12 @@ def pkcs7_sign(self, builder, encoding, options): else: certs = self._lib.sk_X509_new_null() certs = self._ffi.gc(certs, self._lib.sk_X509_free) + # This list is to keep the x509 values alive until end of function + ossl_certs = [] for cert in builder._additional_certs: - res = self._lib.sk_X509_push(certs, cert._x509) + ossl_cert = self._cert2ossl(cert) + ossl_certs.append(ossl_cert) + res = self._lib.sk_X509_push(certs, ossl_cert) self.openssl_assert(res >= 1) if pkcs7.PKCS7Options.DetachedSignature in options: @@ -2711,9 +2712,10 @@ def pkcs7_sign(self, builder, encoding, options): signer_flags |= self._lib.PKCS7_NOCERTS for certificate, private_key, hash_algorithm in builder._signers: + ossl_cert = self._cert2ossl(certificate) md = self._evp_md_non_null_from_algorithm(hash_algorithm) p7signerinfo = self._lib.PKCS7_sign_add_signer( - p7, certificate._x509, private_key._evp_pkey, md, signer_flags + p7, ossl_cert, private_key._evp_pkey, md, signer_flags ) self.openssl_assert(p7signerinfo != self._ffi.NULL) diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 228d3e008392..8e648eba6685 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -169,11 +169,7 @@ def _asn1_string_to_ascii(backend, asn1_string): def _asn1_string_to_utf8(backend, asn1_string) -> str: buf = backend._ffi.new("unsigned char **") res = backend._lib.ASN1_STRING_to_UTF8(buf, asn1_string) - if res == -1: - raise ValueError( - "Unsupported ASN1 string type. Type: {}".format(asn1_string.type) - ) - + backend.openssl_assert(res >= 0) backend.openssl_assert(buf[0] != backend._ffi.NULL) buf = backend._ffi.gc( buf, lambda buffer: backend._lib.OPENSSL_free(buffer[0]) diff --git a/src/cryptography/hazmat/backends/openssl/ocsp.py b/src/cryptography/hazmat/backends/openssl/ocsp.py index 6ef9316e975e..c69be3123c5e 100644 --- a/src/cryptography/hazmat/backends/openssl/ocsp.py +++ b/src/cryptography/hazmat/backends/openssl/ocsp.py @@ -15,7 +15,6 @@ _obj2txt, _parse_asn1_generalized_time, ) -from cryptography.hazmat.backends.openssl.x509 import _Certificate from cryptography.hazmat.primitives import hashes, serialization from cryptography.x509.ocsp import ( OCSPCertStatus, @@ -178,11 +177,7 @@ def certificates(self) -> typing.List[x509.Certificate]: for i in range(num): x509_ptr = self._backend._lib.sk_X509_value(sk_x509, i) self._backend.openssl_assert(x509_ptr != self._backend._ffi.NULL) - cert = _Certificate(self._backend, x509_ptr) - # We need to keep the OCSP response that the certificate came from - # alive until the Certificate object itself goes out of scope, so - # we give it a private reference. - cert._ocsp_resp_ref = self + cert = self._backend._ossl2cert(x509_ptr) certs.append(cert) return certs diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index edbc7c6d5f0c..d2017efdf559 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -6,6 +6,7 @@ import datetime import operator import typing +import warnings from cryptography import utils, x509 from cryptography.exceptions import UnsupportedAlgorithm @@ -26,145 +27,15 @@ from cryptography.x509.name import _ASN1Type -class _Certificate(x509.Certificate): - # Keep-alive reference used by OCSP - _ocsp_resp_ref: typing.Any - - def __init__(self, backend, x509_cert): - self._backend = backend - self._x509 = x509_cert - - version = self._backend._lib.X509_get_version(self._x509) - if version == 0: - self._version = x509.Version.v1 - elif version == 2: - self._version = x509.Version.v3 - else: - raise x509.InvalidVersion( - "{} is not a valid X509 version".format(version), version - ) - - def __repr__(self): - return "".format(self.subject) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, _Certificate): - return NotImplemented - - res = self._backend._lib.X509_cmp(self._x509, other._x509) - return res == 0 - - def __ne__(self, other: object) -> bool: - return not self == other - - def __hash__(self) -> int: - return hash(self.public_bytes(serialization.Encoding.DER)) - - def __deepcopy__(self, memo): - return self - - def fingerprint(self, algorithm: hashes.HashAlgorithm) -> bytes: - h = hashes.Hash(algorithm, self._backend) - h.update(self.public_bytes(serialization.Encoding.DER)) - return h.finalize() - - version = utils.read_only_property("_version") - - @property - def serial_number(self) -> int: - asn1_int = self._backend._lib.X509_get_serialNumber(self._x509) - self._backend.openssl_assert(asn1_int != self._backend._ffi.NULL) - return _asn1_integer_to_int(self._backend, asn1_int) - - def public_key(self) -> PUBLIC_KEY_TYPES: - pkey = self._backend._lib.X509_get_pubkey(self._x509) - if pkey == self._backend._ffi.NULL: - # Remove errors from the stack. - self._backend._consume_errors() - raise ValueError("Certificate public key is of an unknown type") - - pkey = self._backend._ffi.gc(pkey, self._backend._lib.EVP_PKEY_free) - - return self._backend._evp_pkey_to_public_key(pkey) - - @property - def not_valid_before(self) -> datetime.datetime: - asn1_time = self._backend._lib.X509_get0_notBefore(self._x509) - return _parse_asn1_time(self._backend, asn1_time) - - @property - def not_valid_after(self) -> datetime.datetime: - asn1_time = self._backend._lib.X509_get0_notAfter(self._x509) - return _parse_asn1_time(self._backend, asn1_time) - - @property - def issuer(self) -> x509.Name: - issuer = self._backend._lib.X509_get_issuer_name(self._x509) - self._backend.openssl_assert(issuer != self._backend._ffi.NULL) - return _decode_x509_name(self._backend, issuer) - - @property - def subject(self) -> x509.Name: - subject = self._backend._lib.X509_get_subject_name(self._x509) - self._backend.openssl_assert(subject != self._backend._ffi.NULL) - return _decode_x509_name(self._backend, subject) - - @property - def signature_hash_algorithm( - self, - ) -> typing.Optional[hashes.HashAlgorithm]: - oid = self.signature_algorithm_oid - try: - return x509._SIG_OIDS_TO_HASH[oid] - except KeyError: - raise UnsupportedAlgorithm( - "Signature algorithm OID:{} not recognized".format(oid) - ) - - @property - def signature_algorithm_oid(self) -> x509.ObjectIdentifier: - alg = self._backend._ffi.new("X509_ALGOR **") - self._backend._lib.X509_get0_signature( - self._backend._ffi.NULL, alg, self._x509 - ) - self._backend.openssl_assert(alg[0] != self._backend._ffi.NULL) - oid = _obj2txt(self._backend, alg[0].algorithm) - return x509.ObjectIdentifier(oid) - - @utils.cached_property - def extensions(self) -> x509.Extensions: - return self._backend._certificate_extension_parser.parse(self._x509) - - @property - def signature(self) -> bytes: - sig = self._backend._ffi.new("ASN1_BIT_STRING **") - self._backend._lib.X509_get0_signature( - sig, self._backend._ffi.NULL, self._x509 - ) - self._backend.openssl_assert(sig[0] != self._backend._ffi.NULL) - return _asn1_string_to_bytes(self._backend, sig[0]) - - @property - def tbs_certificate_bytes(self) -> bytes: - pp = self._backend._ffi.new("unsigned char **") - res = self._backend._lib.i2d_re_X509_tbs(self._x509, pp) - self._backend.openssl_assert(res > 0) - pp = self._backend._ffi.gc( - pp, lambda pointer: self._backend._lib.OPENSSL_free(pointer[0]) - ) - return self._backend._ffi.buffer(pp[0], res)[:] - - def public_bytes(self, encoding: serialization.Encoding) -> bytes: - bio = self._backend._create_mem_bio_gc() - if encoding is serialization.Encoding.PEM: - res = self._backend._lib.PEM_write_bio_X509(bio, self._x509) - elif encoding is serialization.Encoding.DER: - res = self._backend._lib.i2d_X509_bio(bio, self._x509) - else: - raise TypeError("encoding must be an item from the Encoding enum") - - self._backend.openssl_assert(res == 1) - return self._backend._read_mem_bio(bio) +# This exists for pyOpenSSL compatibility and SHOULD NOT BE USED +# WE WILL REMOVE THIS VERY SOON. +def _Certificate(backend, x509) -> x509.Certificate: # noqa: N802 + warnings.warn( + "This version of cryptography contains a temporary pyOpenSSL " + "fallback path. Upgrade pyOpenSSL now.", + utils.DeprecatedIn35, + ) + return backend._ossl2cert(x509) class _RevokedCertificate(x509.RevokedCertificate): diff --git a/src/cryptography/hazmat/bindings/_rust/x509.pyi b/src/cryptography/hazmat/bindings/_rust/x509.pyi index 53f99a554797..9c334441fb96 100644 --- a/src/cryptography/hazmat/bindings/_rust/x509.pyi +++ b/src/cryptography/hazmat/bindings/_rust/x509.pyi @@ -1,13 +1,20 @@ -from cryptography.x509 import ( - ExtensionType, - PrecertificateSignedCertificateTimestamps, -) +import datetime +import typing -def parse_x509_extension(der_oid: bytes, ext_data: bytes) -> ExtensionType: ... -def parse_crl_entry_ext(der_oid: bytes, data: bytes) -> ExtensionType: ... -def parse_crl_extension(der_oid: bytes, ext_data: bytes) -> ExtensionType: ... +from cryptography import x509 + +def parse_csr_extension( + der_oid: bytes, ext_data: bytes +) -> x509.ExtensionType: ... +def parse_crl_entry_ext(der_oid: bytes, data: bytes) -> x509.ExtensionType: ... +def parse_crl_extension( + der_oid: bytes, ext_data: bytes +) -> x509.ExtensionType: ... +def load_pem_x509_certificate(data: bytes) -> x509.Certificate: ... +def load_der_x509_certificate(data: bytes) -> x509.Certificate: ... def encode_precertificate_signed_certificate_timestamps( - extension: PrecertificateSignedCertificateTimestamps, + extension: x509.PrecertificateSignedCertificateTimestamps, ) -> bytes: ... class Sct: ... +class Certificate: ... diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index 8611d95c8e74..3cfd32e98855 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -23,6 +23,7 @@ class CryptographyDeprecationWarning(UserWarning): PersistentlyDeprecated2017 = CryptographyDeprecationWarning PersistentlyDeprecated2019 = CryptographyDeprecationWarning DeprecatedIn34 = CryptographyDeprecationWarning +DeprecatedIn35 = CryptographyDeprecationWarning def _check_bytes(name: str, value: bytes) -> None: diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index 4e8b4a844a41..3c626efc57cf 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -11,6 +11,7 @@ from cryptography import utils from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.backends.interfaces import Backend +from cryptography.hazmat.bindings._rust import x509 as rust_x509 from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ( dsa, @@ -189,6 +190,10 @@ def public_bytes(self, encoding: serialization.Encoding) -> bytes: """ +# Runtime isinstance checks need this since the rust class is not a subclass. +Certificate.register(rust_x509.Certificate) + + class RevokedCertificate(metaclass=abc.ABCMeta): @abc.abstractproperty def serial_number(self) -> int: @@ -413,18 +418,18 @@ def get_attribute_for_oid(self, oid: ObjectIdentifier) -> bytes: """ +# Backend argument preserved for API compatibility, but ignored. def load_pem_x509_certificate( - data: bytes, backend: typing.Optional[Backend] = None + data: bytes, backend: typing.Any = None ) -> Certificate: - backend = _get_backend(backend) - return backend.load_pem_x509_certificate(data) + return rust_x509.load_pem_x509_certificate(data) +# Backend argument preserved for API compatibility, but ignored. def load_der_x509_certificate( - data: bytes, backend: typing.Optional[Backend] = None + data: bytes, backend: typing.Any = None ) -> Certificate: - backend = _get_backend(backend) - return backend.load_der_x509_certificate(data) + return rust_x509.load_der_x509_certificate(data) def load_pem_x509_csr( diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index aa62697a09cb..9efe36c6bf65 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -41,6 +41,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + [[package]] name = "bitflags" version = "1.2.1" @@ -71,6 +77,7 @@ dependencies = [ "chrono", "lazy_static", "ouroboros", + "pem", "pyo3", ] @@ -220,6 +227,17 @@ dependencies = [ "proc-macro-hack", ] +[[package]] +name = "pem" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb" +dependencies = [ + "base64", + "once_cell", + "regex", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -325,6 +343,21 @@ dependencies = [ "bitflags", ] +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + [[package]] name = "scopeguard" version = "1.1.0" diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index df187bfa4e2b..aa4331ce96e3 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -9,6 +9,7 @@ publish = false lazy_static = "1" pyo3 = { version = "0.14.1" } asn1 = { version = "0.6", default-features = false, features = ["derive"] } +pem = "0.8" chrono = { version = "0.4", default-features = false, features = ["alloc"] } ouroboros = "0.10" diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs index ac511ab5d6c2..f9a1e05ad546 100644 --- a/src/rust/src/asn1.rs +++ b/src/rust/src/asn1.rs @@ -2,6 +2,7 @@ // 2.0, and the BSD License. See the LICENSE file in the root of this repository // for complete details. +use crate::x509::Name; use pyo3::class::basic::CompareOp; use pyo3::conversion::ToPyObject; @@ -22,6 +23,15 @@ impl From for PyAsn1Error { } } +impl From for PyAsn1Error { + fn from(e: pem::PemError) -> PyAsn1Error { + PyAsn1Error::Py(pyo3::exceptions::PyValueError::new_err(format!( + "Unable to load PEM file. See https://cryptography.io/en/latest/faq.html#why-can-t-i-import-my-pem-file for more details. {:?}", + e + ))) + } +} + impl From for pyo3::PyErr { fn from(e: PyAsn1Error) -> pyo3::PyErr { match e { @@ -178,14 +188,6 @@ struct TbsCertificate<'a> { _extensions: Option>, } -pub(crate) type Name<'a> = asn1::SequenceOf<'a, asn1::SetOf<'a, AttributeTypeValue<'a>>>; - -#[derive(asn1::Asn1Read)] -pub(crate) struct AttributeTypeValue<'a> { - pub(crate) type_id: asn1::ObjectIdentifier<'a>, - pub(crate) value: asn1::Tlv<'a>, -} - #[derive(asn1::Asn1Read)] struct Validity<'a> { not_before: asn1::Tlv<'a>, diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index 0dae8b72706a..cbc8b2c359c6 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -2,7 +2,7 @@ // 2.0, and the BSD License. See the LICENSE file in the root of this repository // for complete details. -use crate::asn1::{big_asn1_uint_to_py, AttributeTypeValue, Name, PyAsn1Error, PyAsn1Result}; +use crate::asn1::{big_asn1_uint_to_py, PyAsn1Error, PyAsn1Result}; use chrono::{Datelike, Timelike}; use pyo3::conversion::ToPyObject; use pyo3::types::IntoPyDict; @@ -43,6 +43,502 @@ lazy_static::lazy_static! { static ref CP_USER_NOTICE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.2.2").unwrap(); } +#[derive(asn1::Asn1Read, asn1::Asn1Write)] +struct RawCertificate<'a> { + tbs_cert: TbsCertificate<'a>, + signature_alg: AlgorithmIdentifier<'a>, + signature: asn1::BitString<'a>, +} + +#[derive(asn1::Asn1Read, asn1::Asn1Write)] +struct TbsCertificate<'a> { + #[explicit(0)] + #[default(0)] + version: u8, + serial: asn1::BigUint<'a>, + _signature_alg: asn1::Sequence<'a>, + + issuer: Name<'a>, + validity: Validity, + subject: Name<'a>, + + spki: asn1::Sequence<'a>, + #[implicit(1)] + _issuer_unique_id: Option>, + #[implicit(2)] + _subject_unique_id: Option>, + #[explicit(3)] + extensions: Option>, +} + +pub(crate) type Name<'a> = asn1::SequenceOf<'a, asn1::SetOf<'a, AttributeTypeValue<'a>>>; + +#[derive(asn1::Asn1Read, asn1::Asn1Write)] +pub(crate) struct AttributeTypeValue<'a> { + pub(crate) type_id: asn1::ObjectIdentifier<'a>, + pub(crate) value: asn1::Tlv<'a>, +} + +#[derive(asn1::Asn1Read, asn1::Asn1Write)] +enum Time { + UtcTime(asn1::UtcTime), + GeneralizedTime(asn1::GeneralizedTime), +} + +impl Time { + fn as_chrono(&self) -> &chrono::DateTime { + match self { + Time::UtcTime(data) => data.as_chrono(), + Time::GeneralizedTime(data) => data.as_chrono(), + } + } +} + +#[derive(asn1::Asn1Read, asn1::Asn1Write)] +pub(crate) struct Validity { + not_before: Time, + not_after: Time, +} + +#[ouroboros::self_referencing] +struct OwnedRawCertificate { + data: Vec, + #[borrows(data)] + #[covariant] + value: RawCertificate<'this>, +} + +#[pyo3::prelude::pyclass] +struct Certificate { + raw: OwnedRawCertificate, + cached_extensions: Option, +} + +#[pyo3::prelude::pyproto] +impl pyo3::class::basic::PyObjectProtocol for Certificate { + fn __hash__(&self) -> u64 { + let mut hasher = DefaultHasher::new(); + self.raw.borrow_data().hash(&mut hasher); + hasher.finish() + } + + fn __richcmp__( + &self, + other: pyo3::pycell::PyRef, + op: pyo3::class::basic::CompareOp, + ) -> pyo3::PyResult { + match op { + pyo3::class::basic::CompareOp::Eq => { + Ok(self.raw.borrow_data() == other.raw.borrow_data()) + } + pyo3::class::basic::CompareOp::Ne => { + Ok(self.raw.borrow_data() != other.raw.borrow_data()) + } + _ => Err(pyo3::exceptions::PyTypeError::new_err( + "Certificates cannot be ordered", + )), + } + } + + fn __repr__(&self) -> pyo3::PyResult { + let mut repr = String::from(", + _memo: pyo3::PyObject, + ) -> pyo3::pycell::PyRef<'_, Self> { + slf + } + + fn public_key<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> { + // This makes an unnecessary copy. It'd be nice to get rid of it. + let serialized = pyo3::types::PyBytes::new( + py, + &asn1::write_single(&self.raw.borrow_value().tbs_cert.spki), + ); + py.import("cryptography.hazmat.primitives.serialization")? + .getattr("load_der_public_key")? + .call1((serialized,)) + } + + fn fingerprint<'p>( + &self, + py: pyo3::Python<'p>, + algorithm: pyo3::PyObject, + ) -> pyo3::PyResult<&'p pyo3::PyAny> { + let hasher = py + .import("cryptography.hazmat.primitives.hashes")? + .getattr("Hash")? + .call1((algorithm,))?; + // This makes an unnecessary copy. It'd be nice to get rid of it. + let serialized = + pyo3::types::PyBytes::new(py, &asn1::write_single(&self.raw.borrow_value())); + hasher.call_method1("update", (serialized,))?; + hasher.call_method0("finalize") + } + + fn public_bytes<'p>( + &self, + py: pyo3::Python<'p>, + encoding: &pyo3::PyAny, + ) -> pyo3::PyResult<&'p pyo3::types::PyBytes> { + let encoding_class = py + .import("cryptography.hazmat.primitives.serialization")? + .getattr("Encoding")?; + + let result = asn1::write_single(self.raw.borrow_value()); + if encoding == encoding_class.getattr("DER")? { + Ok(pyo3::types::PyBytes::new(py, &result)) + } else if encoding == encoding_class.getattr("PEM")? { + let pem = pem::encode_config( + &pem::Pem { + tag: "CERTIFICATE".to_string(), + contents: result, + }, + pem::EncodeConfig { + line_ending: pem::LineEnding::LF, + }, + ) + .into_bytes(); + Ok(pyo3::types::PyBytes::new(py, &pem)) + } else { + Err(pyo3::exceptions::PyTypeError::new_err( + "encoding must be an item from the Encoding enum", + )) + } + } + + #[getter] + fn serial_number<'p>(&self, py: pyo3::Python<'p>) -> Result<&'p pyo3::PyAny, PyAsn1Error> { + Ok(big_asn1_uint_to_py( + py, + self.raw.borrow_value().tbs_cert.serial, + )?) + } + + #[getter] + fn version<'p>(&self, py: pyo3::Python<'p>) -> Result<&'p pyo3::PyAny, PyAsn1Error> { + let version = &self.raw.borrow_value().tbs_cert.version; + cert_version(py, *version) + } + + #[getter] + fn issuer<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> { + parse_name(py, &self.raw.borrow_value().tbs_cert.issuer) + } + + #[getter] + fn subject<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> { + parse_name(py, &self.raw.borrow_value().tbs_cert.subject) + } + + #[getter] + fn tbs_certificate_bytes<'p>( + &self, + py: pyo3::Python<'p>, + ) -> Result<&'p pyo3::types::PyBytes, PyAsn1Error> { + let result = asn1::write_single(&self.raw.borrow_value().tbs_cert); + Ok(pyo3::types::PyBytes::new(py, &result)) + } + + #[getter] + fn signature<'p>(&self, py: pyo3::Python<'p>) -> Result<&'p pyo3::types::PyBytes, PyAsn1Error> { + Ok(pyo3::types::PyBytes::new( + py, + self.raw.borrow_value().signature.as_bytes(), + )) + } + + #[getter] + fn not_valid_before<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> { + let chrono = &self + .raw + .borrow_value() + .tbs_cert + .validity + .not_before + .as_chrono(); + chrono_to_py(py, chrono) + } + + #[getter] + fn not_valid_after<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> { + let chrono = &self + .raw + .borrow_value() + .tbs_cert + .validity + .not_after + .as_chrono(); + chrono_to_py(py, chrono) + } + + #[getter] + fn signature_hash_algorithm<'p>( + &self, + py: pyo3::Python<'p>, + ) -> Result<&'p pyo3::PyAny, PyAsn1Error> { + let sig_oids_to_hash = py + .import("cryptography.x509")? + .getattr("_SIG_OIDS_TO_HASH")?; + let hash_alg = sig_oids_to_hash.get_item(self.signature_algorithm_oid(py)?); + match hash_alg { + Ok(data) => Ok(data), + Err(_) => Err(PyAsn1Error::from(pyo3::PyErr::from_instance( + py.import("cryptography.exceptions")?.call_method1( + "UnsupportedAlgorithm", + (format!( + "Signature algorithm OID: {} not recognized", + self.raw.borrow_value().signature_alg.oid.to_string() + ),), + )?, + ))), + } + } + + #[getter] + fn signature_algorithm_oid<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> { + py.import("cryptography.x509")?.call_method1( + "ObjectIdentifier", + (self.raw.borrow_value().signature_alg.oid.to_string(),), + ) + } + + #[getter] + fn extensions(&mut self, py: pyo3::Python<'_>) -> pyo3::PyResult { + let x509_module = py.import("cryptography.x509")?; + parse_and_cache_extensions( + py, + &mut self.cached_extensions, + &self.raw.borrow_value().tbs_cert.extensions, + |oid, ext_data| { + if oid == &*SUBJECT_ALTERNATIVE_NAME_OID { + let gn_seq = + asn1::parse_single::>>(ext_data)?; + let sans = parse_general_names(py, gn_seq)?; + Ok(Some( + x509_module + .getattr("SubjectAlternativeName")? + .call1((sans,))?, + )) + } else if oid == &*ISSUER_ALTERNATIVE_NAME_OID { + let gn_seq = + asn1::parse_single::>>(ext_data)?; + let ians = parse_general_names(py, gn_seq)?; + Ok(Some( + x509_module + .getattr("IssuerAlternativeName")? + .call1((ians,))?, + )) + } else if oid == &*TLS_FEATURE_OID { + let tls_feature_type_to_enum = py + .import("cryptography.x509.extensions")? + .getattr("_TLS_FEATURE_TYPE_TO_ENUM")?; + + let features = pyo3::types::PyList::empty(py); + for feature in asn1::parse_single::>(ext_data)? { + let py_feature = + tls_feature_type_to_enum.get_item(feature.to_object(py))?; + features.append(py_feature)?; + } + Ok(Some(x509_module.getattr("TLSFeature")?.call1((features,))?)) + } else if oid == &*SUBJECT_KEY_IDENTIFIER_OID { + let identifier = asn1::parse_single::<&[u8]>(ext_data)?; + Ok(Some( + x509_module + .getattr("SubjectKeyIdentifier")? + .call1((identifier,))?, + )) + } else if oid == &*EXTENDED_KEY_USAGE_OID { + let ekus = pyo3::types::PyList::empty(py); + for oid in asn1::parse_single::>>( + ext_data, + )? { + let oid_obj = + x509_module.call_method1("ObjectIdentifier", (oid.to_string(),))?; + ekus.append(oid_obj)?; + } + Ok(Some( + x509_module.getattr("ExtendedKeyUsage")?.call1((ekus,))?, + )) + } else if oid == &*KEY_USAGE_OID { + let kus = asn1::parse_single::>(ext_data)?; + let digital_signature = kus.has_bit_set(0); + let content_comitment = kus.has_bit_set(1); + let key_encipherment = kus.has_bit_set(2); + let data_encipherment = kus.has_bit_set(3); + let key_agreement = kus.has_bit_set(4); + let key_cert_sign = kus.has_bit_set(5); + let crl_sign = kus.has_bit_set(6); + let encipher_only = kus.has_bit_set(7); + let decipher_only = kus.has_bit_set(8); + Ok(Some(x509_module.getattr("KeyUsage")?.call1(( + digital_signature, + content_comitment, + key_encipherment, + data_encipherment, + key_agreement, + key_cert_sign, + crl_sign, + encipher_only, + decipher_only, + ))?)) + } else if oid == &*AUTHORITY_INFORMATION_ACCESS_OID { + let ads = parse_access_descriptions(py, ext_data)?; + Ok(Some( + x509_module + .getattr("AuthorityInformationAccess")? + .call1((ads,))?, + )) + } else if oid == &*SUBJECT_INFORMATION_ACCESS_OID { + let ads = parse_access_descriptions(py, ext_data)?; + Ok(Some( + x509_module + .getattr("SubjectInformationAccess")? + .call1((ads,))?, + )) + } else if oid == &*CERTIFICATE_POLICIES_OID { + let cp = parse_cp(py, ext_data)?; + Ok(Some( + x509_module.call_method1("CertificatePolicies", (cp,))?, + )) + } else if oid == &*POLICY_CONSTRAINTS_OID { + let pc = asn1::parse_single::(ext_data)?; + Ok(Some(x509_module.getattr("PolicyConstraints")?.call1(( + pc.require_explicit_policy, + pc.inhibit_policy_mapping, + ))?)) + } else if oid == &*PRECERT_POISON_OID { + asn1::parse_single::<()>(ext_data)?; + Ok(Some(x509_module.getattr("PrecertPoison")?.call0()?)) + } else if oid == &*OCSP_NO_CHECK_OID { + asn1::parse_single::<()>(ext_data)?; + Ok(Some(x509_module.getattr("OCSPNoCheck")?.call0()?)) + } else if oid == &*INHIBIT_ANY_POLICY_OID { + let bignum = asn1::parse_single::>(ext_data)?; + let pynum = big_asn1_uint_to_py(py, bignum)?; + Ok(Some( + x509_module.getattr("InhibitAnyPolicy")?.call1((pynum,))?, + )) + } else if oid == &*BASIC_CONSTRAINTS_OID { + let bc = asn1::parse_single::(ext_data)?; + Ok(Some( + x509_module + .getattr("BasicConstraints")? + .call1((bc.ca, bc.path_length))?, + )) + } else if oid == &*AUTHORITY_KEY_IDENTIFIER_OID { + Ok(Some(parse_authority_key_identifier(py, ext_data)?)) + } else if oid == &*CRL_DISTRIBUTION_POINTS_OID { + let dp = parse_distribution_points(py, ext_data)?; + Ok(Some( + x509_module.getattr("CRLDistributionPoints")?.call1((dp,))?, + )) + } else if oid == &*FRESHEST_CRL_OID { + let dp = parse_distribution_points(py, ext_data)?; + Ok(Some(x509_module.getattr("FreshestCRL")?.call1((dp,))?)) + } else if oid == &*PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS_OID { + let contents = asn1::parse_single::<&[u8]>(ext_data)?; + let scts = parse_scts(py, contents, LogEntryType::PreCertificate)?; + Ok(Some( + x509_module + .getattr("PrecertificateSignedCertificateTimestamps")? + .call1((scts,))?, + )) + } else if oid == &*NAME_CONSTRAINTS_OID { + let nc = asn1::parse_single::>(ext_data)?; + let permitted_subtrees = match nc.permitted_subtrees { + Some(data) => parse_general_subtrees(py, data)?, + None => py.None(), + }; + let excluded_subtrees = match nc.excluded_subtrees { + Some(data) => parse_general_subtrees(py, data)?, + None => py.None(), + }; + Ok(Some( + x509_module + .getattr("NameConstraints")? + .call1((permitted_subtrees, excluded_subtrees))?, + )) + } else { + Ok(None) + } + }, + ) + } + // This getter exists for compatibility with pyOpenSSL and will be removed. + // DO NOT RELY ON IT. WE WILL BREAK YOU WHEN WE FEEL LIKE IT. + #[getter] + fn _x509<'p>( + slf: pyo3::pycell::PyRef<'_, Self>, + py: pyo3::Python<'p>, + ) -> Result<&'p pyo3::PyAny, PyAsn1Error> { + let cryptography_warning = py.import("cryptography.utils")?.getattr("DeprecatedIn35")?; + let warnings = py.import("warnings")?; + warnings.call_method1( + "warn", + ( + "This version of cryptography contains a temporary pyOpenSSL fallback path. Upgrade pyOpenSSL now.", + cryptography_warning, + ), + )?; + let backend = py + .import("cryptography.hazmat.backends.openssl.backend")? + .getattr("backend")?; + Ok(backend.call_method1("_cert2ossl", (slf,))?) + } +} + +fn cert_version(py: pyo3::Python<'_>, version: u8) -> Result<&pyo3::PyAny, PyAsn1Error> { + let x509_module = py.import("cryptography.x509")?; + match version { + 0 => Ok(x509_module.getattr("Version")?.get_item("v1")?), + 2 => Ok(x509_module.getattr("Version")?.get_item("v3")?), + _ => Err(PyAsn1Error::from(pyo3::PyErr::from_instance( + x509_module + .getattr("InvalidVersion")? + .call1((format!("{} is not a valid X509 version", version), version))?, + ))), + } +} + +#[pyo3::prelude::pyfunction] +fn load_pem_x509_certificate(py: pyo3::Python<'_>, data: &[u8]) -> PyAsn1Result { + let parsed = pem::parse(data)?; + if parsed.tag != "CERTIFICATE" { + return Err(PyAsn1Error::from(pyo3::exceptions::PyValueError::new_err( + "Valid PEM but no BEGIN CERTIFICATE/END CERTIFICATE delimiters. Are you sure this is a certificate?" + ))); + } + load_der_x509_certificate(py, &parsed.contents) +} + +#[pyo3::prelude::pyfunction] +fn load_der_x509_certificate(py: pyo3::Python<'_>, data: &[u8]) -> PyAsn1Result { + let raw = OwnedRawCertificate::try_new(data.to_vec(), |data| asn1::parse_single(data))?; + // Parse cert version immediately so we can raise error on parse if it is invalid. + cert_version(py, raw.borrow_value().tbs_cert.version)?; + Ok(Certificate { + raw, + cached_extensions: None, + }) +} + pub(crate) fn parse_and_cache_extensions< 'p, F: Fn(&asn1::ObjectIdentifier<'_>, &[u8]) -> Result, PyAsn1Error>, @@ -848,7 +1344,7 @@ pub(crate) fn parse_scts( } #[pyo3::prelude::pyfunction] -fn parse_x509_extension(py: pyo3::Python<'_>, der_oid: &[u8], ext_data: &[u8]) -> PyAsn1Result { +fn parse_csr_extension(py: pyo3::Python<'_>, der_oid: &[u8], ext_data: &[u8]) -> PyAsn1Result { let oid = asn1::ObjectIdentifier::from_der(der_oid).unwrap(); let x509_module = py.import("cryptography.x509")?; @@ -945,9 +1441,6 @@ fn parse_x509_extension(py: pyo3::Python<'_>, der_oid: &[u8], ext_data: &[u8]) - .getattr("PolicyConstraints")? .call1((pc.require_explicit_policy, pc.inhibit_policy_mapping))? .to_object(py)) - } else if oid == *PRECERT_POISON_OID { - asn1::parse_single::<()>(ext_data)?; - Ok(x509_module.getattr("PrecertPoison")?.call0()?.to_object(py)) } else if oid == *OCSP_NO_CHECK_OID { asn1::parse_single::<()>(ext_data)?; Ok(x509_module.getattr("OCSPNoCheck")?.call0()?.to_object(py)) @@ -977,13 +1470,6 @@ fn parse_x509_extension(py: pyo3::Python<'_>, der_oid: &[u8], ext_data: &[u8]) - .getattr("FreshestCRL")? .call1((parse_distribution_points(py, ext_data)?,))? .to_object(py)) - } else if oid == *PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS_OID { - let contents = asn1::parse_single::<&[u8]>(ext_data)?; - let scts = parse_scts(py, contents, LogEntryType::PreCertificate)?; - Ok(x509_module - .getattr("PrecertificateSignedCertificateTimestamps")? - .call1((scts,))? - .to_object(py)) } else if oid == *NAME_CONSTRAINTS_OID { let nc = asn1::parse_single::>(ext_data)?; let permitted_subtrees = match nc.permitted_subtrees { @@ -1116,12 +1602,15 @@ fn parse_crl_extension(py: pyo3::Python<'_>, der_oid: &[u8], ext_data: &[u8]) -> pub(crate) fn create_submodule(py: pyo3::Python<'_>) -> pyo3::PyResult<&pyo3::prelude::PyModule> { let submod = pyo3::prelude::PyModule::new(py, "x509")?; - submod.add_wrapped(pyo3::wrap_pyfunction!(parse_x509_extension))?; + submod.add_wrapped(pyo3::wrap_pyfunction!(load_der_x509_certificate))?; + submod.add_wrapped(pyo3::wrap_pyfunction!(load_pem_x509_certificate))?; + submod.add_wrapped(pyo3::wrap_pyfunction!(parse_csr_extension))?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_crl_entry_ext))?; submod.add_wrapped(pyo3::wrap_pyfunction!(parse_crl_extension))?; submod.add_wrapped(pyo3::wrap_pyfunction!( encode_precertificate_signed_certificate_timestamps ))?; + submod.add_class::()?; submod.add_class::()?; Ok(submod) diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index a59aa09f31bd..ebc1d8148bc0 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -11,7 +11,7 @@ import pytest -from cryptography import x509 +from cryptography import utils, x509 from cryptography.exceptions import InternalError, _Reasons from cryptography.hazmat.backends.openssl import decode_asn1, encode_asn1 from cryptography.hazmat.backends.openssl.backend import Backend, backend @@ -609,30 +609,6 @@ def test_password_length_limit(self): ) -class TestGOSTCertificate(object): - def test_numeric_string_x509_name_entry(self): - cert = _load_cert( - os.path.join("x509", "e-trust.ru.der"), - x509.load_der_x509_certificate, - backend, - ) - if backend._lib.CRYPTOGRAPHY_IS_LIBRESSL: - with pytest.raises(ValueError) as exc: - cert.subject - - # We assert on the message in this case because if the certificate - # fails to load it will also raise a ValueError and this test could - # erroneously pass. - assert str(exc.value) == "Unsupported ASN1 string type. Type: 18" - else: - assert ( - cert.subject.get_attributes_for_oid( - x509.ObjectIdentifier("1.2.643.3.131.1.1") - )[0].value - == "007710474375" - ) - - @pytest.mark.skipif( backend._lib.Cryptography_HAS_EVP_PKEY_DHX == 1, reason="Requires OpenSSL without EVP_PKEY_DHX (< 1.0.2)", @@ -709,3 +685,19 @@ def test_public_load_dhx_unsupported(self, key_path, loader_func, backend): ) with pytest.raises(ValueError): loader_func(key_bytes, backend) + + +def test_pyopenssl_cert_fallback(): + cert = _load_cert( + os.path.join("x509", "cryptography.io.pem"), + x509.load_pem_x509_certificate, + ) + x509_ossl = None + with pytest.warns(utils.CryptographyDeprecationWarning): + x509_ossl = cert._x509 + assert x509_ossl is not None + + from cryptography.hazmat.backends.openssl.x509 import _Certificate + + with pytest.warns(utils.CryptographyDeprecationWarning): + _Certificate(backend, x509_ossl) diff --git a/tests/hazmat/primitives/test_pkcs7.py b/tests/hazmat/primitives/test_pkcs7.py index 6bc65eef3104..60aa367dde09 100644 --- a/tests/hazmat/primitives/test_pkcs7.py +++ b/tests/hazmat/primitives/test_pkcs7.py @@ -104,8 +104,12 @@ def _pkcs7_verify(encoding, sig, msg, certs, options, backend): store = backend._lib.X509_STORE_new() backend.openssl_assert(store != backend._ffi.NULL) store = backend._ffi.gc(store, backend._lib.X509_STORE_free) + # This list is to keep the x509 values alive until end of function + ossl_certs = [] for cert in certs: - res = backend._lib.X509_STORE_add_cert(store, cert._x509) + ossl_cert = backend._cert2ossl(cert) + ossl_certs.append(ossl_cert) + res = backend._lib.X509_STORE_add_cert(store, ossl_cert) backend.openssl_assert(res == 1) if msg is None: res = backend._lib.PKCS7_verify( diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index fc36d5f4111b..db0a3e819820 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -60,7 +60,7 @@ def __init__(self, value): value = utils.read_only_property("_value") -def _load_cert(filename, loader, backend): +def _load_cert(filename, loader, backend=None): cert = load_vectors_from_file( filename=filename, loader=lambda pemfile: loader(pemfile.read(), backend), @@ -645,12 +645,12 @@ def test_load_pem_cert(self, backend): ) def test_negative_serial_number(self, backend): - cert = _load_cert( - os.path.join("x509", "custom", "negative_serial.pem"), - x509.load_pem_x509_certificate, - backend, - ) - assert cert.serial_number == -18008675309 + with pytest.raises(ValueError, match="TbsCertificate::serial"): + _load_cert( + os.path.join("x509", "custom", "negative_serial.pem"), + x509.load_pem_x509_certificate, + backend, + ) def test_alternate_rsa_with_sha1_oid(self, backend): cert = _load_cert( @@ -1039,6 +1039,20 @@ def test_ne(self, backend): assert cert != cert2 assert cert != object() + def test_ordering_unsupported(self, backend): + cert = _load_cert( + os.path.join("x509", "custom", "post2000utctime.pem"), + x509.load_pem_x509_certificate, + backend, + ) + cert2 = _load_cert( + os.path.join("x509", "custom", "post2000utctime.pem"), + x509.load_pem_x509_certificate, + backend, + ) + with pytest.raises(TypeError, match="cannot be ordered"): + cert > cert2 + def test_hash(self, backend): cert1 = _load_cert( os.path.join("x509", "custom", "post2000utctime.pem"), @@ -1073,9 +1087,17 @@ def test_version_1_cert(self, backend): assert cert.version is x509.Version.v1 def test_invalid_pem(self, backend): - with pytest.raises(ValueError): + with pytest.raises(ValueError, match="Unable to load"): x509.load_pem_x509_certificate(b"notacert", backend) + crl = load_vectors_from_file( + filename=os.path.join("x509", "custom", "crl_empty.pem"), + loader=lambda pemfile: pemfile.read(), + mode="rb", + ) + with pytest.raises(ValueError, match="Valid PEM but no"): + x509.load_pem_x509_certificate(crl, backend) + def test_invalid_der(self, backend): with pytest.raises(ValueError): x509.load_der_x509_certificate(b"notacert", backend) @@ -1183,9 +1205,9 @@ def test_certificate_repr(self, backend): backend, ) assert repr(cert) == ( - ", ...)>" + ", ...)>" ) def test_parse_tls_feature_extension(self, backend): @@ -3204,6 +3226,7 @@ def test_extensions(self, add_ext, backend): subject_private_key.public_key() ) + # Cert cert = ( x509.CertificateBuilder() .subject_name( @@ -3224,6 +3247,19 @@ def test_extensions(self, add_ext, backend): assert ext.critical is False assert ext.value == add_ext + # CSR + csr = ( + x509.CertificateSigningRequestBuilder() + .subject_name( + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) + ) + .add_extension(add_ext, False) + .sign(subject_private_key, hashes.SHA256()) + ) + ext = csr.extensions.get_extension_for_class(type(add_ext)) + assert ext.critical is False + assert ext.value == add_ext + def test_build_ca_request_with_path_length_none(self, backend): private_key = RSA_KEY_2048.private_key(backend) @@ -4178,6 +4214,20 @@ def test_tbs_certrequest_bytes(self, backend): ) +class TestGOSTCertificate(object): + def test_numeric_string_x509_name_entry(self): + cert = _load_cert( + os.path.join("x509", "e-trust.ru.der"), + x509.load_der_x509_certificate, + ) + assert ( + cert.subject.get_attributes_for_oid( + x509.ObjectIdentifier("1.2.643.3.131.1.1") + )[0].value + == "007710474375" + ) + + class TestECDSACertificate(object): def test_load_ecdsa_cert(self, backend): _skip_curve_unsupported(backend, ec.SECP384R1()) @@ -4348,14 +4398,12 @@ def test_unsupported_subject_public_key_info(self, backend): cert.public_key() def test_bad_time_in_validity(self, backend): - cert = _load_cert( - os.path.join("x509", "badasn1time.pem"), - x509.load_pem_x509_certificate, - backend, - ) - - with pytest.raises(ValueError, match="19020701025736Z"): - cert.not_valid_after + with pytest.raises(ValueError, match="Validity::not_after"): + _load_cert( + os.path.join("x509", "badasn1time.pem"), + x509.load_pem_x509_certificate, + backend, + ) class TestNameAttribute(object): From 4aabad3dbf101810323a0d19d71a6970203375f6 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 31 Jul 2021 11:17:51 -0400 Subject: [PATCH 0355/2380] Fixes #6158 -- added more type annotations (#6185) --- src/cryptography/hazmat/backends/openssl/dsa.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/dsa.py b/src/cryptography/hazmat/backends/openssl/dsa.py index d3c54b82fad1..fbce96c2121f 100644 --- a/src/cryptography/hazmat/backends/openssl/dsa.py +++ b/src/cryptography/hazmat/backends/openssl/dsa.py @@ -58,10 +58,10 @@ def __init__(self, backend, public_key, signature, algorithm): self._hash_ctx = hashes.Hash(self._algorithm, self._backend) - def update(self, data): + def update(self, data: bytes): self._hash_ctx.update(data) - def verify(self): + def verify(self) -> None: data_to_verify = self._hash_ctx.finalize() _dsa_sig_verify( @@ -282,7 +282,7 @@ def verify( signature: bytes, data: bytes, algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], - ): + ) -> None: data, algorithm = _calculate_digest_and_algorithm( self._backend, data, algorithm ) From eab2e804380cf17fd2a11e4c74eb5915235ee414 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Sun, 8 Aug 2021 16:17:31 +0200 Subject: [PATCH 0356/2380] Test with 3.0.0-beta2 (#6192) - OpenSSL 3.0.0-beta2 now uses lib64 on X86_64 - fail on implicit function definition --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 46450d94d0c7..c32b5c52f12e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1k"}} - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1k"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1k", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "3.0.0-beta1"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "3.0.0-beta2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "2.9.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.0.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.1.5"}} @@ -91,8 +91,8 @@ jobs: if: matrix.PYTHON.OPENSSL && steps.ossl-cache.outputs.cache-hit != 'true' - name: Set CFLAGS/LDFLAGS run: | - echo "CFLAGS=${CFLAGS} -I${OSSL_PATH}/include" >> $GITHUB_ENV - echo "LDFLAGS=${LDFLAGS} -L${OSSL_PATH}/lib -Wl,-rpath=${OSSL_PATH}/lib" >> $GITHUB_ENV + echo "CFLAGS=${CFLAGS} -Werror=implicit-function-declaration -I${OSSL_PATH}/include" >> $GITHUB_ENV + echo "LDFLAGS=${LDFLAGS} -L${OSSL_PATH}/lib -L${OSSL_PATH}/lib64 -Wl,-rpath=${OSSL_PATH}/lib -Wl,-rpath=${OSSL_PATH}/lib64" >> $GITHUB_ENV if: matrix.PYTHON.OPENSSL - name: Tests run: | From 50d51933b20714b3f2aabe7dc82a7dca31c7b24d Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 8 Aug 2021 10:23:55 -0400 Subject: [PATCH 0357/2380] Correct the documentation on crl_invalid_time.der (#6191) --- docs/development/test-vectors.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index ee8e617edd4d..6d096f63e43b 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -536,7 +536,7 @@ Custom X.509 Certificate Revocation List Vectors * ``crl_unrecognized_extension.der`` - Contains a CRL containing an unsupported extension type. The OID was encoded as "1.2.3.4.5" with an ``extnValue`` of ``abcdef``. -* ``crl_invalid_time.der`` - Contains a CRL with an invalid ``GeneralizedTime`` +* ``crl_invalid_time.der`` - Contains a CRL with an invalid ``UTCTime`` value in ``thisUpdate``. The signature on this CRL is invalid. X.509 OCSP Test Vectors From 97913343d6c8156cdb0e10707f398dae26f933b7 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 8 Aug 2021 11:47:49 -0400 Subject: [PATCH 0358/2380] remove twisted from downstream testing for now (#6193) spurious failures and no resolution so far --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c32b5c52f12e..cc7b9c2ccca0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -401,7 +401,6 @@ jobs: DOWNSTREAM: - paramiko - pyopenssl - - twisted - aws-encryption-sdk - dynamodb-encryption-sdk - certbot From db650fbc784e4ae9ffa7ca8ece7336db16ce0165 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 8 Aug 2021 13:13:44 -0400 Subject: [PATCH 0359/2380] fix OAEP pdf link (#6195) --- docs/hazmat/primitives/asymmetric/rsa.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst index 7a3e835a13d5..009e23ea45b9 100644 --- a/docs/hazmat/primitives/asymmetric/rsa.rst +++ b/docs/hazmat/primitives/asymmetric/rsa.rst @@ -778,4 +778,4 @@ Key interfaces .. _`Chinese Remainder Theorem`: https://en.wikipedia.org/wiki/RSA_%28cryptosystem%29#Using_the_Chinese_remainder_algorithm .. _`security proof`: https://eprint.iacr.org/2001/062.pdf .. _`recommended padding algorithm`: https://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html -.. _`proven secure`: https://cseweb.ucsd.edu/~mihir/papers/oae.pdf +.. _`proven secure`: https://cseweb.ucsd.edu/~mihir/papers/oaep.pdf From 3e93f53ba2516f0ef92af39ad5abf077aa6c2580 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 8 Aug 2021 15:46:27 -0400 Subject: [PATCH 0360/2380] more pypy (#6180) --- .github/workflows/wheel-builder.yml | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 29a1e154f473..1adb7cf2469b 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -3,6 +3,7 @@ on: workflow_dispatch: inputs: version: + description: The version to build required: true jobs: @@ -65,16 +66,25 @@ jobs: PYTHON: - VERSION: '3.8' ABI_VERSION: 'cp36' - DOWNLOAD_URL: 'https://www.python.org/ftp/python/3.8.2/python-3.8.2-macosx10.9.pkg' + DOWNLOAD_URL: 'https://www.python.org/ftp/python/3.8.10/python-3.8.10-macosx10.9.pkg' BIN_PATH: '/Library/Frameworks/Python.framework/Versions/3.8/bin/python3' + - VERSION: 'pypy-3.7' + BIN_PATH: 'pypy3' name: "${{ matrix.PYTHON.VERSION }} ABI ${{ matrix.PYTHON.ABI_VERSION }} macOS" steps: - uses: actions/checkout@v2.3.4 - - run: | + - name: Setup python + run: | curl "$PYTHON_DOWNLOAD_URL" -o python.pkg sudo installer -pkg python.pkg -target / env: PYTHON_DOWNLOAD_URL: ${{ matrix.PYTHON.DOWNLOAD_URL }} + if: contains(matrix.PYTHON.VERSION, 'pypy') == false + - name: Setup pypy + uses: actions/setup-python@v2.2.2 + with: + python-version: ${{ matrix.PYTHON.VERSION }} + if: contains(matrix.PYTHON.VERSION, 'pypy') - run: ${{ matrix.PYTHON.BIN_PATH }} -m pip install -U requests - name: Download OpenSSL run: | @@ -121,6 +131,11 @@ jobs: - {ARCH: 'x64', WINDOWS: 'win64', RUST_TRIPLE: 'x86_64-pc-windows-msvc'} PYTHON: - {VERSION: "3.8", MSVC_VERSION: "2019", "ABI_VERSION": "cp36"} + - {VERSION: "pypy-3.7", MSVC_VERSION: "2019"} + exclude: + # We need to exclude the below configuration because there is no 32-bit pypy3 + - WINDOWS: {ARCH: 'x86', WINDOWS: 'win32', RUST_TRIPLE: 'i686-pc-windows-msvc'} + PYTHON: {VERSION: "pypy-3.7", MSVC_VERSION: "2019"} name: "${{ matrix.PYTHON.VERSION }} ${{ matrix.WINDOWS.WINDOWS }} ${{ matrix.PYTHON.ABI_VERSION }}" steps: - uses: actions/checkout@v2.3.4 From e739727fc3ea3dd3237b45583ce5bd4f388b9c9f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Aug 2021 08:24:19 -0400 Subject: [PATCH 0361/2380] Bump redox_syscall from 0.2.9 to 0.2.10 in /src/rust (#6198) Bumps redox_syscall from 0.2.9 to 0.2.10. --- updated-dependencies: - dependency-name: redox_syscall dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 9efe36c6bf65..691efbcfaf6a 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -336,9 +336,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" dependencies = [ "bitflags", ] From 3ba2c3d3ac40876a49f9b58bf7eede00a696d0f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Aug 2021 08:26:47 -0400 Subject: [PATCH 0362/2380] Bump pyo3 from 0.14.1 to 0.14.2 in /src/rust (#6200) Bumps [pyo3](https://github.com/pyo3/pyo3) from 0.14.1 to 0.14.2. - [Release notes](https://github.com/pyo3/pyo3/releases) - [Changelog](https://github.com/PyO3/pyo3/blob/main/CHANGELOG.md) - [Commits](https://github.com/pyo3/pyo3/compare/v0.14.1...v0.14.2) --- updated-dependencies: - dependency-name: pyo3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 16 ++++++++-------- src/rust/Cargo.toml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 691efbcfaf6a..812a39a5b6b3 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -279,9 +279,9 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "338f7f3701e11fd7f76508c91fbcaabc982564bcaf4d1ca7e1574ff2b4778aec" +checksum = "af205762ba65eec9f27a2fa1a57a40644e8e3368784b8c8b2f2de48f6e8ddd96" dependencies = [ "cfg-if", "indoc", @@ -295,18 +295,18 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb2e98cc9ccc83d4f7115c8f925e0057e88c8d324b1bc4c2db4a7270c06ac9d" +checksum = "755944027ce803c7238e59c5a18e59c1d0a4553db50b23e9ba209a568353028d" dependencies = [ "once_cell", ] [[package]] name = "pyo3-macros" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfb8671a42d0ecc4bec8cc107ae96d49292ca20cd1968e09b98af4aafd516adf" +checksum = "cd31b36bccfd902c78804bd96c28ea93eac6fa0ca311f9d21ef2230b6665b29a" dependencies = [ "pyo3-macros-backend", "quote", @@ -315,9 +315,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9addf6dc422f05d4949cc0990195ee74fa43e3c3780cc9a1972fe9e7b68a9f48" +checksum = "c21c59ba36db9c823e931c662766b0dd01a030b1d96585b67d8857a96a56b972" dependencies = [ "proc-macro2", "pyo3-build-config", diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index aa4331ce96e3..45a853d83bd9 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] lazy_static = "1" -pyo3 = { version = "0.14.1" } +pyo3 = { version = "0.14.2" } asn1 = { version = "0.6", default-features = false, features = ["derive"] } pem = "0.8" chrono = { version = "0.4", default-features = false, features = ["alloc"] } From b48abfb7aeef94a4c6fe2051b494be4e46ed80eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Aug 2021 16:58:03 -0400 Subject: [PATCH 0363/2380] Bump asn1 from 0.6.0 to 0.6.1 in /src/rust (#6202) Bumps [asn1](https://github.com/alex/rust-asn1) from 0.6.0 to 0.6.1. - [Release notes](https://github.com/alex/rust-asn1/releases) - [Commits](https://github.com/alex/rust-asn1/compare/0.6.0...0.6.1) --- updated-dependencies: - dependency-name: asn1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 812a39a5b6b3..3e7ae7c10c34 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -16,9 +16,9 @@ checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" [[package]] name = "asn1" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9680a48fea09cb1af33dc233179b9723674ca43ad9e5c9d01ab6ad1c3c58c0dc" +checksum = "a9c13a3c9cd71e1799fc16511efe36d0281b60bce3b32b4b211156a7b1925bfd" dependencies = [ "asn1_derive", "chrono", @@ -26,9 +26,9 @@ dependencies = [ [[package]] name = "asn1_derive" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f828598cd99548327735aae5db2852e3d78d1508ed81543f204b8ca3cf3ba859" +checksum = "62fc4b7f90b9540f1719f333e3ed85100ea072035d690000d7c01252ecdff096" dependencies = [ "proc-macro2", "quote", From e889be5110a96e95ef91fccdb7bd18da08afa17b Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 9 Aug 2021 20:00:11 -0400 Subject: [PATCH 0364/2380] add concurrency to cancel in-progress jobs (#6203) * add concurrency to cancel in-progress jobs * empty commit to test canceling --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cc7b9c2ccca0..90e56ae978d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,11 @@ on: permissions: read-all +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + + jobs: linux: runs-on: ubuntu-latest From d4e04edd5938c9af62586f16329b3fcd87e1c35a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Aug 2021 08:41:31 -0400 Subject: [PATCH 0365/2380] Bump libc from 0.2.98 to 0.2.99 in /src/rust (#6205) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.98 to 0.2.99. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.98...0.2.99) --- updated-dependencies: - dependency-name: libc dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 3e7ae7c10c34..4ab9b0bf38f8 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -121,9 +121,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.98" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" +checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765" [[package]] name = "lock_api" From 5f5eb5493dd2453b98480330dbf149fc5a0489d1 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 10 Aug 2021 22:56:24 -0400 Subject: [PATCH 0366/2380] support arm64 in GHA (#6204) * support arm64 in GHA * separate workflow that only runs on main, version branches, and tags --- .github/workflows/arm64.yml | 52 +++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .github/workflows/arm64.yml diff --git a/.github/workflows/arm64.yml b/.github/workflows/arm64.yml new file mode 100644 index 000000000000..f8be149af632 --- /dev/null +++ b/.github/workflows/arm64.yml @@ -0,0 +1,52 @@ +name: Arm64 CI +on: + push: + branches: + - main + - '*.*.x' + tags: + - '*.*' + - '*.*.*' + +permissions: read-all + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + linux-arm64: + runs-on: [self-hosted, linux, ARM64] + container: ghcr.io/pyca/cryptography-runner-${{ matrix.IMAGE.IMAGE }} + strategy: + fail-fast: false + matrix: + IMAGE: + - {IMAGE: "ubuntu-focal:aarch64", TOXENV: "py38"} + name: "${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" + timeout-minutes: 20 + steps: + - name: "Delete workspace" # self-hosted runners need this, sigh + run: find ! -name '.' ! -name '..' -delete + - uses: actions/checkout@v2.3.4 + with: + persist-credentials: false + - uses: actions/cache@v2.1.6 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + src/rust/target/ + key: ${{ runner.os }}-${{ matrix.IMAGE.IMAGE }}-cargo-2-${{ hashFiles('**/Cargo.lock') }} + + - run: 'git clone --depth=1 https://github.com/google/wycheproof "$HOME/wycheproof"' + - run: 'tox -- --wycheproof-root="$HOME/wycheproof"' + env: + TOXENV: ${{ matrix.IMAGE.TOXENV }} + RUSTUP_HOME: /root/.rustup + CARGO_TARGET_DIR: ${{ format('{0}/src/rust/target/', github.workspace) }} + - uses: ./.github/actions/upload-coverage + with: + name: "${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" From b93f405c07a312945935a1a718d8d6e1b5153a9b Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 11 Aug 2021 22:47:25 -0400 Subject: [PATCH 0367/2380] Speed up RSA tests in 3.0.0 (#6206) * Speed up RSA tests in 3.0.0 RSA_check_key is slower in OpenSSL 3.0.0 due to improved primality checking. In normal use this is unlikely to be a problem since users don't load new keys constantly, but we do in our tests. This adds some private flags to allow skipping those checks for performance reasons. On my laptop with this patch it takes 16s to run test_rsa.py. The previous commit takes 72s. * black * different approach * skip rsa key checks in wycheproof wycheproof's tets don't rely on broken keys --- .../hazmat/backends/openssl/backend.py | 13 ++++++++++--- src/cryptography/hazmat/backends/openssl/rsa.py | 16 +++++++++++----- tests/conftest.py | 9 +++++++++ tests/hazmat/primitives/test_rsa.py | 10 +++++++--- tests/wycheproof/utils.py | 4 +++- 5 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 349205b13340..3603a1c34adb 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -182,6 +182,7 @@ def __init__(self): self._binding = binding.Binding() self._ffi = self._binding.ffi self._lib = self._binding.lib + self._rsa_skip_check_key = False self._fips_enabled = self._is_fips_enabled() self._cipher_registry = {} @@ -507,7 +508,9 @@ def generate_rsa_private_key(self, public_exponent, key_size): self.openssl_assert(res == 1) evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata) - return _RSAPrivateKey(self, rsa_cdata, evp_pkey) + return _RSAPrivateKey( + self, rsa_cdata, evp_pkey, self._rsa_skip_check_key + ) def generate_rsa_parameters_supported(self, public_exponent, key_size): return ( @@ -546,7 +549,9 @@ def load_rsa_private_numbers(self, numbers): self.openssl_assert(res == 1) evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata) - return _RSAPrivateKey(self, rsa_cdata, evp_pkey) + return _RSAPrivateKey( + self, rsa_cdata, evp_pkey, self._rsa_skip_check_key + ) def load_rsa_public_numbers(self, numbers): rsa._check_public_key_components(numbers.e, numbers.n) @@ -620,7 +625,9 @@ def _evp_pkey_to_private_key(self, evp_pkey): rsa_cdata = self._lib.EVP_PKEY_get1_RSA(evp_pkey) self.openssl_assert(rsa_cdata != self._ffi.NULL) rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) - return _RSAPrivateKey(self, rsa_cdata, evp_pkey) + return _RSAPrivateKey( + self, rsa_cdata, evp_pkey, self._rsa_skip_check_key + ) elif key_type == self._lib.EVP_PKEY_DSA: dsa_cdata = self._lib.EVP_PKEY_get1_DSA(evp_pkey) self.openssl_assert(dsa_cdata != self._ffi.NULL) diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py index 74375ca0e983..ab639c8c7f72 100644 --- a/src/cryptography/hazmat/backends/openssl/rsa.py +++ b/src/cryptography/hazmat/backends/openssl/rsa.py @@ -382,11 +382,17 @@ def verify(self) -> None: class _RSAPrivateKey(RSAPrivateKey): - def __init__(self, backend, rsa_cdata, evp_pkey): - res = backend._lib.RSA_check_key(rsa_cdata) - if res != 1: - errors = backend._consume_errors_with_text() - raise ValueError("Invalid private key", errors) + def __init__(self, backend, rsa_cdata, evp_pkey, _skip_check_key): + # RSA_check_key is slower in OpenSSL 3.0.0 due to improved + # primality checking. In normal use this is unlikely to be a problem + # since users don't load new keys constantly, but for TESTING we've + # added an init arg that allows skipping the checks. You should not + # use this in production code unless you understand the consequences. + if not _skip_check_key: + res = backend._lib.RSA_check_key(rsa_cdata) + if res != 1: + errors = backend._consume_errors_with_text() + raise ValueError("Invalid private key", errors) # Blinding is on by default in many versions of OpenSSL, but let's # just be conservative here. diff --git a/tests/conftest.py b/tests/conftest.py index 2fea50c17b8f..01aba7784586 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -33,3 +33,12 @@ def pytest_runtest_setup(item): def backend(request): check_backend_support(openssl_backend, request) return openssl_backend + + +@pytest.fixture +def disable_rsa_checks(backend): + # Use this fixture to skip RSA key checks in tests that need the + # performance. + backend._rsa_skip_check_key = True + yield + backend._rsa_skip_check_key = False diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 2666fdfc1787..d98bf638d4ec 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -402,7 +402,7 @@ class TestRSASignature(object): skip_message="Does not support PKCS1v1.5.", ) @pytest.mark.skip_fips(reason="SHA1 signing not supported in FIPS mode.") - def test_pkcs1v15_signing(self, backend, subtests): + def test_pkcs1v15_signing(self, backend, disable_rsa_checks, subtests): vectors = _flatten_pkcs1_examples( load_vectors_from_file( os.path.join("asymmetric", "RSA", "pkcs1v15sign-vectors.txt"), @@ -1527,7 +1527,9 @@ class TestRSADecryption(object): ), skip_message="Does not support PKCS1v1.5.", ) - def test_decrypt_pkcs1v15_vectors(self, backend, subtests): + def test_decrypt_pkcs1v15_vectors( + self, backend, disable_rsa_checks, subtests + ): vectors = _flatten_pkcs1_examples( load_vectors_from_file( os.path.join("asymmetric", "RSA", "pkcs1v15crypt-vectors.txt"), @@ -1650,7 +1652,9 @@ def test_decrypt_oaep_vectors(self, vector, backend): "Does not support OAEP using SHA224 MGF1 and SHA224 hash." ), ) - def test_decrypt_oaep_sha2_vectors(self, backend, subtests): + def test_decrypt_oaep_sha2_vectors( + self, backend, disable_rsa_checks, subtests + ): vectors = _build_oaep_sha2_vectors() for private, public, example, mgf1_alg, hash_alg in vectors: with subtests.test(): diff --git a/tests/wycheproof/utils.py b/tests/wycheproof/utils.py index eebbe7ce3bf6..3c18e62afa43 100644 --- a/tests/wycheproof/utils.py +++ b/tests/wycheproof/utils.py @@ -3,7 +3,9 @@ def wycheproof_tests(*paths): def wrapper(func): - def run_wycheproof(backend, subtests, pytestconfig): + def run_wycheproof( + backend, disable_rsa_checks, subtests, pytestconfig + ): wycheproof_root = pytestconfig.getoption( "--wycheproof-root", skip=True ) From f6a81b9c639481684d17ca3bbe5236b3b041d425 Mon Sep 17 00:00:00 2001 From: DivineHawk Date: Thu, 12 Aug 2021 08:09:23 -0400 Subject: [PATCH 0368/2380] Add RDN for emailAddress (#6100) * Add RDN for email address * Update test for nonstandard attribute OID * Fix indent --- src/cryptography/x509/name.py | 1 + tests/x509/test_x509.py | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/cryptography/x509/name.py b/src/cryptography/x509/name.py index b02fda9cfe67..cab8f4b790f1 100644 --- a/src/cryptography/x509/name.py +++ b/src/cryptography/x509/name.py @@ -46,6 +46,7 @@ class _ASN1Type(utils.Enum): NameOID.STREET_ADDRESS: "STREET", NameOID.DOMAIN_COMPONENT: "DC", NameOID.USER_ID: "UID", + NameOID.EMAIL_ADDRESS: "E", } diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index db0a3e819820..58dde9b1aa59 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -4509,10 +4509,8 @@ def test_distinugished_name(self): assert na.rfc4514_string() == r"UID=\# escape\+\,\;\00this\ " # Nonstandard attribute OID - na = x509.NameAttribute(NameOID.EMAIL_ADDRESS, "somebody@example.com") - assert ( - na.rfc4514_string() == "1.2.840.113549.1.9.1=somebody@example.com" - ) + na = x509.NameAttribute(NameOID.BUSINESS_CATEGORY, "banking") + assert na.rfc4514_string() == "2.5.4.15=banking" def test_empty_value(self): na = x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "") From d316405a5a53ab51c89b644febd2ed3bf9dba9de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Aug 2021 12:57:59 -0400 Subject: [PATCH 0369/2380] Bump bitflags from 1.2.1 to 1.3.1 in /src/rust (#6208) Bumps [bitflags](https://github.com/bitflags/bitflags) from 1.2.1 to 1.3.1. - [Release notes](https://github.com/bitflags/bitflags/releases) - [Changelog](https://github.com/bitflags/bitflags/blob/main/CHANGELOG.md) - [Commits](https://github.com/bitflags/bitflags/compare/1.2.1...1.3.1) --- updated-dependencies: - dependency-name: bitflags dependency-type: indirect update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 4ab9b0bf38f8..16429852ae3f 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -49,9 +49,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "2da1976d75adbe5fbc88130ecd119529cf1cc6a93ae1546d8696ee66f0d21af1" [[package]] name = "cfg-if" From 6c1c15feea8bb0b344e2b32a43d237dca8dcd9e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Aug 2021 08:41:31 -0400 Subject: [PATCH 0370/2380] Bump bitflags from 1.3.1 to 1.3.2 in /src/rust (#6211) Bumps [bitflags](https://github.com/bitflags/bitflags) from 1.3.1 to 1.3.2. - [Release notes](https://github.com/bitflags/bitflags/releases) - [Changelog](https://github.com/bitflags/bitflags/blob/main/CHANGELOG.md) - [Commits](https://github.com/bitflags/bitflags/compare/1.3.1...1.3.2) --- updated-dependencies: - dependency-name: bitflags dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 16429852ae3f..3541471995bb 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -49,9 +49,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "bitflags" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da1976d75adbe5fbc88130ecd119529cf1cc6a93ae1546d8696ee66f0d21af1" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "cfg-if" From 7eb9d5a7a3bee399c94d248f8faaad556aeb721c Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Tue, 17 Aug 2021 15:07:32 +0200 Subject: [PATCH 0371/2380] Add more debug assistance (#6210) Print Python version, platform, setuptools, pip, and setuptools_rust on failed builds. Signed-off-by: Christian Heimes --- setup.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/setup.py b/setup.py index f524c2be3d03..51ce120ed25f 100644 --- a/setup.py +++ b/setup.py @@ -153,6 +153,9 @@ # during PEP517 building and prints this text. setuptools raises SystemExit # when compilation fails right now, but it's possible this isn't stable # or a public API commitment so we'll remain ultra conservative. + + import pkg_resources + print( """ =============================DEBUG ASSISTANCE============================= @@ -166,6 +169,18 @@ https://cryptography.io/en/latest/faq.html 4) Ensure you have a recent Rust toolchain installed: https://cryptography.io/en/latest/installation.html#rust + """ + ) + print(f" Python: {'.'.join(str(v) for v in sys.version_info[:3])}") + print(f" platform: {platform.platform()}") + for dist in ["pip", "setuptools", "setuptools_rust"]: + try: + version = pkg_resources.get_distribution(dist).version + except pkg_resources.DistributionNotFound: + version = "n/a" + print(f" {dist}: {version}") + print( + """\ =============================DEBUG ASSISTANCE============================= """ ) From f7ba53cb5050c465338baa127abc0243663cf217 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Aug 2021 09:12:23 -0400 Subject: [PATCH 0372/2380] Bump dessant/lock-threads from 2.1.1 to 2.1.2 (#6212) Bumps [dessant/lock-threads](https://github.com/dessant/lock-threads) from 2.1.1 to 2.1.2. - [Release notes](https://github.com/dessant/lock-threads/releases) - [Changelog](https://github.com/dessant/lock-threads/blob/master/CHANGELOG.md) - [Commits](https://github.com/dessant/lock-threads/compare/v2.1.1...v2.1.2) --- updated-dependencies: - dependency-name: dessant/lock-threads dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/lock.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index 2e19c82c41f5..fe96f070d66a 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -11,7 +11,7 @@ jobs: lock: runs-on: ubuntu-latest steps: - - uses: dessant/lock-threads@v2.1.1 + - uses: dessant/lock-threads@v2.1.2 with: github-token: ${{ secrets.GITHUB_TOKEN }} issue-lock-inactive-days: 90 From 8e671be7a1f9738719617e2da08c26d9da2d44b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Aug 2021 08:52:00 -0400 Subject: [PATCH 0373/2380] Bump pyo3 from 0.14.2 to 0.14.3 in /src/rust (#6216) Bumps [pyo3](https://github.com/pyo3/pyo3) from 0.14.2 to 0.14.3. - [Release notes](https://github.com/pyo3/pyo3/releases) - [Changelog](https://github.com/PyO3/pyo3/blob/main/CHANGELOG.md) - [Commits](https://github.com/pyo3/pyo3/compare/v0.14.2...v0.14.3) --- updated-dependencies: - dependency-name: pyo3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 16 ++++++++-------- src/rust/Cargo.toml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 3541471995bb..5cd467f25f67 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -279,9 +279,9 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af205762ba65eec9f27a2fa1a57a40644e8e3368784b8c8b2f2de48f6e8ddd96" +checksum = "4ce0e80b2b35e9697353a25b0e4fa5374e38c451da2f86f0cd83c40e7f1d5191" dependencies = [ "cfg-if", "indoc", @@ -295,18 +295,18 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "755944027ce803c7238e59c5a18e59c1d0a4553db50b23e9ba209a568353028d" +checksum = "96007b58c38d68ae449ea4d82fbc390faf5f1f2c80c76a6e3d51385bceb56741" dependencies = [ "once_cell", ] [[package]] name = "pyo3-macros" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd31b36bccfd902c78804bd96c28ea93eac6fa0ca311f9d21ef2230b6665b29a" +checksum = "326afb5c23f9789d0a367c37d58275c4d0e97ca74f05b9a25c0d66c6395c1c7b" dependencies = [ "pyo3-macros-backend", "quote", @@ -315,9 +315,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c21c59ba36db9c823e931c662766b0dd01a030b1d96585b67d8857a96a56b972" +checksum = "7e38169a08f98219bba484d19100811a1646d4962706b75d60766d21dce64f9c" dependencies = [ "proc-macro2", "pyo3-build-config", diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 45a853d83bd9..d8c1f2c351cf 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] lazy_static = "1" -pyo3 = { version = "0.14.2" } +pyo3 = { version = "0.14.3" } asn1 = { version = "0.6", default-features = false, features = ["derive"] } pem = "0.8" chrono = { version = "0.4", default-features = false, features = ["alloc"] } From 6cc76c153e86cbb230231efde2e8dbe0b1234b28 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Aug 2021 08:52:45 -0400 Subject: [PATCH 0374/2380] Bump syn from 1.0.74 to 1.0.75 in /src/rust (#6217) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.74 to 1.0.75. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.74...1.0.75) --- updated-dependencies: - dependency-name: syn dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 5cd467f25f67..23af7bcf6e0b 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -378,9 +378,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "syn" -version = "1.0.74" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" +checksum = "b7f58f7e8eaa0009c5fec437aabf511bd9933e4b2d7407bd05273c01a8906ea7" dependencies = [ "proc-macro2", "quote", From dc05cc85ce3579e28b8ab1ff6ddcd72957e91824 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Aug 2021 08:53:21 -0400 Subject: [PATCH 0375/2380] Bump libc from 0.2.99 to 0.2.100 in /src/rust (#6218) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.99 to 0.2.100. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.99...0.2.100) --- updated-dependencies: - dependency-name: libc dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 23af7bcf6e0b..2f87394760f7 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -121,9 +121,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765" +checksum = "a1fa8cddc8fbbee11227ef194b5317ed014b8acbf15139bd716a18ad3fe99ec5" [[package]] name = "lock_api" From 62c270fba93501bcc1061e95093485573c8f0bc3 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 23 Aug 2021 19:45:21 -0400 Subject: [PATCH 0376/2380] move linkcheck to its own action (#6220) this lets us restart it with minimal blast radius --- .github/workflows/ci.yml | 24 ------------------------ .github/workflows/linkcheck.yml | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 24 deletions(-) create mode 100644 .github/workflows/linkcheck.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 90e56ae978d7..289c2c3fb200 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -447,27 +447,3 @@ jobs: env: CARGO_TARGET_DIR: ${{ format('{0}/src/rust/target/', github.workspace) }} - run: ./.github/downstream.d/${{ matrix.DOWNSTREAM }}.sh run - - docs-linkcheck: - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - runs-on: ubuntu-latest - name: "linkcheck" - timeout-minutes: 20 - steps: - - uses: actions/checkout@v2.3.4 - with: - persist-credentials: false - - name: Setup python - uses: actions/setup-python@v2.2.2 - with: - python-version: 3.9 - - uses: actions-rs/toolchain@v1.0.7 - with: - profile: minimal - toolchain: stable - override: true - default: true - - run: python -m pip install -U tox - - run: tox -r -- --color=yes - env: - TOXENV: docs-linkcheck diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml new file mode 100644 index 000000000000..e867b22f618e --- /dev/null +++ b/.github/workflows/linkcheck.yml @@ -0,0 +1,32 @@ +name: "linkcheck" +on: + push: + branches: + - main + +permissions: + contents: read + +jobs: + docs-linkcheck: + runs-on: ubuntu-latest + name: "linkcheck" + timeout-minutes: 20 + steps: + - uses: actions/checkout@v2.3.4 + with: + persist-credentials: false + - name: Setup python + uses: actions/setup-python@v2.2.2 + with: + python-version: 3.9 + - uses: actions-rs/toolchain@v1.0.7 + with: + profile: minimal + toolchain: stable + override: true + default: true + - run: python -m pip install -U tox + - run: tox -r -- --color=yes + env: + TOXENV: docs-linkcheck \ No newline at end of file From d98b2aa16fa2051b33b7fddc8c8c2d99c50901cf Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 23 Aug 2021 21:06:14 -0400 Subject: [PATCH 0377/2380] Don't cancel builds on main -- we always want to run those (#6221) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 289c2c3fb200..60797299056d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ on: permissions: read-all concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} cancel-in-progress: true From 4b1e1d448f83f2f4b285667262bd2e326bbd37b0 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 23 Aug 2021 21:06:51 -0400 Subject: [PATCH 0378/2380] #6221 but for a different workflow (#6222) --- .github/workflows/arm64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/arm64.yml b/.github/workflows/arm64.yml index f8be149af632..372bace94038 100644 --- a/.github/workflows/arm64.yml +++ b/.github/workflows/arm64.yml @@ -11,7 +11,7 @@ on: permissions: read-all concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} cancel-in-progress: true jobs: From f284cc86139d72ce3cfe3147523563ab57b0128c Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 24 Aug 2021 11:01:16 -0400 Subject: [PATCH 0379/2380] test against 1.1.1l (#6223) --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 60797299056d..8f343100698e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,9 +27,9 @@ jobs: - {VERSION: "pypy-3.6", TOXENV: "pypy3-nocoverage", COVERAGE: "false"} - {VERSION: "pypy-3.7", TOXENV: "pypy3-nocoverage", COVERAGE: "false"} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1k"}} - - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1k"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1k", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1l"}} + - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1l"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1l", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "3.0.0-beta2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "2.9.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.0.2"}} From b9eda9f993eabc0114a38f17f9a5e27a537f1bce Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 24 Aug 2021 12:18:12 -0400 Subject: [PATCH 0380/2380] mention we support 3.0.0 (#6224) --- CHANGELOG.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 429b3af61e8b..4304cf7baafe 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -18,6 +18,7 @@ Changelog accessed. * **BACKWARDS INCOMPATIBLE:** Values passed to the X.509 PEM parser must be a single PEM payload and will error on extraneous data. +* Added support for OpenSSL 3.0.0 as a compilation target. * Added support for :class:`~cryptography.hazmat.primitives.hashes.SM3` and :class:`~cryptography.hazmat.primitives.ciphers.algorithms.SM4`, From 69620d612690f5dbf66caacecb237170f5d599af Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 24 Aug 2021 13:45:21 -0400 Subject: [PATCH 0381/2380] port 3.4.8 changelog to main (#6226) --- CHANGELOG.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4304cf7baafe..39929f76ffe0 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -29,6 +29,14 @@ Changelog * Added ``rfc4514_attribute_name`` attribute to :attr:`x509.NameAttribute `, +.. _v3-4-8: + +3.4.8 - 2021-08-24 +~~~~~~~~~~~~~~~~~~ + +* Updated Windows, macOS, and ``manylinux`` wheels to be compiled with + OpenSSL 1.1.1l. + .. _v3-4-7: 3.4.7 - 2021-03-25 From bb0575debe2dbb98b59eb896c46782f350788faf Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 25 Aug 2021 20:02:51 -0400 Subject: [PATCH 0382/2380] bump libre versions for test (#6230) --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f343100698e..d671ddec620b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,8 +34,8 @@ jobs: - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "2.9.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.0.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.1.5"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.2.5"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.3.3"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.2.6"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.3.4"}} - {VERSION: "3.10-dev", TOXENV: "py310"} RUST: - stable From 93f733aeaa158bf00a5a52e65df0b259ddcb0d1d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Aug 2021 08:33:25 -0400 Subject: [PATCH 0383/2380] Bump libc from 0.2.100 to 0.2.101 in /src/rust (#6231) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.100 to 0.2.101. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.100...0.2.101) --- updated-dependencies: - dependency-name: libc dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 2f87394760f7..4a5adc344a0d 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -121,9 +121,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.100" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1fa8cddc8fbbee11227ef194b5317ed014b8acbf15139bd716a18ad3fe99ec5" +checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" [[package]] name = "lock_api" From 57fd59717951e7df4adc50d1c6499f3f641cef71 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Thu, 26 Aug 2021 14:24:41 +0100 Subject: [PATCH 0384/2380] add project_urls especially changelog (#6228) --- setup.cfg | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 setup.cfg diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 000000000000..b3a64b77bfc5 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,6 @@ +[metadata] +project_urls = + Documentation=https://cryptography.io/ + Source=https://github.com/pyca/cryptography/ + Issues=https://github.com/pyca/cryptography/issues + Changelog=https://cryptography.io/en/latest/changelog/ From 3c2488b8a2f46bb897128eb0ae0bde5a2347b307 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 29 Aug 2021 09:43:38 -0400 Subject: [PATCH 0385/2380] Added a missing test case for x509 scts (#6237) --- tests/x509/test_ocsp.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/x509/test_ocsp.py b/tests/x509/test_ocsp.py index 0b8e49074cba..0dc36648c850 100644 --- a/tests/x509/test_ocsp.py +++ b/tests/x509/test_ocsp.py @@ -819,6 +819,22 @@ def test_hash(self, backend): assert hash(sct1) == hash(sct2) assert hash(sct1) != hash(sct3) + def test_entry_type(self, backend): + [sct, _, _, _] = ( + _load_data( + os.path.join("x509", "ocsp", "resp-sct-extension.der"), + ocsp.load_der_ocsp_response, + ) + .single_extensions.get_extension_for_class( + x509.SignedCertificateTimestamps + ) + .value + ) + assert ( + sct.entry_type + == x509.certificate_transparency.LogEntryType.X509_CERTIFICATE + ) + class TestOCSPResponse(object): def test_bad_response(self): From cd4ae74ef123f8ce14f00a0c85f48a4b3b1a7d1f Mon Sep 17 00:00:00 2001 From: match man Date: Sun, 29 Aug 2021 16:45:19 +0300 Subject: [PATCH 0386/2380] Add more demonstrative code to examples (#6234) 1. In signature generation code example, add a `key' assignment so it can be run solely. 2. In verify() code example, add a positive case before the negative one. Also use copy() to do self authentication. Co-authored-by: Baofeng Wang --- docs/hazmat/primitives/mac/hmac.rst | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/hazmat/primitives/mac/hmac.rst b/docs/hazmat/primitives/mac/hmac.rst index 3695270b7ab2..5d44e1272d9b 100644 --- a/docs/hazmat/primitives/mac/hmac.rst +++ b/docs/hazmat/primitives/mac/hmac.rst @@ -28,10 +28,12 @@ of a message. .. doctest:: >>> from cryptography.hazmat.primitives import hashes, hmac + >>> key = b'test key. Beware! A real key should use os.urandom or TRNG to generate' >>> h = hmac.HMAC(key, hashes.SHA256()) >>> h.update(b"message to hash") - >>> h.finalize() - b'#F\xdaI\x8b"e\xc4\xf1\xbb\x9a\x8fc\xff\xf5\xdex.\xbc\xcd/+\x8a\x86\x1d\x84\'\xc3\xa6\x1d\xd8J' + >>> signature = h.finalize() + >>> signature + b'k\xd9\xb29\xefS\xf8\xcf\xec\xed\xbf\x95\xe6\x97X\x18\x9e%\x11DU1\x9fq}\x9a\x9c\xe0)y`=' If the backend doesn't support the requested ``algorithm`` an :class:`~cryptography.exceptions.UnsupportedAlgorithm` exception will be @@ -48,7 +50,10 @@ of a message. >>> h = hmac.HMAC(key, hashes.SHA256()) >>> h.update(b"message to hash") - >>> h.verify(b"an incorrect signature") + >>> h_copy = h.copy() # get a copy of `h' to be reused + >>> h.verify(signature) + >>> + >>> h_copy.verify(b"an incorrect signature") Traceback (most recent call last): ... cryptography.exceptions.InvalidSignature: Signature did not match digest. From 27374c62c7b2854ea22a01e9dd5894fa2ec77722 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 29 Aug 2021 10:05:32 -0400 Subject: [PATCH 0387/2380] FIPS 3.0.0 support (#6012) * FIPS 3.0.0 support * comments * remove unneeded error clear * review comments * small refactor * black * flake8 too * review feedback * oops * fix --- .github/workflows/build_openssl.sh | 12 ++++ .github/workflows/ci.yml | 7 +- src/_cffi_src/build_openssl.py | 3 +- src/_cffi_src/openssl/evp.py | 12 ++++ .../hazmat/backends/openssl/backend.py | 67 ++++++++++++++++--- .../hazmat/bindings/openssl/_conditional.py | 8 +++ .../hazmat/bindings/openssl/binding.py | 16 +++++ tests/conftest.py | 6 ++ tests/hazmat/primitives/test_dh.py | 2 + tests/hazmat/primitives/test_pkcs12.py | 10 ++- tests/hazmat/primitives/test_pkcs7.py | 10 ++- tests/hazmat/primitives/test_serialization.py | 18 ++++- tests/wycheproof/test_hmac.py | 2 +- tests/wycheproof/test_rsa.py | 7 ++ 14 files changed, 163 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build_openssl.sh b/.github/workflows/build_openssl.sh index 99c3f4d33805..440cdcecc69f 100755 --- a/.github/workflows/build_openssl.sh +++ b/.github/workflows/build_openssl.sh @@ -22,6 +22,18 @@ if [[ "${TYPE}" == "openssl" ]]; then # avoid installing the docs (for performance) # https://github.com/openssl/openssl/issues/6685#issuecomment-403838728 make install_sw install_ssldirs + # For OpenSSL 3.0.0 set up the FIPS config. This does not activate it by + # default, but allows programmatic activation at runtime + if [[ "${VERSION}" =~ 3.0.0 && "${CONFIG_FLAGS}" =~ enable-fips ]]; then + # As of alpha16 we have to install it separately and enable it in the config flags + make -j"$(nproc)" install_fips + pushd "${OSSL_PATH}" + # include the conf file generated as part of install_fips + sed -i "s:# .include fipsmodule.cnf:.include $(pwd)/ssl/fipsmodule.cnf:" ssl/openssl.cnf + # uncomment the FIPS section + sed -i 's:# fips = fips_sect:fips = fips_sect:' ssl/openssl.cnf + popd + fi popd elif [[ "${TYPE}" == "libressl" ]]; then curl -O "https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-${VERSION}.tar.gz" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d671ddec620b..0fb86db7f068 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,6 +31,7 @@ jobs: - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1l"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1l", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "3.0.0-beta2"}} + - {VERSION: "3.9", TOXENV: "py39", TOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.0.0-beta2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "2.9.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.0.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.1.5"}} @@ -39,7 +40,7 @@ jobs: - {VERSION: "3.10-dev", TOXENV: "py310"} RUST: - stable - name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" + name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 20 steps: - uses: actions/checkout@v2.3.4 @@ -86,7 +87,7 @@ jobs: path: ${{ github.workspace }}/osslcache # When altering the openssl build process you may need to increment the value on the end of this cache key # so that you can prevent it from fetching the cache and skipping the build step. - key: ${{ matrix.PYTHON.OPENSSL.TYPE }}-${{ matrix.PYTHON.OPENSSL.VERSION }}-${{ env.CONFIG_HASH }}-1 + key: ${{ matrix.PYTHON.OPENSSL.TYPE }}-${{ matrix.PYTHON.OPENSSL.VERSION }}-${{ env.CONFIG_HASH }}-2 if: matrix.PYTHON.OPENSSL - name: Build custom OpenSSL/LibreSSL run: .github/workflows/build_openssl.sh @@ -101,7 +102,7 @@ jobs: if: matrix.PYTHON.OPENSSL - name: Tests run: | - tox -r -- --color=yes --wycheproof-root=wycheproof + tox -r -- --color=yes --wycheproof-root=wycheproof ${{ matrix.PYTHON.TOXARGS }} env: TOXENV: ${{ matrix.PYTHON.TOXENV }} CARGO_TARGET_DIR: ${{ format('{0}/src/rust/target/', github.workspace) }} diff --git a/src/_cffi_src/build_openssl.py b/src/_cffi_src/build_openssl.py index df11130371d1..04d6d4611b33 100644 --- a/src/_cffi_src/build_openssl.py +++ b/src/_cffi_src/build_openssl.py @@ -79,6 +79,8 @@ def _extra_compile_args(platform): modules=[ # This goes first so we can define some cryptography-wide symbols. "cryptography", + # Provider comes early as well so we define OSSL_LIB_CTX + "provider", "aes", "asn1", "bignum", @@ -103,7 +105,6 @@ def _extra_compile_args(platform): "osrandom_engine", "pem", "pkcs12", - "provider", "rand", "rsa", "ssl", diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py index 2b2f995e389f..735b8c37cfa2 100644 --- a/src/_cffi_src/openssl/evp.py +++ b/src/_cffi_src/openssl/evp.py @@ -36,6 +36,7 @@ static const int Cryptography_HAS_ONESHOT_EVP_DIGEST_SIGN_VERIFY; static const long Cryptography_HAS_RAW_KEY; static const long Cryptography_HAS_EVP_DIGESTFINAL_XOF; +static const long Cryptography_HAS_300_FIPS; """ FUNCTIONS = """ @@ -165,6 +166,9 @@ size_t); int EVP_PKEY_get_raw_private_key(const EVP_PKEY *, unsigned char *, size_t *); int EVP_PKEY_get_raw_public_key(const EVP_PKEY *, unsigned char *, size_t *); + +int EVP_default_properties_is_fips_enabled(OSSL_LIB_CTX *); +int EVP_default_properties_enable_fips(OSSL_LIB_CTX *, int); """ CUSTOMIZATIONS = """ @@ -269,4 +273,12 @@ #ifndef EVP_PKEY_POLY1305 #define EVP_PKEY_POLY1305 NID_poly1305 #endif + +#if CRYPTOGRAPHY_OPENSSL_300_OR_GREATER +static const long Cryptography_HAS_300_FIPS = 1; +#else +static const long Cryptography_HAS_300_FIPS = 0; +int (*EVP_default_properties_is_fips_enabled)(OSSL_LIB_CTX *) = NULL; +int (*EVP_default_properties_enable_fips)(OSSL_LIB_CTX *, int) = NULL; +#endif """ diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 3603a1c34adb..1a1db1ccca60 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -157,8 +157,9 @@ class Backend(BackendInterface): b"aes-256-gcm", } _fips_ciphers = (AES, TripleDES) + # Sometimes SHA1 is still permissible. That logic is contained + # within the various *_supported methods. _fips_hashes = ( - hashes.SHA1, hashes.SHA224, hashes.SHA256, hashes.SHA384, @@ -172,6 +173,12 @@ class Backend(BackendInterface): hashes.SHAKE128, hashes.SHAKE256, ) + _fips_ecdh_curves = ( + ec.SECP224R1, + ec.SECP256R1, + ec.SECP384R1, + ec.SECP521R1, + ) _fips_rsa_min_key_size = 2048 _fips_rsa_min_public_exponent = 65537 _fips_dsa_min_modulus = 1 << 2048 @@ -200,17 +207,34 @@ def __init__(self): if self._lib.Cryptography_HAS_EVP_PKEY_DHX: self._dh_types.append(self._lib.EVP_PKEY_DHX) + def __repr__(self): + return "".format( + self.openssl_version_text(), self._fips_enabled + ) + def openssl_assert(self, ok, errors=None): return binding._openssl_assert(self._lib, ok, errors=errors) def _is_fips_enabled(self): - fips_mode = getattr(self._lib, "FIPS_mode", lambda: 0) - mode = fips_mode() + if self._lib.Cryptography_HAS_300_FIPS: + mode = self._lib.EVP_default_properties_is_fips_enabled( + self._ffi.NULL + ) + else: + mode = getattr(self._lib, "FIPS_mode", lambda: 0)() + if mode == 0: # OpenSSL without FIPS pushes an error on the error stack self._lib.ERR_clear_error() return bool(mode) + def _enable_fips(self): + # This function enables FIPS mode for OpenSSL 3.0.0 on installs that + # have the FIPS provider installed properly. + self._binding._enable_fips() + assert self._is_fips_enabled() + self._fips_enabled = self._is_fips_enabled() + def activate_builtin_random(self): if self._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE: # Obtain a new structural reference. @@ -306,17 +330,31 @@ def hash_supported(self, algorithm): return evp_md != self._ffi.NULL def scrypt_supported(self): - return self._lib.Cryptography_HAS_SCRYPT == 1 + if self._fips_enabled: + return False + else: + return self._lib.Cryptography_HAS_SCRYPT == 1 def hmac_supported(self, algorithm): + # FIPS mode still allows SHA1 for HMAC + if self._fips_enabled and isinstance(algorithm, hashes.SHA1): + return True + return self.hash_supported(algorithm) def create_hash_ctx(self, algorithm): return _HashContext(self, algorithm) def cipher_supported(self, cipher, mode): - if self._fips_enabled and not isinstance(cipher, self._fips_ciphers): - return False + if self._fips_enabled: + # FIPS mode requires AES or TripleDES, but only CBC/ECB allowed + # in TripleDES mode. + if not isinstance(cipher, self._fips_ciphers) or ( + isinstance(cipher, TripleDES) + and not isinstance(mode, (CBC, ECB)) + ): + return False + try: adapter = self._cipher_registry[type(cipher), type(mode)] except KeyError: @@ -720,7 +758,13 @@ def rsa_padding_supported(self, padding): if isinstance(padding, PKCS1v15): return True elif isinstance(padding, PSS) and isinstance(padding._mgf, MGF1): - return self.hash_supported(padding._mgf._algorithm) + # SHA1 is permissible in MGF1 in FIPS + if self._fips_enabled and isinstance( + padding._mgf._algorithm, hashes.SHA1 + ): + return True + else: + return self.hash_supported(padding._mgf._algorithm) elif isinstance(padding, OAEP) and isinstance(padding._mgf, MGF1): return ( self._oaep_hash_supported(padding._mgf._algorithm) @@ -1489,10 +1533,12 @@ def _handle_key_loading_error(self): raise ValueError("Unsupported public key algorithm.") else: + errors = binding._errors_with_text(errors) raise ValueError( "Could not deserialize key data. The data may be in an " "incorrect format or it may be encrypted with an unsupported " - "algorithm." + "algorithm.", + errors, ) def elliptic_curve_supported(self, curve): @@ -1777,6 +1823,11 @@ def create_ocsp_response( return _OCSPResponse(self, ocsp_resp) def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve): + if self._fips_enabled and not isinstance( + curve, self._fips_ecdh_curves + ): + return False + return self.elliptic_curve_supported(curve) and isinstance( algorithm, ec.ECDH ) diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index 912aff302607..5f403e610ebf 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -254,6 +254,13 @@ def cryptography_has_dtls_get_data_mtu(): ] +def cryptography_has_300_fips(): + return [ + "EVP_default_properties_is_fips_enabled", + "EVP_default_properties_enable_fips", + ] + + # This is a mapping of # {condition: function-returning-names-dependent-on-that-condition} so we can # loop over them and delete unsupported names at runtime. It will be removed @@ -305,4 +312,5 @@ def cryptography_has_dtls_get_data_mtu(): cryptography_has_op_no_renegotiation ), "Cryptography_HAS_DTLS_GET_DATA_MTU": cryptography_has_dtls_get_data_mtu, + "Cryptography_HAS_300_FIPS": cryptography_has_300_fips, } diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py index f651ab672383..92d5b2448a48 100644 --- a/src/cryptography/hazmat/bindings/openssl/binding.py +++ b/src/cryptography/hazmat/bindings/openssl/binding.py @@ -116,6 +116,22 @@ class Binding(object): def __init__(self): self._ensure_ffi_initialized() + def _enable_fips(self): + # This function enables FIPS mode for OpenSSL 3.0.0 on installs that + # have the FIPS provider installed properly. + _openssl_assert(self.lib, self.lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER) + self._base_provider = self.lib.OSSL_PROVIDER_load( + self.ffi.NULL, b"base" + ) + _openssl_assert(self.lib, self._base_provider != self.ffi.NULL) + self.lib._fips_provider = self.lib.OSSL_PROVIDER_load( + self.ffi.NULL, b"fips" + ) + _openssl_assert(self.lib, self.lib._fips_provider != self.ffi.NULL) + + res = self.lib.EVP_default_properties_enable_fips(self.ffi.NULL, 1) + _openssl_assert(self.lib, res == 1) + @classmethod def _register_osrandom_engine(cls): # Clear any errors extant in the queue before we start. In many diff --git a/tests/conftest.py b/tests/conftest.py index 01aba7784586..b2f963c534d6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,6 +10,11 @@ from .utils import check_backend_support +def pytest_configure(config): + if config.getoption("--enable-fips"): + openssl_backend._enable_fips() + + def pytest_report_header(config): return "\n".join( [ @@ -21,6 +26,7 @@ def pytest_report_header(config): def pytest_addoption(parser): parser.addoption("--wycheproof-root", default=None) + parser.addoption("--enable-fips", default=False) def pytest_runtest_setup(item): diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index 7efc09456e6d..29b77543c20a 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -663,6 +663,7 @@ def test_public_bytes(self, backend, encoding, loader_func): pub_num = key.public_numbers() assert loaded_pub_num == pub_num + @pytest.mark.skip_fips(reason="non-FIPS parameters") @pytest.mark.parametrize( ("key_path", "loader_func", "encoding", "is_dhx"), [ @@ -706,6 +707,7 @@ def test_public_bytes_match( ) assert serialized == key_bytes + @pytest.mark.skip_fips(reason="non-FIPS parameters") @pytest.mark.parametrize( ("key_path", "loader_func", "vec_path", "is_dhx"), [ diff --git a/tests/hazmat/primitives/test_pkcs12.py b/tests/hazmat/primitives/test_pkcs12.py index f99c121d9554..62006643769c 100644 --- a/tests/hazmat/primitives/test_pkcs12.py +++ b/tests/hazmat/primitives/test_pkcs12.py @@ -22,6 +22,9 @@ from ...doubles import DummyKeySerializationEncryption +@pytest.mark.skip_fips( + reason="PKCS12 unsupported in FIPS mode. So much bad crypto in it." +) class TestPKCS12Loading(object): def _test_load_pkcs12_ec_keys(self, filename, password, backend): cert = load_vectors_from_file( @@ -70,7 +73,6 @@ def test_load_pkcs12_ec_keys(self, filename, password, backend): only_if=lambda backend: backend.cipher_supported(_RC2(), None), skip_message="Does not support RC2", ) - @pytest.mark.skip_fips(reason="Unsupported algorithm in FIPS mode") def test_load_pkcs12_ec_keys_rc2(self, filename, password, backend): self._test_load_pkcs12_ec_keys(filename, password, backend) @@ -167,6 +169,9 @@ def _load_ca(backend): return cert, key +@pytest.mark.skip_fips( + reason="PKCS12 unsupported in FIPS mode. So much bad crypto in it." +) class TestPKCS12Creation(object): @pytest.mark.parametrize("name", [None, b"name"]) @pytest.mark.parametrize( @@ -275,6 +280,9 @@ def test_generate_unsupported_encryption_type(self, backend): assert str(exc.value) == "Unsupported key encryption type" +@pytest.mark.skip_fips( + reason="PKCS12 unsupported in FIPS mode. So much bad crypto in it." +) def test_pkcs12_ordering(): """ In OpenSSL < 3.0.0 PKCS12 parsing reverses the order. However, we diff --git a/tests/hazmat/primitives/test_pkcs7.py b/tests/hazmat/primitives/test_pkcs7.py index 60aa367dde09..519c01b57449 100644 --- a/tests/hazmat/primitives/test_pkcs7.py +++ b/tests/hazmat/primitives/test_pkcs7.py @@ -335,6 +335,9 @@ def test_sign_pem(self, backend): def test_sign_alternate_digests_der( self, hash_alg, expected_value, backend ): + if isinstance(hash_alg, hashes.SHA1) and backend._fips_enabled: + pytest.skip("SHA1 not supported in FIPS mode") + data = b"hello world" cert, key = _load_cert_key() builder = ( @@ -358,7 +361,12 @@ def test_sign_alternate_digests_der( (hashes.SHA512(), b"sha-512"), ], ) - def test_sign_alternate_digests_detached(self, hash_alg, expected_value): + def test_sign_alternate_digests_detached( + self, hash_alg, expected_value, backend + ): + if isinstance(hash_alg, hashes.SHA1) and backend._fips_enabled: + pytest.skip("SHA1 not supported in FIPS mode") + data = b"hello world" cert, key = _load_cert_key() builder = ( diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index ed3f8e7f8f05..5c845018437d 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -52,8 +52,19 @@ def _skip_fips_format(key_path, password, backend): if backend._fips_enabled: if key_path[0] == "Traditional_OpenSSL_Serialization": pytest.skip("Traditional OpenSSL format blocked in FIPS mode") - if key_path[0] == "PEM_Serialization" and password is not None: - pytest.skip("Encrypted PEM_Serialization blocked in FIPS mode") + if ( + key_path[0] in ("PEM_Serialization", "PKCS8") + and password is not None + ): + pytest.skip( + "The encrypted PEM vectors currently have encryption " + "that is not FIPS approved in the 3.0 provider" + ) + if key_path[0] == "DER_Serialization" and password is not None: + pytest.skip( + "The encrypted PKCS8 DER vectors currently have encryption " + "that is not FIPS approved in the 3.0 provider" + ) class TestBufferProtocolSerialization(object): @@ -67,6 +78,7 @@ class TestBufferProtocolSerialization(object): ], ) def test_load_der_rsa_private_key(self, key_path, password, backend): + _skip_fips_format(key_path, password, backend) data = load_vectors_from_file( os.path.join("asymmetric", *key_path), lambda derfile: derfile.read(), @@ -117,6 +129,7 @@ class TestDERSerialization(object): ], ) def test_load_der_rsa_private_key(self, key_path, password, backend): + _skip_fips_format(key_path, password, backend) key = load_vectors_from_file( os.path.join("asymmetric", *key_path), lambda derfile: load_der_private_key( @@ -814,6 +827,7 @@ def test_pks8_encrypted_corrupt_format(self, backend): with pytest.raises(ValueError): load_pem_private_key(key_data, password, backend) + @pytest.mark.skip_fips(reason="non-FIPS parameters") def test_rsa_pkcs8_encrypted_values(self, backend): pkey = load_vectors_from_file( os.path.join("asymmetric", "PKCS8", "enc-rsa-pkcs8.pem"), diff --git a/tests/wycheproof/test_hmac.py b/tests/wycheproof/test_hmac.py index bfc690795122..84b0c19a0539 100644 --- a/tests/wycheproof/test_hmac.py +++ b/tests/wycheproof/test_hmac.py @@ -41,7 +41,7 @@ def test_hmac(backend, wycheproof): hash_algo = _HMAC_ALGORITHMS[wycheproof.testfiledata["algorithm"]] if wycheproof.testgroup["tagSize"] // 8 != hash_algo.digest_size: pytest.skip("Truncated HMAC not supported") - if not backend.hash_supported(hash_algo): + if not backend.hmac_supported(hash_algo): pytest.skip("Hash {} not supported".format(hash_algo.name)) h = hmac.HMAC( diff --git a/tests/wycheproof/test_rsa.py b/tests/wycheproof/test_rsa.py index 73ff711154d9..79fd682b7e70 100644 --- a/tests/wycheproof/test_rsa.py +++ b/tests/wycheproof/test_rsa.py @@ -102,6 +102,13 @@ def test_rsa_pkcs1v15_signature_generation(backend, wycheproof): assert isinstance(key, rsa.RSAPrivateKey) digest = _DIGESTS[wycheproof.testgroup["sha"]] assert digest is not None + if backend._fips_enabled: + if key.key_size < 2048 or isinstance(digest, hashes.SHA1): + pytest.skip( + "Invalid params for FIPS. key: {} bits, digest: {}".format( + key.key_size, digest.name + ) + ) sig = key.sign( binascii.unhexlify(wycheproof.testcase["msg"]), From 5b966396a255cdb0f8e90f998c7e42b11ffdecd8 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 29 Aug 2021 10:19:36 -0400 Subject: [PATCH 0388/2380] split flake, rust, and docs jobs back into separate CI jobs (#6238) we previously combined these to simplify our CI matrix, but it's difficult to read the output and now that we have auto-cancellation job proliferation isn't really an issue. Reverting --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0fb86db7f068..fec19064ae39 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,9 @@ jobs: fail-fast: false matrix: PYTHON: - - {VERSION: "3.9", TOXENV: "flake,rust,docs", COVERAGE: "false"} + - {VERSION: "3.9", TOXENV: "flake", COVERAGE: "false"} + - {VERSION: "3.9", TOXENV: "rust", COVERAGE: "false"} + - {VERSION: "3.9", TOXENV: "docs", COVERAGE: "false"} - {VERSION: "pypy-3.6", TOXENV: "pypy3-nocoverage", COVERAGE: "false"} - {VERSION: "pypy-3.7", TOXENV: "pypy3-nocoverage", COVERAGE: "false"} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} From eb6f658e5fccf0f5a66e1d6bdb4dda4ced5c6aa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20Panzenb=C3=B6ck?= Date: Sun, 29 Aug 2021 19:43:16 +0200 Subject: [PATCH 0389/2380] add PKCS7_get0_signers(), X509_STORE_set_purpose(), and X509_PURPOSE_* (#6187) * add PKCS7_get0_signers(), X509_STORE_set_purpose(), and X509_PURPOSE_* * removed argument names of X509_STORE_set_purpose() and PKCS7_get0_signers() * Update pkcs7.py * Update x509_vfy.py Co-authored-by: Paul Kehrer --- src/_cffi_src/openssl/pkcs7.py | 5 +++++ src/_cffi_src/openssl/x509_vfy.py | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/_cffi_src/openssl/pkcs7.py b/src/_cffi_src/openssl/pkcs7.py index 052bd050819f..b58b293a5c0c 100644 --- a/src/_cffi_src/openssl/pkcs7.py +++ b/src/_cffi_src/openssl/pkcs7.py @@ -68,6 +68,11 @@ int PKCS7_verify(PKCS7 *, Cryptography_STACK_OF_X509 *, X509_STORE *, BIO *, BIO *, int); PKCS7 *SMIME_read_PKCS7(BIO *, BIO **); +/* Included due to external consumer, see + https://github.com/pyca/pyopenssl/issues/1031 */ +Cryptography_STACK_OF_X509 *PKCS7_get0_signers(PKCS7 *, + Cryptography_STACK_OF_X509 *, + int); int PKCS7_type_is_signed(PKCS7 *); int PKCS7_type_is_enveloped(PKCS7 *); diff --git a/src/_cffi_src/openssl/x509_vfy.py b/src/_cffi_src/openssl/x509_vfy.py index 4642d827765c..16c0ae0beb50 100644 --- a/src/_cffi_src/openssl/x509_vfy.py +++ b/src/_cffi_src/openssl/x509_vfy.py @@ -124,6 +124,20 @@ static const long X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS; static const long X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS; static const long X509_CHECK_FLAG_NEVER_CHECK_SUBJECT; + +/* Included due to external consumer, see + https://github.com/pyca/pyopenssl/issues/1031 */ +static const long X509_PURPOSE_SSL_CLIENT; +static const long X509_PURPOSE_SSL_SERVER; +static const long X509_PURPOSE_NS_SSL_SERVER; +static const long X509_PURPOSE_SMIME_SIGN; +static const long X509_PURPOSE_SMIME_ENCRYPT; +static const long X509_PURPOSE_CRL_SIGN; +static const long X509_PURPOSE_ANY; +static const long X509_PURPOSE_OCSP_HELPER; +static const long X509_PURPOSE_TIMESTAMP_SIGN; +static const long X509_PURPOSE_MIN; +static const long X509_PURPOSE_MAX; """ FUNCTIONS = """ @@ -137,6 +151,9 @@ int X509_STORE_set1_param(X509_STORE *, X509_VERIFY_PARAM *); int X509_STORE_set_default_paths(X509_STORE *); int X509_STORE_set_flags(X509_STORE *, unsigned long); +/* Included due to external consumer, see + https://github.com/pyca/pyopenssl/issues/1031 */ +int X509_STORE_set_purpose(X509_STORE *, int); void X509_STORE_free(X509_STORE *); /* X509_STORE_CTX */ From b5c3bd213099b6e35c30bee5d37258b5f084b901 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 29 Aug 2021 14:18:18 -0500 Subject: [PATCH 0390/2380] turn on mypy disallow implicit reexport and fix issues (#6240) * turn on mypy disallow implicit reexport and fix issues * import ordering --- pyproject.toml | 1 + src/cryptography/hazmat/primitives/asymmetric/padding.py | 4 +++- src/cryptography/hazmat/primitives/ciphers/base.py | 4 +++- src/cryptography/x509/__init__.py | 2 ++ src/cryptography/x509/base.py | 4 ++-- tests/hazmat/primitives/test_pkcs12.py | 2 +- tests/hazmat/primitives/test_pkcs7.py | 3 +-- tests/hazmat/primitives/test_serialization.py | 2 +- 8 files changed, 14 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 913a4e46d1c1..cffd317087d5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,6 +24,7 @@ markers = [ [tool.mypy] show_error_codes = true check_untyped_defs = true +no_implicit_reexport = true [[tool.mypy.overrides]] module = [ diff --git a/src/cryptography/hazmat/primitives/asymmetric/padding.py b/src/cryptography/hazmat/primitives/asymmetric/padding.py index 301c64c92898..a97c5db09177 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/padding.py +++ b/src/cryptography/hazmat/primitives/asymmetric/padding.py @@ -6,7 +6,9 @@ import typing from cryptography.hazmat.primitives import hashes -from cryptography.hazmat.primitives._asymmetric import AsymmetricPadding +from cryptography.hazmat.primitives._asymmetric import ( + AsymmetricPadding as AsymmetricPadding, +) from cryptography.hazmat.primitives.asymmetric import rsa diff --git a/src/cryptography/hazmat/primitives/ciphers/base.py b/src/cryptography/hazmat/primitives/ciphers/base.py index 7261a275b42e..ad3c7ed8fdc4 100644 --- a/src/cryptography/hazmat/primitives/ciphers/base.py +++ b/src/cryptography/hazmat/primitives/ciphers/base.py @@ -16,7 +16,9 @@ ) from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.backends.interfaces import Backend, CipherBackend -from cryptography.hazmat.primitives._cipheralgorithm import CipherAlgorithm +from cryptography.hazmat.primitives._cipheralgorithm import ( + CipherAlgorithm as CipherAlgorithm, +) from cryptography.hazmat.primitives.ciphers import modes diff --git a/src/cryptography/x509/__init__.py b/src/cryptography/x509/__init__.py index 793714693040..5003e09d3fa9 100644 --- a/src/cryptography/x509/__init__.py +++ b/src/cryptography/x509/__init__.py @@ -244,4 +244,6 @@ "PrecertPoison", "OCSPNonce", "SignedCertificateTimestamps", + "SignatureAlgorithmOID", + "NameOID", ] diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index 3c626efc57cf..0e8154425f5d 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -21,8 +21,8 @@ rsa, ) from cryptography.hazmat.primitives.asymmetric.types import ( - PRIVATE_KEY_TYPES, - PUBLIC_KEY_TYPES, + PRIVATE_KEY_TYPES as PRIVATE_KEY_TYPES, + PUBLIC_KEY_TYPES as PUBLIC_KEY_TYPES, ) from cryptography.x509.extensions import Extension, ExtensionType, Extensions from cryptography.x509.name import Name diff --git a/tests/hazmat/primitives/test_pkcs12.py b/tests/hazmat/primitives/test_pkcs12.py index 62006643769c..47262e5e1922 100644 --- a/tests/hazmat/primitives/test_pkcs12.py +++ b/tests/hazmat/primitives/test_pkcs12.py @@ -18,8 +18,8 @@ serialize_key_and_certificates, ) -from .utils import load_vectors_from_file from ...doubles import DummyKeySerializationEncryption +from ...utils import load_vectors_from_file @pytest.mark.skip_fips( diff --git a/tests/hazmat/primitives/test_pkcs7.py b/tests/hazmat/primitives/test_pkcs7.py index 519c01b57449..f90fd1810b8f 100644 --- a/tests/hazmat/primitives/test_pkcs7.py +++ b/tests/hazmat/primitives/test_pkcs7.py @@ -14,8 +14,7 @@ from cryptography.hazmat.primitives.asymmetric import ed25519 from cryptography.hazmat.primitives.serialization import pkcs7 -from .utils import load_vectors_from_file -from ...utils import raises_unsupported_algorithm +from ...utils import load_vectors_from_file, raises_unsupported_algorithm class TestPKCS7Loading(object): diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index 5c845018437d..c9b8fd641840 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -43,9 +43,9 @@ from .utils import ( _check_dsa_private_numbers, _check_rsa_private_numbers, - load_vectors_from_file, ) from ...doubles import DummyKeySerializationEncryption +from ...utils import load_vectors_from_file def _skip_fips_format(key_path, password, backend): From 4dbac5c5c716827edc557774038280b280d31643 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 29 Aug 2021 15:35:20 -0400 Subject: [PATCH 0391/2380] Use action to clone wycheproof for consistency (#6241) --- .github/workflows/ci.yml | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fec19064ae39..f1f9619cf374 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,7 +68,10 @@ jobs: toolchain: ${{ matrix.RUST }} override: true default: true - - run: git clone --depth=1 https://github.com/google/wycheproof + - uses: actions/checkout@v2.3.4 + with: + repository: "google/wycheproof" + path: "wycheproof" - run: python -m pip install tox requests coverage - name: Compute config hash and set config vars run: | @@ -147,12 +150,15 @@ jobs: src/rust/target/ key: ${{ runner.os }}-${{ matrix.IMAGE.IMAGE }}-cargo-2-${{ hashFiles('**/Cargo.lock') }} - - run: 'git clone --depth=1 https://github.com/google/wycheproof "$HOME/wycheproof"' + - uses: actions/checkout@v2.3.4 + with: + repository: "google/wycheproof" + path: "wycheproof" - run: | echo "OPENSSL_FORCE_FIPS_MODE=1" >> $GITHUB_ENV echo "CFLAGS=-DUSE_OSRANDOM_RNG_FOR_TESTING" >> $GITHUB_ENV if: matrix.IMAGE.FIPS - - run: 'tox -- --wycheproof-root="$HOME/wycheproof"' + - run: 'tox -- --wycheproof-root="wycheproof"' env: TOXENV: ${{ matrix.IMAGE.TOXENV }} RUSTUP_HOME: /root/.rustup @@ -200,7 +206,10 @@ jobs: toolchain: ${{ matrix.RUST }} override: true default: true - - run: git clone --depth=1 https://github.com/google/wycheproof + - uses: actions/checkout@v2.3.4 + with: + repository: "google/wycheproof" + path: "wycheproof" - run: python -m pip install tox coverage - name: Tests run: | @@ -248,7 +257,10 @@ jobs: version: latest if: steps.cargo-cache.outputs.cache-hit != 'true' - - run: git clone --depth=1 https://github.com/google/wycheproof + - uses: actions/checkout@v2.3.4 + with: + repository: "google/wycheproof" + path: "wycheproof" - run: python -m pip install tox coverage - name: Tests run: | @@ -314,7 +326,10 @@ jobs: - run: python -m pip install tox requests coverage - - run: git clone https://github.com/google/wycheproof + - uses: actions/checkout@v2.3.4 + with: + repository: "google/wycheproof" + path: "wycheproof" - name: Download OpenSSL run: | @@ -390,7 +405,10 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} shell: bash - - run: git clone https://github.com/google/wycheproof + - uses: actions/checkout@v2.3.4 + with: + repository: "google/wycheproof" + path: "wycheproof" - run: tox -r -- --color=yes --wycheproof-root=wycheproof --num-shards=4 --shard-id=${{ matrix.JOB_NUMBER }} env: From 4b2a3d630c3b4c8895c2e8199a183f260a4b3569 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 29 Aug 2021 16:05:47 -0400 Subject: [PATCH 0392/2380] same as #6241 but for arm64 (#6242) --- .github/workflows/arm64.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/arm64.yml b/.github/workflows/arm64.yml index 372bace94038..39fe46517ec8 100644 --- a/.github/workflows/arm64.yml +++ b/.github/workflows/arm64.yml @@ -41,8 +41,11 @@ jobs: src/rust/target/ key: ${{ runner.os }}-${{ matrix.IMAGE.IMAGE }}-cargo-2-${{ hashFiles('**/Cargo.lock') }} - - run: 'git clone --depth=1 https://github.com/google/wycheproof "$HOME/wycheproof"' - - run: 'tox -- --wycheproof-root="$HOME/wycheproof"' + - uses: actions/checkout@v2.3.4 + with: + repository: "google/wycheproof" + path: "wycheproof" + - run: 'tox -- --wycheproof-root="wycheproof"' env: TOXENV: ${{ matrix.IMAGE.TOXENV }} RUSTUP_HOME: /root/.rustup From e703fb9f3a8114513481f032913e73b09fc509c8 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 29 Aug 2021 16:38:34 -0500 Subject: [PATCH 0393/2380] Port most of setup.py to setup.cfg (#6239) * try porting over setup.py config * reduce duplication * flake * move long_description, remove more lines from setup.py --- setup.cfg | 82 ++++++++++++++++++++++++++++++ setup.py | 94 +---------------------------------- src/cryptography/__about__.py | 15 ------ src/cryptography/__init__.py | 10 ---- 4 files changed, 84 insertions(+), 117 deletions(-) diff --git a/setup.cfg b/setup.cfg index b3a64b77bfc5..b8c396964a45 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,88 @@ [metadata] +name = cryptography +version = attr: cryptography.__version__ +description = cryptography is a package which provides cryptographic recipes and primitives to Python developers. +long_description = file: README.rst +long_description_content_type = text/x-rst +license = BSD or Apache License, Version 2.0 +url = https://github.com/pyca/cryptography +author = The Python Cryptographic Authority and individual contributors +author_email = cryptography-dev@python.org project_urls = Documentation=https://cryptography.io/ Source=https://github.com/pyca/cryptography/ Issues=https://github.com/pyca/cryptography/issues Changelog=https://cryptography.io/en/latest/changelog/ +classifiers = + Development Status :: 5 - Production/Stable + Intended Audience :: Developers + License :: OSI Approved :: Apache Software License + License :: OSI Approved :: BSD License + Natural Language :: English + Operating System :: MacOS :: MacOS X + Operating System :: POSIX + Operating System :: POSIX :: BSD + Operating System :: POSIX :: Linux + Operating System :: Microsoft :: Windows + Programming Language :: Python + Programming Language :: Python :: 3 + Programming Language :: Python :: 3 :: Only + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: Implementation :: CPython + Programming Language :: Python :: Implementation :: PyPy + Topic :: Security :: Cryptography + +[options] +python_requires = >=3.6 +include_package_data = True +zip_safe = False +package_dir = + =src +packages = find: +ext_package = cryptography.hazmat.bindings +# `install_requires` and `setup_requires` must be kept in sync with +# `pyproject.toml` +install_requires = + cffi >=1.12 +setup_requires = + cffi >=1.12 + setuptools_rust >= 0.11.4 + +[options.packages.find] +where = src +exclude = + _cffi_src + _cffi_src.* + +[options.extras_require] +test = + pytest>=6.2.0 + pytest-cov + pytest-subtests + pytest-xdist + pretend + iso8601 + pytz + hypothesis>=1.11.4,!=3.79.2 +docs = + sphinx >= 1.6.5,!=1.8.0,!=3.1.0,!=3.1.1 + sphinx_rtd_theme +docstest = + doc8 + pyenchant >= 1.6.11 + twine >= 1.12.0 + sphinxcontrib-spelling >= 4.0.1 +sdist = + setuptools_rust >= 0.11.4 +pep8test = + black + flake8 + flake8-import-order + pep8-naming +# This extra is for OpenSSH private keys that use bcrypt KDF +# Versions: v3.1.3 - ignore_few_rounds, v3.1.5 - abi3 +ssh = + bcrypt >= 3.1.5 \ No newline at end of file diff --git a/setup.py b/setup.py index 51ce120ed25f..f91c04cfc895 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ import platform import sys -from setuptools import find_packages, setup +from setuptools import setup try: from setuptools_rust import RustExtension @@ -34,99 +34,9 @@ # means that we need to add the src/ directory to the sys.path. sys.path.insert(0, src_dir) -about = {} -with open(os.path.join(src_dir, "cryptography", "__about__.py")) as f: - exec(f.read(), about) - - -# `install_requirements` and `setup_requirements` must be kept in sync with -# `pyproject.toml` -setuptools_rust = "setuptools-rust>=0.11.4" -install_requirements = ["cffi>=1.12"] -setup_requirements = install_requirements + [setuptools_rust] - -with open(os.path.join(base_dir, "README.rst")) as f: - long_description = f.read() - - try: + # See setup.cfg for most of the config metadata. setup( - name=about["__title__"], - version=about["__version__"], - description=about["__summary__"], - long_description=long_description, - long_description_content_type="text/x-rst", - license=about["__license__"], - url=about["__uri__"], - author=about["__author__"], - author_email=about["__email__"], - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", - "License :: OSI Approved :: BSD License", - "Natural Language :: English", - "Operating System :: MacOS :: MacOS X", - "Operating System :: POSIX", - "Operating System :: POSIX :: BSD", - "Operating System :: POSIX :: Linux", - "Operating System :: Microsoft :: Windows", - "Programming Language :: Python", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: Implementation :: CPython", - "Programming Language :: Python :: Implementation :: PyPy", - "Topic :: Security :: Cryptography", - ], - package_dir={"": "src"}, - packages=find_packages( - where="src", exclude=["_cffi_src", "_cffi_src.*"] - ), - include_package_data=True, - python_requires=">=3.6", - install_requires=install_requirements, - setup_requires=setup_requirements, - extras_require={ - "test": [ - "pytest>=6.2.0", - "pytest-cov", - "pytest-subtests", - "pytest-xdist", - "pretend", - "iso8601", - "pytz", - "hypothesis>=1.11.4,!=3.79.2", - ], - "docs": [ - "sphinx >= 1.6.5,!=1.8.0,!=3.1.0,!=3.1.1", - "sphinx_rtd_theme", - ], - "docstest": [ - "doc8", - "pyenchant >= 1.6.11", - "twine >= 1.12.0", - "sphinxcontrib-spelling >= 4.0.1", - ], - "sdist": [ - setuptools_rust, - ], - "pep8test": [ - "black", - "flake8", - "flake8-import-order", - "pep8-naming", - ], - # This extra is for OpenSSH private keys that use bcrypt KDF - # Versions: v3.1.3 - ignore_few_rounds, v3.1.5 - abi3 - "ssh": ["bcrypt >= 3.1.5"], - }, - # for cffi - zip_safe=False, - ext_package="cryptography.hazmat.bindings", cffi_modules=[ "src/_cffi_src/build_openssl.py:ffi", ], diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py index a035fa12ffd2..7dd3030517c0 100644 --- a/src/cryptography/__about__.py +++ b/src/cryptography/__about__.py @@ -4,27 +4,12 @@ __all__ = [ - "__title__", - "__summary__", - "__uri__", "__version__", "__author__", - "__email__", - "__license__", "__copyright__", ] -__title__ = "cryptography" -__summary__ = ( - "cryptography is a package which provides cryptographic recipes" - " and primitives to Python developers." -) -__uri__ = "https://github.com/pyca/cryptography" - __version__ = "35.0.0.dev1" __author__ = "The Python Cryptographic Authority and individual contributors" -__email__ = "cryptography-dev@python.org" - -__license__ = "BSD or Apache License, Version 2.0" __copyright__ = "Copyright 2013-2021 {}".format(__author__) diff --git a/src/cryptography/__init__.py b/src/cryptography/__init__.py index 15e7835e1d2f..983b6018c68d 100644 --- a/src/cryptography/__init__.py +++ b/src/cryptography/__init__.py @@ -6,22 +6,12 @@ from cryptography.__about__ import ( __author__, __copyright__, - __email__, - __license__, - __summary__, - __title__, - __uri__, __version__, ) __all__ = [ - "__title__", - "__summary__", - "__uri__", "__version__", "__author__", - "__email__", - "__license__", "__copyright__", ] From efc37b4a23eb51f6ae80c0ac496ab25911c2a714 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 29 Aug 2021 17:07:54 -0500 Subject: [PATCH 0394/2380] convert cryptography_vectors to setup.cfg (#6243) * convert cryptography_vectors to setup.cfg * put it in the right section --- vectors/cryptography_vectors/__about__.py | 18 ----------------- vectors/cryptography_vectors/__init__.py | 18 +---------------- vectors/setup.cfg | 16 +++++++++++++++ vectors/setup.py | 24 ++--------------------- 4 files changed, 19 insertions(+), 57 deletions(-) diff --git a/vectors/cryptography_vectors/__about__.py b/vectors/cryptography_vectors/__about__.py index 05fa40efc53d..6c670bb6efa8 100644 --- a/vectors/cryptography_vectors/__about__.py +++ b/vectors/cryptography_vectors/__about__.py @@ -3,25 +3,7 @@ # for complete details. __all__ = [ - "__title__", - "__summary__", - "__uri__", "__version__", - "__author__", - "__email__", - "__license__", - "__copyright__", ] -__title__ = "cryptography_vectors" -__summary__ = "Test vectors for the cryptography package." - -__uri__ = "https://github.com/pyca/cryptography" - __version__ = "35.0.0.dev1" - -__author__ = "The Python Cryptographic Authority and individual contributors" -__email__ = "cryptography-dev@python.org" - -__license__ = "BSD or Apache License, Version 2.0" -__copyright__ = "Copyright 2013-2021 %s" % __author__ diff --git a/vectors/cryptography_vectors/__init__.py b/vectors/cryptography_vectors/__init__.py index 86cddaca382f..1fe176754275 100644 --- a/vectors/cryptography_vectors/__init__.py +++ b/vectors/cryptography_vectors/__init__.py @@ -5,27 +5,11 @@ import os import typing -from cryptography_vectors.__about__ import ( - __author__, - __copyright__, - __email__, - __license__, - __summary__, - __title__, - __uri__, - __version__, -) +from cryptography_vectors.__about__ import __version__ __all__ = [ - "__title__", - "__summary__", - "__uri__", "__version__", - "__author__", - "__email__", - "__license__", - "__copyright__", ] diff --git a/vectors/setup.cfg b/vectors/setup.cfg index 2a9acf13daa9..99faeffba83b 100644 --- a/vectors/setup.cfg +++ b/vectors/setup.cfg @@ -1,2 +1,18 @@ +[metadata] +name = cryptography_vectors +version = attr: cryptography_vectors.__version__ +description = Test vectors for the cryptography package. +license = BSD or Apache License, Version 2.0 +url = https://github.com/pyca/cryptography +author = The Python Cryptographic Authority and individual contributors +author_email = cryptography-dev@python.org + + +[options] +zip_safe = False +include_package_data = True +packages = find: + + [bdist_wheel] universal = 1 diff --git a/vectors/setup.py b/vectors/setup.py index 5aaa62101978..68ff1cd8a507 100644 --- a/vectors/setup.py +++ b/vectors/setup.py @@ -4,27 +4,7 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. -import os +from setuptools import setup -from setuptools import find_packages, setup - -base_dir = os.path.dirname(__file__) - -about = {} -with open(os.path.join(base_dir, "cryptography_vectors", "__about__.py")) as f: - exec(f.read(), about) - - -setup( - name=about["__title__"], - version=about["__version__"], - description=about["__summary__"], - license=about["__license__"], - url=about["__uri__"], - author=about["__author__"], - author_email=about["__email__"], - packages=find_packages(), - zip_safe=False, - include_package_data=True, -) +setup() From 66ac2ad6ac4a51b9a433f0847106e74254f941ee Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 29 Aug 2021 22:41:52 -0400 Subject: [PATCH 0395/2380] updated comments in pyproject.tom (#6245) --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index cffd317087d5..a942869cd49a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,10 @@ [build-system] requires = [ # The minimum setuptools version is specific to the PEP 517 backend, - # and may be stricter than the version required in `setup.py` + # and may be stricter than the version required in `setup.cfg` "setuptools>=40.6.0", "wheel", - # Must be kept in sync with the `setup_requirements` in `setup.py` + # Must be kept in sync with the `setup_requirements` in `setup.cfg` "cffi>=1.12; platform_python_implementation != 'PyPy'", "setuptools-rust>=0.11.4", ] From 141a1ffaf2efb79900872bebd46b5149755573a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Aug 2021 08:16:17 -0500 Subject: [PATCH 0396/2380] Bump pyo3 from 0.14.3 to 0.14.4 in /src/rust (#6251) Bumps [pyo3](https://github.com/pyo3/pyo3) from 0.14.3 to 0.14.4. - [Release notes](https://github.com/pyo3/pyo3/releases) - [Changelog](https://github.com/PyO3/pyo3/blob/main/CHANGELOG.md) - [Commits](https://github.com/pyo3/pyo3/compare/v0.14.3...v0.14.4) --- updated-dependencies: - dependency-name: pyo3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 16 ++++++++-------- src/rust/Cargo.toml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 4a5adc344a0d..77b7dd53ac20 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -279,9 +279,9 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ce0e80b2b35e9697353a25b0e4fa5374e38c451da2f86f0cd83c40e7f1d5191" +checksum = "a192cd06356bb941c663c969a7f3e27c7c8e187efe772c1406a447f122443f71" dependencies = [ "cfg-if", "indoc", @@ -295,18 +295,18 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96007b58c38d68ae449ea4d82fbc390faf5f1f2c80c76a6e3d51385bceb56741" +checksum = "650911ce22a793e9af67a0a880741ab1519e4f84740642716cbe83e129d17a2e" dependencies = [ "once_cell", ] [[package]] name = "pyo3-macros" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "326afb5c23f9789d0a367c37d58275c4d0e97ca74f05b9a25c0d66c6395c1c7b" +checksum = "92d6659c1e336eec5a6ebc53bd80705e31ea0b95bff03bf384e868984b8ce573" dependencies = [ "pyo3-macros-backend", "quote", @@ -315,9 +315,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e38169a08f98219bba484d19100811a1646d4962706b75d60766d21dce64f9c" +checksum = "0b425a4975523acb80087d24903cffce30287a1324ab29714ce33006043c7dbe" dependencies = [ "proc-macro2", "pyo3-build-config", diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index d8c1f2c351cf..16cec56f848b 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] lazy_static = "1" -pyo3 = { version = "0.14.3" } +pyo3 = { version = "0.14.4" } asn1 = { version = "0.6", default-features = false, features = ["derive"] } pem = "0.8" chrono = { version = "0.4", default-features = false, features = ["alloc"] } From fa9e7f638bc8935d468d2fa84848ab43766b6146 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Aug 2021 08:16:43 -0500 Subject: [PATCH 0397/2380] Bump lock_api from 0.4.4 to 0.4.5 in /src/rust (#6247) Bumps [lock_api](https://github.com/Amanieu/parking_lot) from 0.4.4 to 0.4.5. - [Release notes](https://github.com/Amanieu/parking_lot/releases) - [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md) - [Commits](https://github.com/Amanieu/parking_lot/compare/lock_api-0.4.4...lock_api-0.4.5) --- updated-dependencies: - dependency-name: lock_api dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 77b7dd53ac20..a632446b93e1 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -127,9 +127,9 @@ checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" [[package]] name = "lock_api" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" dependencies = [ "scopeguard", ] From 7b70affdabf9ae7e6f2860fbad4795e1a44008e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Aug 2021 08:17:24 -0500 Subject: [PATCH 0398/2380] Bump parking_lot from 0.11.1 to 0.11.2 in /src/rust (#6249) Bumps [parking_lot](https://github.com/Amanieu/parking_lot) from 0.11.1 to 0.11.2. - [Release notes](https://github.com/Amanieu/parking_lot/releases) - [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md) - [Commits](https://github.com/Amanieu/parking_lot/compare/0.11.1...0.11.2) --- updated-dependencies: - dependency-name: parking_lot dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index a632446b93e1..6677f1b35715 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -185,9 +185,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", @@ -196,9 +196,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ "cfg-if", "instant", From 905fa95de679738e0e64a59a8ce98e47b12e364c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Aug 2021 20:08:08 -0400 Subject: [PATCH 0399/2380] Bump proc-macro2 from 1.0.28 to 1.0.29 in /src/rust (#6252) Bumps [proc-macro2](https://github.com/alexcrichton/proc-macro2) from 1.0.28 to 1.0.29. - [Release notes](https://github.com/alexcrichton/proc-macro2/releases) - [Commits](https://github.com/alexcrichton/proc-macro2/compare/1.0.28...1.0.29) --- updated-dependencies: - dependency-name: proc-macro2 dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 6677f1b35715..c875915d6d89 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -270,9 +270,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.28" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" +checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" dependencies = [ "unicode-xid", ] From 032edb255c57eba80c9aea6986b72efdd464add4 Mon Sep 17 00:00:00 2001 From: April King Date: Fri, 3 Sep 2021 16:08:21 -0500 Subject: [PATCH 0400/2380] Updated recommendations for PBKDF2 (#6257) Django recommends 320,000 rounds of PBKDF2 as of January 2021. Note that it hasn't been 100,000 for some time, so this number should probably be revisited somewhat more frequently. I did point to the source code, to make that number easier to find for people. --- docs/fernet.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/fernet.rst b/docs/fernet.rst index 5e2655d3a72b..95579d4e6aed 100644 --- a/docs/fernet.rst +++ b/docs/fernet.rst @@ -251,8 +251,8 @@ In this scheme, the salt has to be stored in a retrievable location in order to derive the same key from the password in the future. The iteration count used should be adjusted to be as high as your server can -tolerate. A good default is at least 100,000 iterations which is what Django -recommended in 2014. +tolerate. A good default is at least 320,000 iterations, which is what `Django +recommends as of January 2021`_. Implementation -------------- @@ -280,4 +280,5 @@ unsuitable for very large files at this time. .. _`Fernet`: https://github.com/fernet/spec/ +.. _`Django recommends as of January 2021`: https://github.com/django/django/blob/main/django/contrib/auth/hashers.py .. _`specification`: https://github.com/fernet/spec/blob/master/Spec.md From 5dfda63a97d71e33e191ceed80e5b1b1c174c7bc Mon Sep 17 00:00:00 2001 From: kjackiewicz Date: Sat, 4 Sep 2021 00:40:27 +0200 Subject: [PATCH 0401/2380] Implement KBKDFCMAC (#6181) * Implement KBKDFCMAC Also adjust KBKDFHMAC to avoid code duplication. * Add KBKDFCMAC unit tests * Enable KBKDFCMAC vector tests * Fix doc8 too long line issue in changelog Adding bullet list entries after line 30 in the CHANGELOG.rst leads to doc8 D001 error in line 30. Looks like a doc8 bug. Breaking the line in the middle of the cross-reference solves the problem for now. Also replace the trailing comma with a dot. * Add KBKDFCMAC documentation and update changelog --- CHANGELOG.rst | 5 +- .../primitives/key-derivation-functions.rst | 137 +++++++ .../hazmat/primitives/kdf/kbkdf.py | 174 ++++++-- tests/doubles.py | 12 +- tests/hazmat/primitives/test_kbkdf.py | 374 +++++++++++++++++- tests/hazmat/primitives/utils.py | 89 ++++- 6 files changed, 736 insertions(+), 55 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 39929f76ffe0..2b054e8cfa78 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -26,8 +26,9 @@ Changelog in regions where they may be required, and are not generally recommended. * We now ship ``manylinux_2_24`` wheels, in addition to our ``manylinux2010`` and ``manylinux2014`` wheels. -* Added ``rfc4514_attribute_name`` attribute to - :attr:`x509.NameAttribute `, +* Added ``rfc4514_attribute_name`` attribute to :attr:`x509.NameAttribute + `. +* Added :class:`~cryptography.hazmat.primitives.kdf.kbkdf.KBKDFCMAC`. .. _v3-4-8: diff --git a/docs/hazmat/primitives/key-derivation-functions.rst b/docs/hazmat/primitives/key-derivation-functions.rst index 62457b28490c..0ec4eccb5f5f 100644 --- a/docs/hazmat/primitives/key-derivation-functions.rst +++ b/docs/hazmat/primitives/key-derivation-functions.rst @@ -755,6 +755,143 @@ KBKDF ``key_material`` generates the same key as the ``expected_key``, and raises an exception if they do not match. +.. class:: KBKDFCMAC(algorithm, mode, length, rlen, llen, location,\ + label, context, fixed, backend=None) + + .. versionadded:: 35.0 + + KBKDF (Key Based Key Derivation Function) is defined by the + `NIST SP 800-108`_ document, to be used to derive additional + keys from a key that has been established through an automated + key-establishment scheme. + + .. warning:: + + KBKDFCMAC should not be used for password storage. + + .. doctest:: + + >>> from cryptography.hazmat.primitives.ciphers import algorithms + >>> from cryptography.hazmat.primitives.kdf.kbkdf import ( + ... CounterLocation, KBKDFCMAC, Mode + ... ) + >>> label = b"KBKDF CMAC Label" + >>> context = b"KBKDF CMAC Context" + >>> kdf = KBKDFCMAC( + ... algorithm=algorithms.AES, + ... mode=Mode.CounterMode, + ... length=32, + ... rlen=4, + ... llen=4, + ... location=CounterLocation.BeforeFixed, + ... label=label, + ... context=context, + ... fixed=None, + ... ) + >>> key = kdf.derive(b"32 bytes long input key material") + >>> kdf = KBKDFCMAC( + ... algorithm=algorithms.AES, + ... mode=Mode.CounterMode, + ... length=32, + ... rlen=4, + ... llen=4, + ... location=CounterLocation.BeforeFixed, + ... label=label, + ... context=context, + ... fixed=None, + ... ) + >>> kdf.verify(b"32 bytes long input key material", key) + + :param algorithm: A class implementing a block cipher algorithm being a + subclass of + :class:`~cryptography.hazmat.primitives.ciphers.CipherAlgorithm` and + :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`. + + :param mode: The desired mode of the PRF. A value from the + :class:`~cryptography.hazmat.primitives.kdf.kbkdf.Mode` enum. + + :param int length: The desired length of the derived key in bytes. + + :param int rlen: An integer that indicates the length of the binary + representation of the counter in bytes. + + :param int llen: An integer that indicates the binary + representation of the ``length`` in bytes. + + :param location: The desired location of the counter. A value from the + :class:`~cryptography.hazmat.primitives.kdf.kbkdf.CounterLocation` enum. + + :param bytes label: Application specific label information. If ``None`` + is explicitly passed an empty byte string will be used. + + :param bytes context: Application specific context information. If ``None`` + is explicitly passed an empty byte string will be used. + + :param bytes fixed: Instead of specifying ``label`` and ``context`` you + may supply your own fixed data. If ``fixed`` is specified, ``label`` + and ``context`` is ignored. + + :param backend: An optional instance of + :class:`~cryptography.hazmat.backends.interfaces.CMACBackend`. + + :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised + if the provided ``backend`` does not implement + :class:`~cryptography.hazmat.backends.interfaces.CMACBackend` or + ``algorithm`` is not a subclass of + :class:`~cryptography.hazmat.primitives.ciphers.CipherAlgorithm` and + :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`. + + :raises TypeError: This exception is raised if ``label`` or ``context`` + is not ``bytes``, ``rlen`` or ``llen`` is not ``int``, ``mode`` is not + :class:`~cryptography.hazmat.primitives.kdf.kbkdf.Mode` or ``location`` + is not + :class:`~cryptography.hazmat.primitives.kdf.kbkdf.CounterLocation`. + + :raises ValueError: This exception is raised if ``rlen`` or ``llen`` + is greater than 4 or less than 1. This exception is also raised if + you specify a ``label`` or ``context`` and ``fixed``. + + .. method:: derive(key_material) + + :param key_material: The input key material. + :type key_material: :term:`bytes-like` + :return bytes: The derived key. + :raises TypeError: This exception is raised if ``key_material`` is + not ``bytes``. + :raises ValueError: This exception is raised if ``key_material`` is + not a valid key for ``algorithm`` passed to + :class:`~cryptography.hazmat.primitives.kdf.kbkdf.KBKDFCMAC` + constructor. + :raises cryptography.exceptions.AlreadyFinalized: This is raised when + :meth:`derive` or + :meth:`verify` is + called more than + once. + :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised + if ``backend`` passed to + :class:`~cryptography.hazmat.primitives.kdf.kbkdf.KBKDFCMAC` + constructor does not support an ``algorithm`` passed to + :class:`~cryptography.hazmat.primitives.kdf.kbkdf.KBKDFCMAC` + constructor with given ``key_material``. + + Derives a new key from the input key material. + + .. method:: verify(key_material, expected_key) + + :param bytes key_material: The input key material. This is the same as + ``key_material`` in :meth:`derive`. + :param bytes expected_key: The expected result of deriving a new key, + this is the same as the return value of + :meth:`derive`. + :raises cryptography.exceptions.InvalidKey: This is raised when the + derived key does not match + the expected key. + :raises: Exceptions raised by :meth:`derive`. + + This checks whether deriving a new key from the supplied + ``key_material`` generates the same key as the ``expected_key``, and + raises an exception if they do not match. + .. class:: Mode An enumeration for the key based key derivative modes. diff --git a/src/cryptography/hazmat/primitives/kdf/kbkdf.py b/src/cryptography/hazmat/primitives/kdf/kbkdf.py index 1d106d1e5dec..d09da2b64748 100644 --- a/src/cryptography/hazmat/primitives/kdf/kbkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/kbkdf.py @@ -2,7 +2,6 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. - import typing from cryptography import utils @@ -13,8 +12,18 @@ _Reasons, ) from cryptography.hazmat.backends import _get_backend -from cryptography.hazmat.backends.interfaces import Backend, HMACBackend -from cryptography.hazmat.primitives import constant_time, hashes, hmac +from cryptography.hazmat.backends.interfaces import ( + Backend, + CMACBackend, + HMACBackend, +) +from cryptography.hazmat.primitives import ( + ciphers, + cmac, + constant_time, + hashes, + hmac, +) from cryptography.hazmat.primitives.kdf import KeyDerivationFunction @@ -27,10 +36,10 @@ class CounterLocation(utils.Enum): AfterFixed = "after_fixed" -class KBKDFHMAC(KeyDerivationFunction): +class _KBKDFDeriver: def __init__( self, - algorithm: hashes.HashAlgorithm, + prf: typing.Callable, mode: Mode, length: int, rlen: int, @@ -39,26 +48,8 @@ def __init__( label: typing.Optional[bytes], context: typing.Optional[bytes], fixed: typing.Optional[bytes], - backend: typing.Optional[Backend] = None, ): - backend = _get_backend(backend) - if not isinstance(backend, HMACBackend): - raise UnsupportedAlgorithm( - "Backend object does not implement HMACBackend.", - _Reasons.BACKEND_MISSING_INTERFACE, - ) - - if not isinstance(algorithm, hashes.HashAlgorithm): - raise UnsupportedAlgorithm( - "Algorithm supplied is not a supported hash algorithm.", - _Reasons.UNSUPPORTED_HASH, - ) - - if not backend.hmac_supported(algorithm): - raise UnsupportedAlgorithm( - "Algorithm supplied is not a supported hmac algorithm.", - _Reasons.UNSUPPORTED_HASH, - ) + assert callable(prf) if not isinstance(mode, Mode): raise TypeError("mode must be of type Mode") @@ -88,7 +79,7 @@ def __init__( utils._check_bytes("label", label) utils._check_bytes("context", context) - self._algorithm = algorithm + self._prf = prf self._mode = mode self._length = length self._rlen = rlen @@ -96,11 +87,11 @@ def __init__( self._location = location self._label = label self._context = context - self._backend = backend self._used = False self._fixed_data = fixed - def _valid_byte_length(self, value: int) -> bool: + @staticmethod + def _valid_byte_length(value: int) -> bool: if not isinstance(value, int): raise TypeError("value must be of type int") @@ -109,7 +100,7 @@ def _valid_byte_length(self, value: int) -> bool: return False return True - def derive(self, key_material: bytes) -> bytes: + def derive(self, key_material: bytes, prf_output_size: int) -> bytes: if self._used: raise AlreadyFinalized @@ -117,7 +108,7 @@ def derive(self, key_material: bytes) -> bytes: self._used = True # inverse floor division (equivalent to ceiling) - rounds = -(-self._length // self._algorithm.digest_size) + rounds = -(-self._length // prf_output_size) output = [b""] @@ -130,7 +121,7 @@ def derive(self, key_material: bytes) -> bytes: raise ValueError("There are too many iterations.") for i in range(1, rounds + 1): - h = hmac.HMAC(key_material, self._algorithm, backend=self._backend) + h = self._prf(key_material) counter = utils.int_to_bytes(i, self._rlen) if self._location == CounterLocation.BeforeFixed: @@ -153,6 +144,129 @@ def _generate_fixed_input(self) -> bytes: return b"".join([self._label, b"\x00", self._context, l_val]) + +class KBKDFHMAC(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + mode: Mode, + length: int, + rlen: int, + llen: typing.Optional[int], + location: CounterLocation, + label: typing.Optional[bytes], + context: typing.Optional[bytes], + fixed: typing.Optional[bytes], + backend: typing.Optional[Backend] = None, + ): + backend = _get_backend(backend) + if not isinstance(backend, HMACBackend): + raise UnsupportedAlgorithm( + "Backend object does not implement HMACBackend.", + _Reasons.BACKEND_MISSING_INTERFACE, + ) + + if not isinstance(algorithm, hashes.HashAlgorithm): + raise UnsupportedAlgorithm( + "Algorithm supplied is not a supported hash algorithm.", + _Reasons.UNSUPPORTED_HASH, + ) + + if not backend.hmac_supported(algorithm): + raise UnsupportedAlgorithm( + "Algorithm supplied is not a supported hmac algorithm.", + _Reasons.UNSUPPORTED_HASH, + ) + + self._algorithm = algorithm + self._backend = backend + + self._deriver = _KBKDFDeriver( + self._prf, + mode, + length, + rlen, + llen, + location, + label, + context, + fixed, + ) + + def _prf(self, key_material: bytes): + return hmac.HMAC(key_material, self._algorithm, backend=self._backend) + + def derive(self, key_material) -> bytes: + return self._deriver.derive(key_material, self._algorithm.digest_size) + + def verify(self, key_material: bytes, expected_key: bytes) -> None: + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey + + +class KBKDFCMAC(KeyDerivationFunction): + def __init__( + self, + algorithm, + mode: Mode, + length: int, + rlen: int, + llen: typing.Optional[int], + location: CounterLocation, + label: typing.Optional[bytes], + context: typing.Optional[bytes], + fixed: typing.Optional[bytes], + backend: typing.Optional[Backend] = None, + ): + backend = _get_backend(backend) + if not isinstance(backend, CMACBackend): + raise UnsupportedAlgorithm( + "Backend object does not implement CMACBackend.", + _Reasons.BACKEND_MISSING_INTERFACE, + ) + + if not issubclass( + algorithm, ciphers.BlockCipherAlgorithm + ) or not issubclass(algorithm, ciphers.CipherAlgorithm): + raise UnsupportedAlgorithm( + "Algorithm supplied is not a supported cipher algorithm.", + _Reasons.UNSUPPORTED_CIPHER, + ) + + self._algorithm = algorithm + self._backend = backend + self._cipher: typing.Optional[ciphers.BlockCipherAlgorithm] = None + + self._deriver = _KBKDFDeriver( + self._prf, + mode, + length, + rlen, + llen, + location, + label, + context, + fixed, + ) + + def _prf(self, _: bytes): + assert self._cipher is not None + + return cmac.CMAC(self._cipher, backend=self._backend) + + def derive(self, key_material: bytes) -> bytes: + self._cipher = self._algorithm(key_material) + + assert self._cipher is not None + + if not self._backend.cmac_algorithm_supported(self._cipher): + raise UnsupportedAlgorithm( + "Algorithm supplied is not a supported cipher algorithm.", + _Reasons.UNSUPPORTED_CIPHER, + ) + + return self._deriver.derive(key_material, self._cipher.block_size // 8) + def verify(self, key_material: bytes, expected_key: bytes) -> None: if not constant_time.bytes_eq(self.derive(key_material), expected_key): raise InvalidKey diff --git a/tests/doubles.py b/tests/doubles.py index de79fbe8c435..3b6f2db35994 100644 --- a/tests/doubles.py +++ b/tests/doubles.py @@ -5,7 +5,10 @@ from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import padding -from cryptography.hazmat.primitives.ciphers import CipherAlgorithm +from cryptography.hazmat.primitives.ciphers import ( + BlockCipherAlgorithm, + CipherAlgorithm, +) from cryptography.hazmat.primitives.ciphers.modes import Mode @@ -16,6 +19,13 @@ class DummyCipherAlgorithm(CipherAlgorithm): key_sizes = frozenset([256]) +class DummyBlockCipherAlgorithm(DummyCipherAlgorithm, BlockCipherAlgorithm): + def __init__(self, _): + pass + + name = "dummy-block-cipher" + + class DummyMode(Mode): name = "dummy-mode" diff --git a/tests/hazmat/primitives/test_kbkdf.py b/tests/hazmat/primitives/test_kbkdf.py index ae9330807140..4a44db8d8cd4 100644 --- a/tests/hazmat/primitives/test_kbkdf.py +++ b/tests/hazmat/primitives/test_kbkdf.py @@ -7,13 +7,19 @@ from cryptography.exceptions import AlreadyFinalized, InvalidKey, _Reasons from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.ciphers import algorithms from cryptography.hazmat.primitives.kdf.kbkdf import ( CounterLocation, + KBKDFCMAC, KBKDFHMAC, Mode, ) -from ...doubles import DummyHashAlgorithm +from ...doubles import ( + DummyBlockCipherAlgorithm, + DummyCipherAlgorithm, + DummyHashAlgorithm, +) from ...utils import raises_unsupported_algorithm @@ -333,3 +339,369 @@ def test_buffer_protocol(self, backend): key = kdf.derive(bytearray(b"material")) assert key == b"\xb7\x01\x05\x98\xf5\x1a\x12L\xc7." + + +class TestKBKDFCMAC(object): + _KEY_MATERIAL = bytes(32) + _KEY_MATERIAL2 = _KEY_MATERIAL.replace(b"\x00", b"\x01", 1) + + def test_invalid_key(self, backend): + kdf = KBKDFCMAC( + algorithms.AES, + Mode.CounterMode, + 32, + 4, + 4, + CounterLocation.BeforeFixed, + b"label", + b"context", + None, + backend=backend, + ) + + key = kdf.derive(self._KEY_MATERIAL) + + kdf = KBKDFCMAC( + algorithms.AES, + Mode.CounterMode, + 32, + 4, + 4, + CounterLocation.BeforeFixed, + b"label", + b"context", + None, + backend=backend, + ) + + with pytest.raises(InvalidKey): + kdf.verify(self._KEY_MATERIAL2, key) + + def test_already_finalized(self, backend): + kdf = KBKDFCMAC( + algorithms.AES, + Mode.CounterMode, + 32, + 4, + 4, + CounterLocation.BeforeFixed, + b"label", + b"context", + None, + backend=backend, + ) + + kdf.derive(self._KEY_MATERIAL) + + with pytest.raises(AlreadyFinalized): + kdf.derive(self._KEY_MATERIAL2) + + kdf = KBKDFCMAC( + algorithms.AES, + Mode.CounterMode, + 32, + 4, + 4, + CounterLocation.BeforeFixed, + b"label", + b"context", + None, + backend=backend, + ) + + key = kdf.derive(self._KEY_MATERIAL) + + with pytest.raises(AlreadyFinalized): + kdf.verify(self._KEY_MATERIAL, key) + + kdf = KBKDFCMAC( + algorithms.AES, + Mode.CounterMode, + 32, + 4, + 4, + CounterLocation.BeforeFixed, + b"label", + b"context", + None, + backend=backend, + ) + kdf.verify(self._KEY_MATERIAL, key) + + with pytest.raises(AlreadyFinalized): + kdf.verify(self._KEY_MATERIAL, key) + + def test_key_length(self, backend): + kdf = KBKDFCMAC( + algorithms.AES, + Mode.CounterMode, + 85899345920, + 4, + 4, + CounterLocation.BeforeFixed, + b"label", + b"context", + None, + backend=backend, + ) + + with pytest.raises(ValueError): + kdf.derive(self._KEY_MATERIAL) + + def test_rlen(self, backend): + with pytest.raises(ValueError): + KBKDFCMAC( + algorithms.AES, + Mode.CounterMode, + 32, + 5, + 4, + CounterLocation.BeforeFixed, + b"label", + b"context", + None, + backend=backend, + ) + + def test_r_type(self, backend): + with pytest.raises(TypeError): + KBKDFCMAC( + algorithms.AES, + Mode.CounterMode, + 32, + b"r", # type: ignore[arg-type] + 4, + CounterLocation.BeforeFixed, + b"label", + b"context", + None, + backend=backend, + ) + + def test_l_type(self, backend): + with pytest.raises(TypeError): + KBKDFCMAC( + algorithms.AES, + Mode.CounterMode, + 32, + 4, + b"l", # type: ignore[arg-type] + CounterLocation.BeforeFixed, + b"label", + b"context", + None, + backend=backend, + ) + + def test_l(self, backend): + with pytest.raises(ValueError): + KBKDFCMAC( + algorithms.AES, + Mode.CounterMode, + 32, + 4, + None, + CounterLocation.BeforeFixed, + b"label", + b"context", + None, + backend=backend, + ) + + def test_unsupported_mode(self, backend): + with pytest.raises(TypeError): + KBKDFCMAC( + algorithms.AES, + None, # type: ignore[arg-type] + 32, + 4, + 4, + CounterLocation.BeforeFixed, + b"label", + b"context", + None, + backend=backend, + ) + + def test_unsupported_location(self, backend): + with pytest.raises(TypeError): + KBKDFCMAC( + algorithms.AES, + Mode.CounterMode, + 32, + 4, + 4, + None, # type: ignore[arg-type] + b"label", + b"context", + None, + backend=backend, + ) + + def test_unsupported_parameters(self, backend): + with pytest.raises(ValueError): + KBKDFCMAC( + algorithms.AES, + Mode.CounterMode, + 32, + 4, + 4, + CounterLocation.BeforeFixed, + b"label", + b"context", + b"fixed", + backend=backend, + ) + + def test_unsupported_algorithm(self, backend): + with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER): + KBKDFCMAC( + object, # type: ignore[arg-type] + Mode.CounterMode, + 32, + 4, + 4, + CounterLocation.BeforeFixed, + b"label", + b"context", + None, + backend=backend, + ) + + with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER): + KBKDFCMAC( + DummyCipherAlgorithm, + Mode.CounterMode, + 32, + 4, + 4, + CounterLocation.BeforeFixed, + b"label", + b"context", + None, + backend=backend, + ) + + with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER): + KBKDFCMAC( + algorithms.ARC4, + Mode.CounterMode, + 32, + 4, + 4, + CounterLocation.BeforeFixed, + b"label", + b"context", + None, + backend=backend, + ) + + def test_invalid_backend(self, backend): + with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE): + KBKDFCMAC( + algorithms.AES, + Mode.CounterMode, + 32, + 4, + 4, + CounterLocation.BeforeFixed, + b"label", + b"context", + None, + backend=object(), # type: ignore[arg-type] + ) + + def test_unicode_error_label(self, backend): + with pytest.raises(TypeError): + KBKDFCMAC( + algorithms.AES, + Mode.CounterMode, + 32, + 4, + 4, + CounterLocation.BeforeFixed, + "label", # type: ignore[arg-type] + b"context", + None, + backend=backend, + ) + + def test_unicode_error_context(self, backend): + with pytest.raises(TypeError): + KBKDFCMAC( + algorithms.AES, + Mode.CounterMode, + 32, + 4, + 4, + CounterLocation.BeforeFixed, + b"label", + "context", # type: ignore[arg-type] + None, + backend=backend, + ) + + def test_unsupported_cipher(self, backend): + kdf = KBKDFCMAC( + DummyBlockCipherAlgorithm, + Mode.CounterMode, + 32, + 4, + 4, + CounterLocation.BeforeFixed, + b"label", + b"context", + None, + backend=backend, + ) + with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER): + kdf.derive(self._KEY_MATERIAL) + + def test_unicode_error_key_material(self, backend): + kdf = KBKDFCMAC( + algorithms.AES, + Mode.CounterMode, + 32, + 4, + 4, + CounterLocation.BeforeFixed, + b"label", + b"context", + None, + backend=backend, + ) + with pytest.raises(TypeError): + kdf.derive("material") # type: ignore[arg-type] + + def test_wrong_key_material_length(self, backend): + kdf = KBKDFCMAC( + algorithms.AES, + Mode.CounterMode, + 32, + 4, + 4, + CounterLocation.BeforeFixed, + b"label", + b"context", + None, + backend=backend, + ) + with pytest.raises(ValueError): + kdf.derive(b"material") # type: ignore[arg-type] + + def test_buffer_protocol(self, backend): + kdf = KBKDFCMAC( + algorithms.AES, + Mode.CounterMode, + 10, + 4, + 4, + CounterLocation.BeforeFixed, + b"label", + b"context", + None, + backend=backend, + ) + + key = kdf.derive(bytearray(self._KEY_MATERIAL)) + assert key == b"\x19\xcd\xbe\x17Lb\x115<\xd0" diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py index 44af12dcbf4f..639f8d5bef70 100644 --- a/tests/hazmat/primitives/utils.py +++ b/tests/hazmat/primitives/utils.py @@ -18,11 +18,16 @@ ) from cryptography.hazmat.primitives import hashes, hmac, serialization from cryptography.hazmat.primitives.asymmetric import rsa -from cryptography.hazmat.primitives.ciphers import Cipher +from cryptography.hazmat.primitives.ciphers import ( + BlockCipherAlgorithm, + Cipher, + algorithms, +) from cryptography.hazmat.primitives.ciphers.modes import GCM from cryptography.hazmat.primitives.kdf.hkdf import HKDF, HKDFExpand from cryptography.hazmat.primitives.kdf.kbkdf import ( CounterLocation, + KBKDFCMAC, KBKDFHMAC, Mode, ) @@ -411,8 +416,8 @@ def test_kbkdf(self, backend, subtests): return test_kbkdf -def kbkdf_counter_mode_test(backend, params): - supported_algorithms: typing.Dict[ +def _kbkdf_hmac_counter_mode_test(backend, prf, ctr_loc, params): + supported_hash_algorithms: typing.Dict[ str, typing.Type[hashes.HashAlgorithm] ] = { "hmac_sha1": hashes.SHA1, @@ -422,24 +427,9 @@ def kbkdf_counter_mode_test(backend, params): "hmac_sha512": hashes.SHA512, } - supported_counter_locations = { - "before_fixed": CounterLocation.BeforeFixed, - "after_fixed": CounterLocation.AfterFixed, - } - - algorithm = supported_algorithms.get(params.get("prf")) - if algorithm is None or not backend.hmac_supported(algorithm()): - pytest.skip( - "KBKDF does not support algorithm: {}".format(params.get("prf")) - ) - - ctr_loc = supported_counter_locations.get(params.get("ctrlocation")) - if ctr_loc is None or not isinstance(ctr_loc, CounterLocation): - pytest.skip( - "Does not support counter location: {}".format( - params.get("ctrlocation") - ) - ) + algorithm = supported_hash_algorithms.get(prf) + assert algorithm is not None + assert backend.hmac_supported(algorithm()) ctrkdf = KBKDFHMAC( algorithm(), @@ -458,6 +448,63 @@ def kbkdf_counter_mode_test(backend, params): assert binascii.hexlify(ko) == params["ko"] +def _kbkdf_cmac_counter_mode_test(backend, prf, ctr_loc, params): + supported_cipher_algorithms: typing.Dict[ + str, typing.Type[BlockCipherAlgorithm] + ] = { + "cmac_aes128": algorithms.AES, + "cmac_aes192": algorithms.AES, + "cmac_aes256": algorithms.AES, + "cmac_tdes2": algorithms.TripleDES, + "cmac_tdes3": algorithms.TripleDES, + } + + algorithm = supported_cipher_algorithms.get(prf) + assert algorithm is not None + + ctrkdf = KBKDFCMAC( + algorithm, + Mode.CounterMode, + params["l"] // 8, + params["rlen"] // 8, + None, + ctr_loc, + None, + None, + binascii.unhexlify(params["fixedinputdata"]), + backend=backend, + ) + + ko = ctrkdf.derive(binascii.unhexlify(params["ki"])) + assert binascii.hexlify(ko) == params["ko"] + + +def kbkdf_counter_mode_test(backend, params): + supported_counter_locations = { + "before_fixed": CounterLocation.BeforeFixed, + "after_fixed": CounterLocation.AfterFixed, + } + + ctr_loc = supported_counter_locations.get(params.get("ctrlocation")) + if ctr_loc is None or not isinstance(ctr_loc, CounterLocation): + pytest.skip( + "Does not support counter location: {}".format( + params.get("ctrlocation") + ) + ) + del params["ctrlocation"] + + prf = params.get("prf") + assert prf is not None + assert isinstance(prf, str) + del params["prf"] + if prf.startswith("hmac"): + _kbkdf_hmac_counter_mode_test(backend, prf, ctr_loc, params) + else: + assert prf.startswith("cmac") + _kbkdf_cmac_counter_mode_test(backend, prf, ctr_loc, params) + + def generate_rsa_verification_test( param_loader, path, file_names, hash_alg, pad_factory ): From 9adb7519ded3dd6411dfeb19595c16e566d5f48f Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 4 Sep 2021 04:02:29 -0700 Subject: [PATCH 0402/2380] raise a ValueError if the AEAD tag is too long (#6246) * raise a ValueError if the GCM tag is too long this is checked in both the GCM mode constructor as well as finalize_with_tag * make it work * fix * import ordering --- .../hazmat/backends/openssl/ciphers.py | 9 ++++++++- .../hazmat/primitives/ciphers/__init__.py | 6 ++++-- .../hazmat/primitives/ciphers/base.py | 12 +----------- .../hazmat/primitives/ciphers/modes.py | 18 +++++++++++++++++- tests/hazmat/primitives/test_aes_gcm.py | 5 +++-- tests/hazmat/primitives/test_ciphers.py | 8 ++++++++ tests/hazmat/primitives/utils.py | 7 +++++++ 7 files changed, 48 insertions(+), 17 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py index ec272e04d4f4..69f7f6bfd382 100644 --- a/src/cryptography/hazmat/backends/openssl/ciphers.py +++ b/src/cryptography/hazmat/backends/openssl/ciphers.py @@ -238,12 +238,19 @@ def finalize(self) -> bytes: return self._backend._ffi.buffer(buf)[: outlen[0]] def finalize_with_tag(self, tag: bytes) -> bytes: - if len(tag) < self._mode._min_tag_length: + tag_len = len(tag) + if tag_len < self._mode._min_tag_length: raise ValueError( "Authentication tag must be {} bytes or longer.".format( self._mode._min_tag_length ) ) + elif tag_len > self._block_size_bytes: + raise ValueError( + "Authentication tag cannot be more than {} bytes.".format( + self._block_size_bytes + ) + ) res = self._backend._lib.EVP_CIPHER_CTX_ctrl( self._ctx, self._backend._lib.EVP_CTRL_AEAD_SET_TAG, len(tag), tag ) diff --git a/src/cryptography/hazmat/primitives/ciphers/__init__.py b/src/cryptography/hazmat/primitives/ciphers/__init__.py index 7d3a2dcc65f8..874dbd456e8f 100644 --- a/src/cryptography/hazmat/primitives/ciphers/__init__.py +++ b/src/cryptography/hazmat/primitives/ciphers/__init__.py @@ -3,13 +3,15 @@ # for complete details. +from cryptography.hazmat.primitives._cipheralgorithm import ( + BlockCipherAlgorithm, + CipherAlgorithm, +) from cryptography.hazmat.primitives.ciphers.base import ( AEADCipherContext, AEADDecryptionContext, AEADEncryptionContext, - BlockCipherAlgorithm, Cipher, - CipherAlgorithm, CipherContext, ) diff --git a/src/cryptography/hazmat/primitives/ciphers/base.py b/src/cryptography/hazmat/primitives/ciphers/base.py index ad3c7ed8fdc4..0ae519c6d5e2 100644 --- a/src/cryptography/hazmat/primitives/ciphers/base.py +++ b/src/cryptography/hazmat/primitives/ciphers/base.py @@ -16,20 +16,10 @@ ) from cryptography.hazmat.backends import _get_backend from cryptography.hazmat.backends.interfaces import Backend, CipherBackend -from cryptography.hazmat.primitives._cipheralgorithm import ( - CipherAlgorithm as CipherAlgorithm, -) +from cryptography.hazmat.primitives._cipheralgorithm import CipherAlgorithm from cryptography.hazmat.primitives.ciphers import modes -class BlockCipherAlgorithm(metaclass=abc.ABCMeta): - @abc.abstractproperty - def block_size(self) -> int: - """ - The size of a block as an integer in bits (e.g. 64, 128). - """ - - class CipherContext(metaclass=abc.ABCMeta): @abc.abstractmethod def update(self, data: bytes) -> bytes: diff --git a/src/cryptography/hazmat/primitives/ciphers/modes.py b/src/cryptography/hazmat/primitives/ciphers/modes.py index 43ddc6d24678..3491dc2038c2 100644 --- a/src/cryptography/hazmat/primitives/ciphers/modes.py +++ b/src/cryptography/hazmat/primitives/ciphers/modes.py @@ -7,7 +7,11 @@ import typing from cryptography import utils -from cryptography.hazmat.primitives._cipheralgorithm import CipherAlgorithm +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.primitives._cipheralgorithm import ( + BlockCipherAlgorithm, + CipherAlgorithm, +) class Mode(metaclass=abc.ABCMeta): @@ -229,3 +233,15 @@ def initialization_vector(self) -> bytes: def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: _check_aes_key_length(self, algorithm) + if not isinstance(algorithm, BlockCipherAlgorithm): + raise UnsupportedAlgorithm( + "GCM requires a block cipher algorithm", + _Reasons.UNSUPPORTED_CIPHER, + ) + block_size_bytes = algorithm.block_size // 8 + if self._tag is not None and len(self._tag) > block_size_bytes: + raise ValueError( + "Authentication tag cannot be more than {} bytes.".format( + block_size_bytes + ) + ) diff --git a/tests/hazmat/primitives/test_aes_gcm.py b/tests/hazmat/primitives/test_aes_gcm.py index bae213da82d9..cc3b386aa697 100644 --- a/tests/hazmat/primitives/test_aes_gcm.py +++ b/tests/hazmat/primitives/test_aes_gcm.py @@ -168,12 +168,13 @@ def test_gcm_tag_decrypt_finalize(self, backend): decryptor.finalize_with_tag(tag) - def test_gcm_tag_decrypt_finalize_tag_length(self, backend): + @pytest.mark.parametrize("tag", [b"tagtooshort", b"toolong" * 12]) + def test_gcm_tag_decrypt_finalize_tag_length(self, tag, backend): decryptor = base.Cipher( algorithms.AES(b"0" * 16), modes.GCM(b"0" * 12), backend=backend ).decryptor() with pytest.raises(ValueError): - decryptor.finalize_with_tag(b"tagtooshort") + decryptor.finalize_with_tag(tag) def test_buffer_protocol(self, backend): data = bytearray(b"helloworld") diff --git a/tests/hazmat/primitives/test_ciphers.py b/tests/hazmat/primitives/test_ciphers.py index 99aa4af3f919..bb5d0e8bd668 100644 --- a/tests/hazmat/primitives/test_ciphers.py +++ b/tests/hazmat/primitives/test_ciphers.py @@ -209,6 +209,14 @@ def test_invalid_backend(): ) +def test_invalid_gcm_algorithm(): + with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER): + ciphers.Cipher( + ARC4(b"\x00" * 16), + modes.GCM(b"\x00" * 12), + ) + + @pytest.mark.supported( only_if=lambda backend: backend.cipher_supported( AES(b"\x00" * 16), modes.ECB() diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py index 639f8d5bef70..682adfbb6b04 100644 --- a/tests/hazmat/primitives/utils.py +++ b/tests/hazmat/primitives/utils.py @@ -337,6 +337,13 @@ def aead_tag_exception_test(backend, cipher_factory, mode_factory): with pytest.raises(ValueError): mode_factory(binascii.unhexlify(b"0" * 24), b"000") + with pytest.raises(ValueError): + Cipher( + cipher_factory(binascii.unhexlify(b"0" * 32)), + mode_factory(binascii.unhexlify(b"0" * 24), b"toolong" * 12), + backend, + ) + with pytest.raises(ValueError): mode_factory(binascii.unhexlify(b"0" * 24), b"000000", 2) From 2b19ea98872c6dad69b32f6a87e74e0d5343e42d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 4 Sep 2021 19:47:21 -0400 Subject: [PATCH 0403/2380] Bump asn1 from 0.6.1 to 0.6.2 in /src/rust (#6258) Bumps [asn1](https://github.com/alex/rust-asn1) from 0.6.1 to 0.6.2. - [Release notes](https://github.com/alex/rust-asn1/releases) - [Commits](https://github.com/alex/rust-asn1/compare/0.6.1...0.6.2) --- updated-dependencies: - dependency-name: asn1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index c875915d6d89..1d70e791970c 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -16,9 +16,9 @@ checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" [[package]] name = "asn1" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c13a3c9cd71e1799fc16511efe36d0281b60bce3b32b4b211156a7b1925bfd" +checksum = "fec9ecc08f53758f70c0517f9dcc2b045da21f288642c9dbcb0f2064c8471aa8" dependencies = [ "asn1_derive", "chrono", @@ -26,9 +26,9 @@ dependencies = [ [[package]] name = "asn1_derive" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62fc4b7f90b9540f1719f333e3ed85100ea072035d690000d7c01252ecdff096" +checksum = "48b320511d6729e965d3d9f7a2e9d35249d5abf7a6d74a033df4f3f6e2780379" dependencies = [ "proc-macro2", "quote", From 0b719e38f9e63bef7ce92f4a57dffe95972acc9b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 4 Sep 2021 20:02:58 -0400 Subject: [PATCH 0404/2380] Bump syn from 1.0.75 to 1.0.76 in /src/rust (#6259) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.75 to 1.0.76. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.75...1.0.76) --- updated-dependencies: - dependency-name: syn dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 1d70e791970c..b5d6f2035676 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -378,9 +378,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "syn" -version = "1.0.75" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f58f7e8eaa0009c5fec437aabf511bd9933e4b2d7407bd05273c01a8906ea7" +checksum = "c6f107db402c2c2055242dbf4d2af0e69197202e9faacbef9571bbe47f5a1b84" dependencies = [ "proc-macro2", "quote", From 8804475a92bb5300342917b24e7fef5e0171e0ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Sep 2021 08:27:47 -0400 Subject: [PATCH 0405/2380] Bump pyo3 from 0.14.4 to 0.14.5 in /src/rust (#6261) Bumps [pyo3](https://github.com/pyo3/pyo3) from 0.14.4 to 0.14.5. - [Release notes](https://github.com/pyo3/pyo3/releases) - [Changelog](https://github.com/PyO3/pyo3/blob/main/CHANGELOG.md) - [Commits](https://github.com/pyo3/pyo3/compare/v0.14.4...v0.14.5) --- updated-dependencies: - dependency-name: pyo3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 16 ++++++++-------- src/rust/Cargo.toml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index b5d6f2035676..481e7385218f 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -279,9 +279,9 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.14.4" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a192cd06356bb941c663c969a7f3e27c7c8e187efe772c1406a447f122443f71" +checksum = "35100f9347670a566a67aa623369293703322bb9db77d99d7df7313b575ae0c8" dependencies = [ "cfg-if", "indoc", @@ -295,18 +295,18 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.14.4" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650911ce22a793e9af67a0a880741ab1519e4f84740642716cbe83e129d17a2e" +checksum = "d12961738cacbd7f91b7c43bc25cfeeaa2698ad07a04b3be0aa88b950865738f" dependencies = [ "once_cell", ] [[package]] name = "pyo3-macros" -version = "0.14.4" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d6659c1e336eec5a6ebc53bd80705e31ea0b95bff03bf384e868984b8ce573" +checksum = "fc0bc5215d704824dfddddc03f93cb572e1155c68b6761c37005e1c288808ea8" dependencies = [ "pyo3-macros-backend", "quote", @@ -315,9 +315,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.14.4" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b425a4975523acb80087d24903cffce30287a1324ab29714ce33006043c7dbe" +checksum = "71623fc593224afaab918aa3afcaf86ed2f43d34f6afde7f3922608f253240df" dependencies = [ "proc-macro2", "pyo3-build-config", diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 16cec56f848b..3c3d9d7433e9 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] lazy_static = "1" -pyo3 = { version = "0.14.4" } +pyo3 = { version = "0.14.5" } asn1 = { version = "0.6", default-features = false, features = ["derive"] } pem = "0.8" chrono = { version = "0.4", default-features = false, features = ["alloc"] } From e4934064868c8863a66fcc54802f829086af24cf Mon Sep 17 00:00:00 2001 From: match man Date: Mon, 6 Sep 2021 23:53:29 +0300 Subject: [PATCH 0406/2380] Make OAEP test vector generating works on python3 (#6255) Use always string as output format Co-authored-by: Baofeng Wang --- .../rsa-oaep-sha2/generate_rsa_oaep_sha2.py | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py b/docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py index 000467327538..2fe62303b506 100644 --- a/docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py +++ b/docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py @@ -27,29 +27,29 @@ def build_vectors(mgf1alg, hashalg, filename): skey = rsa.generate_private_key(65537, 2048, backend) pn = skey.private_numbers() examples = private["examples"] - output.append(b"# =============================================") - output.append(b"# Example") - output.append(b"# Public key") - output.append(b"# Modulus:") + output.append("# =============================================") + output.append("# Example") + output.append("# Public key") + output.append("# Modulus:") output.append(format(pn.public_numbers.n, "x")) - output.append(b"# Exponent:") + output.append("# Exponent:") output.append(format(pn.public_numbers.e, "x")) - output.append(b"# Private key") - output.append(b"# Modulus:") + output.append("# Private key") + output.append("# Modulus:") output.append(format(pn.public_numbers.n, "x")) - output.append(b"# Public exponent:") + output.append("# Public exponent:") output.append(format(pn.public_numbers.e, "x")) - output.append(b"# Exponent:") + output.append("# Exponent:") output.append(format(pn.d, "x")) - output.append(b"# Prime 1:") + output.append("# Prime 1:") output.append(format(pn.p, "x")) - output.append(b"# Prime 2:") + output.append("# Prime 2:") output.append(format(pn.q, "x")) - output.append(b"# Prime exponent 1:") + output.append("# Prime exponent 1:") output.append(format(pn.dmp1, "x")) - output.append(b"# Prime exponent 2:") + output.append("# Prime exponent 2:") output.append(format(pn.dmq1, "x")) - output.append(b"# Coefficient:") + output.append("# Coefficient:") output.append(format(pn.iqmp, "x")) pkey = skey.public_key() vectorkey = rsa.RSAPrivateNumbers( @@ -84,17 +84,17 @@ def build_vectors(mgf1alg, hashalg, filename): ), ) output.append( - b"# OAEP Example {0} alg={1} mgf1={2}".format( + "# OAEP Example {0} alg={1} mgf1={2}".format( count, hashalg.name, mgf1alg.name ) ) count += 1 - output.append(b"# Message:") - output.append(example["message"]) - output.append(b"# Encryption:") - output.append(binascii.hexlify(ct)) + output.append("# Message:") + output.append(example["message"].decode("utf-8")) + output.append("# Encryption:") + output.append(binascii.hexlify(ct).decode("utf-8")) - return b"\n".join(output) + return "\n".join(output) def write_file(data, filename): From 3cf6f7d56777177d9031f7cb47ed6e1e2eae5f9c Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 7 Sep 2021 09:37:58 -0400 Subject: [PATCH 0407/2380] updated installation docs to reflect what we test on (#6265) --- docs/installation.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index a9f40bf9afa4..65a8d012452a 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -16,10 +16,11 @@ Supported platforms Currently we test ``cryptography`` on Python 3.6+ and PyPy3 7.3.1 on these operating systems. -* x86-64 & AArch64 CentOS 8.x +* x86-64 CentOS 8.x * x86-64 Fedora (latest) * x86-64 macOS 10.15 Catalina -* x86-64 & AArch64 Ubuntu 18.04, 20.04 +* x86-64 Ubuntu 18.04, 20.04 +* AArch64 Ubuntu 20.04 * x86-64 Ubuntu rolling * x86-64 Debian Stretch (9.x), Buster (10.x), Bullseye (11.x), and Sid (unstable) @@ -31,6 +32,7 @@ OpenSSL releases: * ``OpenSSL 1.1.0-latest`` * ``OpenSSL 1.1.1-latest`` +* ``OpenSSL 3.0-latest`` Building cryptography on Windows From 7bb03065237d9a16477e2d94734638aa8f8ba692 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 7 Sep 2021 09:38:30 -0400 Subject: [PATCH 0408/2380] new year, new openssl (#6264) --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f1f9619cf374..be414baa0307 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,8 +32,8 @@ jobs: - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1l"}} - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1l"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1l", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct"}} - - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "3.0.0-beta2"}} - - {VERSION: "3.9", TOXENV: "py39", TOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.0.0-beta2"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "3.0.0"}} + - {VERSION: "3.9", TOXENV: "py39", TOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.0.0"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "2.9.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.0.2"}} - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.1.5"}} From 11939664bcb1221278f90fb33a3f2a626665b6dd Mon Sep 17 00:00:00 2001 From: match man Date: Mon, 13 Sep 2021 01:20:14 +0300 Subject: [PATCH 0409/2380] cffi: check openssl version is less than 1.1.0 (#6266) Issue an #error directive if it is Signed-off-by: Baofeng Wang Co-authored-by: Baofeng Wang --- src/_cffi_src/openssl/cryptography.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/_cffi_src/openssl/cryptography.py b/src/_cffi_src/openssl/cryptography.py index 802a72acbf58..310b78baf165 100644 --- a/src/_cffi_src/openssl/cryptography.py +++ b/src/_cffi_src/openssl/cryptography.py @@ -39,6 +39,10 @@ #define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_332 (0) #endif +#if OPENSSL_VERSION_NUMBER < 0x10100000 + #error "pyca/cryptography MUST be linked with Openssl 1.1.0 or later" +#endif + #define CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER \ (OPENSSL_VERSION_NUMBER >= 0x1010006f && !CRYPTOGRAPHY_IS_LIBRESSL) #define CRYPTOGRAPHY_OPENSSL_111D_OR_GREATER \ From 86a14d8fa8b8a69236a987b195fdac3e600bdc68 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 13 Sep 2021 07:43:26 +0800 Subject: [PATCH 0410/2380] add more eku oids (#6271) * add more eku oids fixes #5892 * kerberos is a word in our world --- docs/spelling_wordlist.txt | 1 + docs/x509/reference.rst | 17 +++++++++++++++++ src/cryptography/x509/oid.py | 4 ++++ 3 files changed, 22 insertions(+) diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt index c74cfa469b6a..6de134333858 100644 --- a/docs/spelling_wordlist.txt +++ b/docs/spelling_wordlist.txt @@ -66,6 +66,7 @@ introspectability invariants iOS iterable +Kerberos Koblitz Lange logins diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst index eb4d07b54508..92d6f9062cef 100644 --- a/docs/x509/reference.rst +++ b/docs/x509/reference.rst @@ -3027,6 +3027,23 @@ instances. The following common OIDs are available as constants. the application. Therefore, the presence of this OID does not mean a given application will accept the certificate for all purposes. + .. attribute:: SMARTCARD_LOGON + + .. versionadded:: 35.0 + + Corresponds to the dotted string ``"1.3.6.1.4.1.311.20.2.2"``. This + is used to denote that a certificate may be used for ``PKINIT`` access + on Windows. + + .. attribute:: KERBEROS_PKINIT_KDC + + .. versionadded:: 35.0 + + Corresponds to the dotted string ``"1.3.6.1.5.2.3.5"``. This + is used to denote that a certificate may be used as a Kerberos + domain controller certificate authorizing ``PKINIT`` access. For + more information see :rfc:`4556`. + .. class:: AuthorityInformationAccessOID diff --git a/src/cryptography/x509/oid.py b/src/cryptography/x509/oid.py index 228ac1155324..cc3250c891d0 100644 --- a/src/cryptography/x509/oid.py +++ b/src/cryptography/x509/oid.py @@ -140,6 +140,8 @@ class ExtendedKeyUsageOID(object): TIME_STAMPING = ObjectIdentifier("1.3.6.1.5.5.7.3.8") OCSP_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.9") ANY_EXTENDED_KEY_USAGE = ObjectIdentifier("2.5.29.37.0") + SMARTCARD_LOGON = ObjectIdentifier("1.3.6.1.4.1.311.20.2.2") + KERBEROS_PKINIT_KDC = ObjectIdentifier("1.3.6.1.5.2.3.5") class AuthorityInformationAccessOID(object): @@ -225,6 +227,8 @@ class AttributeOID(object): ExtendedKeyUsageOID.EMAIL_PROTECTION: "emailProtection", ExtendedKeyUsageOID.TIME_STAMPING: "timeStamping", ExtendedKeyUsageOID.OCSP_SIGNING: "OCSPSigning", + ExtendedKeyUsageOID.SMARTCARD_LOGON: "msSmartcardLogin", + ExtendedKeyUsageOID.KERBEROS_PKINIT_KDC: "pkInitKDC", ExtensionOID.SUBJECT_DIRECTORY_ATTRIBUTES: "subjectDirectoryAttributes", ExtensionOID.SUBJECT_KEY_IDENTIFIER: "subjectKeyIdentifier", ExtensionOID.KEY_USAGE: "keyUsage", From 7b5634911c892fbc64b363523b8af74a4b772f7b Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 13 Sep 2021 08:12:04 +0800 Subject: [PATCH 0411/2380] resolve lazy import race condition (#6272) some private constants are no longer re-exported to the same spots --- src/cryptography/hazmat/_oid.py | 268 ++++++++++++++++- .../hazmat/backends/openssl/ocsp.py | 3 +- .../hazmat/backends/openssl/x509.py | 5 +- src/cryptography/x509/__init__.py | 2 - src/cryptography/x509/oid.py | 280 +----------------- src/rust/src/x509.rs | 2 +- tests/x509/test_x509_ext.py | 2 +- 7 files changed, 285 insertions(+), 277 deletions(-) diff --git a/src/cryptography/hazmat/_oid.py b/src/cryptography/hazmat/_oid.py index dbd04bc37609..71d41a17ddcd 100644 --- a/src/cryptography/hazmat/_oid.py +++ b/src/cryptography/hazmat/_oid.py @@ -4,6 +4,8 @@ import typing +from cryptography.hazmat.primitives import hashes + class ObjectIdentifier(object): def __init__(self, dotted_string: str) -> None: @@ -67,11 +69,271 @@ def __hash__(self) -> int: @property def _name(self) -> str: - # Lazy import to avoid an import cycle - from cryptography.x509.oid import _OID_NAMES - return _OID_NAMES.get(self, "Unknown OID") @property def dotted_string(self) -> str: return self._dotted_string + + +class ExtensionOID(object): + SUBJECT_DIRECTORY_ATTRIBUTES = ObjectIdentifier("2.5.29.9") + SUBJECT_KEY_IDENTIFIER = ObjectIdentifier("2.5.29.14") + KEY_USAGE = ObjectIdentifier("2.5.29.15") + SUBJECT_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.17") + ISSUER_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.18") + BASIC_CONSTRAINTS = ObjectIdentifier("2.5.29.19") + NAME_CONSTRAINTS = ObjectIdentifier("2.5.29.30") + CRL_DISTRIBUTION_POINTS = ObjectIdentifier("2.5.29.31") + CERTIFICATE_POLICIES = ObjectIdentifier("2.5.29.32") + POLICY_MAPPINGS = ObjectIdentifier("2.5.29.33") + AUTHORITY_KEY_IDENTIFIER = ObjectIdentifier("2.5.29.35") + POLICY_CONSTRAINTS = ObjectIdentifier("2.5.29.36") + EXTENDED_KEY_USAGE = ObjectIdentifier("2.5.29.37") + FRESHEST_CRL = ObjectIdentifier("2.5.29.46") + INHIBIT_ANY_POLICY = ObjectIdentifier("2.5.29.54") + ISSUING_DISTRIBUTION_POINT = ObjectIdentifier("2.5.29.28") + AUTHORITY_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.1") + SUBJECT_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.11") + OCSP_NO_CHECK = ObjectIdentifier("1.3.6.1.5.5.7.48.1.5") + TLS_FEATURE = ObjectIdentifier("1.3.6.1.5.5.7.1.24") + CRL_NUMBER = ObjectIdentifier("2.5.29.20") + DELTA_CRL_INDICATOR = ObjectIdentifier("2.5.29.27") + PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS = ObjectIdentifier( + "1.3.6.1.4.1.11129.2.4.2" + ) + PRECERT_POISON = ObjectIdentifier("1.3.6.1.4.1.11129.2.4.3") + SIGNED_CERTIFICATE_TIMESTAMPS = ObjectIdentifier("1.3.6.1.4.1.11129.2.4.5") + + +class OCSPExtensionOID(object): + NONCE = ObjectIdentifier("1.3.6.1.5.5.7.48.1.2") + + +class CRLEntryExtensionOID(object): + CERTIFICATE_ISSUER = ObjectIdentifier("2.5.29.29") + CRL_REASON = ObjectIdentifier("2.5.29.21") + INVALIDITY_DATE = ObjectIdentifier("2.5.29.24") + + +class NameOID(object): + COMMON_NAME = ObjectIdentifier("2.5.4.3") + COUNTRY_NAME = ObjectIdentifier("2.5.4.6") + LOCALITY_NAME = ObjectIdentifier("2.5.4.7") + STATE_OR_PROVINCE_NAME = ObjectIdentifier("2.5.4.8") + STREET_ADDRESS = ObjectIdentifier("2.5.4.9") + ORGANIZATION_NAME = ObjectIdentifier("2.5.4.10") + ORGANIZATIONAL_UNIT_NAME = ObjectIdentifier("2.5.4.11") + SERIAL_NUMBER = ObjectIdentifier("2.5.4.5") + SURNAME = ObjectIdentifier("2.5.4.4") + GIVEN_NAME = ObjectIdentifier("2.5.4.42") + TITLE = ObjectIdentifier("2.5.4.12") + GENERATION_QUALIFIER = ObjectIdentifier("2.5.4.44") + X500_UNIQUE_IDENTIFIER = ObjectIdentifier("2.5.4.45") + DN_QUALIFIER = ObjectIdentifier("2.5.4.46") + PSEUDONYM = ObjectIdentifier("2.5.4.65") + USER_ID = ObjectIdentifier("0.9.2342.19200300.100.1.1") + DOMAIN_COMPONENT = ObjectIdentifier("0.9.2342.19200300.100.1.25") + EMAIL_ADDRESS = ObjectIdentifier("1.2.840.113549.1.9.1") + JURISDICTION_COUNTRY_NAME = ObjectIdentifier("1.3.6.1.4.1.311.60.2.1.3") + JURISDICTION_LOCALITY_NAME = ObjectIdentifier("1.3.6.1.4.1.311.60.2.1.1") + JURISDICTION_STATE_OR_PROVINCE_NAME = ObjectIdentifier( + "1.3.6.1.4.1.311.60.2.1.2" + ) + BUSINESS_CATEGORY = ObjectIdentifier("2.5.4.15") + POSTAL_ADDRESS = ObjectIdentifier("2.5.4.16") + POSTAL_CODE = ObjectIdentifier("2.5.4.17") + INN = ObjectIdentifier("1.2.643.3.131.1.1") + OGRN = ObjectIdentifier("1.2.643.100.1") + SNILS = ObjectIdentifier("1.2.643.100.3") + UNSTRUCTURED_NAME = ObjectIdentifier("1.2.840.113549.1.9.2") + + +class SignatureAlgorithmOID(object): + RSA_WITH_MD5 = ObjectIdentifier("1.2.840.113549.1.1.4") + RSA_WITH_SHA1 = ObjectIdentifier("1.2.840.113549.1.1.5") + # This is an alternate OID for RSA with SHA1 that is occasionally seen + _RSA_WITH_SHA1 = ObjectIdentifier("1.3.14.3.2.29") + RSA_WITH_SHA224 = ObjectIdentifier("1.2.840.113549.1.1.14") + RSA_WITH_SHA256 = ObjectIdentifier("1.2.840.113549.1.1.11") + RSA_WITH_SHA384 = ObjectIdentifier("1.2.840.113549.1.1.12") + RSA_WITH_SHA512 = ObjectIdentifier("1.2.840.113549.1.1.13") + RSASSA_PSS = ObjectIdentifier("1.2.840.113549.1.1.10") + ECDSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10045.4.1") + ECDSA_WITH_SHA224 = ObjectIdentifier("1.2.840.10045.4.3.1") + ECDSA_WITH_SHA256 = ObjectIdentifier("1.2.840.10045.4.3.2") + ECDSA_WITH_SHA384 = ObjectIdentifier("1.2.840.10045.4.3.3") + ECDSA_WITH_SHA512 = ObjectIdentifier("1.2.840.10045.4.3.4") + DSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10040.4.3") + DSA_WITH_SHA224 = ObjectIdentifier("2.16.840.1.101.3.4.3.1") + DSA_WITH_SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.3.2") + ED25519 = ObjectIdentifier("1.3.101.112") + ED448 = ObjectIdentifier("1.3.101.113") + GOSTR3411_94_WITH_3410_2001 = ObjectIdentifier("1.2.643.2.2.3") + GOSTR3410_2012_WITH_3411_2012_256 = ObjectIdentifier("1.2.643.7.1.1.3.2") + GOSTR3410_2012_WITH_3411_2012_512 = ObjectIdentifier("1.2.643.7.1.1.3.3") + + +_SIG_OIDS_TO_HASH: typing.Dict[ + ObjectIdentifier, typing.Optional[hashes.HashAlgorithm] +] = { + SignatureAlgorithmOID.RSA_WITH_MD5: hashes.MD5(), + SignatureAlgorithmOID.RSA_WITH_SHA1: hashes.SHA1(), + SignatureAlgorithmOID._RSA_WITH_SHA1: hashes.SHA1(), + SignatureAlgorithmOID.RSA_WITH_SHA224: hashes.SHA224(), + SignatureAlgorithmOID.RSA_WITH_SHA256: hashes.SHA256(), + SignatureAlgorithmOID.RSA_WITH_SHA384: hashes.SHA384(), + SignatureAlgorithmOID.RSA_WITH_SHA512: hashes.SHA512(), + SignatureAlgorithmOID.ECDSA_WITH_SHA1: hashes.SHA1(), + SignatureAlgorithmOID.ECDSA_WITH_SHA224: hashes.SHA224(), + SignatureAlgorithmOID.ECDSA_WITH_SHA256: hashes.SHA256(), + SignatureAlgorithmOID.ECDSA_WITH_SHA384: hashes.SHA384(), + SignatureAlgorithmOID.ECDSA_WITH_SHA512: hashes.SHA512(), + SignatureAlgorithmOID.DSA_WITH_SHA1: hashes.SHA1(), + SignatureAlgorithmOID.DSA_WITH_SHA224: hashes.SHA224(), + SignatureAlgorithmOID.DSA_WITH_SHA256: hashes.SHA256(), + SignatureAlgorithmOID.ED25519: None, + SignatureAlgorithmOID.ED448: None, + SignatureAlgorithmOID.GOSTR3411_94_WITH_3410_2001: None, + SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_256: None, + SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_512: None, +} + + +class ExtendedKeyUsageOID(object): + SERVER_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.1") + CLIENT_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.2") + CODE_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.3") + EMAIL_PROTECTION = ObjectIdentifier("1.3.6.1.5.5.7.3.4") + TIME_STAMPING = ObjectIdentifier("1.3.6.1.5.5.7.3.8") + OCSP_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.9") + ANY_EXTENDED_KEY_USAGE = ObjectIdentifier("2.5.29.37.0") + SMARTCARD_LOGON = ObjectIdentifier("1.3.6.1.4.1.311.20.2.2") + KERBEROS_PKINIT_KDC = ObjectIdentifier("1.3.6.1.5.2.3.5") + + +class AuthorityInformationAccessOID(object): + CA_ISSUERS = ObjectIdentifier("1.3.6.1.5.5.7.48.2") + OCSP = ObjectIdentifier("1.3.6.1.5.5.7.48.1") + + +class SubjectInformationAccessOID(object): + CA_REPOSITORY = ObjectIdentifier("1.3.6.1.5.5.7.48.5") + + +class CertificatePoliciesOID(object): + CPS_QUALIFIER = ObjectIdentifier("1.3.6.1.5.5.7.2.1") + CPS_USER_NOTICE = ObjectIdentifier("1.3.6.1.5.5.7.2.2") + ANY_POLICY = ObjectIdentifier("2.5.29.32.0") + + +class AttributeOID(object): + CHALLENGE_PASSWORD = ObjectIdentifier("1.2.840.113549.1.9.7") + UNSTRUCTURED_NAME = ObjectIdentifier("1.2.840.113549.1.9.2") + + +_OID_NAMES = { + NameOID.COMMON_NAME: "commonName", + NameOID.COUNTRY_NAME: "countryName", + NameOID.LOCALITY_NAME: "localityName", + NameOID.STATE_OR_PROVINCE_NAME: "stateOrProvinceName", + NameOID.STREET_ADDRESS: "streetAddress", + NameOID.ORGANIZATION_NAME: "organizationName", + NameOID.ORGANIZATIONAL_UNIT_NAME: "organizationalUnitName", + NameOID.SERIAL_NUMBER: "serialNumber", + NameOID.SURNAME: "surname", + NameOID.GIVEN_NAME: "givenName", + NameOID.TITLE: "title", + NameOID.GENERATION_QUALIFIER: "generationQualifier", + NameOID.X500_UNIQUE_IDENTIFIER: "x500UniqueIdentifier", + NameOID.DN_QUALIFIER: "dnQualifier", + NameOID.PSEUDONYM: "pseudonym", + NameOID.USER_ID: "userID", + NameOID.DOMAIN_COMPONENT: "domainComponent", + NameOID.EMAIL_ADDRESS: "emailAddress", + NameOID.JURISDICTION_COUNTRY_NAME: "jurisdictionCountryName", + NameOID.JURISDICTION_LOCALITY_NAME: "jurisdictionLocalityName", + NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME: ( + "jurisdictionStateOrProvinceName" + ), + NameOID.BUSINESS_CATEGORY: "businessCategory", + NameOID.POSTAL_ADDRESS: "postalAddress", + NameOID.POSTAL_CODE: "postalCode", + NameOID.INN: "INN", + NameOID.OGRN: "OGRN", + NameOID.SNILS: "SNILS", + NameOID.UNSTRUCTURED_NAME: "unstructuredName", + SignatureAlgorithmOID.RSA_WITH_MD5: "md5WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA1: "sha1WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA224: "sha224WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA256: "sha256WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA384: "sha384WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA512: "sha512WithRSAEncryption", + SignatureAlgorithmOID.RSASSA_PSS: "RSASSA-PSS", + SignatureAlgorithmOID.ECDSA_WITH_SHA1: "ecdsa-with-SHA1", + SignatureAlgorithmOID.ECDSA_WITH_SHA224: "ecdsa-with-SHA224", + SignatureAlgorithmOID.ECDSA_WITH_SHA256: "ecdsa-with-SHA256", + SignatureAlgorithmOID.ECDSA_WITH_SHA384: "ecdsa-with-SHA384", + SignatureAlgorithmOID.ECDSA_WITH_SHA512: "ecdsa-with-SHA512", + SignatureAlgorithmOID.DSA_WITH_SHA1: "dsa-with-sha1", + SignatureAlgorithmOID.DSA_WITH_SHA224: "dsa-with-sha224", + SignatureAlgorithmOID.DSA_WITH_SHA256: "dsa-with-sha256", + SignatureAlgorithmOID.ED25519: "ed25519", + SignatureAlgorithmOID.ED448: "ed448", + SignatureAlgorithmOID.GOSTR3411_94_WITH_3410_2001: ( + "GOST R 34.11-94 with GOST R 34.10-2001" + ), + SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_256: ( + "GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)" + ), + SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_512: ( + "GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit)" + ), + ExtendedKeyUsageOID.SERVER_AUTH: "serverAuth", + ExtendedKeyUsageOID.CLIENT_AUTH: "clientAuth", + ExtendedKeyUsageOID.CODE_SIGNING: "codeSigning", + ExtendedKeyUsageOID.EMAIL_PROTECTION: "emailProtection", + ExtendedKeyUsageOID.TIME_STAMPING: "timeStamping", + ExtendedKeyUsageOID.OCSP_SIGNING: "OCSPSigning", + ExtendedKeyUsageOID.SMARTCARD_LOGON: "msSmartcardLogin", + ExtendedKeyUsageOID.KERBEROS_PKINIT_KDC: "pkInitKDC", + ExtensionOID.SUBJECT_DIRECTORY_ATTRIBUTES: "subjectDirectoryAttributes", + ExtensionOID.SUBJECT_KEY_IDENTIFIER: "subjectKeyIdentifier", + ExtensionOID.KEY_USAGE: "keyUsage", + ExtensionOID.SUBJECT_ALTERNATIVE_NAME: "subjectAltName", + ExtensionOID.ISSUER_ALTERNATIVE_NAME: "issuerAltName", + ExtensionOID.BASIC_CONSTRAINTS: "basicConstraints", + ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: ( + "signedCertificateTimestampList" + ), + ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS: ( + "signedCertificateTimestampList" + ), + ExtensionOID.PRECERT_POISON: "ctPoison", + CRLEntryExtensionOID.CRL_REASON: "cRLReason", + CRLEntryExtensionOID.INVALIDITY_DATE: "invalidityDate", + CRLEntryExtensionOID.CERTIFICATE_ISSUER: "certificateIssuer", + ExtensionOID.NAME_CONSTRAINTS: "nameConstraints", + ExtensionOID.CRL_DISTRIBUTION_POINTS: "cRLDistributionPoints", + ExtensionOID.CERTIFICATE_POLICIES: "certificatePolicies", + ExtensionOID.POLICY_MAPPINGS: "policyMappings", + ExtensionOID.AUTHORITY_KEY_IDENTIFIER: "authorityKeyIdentifier", + ExtensionOID.POLICY_CONSTRAINTS: "policyConstraints", + ExtensionOID.EXTENDED_KEY_USAGE: "extendedKeyUsage", + ExtensionOID.FRESHEST_CRL: "freshestCRL", + ExtensionOID.INHIBIT_ANY_POLICY: "inhibitAnyPolicy", + ExtensionOID.ISSUING_DISTRIBUTION_POINT: ("issuingDistributionPoint"), + ExtensionOID.AUTHORITY_INFORMATION_ACCESS: "authorityInfoAccess", + ExtensionOID.SUBJECT_INFORMATION_ACCESS: "subjectInfoAccess", + ExtensionOID.OCSP_NO_CHECK: "OCSPNoCheck", + ExtensionOID.CRL_NUMBER: "cRLNumber", + ExtensionOID.DELTA_CRL_INDICATOR: "deltaCRLIndicator", + ExtensionOID.TLS_FEATURE: "TLSFeature", + AuthorityInformationAccessOID.OCSP: "OCSP", + AuthorityInformationAccessOID.CA_ISSUERS: "caIssuers", + SubjectInformationAccessOID.CA_REPOSITORY: "caRepository", + CertificatePoliciesOID.CPS_QUALIFIER: "id-qt-cps", + CertificatePoliciesOID.CPS_USER_NOTICE: "id-qt-unotice", + OCSPExtensionOID.NONCE: "OCSPNonce", + AttributeOID.CHALLENGE_PASSWORD: "challengePassword", +} diff --git a/src/cryptography/hazmat/backends/openssl/ocsp.py b/src/cryptography/hazmat/backends/openssl/ocsp.py index c69be3123c5e..82a5c057b124 100644 --- a/src/cryptography/hazmat/backends/openssl/ocsp.py +++ b/src/cryptography/hazmat/backends/openssl/ocsp.py @@ -7,6 +7,7 @@ from cryptography import utils, x509 from cryptography.exceptions import UnsupportedAlgorithm +from cryptography.hazmat._oid import _SIG_OIDS_TO_HASH from cryptography.hazmat.backends.openssl.decode_asn1 import ( _CRL_ENTRY_REASON_CODE_TO_ENUM, _asn1_integer_to_int, @@ -141,7 +142,7 @@ def signature_hash_algorithm( self._requires_successful_response() oid = self.signature_algorithm_oid try: - return x509._SIG_OIDS_TO_HASH[oid] + return _SIG_OIDS_TO_HASH[oid] except KeyError: raise UnsupportedAlgorithm( "Signature algorithm OID:{} not recognized".format(oid) diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index d2017efdf559..be9436e01ae7 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -10,6 +10,7 @@ from cryptography import utils, x509 from cryptography.exceptions import UnsupportedAlgorithm +from cryptography.hazmat._oid import _SIG_OIDS_TO_HASH from cryptography.hazmat.backends.openssl import dsa, ec, rsa from cryptography.hazmat.backends.openssl.decode_asn1 import ( _asn1_integer_to_int, @@ -131,7 +132,7 @@ def signature_hash_algorithm( ) -> typing.Optional[hashes.HashAlgorithm]: oid = self.signature_algorithm_oid try: - return x509._SIG_OIDS_TO_HASH[oid] + return _SIG_OIDS_TO_HASH[oid] except KeyError: raise UnsupportedAlgorithm( "Signature algorithm OID:{} not recognized".format(oid) @@ -292,7 +293,7 @@ def signature_hash_algorithm( ) -> typing.Optional[hashes.HashAlgorithm]: oid = self.signature_algorithm_oid try: - return x509._SIG_OIDS_TO_HASH[oid] + return _SIG_OIDS_TO_HASH[oid] except KeyError: raise UnsupportedAlgorithm( "Signature algorithm OID:{} not recognized".format(oid) diff --git a/src/cryptography/x509/__init__.py b/src/cryptography/x509/__init__.py index 5003e09d3fa9..fa7fbd48094d 100644 --- a/src/cryptography/x509/__init__.py +++ b/src/cryptography/x509/__init__.py @@ -93,7 +93,6 @@ NameOID, ObjectIdentifier, SignatureAlgorithmOID, - _SIG_OIDS_TO_HASH, ) @@ -231,7 +230,6 @@ "CertificateSigningRequestBuilder", "CertificateBuilder", "Version", - "_SIG_OIDS_TO_HASH", "OID_CA_ISSUERS", "OID_OCSP", "_GENERAL_NAMES", diff --git a/src/cryptography/x509/oid.py b/src/cryptography/x509/oid.py index cc3250c891d0..9bfac75a4803 100644 --- a/src/cryptography/x509/oid.py +++ b/src/cryptography/x509/oid.py @@ -2,273 +2,19 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. -import typing - -from cryptography.hazmat._oid import ObjectIdentifier -from cryptography.hazmat.primitives import hashes - - -class ExtensionOID(object): - SUBJECT_DIRECTORY_ATTRIBUTES = ObjectIdentifier("2.5.29.9") - SUBJECT_KEY_IDENTIFIER = ObjectIdentifier("2.5.29.14") - KEY_USAGE = ObjectIdentifier("2.5.29.15") - SUBJECT_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.17") - ISSUER_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.18") - BASIC_CONSTRAINTS = ObjectIdentifier("2.5.29.19") - NAME_CONSTRAINTS = ObjectIdentifier("2.5.29.30") - CRL_DISTRIBUTION_POINTS = ObjectIdentifier("2.5.29.31") - CERTIFICATE_POLICIES = ObjectIdentifier("2.5.29.32") - POLICY_MAPPINGS = ObjectIdentifier("2.5.29.33") - AUTHORITY_KEY_IDENTIFIER = ObjectIdentifier("2.5.29.35") - POLICY_CONSTRAINTS = ObjectIdentifier("2.5.29.36") - EXTENDED_KEY_USAGE = ObjectIdentifier("2.5.29.37") - FRESHEST_CRL = ObjectIdentifier("2.5.29.46") - INHIBIT_ANY_POLICY = ObjectIdentifier("2.5.29.54") - ISSUING_DISTRIBUTION_POINT = ObjectIdentifier("2.5.29.28") - AUTHORITY_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.1") - SUBJECT_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.11") - OCSP_NO_CHECK = ObjectIdentifier("1.3.6.1.5.5.7.48.1.5") - TLS_FEATURE = ObjectIdentifier("1.3.6.1.5.5.7.1.24") - CRL_NUMBER = ObjectIdentifier("2.5.29.20") - DELTA_CRL_INDICATOR = ObjectIdentifier("2.5.29.27") - PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS = ObjectIdentifier( - "1.3.6.1.4.1.11129.2.4.2" - ) - PRECERT_POISON = ObjectIdentifier("1.3.6.1.4.1.11129.2.4.3") - SIGNED_CERTIFICATE_TIMESTAMPS = ObjectIdentifier("1.3.6.1.4.1.11129.2.4.5") - - -class OCSPExtensionOID(object): - NONCE = ObjectIdentifier("1.3.6.1.5.5.7.48.1.2") - - -class CRLEntryExtensionOID(object): - CERTIFICATE_ISSUER = ObjectIdentifier("2.5.29.29") - CRL_REASON = ObjectIdentifier("2.5.29.21") - INVALIDITY_DATE = ObjectIdentifier("2.5.29.24") - - -class NameOID(object): - COMMON_NAME = ObjectIdentifier("2.5.4.3") - COUNTRY_NAME = ObjectIdentifier("2.5.4.6") - LOCALITY_NAME = ObjectIdentifier("2.5.4.7") - STATE_OR_PROVINCE_NAME = ObjectIdentifier("2.5.4.8") - STREET_ADDRESS = ObjectIdentifier("2.5.4.9") - ORGANIZATION_NAME = ObjectIdentifier("2.5.4.10") - ORGANIZATIONAL_UNIT_NAME = ObjectIdentifier("2.5.4.11") - SERIAL_NUMBER = ObjectIdentifier("2.5.4.5") - SURNAME = ObjectIdentifier("2.5.4.4") - GIVEN_NAME = ObjectIdentifier("2.5.4.42") - TITLE = ObjectIdentifier("2.5.4.12") - GENERATION_QUALIFIER = ObjectIdentifier("2.5.4.44") - X500_UNIQUE_IDENTIFIER = ObjectIdentifier("2.5.4.45") - DN_QUALIFIER = ObjectIdentifier("2.5.4.46") - PSEUDONYM = ObjectIdentifier("2.5.4.65") - USER_ID = ObjectIdentifier("0.9.2342.19200300.100.1.1") - DOMAIN_COMPONENT = ObjectIdentifier("0.9.2342.19200300.100.1.25") - EMAIL_ADDRESS = ObjectIdentifier("1.2.840.113549.1.9.1") - JURISDICTION_COUNTRY_NAME = ObjectIdentifier("1.3.6.1.4.1.311.60.2.1.3") - JURISDICTION_LOCALITY_NAME = ObjectIdentifier("1.3.6.1.4.1.311.60.2.1.1") - JURISDICTION_STATE_OR_PROVINCE_NAME = ObjectIdentifier( - "1.3.6.1.4.1.311.60.2.1.2" - ) - BUSINESS_CATEGORY = ObjectIdentifier("2.5.4.15") - POSTAL_ADDRESS = ObjectIdentifier("2.5.4.16") - POSTAL_CODE = ObjectIdentifier("2.5.4.17") - INN = ObjectIdentifier("1.2.643.3.131.1.1") - OGRN = ObjectIdentifier("1.2.643.100.1") - SNILS = ObjectIdentifier("1.2.643.100.3") - UNSTRUCTURED_NAME = ObjectIdentifier("1.2.840.113549.1.9.2") - - -class SignatureAlgorithmOID(object): - RSA_WITH_MD5 = ObjectIdentifier("1.2.840.113549.1.1.4") - RSA_WITH_SHA1 = ObjectIdentifier("1.2.840.113549.1.1.5") - # This is an alternate OID for RSA with SHA1 that is occasionally seen - _RSA_WITH_SHA1 = ObjectIdentifier("1.3.14.3.2.29") - RSA_WITH_SHA224 = ObjectIdentifier("1.2.840.113549.1.1.14") - RSA_WITH_SHA256 = ObjectIdentifier("1.2.840.113549.1.1.11") - RSA_WITH_SHA384 = ObjectIdentifier("1.2.840.113549.1.1.12") - RSA_WITH_SHA512 = ObjectIdentifier("1.2.840.113549.1.1.13") - RSASSA_PSS = ObjectIdentifier("1.2.840.113549.1.1.10") - ECDSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10045.4.1") - ECDSA_WITH_SHA224 = ObjectIdentifier("1.2.840.10045.4.3.1") - ECDSA_WITH_SHA256 = ObjectIdentifier("1.2.840.10045.4.3.2") - ECDSA_WITH_SHA384 = ObjectIdentifier("1.2.840.10045.4.3.3") - ECDSA_WITH_SHA512 = ObjectIdentifier("1.2.840.10045.4.3.4") - DSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10040.4.3") - DSA_WITH_SHA224 = ObjectIdentifier("2.16.840.1.101.3.4.3.1") - DSA_WITH_SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.3.2") - ED25519 = ObjectIdentifier("1.3.101.112") - ED448 = ObjectIdentifier("1.3.101.113") - GOSTR3411_94_WITH_3410_2001 = ObjectIdentifier("1.2.643.2.2.3") - GOSTR3410_2012_WITH_3411_2012_256 = ObjectIdentifier("1.2.643.7.1.1.3.2") - GOSTR3410_2012_WITH_3411_2012_512 = ObjectIdentifier("1.2.643.7.1.1.3.3") - - -_SIG_OIDS_TO_HASH: typing.Dict[ - ObjectIdentifier, typing.Optional[hashes.HashAlgorithm] -] = { - SignatureAlgorithmOID.RSA_WITH_MD5: hashes.MD5(), - SignatureAlgorithmOID.RSA_WITH_SHA1: hashes.SHA1(), - SignatureAlgorithmOID._RSA_WITH_SHA1: hashes.SHA1(), - SignatureAlgorithmOID.RSA_WITH_SHA224: hashes.SHA224(), - SignatureAlgorithmOID.RSA_WITH_SHA256: hashes.SHA256(), - SignatureAlgorithmOID.RSA_WITH_SHA384: hashes.SHA384(), - SignatureAlgorithmOID.RSA_WITH_SHA512: hashes.SHA512(), - SignatureAlgorithmOID.ECDSA_WITH_SHA1: hashes.SHA1(), - SignatureAlgorithmOID.ECDSA_WITH_SHA224: hashes.SHA224(), - SignatureAlgorithmOID.ECDSA_WITH_SHA256: hashes.SHA256(), - SignatureAlgorithmOID.ECDSA_WITH_SHA384: hashes.SHA384(), - SignatureAlgorithmOID.ECDSA_WITH_SHA512: hashes.SHA512(), - SignatureAlgorithmOID.DSA_WITH_SHA1: hashes.SHA1(), - SignatureAlgorithmOID.DSA_WITH_SHA224: hashes.SHA224(), - SignatureAlgorithmOID.DSA_WITH_SHA256: hashes.SHA256(), - SignatureAlgorithmOID.ED25519: None, - SignatureAlgorithmOID.ED448: None, - SignatureAlgorithmOID.GOSTR3411_94_WITH_3410_2001: None, - SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_256: None, - SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_512: None, -} - - -class ExtendedKeyUsageOID(object): - SERVER_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.1") - CLIENT_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.2") - CODE_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.3") - EMAIL_PROTECTION = ObjectIdentifier("1.3.6.1.5.5.7.3.4") - TIME_STAMPING = ObjectIdentifier("1.3.6.1.5.5.7.3.8") - OCSP_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.9") - ANY_EXTENDED_KEY_USAGE = ObjectIdentifier("2.5.29.37.0") - SMARTCARD_LOGON = ObjectIdentifier("1.3.6.1.4.1.311.20.2.2") - KERBEROS_PKINIT_KDC = ObjectIdentifier("1.3.6.1.5.2.3.5") - - -class AuthorityInformationAccessOID(object): - CA_ISSUERS = ObjectIdentifier("1.3.6.1.5.5.7.48.2") - OCSP = ObjectIdentifier("1.3.6.1.5.5.7.48.1") - - -class SubjectInformationAccessOID(object): - CA_REPOSITORY = ObjectIdentifier("1.3.6.1.5.5.7.48.5") - - -class CertificatePoliciesOID(object): - CPS_QUALIFIER = ObjectIdentifier("1.3.6.1.5.5.7.2.1") - CPS_USER_NOTICE = ObjectIdentifier("1.3.6.1.5.5.7.2.2") - ANY_POLICY = ObjectIdentifier("2.5.29.32.0") - - -class AttributeOID(object): - CHALLENGE_PASSWORD = ObjectIdentifier("1.2.840.113549.1.9.7") - UNSTRUCTURED_NAME = ObjectIdentifier("1.2.840.113549.1.9.2") - - -_OID_NAMES = { - NameOID.COMMON_NAME: "commonName", - NameOID.COUNTRY_NAME: "countryName", - NameOID.LOCALITY_NAME: "localityName", - NameOID.STATE_OR_PROVINCE_NAME: "stateOrProvinceName", - NameOID.STREET_ADDRESS: "streetAddress", - NameOID.ORGANIZATION_NAME: "organizationName", - NameOID.ORGANIZATIONAL_UNIT_NAME: "organizationalUnitName", - NameOID.SERIAL_NUMBER: "serialNumber", - NameOID.SURNAME: "surname", - NameOID.GIVEN_NAME: "givenName", - NameOID.TITLE: "title", - NameOID.GENERATION_QUALIFIER: "generationQualifier", - NameOID.X500_UNIQUE_IDENTIFIER: "x500UniqueIdentifier", - NameOID.DN_QUALIFIER: "dnQualifier", - NameOID.PSEUDONYM: "pseudonym", - NameOID.USER_ID: "userID", - NameOID.DOMAIN_COMPONENT: "domainComponent", - NameOID.EMAIL_ADDRESS: "emailAddress", - NameOID.JURISDICTION_COUNTRY_NAME: "jurisdictionCountryName", - NameOID.JURISDICTION_LOCALITY_NAME: "jurisdictionLocalityName", - NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME: ( - "jurisdictionStateOrProvinceName" - ), - NameOID.BUSINESS_CATEGORY: "businessCategory", - NameOID.POSTAL_ADDRESS: "postalAddress", - NameOID.POSTAL_CODE: "postalCode", - NameOID.INN: "INN", - NameOID.OGRN: "OGRN", - NameOID.SNILS: "SNILS", - NameOID.UNSTRUCTURED_NAME: "unstructuredName", - SignatureAlgorithmOID.RSA_WITH_MD5: "md5WithRSAEncryption", - SignatureAlgorithmOID.RSA_WITH_SHA1: "sha1WithRSAEncryption", - SignatureAlgorithmOID.RSA_WITH_SHA224: "sha224WithRSAEncryption", - SignatureAlgorithmOID.RSA_WITH_SHA256: "sha256WithRSAEncryption", - SignatureAlgorithmOID.RSA_WITH_SHA384: "sha384WithRSAEncryption", - SignatureAlgorithmOID.RSA_WITH_SHA512: "sha512WithRSAEncryption", - SignatureAlgorithmOID.RSASSA_PSS: "RSASSA-PSS", - SignatureAlgorithmOID.ECDSA_WITH_SHA1: "ecdsa-with-SHA1", - SignatureAlgorithmOID.ECDSA_WITH_SHA224: "ecdsa-with-SHA224", - SignatureAlgorithmOID.ECDSA_WITH_SHA256: "ecdsa-with-SHA256", - SignatureAlgorithmOID.ECDSA_WITH_SHA384: "ecdsa-with-SHA384", - SignatureAlgorithmOID.ECDSA_WITH_SHA512: "ecdsa-with-SHA512", - SignatureAlgorithmOID.DSA_WITH_SHA1: "dsa-with-sha1", - SignatureAlgorithmOID.DSA_WITH_SHA224: "dsa-with-sha224", - SignatureAlgorithmOID.DSA_WITH_SHA256: "dsa-with-sha256", - SignatureAlgorithmOID.ED25519: "ed25519", - SignatureAlgorithmOID.ED448: "ed448", - SignatureAlgorithmOID.GOSTR3411_94_WITH_3410_2001: ( - "GOST R 34.11-94 with GOST R 34.10-2001" - ), - SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_256: ( - "GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)" - ), - SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_512: ( - "GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit)" - ), - ExtendedKeyUsageOID.SERVER_AUTH: "serverAuth", - ExtendedKeyUsageOID.CLIENT_AUTH: "clientAuth", - ExtendedKeyUsageOID.CODE_SIGNING: "codeSigning", - ExtendedKeyUsageOID.EMAIL_PROTECTION: "emailProtection", - ExtendedKeyUsageOID.TIME_STAMPING: "timeStamping", - ExtendedKeyUsageOID.OCSP_SIGNING: "OCSPSigning", - ExtendedKeyUsageOID.SMARTCARD_LOGON: "msSmartcardLogin", - ExtendedKeyUsageOID.KERBEROS_PKINIT_KDC: "pkInitKDC", - ExtensionOID.SUBJECT_DIRECTORY_ATTRIBUTES: "subjectDirectoryAttributes", - ExtensionOID.SUBJECT_KEY_IDENTIFIER: "subjectKeyIdentifier", - ExtensionOID.KEY_USAGE: "keyUsage", - ExtensionOID.SUBJECT_ALTERNATIVE_NAME: "subjectAltName", - ExtensionOID.ISSUER_ALTERNATIVE_NAME: "issuerAltName", - ExtensionOID.BASIC_CONSTRAINTS: "basicConstraints", - ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: ( - "signedCertificateTimestampList" - ), - ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS: ( - "signedCertificateTimestampList" - ), - ExtensionOID.PRECERT_POISON: "ctPoison", - CRLEntryExtensionOID.CRL_REASON: "cRLReason", - CRLEntryExtensionOID.INVALIDITY_DATE: "invalidityDate", - CRLEntryExtensionOID.CERTIFICATE_ISSUER: "certificateIssuer", - ExtensionOID.NAME_CONSTRAINTS: "nameConstraints", - ExtensionOID.CRL_DISTRIBUTION_POINTS: "cRLDistributionPoints", - ExtensionOID.CERTIFICATE_POLICIES: "certificatePolicies", - ExtensionOID.POLICY_MAPPINGS: "policyMappings", - ExtensionOID.AUTHORITY_KEY_IDENTIFIER: "authorityKeyIdentifier", - ExtensionOID.POLICY_CONSTRAINTS: "policyConstraints", - ExtensionOID.EXTENDED_KEY_USAGE: "extendedKeyUsage", - ExtensionOID.FRESHEST_CRL: "freshestCRL", - ExtensionOID.INHIBIT_ANY_POLICY: "inhibitAnyPolicy", - ExtensionOID.ISSUING_DISTRIBUTION_POINT: ("issuingDistributionPoint"), - ExtensionOID.AUTHORITY_INFORMATION_ACCESS: "authorityInfoAccess", - ExtensionOID.SUBJECT_INFORMATION_ACCESS: "subjectInfoAccess", - ExtensionOID.OCSP_NO_CHECK: "OCSPNoCheck", - ExtensionOID.CRL_NUMBER: "cRLNumber", - ExtensionOID.DELTA_CRL_INDICATOR: "deltaCRLIndicator", - ExtensionOID.TLS_FEATURE: "TLSFeature", - AuthorityInformationAccessOID.OCSP: "OCSP", - AuthorityInformationAccessOID.CA_ISSUERS: "caIssuers", - SubjectInformationAccessOID.CA_REPOSITORY: "caRepository", - CertificatePoliciesOID.CPS_QUALIFIER: "id-qt-cps", - CertificatePoliciesOID.CPS_USER_NOTICE: "id-qt-unotice", - OCSPExtensionOID.NONCE: "OCSPNonce", - AttributeOID.CHALLENGE_PASSWORD: "challengePassword", -} +from cryptography.hazmat._oid import ( + AttributeOID, + AuthorityInformationAccessOID, + CRLEntryExtensionOID, + CertificatePoliciesOID, + ExtendedKeyUsageOID, + ExtensionOID, + NameOID, + OCSPExtensionOID, + ObjectIdentifier, + SignatureAlgorithmOID, + SubjectInformationAccessOID, +) __all__ = [ diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index cbc8b2c359c6..1be065a89d18 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -294,7 +294,7 @@ impl Certificate { py: pyo3::Python<'p>, ) -> Result<&'p pyo3::PyAny, PyAsn1Error> { let sig_oids_to_hash = py - .import("cryptography.x509")? + .import("cryptography.hazmat._oid")? .getattr("_SIG_OIDS_TO_HASH")?; let hash_alg = sig_oids_to_hash.get_item(self.signature_algorithm_oid(py)?); match hash_alg { diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index bc3688bd0d8f..3a8d78168df7 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -14,6 +14,7 @@ import pytest from cryptography import x509 +from cryptography.hazmat._oid import _OID_NAMES from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import ec from cryptography.x509 import DNSName, NameConstraints, SubjectAlternativeName @@ -25,7 +26,6 @@ NameOID, ObjectIdentifier, SubjectInformationAccessOID, - _OID_NAMES, ) from .test_x509 import _load_cert From bacf23f3edfa2ce880b7cd740d63f10058732fd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A1ndor=20Jenei?= <35337337+SlaushVunter@users.noreply.github.com> Date: Mon, 13 Sep 2021 11:08:34 +0200 Subject: [PATCH 0412/2380] _ModuleWithDeprecations should inherit from types.ModuleType (#6267) (#6268) * _ModuleWithDeprecations should inherit from types.ModuleType (#6267) Update utils.py * fix typos reported by black * flake8 fix * Test should fail when int_from_bytes will be removed. Because this test would become pointless then. --- src/cryptography/utils.py | 4 +++- tests/test_utils.py | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index 3cfd32e98855..2ce68f7ce887 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -7,6 +7,7 @@ import enum import inspect import sys +import types import typing import warnings @@ -113,8 +114,9 @@ def __init__(self, value, message, warning_class): self.warning_class = warning_class -class _ModuleWithDeprecations(object): +class _ModuleWithDeprecations(types.ModuleType): def __init__(self, module): + super().__init__(module.__name__) self.__dict__["_module"] = module def __getattr__(self, attr): diff --git a/tests/test_utils.py b/tests/test_utils.py index 389638f151a8..ee411c36718c 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -4,6 +4,7 @@ import binascii +import inspect import os import textwrap @@ -12,6 +13,7 @@ import pytest import cryptography +import cryptography.utils from cryptography.exceptions import UnsupportedAlgorithm, _Reasons import cryptography_vectors @@ -4444,3 +4446,13 @@ def test_raises_unsupported_algorithm(): "An error.", _Reasons.BACKEND_MISSING_INTERFACE ) assert exc_info.type is UnsupportedAlgorithm + + +def test_inspect_deprecated_module(): + # Check if inspection is supported by _ModuleWithDeprecations. + assert isinstance( + cryptography.utils, cryptography.utils._ModuleWithDeprecations + ) + source_file = inspect.getsourcefile(cryptography.utils) + assert isinstance(source_file, str) + assert source_file.endswith("utils.py") From e6f0e1f7063491a03cbb273f8c8d2b012921da14 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Sep 2021 08:22:28 -0400 Subject: [PATCH 0413/2380] Bump libc from 0.2.101 to 0.2.102 in /src/rust (#6274) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.101 to 0.2.102. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.101...0.2.102) --- updated-dependencies: - dependency-name: libc dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 481e7385218f..7ea29279d5fd 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -121,9 +121,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.101" +version = "0.2.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" +checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103" [[package]] name = "lock_api" From dda20a4438ac440ada18139d96fb6b74471514d4 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 18 Sep 2021 19:07:45 -0400 Subject: [PATCH 0414/2380] backport some tests needed for full coverage of rust (#6277) --- tests/x509/test_x509.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 58dde9b1aa59..405c09e8d869 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -102,6 +102,14 @@ def test_invalid_pem(self, backend): with pytest.raises(ValueError): x509.load_pem_x509_crl(b"notacrl", backend) + pem_bytes = _load_cert( + os.path.join("x509", "custom", "valid_signature_cert.pem"), + lambda data, backend: data, + backend, + ) + with pytest.raises(ValueError): + x509.load_pem_x509_crl(pem_bytes, backend) + def test_invalid_der(self, backend): with pytest.raises(ValueError): x509.load_der_x509_crl(b"notacrl", backend) @@ -170,6 +178,15 @@ def test_equality(self, backend): assert crl1 != crl3 assert crl1 != object() + def test_comparison(self, backend): + crl1 = _load_cert( + os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"), + x509.load_der_x509_crl, + backend, + ) + with pytest.raises(TypeError): + crl1 < crl1 + def test_update_dates(self, backend): crl = _load_cert( os.path.join("x509", "custom", "crl_all_reasons.pem"), From 88e805808883d2b321857f956ee523d0665bbf35 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 19 Sep 2021 07:50:12 +0800 Subject: [PATCH 0415/2380] add vector omitting optional ASN.1 SEQUENCE for an empty CRL (#6279) --- docs/development/test-vectors.rst | 2 ++ tests/x509/test_x509.py | 10 ++++++++++ .../x509/custom/crl_empty_no_sequence.der | Bin 0 -> 361 bytes 3 files changed, 12 insertions(+) create mode 100644 vectors/cryptography_vectors/x509/custom/crl_empty_no_sequence.der diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index 6d096f63e43b..8de8bf347e51 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -495,6 +495,8 @@ Custom X.509 Certificate Revocation List Vectors * ``crl_inval_cert_issuer_entry_ext.pem`` - Contains a CRL with one revocation which has one entry extension for certificate issuer with an empty value. * ``crl_empty.pem`` - Contains a CRL with no revoked certificates. +* ``crl_empty_no_sequence.der`` - Contains a CRL with no revoked certificates + and the optional ASN.1 sequence for revoked certificates is omitted. * ``crl_ian_aia_aki.pem`` - Contains a CRL with ``IssuerAlternativeName``, ``AuthorityInformationAccess``, ``AuthorityKeyIdentifier`` and ``CRLNumber`` extensions. diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 405c09e8d869..ef412bc606d0 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -98,6 +98,16 @@ def test_load_der_crl(self, backend): assert fingerprint == b"dd3db63c50f4c4a13e090f14053227cb1011a5ad" assert isinstance(crl.signature_hash_algorithm, hashes.SHA256) + def test_empty_crl_no_sequence(self, backend): + # The SEQUENCE for revoked certificates is optional so let's + # test that we handle it properly. + crl = _load_cert( + os.path.join("x509", "custom", "crl_empty_no_sequence.der"), + x509.load_der_x509_crl, + backend, + ) + assert len(crl) == 0 + def test_invalid_pem(self, backend): with pytest.raises(ValueError): x509.load_pem_x509_crl(b"notacrl", backend) diff --git a/vectors/cryptography_vectors/x509/custom/crl_empty_no_sequence.der b/vectors/cryptography_vectors/x509/custom/crl_empty_no_sequence.der new file mode 100644 index 0000000000000000000000000000000000000000..7dd7b7ffb34082f564a09ca2e39a8f3d4d11e6eb GIT binary patch literal 361 zcmXqLVoWvgXJTYD;AP{~YV&CO&dbQi&B|aPYbb3X$;KSY!ptL-TvS<5lAm6bSddYv zmzl5N>?qD_U}RuuU}y*;4Wh((jSY~vXl5}tF)}i!v`>5S>4{_a17r4+rw>i3-a4hQ zNPJsVc~thcCdE(H;Tt~B_jwzZyewXaapHucv*j7Q*>dGfamuZBtNgA9&6j?d#-iWy zWm-iw*TyAs%CApsO5~rtZQfnwmr~A7lX9nY`DQ)jU04&i`bJTG!;>Ex{L3zKYgvli zc*B`){M=%v*Piz$^Gq1H0*2A-7kyUL zuATJJ_ox#uj>ihDS34ci>=Lk@Ebzq}AV8QS!ErG=x(D*f~Cm2_D@ ut$Q47CH1pt3uArM!^;O9L;PM$-*e*Sm9I~#EjzU(_OS_Ef2sYeUkCugot4%A literal 0 HcmV?d00001 From 77358f80fd66f8c9edef4cab6dafd6f21db7459d Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 18 Sep 2021 20:15:37 -0400 Subject: [PATCH 0416/2380] Added a test of encoding a CRLReason, needed for Rust coverage (#6278) --- tests/x509/test_x509_crlbuilder.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/x509/test_x509_crlbuilder.py b/tests/x509/test_x509_crlbuilder.py index 14fe2387107f..cc09db78f1f9 100644 --- a/tests/x509/test_x509_crlbuilder.py +++ b/tests/x509/test_x509_crlbuilder.py @@ -748,6 +748,9 @@ def test_sign_with_revoked_certificates(self, backend): .serial_number(2) .revocation_date(datetime.datetime(2012, 1, 1, 1, 1)) .add_extension(invalidity_date, False) + .add_extension( + x509.CRLReason(x509.ReasonFlags.ca_compromise), False + ) .build(backend) ) builder = ( @@ -776,7 +779,7 @@ def test_sign_with_revoked_certificates(self, backend): assert len(crl[0].extensions) == 0 assert crl[1].serial_number == revoked_cert1.serial_number assert crl[1].revocation_date == revoked_cert1.revocation_date - assert len(crl[1].extensions) == 1 + assert len(crl[1].extensions) == 2 ext = crl[1].extensions.get_extension_for_class(x509.InvalidityDate) assert ext.critical is False assert ext.value == invalidity_date From 0af8579975d1449157900679080888199e0fad5e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 18 Sep 2021 20:27:37 -0400 Subject: [PATCH 0417/2380] Added more tests for empty CRL (#6281) --- tests/x509/test_x509.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index ef412bc606d0..0d0997baaec1 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -108,6 +108,11 @@ def test_empty_crl_no_sequence(self, backend): ) assert len(crl) == 0 + with pytest.raises(IndexError): + crl[0] + assert crl.get_revoked_certificate_by_serial_number(12) is None + assert list(iter(crl)) == [] + def test_invalid_pem(self, backend): with pytest.raises(ValueError): x509.load_pem_x509_crl(b"notacrl", backend) From 1a0ba3e79d1f52cf1967e4ac177cdae788d9829a Mon Sep 17 00:00:00 2001 From: John Jones Date: Sat, 18 Sep 2021 18:13:45 -0700 Subject: [PATCH 0418/2380] preparations for musllinux (#6236) * preparations for musllinux * wheel-builder | skip PyPy on musllinux builds --- .github/workflows/wheel-builder.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 1adb7cf2469b..b4936b42a92f 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -21,6 +21,13 @@ jobs: - { NAME: "manylinux2010_x86_64", CONTAINER: "cryptography-manylinux2010:x86_64" } - { NAME: "manylinux2014_x86_64", CONTAINER: "cryptography-manylinux2014:x86_64" } - { name: "manylinux_2_24_x86_64", CONTAINER: "cryptography-manylinux_2_24:x86_64"} + - { name: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64"} + exclude: + # There are no readily available musllinux PyPy distributions + - PYTHON: { VERSION: "pypy3.6", PATH: "/opt/pypy3.6/bin/pypy" } + MANYLINUX: { name: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64" } + - PYTHON: { VERSION: "pypy3.7", PATH: "/opt/pypy3.7/bin/pypy" } + MANYLINUX: { name: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64"} name: "${{ matrix.PYTHON.VERSION }} for ${{ matrix.MANYLINUX.NAME }}" steps: - run: ${{ matrix.PYTHON.PATH }} -m venv .venv @@ -41,8 +48,8 @@ jobs: - run: auditwheel repair --plat ${{ matrix.MANYLINUX.NAME }} tmpwheelhouse/cryptograph*.whl -w wheelhouse/ - run: unzip wheelhouse/*.whl -d execstack.check - run: | - results=$(execstack execstack.check/cryptography/hazmat/bindings/*.so) - count=$(echo "$results" | grep -c '^X' || true) + results=$(readelf -lW execstack.check/cryptography/hazmat/bindings/*.so) + count=$(echo "$results" | grep -c 'GNU_STACK.*[R ][W ]E' || true) if [ "$count" -ne 0 ]; then exit 1 else From 6542c2f2f4beab41e883e860d3b3554993231bf4 Mon Sep 17 00:00:00 2001 From: John Jones Date: Sat, 18 Sep 2021 18:30:58 -0700 Subject: [PATCH 0419/2380] per discussion in #6236 (#6254) --- docs/faq.rst | 5 ++--- docs/installation.rst | 27 +++++++++++++-------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/docs/faq.rst b/docs/faq.rst index cfa2952fec29..befe3942e624 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -78,9 +78,8 @@ OpenSSL. If you see this error it is likely because your copy of ``pip`` is too old to find our wheel files. Upgrade your ``pip`` with ``pip install -U pip`` and then try to install ``cryptography`` again. -Users on PyPy, unusual CPU architectures, or distributions of Linux using -``musl`` (like Alpine) will need to compile ``cryptography`` themselves. Please -view our :doc:`/installation` documentation. +Users on unusual CPU architectures will need to compile ``cryptography`` +themselves. Please view our :doc:`/installation` documentation. ``cryptography`` raised an ``InternalError`` and I'm not sure what to do? ------------------------------------------------------------------------- diff --git a/docs/installation.rst b/docs/installation.rst index 65a8d012452a..a3b0cafdf730 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -87,17 +87,16 @@ Building cryptography on Linux ``cryptography`` ships ``manylinux`` wheels (as of 2.0) so all dependencies are included. For users on **pip 19.0** or above running on a ``manylinux2010`` -(or greater) compatible distribution (almost everything **except Alpine**) all +(or greater) compatible distribution (or **pip 21.2.4** for ``musllinux``) all you should need to do is: .. code-block:: console $ pip install cryptography -If you are on Alpine or just want to compile it yourself then -``cryptography`` requires a C compiler, a Rust compiler, headers for Python (if -you're not using ``pypy``), and headers for the OpenSSL and ``libffi`` libraries -available on your system. +If you want to compile ``cryptography`` yourself you'll need a C compiler, a +Rust compiler, headers for Python (if you're not using ``pypy``), and headers +for the OpenSSL and ``libffi`` libraries available on your system. On all Linux distributions you will need to have :ref:`Rust installed and available`. @@ -198,15 +197,15 @@ Static Wheels ~~~~~~~~~~~~~ Cryptography ships statically-linked wheels for macOS, Windows, and Linux (via -``manylinux``). This allows compatible environments to use the most recent -OpenSSL, regardless of what is shipped by default on those platforms. Some -Linux distributions (most notably Alpine) are not ``manylinux`` compatible so -we cannot distribute wheels for them. - -However, you can build your own statically-linked wheels that will work on your -own systems. This will allow you to continue to use relatively old Linux -distributions (such as LTS releases), while making sure you have the most -recent OpenSSL available to your Python programs. +``manylinux`` and ``musllinux``). This allows compatible environments to use +the most recent OpenSSL, regardless of what is shipped by default on those +platforms. + +If you are using a platform not covered by our wheels, you can build your own +statically-linked wheels that will work on your own systems. This will allow +you to continue to use relatively old Linux distributions (such as LTS +releases), while making sure you have the most recent OpenSSL available to +your Python programs. To do so, you should find yourself a machine that is as similar as possible to your target environment (e.g. your production environment): for example, spin From b1002451c01c455a21931a3fa51d9a19411fd83c Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 18 Sep 2021 21:57:38 -0400 Subject: [PATCH 0420/2380] Don't internal error on CRL with no nextUpdate value (#6282) * Don't internal error on CRL with no nextUpdate value * Fix typing * docs --- docs/development/test-vectors.rst | 2 ++ src/cryptography/hazmat/backends/openssl/x509.py | 5 +++-- src/cryptography/x509/base.py | 2 +- tests/x509/test_x509.py | 8 ++++++++ .../x509/custom/crl_no_next_update.pem | 12 ++++++++++++ 5 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 vectors/cryptography_vectors/x509/custom/crl_no_next_update.pem diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index 8de8bf347e51..20f246cf6e68 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -540,6 +540,8 @@ Custom X.509 Certificate Revocation List Vectors ``extnValue`` of ``abcdef``. * ``crl_invalid_time.der`` - Contains a CRL with an invalid ``UTCTime`` value in ``thisUpdate``. The signature on this CRL is invalid. +* ``crl_no_next_time.pem`` - Contains a CRL with no ``nextUpdate`` value. The + signature on this CRL is invalid. X.509 OCSP Test Vectors ~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index be9436e01ae7..b2dedcfd1338 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -155,9 +155,10 @@ def issuer(self) -> x509.Name: return _decode_x509_name(self._backend, issuer) @property - def next_update(self) -> datetime.datetime: + def next_update(self) -> typing.Optional[datetime.datetime]: nu = self._backend._lib.X509_CRL_get0_nextUpdate(self._x509_crl) - self._backend.openssl_assert(nu != self._backend._ffi.NULL) + if nu == self._backend._ffi.NULL: + return None return _parse_asn1_time(self._backend, nu) @property diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index 0e8154425f5d..22f6509f6eb5 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -258,7 +258,7 @@ def issuer(self) -> Name: """ @abc.abstractproperty - def next_update(self) -> datetime.datetime: + def next_update(self) -> typing.Optional[datetime.datetime]: """ Returns the date of next update for this CRL. """ diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 0d0997baaec1..99b7d4f82f69 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -215,6 +215,14 @@ def test_update_dates(self, backend): assert crl.next_update.isoformat() == "2016-01-01T00:00:00" assert crl.last_update.isoformat() == "2015-01-01T00:00:00" + def test_no_next_update(self, backend): + crl = _load_cert( + os.path.join("x509", "custom", "crl_no_next_update.pem"), + x509.load_pem_x509_crl, + backend, + ) + assert crl.next_update is None + def test_unrecognized_extension(self, backend): crl = _load_cert( os.path.join("x509", "custom", "crl_unrecognized_extension.der"), diff --git a/vectors/cryptography_vectors/x509/custom/crl_no_next_update.pem b/vectors/cryptography_vectors/x509/custom/crl_no_next_update.pem new file mode 100644 index 000000000000..9acfa2dc953d --- /dev/null +++ b/vectors/cryptography_vectors/x509/custom/crl_no_next_update.pem @@ -0,0 +1,12 @@ +-----BEGIN X509 CRL----- +MIIBtjCBnwIBATANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQGEwJVUzERMA8GA1UE +CAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xETAPBgNVBAoMCHI1MDkgTExD +MRowGAYDVQQDDBFyNTA5IENSTCBEZWxlZ2F0ZRcNMTUxMjIwMjM0NDQ3WqAZMBcw +CgYDVR0UBAMCAQEwCQYDVR0jBAIwADANBgkqhkiG9w0BAQUFAAOCAQEAXebqoZfE +VAC4NcSEB5oGqUviUn/AnY6TzB6hUe8XC7yqEkBcyTgkG1Zq+b+T/5X1ewTldvuU +qv19WAU/Epbbu4488PoH5qMV8Aii2XcotLJOR9OBANp0Yy4ir/n6qyw8kM3hXJlo +E+xgkELhd5JmKCnlXihM1BTl7Xp7jyKeQ86omR+DhItbCU+9RoqOK9Hm087Z7Rur +XVrz5RKltQo7VLCp8VmrxFwfALCZENXGEQ+g5VkvoCjcph5jqOSyzp7aZy1pnLE/ +6U6V32ItskrwqA+x4oj2Wvzir/Q23y2zYfqOkuq4fTd2lWW+w5mB167fIWmd6efe +cDn1ZqbdECDPUg== +-----END X509 CRL----- From df4a0fd70b90a45d7bfb1973969d671fb46e156f Mon Sep 17 00:00:00 2001 From: "Nathaniel J. Smith" Date: Sun, 19 Sep 2021 01:35:30 -0700 Subject: [PATCH 0421/2380] musllinux ftw (#6285) * musllinux ftw * appease the spellchecker --- docs/installation.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index a3b0cafdf730..7737ed12f7a9 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -321,11 +321,11 @@ Rust .. note:: - If you are on RHEL/CentOS/Fedora/Debian/Ubuntu or another distribution - derived from the preceding list, then you should **upgrade pip** (in - a virtual environment!) and attempt to install ``cryptography`` again - before trying to install the Rust toolchain. These platforms will receive - a binary wheel and require no compiler if you have an updated ``pip``! + If you are using Linux, then you should **upgrade pip** (in + a virtual environment!) and attempt to install ``cryptography`` again before + trying to install the Rust toolchain. On most Linux distributions, the latest + version of ``pip`` will be able to install a binary wheel, so you won't need + a Rust toolchain. Building ``cryptography`` requires having a working Rust toolchain. The current minimum supported Rust version is 1.41.0. **This is newer than the Rust most From 770de275181a2f06358d916f629e88404835d793 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 19 Sep 2021 19:49:40 +0800 Subject: [PATCH 0422/2380] add musllinux arm64 build to zuul (#6280) * add musllinux arm64 build to zuul * remove unneeded installs + more debug * absurd * experiment * cccchanges * sigh --- .zuul.d/jobs.yaml | 4 ++++ .../wheel/roles/build-wheel-manylinux/files/build-wheels.sh | 2 ++ .../wheel/roles/build-wheel-manylinux/tasks/main.yaml | 4 ---- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.zuul.d/jobs.yaml b/.zuul.d/jobs.yaml index 8a61080ea537..cf4abaf9e9ec 100644 --- a/.zuul.d/jobs.yaml +++ b/.zuul.d/jobs.yaml @@ -32,6 +32,10 @@ image: ghcr.io/pyca/cryptography-manylinux_2_24:aarch64 pythons: - cp36-cp36m + - platform: musllinux_1_1_aarch64 + image: ghcr.io/pyca/cryptography-musllinux_1_1:aarch64 + pythons: + - cp36-cp36m - job: name: pyca-cryptography-build-wheel-x86_64 diff --git a/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/files/build-wheels.sh b/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/files/build-wheels.sh index 41cd6bcaedf9..216a839338e8 100644 --- a/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/files/build-wheels.sh +++ b/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/files/build-wheels.sh @@ -4,6 +4,8 @@ cd /io mkdir -p wheelhouse.final +rm -rf build +rm -rf dist for P in ${PYTHONS}; do diff --git a/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/tasks/main.yaml b/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/tasks/main.yaml index dbd2328713b1..680da00055d9 100644 --- a/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/tasks/main.yaml +++ b/.zuul.playbooks/playbooks/wheel/roles/build-wheel-manylinux/tasks/main.yaml @@ -23,10 +23,6 @@ become: yes when: ansible_distribution in ['Debian', 'Ubuntu'] -- name: Install rust - include_role: - name: ensure-rust - - name: Install setuptools-rust pip: name: setuptools-rust From d702f5cdd88831feff7237006a86262164e4f04b Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 19 Sep 2021 19:51:54 +0800 Subject: [PATCH 0423/2380] changelog for musllinux (#6283) --- CHANGELOG.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2b054e8cfa78..3a84238ce7db 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -24,8 +24,10 @@ Changelog :class:`~cryptography.hazmat.primitives.ciphers.algorithms.SM4`, when using OpenSSL 1.1.1. These algorithms are provided for compatibility in regions where they may be required, and are not generally recommended. -* We now ship ``manylinux_2_24`` wheels, in addition to our ``manylinux2010`` - and ``manylinux2014`` wheels. +* We now ship ``manylinux_2_24`` and ``musllinux_1_1`` wheels, in addition to + our ``manylinux2010`` and ``manylinux2014`` wheels. Users on distributions + like Alpine Linux should ensure they upgrade to the latest ``pip`` to + correctly receive wheels. * Added ``rfc4514_attribute_name`` attribute to :attr:`x509.NameAttribute `. * Added :class:`~cryptography.hazmat.primitives.kdf.kbkdf.KBKDFCMAC`. From 6bc56acc25658a3e3c3a2ee76e6e92369f3915ab Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 19 Sep 2021 19:52:10 +0800 Subject: [PATCH 0424/2380] update setup.py links to the canonical URL (#6284) URL fragments don't work on the redirects anyway --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index f91c04cfc895..24b9f102bbf0 100644 --- a/setup.py +++ b/setup.py @@ -73,12 +73,12 @@ successfully install cryptography: 1) Upgrade to the latest pip and try again. This will fix errors for most users. See: https://pip.pypa.io/en/stable/installing/#upgrading-pip - 2) Read https://cryptography.io/en/latest/installation.html for specific + 2) Read https://cryptography.io/en/latest/installation/ for specific instructions for your platform. 3) Check our frequently asked questions for more information: - https://cryptography.io/en/latest/faq.html + https://cryptography.io/en/latest/faq/ 4) Ensure you have a recent Rust toolchain installed: - https://cryptography.io/en/latest/installation.html#rust + https://cryptography.io/en/latest/installation/#rust """ ) print(f" Python: {'.'.join(str(v) for v in sys.version_info[:3])}") From 9f6ac959a099702b89368d3b704044a2a8f231d8 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 19 Sep 2021 18:49:10 -0400 Subject: [PATCH 0425/2380] Migrate CRL implementation to Rust (#6276) (Lots of commits that got squashed) --- docs/x509/reference.rst | 2 +- .../hazmat/backends/interfaces.py | 12 - .../hazmat/backends/openssl/backend.py | 125 ++-- .../hazmat/backends/openssl/decode_asn1.py | 18 - .../hazmat/backends/openssl/x509.py | 247 +------ .../hazmat/bindings/_rust/x509.pyi | 8 +- src/cryptography/x509/base.py | 13 +- src/rust/src/asn1.rs | 2 +- src/rust/src/ocsp.rs | 4 +- src/rust/src/x509.rs | 615 +++++++++++++++--- tests/x509/test_x509.py | 18 +- 11 files changed, 642 insertions(+), 422 deletions(-) diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst index 92d6f9062cef..36dbd6db68a7 100644 --- a/docs/x509/reference.rst +++ b/docs/x509/reference.rst @@ -513,7 +513,7 @@ X.509 CRL (Certificate Revocation List) Object 1 >>> revoked_certificate = crl[0] >>> type(revoked_certificate) - + >>> for r in crl: ... print(r.serial_number) 0 diff --git a/src/cryptography/hazmat/backends/interfaces.py b/src/cryptography/hazmat/backends/interfaces.py index 4b2d80a7770a..db708d4cdb0f 100644 --- a/src/cryptography/hazmat/backends/interfaces.py +++ b/src/cryptography/hazmat/backends/interfaces.py @@ -341,18 +341,6 @@ def x509_name_bytes(self, name: "Name") -> bytes: Compute the DER encoded bytes of an X509 Name object. """ - @abc.abstractmethod - def load_pem_x509_crl(self, data: bytes) -> "CertificateRevocationList": - """ - Load an X.509 CRL from PEM encoded data. - """ - - @abc.abstractmethod - def load_der_x509_crl(self, data: bytes) -> "CertificateRevocationList": - """ - Load an X.509 CRL from DER encoded data. - """ - class DHBackend(metaclass=abc.ABCMeta): @abc.abstractmethod diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 1a1db1ccca60..ab4ff1015f20 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -75,9 +75,8 @@ _X448PublicKey, ) from cryptography.hazmat.backends.openssl.x509 import ( - _CertificateRevocationList, _CertificateSigningRequest, - _RevokedCertificate, + _RawRevokedCertificate, ) from cryptography.hazmat.bindings._rust import ( asn1, @@ -126,6 +125,7 @@ from cryptography.hazmat.primitives.kdf import scrypt from cryptography.hazmat.primitives.serialization import pkcs7, ssh from cryptography.x509 import ocsp +from cryptography.x509.base import PUBLIC_KEY_TYPES from cryptography.x509.name import Name @@ -427,18 +427,6 @@ def _register_x509_ext_parsers(self): get_ext=self._lib.sk_X509_EXTENSION_value, rust_callback=rust_x509.parse_csr_extension, ) - self._revoked_cert_extension_parser = _X509ExtensionParser( - self, - ext_count=self._lib.X509_REVOKED_get_ext_count, - get_ext=self._lib.X509_REVOKED_get_ext, - rust_callback=rust_x509.parse_crl_entry_ext, - ) - self._crl_extension_parser = _X509ExtensionParser( - self, - ext_count=self._lib.X509_CRL_get_ext_count, - get_ext=self._lib.X509_CRL_get_ext, - rust_callback=rust_x509.parse_crl_extension, - ) self._ocsp_basicresp_ext_parser = _X509ExtensionParser( self, ext_count=self._lib.OCSP_BASICRESP_get_ext_count, @@ -1102,7 +1090,7 @@ def create_x509_crl( builder: x509.CertificateRevocationListBuilder, private_key: PRIVATE_KEY_TYPES, algorithm: typing.Optional[hashes.HashAlgorithm], - ) -> _CertificateRevocationList: + ) -> x509.CertificateRevocationList: if not isinstance(builder, x509.CertificateRevocationListBuilder): raise TypeError("Builder type mismatch.") self._x509_check_signature_params(private_key, algorithm) @@ -1144,13 +1132,30 @@ def create_x509_crl( # add revoked certificates for revoked_cert in builder._revoked_certificates: - # Duplicating because the X509_CRL takes ownership and will free - # this memory when X509_CRL_free is called. - revoked = self._lib.X509_REVOKED_dup( - revoked_cert._x509_revoked # type: ignore[attr-defined] + x509_revoked = self._lib.X509_REVOKED_new() + self.openssl_assert(x509_revoked != self._ffi.NULL) + serial_number = _encode_asn1_int_gc( + self, revoked_cert.serial_number + ) + res = self._lib.X509_REVOKED_set_serialNumber( + x509_revoked, serial_number ) - self.openssl_assert(revoked != self._ffi.NULL) - res = self._lib.X509_CRL_add0_revoked(x509_crl, revoked) + self.openssl_assert(res == 1) + rev_date = self._create_asn1_time(revoked_cert.revocation_date) + res = self._lib.X509_REVOKED_set_revocationDate( + x509_revoked, rev_date + ) + self.openssl_assert(res == 1) + # add CRL entry extensions + self._create_x509_extensions( + extensions=revoked_cert.extensions, + handlers=self._crl_entry_extension_encode_handlers, + x509_obj=x509_revoked, + add_func=self._lib.X509_REVOKED_add_ext, + gc=True, + ) + + res = self._lib.X509_CRL_add0_revoked(x509_crl, x509_revoked) self.openssl_assert(res == 1) res = self._lib.X509_CRL_sign( @@ -1160,7 +1165,10 @@ def create_x509_crl( errors = self._consume_errors_with_text() raise ValueError("Signing failed", errors) - return _CertificateRevocationList(self, x509_crl) + bio = self._create_mem_bio_gc() + res = self._lib.i2d_X509_CRL_bio(bio, x509_crl) + self.openssl_assert(res == 1) + return rust_x509.load_der_x509_crl(self._read_mem_bio(bio)) def _create_x509_extensions( self, extensions, handlers, x509_obj, add_func, gc @@ -1225,30 +1233,18 @@ def _create_x509_extension(self, handlers, extension): def create_x509_revoked_certificate( self, builder: x509.RevokedCertificateBuilder - ) -> _RevokedCertificate: + ) -> x509.RevokedCertificate: if not isinstance(builder, x509.RevokedCertificateBuilder): raise TypeError("Builder type mismatch.") - - x509_revoked = self._lib.X509_REVOKED_new() - self.openssl_assert(x509_revoked != self._ffi.NULL) - x509_revoked = self._ffi.gc(x509_revoked, self._lib.X509_REVOKED_free) - serial_number = _encode_asn1_int_gc(self, builder._serial_number) - res = self._lib.X509_REVOKED_set_serialNumber( - x509_revoked, serial_number - ) - self.openssl_assert(res == 1) - rev_date = self._create_asn1_time(builder._revocation_date) - res = self._lib.X509_REVOKED_set_revocationDate(x509_revoked, rev_date) - self.openssl_assert(res == 1) - # add CRL entry extensions - self._create_x509_extensions( - extensions=builder._extensions, - handlers=self._crl_entry_extension_encode_handlers, - x509_obj=x509_revoked, - add_func=self._lib.X509_REVOKED_add_ext, - gc=True, + serial_number = builder._serial_number + revocation_date = builder._revocation_date + assert serial_number is not None + assert revocation_date is not None + return _RawRevokedCertificate( + serial_number, + revocation_date, + x509.Extensions(builder._extensions), ) - return _RevokedCertificate(self, None, x509_revoked) def load_pem_private_key(self, data, password): return self._load_key( @@ -1390,31 +1386,34 @@ def _ossl2cert(self, x509: typing.Any) -> x509.Certificate: self.openssl_assert(res == 1) return rust_x509.load_der_x509_certificate(self._read_mem_bio(bio)) - def load_pem_x509_crl(self, data: bytes) -> _CertificateRevocationList: - mem_bio = self._bytes_to_bio(data) - x509_crl = self._lib.PEM_read_bio_X509_CRL( - mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL - ) - if x509_crl == self._ffi.NULL: - self._consume_errors() - raise ValueError( - "Unable to load CRL. See https://cryptography.io/en/la" - "test/faq.html#why-can-t-i-import-my-pem-file for more" - " details." + def _crl_is_signature_valid( + self, crl: x509.CertificateRevocationList, public_key: PUBLIC_KEY_TYPES + ) -> bool: + if not isinstance( + public_key, + ( + _DSAPublicKey, + _RSAPublicKey, + _EllipticCurvePublicKey, + ), + ): + raise TypeError( + "Expecting one of DSAPublicKey, RSAPublicKey," + " or EllipticCurvePublicKey." ) - - x509_crl = self._ffi.gc(x509_crl, self._lib.X509_CRL_free) - return _CertificateRevocationList(self, x509_crl) - - def load_der_x509_crl(self, data: bytes) -> _CertificateRevocationList: + data = crl.public_bytes(serialization.Encoding.DER) mem_bio = self._bytes_to_bio(data) x509_crl = self._lib.d2i_X509_CRL_bio(mem_bio.bio, self._ffi.NULL) - if x509_crl == self._ffi.NULL: + self.openssl_assert(x509_crl != self._ffi.NULL) + x509_crl = self._ffi.gc(x509_crl, self._lib.X509_CRL_free) + + res = self._lib.X509_CRL_verify(x509_crl, public_key._evp_pkey) + + if res != 1: self._consume_errors() - raise ValueError("Unable to load CRL") + return False - x509_crl = self._ffi.gc(x509_crl, self._lib.X509_CRL_free) - return _CertificateRevocationList(self, x509_crl) + return True def load_pem_x509_csr(self, data: bytes) -> _CertificateSigningRequest: mem_bio = self._bytes_to_bio(data) diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 8e648eba6685..9a7b9f6eeb5c 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -177,24 +177,6 @@ def _asn1_string_to_utf8(backend, asn1_string) -> str: return backend._ffi.buffer(buf[0], res)[:].decode("utf8") -def _parse_asn1_time(backend, asn1_time): - backend.openssl_assert(asn1_time != backend._ffi.NULL) - generalized_time = backend._lib.ASN1_TIME_to_generalizedtime( - asn1_time, backend._ffi.NULL - ) - if generalized_time == backend._ffi.NULL: - raise ValueError( - "Couldn't parse ASN.1 time as generalizedtime {!r}".format( - _asn1_string_to_bytes(backend, asn1_time) - ) - ) - - generalized_time = backend._ffi.gc( - generalized_time, backend._lib.ASN1_GENERALIZEDTIME_free - ) - return _parse_asn1_generalized_time(backend, generalized_time) - - def _parse_asn1_generalized_time(backend, generalized_time): time = _asn1_string_to_ascii( backend, backend._ffi.cast("ASN1_STRING *", generalized_time) diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index b2dedcfd1338..52d08a0249b5 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -4,23 +4,18 @@ import datetime -import operator import typing import warnings from cryptography import utils, x509 from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat._oid import _SIG_OIDS_TO_HASH -from cryptography.hazmat.backends.openssl import dsa, ec, rsa from cryptography.hazmat.backends.openssl.decode_asn1 import ( - _asn1_integer_to_int, _asn1_string_to_bytes, _decode_x509_name, _obj2txt, - _parse_asn1_time, ) from cryptography.hazmat.backends.openssl.encode_asn1 import ( - _encode_asn1_int_gc, _txt2obj_gc, ) from cryptography.hazmat.primitives import hashes, serialization @@ -39,224 +34,6 @@ def _Certificate(backend, x509) -> x509.Certificate: # noqa: N802 return backend._ossl2cert(x509) -class _RevokedCertificate(x509.RevokedCertificate): - def __init__(self, backend, crl, x509_revoked): - self._backend = backend - # The X509_REVOKED_value is a X509_REVOKED * that has - # no reference counting. This means when X509_CRL_free is - # called then the CRL and all X509_REVOKED * are freed. Since - # you can retain a reference to a single revoked certificate - # and let the CRL fall out of scope we need to retain a - # private reference to the CRL inside the RevokedCertificate - # object to prevent the gc from being called inappropriately. - self._crl = crl - self._x509_revoked = x509_revoked - - @property - def serial_number(self) -> int: - asn1_int = self._backend._lib.X509_REVOKED_get0_serialNumber( - self._x509_revoked - ) - self._backend.openssl_assert(asn1_int != self._backend._ffi.NULL) - return _asn1_integer_to_int(self._backend, asn1_int) - - @property - def revocation_date(self) -> datetime.datetime: - return _parse_asn1_time( - self._backend, - self._backend._lib.X509_REVOKED_get0_revocationDate( - self._x509_revoked - ), - ) - - @utils.cached_property - def extensions(self) -> x509.Extensions: - return self._backend._revoked_cert_extension_parser.parse( - self._x509_revoked - ) - - -class _CertificateRevocationList(x509.CertificateRevocationList): - def __init__(self, backend, x509_crl): - self._backend = backend - self._x509_crl = x509_crl - - def __eq__(self, other: object) -> bool: - if not isinstance(other, _CertificateRevocationList): - return NotImplemented - - res = self._backend._lib.X509_CRL_cmp(self._x509_crl, other._x509_crl) - return res == 0 - - def __ne__(self, other: object) -> bool: - return not self == other - - def fingerprint(self, algorithm: hashes.HashAlgorithm) -> bytes: - h = hashes.Hash(algorithm, self._backend) - bio = self._backend._create_mem_bio_gc() - res = self._backend._lib.i2d_X509_CRL_bio(bio, self._x509_crl) - self._backend.openssl_assert(res == 1) - der = self._backend._read_mem_bio(bio) - h.update(der) - return h.finalize() - - @utils.cached_property - def _sorted_crl(self): - # X509_CRL_get0_by_serial sorts in place, which breaks a variety of - # things we don't want to break (like iteration and the signature). - # Let's dupe it and sort that instead. - dup = self._backend._lib.X509_CRL_dup(self._x509_crl) - self._backend.openssl_assert(dup != self._backend._ffi.NULL) - dup = self._backend._ffi.gc(dup, self._backend._lib.X509_CRL_free) - return dup - - def get_revoked_certificate_by_serial_number( - self, serial_number: int - ) -> typing.Optional[x509.RevokedCertificate]: - revoked = self._backend._ffi.new("X509_REVOKED **") - asn1_int = _encode_asn1_int_gc(self._backend, serial_number) - res = self._backend._lib.X509_CRL_get0_by_serial( - self._sorted_crl, revoked, asn1_int - ) - if res == 0: - return None - else: - self._backend.openssl_assert(revoked[0] != self._backend._ffi.NULL) - return _RevokedCertificate( - self._backend, self._sorted_crl, revoked[0] - ) - - @property - def signature_hash_algorithm( - self, - ) -> typing.Optional[hashes.HashAlgorithm]: - oid = self.signature_algorithm_oid - try: - return _SIG_OIDS_TO_HASH[oid] - except KeyError: - raise UnsupportedAlgorithm( - "Signature algorithm OID:{} not recognized".format(oid) - ) - - @property - def signature_algorithm_oid(self) -> x509.ObjectIdentifier: - alg = self._backend._ffi.new("X509_ALGOR **") - self._backend._lib.X509_CRL_get0_signature( - self._x509_crl, self._backend._ffi.NULL, alg - ) - self._backend.openssl_assert(alg[0] != self._backend._ffi.NULL) - oid = _obj2txt(self._backend, alg[0].algorithm) - return x509.ObjectIdentifier(oid) - - @property - def issuer(self) -> x509.Name: - issuer = self._backend._lib.X509_CRL_get_issuer(self._x509_crl) - self._backend.openssl_assert(issuer != self._backend._ffi.NULL) - return _decode_x509_name(self._backend, issuer) - - @property - def next_update(self) -> typing.Optional[datetime.datetime]: - nu = self._backend._lib.X509_CRL_get0_nextUpdate(self._x509_crl) - if nu == self._backend._ffi.NULL: - return None - return _parse_asn1_time(self._backend, nu) - - @property - def last_update(self) -> datetime.datetime: - lu = self._backend._lib.X509_CRL_get0_lastUpdate(self._x509_crl) - self._backend.openssl_assert(lu != self._backend._ffi.NULL) - return _parse_asn1_time(self._backend, lu) - - @property - def signature(self) -> bytes: - sig = self._backend._ffi.new("ASN1_BIT_STRING **") - self._backend._lib.X509_CRL_get0_signature( - self._x509_crl, sig, self._backend._ffi.NULL - ) - self._backend.openssl_assert(sig[0] != self._backend._ffi.NULL) - return _asn1_string_to_bytes(self._backend, sig[0]) - - @property - def tbs_certlist_bytes(self) -> bytes: - pp = self._backend._ffi.new("unsigned char **") - res = self._backend._lib.i2d_re_X509_CRL_tbs(self._x509_crl, pp) - self._backend.openssl_assert(res > 0) - pp = self._backend._ffi.gc( - pp, lambda pointer: self._backend._lib.OPENSSL_free(pointer[0]) - ) - return self._backend._ffi.buffer(pp[0], res)[:] - - def public_bytes(self, encoding: serialization.Encoding) -> bytes: - bio = self._backend._create_mem_bio_gc() - if encoding is serialization.Encoding.PEM: - res = self._backend._lib.PEM_write_bio_X509_CRL( - bio, self._x509_crl - ) - elif encoding is serialization.Encoding.DER: - res = self._backend._lib.i2d_X509_CRL_bio(bio, self._x509_crl) - else: - raise TypeError("encoding must be an item from the Encoding enum") - - self._backend.openssl_assert(res == 1) - return self._backend._read_mem_bio(bio) - - def _revoked_cert(self, idx): - revoked = self._backend._lib.X509_CRL_get_REVOKED(self._x509_crl) - r = self._backend._lib.sk_X509_REVOKED_value(revoked, idx) - self._backend.openssl_assert(r != self._backend._ffi.NULL) - return _RevokedCertificate(self._backend, self, r) - - def __iter__(self): - for i in range(len(self)): - yield self._revoked_cert(i) - - def __getitem__(self, idx): - if isinstance(idx, slice): - start, stop, step = idx.indices(len(self)) - return [self._revoked_cert(i) for i in range(start, stop, step)] - else: - idx = operator.index(idx) - if idx < 0: - idx += len(self) - if not 0 <= idx < len(self): - raise IndexError - return self._revoked_cert(idx) - - def __len__(self) -> int: - revoked = self._backend._lib.X509_CRL_get_REVOKED(self._x509_crl) - if revoked == self._backend._ffi.NULL: - return 0 - else: - return self._backend._lib.sk_X509_REVOKED_num(revoked) - - @utils.cached_property - def extensions(self) -> x509.Extensions: - return self._backend._crl_extension_parser.parse(self._x509_crl) - - def is_signature_valid(self, public_key: PUBLIC_KEY_TYPES) -> bool: - if not isinstance( - public_key, - ( - dsa._DSAPublicKey, - rsa._RSAPublicKey, - ec._EllipticCurvePublicKey, - ), - ): - raise TypeError( - "Expecting one of DSAPublicKey, RSAPublicKey," - " or EllipticCurvePublicKey." - ) - res = self._backend._lib.X509_CRL_verify( - self._x509_crl, public_key._evp_pkey - ) - - if res != 1: - self._backend._consume_errors() - return False - - return True - - class _CertificateSigningRequest(x509.CertificateSigningRequest): def __init__(self, backend, x509_req): self._backend = backend @@ -410,3 +187,27 @@ def get_attribute_for_oid(self, oid: x509.ObjectIdentifier) -> bytes: # that it is always a type of ASN1_STRING data = self._backend._ffi.cast("ASN1_STRING *", data) return _asn1_string_to_bytes(self._backend, data) + + +class _RawRevokedCertificate(x509.RevokedCertificate): + def __init__( + self, + serial_number: int, + revocation_date: datetime.datetime, + extensions: x509.Extensions, + ): + self._serial_number = serial_number + self._revocation_date = revocation_date + self._extensions = extensions + + @property + def serial_number(self) -> int: + return self._serial_number + + @property + def revocation_date(self) -> datetime.datetime: + return self._revocation_date + + @property + def extensions(self) -> x509.Extensions: + return self._extensions diff --git a/src/cryptography/hazmat/bindings/_rust/x509.pyi b/src/cryptography/hazmat/bindings/_rust/x509.pyi index 9c334441fb96..08b4e6c2ec06 100644 --- a/src/cryptography/hazmat/bindings/_rust/x509.pyi +++ b/src/cryptography/hazmat/bindings/_rust/x509.pyi @@ -6,15 +6,15 @@ from cryptography import x509 def parse_csr_extension( der_oid: bytes, ext_data: bytes ) -> x509.ExtensionType: ... -def parse_crl_entry_ext(der_oid: bytes, data: bytes) -> x509.ExtensionType: ... -def parse_crl_extension( - der_oid: bytes, ext_data: bytes -) -> x509.ExtensionType: ... def load_pem_x509_certificate(data: bytes) -> x509.Certificate: ... def load_der_x509_certificate(data: bytes) -> x509.Certificate: ... +def load_pem_x509_crl(data: bytes) -> x509.CertificateRevocationList: ... +def load_der_x509_crl(data: bytes) -> x509.CertificateRevocationList: ... def encode_precertificate_signed_certificate_timestamps( extension: x509.PrecertificateSignedCertificateTimestamps, ) -> bytes: ... class Sct: ... class Certificate: ... +class RevokedCertificate: ... +class CertificateRevocationList: ... diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index 22f6509f6eb5..17ab61fe7376 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -214,6 +214,10 @@ def extensions(self) -> Extensions: """ +# Runtime isinstance checks need this since the rust class is not a subclass. +RevokedCertificate.register(rust_x509.RevokedCertificate) + + class CertificateRevocationList(metaclass=abc.ABCMeta): @abc.abstractmethod def public_bytes(self, encoding: serialization.Encoding) -> bytes: @@ -334,6 +338,9 @@ def is_signature_valid(self, public_key: PUBLIC_KEY_TYPES) -> bool: """ +CertificateRevocationList.register(rust_x509.CertificateRevocationList) + + class CertificateSigningRequest(metaclass=abc.ABCMeta): @abc.abstractmethod def __eq__(self, other: object) -> bool: @@ -449,15 +456,13 @@ def load_der_x509_csr( def load_pem_x509_crl( data: bytes, backend: typing.Optional[Backend] = None ) -> CertificateRevocationList: - backend = _get_backend(backend) - return backend.load_pem_x509_crl(data) + return rust_x509.load_pem_x509_crl(data) def load_der_x509_crl( data: bytes, backend: typing.Optional[Backend] = None ) -> CertificateRevocationList: - backend = _get_backend(backend) - return backend.load_der_x509_crl(data) + return rust_x509.load_der_x509_crl(data) class CertificateSigningRequestBuilder(object): diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs index f9a1e05ad546..07590b3d2606 100644 --- a/src/rust/src/asn1.rs +++ b/src/rust/src/asn1.rs @@ -117,7 +117,7 @@ fn decode_dss_signature(py: pyo3::Python<'_>, data: &[u8]) -> Result( +pub(crate) fn py_uint_to_big_endian_bytes<'p>( py: pyo3::Python<'p>, v: &'p pyo3::types::PyLong, ) -> pyo3::PyResult<&'p [u8]> { diff --git a/src/rust/src/ocsp.rs b/src/rust/src/ocsp.rs index 97dda1144e3f..4b6e391a53f9 100644 --- a/src/rust/src/ocsp.rs +++ b/src/rust/src/ocsp.rs @@ -226,7 +226,9 @@ fn parse_ocsp_singleresp_ext(py: pyo3::Python<'_>, der_oid: &[u8], data: &[u8]) .call1((scts,))? .to_object(py)) } else { - x509::parse_crl_entry_ext(py, der_oid, data) + Ok(x509::parse_crl_entry_ext(py, oid, data)? + .map(|p| p.to_object(py)) + .unwrap_or_else(|| py.None())) } } diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index 1be065a89d18..22136da56097 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -2,7 +2,7 @@ // 2.0, and the BSD License. See the LICENSE file in the root of this repository // for complete details. -use crate::asn1::{big_asn1_uint_to_py, PyAsn1Error, PyAsn1Result}; +use crate::asn1::{big_asn1_uint_to_py, py_uint_to_big_endian_bytes, PyAsn1Error, PyAsn1Result}; use chrono::{Datelike, Timelike}; use pyo3::conversion::ToPyObject; use pyo3::types::IntoPyDict; @@ -10,6 +10,7 @@ use std::collections::hash_map::DefaultHasher; use std::collections::HashSet; use std::convert::TryInto; use std::hash::{Hash, Hasher}; +use std::sync::Arc; lazy_static::lazy_static! { static ref TLS_FEATURE_OID: asn1::ObjectIdentifier<'static> = asn1::ObjectIdentifier::from_string("1.3.6.1.5.5.7.1.24").unwrap(); @@ -73,13 +74,13 @@ struct TbsCertificate<'a> { pub(crate) type Name<'a> = asn1::SequenceOf<'a, asn1::SetOf<'a, AttributeTypeValue<'a>>>; -#[derive(asn1::Asn1Read, asn1::Asn1Write)] +#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Hash)] pub(crate) struct AttributeTypeValue<'a> { pub(crate) type_id: asn1::ObjectIdentifier<'a>, pub(crate) value: asn1::Tlv<'a>, } -#[derive(asn1::Asn1Read, asn1::Asn1Write)] +#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Hash, Clone)] enum Time { UtcTime(asn1::UtcTime), GeneralizedTime(asn1::GeneralizedTime), @@ -539,6 +540,509 @@ fn load_der_x509_certificate(py: pyo3::Python<'_>, data: &[u8]) -> PyAsn1Result< }) } +#[pyo3::prelude::pyfunction] +fn load_der_x509_crl( + _py: pyo3::Python<'_>, + data: &[u8], +) -> Result { + let raw = OwnedRawCertificateRevocationList::try_new( + data.to_vec(), + |data| asn1::parse_single(data), + |_| Ok(pyo3::once_cell::GILOnceCell::new()), + )?; + + Ok(CertificateRevocationList { + raw: Arc::new(raw), + cached_extensions: None, + }) +} + +#[pyo3::prelude::pyfunction] +fn load_pem_x509_crl( + py: pyo3::Python<'_>, + data: &[u8], +) -> Result { + let block = pem::parse(data)?; + if block.tag != "X509 CRL" { + return Err(PyAsn1Error::from(pyo3::exceptions::PyValueError::new_err( + "Valid PEM but no BEGIN X509 CRL/END X509 delimiters. Are you sure this is a CRL?", + ))); + } + // TODO: Produces an extra copy + load_der_x509_crl(py, &block.contents) +} + +#[ouroboros::self_referencing] +struct OwnedRawCertificateRevocationList { + data: Vec, + #[borrows(data)] + #[covariant] + value: RawCertificateRevocationList<'this>, + #[borrows(data)] + #[not_covariant] + revoked_certs: pyo3::once_cell::GILOnceCell>>, +} + +#[pyo3::prelude::pyclass] +struct CertificateRevocationList { + raw: Arc, + + cached_extensions: Option, +} + +impl CertificateRevocationList { + fn public_bytes_der(&self) -> Vec { + asn1::write_single(self.raw.borrow_value()) + } + + fn revoked_cert(&self, py: pyo3::Python<'_>, idx: usize) -> pyo3::PyResult { + let raw = try_map_arc_data_crl(&self.raw, |_crl, revoked_certs| { + let revoked_certs = revoked_certs.get(py).unwrap(); + Ok::<_, pyo3::PyErr>(revoked_certs.get(idx).cloned().unwrap()) + })?; + Ok(RevokedCertificate { + raw, + cached_extensions: None, + }) + } + + fn len(&self) -> usize { + self.raw + .borrow_value() + .tbs_cert_list + .revoked_certificates + .as_ref() + .map_or(0, |v| v.len()) + } +} + +#[pyo3::prelude::pyproto] +impl pyo3::class::basic::PyObjectProtocol for CertificateRevocationList { + fn __richcmp__( + &self, + other: pyo3::pycell::PyRef, + op: pyo3::class::basic::CompareOp, + ) -> pyo3::PyResult { + match op { + pyo3::class::basic::CompareOp::Eq => { + Ok(self.raw.borrow_value() == other.raw.borrow_value()) + } + pyo3::class::basic::CompareOp::Ne => { + Ok(self.raw.borrow_value() != other.raw.borrow_value()) + } + _ => Err(pyo3::exceptions::PyTypeError::new_err( + "CRLs cannot be ordered", + )), + } + } +} + +#[pyo3::prelude::pyproto] +impl pyo3::PyMappingProtocol for CertificateRevocationList { + fn __len__(&self) -> usize { + self.len() + } + + fn __getitem__(&self, idx: &pyo3::PyAny) -> pyo3::PyResult { + let gil = pyo3::Python::acquire_gil(); + let py = gil.python(); + + self.raw.with(|val| { + val.revoked_certs.get_or_init(py, || { + match &val.value.tbs_cert_list.revoked_certificates { + Some(c) => c.clone().collect(), + None => vec![], + } + }); + }); + + if idx.is_instance::()? { + let indices = idx + .downcast::()? + .indices(self.len().try_into().unwrap())?; + let result = pyo3::types::PyList::empty(py); + for i in (indices.start..indices.stop).step_by(indices.step.try_into().unwrap()) { + let revoked_cert = + pyo3::pycell::PyCell::new(py, self.revoked_cert(py, i as usize)?)?; + result.append(revoked_cert)?; + } + Ok(result.to_object(py)) + } else { + let mut idx = idx.extract::()?; + if idx < 0 { + idx += self.len() as isize; + } + if idx >= (self.len() as isize) || idx < 0 { + return Err(pyo3::exceptions::PyIndexError::new_err(())); + } + Ok(pyo3::pycell::PyCell::new(py, self.revoked_cert(py, idx as usize)?)?.to_object(py)) + } + } +} + +#[pyo3::prelude::pymethods] +impl CertificateRevocationList { + fn fingerprint<'p>( + &self, + py: pyo3::Python<'p>, + algorithm: pyo3::PyObject, + ) -> pyo3::PyResult<&'p pyo3::PyAny> { + let hashes_mod = py.import("cryptography.hazmat.primitives.hashes")?; + let h = hashes_mod.getattr("Hash")?.call1((algorithm,))?; + h.call_method1("update", (self.public_bytes_der().as_slice(),))?; + h.call_method0("finalize") + } + + #[getter] + fn signature_algorithm_oid<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> { + let x509_module = py.import("cryptography.x509")?; + x509_module.call_method1( + "ObjectIdentifier", + (self.raw.borrow_value().signature_algorithm.oid.to_string(),), + ) + } + + #[getter] + fn signature_hash_algorithm<'p>( + &self, + py: pyo3::Python<'p>, + ) -> pyo3::PyResult<&'p pyo3::PyAny> { + let oid = self.signature_algorithm_oid(py)?; + let oid_module = py.import("cryptography.hazmat._oid")?; + let exceptions_module = py.import("cryptography.exceptions")?; + match oid_module.getattr("_SIG_OIDS_TO_HASH")?.get_item(oid) { + Ok(v) => Ok(v), + Err(_) => Err(pyo3::PyErr::from_instance(exceptions_module.call_method1( + "UnsupportedAlgorithm", + (format!( + "Signature algorithm OID:{} not recognized", + self.raw.borrow_value().signature_algorithm.oid + ),), + )?)), + } + } + + #[getter] + fn signature(&self) -> &[u8] { + self.raw.borrow_value().signature_value.as_bytes() + } + + #[getter] + fn tbs_certlist_bytes<'p>(&self, py: pyo3::Python<'p>) -> &'p pyo3::types::PyBytes { + let b = asn1::write_single(&self.raw.borrow_value().tbs_cert_list); + pyo3::types::PyBytes::new(py, &b) + } + + fn public_bytes<'p>( + &self, + py: pyo3::Python<'p>, + encoding: &pyo3::PyAny, + ) -> pyo3::PyResult<&'p pyo3::types::PyBytes> { + let encoding_class = py + .import("cryptography.hazmat.primitives.serialization")? + .getattr("Encoding")?; + + let result = asn1::write_single(self.raw.borrow_value()); + if encoding == encoding_class.getattr("DER")? { + Ok(pyo3::types::PyBytes::new(py, &result)) + } else if encoding == encoding_class.getattr("PEM")? { + let pem = pem::encode_config( + &pem::Pem { + tag: "X509 CRL".to_string(), + contents: result, + }, + pem::EncodeConfig { + line_ending: pem::LineEnding::LF, + }, + ) + .into_bytes(); + Ok(pyo3::types::PyBytes::new(py, &pem)) + } else { + Err(pyo3::exceptions::PyTypeError::new_err( + "encoding must be an item from the Encoding enum", + )) + } + } + + #[getter] + fn issuer<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> { + parse_name(py, &self.raw.borrow_value().tbs_cert_list.issuer) + } + + #[getter] + fn next_update<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> { + match &self.raw.borrow_value().tbs_cert_list.next_update { + Some(t) => chrono_to_py(py, t.as_chrono()), + None => Ok(py.None().into_ref(py)), + } + } + + #[getter] + fn last_update<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> { + chrono_to_py( + py, + self.raw + .borrow_value() + .tbs_cert_list + .this_update + .as_chrono(), + ) + } + + #[getter] + fn extensions(&mut self, py: pyo3::Python<'_>) -> pyo3::PyResult { + let x509_module = py.import("cryptography.x509")?; + parse_and_cache_extensions( + py, + &mut self.cached_extensions, + &self.raw.borrow_value().tbs_cert_list.crl_extensions, + |oid, ext_data| { + if oid == &*CRL_NUMBER_OID { + let bignum = asn1::parse_single::>(ext_data)?; + let pynum = big_asn1_uint_to_py(py, bignum)?; + Ok(Some(x509_module.getattr("CRLNumber")?.call1((pynum,))?)) + } else if oid == &*DELTA_CRL_INDICATOR_OID { + let bignum = asn1::parse_single::>(ext_data)?; + let pynum = big_asn1_uint_to_py(py, bignum)?; + Ok(Some( + x509_module.getattr("DeltaCRLIndicator")?.call1((pynum,))?, + )) + } else if oid == &*ISSUER_ALTERNATIVE_NAME_OID { + let gn_seq = + asn1::parse_single::>>(ext_data)?; + let ians = parse_general_names(py, gn_seq)?; + Ok(Some( + x509_module + .getattr("IssuerAlternativeName")? + .call1((ians,))?, + )) + } else if oid == &*AUTHORITY_INFORMATION_ACCESS_OID { + let ads = parse_access_descriptions(py, ext_data)?; + Ok(Some( + x509_module + .getattr("AuthorityInformationAccess")? + .call1((ads,))?, + )) + } else if oid == &*AUTHORITY_KEY_IDENTIFIER_OID { + Ok(Some(parse_authority_key_identifier(py, ext_data)?)) + } else if oid == &*ISSUING_DISTRIBUTION_POINT_OID { + let idp = asn1::parse_single::>(ext_data)?; + let (full_name, relative_name) = match idp.distribution_point { + Some(data) => parse_distribution_point_name(py, data)?, + None => (py.None(), py.None()), + }; + let reasons = parse_distribution_point_reasons(py, idp.only_some_reasons)?; + Ok(Some( + x509_module.getattr("IssuingDistributionPoint")?.call1(( + full_name, + relative_name, + idp.only_contains_user_certs, + idp.only_contains_ca_certs, + reasons, + idp.indirect_crl, + idp.only_contains_attribute_certs, + ))?, + )) + } else if oid == &*FRESHEST_CRL_OID { + Ok(Some( + x509_module + .getattr("FreshestCRL")? + .call1((parse_distribution_points(py, ext_data)?,))?, + )) + } else { + Ok(None) + } + }, + ) + } + + fn get_revoked_certificate_by_serial_number( + &mut self, + py: pyo3::Python<'_>, + serial: &pyo3::types::PyLong, + ) -> pyo3::PyResult> { + let serial_bytes = py_uint_to_big_endian_bytes(py, serial)?; + let owned = OwnedRawRevokedCertificate::try_new(Arc::clone(&self.raw), |v| { + let certs = match v.borrow_value().tbs_cert_list.revoked_certificates.clone() { + Some(certs) => certs, + None => return Err(()), + }; + + // TODO: linear scan. Make a hash or bisect! + for cert in certs { + if serial_bytes == cert.user_certificate.as_bytes() { + return Ok(cert); + } + } + Err(()) + }); + match owned { + Ok(o) => Ok(Some(RevokedCertificate { + raw: o, + cached_extensions: None, + })), + Err(()) => Ok(None), + } + } + + fn is_signature_valid<'p>( + slf: pyo3::pycell::PyRef<'_, Self>, + py: pyo3::Python<'p>, + public_key: &'p pyo3::PyAny, + ) -> pyo3::PyResult<&'p pyo3::PyAny> { + let backend = py + .import("cryptography.hazmat.backends.openssl.backend")? + .getattr("backend")?; + backend.call_method1("_crl_is_signature_valid", (slf, public_key)) + } +} + +#[pyo3::prelude::pyproto] +impl pyo3::PyIterProtocol<'_> for CertificateRevocationList { + fn __iter__(slf: pyo3::pycell::PyRef<'p, Self>) -> CRLIterator { + CRLIterator { + contents: OwnedCRLIteratorData::try_new(Arc::clone(&slf.raw), |v| { + Ok::<_, ()>(v.borrow_value().tbs_cert_list.revoked_certificates.clone()) + }) + .unwrap(), + } + } +} + +#[ouroboros::self_referencing] +struct OwnedCRLIteratorData { + data: Arc, + #[borrows(data)] + #[covariant] + value: Option>>, +} + +#[pyo3::prelude::pyclass] +struct CRLIterator { + contents: OwnedCRLIteratorData, +} + +// Open-coded implementation of the API discussed in +// https://github.com/joshua-maros/ouroboros/issues/38 +fn try_map_arc_data_crl( + crl: &Arc, + f: impl for<'this> FnOnce( + &'this OwnedRawCertificateRevocationList, + &pyo3::once_cell::GILOnceCell>>, + ) -> Result, E>, +) -> Result { + OwnedRawRevokedCertificate::try_new(Arc::clone(crl), |inner_crl| { + crl.with(|value| { + f(inner_crl, unsafe { + std::mem::transmute(value.revoked_certs) + }) + }) + }) +} +fn try_map_arc_data_mut_crl_iterator( + it: &mut OwnedCRLIteratorData, + f: impl for<'this> FnOnce( + &'this OwnedRawCertificateRevocationList, + &mut Option>>, + ) -> Result, E>, +) -> Result { + OwnedRawRevokedCertificate::try_new(Arc::clone(it.borrow_data()), |inner_it| { + it.with_value_mut(|value| f(inner_it, unsafe { std::mem::transmute(value) })) + }) +} + +#[pyo3::prelude::pyproto] +impl pyo3::PyIterProtocol<'_> for CRLIterator { + fn __iter__(slf: pyo3::pycell::PyRef<'p, Self>) -> pyo3::pycell::PyRef<'p, Self> { + slf + } + + fn __next__(mut slf: pyo3::pycell::PyRefMut<'p, Self>) -> Option { + let revoked = try_map_arc_data_mut_crl_iterator(&mut slf.contents, |_data, v| match v { + Some(v) => match v.next() { + Some(revoked) => Ok(revoked), + None => Err(()), + }, + None => Err(()), + }) + .ok()?; + Some(RevokedCertificate { + raw: revoked, + cached_extensions: None, + }) + } +} + +#[pyo3::prelude::pyproto] +impl pyo3::PySequenceProtocol<'_> for CRLIterator { + fn __len__(&self) -> usize { + self.contents.borrow_value().clone().map_or(0, |v| v.len()) + } +} + +#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Hash)] +struct RawCertificateRevocationList<'a> { + tbs_cert_list: TBSCertList<'a>, + signature_algorithm: AlgorithmIdentifier<'a>, + signature_value: asn1::BitString<'a>, +} + +#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Hash)] +struct TBSCertList<'a> { + version: Option, + signature: AlgorithmIdentifier<'a>, + issuer: Name<'a>, + this_update: Time, + next_update: Option