Upgrade cryptography from 2.5 to 3.3 am: c6ba99dd61 am: 59e6f3b36b am: 3be2d17c44 am: 5b1b2f5ab8

Original change: https://android-review.googlesource.com/c/platform/external/python/cryptography/+/1888276

Change-Id: I312ce518598bb6d0e2ee4ec1649429e04b8958e1
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 7ee6d4d..4dd7146 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,300 @@
 Changelog
 =========
 
+.. _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
+~~~~~~~~~~~~~~~~~~
+
+* Re-added a legacy symbol causing problems for older ``pyOpenSSL`` users.
+
+.. _v3-3:
+
+3.3 - 2020-12-08
+~~~~~~~~~~~~~~~~
+
+* **BACKWARDS INCOMPATIBLE:** Support for Python 3.5 has been removed due to
+  low usage and maintenance burden.
+* **BACKWARDS INCOMPATIBLE:** The
+  :class:`~cryptography.hazmat.primitives.ciphers.modes.GCM` and
+  :class:`~cryptography.hazmat.primitives.ciphers.aead.AESGCM` now require
+  64-bit to 1024-bit (8 byte to 128 byte) initialization vectors. This change
+  is to conform with an upcoming OpenSSL release that will no longer support
+  sizes outside this window.
+* **BACKWARDS INCOMPATIBLE:** When deserializing asymmetric keys we now
+  raise ``ValueError`` rather than ``UnsupportedAlgorithm`` when an
+  unsupported cipher is used. This change is to conform with an upcoming
+  OpenSSL release that will no longer distinguish between error types.
+* **BACKWARDS INCOMPATIBLE:** We no longer allow loading of finite field
+  Diffie-Hellman parameters of less than 512 bits in length. This change is to
+  conform with an upcoming OpenSSL release that no longer supports smaller
+  sizes. These keys were already wildly insecure and should not have been used
+  in any application outside of testing.
+* Updated Windows, macOS, and ``manylinux`` wheels to be compiled with
+  OpenSSL 1.1.1i.
+* Python 2 support is deprecated in ``cryptography``. This is the last release
+  that will support Python 2.
+* Added the
+  :meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey.recover_data_from_signature`
+  function to
+  :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`
+  for recovering the signed data from an RSA signature.
+
+.. _v3-2-1:
+
+3.2.1 - 2020-10-27
+~~~~~~~~~~~~~~~~~~
+
+* Disable blinding on RSA public keys to address an error with some versions
+  of OpenSSL.
+
+.. _v3-2:
+
+3.2 - 2020-10-25
+~~~~~~~~~~~~~~~~
+
+* **SECURITY ISSUE:** Attempted to make RSA PKCS#1v1.5 decryption more constant
+  time, to protect against Bleichenbacher vulnerabilities. Due to limitations
+  imposed by our API, we cannot completely mitigate this vulnerability and a
+  future release will contain a new API which is designed to be resilient to
+  these for contexts where it is required. Credit to **Hubert Kario** for
+  reporting the issue. *CVE-2020-25659*
+* Support for OpenSSL 1.0.2 has been removed. Users on older version of OpenSSL
+  will need to upgrade.
+* Added basic support for PKCS7 signing (including SMIME) via
+  :class:`~cryptography.hazmat.primitives.serialization.pkcs7.PKCS7SignatureBuilder`.
+
+.. _v3-1-1:
+
+3.1.1 - 2020-09-22
+~~~~~~~~~~~~~~~~~~
+
+* Updated Windows, macOS, and ``manylinux`` wheels to be compiled with
+  OpenSSL 1.1.1h.
+
+.. _v3-1:
+
+3.1 - 2020-08-26
+~~~~~~~~~~~~~~~~
+
+* **BACKWARDS INCOMPATIBLE:** Removed support for ``idna`` based
+  :term:`U-label` parsing in various X.509 classes. This support was originally
+  deprecated in version 2.1 and moved to an extra in 2.5.
+* Deprecated OpenSSL 1.0.2 support. OpenSSL 1.0.2 is no longer supported by
+  the OpenSSL project. The next version of ``cryptography`` will drop support
+  for it.
+* Deprecated support for Python 3.5. This version sees very little use and will
+  be removed in the next release.
+* ``backend`` arguments to functions are no longer required and the
+  default backend will automatically be selected if no ``backend`` is provided.
+* Added initial support for parsing certificates from PKCS7 files with
+  :func:`~cryptography.hazmat.primitives.serialization.pkcs7.load_pem_pkcs7_certificates`
+  and
+  :func:`~cryptography.hazmat.primitives.serialization.pkcs7.load_der_pkcs7_certificates`
+  .
+* Calling ``update`` or ``update_into`` on
+  :class:`~cryptography.hazmat.primitives.ciphers.CipherContext` with ``data``
+  longer than 2\ :sup:`31` bytes no longer raises an ``OverflowError``. This
+  also resolves the same issue in :doc:`/fernet`.
+
+.. _v3-0:
+
+3.0 - 2020-07-20
+~~~~~~~~~~~~~~~~
+
+* **BACKWARDS INCOMPATIBLE:** Removed support for passing an
+  :class:`~cryptography.x509.Extension` instance to
+  :meth:`~cryptography.x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier`,
+  as per our deprecation policy.
+* **BACKWARDS INCOMPATIBLE:** Support for LibreSSL 2.7.x, 2.8.x, and 2.9.0 has
+  been removed (2.9.1+ is still supported).
+* **BACKWARDS INCOMPATIBLE:** Dropped support for macOS 10.9, macOS users must
+  upgrade to 10.10 or newer.
+* **BACKWARDS INCOMPATIBLE:** RSA
+  :meth:`~cryptography.hazmat.primitives.asymmetric.rsa.generate_private_key`
+  no longer accepts ``public_exponent`` values except 65537 and 3 (the latter
+  for legacy purposes).
+* **BACKWARDS INCOMPATIBLE:** X.509 certificate parsing now enforces that the
+  ``version`` field contains a valid value, rather than deferring this check
+  until :attr:`~cryptography.x509.Certificate.version` is accessed.
+* Deprecated support for Python 2. At the time there is no time table for
+  actually dropping support, however we strongly encourage all users to upgrade
+  their Python, as Python 2 no longer receives support from the Python core
+  team.
+
+  If you have trouble suppressing this warning in tests view the :ref:`FAQ
+  entry addressing this issue <faq-howto-handle-deprecation-warning>`.
+
+* Added support for ``OpenSSH`` serialization format for
+  ``ec``, ``ed25519``, ``rsa`` and ``dsa`` private keys:
+  :func:`~cryptography.hazmat.primitives.serialization.load_ssh_private_key`
+  for loading and
+  :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.OpenSSH`
+  for writing.
+* Added support for ``OpenSSH`` certificates to
+  :func:`~cryptography.hazmat.primitives.serialization.load_ssh_public_key`.
+* Added :meth:`~cryptography.fernet.Fernet.encrypt_at_time` and
+  :meth:`~cryptography.fernet.Fernet.decrypt_at_time` to
+  :class:`~cryptography.fernet.Fernet`.
+* Added support for the :class:`~cryptography.x509.SubjectInformationAccess`
+  X.509 extension.
+* Added support for parsing
+  :class:`~cryptography.x509.SignedCertificateTimestamps` in OCSP responses.
+* Added support for parsing attributes in certificate signing requests via
+  :meth:`~cryptography.x509.CertificateSigningRequest.get_attribute_for_oid`.
+* Added support for encoding attributes in certificate signing requests via
+  :meth:`~cryptography.x509.CertificateSigningRequestBuilder.add_attribute`.
+* On OpenSSL 1.1.1d and higher ``cryptography`` now uses OpenSSL's
+  built-in CSPRNG instead of its own OS random engine because these versions of
+  OpenSSL properly reseed on fork.
+* Added initial support for creating PKCS12 files with
+  :func:`~cryptography.hazmat.primitives.serialization.pkcs12.serialize_key_and_certificates`.
+
+.. _v2-9-2:
+
+2.9.2 - 2020-04-22
+~~~~~~~~~~~~~~~~~~
+
+* Updated the macOS wheel to fix an issue where it would not run on macOS
+  versions older than 10.15.
+
+.. _v2-9-1:
+
+2.9.1 - 2020-04-21
+~~~~~~~~~~~~~~~~~~
+
+* Updated Windows, macOS, and ``manylinux`` wheels to be compiled with
+  OpenSSL 1.1.1g.
+
+.. _v2-9:
+
+2.9 - 2020-04-02
+~~~~~~~~~~~~~~~~
+
+* **BACKWARDS INCOMPATIBLE:** Support for Python 3.4 has been removed due to
+  low usage and maintenance burden.
+* **BACKWARDS INCOMPATIBLE:** Support for OpenSSL 1.0.1 has been removed.
+  Users on older version of OpenSSL will need to upgrade.
+* **BACKWARDS INCOMPATIBLE:** Support for LibreSSL 2.6.x has been removed.
+* Removed support for calling
+  :meth:`~cryptography.hazmat.primitives.asymmetric.x25519.X25519PublicKey.public_bytes`
+  with no arguments, as per our deprecation policy. You must now pass
+  ``encoding`` and ``format``.
+* **BACKWARDS INCOMPATIBLE:** Reversed the order in which
+  :meth:`~cryptography.x509.Name.rfc4514_string` returns the RDNs
+  as required by :rfc:`4514`.
+* Updated Windows, macOS, and ``manylinux`` wheels to be compiled with
+  OpenSSL 1.1.1f.
+* Added support for parsing
+  :attr:`~cryptography.x509.ocsp.OCSPResponse.single_extensions` in an OCSP
+  response.
+* :class:`~cryptography.x509.NameAttribute` values can now be empty strings.
+
+.. _v2-8:
+
+2.8 - 2019-10-16
+~~~~~~~~~~~~~~~~
+
+* Updated Windows, macOS, and ``manylinux`` wheels to be compiled with
+  OpenSSL 1.1.1d.
+* Added support for Python 3.8.
+* Added class methods
+  :meth:`Poly1305.generate_tag
+  <cryptography.hazmat.primitives.poly1305.Poly1305.generate_tag>`
+  and
+  :meth:`Poly1305.verify_tag
+  <cryptography.hazmat.primitives.poly1305.Poly1305.verify_tag>`
+  for Poly1305 sign and verify operations.
+* Deprecated support for OpenSSL 1.0.1. Support will be removed in
+  ``cryptography`` 2.9.
+* We now ship ``manylinux2010`` wheels in addition to our ``manylinux1``
+  wheels.
+* Added support for ``ed25519`` and ``ed448`` keys in the
+  :class:`~cryptography.x509.CertificateBuilder`,
+  :class:`~cryptography.x509.CertificateSigningRequestBuilder`,
+  :class:`~cryptography.x509.CertificateRevocationListBuilder` and
+  :class:`~cryptography.x509.ocsp.OCSPResponseBuilder`.
+* ``cryptography`` no longer depends on ``asn1crypto``.
+* :class:`~cryptography.x509.FreshestCRL` is now allowed as a
+  :class:`~cryptography.x509.CertificateRevocationList` extension.
+
+.. _v2-7:
+
+2.7 - 2019-05-30
+~~~~~~~~~~~~~~~~
+
+* **BACKWARDS INCOMPATIBLE:** We no longer distribute 32-bit ``manylinux1``
+  wheels. Continuing to produce them was a maintenance burden.
+* **BACKWARDS INCOMPATIBLE:** Removed the
+  ``cryptography.hazmat.primitives.mac.MACContext`` interface. The ``CMAC`` and
+  ``HMAC`` APIs have not changed, but they are no longer registered as
+  ``MACContext`` instances.
+* Updated Windows, macOS, and ``manylinux1`` wheels to be compiled with
+  OpenSSL 1.1.1c.
+* Removed support for running our tests with ``setup.py test``. Users
+  interested in running our tests can continue to follow the directions in our
+  :doc:`development documentation</development/getting-started>`.
+* Add support for :class:`~cryptography.hazmat.primitives.poly1305.Poly1305`
+  when using OpenSSL 1.1.1 or newer.
+* Support serialization with ``Encoding.OpenSSH`` and ``PublicFormat.OpenSSH``
+  in
+  :meth:`Ed25519PublicKey.public_bytes
+  <cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey.public_bytes>`
+  .
+* Correctly allow passing a ``SubjectKeyIdentifier`` to
+  :meth:`~cryptography.x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier`
+  and deprecate passing an ``Extension`` object. The documentation always
+  required ``SubjectKeyIdentifier`` but the implementation previously
+  required an ``Extension``.
+
+.. _v2-6-1:
+
+2.6.1 - 2019-02-27
+~~~~~~~~~~~~~~~~~~
+
+* Resolved an error in our build infrastructure that broke our Python3 wheels
+  for macOS and Linux.
+
+.. _v2-6:
+
+2.6 - 2019-02-27
+~~~~~~~~~~~~~~~~
+
+* **BACKWARDS INCOMPATIBLE:** Removed
+  ``cryptography.hazmat.primitives.asymmetric.utils.encode_rfc6979_signature``
+  and
+  ``cryptography.hazmat.primitives.asymmetric.utils.decode_rfc6979_signature``,
+  which had been deprecated for nearly 4 years. Use
+  :func:`~cryptography.hazmat.primitives.asymmetric.utils.encode_dss_signature`
+  and
+  :func:`~cryptography.hazmat.primitives.asymmetric.utils.decode_dss_signature`
+  instead.
+* **BACKWARDS INCOMPATIBLE**: Removed ``cryptography.x509.Certificate.serial``,
+  which had been deprecated for nearly 3 years. Use
+  :attr:`~cryptography.x509.Certificate.serial_number` instead.
+* Updated Windows, macOS, and ``manylinux1`` wheels to be compiled with
+  OpenSSL 1.1.1b.
+* Added support for :doc:`/hazmat/primitives/asymmetric/ed448` when using
+  OpenSSL 1.1.1b or newer.
+* Added support for :doc:`/hazmat/primitives/asymmetric/ed25519` when using
+  OpenSSL 1.1.1b or newer.
+* :func:`~cryptography.hazmat.primitives.serialization.load_ssh_public_key` can
+  now load ``ed25519`` public keys.
+* Add support for easily mapping an object identifier to its elliptic curve
+  class via
+  :func:`~cryptography.hazmat.primitives.asymmetric.ec.get_curve_for_oid`.
+* Add support for OpenSSL when compiled with the ``no-engine``
+  (``OPENSSL_NO_ENGINE``) flag.
+
 .. _v2-5:
 
 2.5 - 2019-01-22
@@ -1099,8 +1393,8 @@
   :class:`~cryptography.fernet.MultiFernet`.
 * More bit-lengths are now supported for ``p`` and ``q`` when loading DSA keys
   from numbers.
-* Added :class:`~cryptography.hazmat.primitives.mac.MACContext` as a
-  common interface for CMAC and HMAC and deprecated ``CMACContext``.
+* Added ``MACContext`` as a common interface for CMAC and HMAC and
+  deprecated ``CMACContext``.
 * Added support for encoding and decoding :rfc:`6979` signatures in
   :doc:`/hazmat/primitives/asymmetric/utils`.
 * Added
diff --git a/Jenkinsfile b/Jenkinsfile
deleted file mode 100644
index 14a1ed7..0000000
--- a/Jenkinsfile
+++ /dev/null
@@ -1,247 +0,0 @@
-if (env.BRANCH_NAME == "master") {
-    properties([pipelineTriggers([cron('@daily')])])
-}
-
-def configs = [
-    [
-        label: 'windows',
-        toxenvs: ['py27', 'py34', 'py35', 'py36', 'py37'],
-    ],
-    [
-        label: 'windows64',
-        toxenvs: ['py27', 'py34', 'py35', 'py36', 'py37'],
-    ],
-    [
-        label: 'sierra',
-        toxenvs: ['py27', 'py36'],
-    ],
-    [
-        label: 'yosemite',
-        toxenvs: ['py27'],
-    ],
-    [
-        label: 'docker',
-        imageName: 'pyca/cryptography-runner-sid',
-        toxenvs: ['docs'],
-        artifacts: 'cryptography/docs/_build/html/**',
-        artifactExcludes: '**/*.doctree',
-    ],
-]
-
-def checkout_git(label) {
-    retry(3) {
-        def script = ""
-        if (env.BRANCH_NAME.startsWith('PR-')) {
-            script = """
-            git clone --depth=1 https://github.com/pyca/cryptography
-            cd cryptography
-            git fetch origin +refs/pull/${env.CHANGE_ID}/merge:
-            git checkout -qf FETCH_HEAD
-            """
-            if (label.contains("windows")) {
-                bat script
-            } else {
-                sh """#!/bin/sh
-                    set -xe
-                    ${script}
-                """
-            }
-        } else {
-            checkout([
-                $class: 'GitSCM',
-                branches: [[name: "*/${env.BRANCH_NAME}"]],
-                doGenerateSubmoduleConfigurations: false,
-                extensions: [[
-                    $class: 'RelativeTargetDirectory',
-                    relativeTargetDir: 'cryptography'
-                ]],
-                submoduleCfg: [],
-                userRemoteConfigs: [[
-                    'url': 'https://github.com/pyca/cryptography'
-                ]]
-            ])
-        }
-    }
-    if (label.contains("windows")) {
-        bat """
-            cd cryptography
-            git rev-parse HEAD
-        """
-    } else {
-        sh """
-            cd cryptography
-            git rev-parse HEAD
-        """
-    }
-}
-def build(toxenv, label, imageName, artifacts, artifactExcludes) {
-    try {
-        timeout(time: 30, unit: 'MINUTES') {
-
-            checkout_git(label)
-            checkout([
-                $class: 'GitSCM',
-                extensions: [[
-                    $class: 'RelativeTargetDirectory',
-                    relativeTargetDir: 'wycheproof',
-                ]],
-                userRemoteConfigs: [[
-                    'url': 'https://github.com/google/wycheproof',
-                ]]
-            ])
-
-            withCredentials([string(credentialsId: 'cryptography-codecov-token', variable: 'CODECOV_TOKEN')]) {
-                withEnv(["LABEL=$label", "TOXENV=$toxenv", "IMAGE_NAME=$imageName"]) {
-                    if (label.contains("windows")) {
-                        def pythonPath = [
-                            py27: "C:\\Python27\\python.exe",
-                            py34: "C:\\Python34\\python.exe",
-                            py35: "C:\\Python35\\python.exe",
-                            py36: "C:\\Python36\\python.exe",
-                            py37: "C:\\Python37\\python.exe"
-                        ]
-                        if (toxenv == "py35" || toxenv == "py36" || toxenv == "py37") {
-                            opensslPaths = [
-                                "windows": [
-                                    "include": "C:\\OpenSSL-Win32-2015\\include",
-                                    "lib": "C:\\OpenSSL-Win32-2015\\lib"
-                                ],
-                                "windows64": [
-                                    "include": "C:\\OpenSSL-Win64-2015\\include",
-                                    "lib": "C:\\OpenSSL-Win64-2015\\lib"
-                                ]
-                            ]
-                        } else {
-                            opensslPaths = [
-                                "windows": [
-                                    "include": "C:\\OpenSSL-Win32-2010\\include",
-                                    "lib": "C:\\OpenSSL-Win32-2010\\lib"
-                                ],
-                                "windows64": [
-                                    "include": "C:\\OpenSSL-Win64-2010\\include",
-                                    "lib": "C:\\OpenSSL-Win64-2010\\lib"
-                                ]
-                            ]
-                        }
-                        bat """
-                            cd cryptography
-                            @set PATH="C:\\Python27";"C:\\Python27\\Scripts";%PATH%
-                            @set PYTHON="${pythonPath[toxenv]}"
-
-                            @set INCLUDE="${opensslPaths[label]['include']}";%INCLUDE%
-                            @set LIB="${opensslPaths[label]['lib']}";%LIB%
-                            tox -r -- --wycheproof-root=../wycheproof
-                            IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
-                            virtualenv .codecov
-                            call .codecov/Scripts/activate
-                            REM this pin must be kept in sync with tox.ini
-                            pip install coverage
-                            pip install codecov
-                            codecov -e JOB_BASE_NAME,LABEL,TOXENV
-                        """
-                    } else if (label.contains("sierra") || label.contains("yosemite")) {
-                        ansiColor {
-                            sh """#!/usr/bin/env bash
-                                set -xe
-                                # Jenkins logs in as a non-interactive shell, so we don't even have /usr/local/bin in PATH
-                                export PATH="/usr/local/bin:\${PATH}"
-                                export PATH="/Users/jenkins/.pyenv/shims:\${PATH}"
-                                cd cryptography
-                                CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS=1 \
-                                    LDFLAGS="/usr/local/opt/openssl\\@1.1/lib/libcrypto.a /usr/local/opt/openssl\\@1.1/lib/libssl.a" \
-                                    CFLAGS="-I/usr/local/opt/openssl\\@1.1/include -Werror -Wno-error=deprecated-declarations -Wno-error=incompatible-pointer-types-discards-qualifiers -Wno-error=unused-function -Wno-error=unused-command-line-argument -mmacosx-version-min=10.9" \
-                                    tox -r --  --color=yes --wycheproof-root=../wycheproof
-                                virtualenv .venv
-                                source .venv/bin/activate
-                                # This pin must be kept in sync with tox.ini
-                                pip install coverage
-                                bash <(curl -s https://codecov.io/bash) -e JOB_BASE_NAME,LABEL,TOXENV
-                            """
-                        }
-                    } else {
-                        ansiColor {
-                            sh """#!/usr/bin/env bash
-                                set -xe
-                                cd cryptography
-                                tox -r -- --color=yes --wycheproof-root=../wycheproof
-                                virtualenv .venv
-                                source .venv/bin/activate
-                                # This pin must be kept in sync with tox.ini
-                                pip install coverage
-                                bash <(curl -s https://codecov.io/bash) -e JOB_BASE_NAME,LABEL,TOXENV,IMAGE_NAME
-                            """
-                        }
-                        if (artifacts) {
-                            archiveArtifacts artifacts: artifacts, excludes: artifactExcludes
-                        }
-                    }
-                }
-            }
-        }
-    } finally {
-        deleteDir()
-    }
-
-}
-
-def builders = [:]
-for (config in configs) {
-    def label = config["label"]
-    def toxenvs = config["toxenvs"]
-    def artifacts = config["artifacts"]
-    def artifactExcludes = config["artifactExcludes"]
-
-    for (_toxenv in toxenvs) {
-        def toxenv = _toxenv
-
-        if (label.contains("docker")) {
-            def imageName = config["imageName"]
-            def combinedName = "${imageName}-${toxenv}"
-            builders[combinedName] = {
-                node(label) {
-                    stage(combinedName) {
-                        def buildImage = docker.image(imageName)
-                        buildImage.pull()
-                        buildImage.inside {
-                            build(toxenv, label, imageName, artifacts, artifactExcludes)
-                        }
-                    }
-                }
-            }
-        } else {
-            def combinedName = "${label}-${toxenv}"
-            builders[combinedName] = {
-                node(label) {
-                    stage(combinedName) {
-                        build(toxenv, label, '', null, null)
-                    }
-                }
-            }
-        }
-    }
-}
-
-/* Add the python setup.py test builder */
-builders["setup.py-test"] = {
-    node("docker") {
-        stage("python setup.py test") {
-            docker.image("pyca/cryptography-runner-ubuntu-rolling").inside {
-                try {
-                    checkout_git("docker")
-                    sh """#!/usr/bin/env bash
-                        set -xe
-                        cd cryptography
-                        virtualenv .venv
-                        source .venv/bin/activate
-                        python setup.py test
-                    """
-                } finally {
-                    deleteDir()
-                }
-
-            }
-        }
-    }
-}
-
-parallel builders
diff --git a/LICENSE b/LICENSE
index a7692a9..0707425 100644
--- a/LICENSE
+++ b/LICENSE
@@ -2,282 +2,5 @@
 found in LICENSE.APACHE or LICENSE.BSD. Contributions to cryptography are made
 under the terms of *both* these licenses.
 
-The code used in the OpenSSL locking callback and OS random engine is derived
-from CPython, and is licensed under the terms of the PSF License Agreement.
-
-
-LICENSE.APACHE:
-                                 Apache License
-                           Version 2.0, January 2004
-                        https://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       https://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-
-LICENSE.BSD:
-Copyright (c) Individual contributors.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    1. Redistributions of source code must retain the above copyright notice,
-       this list of conditions and the following disclaimer.
-
-    2. Redistributions in binary form must reproduce the above copyright
-       notice, this list of conditions and the following disclaimer in the
-       documentation and/or other materials provided with the distribution.
-
-    3. Neither the name of PyCA Cryptography nor the names of its contributors
-       may be used to endorse or promote products derived from this software
-       without specific prior written permission.
-
-
-LICENSE.PSF:
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and
-   the Individual or Organization ("Licensee") accessing and otherwise using Python
-   2.7.12 software in source or binary form and its associated documentation.
-
-2. Subject to the terms and conditions of this License Agreement, PSF hereby
-   grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
-   analyze, test, perform and/or display publicly, prepare derivative works,
-   distribute, and otherwise use Python 2.7.12 alone or in any derivative
-   version, provided, however, that PSF's License Agreement and PSF's notice of
-   copyright, i.e., "Copyright © 2001-2016 Python Software Foundation; All Rights
-   Reserved" are retained in Python 2.7.12 alone or in any derivative version
-   prepared by Licensee.
-
-3. In the event Licensee prepares a derivative work that is based on or
-   incorporates Python 2.7.12 or any part thereof, and wants to make the
-   derivative work available to others as provided herein, then Licensee hereby
-   agrees to include in any such work a brief summary of the changes made to Python
-   2.7.12.
-
-4. PSF is making Python 2.7.12 available to Licensee on an "AS IS" basis.
-   PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.  BY WAY OF
-   EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR
-   WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE
-   USE OF PYTHON 2.7.12 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
-
-5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 2.7.12
-   FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF
-   MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.7.12, OR ANY DERIVATIVE
-   THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
-
-6. This License Agreement will automatically terminate upon a material breach of
-   its terms and conditions.
-
-7. Nothing in this License Agreement shall be deemed to create any relationship
-   of agency, partnership, or joint venture between PSF and Licensee.  This License
-   Agreement does not grant permission to use PSF trademarks or trade name in a
-   trademark sense to endorse or promote products or services of Licensee, or any
-   third party.
-
-8. By copying, installing or otherwise using Python 2.7.12, Licensee agrees
-   to be bound by the terms and conditions of this License Agreement.
+The code used in the OS random engine is derived from CPython, and is licensed
+under the terms of the PSF License Agreement.
diff --git a/MANIFEST.in b/MANIFEST.in
index 373c242..5c82725 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -4,6 +4,7 @@
 include LICENSE
 include LICENSE.APACHE
 include LICENSE.BSD
+include LICENSE.PSF
 include README.rst
 
 include pyproject.toml
@@ -12,4 +13,12 @@
 recursive-include src/_cffi_src *.py *.c *.h
 prune docs/_build
 recursive-include tests *.py
+exclude vectors
 recursive-exclude vectors *
+
+recursive-exclude .github *
+
+exclude release.py .coveragerc codecov.yml .readthedocs.yml dev-requirements.txt rtd-requirements.txt tox.ini
+
+recursive-exclude .zuul.d *
+recursive-exclude .zuul.playbooks *
diff --git a/METADATA b/METADATA
index 156c17a..ca6f3d5 100644
--- a/METADATA
+++ b/METADATA
@@ -2,7 +2,7 @@
 description:
     "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.4+, and "
+    ""cryptographic standard library". It supports Python 2.7, Python 3.6+, and "
     "PyPy 5.4+."
 
 third_party {
@@ -14,7 +14,7 @@
     type: GIT
     value: "https://github.com/pyca/cryptography"
   }
-  version: "2.5"
-  last_upgrade_date { year: 2019 month: 2 day: 26 }
+  version: "3.3.2"
+  last_upgrade_date { year: 2021 month: 11 day: 8 }
   license_type: NOTICE
 }
diff --git a/README.rst b/README.rst
index 13f2d7d..10de198 100644
--- a/README.rst
+++ b/README.rst
@@ -9,8 +9,8 @@
     :target: https://cryptography.io
     :alt: Latest Docs
 
-.. image:: https://travis-ci.org/pyca/cryptography.svg?branch=master
-    :target: https://travis-ci.org/pyca/cryptography
+.. 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://codecov.io/github/pyca/cryptography/coverage.svg?branch=master
     :target: https://codecov.io/github/pyca/cryptography?branch=master
@@ -18,7 +18,7 @@
 
 ``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.4+, and PyPy 5.3+.
+standard library". It supports Python 2.7, Python 3.6+, and PyPy 5.4+.
 
 ``cryptography`` includes both high level recipes and low level interfaces to
 common cryptographic algorithms such as symmetric ciphers, message digests, and
@@ -65,7 +65,7 @@
 
 
 .. _`documentation`: https://cryptography.io/
-.. _`the installation documentation`: https://cryptography.io/en/latest/installation/
+.. _`the installation documentation`: https://cryptography.io/en/latest/installation.html
 .. _`issue tracker`: https://github.com/pyca/cryptography/issues
 .. _`cryptography-dev`: https://mail.python.org/mailman/listinfo/cryptography-dev
-.. _`security reporting`: https://cryptography.io/en/latest/security/
+.. _`security reporting`: https://cryptography.io/en/latest/security.html
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 58827ed..333faad 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -1,7 +1,5 @@
 click
-clint
 coverage
-requests
 tox >= 2.4.1
 twine >= 1.8.0
 -e .[test,docs,docstest,pep8test]
diff --git a/docs/api-stability.rst b/docs/api-stability.rst
index 205b184..fd34ced 100644
--- a/docs/api-stability.rst
+++ b/docs/api-stability.rst
@@ -1,7 +1,7 @@
 API stability
 =============
 
-From its first release, ``cryptography`` will have a strong API stability
+From its first release, ``cryptography`` has had a strong API stability
 policy.
 
 What does this policy cover?
diff --git a/docs/conf.py b/docs/conf.py
index 4349b05..fb67ada 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -35,7 +35,7 @@
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
-sys.path.insert(0, os.path.abspath('.'))
+sys.path.insert(0, os.path.abspath("."))
 
 # -- General configuration ----------------------------------------------------
 
@@ -45,33 +45,33 @@
 # Add any Sphinx extension module names here, as strings. They can be
 # extensions  coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
 extensions = [
-    'sphinx.ext.autodoc',
-    'sphinx.ext.doctest',
-    'sphinx.ext.intersphinx',
-    'sphinx.ext.viewcode',
-    'cryptography-docs',
+    "sphinx.ext.autodoc",
+    "sphinx.ext.doctest",
+    "sphinx.ext.intersphinx",
+    "sphinx.ext.viewcode",
+    "cryptography-docs",
 ]
 
 if spelling is not None:
-    extensions.append('sphinxcontrib.spelling')
+    extensions.append("sphinxcontrib.spelling")
 
 # Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
+templates_path = ["_templates"]
 
 nitpicky = True
 
 # The suffix of source filenames.
-source_suffix = '.rst'
+source_suffix = ".rst"
 
 # The encoding of source files.
 # source_encoding = 'utf-8-sig'
 
 # The master toctree document.
-master_doc = 'index'
+master_doc = "index"
 
 # General information about the project.
-project = 'Cryptography'
-copyright = '2013-2017, Individual Contributors'
+project = "Cryptography"
+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
@@ -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__"]
 
@@ -97,7 +97,7 @@
 
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
-exclude_patterns = ['_build']
+exclude_patterns = ["_build"]
 
 # The reST default role (used for this markup: `text`) to use for all documents
 # default_role = None
@@ -114,7 +114,7 @@
 # show_authors = False
 
 # The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+pygments_style = "sphinx"
 
 # -- Options for HTML output --------------------------------------------------
 
@@ -130,22 +130,26 @@
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
 # so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+html_static_path = ["_static"]
 
 # Output file base name for HTML help builder.
-htmlhelp_basename = 'Cryptographydoc'
+htmlhelp_basename = "Cryptographydoc"
 
 
 # -- Options for LaTeX output -------------------------------------------------
 
-latex_elements = {
-}
+latex_elements = {}
 
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title, author, documentclass [howto/manual])
 latex_documents = [
-    ('index', 'Cryptography.tex', 'Cryptography Documentation',
-        'Individual Contributors', 'manual'),
+    (
+        "index",
+        "Cryptography.tex",
+        "Cryptography Documentation",
+        "Individual Contributors",
+        "manual",
+    ),
 ]
 
 # -- Options for manual page output -------------------------------------------
@@ -153,8 +157,13 @@
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
 man_pages = [
-    ('index', 'cryptography', 'Cryptography Documentation',
-        ['Individual Contributors'], 1)
+    (
+        "index",
+        "cryptography",
+        "Cryptography Documentation",
+        ["Individual Contributors"],
+        1,
+    )
 ]
 
 # -- Options for Texinfo output -----------------------------------------------
@@ -163,22 +172,31 @@
 # (source start file, target name, title, author,
 #  dir menu entry, description, category)
 texinfo_documents = [
-    ('index', 'Cryptography', 'Cryptography Documentation',
-        'Individual Contributors', 'Cryptography',
-        'One line description of project.',
-        'Miscellaneous'),
+    (
+        "index",
+        "Cryptography",
+        "Cryptography Documentation",
+        "Individual Contributors",
+        "Cryptography",
+        "One line description of project.",
+        "Miscellaneous",
+    ),
 ]
 
 # Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {'https://docs.python.org/3': None}
+intersphinx_mapping = {"https://docs.python.org/3": None}
 
-epub_theme = 'epub'
+epub_theme = "epub"
 
 # Retry requests in the linkcheck builder so that we're resillient against
 # transient network errors.
 linkcheck_retries = 10
 
+linkcheck_timeout = 5
+
 linkcheck_ignore = [
     # Small DH key results in a TLS failure on modern OpenSSL
-    "https://info.isl.ntt.co.jp/crypt/eng/camellia/",
+    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",
 ]
diff --git a/docs/development/c-bindings.rst b/docs/development/c-bindings.rst
index 1b58dab..e53e0ba 100644
--- a/docs/development/c-bindings.rst
+++ b/docs/development/c-bindings.rst
@@ -5,7 +5,7 @@
 
 .. _cffi: https://cffi.readthedocs.io
 
-Bindings live in :py:mod:`cryptography.hazmat.bindings`.
+Bindings live in ``cryptography.hazmat.bindings``.
 
 When modifying the bindings you will need to recompile the C extensions to
 test the changes. This can be accomplished with ``pip install -e .`` in the
@@ -189,9 +189,9 @@
 Sometimes, a set of loosely related features are added in the same
 version, and it's impractical to create ``#ifdef`` statements for each
 one. In that case, it may make sense to either check for a particular
-version. For example, to check for OpenSSL 1.1.0 or newer::
+version. For example, to check for OpenSSL 1.1.1 or newer::
 
-    #if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
+    #if CRYPTOGRAPHY_OPENSSL_111_OR_GREATER
 
 Sometimes, the version of a library on a particular platform will have
 features that you thought it wouldn't, based on its version.
diff --git a/docs/development/custom-vectors/arc4/generate_arc4.py b/docs/development/custom-vectors/arc4/generate_arc4.py
index 3dee44a..2ca85c9 100644
--- a/docs/development/custom-vectors/arc4/generate_arc4.py
+++ b/docs/development/custom-vectors/arc4/generate_arc4.py
@@ -12,10 +12,14 @@
 
 
 _RFC6229_KEY_MATERIALS = [
-    (True,
-     8 * '0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20'),
-    (False,
-     8 * '1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a')
+    (
+        True,
+        8 * "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20",
+    ),
+    (
+        False,
+        8 * "1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a",
+    ),
 ]
 
 
@@ -37,42 +41,43 @@
     3056,
     3072,
     4080,
-    4096
+    4096,
 ]
 
 
-_SIZES_TO_GENERATE = [
-    160
-]
+_SIZES_TO_GENERATE = [160]
 
 
 def _key_for_size(size, keyinfo):
     msb, key = keyinfo
     if msb:
-        return key[:size // 4]
+        return key[: size // 4]
     else:
-        return key[-size // 4:]
+        return key[-size // 4 :]
 
 
 def _build_vectors():
     count = 0
     output = []
     key = None
-    plaintext = binascii.unhexlify(32 * '0')
+    plaintext = binascii.unhexlify(32 * "0")
     for size in _SIZES_TO_GENERATE:
         for keyinfo in _RFC6229_KEY_MATERIALS:
             key = _key_for_size(size, keyinfo)
             cipher = ciphers.Cipher(
                 algorithms.ARC4(binascii.unhexlify(key)),
                 None,
-                default_backend())
+                default_backend(),
+            )
             encryptor = cipher.encryptor()
             current_offset = 0
             for offset in _RFC6229_OFFSETS:
                 if offset % 16 != 0:
                     raise ValueError(
-                        "Offset {} is not evenly divisible by 16"
-                        .format(offset))
+                        "Offset {} is not evenly divisible by 16".format(
+                            offset
+                        )
+                    )
                 while current_offset < offset:
                     encryptor.update(plaintext)
                     current_offset += len(plaintext)
@@ -80,19 +85,23 @@
                 count += 1
                 output.append("KEY = {}".format(key))
                 output.append("OFFSET = {}".format(offset))
-                output.append("PLAINTEXT = {}".format(
-                    binascii.hexlify(plaintext)))
-                output.append("CIPHERTEXT = {}".format(
-                    binascii.hexlify(encryptor.update(plaintext))))
+                output.append(
+                    "PLAINTEXT = {}".format(binascii.hexlify(plaintext))
+                )
+                output.append(
+                    "CIPHERTEXT = {}".format(
+                        binascii.hexlify(encryptor.update(plaintext))
+                    )
+                )
                 current_offset += len(plaintext)
             assert not encryptor.finalize()
     return "\n".join(output)
 
 
 def _write_file(data, filename):
-    with open(filename, 'w') as f:
+    with open(filename, "w") as f:
         f.write(data)
 
 
-if __name__ == '__main__':
-    _write_file(_build_vectors(), 'arc4.txt')
+if __name__ == "__main__":
+    _write_file(_build_vectors(), "arc4.txt")
diff --git a/docs/development/custom-vectors/cast5/generate_cast5.py b/docs/development/custom-vectors/cast5/generate_cast5.py
index a0e28e3..5208b90 100644
--- a/docs/development/custom-vectors/cast5/generate_cast5.py
+++ b/docs/development/custom-vectors/cast5/generate_cast5.py
@@ -14,7 +14,7 @@
     cipher = base.Cipher(
         algorithms.CAST5(binascii.unhexlify(key)),
         mode(binascii.unhexlify(iv)),
-        default_backend()
+        default_backend(),
     )
     encryptor = cipher.encryptor()
     ct = encryptor.update(binascii.unhexlify(plaintext))
@@ -23,33 +23,36 @@
 
 
 def build_vectors(mode, filename):
-    vector_file = open(filename, "r")
-
     count = 0
     output = []
     key = None
     iv = None
     plaintext = None
-    for line in vector_file:
-        line = line.strip()
-        if line.startswith("KEY"):
-            if count != 0:
-                output.append("CIPHERTEXT = {}".format(
-                    encrypt(mode, key, iv, plaintext))
-                )
-            output.append("\nCOUNT = {}".format(count))
-            count += 1
-            name, key = line.split(" = ")
-            output.append("KEY = {}".format(key))
-        elif line.startswith("IV"):
-            name, iv = line.split(" = ")
-            iv = iv[0:16]
-            output.append("IV = {}".format(iv))
-        elif line.startswith("PLAINTEXT"):
-            name, plaintext = line.split(" = ")
-            output.append("PLAINTEXT = {}".format(plaintext))
 
-    output.append("CIPHERTEXT = {}".format(encrypt(mode, key, iv, plaintext)))
+    with open(filename, "r") as vector_file:
+        for line in vector_file:
+            line = line.strip()
+            if line.startswith("KEY"):
+                if count != 0:
+                    output.append(
+                        "CIPHERTEXT = {}".format(
+                            encrypt(mode, key, iv, plaintext)
+                        )
+                    )
+                output.append("\nCOUNT = {}".format(count))
+                count += 1
+                name, key = line.split(" = ")
+                output.append("KEY = {}".format(key))
+            elif line.startswith("IV"):
+                name, iv = line.split(" = ")
+                iv = iv[0:16]
+                output.append("IV = {}".format(iv))
+            elif line.startswith("PLAINTEXT"):
+                name, plaintext = line.split(" = ")
+                output.append("PLAINTEXT = {}".format(plaintext))
+        output.append(
+            "CIPHERTEXT = {}".format(encrypt(mode, key, iv, plaintext))
+        )
     return "\n".join(output)
 
 
diff --git a/docs/development/custom-vectors/hkdf/generate_hkdf.py b/docs/development/custom-vectors/hkdf/generate_hkdf.py
index 767aedd..aa2fc27 100644
--- a/docs/development/custom-vectors/hkdf/generate_hkdf.py
+++ b/docs/development/custom-vectors/hkdf/generate_hkdf.py
@@ -13,27 +13,31 @@
 IKM = binascii.unhexlify(b"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b")
 L = 1200
 OKM = HKDF(
-    algorithm=hashes.SHA256(), length=L, salt=None, info=None,
-    backend=default_backend()
+    algorithm=hashes.SHA256(),
+    length=L,
+    salt=None,
+    info=None,
+    backend=default_backend(),
 ).derive(IKM)
 
 
 def _build_vectors():
-    output = []
-    output.append("COUNT = 0")
-    output.append("Hash = SHA-256")
-    output.append("IKM = " + binascii.hexlify(IKM).decode("ascii"))
-    output.append("salt = ")
-    output.append("info = ")
-    output.append("L = {}".format(L))
-    output.append("OKM = " + binascii.hexlify(OKM).decode("ascii"))
+    output = [
+        "COUNT = 0",
+        "Hash = SHA-256",
+        "IKM = " + binascii.hexlify(IKM).decode("ascii"),
+        "salt = ",
+        "info = ",
+        "L = {}".format(L),
+        "OKM = " + binascii.hexlify(OKM).decode("ascii"),
+    ]
     return "\n".join(output)
 
 
 def _write_file(data, filename):
-    with open(filename, 'w') as f:
+    with open(filename, "w") as f:
         f.write(data)
 
 
-if __name__ == '__main__':
-    _write_file(_build_vectors(), 'hkdf.txt')
+if __name__ == "__main__":
+    _write_file(_build_vectors(), "hkdf.txt")
diff --git a/docs/development/custom-vectors/idea/generate_idea.py b/docs/development/custom-vectors/idea/generate_idea.py
index 2eb6996..0030956 100644
--- a/docs/development/custom-vectors/idea/generate_idea.py
+++ b/docs/development/custom-vectors/idea/generate_idea.py
@@ -8,7 +8,7 @@
     cipher = base.Cipher(
         algorithms.IDEA(binascii.unhexlify(key)),
         mode(binascii.unhexlify(iv)),
-        backend
+        backend,
     )
     encryptor = cipher.encryptor()
     ct = encryptor.update(binascii.unhexlify(plaintext))
@@ -29,8 +29,10 @@
         line = line.strip()
         if line.startswith("KEY"):
             if count != 0:
-                output.append("CIPHERTEXT = {0}".format(
-                    encrypt(mode, key, iv, plaintext))
+                output.append(
+                    "CIPHERTEXT = {0}".format(
+                        encrypt(mode, key, iv, plaintext)
+                    )
                 )
             output.append("\nCOUNT = {0}".format(count))
             count += 1
diff --git a/docs/development/custom-vectors/idea/verify_idea.py b/docs/development/custom-vectors/idea/verify_idea.py
index 89713c8..d356de0 100644
--- a/docs/development/custom-vectors/idea/verify_idea.py
+++ b/docs/development/custom-vectors/idea/verify_idea.py
@@ -8,11 +8,13 @@
 
 
 def encrypt(mode, key, iv, plaintext):
-    encryptor = botan.Cipher("IDEA/{0}/NoPadding".format(mode), "encrypt",
-                             binascii.unhexlify(key))
+    encryptor = botan.Cipher(
+        "IDEA/{0}/NoPadding".format(mode), "encrypt", binascii.unhexlify(key)
+    )
 
-    cipher_text = encryptor.cipher(binascii.unhexlify(plaintext),
-                                   binascii.unhexlify(iv))
+    cipher_text = encryptor.cipher(
+        binascii.unhexlify(plaintext), binascii.unhexlify(iv)
+    )
     return binascii.hexlify(cipher_text)
 
 
@@ -22,12 +24,7 @@
 
     vectors = load_nist_vectors(vector_file)
     for vector in vectors:
-        ct = encrypt(
-            mode,
-            vector["key"],
-            vector["iv"],
-            vector["plaintext"]
-        )
+        ct = encrypt(mode, vector["key"], vector["iv"], vector["plaintext"])
         assert ct == vector["ciphertext"]
 
 
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 bd5148f..a43e150 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
@@ -62,9 +62,8 @@
             dmq1=private["dmq1"],
             iqmp=private["iqmp"],
             public_numbers=rsa.RSAPublicNumbers(
-                e=private["public_exponent"],
-                n=private["modulus"]
-            )
+                e=private["public_exponent"], n=private["modulus"]
+            ),
         ).private_key(backend)
         count = 1
 
@@ -74,8 +73,8 @@
                 padding.OAEP(
                     mgf=padding.MGF1(algorithm=hashes.SHA1()),
                     algorithm=hashes.SHA1(),
-                    label=None
-                )
+                    label=None,
+                ),
             )
             assert message == binascii.unhexlify(example["message"])
             ct = pkey.encrypt(
@@ -83,8 +82,8 @@
                 padding.OAEP(
                     mgf=padding.MGF1(algorithm=mgf1alg),
                     algorithm=hashalg,
-                    label=None
-                )
+                    label=None,
+                ),
             )
             output.append(
                 b"# OAEP Example {0} alg={1} mgf1={2}".format(
@@ -116,13 +115,12 @@
     hashes.SHA512(),
 ]
 for hashtuple in itertools.product(hashalgs, hashalgs):
-    if (
-        isinstance(hashtuple[0], hashes.SHA1) and
-        isinstance(hashtuple[1], hashes.SHA1)
+    if isinstance(hashtuple[0], hashes.SHA1) and isinstance(
+        hashtuple[1], hashes.SHA1
     ):
         continue
 
     write_file(
         build_vectors(hashtuple[0], hashtuple[1], oaep_path),
-        "oaep-{0}-{1}.txt".format(hashtuple[0].name, hashtuple[1].name)
+        "oaep-{0}-{1}.txt".format(hashtuple[0].name, hashtuple[1].name),
     )
diff --git a/docs/development/custom-vectors/secp256k1/generate_secp256k1.py b/docs/development/custom-vectors/secp256k1/generate_secp256k1.py
index d6a2071..bfb150b 100644
--- a/docs/development/custom-vectors/secp256k1/generate_secp256k1.py
+++ b/docs/development/custom-vectors/secp256k1/generate_secp256k1.py
@@ -10,9 +10,7 @@
 
 from cryptography_vectors import open_vector_file
 
-from tests.utils import (
-    load_fips_ecdsa_signing_vectors, load_vectors_from_file
-)
+from tests.utils import load_fips_ecdsa_signing_vectors, load_vectors_from_file
 
 HASHLIB_HASH_TYPES = {
     "SHA-1": hashlib.sha1,
@@ -32,13 +30,13 @@
         return self
 
     def digest(self):
-        return self.hasher.digest()[:256 // 8]
+        return self.hasher.digest()[: 256 // 8]
 
 
 def build_vectors(fips_vectors):
     vectors = defaultdict(list)
     for vector in fips_vectors:
-        vectors[vector['digest_algorithm']].append(vector['message'])
+        vectors[vector["digest_algorithm"]].append(vector["message"])
 
     for digest_algorithm, messages in vectors.items():
         if digest_algorithm not in HASHLIB_HASH_TYPES:
@@ -55,8 +53,9 @@
             # Sign the message using warner/ecdsa
             secret_key = SigningKey.generate(curve=SECP256k1)
             public_key = secret_key.get_verifying_key()
-            signature = secret_key.sign(message, hashfunc=hash_func,
-                                        sigencode=sigencode_der)
+            signature = secret_key.sign(
+                message, hashfunc=hash_func, sigencode=sigencode_der
+            )
 
             r, s = sigdecode_der(signature, None)
 
@@ -79,12 +78,8 @@
 dest_path = os.path.join("asymmetric", "ECDSA", "SECP256K1", "SigGen.txt")
 
 fips_vectors = load_vectors_from_file(
-    source_path,
-    load_fips_ecdsa_signing_vectors
+    source_path, load_fips_ecdsa_signing_vectors
 )
 
 with open_vector_file(dest_path, "w") as dest_file:
-    write_file(
-        build_vectors(fips_vectors),
-        dest_file
-    )
+    write_file(build_vectors(fips_vectors), dest_file)
diff --git a/docs/development/custom-vectors/secp256k1/verify_secp256k1.py b/docs/development/custom-vectors/secp256k1/verify_secp256k1.py
index b236d77..f721b00 100644
--- a/docs/development/custom-vectors/secp256k1/verify_secp256k1.py
+++ b/docs/development/custom-vectors/secp256k1/verify_secp256k1.py
@@ -6,12 +6,10 @@
 from cryptography.hazmat.primitives import hashes
 from cryptography.hazmat.primitives.asymmetric import ec
 from cryptography.hazmat.primitives.asymmetric.utils import (
-    encode_dss_signature
+    encode_dss_signature,
 )
 
-from tests.utils import (
-    load_fips_ecdsa_signing_vectors, load_vectors_from_file
-)
+from tests.utils import load_fips_ecdsa_signing_vectors, load_vectors_from_file
 
 CRYPTOGRAPHY_HASH_TYPES = {
     "SHA-1": hashes.SHA1,
@@ -23,37 +21,32 @@
 
 
 def verify_one_vector(vector):
-    digest_algorithm = vector['digest_algorithm']
-    message = vector['message']
-    x = vector['x']
-    y = vector['y']
-    signature = encode_dss_signature(vector['r'], vector['s'])
+    digest_algorithm = vector["digest_algorithm"]
+    message = vector["message"]
+    x = vector["x"]
+    y = vector["y"]
+    signature = encode_dss_signature(vector["r"], vector["s"])
 
-    numbers = ec.EllipticCurvePublicNumbers(
-        x, y,
-        ec.SECP256K1()
-    )
+    numbers = ec.EllipticCurvePublicNumbers(x, y, ec.SECP256K1())
 
     key = numbers.public_key(default_backend())
 
     verifier = key.verifier(
-        signature,
-        ec.ECDSA(CRYPTOGRAPHY_HASH_TYPES[digest_algorithm]())
+        signature, ec.ECDSA(CRYPTOGRAPHY_HASH_TYPES[digest_algorithm]())
     )
     verifier.update(message)
-    return verifier.verify()
+    verifier.verify()
 
 
 def verify_vectors(vectors):
     for vector in vectors:
-        assert verify_one_vector(vector)
+        verify_one_vector(vector)
 
 
 vector_path = os.path.join("asymmetric", "ECDSA", "SECP256K1", "SigGen.txt")
 
 secp256k1_vectors = load_vectors_from_file(
-    vector_path,
-    load_fips_ecdsa_signing_vectors
+    vector_path, load_fips_ecdsa_signing_vectors
 )
 
 verify_vectors(secp256k1_vectors)
diff --git a/docs/development/custom-vectors/seed/generate_seed.py b/docs/development/custom-vectors/seed/generate_seed.py
index 5c62d67..046fcfb 100644
--- a/docs/development/custom-vectors/seed/generate_seed.py
+++ b/docs/development/custom-vectors/seed/generate_seed.py
@@ -8,7 +8,7 @@
     cipher = base.Cipher(
         algorithms.SEED(binascii.unhexlify(key)),
         mode(binascii.unhexlify(iv)),
-        backend
+        backend,
     )
     encryptor = cipher.encryptor()
     ct = encryptor.update(binascii.unhexlify(plaintext))
@@ -29,8 +29,10 @@
         line = line.strip()
         if line.startswith("KEY"):
             if count != 0:
-                output.append("CIPHERTEXT = {0}".format(
-                    encrypt(mode, key, iv, plaintext))
+                output.append(
+                    "CIPHERTEXT = {0}".format(
+                        encrypt(mode, key, iv, plaintext)
+                    )
                 )
             output.append("\nCOUNT = {0}".format(count))
             count += 1
diff --git a/docs/development/custom-vectors/seed/verify_seed.py b/docs/development/custom-vectors/seed/verify_seed.py
index e626428..252088d 100644
--- a/docs/development/custom-vectors/seed/verify_seed.py
+++ b/docs/development/custom-vectors/seed/verify_seed.py
@@ -6,11 +6,13 @@
 
 
 def encrypt(mode, key, iv, plaintext):
-    encryptor = botan.Cipher("SEED/{0}/NoPadding".format(mode), "encrypt",
-                             binascii.unhexlify(key))
+    encryptor = botan.Cipher(
+        "SEED/{0}/NoPadding".format(mode), "encrypt", binascii.unhexlify(key)
+    )
 
-    cipher_text = encryptor.cipher(binascii.unhexlify(plaintext),
-                                   binascii.unhexlify(iv))
+    cipher_text = encryptor.cipher(
+        binascii.unhexlify(plaintext), binascii.unhexlify(iv)
+    )
     return binascii.hexlify(cipher_text)
 
 
@@ -20,12 +22,7 @@
 
     vectors = load_nist_vectors(vector_file)
     for vector in vectors:
-        ct = encrypt(
-            mode,
-            vector["key"],
-            vector["iv"],
-            vector["plaintext"]
-        )
+        ct = encrypt(mode, vector["key"], vector["iv"], vector["plaintext"])
         assert ct == vector["ciphertext"]
 
 
diff --git a/docs/development/getting-started.rst b/docs/development/getting-started.rst
index cc333e4..1d939a9 100644
--- a/docs/development/getting-started.rst
+++ b/docs/development/getting-started.rst
@@ -81,7 +81,7 @@
     ...
      py27: commands succeeded
     ERROR:   pypy: InterpreterNotFound: pypy
-     py34: commands succeeded
+     py38: commands succeeded
      docs: commands succeeded
      pep8: commands succeeded
 
diff --git a/docs/development/reviewing-patches.rst b/docs/development/reviewing-patches.rst
index bd3ee96..0844618 100644
--- a/docs/development/reviewing-patches.rst
+++ b/docs/development/reviewing-patches.rst
@@ -7,18 +7,18 @@
 
 When reviewing a patch try to keep each of these concepts in mind:
 
-Architecture
-------------
-
-* Is the proposed change being made in the correct place? Is it a fix in a
-  backend when it should be in the primitives?
-
 Intent
 ------
 
 * What is the change being proposed?
 * Do we want this feature or is the bug they're fixing really a bug?
 
+Architecture
+------------
+
+* Is the proposed change being made in the correct place? Is it a fix in a
+  backend when it should be in the primitives?
+
 Implementation
 --------------
 
diff --git a/docs/development/submitting-patches.rst b/docs/development/submitting-patches.rst
index ec00aa5..b4ed175 100644
--- a/docs/development/submitting-patches.rst
+++ b/docs/development/submitting-patches.rst
@@ -19,9 +19,10 @@
 ----
 
 When in doubt, refer to :pep:`8` for Python code. You can check if your code
-meets our automated requirements by running ``flake8`` against it. If you've
-installed the development requirements this will automatically use our
-configuration. You can also run the ``tox`` job with ``tox -e pep8``.
+meets our automated requirements by formatting it with ``black`` and running
+``flake8`` against it. If you've installed the development requirements this
+will automatically use our configuration. You can also run the ``tox`` job with
+``tox -e pep8``.
 
 `Write comments as complete sentences.`_
 
@@ -80,10 +81,9 @@
 output in order to allow transparent upgrading of the algorithms in use, as
 the algorithms or parameters needed to achieve a given security margin evolve.
 
-APIs at the :doc:`/hazmat/primitives/index` layer should always take an
-explicit backend, APIs at the recipes layer should automatically use the
-:func:`~cryptography.hazmat.backends.default_backend`, but optionally allow
-specifying a different backend.
+APIs at the :doc:`/hazmat/primitives/index` and recipes layer should
+automatically use the :func:`~cryptography.hazmat.backends.default_backend`,
+but optionally allow specifying a different backend.
 
 C bindings
 ~~~~~~~~~~
@@ -156,6 +156,6 @@
 
 .. _`Write comments as complete sentences.`: https://nedbatchelder.com/blog/201401/comments_should_be_sentences.html
 .. _`syntax`: https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#info-field-lists
-.. _`Studies have shown`: https://smartbear.com/SmartBear/media/pdfs/11_Best_Practices_for_Peer_Code_Review.pdf
+.. _`Studies have shown`: https://smartbear.com/learn/code-review/best-practices-for-peer-code-review/
 .. _`our mailing list`: https://mail.python.org/mailman/listinfo/cryptography-dev
 .. _`doc8`: https://github.com/openstack/doc8
diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst
index df1ecfa..f952337 100644
--- a/docs/development/test-vectors.rst
+++ b/docs/development/test-vectors.rst
@@ -23,7 +23,7 @@
 continuous integration environments.
 
 We have ensured all test vectors are used as of commit
-``c313761979d74b0417230eddd0f87d0cfab2b46b``.
+``2196000605e45d91097147c9c71f26b72af58003``.
 
 Asymmetric ciphers
 ~~~~~~~~~~~~~~~~~~
@@ -78,6 +78,8 @@
 * ``asymmetric/PEM_Serialization/rsa_public_key.pem`` and
   ``asymmetric/DER_Serialization/rsa_public_key.der``- Contains an RSA 2048
   bit public generated using OpenSSL from ``rsa_private_key.pem``.
+* ``asymmetric/PEM_Serialization/dsa_4096.pem`` - Contains a 4096-bit DSA
+  private key generated using OpenSSL.
 * ``asymmetric/PEM_Serialization/dsaparam.pem`` - Contains 2048-bit DSA
   parameters generated using OpenSSL; contains no keys.
 * ``asymmetric/PEM_Serialization/dsa_private_key.pem`` - Contains a DSA 2048
@@ -86,6 +88,11 @@
 * ``asymmetric/PEM_Serialization/dsa_public_key.pem`` and
   ``asymmetric/DER_Serialization/dsa_public_key.der`` - Contains a DSA 2048 bit
   key generated using OpenSSL from ``dsa_private_key.pem``.
+* ``asymmetric/DER_Serialization/dsa_public_key_no_params.der`` - Contains a
+  DSA public key with the optional parameters removed.
+* ``asymmetric/DER_Serialization/dsa_public_key_invalid_bit_string.der`` -
+  Contains a DSA public key with the bit string padding value set to 2 rather
+  than the required 0.
 * ``asymmetric/PKCS8/unenc-dsa-pkcs8.pem`` and
   ``asymmetric/DER_Serialization/unenc-dsa-pkcs8.der`` - Contains a DSA 1024
   bit key generated using OpenSSL.
@@ -102,6 +109,8 @@
 * ``x509/custom/ca/ca_key.pem`` - An unencrypted PCKS8 ``secp256r1`` key. It is
   the private key for the certificate ``x509/custom/ca/ca.pem``. This key is
   encoded in several of the PKCS12 custom vectors.
+* ``x509/custom/ca/rsa_key.pem`` - An unencrypted PCKS8 4096 bit RSA key. It is
+  the private key for the certificate ``x509/custom/ca/rsa_ca.pem``.
 * ``asymmetric/EC/compressed_points.txt`` - Contains compressed public points
   generated using OpenSSL.
 * ``asymmetric/X448/x448-pkcs8-enc.pem`` and
@@ -111,6 +120,13 @@
   contain an unencrypted X448 key.
 * ``asymmetric/X448/x448-pub.pem`` and ``asymmetric/X448/x448-pub.der`` contain
   an X448 public key.
+* ``asymmetric/Ed25519/ed25519-pkcs8-enc.pem`` and
+  ``asymmetric/Ed25519/ed25519-pkcs8-enc.der`` contain an Ed25519 key encrypted
+  with AES 256 CBC with the password ``password``.
+* ``asymmetric/Ed25519/ed25519-pkcs8.pem`` and
+  ``asymmetric/Ed25519/ed25519-pkcs8.der`` contain an unencrypted Ed25519 key.
+* ``asymmetric/Ed25519/ed25519-pub.pem`` and
+  ``asymmetric/Ed25519/ed25519-pub.der`` contain an Ed25519 public key.
 * ``asymmetric/X25519/x25519-pkcs8-enc.pem`` and
   ``asymmetric/X25519/x25519-pkcs8-enc.der`` contain an X25519 key encrypted
   with AES 256 CBC with the password ``password``.
@@ -118,6 +134,13 @@
   ``asymmetric/X25519/x25519-pkcs8.der`` contain an unencrypted X25519 key.
 * ``asymmetric/X25519/x25519-pub.pem`` and ``asymmetric/X25519/x25519-pub.der``
   contain an X25519 public key.
+* ``asymmetric/Ed448/ed448-pkcs8-enc.pem`` and
+  ``asymmetric/Ed448/ed448-pkcs8-enc.der`` contain an Ed448 key encrypted
+  with AES 256 CBC with the password ``password``.
+* ``asymmetric/Ed448/ed448-pkcs8.pem`` and
+  ``asymmetric/Ed448/ed448-pkcs8.der`` contain an unencrypted Ed448 key.
+* ``asymmetric/Ed448/ed448-pub.pem`` and ``asymmetric/Ed448/ed448-pub.der``
+  contain an Ed448 public key.
 
 
 Key exchange
@@ -161,6 +184,8 @@
   ``vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.der`` and
   ``vectors/cryptography_vectors/asymmetric/DH/dhpub_rfc5114_2.der`` contains
   are the above parameters and keys in DER format.
+* ``vectors/cryptography_vectors/asymmetric/DH/dh_key_256.pem`` contains
+  a PEM PKCS8 encoded DH key with a 256-bit key size.
 
 * ``vectors/cryptoraphy_vectors/asymmetric/ECDH/brainpool.txt`` contains
   Brainpool vectors from :rfc:`7027`.
@@ -217,6 +242,17 @@
   UTCTime in its validity->not_after.
 * ``letsencryptx3.pem`` - A subordinate certificate used by Let's Encrypt to
   issue end entity certificates.
+* ``ed25519-rfc8410.pem`` - A certificate containing an X25519 public key with
+  an ``ed25519`` signature taken from :rfc:`8410`.
+* ``root-ed25519.pem`` - An ``ed25519`` root certificate (``ed25519`` signature
+  with ``ed25519`` public key) from the OpenSSL test suite.
+  (`root-ed25519.pem`_)
+* ``server-ed25519-cert.pem`` - An ``ed25519`` server certificate (RSA
+  signature with ``ed25519`` public key) from the OpenSSL test suite.
+  (`server-ed25519-cert.pem`_)
+* ``server-ed448-cert.pem`` - An ``ed448`` server certificate (RSA
+  signature with ``ed448`` public key) from the OpenSSL test suite.
+  (`server-ed448-cert.pem`_)
 
 Custom X.509 Vectors
 ~~~~~~~~~~~~~~~~~~~~
@@ -371,9 +407,19 @@
   a ``policyConstraints`` extension with a ``requireExplicitPolicy`` value.
 * ``freshestcrl.pem`` - A self-signed certificate containing a ``freshestCRL``
   extension.
+* ``sia.pem`` - An RSA 2048 bit self-signed certificate containing a subject
+  information access extension with both a CA repository entry and a custom
+  OID entry.
 * ``ca/ca.pem`` - A self-signed certificate with ``basicConstraints`` set to
   true. Its private key is ``ca/ca_key.pem``. This certificate is encoded in
   several of the PKCS12 custom vectors.
+* ``negative_serial.pem`` - A certificate with a serial number that is a
+  negative number.
+* ``rsa_pss.pem`` - A certificate with an RSA PSS signature.
+* ``root-ed448.pem`` - An ``ed448`` self-signed CA certificate
+  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``.
 
 Custom X.509 Request Vectors
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -406,6 +452,14 @@
   critical.
 * ``invalid_signature.pem`` - A certificate signing request for an RSA
   1024 bit key containing an invalid signature with correct padding.
+* ``challenge.pem`` - A certificate signing request for an RSA 2048 bit key
+  containing a challenge password.
+* ``challenge-invalid.der`` - A certificate signing request for an RSA 2048 bit
+  key containing a challenge password attribute that has been encoded as an
+  ASN.1 integer rather than a string.
+* ``challenge-unstructured.pem`` - A certificate signing request for an RSA
+  2048 bit key containing a challenge password attribute and an unstructured
+  name attribute.
 
 Custom X.509 Certificate Revocation List Vectors
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -480,6 +534,12 @@
   contains a revoked certificate and no ``nextUpdate`` value.
 * ``x509/ocsp/resp-invalid-signature-oid.der`` - An OCSP response that was
   modified to contain an MD2 signature algorithm object identifier.
+* ``x509/ocsp/resp-single-extension-reason.der`` - An OCSP response that
+  contains a ``CRLReason`` single extension.
+* ``x509/ocsp/resp-sct-extension.der`` - An OCSP response containing a
+  ``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.
 
 Custom X.509 OCSP Test Vectors
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -515,6 +575,49 @@
   (``x509/custom/ca/ca.pem``) encrypted via AES 256 CBC with the
   password ``cryptography`` and no private key.
 
+Custom PKCS7 Test Vectors
+~~~~~~~~~~~~~~~~~~~~~~~~~
+* ``pkcs7/isrg.pem`` - A PEM encoded PKCS7 file containing the ISRG X1 root
+  CA.
+* ``pkcs7/amazon-roots.p7b`` - A DER encoded PCKS7 file containing Amazon Root
+  CA 2 and 3.
+* ``pkcs7/enveloped.pem`` - A PEM encoded PKCS7 file with enveloped data.
+
+Custom OpenSSH Test Vectors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Generated by
+``asymmetric/OpenSSH/gen.sh``
+using command-line tools from OpenSSH_7.6p1 package.
+
+* ``dsa-nopsw.key``, ``dsa-nopsw.key.pub``, ``dsa-nopsw.key-cert.pub`` -
+  DSA-1024 private key; and corresponding public key in plain format
+  and with self-signed certificate.
+* ``dsa-psw.key``, ``dsa-psw.key.pub`` -
+  Password-protected DSA-1024 private key and corresponding public key.
+  Password is "password".
+* ``ecdsa-nopsw.key``, ``ecdsa-nopsw.key.pub``,
+  ``ecdsa-nopsw.key-cert.pub`` -
+  SECP256R1 private key; and corresponding public key in plain format
+  and with self-signed certificate.
+* ``ecdsa-psw.key``, ``ecdsa-psw.key.pub`` -
+  Password-protected SECP384R1 private key and corresponding public key.
+  Password is "password".
+* ``ed25519-nopsw.key``, ``ed25519-nopsw.key.pub``,
+  ``ed25519-nopsw.key-cert.pub`` -
+  Ed25519 private key; and corresponding public key in plain format
+  and with self-signed certificate.
+* ``ed25519-psw.key``, ``ed25519-psw.key.pub`` -
+  Password-protected Ed25519 private key and corresponding public key.
+  Password is "password".
+* ``rsa-nopsw.key``, ``rsa-nopsw.key.pub``,
+  ``rsa-nopsw.key-cert.pub`` -
+  RSA-2048 private key; and corresponding public key in plain format
+  and with self-signed certificate.
+* ``rsa-psw.key``, ``rsa-psw.key.pub`` -
+  Password-protected RSA-2048 private key and corresponding public key.
+  Password is "password".
+
 Hashes
 ~~~~~~
 
@@ -593,6 +696,11 @@
 
 * AES-128, AES-192, AES-256, 3DES from `NIST SP-800-38B`_
 
+Poly1305
+~~~~~~~~
+
+* Test vectors from :rfc:`7539`.
+
 Creating test vectors
 ---------------------
 
@@ -629,7 +737,7 @@
 .. _`IETF`: https://www.ietf.org/
 .. _`Project Wycheproof`: https://github.com/google/wycheproof
 .. _`NIST CAVP`: https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program
-.. _`Bruce Schneier's vectors`: https://www.schneier.com/code/vectors.txt
+.. _`Bruce Schneier's vectors`: https://www.schneier.com/wp-content/uploads/2015/12/vectors-2.txt
 .. _`Camellia page`: https://info.isl.ntt.co.jp/crypt/eng/camellia/
 .. _`CRYPTREC`: https://www.cryptrec.go.jp
 .. _`OpenSSL's test vectors`: https://github.com/openssl/openssl/blob/97cf1f6c2854a3a955fd7dd3a1f113deba00c9ef/crypto/evp/evptests.txt#L232
@@ -654,13 +762,16 @@
 .. _`NIST SP-800-38B`: https://csrc.nist.gov/publications/detail/sp/800-38b/archive/2005-05-01
 .. _`NIST PKI Testing`: https://csrc.nist.gov/Projects/PKI-Testing
 .. _`testx509.pem`: https://github.com/openssl/openssl/blob/master/test/testx509.pem
-.. _`DigiCert Global Root G3`: https://cacerts.digicert.com/DigiCertGlobalRootG3.crt
+.. _`DigiCert Global Root G3`: http://cacerts.digicert.com/DigiCertGlobalRootG3.crt
 .. _`root data`: https://hg.mozilla.org/projects/nss/file/25b2922cc564/security/nss/lib/ckfw/builtins/certdata.txt#l2053
 .. _`asymmetric/public/PKCS1/dsa.pub.pem`: https://github.com/ruby/ruby/blob/4ccb387f3bc436a08fc6d72c4931994f5de95110/test/openssl/test_pkey_dsa.rb#L53
 .. _`Mozilla bug`: https://bugzilla.mozilla.org/show_bug.cgi?id=233586
-.. _`Russian CA`: https://e-trust.gosuslugi.ru/MainCA
+.. _`Russian CA`: https://e-trust.gosuslugi.ru/
 .. _`test/evptests.txt`: https://github.com/openssl/openssl/blob/2d0b44126763f989a4cbffbffe9d0c7518158bb7/test/evptests.txt
 .. _`unknown signature OID`: https://bugzilla.mozilla.org/show_bug.cgi?id=405966
 .. _`botan`: https://github.com/randombit/botan/blob/57789bdfc55061002b2727d0b32587612829a37c/src/tests/data/pubkey/dh.vec
 .. _`DHKE`: https://sandilands.info/sgordon/diffie-hellman-secret-key-exchange-with-openssl
 .. _`Botan's key wrap vectors`: https://github.com/randombit/botan/blob/737f33c09a18500e044dca3e2ae13bd2c08bafdd/src/tests/data/keywrap/nist_key_wrap.vec
+.. _`root-ed25519.pem`: https://github.com/openssl/openssl/blob/2a1e2fe145c6eb8e75aa2e1b3a8c3a49384b2852/test/certs/root-ed25519.pem
+.. _`server-ed25519-cert.pem`: https://github.com/openssl/openssl/blob/2a1e2fe145c6eb8e75aa2e1b3a8c3a49384b2852/test/certs/server-ed25519-cert.pem
+.. _`server-ed448-cert.pem`: https://github.com/openssl/openssl/blob/2a1e2fe145c6eb8e75aa2e1b3a8c3a49384b2852/test/certs/server-ed448-cert.pem
diff --git a/docs/doing-a-release.rst b/docs/doing-a-release.rst
index e7ee88f..043d52d 100644
--- a/docs/doing-a-release.rst
+++ b/docs/doing-a-release.rst
@@ -21,10 +21,10 @@
 -------------------------
 
 The release process creates wheels bundling OpenSSL for Windows, macOS, and
-Linux. Check that the Windows and macOS Jenkins builders have the latest
-version of OpenSSL installed and verify that the latest version is present in
-the ``pyca/cryptography-manylinux1`` docker containers. If anything is out
-of date follow the instructions for upgrading OpenSSL.
+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.
 
 Upgrading OpenSSL
 -----------------
diff --git a/docs/faq.rst b/docs/faq.rst
index 6d87661..d6f4ad3 100644
--- a/docs/faq.rst
+++ b/docs/faq.rst
@@ -1,6 +1,33 @@
 Frequently asked questions
 ==========================
 
+.. _faq-howto-handle-deprecation-warning:
+
+I cannot suppress the deprecation warning that ``cryptography`` emits on import
+-------------------------------------------------------------------------------
+
+.. hint::
+
+   The deprecation warning emitted on import does not inherit
+   :py:exc:`DeprecationWarning` but inherits :py:exc:`UserWarning`
+   instead.
+
+If your pytest setup follows the best practices of failing on
+emitted warnings (``filterwarnings = error``), you may ignore it
+by adding the following line at the end of the list::
+
+   ignore:Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.:UserWarning
+
+**Note:** Using ``cryptography.utils.CryptographyDeprecationWarning``
+is not possible here because specifying it triggers
+``import cryptography`` internally that emits the warning before
+the ignore rule even kicks in.
+
+Ref: https://github.com/pytest-dev/pytest/issues/7524
+
+The same applies when you use :py:func:`~warnings.filterwarnings` in
+your code or invoke CPython with :std:option:`-W` command line option.
+
 ``cryptography`` failed to install!
 -----------------------------------
 
@@ -43,18 +70,17 @@
   :class:`AES-GCM <cryptography.hazmat.primitives.ciphers.modes.GCM>` and
   :class:`~cryptography.hazmat.primitives.kdf.hkdf.HKDF`.
 
-Compiling ``cryptography`` on macOS produces a ``fatal error: 'openssl/aes.h' file not found`` error
-----------------------------------------------------------------------------------------------------
+Installing ``cryptography`` produces a ``fatal error: 'openssl/opensslv.h' file not found`` error
+-------------------------------------------------------------------------------------------------
 
-This happens because macOS 10.11 no longer includes a copy of OpenSSL.
-``cryptography`` now provides wheels which include a statically linked copy of
-OpenSSL. You're seeing this error because your copy of pip is too old to find
-our wheel files. Upgrade your copy of pip with ``pip install -U pip`` and then
-try install ``cryptography`` again.
+``cryptography`` provides wheels which include a statically linked copy of
+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.
 
-If you are using PyPy, we do not currently ship ``cryptography`` wheels for
-PyPy. You will need to install your own copy of OpenSSL -- we recommend using
-Homebrew.
+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.
 
 ``cryptography`` raised an ``InternalError`` and I'm not sure what to do?
 -------------------------------------------------------------------------
@@ -82,34 +108,22 @@
 versions with ``pip install -U pip setuptools`` (or on Windows
 ``python -m pip install -U pip setuptools``).
 
-Installing cryptography with OpenSSL 0.9.8 or 1.0.0 fails
----------------------------------------------------------
+Installing cryptography with OpenSSL 0.9.8, 1.0.0, 1.0.1, 1.0.2 fails
+---------------------------------------------------------------------
 
-The OpenSSL project has dropped support for the 0.9.8 and 1.0.0 release series.
-Since they are no longer receiving security patches from upstream,
-``cryptography`` is also dropping support for them. To fix this issue you
-should upgrade to a newer version of OpenSSL (1.0.2 or later). This may require
-you to upgrade to a newer operating system.
+The OpenSSL project has dropped support for the 0.9.8, 1.0.0, 1.0.1, and 1.0.2
+release series. Since they are no longer receiving security patches from
+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.
 
-Why are there no wheels for Python 3.5+ on Linux or macOS?
-----------------------------------------------------------
+Why are there no wheels for my Python3.x version?
+-------------------------------------------------
 
-Our Python3 wheels, for macOS and Linux, are ``abi3`` wheels. This means they
-support multiple versions of Python. The Python 3.4 ``abi3`` wheel can be used
-with any version of Python greater than or equal to 3.4. Recent versions of
-``pip`` will automatically install ``abi3`` wheels.
-
-``ImportError``: ``idna`` is not installed
-------------------------------------------
-
-``cryptography`` deprecated passing :term:`U-label` strings to various X.509
-constructors in version 2.1 and in version 2.5 moved the ``idna`` dependency
-to a ``setuptools`` extra. If you see this exception you should upgrade your
-software so that it no longer depends on this deprecated feature. If that is
-not yet possible you  can also install ``cryptography`` with
-``pip install cryptography[idna]`` to automatically install the missing
-dependency. This workaround will be available until the feature is fully
-removed.
+Our Python3 wheels are ``abi3`` wheels. This means they support multiple
+versions of Python. The ``abi3`` wheel can be used with any version of Python
+greater than or equal to the version it specifies. Recent versions of ``pip``
+will automatically install ``abi3`` wheels.
 
 Why can't I import my PEM file?
 -------------------------------
diff --git a/docs/fernet.rst b/docs/fernet.rst
index 9b95621..5e2655d 100644
--- a/docs/fernet.rst
+++ b/docs/fernet.rst
@@ -23,9 +23,10 @@
         >>> f.decrypt(token)
         b'my deep dark secret'
 
-    :param bytes key: A URL-safe base64-encoded 32-byte key. This **must** be
-                      kept secret. Anyone with this key is able to create and
-                      read messages.
+    :param key: A URL-safe base64-encoded 32-byte key. This **must** be
+                kept secret. Anyone with this key is able to create and
+                read messages.
+    :type key: bytes or str
 
     .. classmethod:: generate_key()
 
@@ -53,6 +54,28 @@
             generated in *plaintext*, the time a message was created will
             therefore be visible to a possible attacker.
 
+    .. method:: encrypt_at_time(data, current_time)
+
+       .. versionadded:: 3.0
+
+       Encrypts data passed using explicitly passed current time. See
+       :meth:`encrypt` for the documentation of the ``data`` parameter, the
+       return type and the exceptions raised.
+
+       The motivation behind this method is for the client code to be able to
+       test token expiration. Since this method can be used in an insecure
+       manner one should make sure the correct time (``int(time.time())``)
+       is passed as ``current_time`` outside testing.
+
+       :param int current_time: The current time.
+
+       .. note::
+
+            Similarly to :meth:`encrypt` the encrypted message contains the
+            timestamp in *plaintext*, in this case the timestamp is the value
+            of the ``current_time`` parameter.
+
+
     .. method:: decrypt(token, ttl=None)
 
         Decrypts a Fernet token. If successfully decrypted you will receive the
@@ -80,6 +103,23 @@
         :raises TypeError: This exception is raised if ``token`` is not
                            ``bytes``.
 
+    .. method:: decrypt_at_time(token, ttl, current_time)
+
+       .. versionadded:: 3.0
+
+       Decrypts a token using explicitly passed current time. See
+       :meth:`decrypt` for the documentation of the ``token`` and ``ttl``
+       parameters (``ttl`` is required here), the return type and the exceptions
+       raised.
+
+       The motivation behind this method is for the client code to be able to
+       test token expiration. Since this method can be used in an insecure
+       manner one should make sure the correct time (``int(time.time())``)
+       is passed as ``current_time`` outside testing.
+
+       :param int current_time: The current time.
+
+
     .. method:: extract_timestamp(token)
 
         .. versionadded:: 2.3
@@ -189,7 +229,6 @@
     >>> import base64
     >>> import os
     >>> from cryptography.fernet import Fernet
-    >>> from cryptography.hazmat.backends import default_backend
     >>> from cryptography.hazmat.primitives import hashes
     >>> from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
     >>> password = b"password"
@@ -199,7 +238,6 @@
     ...     length=32,
     ...     salt=salt,
     ...     iterations=100000,
-    ...     backend=default_backend()
     ... )
     >>> key = base64.urlsafe_b64encode(kdf.derive(password))
     >>> f = Fernet(key)
@@ -236,8 +274,9 @@
 -----------
 
 Fernet is ideal for encrypting data that easily fits in memory. As a design
-feature it does not expose unauthenticated bytes. Unfortunately, this makes it
-generally unsuitable for very large files at this time.
+feature it does not expose unauthenticated bytes. This means that the complete
+message contents must be available in memory, making Fernet generally
+unsuitable for very large files at this time.
 
 
 .. _`Fernet`: https://github.com/fernet/spec/
diff --git a/docs/hazmat/backends/index.rst b/docs/hazmat/backends/index.rst
index a8a1ff3..97dbc86 100644
--- a/docs/hazmat/backends/index.rst
+++ b/docs/hazmat/backends/index.rst
@@ -8,10 +8,13 @@
 
 .. currentmodule:: cryptography.hazmat.backends
 
-``cryptography`` was originally designed to support multiple backends, but
-this design has been deprecated.
+``cryptography`` was designed to support multiple cryptographic backends, but
+consumers rarely need this flexibility. Starting with version 3.1 ``backend``
+arguments are optional and the default backend will automatically be selected
+if none is specified.
 
-You can get the default backend by calling :func:`~default_backend`.
+On older versions you can get the default backend by calling
+:func:`~default_backend`.
 
 
 .. function:: default_backend()
diff --git a/docs/hazmat/backends/interfaces.rst b/docs/hazmat/backends/interfaces.rst
index 2c2d70e..36dd3a7 100644
--- a/docs/hazmat/backends/interfaces.rst
+++ b/docs/hazmat/backends/interfaces.rst
@@ -159,14 +159,13 @@
     .. method:: create_cmac_ctx(algorithm)
 
         Create a
-        :class:`~cryptography.hazmat.primitives.mac.MACContext` that
+        context that
         uses the specified ``algorithm`` to calculate a message authentication code.
 
         :param algorithm: An instance of
             :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`.
 
-        :returns:
-            :class:`~cryptography.hazmat.primitives.mac.MACContext`
+        :returns: CMAC object.
 
 
 .. class:: PBKDF2HMACBackend
diff --git a/docs/hazmat/backends/openssl.rst b/docs/hazmat/backends/openssl.rst
index 07ae74a..dd85d86 100644
--- a/docs/hazmat/backends/openssl.rst
+++ b/docs/hazmat/backends/openssl.rst
@@ -3,7 +3,7 @@
 OpenSSL backend
 ===============
 
-The `OpenSSL`_ C library. Cryptography supports OpenSSL version 1.0.1 and
+The `OpenSSL`_ C library. Cryptography supports OpenSSL version 1.1.0 and
 greater.
 
 .. data:: cryptography.hazmat.backends.openssl.backend
@@ -68,6 +68,12 @@
 OS random engine
 ----------------
 
+.. note::
+
+    As of OpenSSL 1.1.1d its CSPRNG is fork-safe by default.
+    ``cryptography`` does not compile or load the custom engine on
+    these versions.
+
 By default OpenSSL uses a user-space CSPRNG that is seeded from system random (
 ``/dev/urandom`` or ``CryptGenRandom``). This CSPRNG is not reseeded
 automatically when a process calls ``fork()``. This can result in situations
@@ -106,7 +112,7 @@
 +------------------------------------------+------------------------------+
 | Windows                                  | ``CryptGenRandom()``         |
 +------------------------------------------+------------------------------+
-| Linux >= 3.17 with working               | ``getrandom(GRND_NONBLOCK)`` |
+| Linux >= 3.17 with working               | ``getrandom()``              |
 | ``SYS_getrandom`` syscall                |                              |
 +------------------------------------------+------------------------------+
 | OpenBSD >= 5.6                           | ``getentropy()``             |
diff --git a/docs/hazmat/bindings/index.rst b/docs/hazmat/bindings/index.rst
deleted file mode 100644
index 655f462..0000000
--- a/docs/hazmat/bindings/index.rst
+++ /dev/null
@@ -1,22 +0,0 @@
-.. hazmat::
-
-Bindings
-========
-
-.. module:: cryptography.hazmat.bindings
-
-``cryptography`` aims to provide low-level CFFI based bindings to multiple
-native C libraries. These provide no automatic initialization of the library
-and may not provide complete wrappers for its API.
-
-Using these functions directly is likely to require you to be careful in
-managing memory allocation, locking and other resources.
-
-
-Individual bindings
--------------------
-
-.. toctree::
-    :maxdepth: 1
-
-    openssl
diff --git a/docs/hazmat/bindings/openssl.rst b/docs/hazmat/bindings/openssl.rst
deleted file mode 100644
index ac65aa9..0000000
--- a/docs/hazmat/bindings/openssl.rst
+++ /dev/null
@@ -1,48 +0,0 @@
-.. hazmat::
-
-OpenSSL binding
-===============
-
-.. currentmodule:: cryptography.hazmat.bindings.openssl.binding
-
-These are `CFFI`_ bindings to the `OpenSSL`_ C library. Cryptography supports
-OpenSSL version 1.0.1 and greater.
-
-.. class:: cryptography.hazmat.bindings.openssl.binding.Binding()
-
-    This is the exposed API for the OpenSSL bindings. It has two public
-    attributes:
-
-    .. attribute:: ffi
-
-        This is a ``cffi.FFI`` instance. It can be used to allocate and
-        otherwise manipulate OpenSSL structures.
-
-    .. attribute:: lib
-
-        This is a ``cffi`` library. It can be used to call OpenSSL functions,
-        and access constants.
-
-    .. classmethod:: init_static_locks
-
-        Enables the best available locking callback for OpenSSL.
-        See :ref:`openssl-threading`.
-
-.. _openssl-threading:
-
-Threading
----------
-
-``cryptography`` enables OpenSSLs `thread safety facilities`_ in two different
-ways depending on the configuration of your system. Normally the locking
-callbacks provided by your Python implementation specifically for OpenSSL will
-be used. However, if you have linked ``cryptography`` to a different version of
-OpenSSL than that used by your Python implementation we enable an alternative
-locking callback. This version is implemented in Python and so may result in
-lower performance in some situations. In particular parallelism is reduced
-because it has to acquire the GIL whenever any lock operations occur within
-OpenSSL.
-
-.. _`CFFI`: https://cffi.readthedocs.io
-.. _`OpenSSL`: https://www.openssl.org/
-.. _`thread safety facilities`: https://www.openssl.org/docs/man1.0.2/crypto/threads.html
diff --git a/docs/hazmat/primitives/asymmetric/dh.rst b/docs/hazmat/primitives/asymmetric/dh.rst
index edfe614..6b47da0 100644
--- a/docs/hazmat/primitives/asymmetric/dh.rst
+++ b/docs/hazmat/primitives/asymmetric/dh.rst
@@ -31,13 +31,11 @@
 
 .. code-block:: pycon
 
-    >>> from cryptography.hazmat.backends import default_backend
     >>> from cryptography.hazmat.primitives import hashes
     >>> from cryptography.hazmat.primitives.asymmetric import dh
     >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
     >>> # Generate some parameters. These can be reused.
-    >>> parameters = dh.generate_parameters(generator=2, key_size=2048,
-    ...                                     backend=default_backend())
+    >>> parameters = dh.generate_parameters(generator=2, key_size=2048)
     >>> # Generate a private key for use in the exchange.
     >>> server_private_key = parameters.generate_private_key()
     >>> # In a real handshake the peer is a remote client. For this
@@ -51,7 +49,6 @@
     ...     length=32,
     ...     salt=None,
     ...     info=b'handshake data',
-    ...     backend=default_backend()
     ... ).derive(shared_key)
     >>> # And now we can demonstrate that the handshake performed in the
     >>> # opposite direction gives the same final value
@@ -63,7 +60,6 @@
     ...     length=32,
     ...     salt=None,
     ...     info=b'handshake data',
-    ...     backend=default_backend()
     ... ).derive(same_shared_key)
     >>> derived_key == same_derived_key
 
@@ -75,13 +71,11 @@
 
 .. code-block:: pycon
 
-    >>> from cryptography.hazmat.backends import default_backend
     >>> from cryptography.hazmat.primitives import hashes
     >>> from cryptography.hazmat.primitives.asymmetric import dh
     >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
     >>> # Generate some parameters. These can be reused.
-    >>> parameters = dh.generate_parameters(generator=2, key_size=2048,
-    ...                                     backend=default_backend())
+    >>> parameters = dh.generate_parameters(generator=2, key_size=2048)
     >>> # Generate a private key for use in the exchange.
     >>> private_key = parameters.generate_private_key()
     >>> # In a real handshake the peer_public_key will be received from the
@@ -96,7 +90,6 @@
     ...     length=32,
     ...     salt=None,
     ...     info=b'handshake data',
-    ...     backend=default_backend()
     ... ).derive(shared_key)
     >>> # For the next handshake we MUST generate another private key, but
     >>> # we can reuse the parameters.
@@ -108,7 +101,6 @@
     ...     length=32,
     ...     salt=None,
     ...     info=b'handshake data',
-    ...     backend=default_backend()
     ... ).derive(shared_key_2)
 
 To assemble a :class:`~DHParameters` and a :class:`~DHPublicKey` from
@@ -118,9 +110,9 @@
 peer::
 
     pn = dh.DHParameterNumbers(p, g)
-    parameters = pn.parameters(default_backend())
+    parameters = pn.parameters()
     peer_public_numbers = dh.DHPublicNumbers(y, pn)
-    peer_public_key = peer_public_numbers.public_key(default_backend())
+    peer_public_key = peer_public_numbers.public_key()
 
 
 See also the :class:`~cryptography.hazmat.backends.interfaces.DHBackend`
@@ -129,7 +121,7 @@
 Group parameters
 ~~~~~~~~~~~~~~~~
 
-.. function:: generate_parameters(generator, key_size, backend)
+.. function:: generate_parameters(generator, key_size, backend=None)
 
     .. versionadded:: 1.7
 
@@ -140,7 +132,7 @@
 
     :param key_size: The bit length of the prime modulus to generate.
 
-    :param backend: A
+    :param backend: An optional
         :class:`~cryptography.hazmat.backends.interfaces.DHBackend`
         instance.
 
@@ -349,11 +341,11 @@
 
         p subgroup order value.
 
-    .. method:: parameters(backend)
+    .. method:: parameters(backend=None)
 
         .. versionadded:: 1.7
 
-        :param backend: An instance of
+        :param backend: An optional instance of
             :class:`~cryptography.hazmat.backends.interfaces.DHBackend`.
 
         :returns: A new instance of :class:`DHParameters`.
@@ -377,11 +369,11 @@
 
         The private value.
 
-    .. method:: private_key(backend)
+    .. method:: private_key(backend=None)
 
         .. versionadded:: 1.7
 
-        :param backend: An instance of
+        :param backend: An optional instance of
             :class:`~cryptography.hazmat.backends.interfaces.DHBackend`.
 
         :returns: A new instance of :class:`DHPrivateKey`.
@@ -405,11 +397,11 @@
 
         The public value.
 
-    .. method:: public_key(backend)
+    .. method:: public_key(backend=None)
 
         .. versionadded:: 1.7
 
-        :param backend: An instance of
+        :param backend: An optional instance of
             :class:`~cryptography.hazmat.backends.interfaces.DHBackend`.
 
         :returns: A new instance of :class:`DHPublicKey`.
diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst
index 7b05986..788e427 100644
--- a/docs/hazmat/primitives/asymmetric/dsa.rst
+++ b/docs/hazmat/primitives/asymmetric/dsa.rst
@@ -5,26 +5,36 @@
 
 .. module:: cryptography.hazmat.primitives.asymmetric.dsa
 
+.. note::
+
+    DSA is a **legacy algorithm** and should generally be avoided in favor of
+    choices like
+    :doc:`EdDSA using curve25519</hazmat/primitives/asymmetric/ed25519>` or
+    :doc:`ECDSA</hazmat/primitives/asymmetric/ec>`.
+
 `DSA`_ is a `public-key`_ algorithm for signing messages.
 
 Generation
 ~~~~~~~~~~
 
-.. function:: generate_private_key(key_size, backend)
+.. function:: generate_private_key(key_size, backend=None)
 
     .. versionadded:: 0.5
 
+    .. versionchanged:: 3.0
+
+        Added support for 4096-bit keys for some legacy applications that
+        continue to use DSA despite the wider cryptographic community's
+        `ongoing protestations`_.
+
     Generate a DSA private key from the given key size. This function will
     generate a new set of parameters and key in one step.
 
     :param int key_size: The length of the modulus in :term:`bits`. It should
-        be either 1024, 2048 or 3072. For keys generated in 2015 this should
-        be `at least 2048`_ (See page 41).  Note that some applications
-        (such as SSH) have not yet gained support for larger key sizes
-        specified in FIPS 186-3 and are still restricted to only the
-        1024-bit keys specified in FIPS 186-2.
+        be either 1024, 2048, 3072, or 4096. For keys generated in 2015 this
+        should be `at least 2048`_ (See page 41).
 
-    :param backend: An instance of
+    :param backend: An optional instance of
         :class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
 
     :return: An instance of
@@ -34,20 +44,23 @@
         the provided ``backend`` does not implement
         :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
 
-.. function:: generate_parameters(key_size, backend)
+.. function:: generate_parameters(key_size, backend=None)
 
     .. versionadded:: 0.5
 
+    .. versionchanged:: 3.0
+
+        Added support for 4096-bit keys for some legacy applications that
+        continue to use DSA despite the wider cryptographic community's
+        `ongoing protestations`_.
+
     Generate DSA parameters using the provided ``backend``.
 
     :param int key_size: The length of :attr:`~DSAParameterNumbers.q`. It
-        should be either 1024, 2048 or 3072. For keys generated in 2015 this
-        should be `at least 2048`_ (See page 41).  Note that some applications
-        (such as SSH) have not yet gained support for larger key sizes
-        specified in FIPS 186-3 and are still restricted to only the
-        1024-bit keys specified in FIPS 186-2.
+        should be either 1024, 2048, 3072, or 4096. For keys generated in 2015
+        this should be `at least 2048`_ (See page 41).
 
-    :param backend: An instance of
+    :param backend: An optional instance of
         :class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
 
     :return: An instance of
@@ -65,12 +78,10 @@
 
 .. doctest::
 
-    >>> from cryptography.hazmat.backends import default_backend
     >>> from cryptography.hazmat.primitives import hashes
     >>> from cryptography.hazmat.primitives.asymmetric import dsa
     >>> private_key = dsa.generate_private_key(
     ...     key_size=1024,
-    ...     backend=default_backend()
     ... )
     >>> data = b"this is some data I'd like to sign"
     >>> signature = private_key.sign(
@@ -90,7 +101,7 @@
 
     >>> from cryptography.hazmat.primitives.asymmetric import utils
     >>> chosen_hash = hashes.SHA256()
-    >>> hasher = hashes.Hash(chosen_hash, default_backend())
+    >>> hasher = hashes.Hash(chosen_hash)
     >>> hasher.update(b"data & ")
     >>> hasher.update(b"more data")
     >>> digest = hasher.finalize()
@@ -133,7 +144,7 @@
 .. doctest::
 
     >>> chosen_hash = hashes.SHA256()
-    >>> hasher = hashes.Hash(chosen_hash, default_backend())
+    >>> hasher = hashes.Hash(chosen_hash)
     >>> hasher.update(b"data & ")
     >>> hasher.update(b"more data")
     >>> digest = hasher.finalize()
@@ -170,9 +181,9 @@
 
         The generator.
 
-    .. method:: parameters(backend)
+    .. method:: parameters(backend=None)
 
-        :param backend: An instance of
+        :param backend: An optional instance of
             :class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
 
         :returns: A new instance of
@@ -197,9 +208,9 @@
         The :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameterNumbers`
         associated with the public key.
 
-    .. method:: public_key(backend)
+    .. method:: public_key(backend=None)
 
-        :param backend: An instance of
+        :param backend: An optional instance of
             :class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
 
         :returns: A new instance of
@@ -229,9 +240,9 @@
         The :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicNumbers`
         associated with the private key.
 
-    .. method:: private_key(backend)
+    .. method:: private_key(backend=None)
 
-        :param backend: An instance of
+        :param backend: An optional instance of
             :class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
 
         :returns: A new instance of
@@ -344,7 +355,8 @@
         :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` or
         :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`),
         format (
-        :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.TraditionalOpenSSL`
+        :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.TraditionalOpenSSL`,
+        :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.OpenSSH`
         or
         :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`)
         and encryption algorithm (such as
@@ -445,3 +457,4 @@
 .. _`public-key`: https://en.wikipedia.org/wiki/Public-key_cryptography
 .. _`FIPS 186-4`: https://csrc.nist.gov/publications/detail/fips/186/4/final
 .. _`at least 2048`: https://www.cosic.esat.kuleuven.be/ecrypt/ecrypt2/documents/D.SPA.20.pdf
+.. _`ongoing protestations`: https://buttondown.email/cryptography-dispatches/archive/cryptography-dispatches-dsa-is-past-its-prime/
diff --git a/docs/hazmat/primitives/asymmetric/ec.rst b/docs/hazmat/primitives/asymmetric/ec.rst
index d89fde3..5691560 100644
--- a/docs/hazmat/primitives/asymmetric/ec.rst
+++ b/docs/hazmat/primitives/asymmetric/ec.rst
@@ -6,7 +6,7 @@
 .. module:: cryptography.hazmat.primitives.asymmetric.ec
 
 
-.. function:: generate_private_key(curve, backend)
+.. function:: generate_private_key(curve, backend=None)
 
     .. versionadded:: 0.5
 
@@ -14,13 +14,13 @@
 
     :param curve: An instance of :class:`EllipticCurve`.
 
-    :param backend: An instance of
+    :param backend: An optional instance of
         :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`.
 
     :returns: A new instance of :class:`EllipticCurvePrivateKey`.
 
 
-.. function:: derive_private_key(private_value, curve, backend)
+.. function:: derive_private_key(private_value, curve, backend=None)
 
     .. versionadded:: 1.6
 
@@ -31,7 +31,7 @@
 
     :param curve: An instance of :class:`EllipticCurve`.
 
-    :param backend: An instance of
+    :param backend: An optional instance of
         :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`.
 
     :returns: A new instance of :class:`EllipticCurvePrivateKey`.
@@ -47,16 +47,19 @@
     The ECDSA signature algorithm first standardized in NIST publication
     `FIPS 186-3`_, and later in `FIPS 186-4`_.
 
+    Note that while elliptic curve keys can be used for both signing and key
+    exchange, this is `bad cryptographic practice`_. Instead, users should
+    generate separate signing and ECDH keys.
+
     :param algorithm: An instance of
         :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
 
     .. doctest::
 
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives import hashes
         >>> from cryptography.hazmat.primitives.asymmetric import ec
         >>> private_key = ec.generate_private_key(
-        ...     ec.SECP384R1(), default_backend()
+        ...     ec.SECP384R1()
         ... )
         >>> data = b"this is some data I'd like to sign"
         >>> signature = private_key.sign(
@@ -64,7 +67,7 @@
         ...     ec.ECDSA(hashes.SHA256())
         ... )
 
-    The ``signature`` is a ``bytes`` object, whose contents is DER encoded as
+    The ``signature`` is a ``bytes`` object, whose contents are DER encoded as
     described in :rfc:`3279`. This can be decoded using
     :func:`~cryptography.hazmat.primitives.asymmetric.utils.decode_dss_signature`.
 
@@ -76,7 +79,7 @@
 
         >>> from cryptography.hazmat.primitives.asymmetric import utils
         >>> chosen_hash = hashes.SHA256()
-        >>> hasher = hashes.Hash(chosen_hash, default_backend())
+        >>> hasher = hashes.Hash(chosen_hash)
         >>> hasher.update(b"data & ")
         >>> hasher.update(b"more data")
         >>> digest = hasher.finalize()
@@ -86,13 +89,18 @@
         ... )
 
 
-    Verification requires the public key, the signature itself, the signed
-    data, and knowledge of the hashing algorithm that was used when producing
-    the signature:
+    Verification requires the public key, the DER-encoded signature itself, the
+    signed data, and knowledge of the hashing algorithm that was used when
+    producing the signature:
 
     >>> public_key = private_key.public_key()
     >>> public_key.verify(signature, data, ec.ECDSA(hashes.SHA256()))
 
+    As above, the ``signature`` is a ``bytes`` object whose contents are DER
+    encoded as described in :rfc:`3279`. It can be created from a raw ``(r,s)``
+    pair by using
+    :func:`~cryptography.hazmat.primitives.asymmetric.utils.encode_dss_signature`.
+
     If the signature is not valid, an
     :class:`~cryptography.exceptions.InvalidSignature` exception will be raised.
 
@@ -103,7 +111,7 @@
     .. doctest::
 
         >>> chosen_hash = hashes.SHA256()
-        >>> hasher = hashes.Hash(chosen_hash, default_backend())
+        >>> hasher = hashes.Hash(chosen_hash)
         >>> hasher.update(b"data & ")
         >>> hasher.update(b"more data")
         >>> digest = hasher.finalize()
@@ -139,12 +147,12 @@
 
         The private value.
 
-    .. method:: private_key(backend)
+    .. method:: private_key(backend=None)
 
         Convert a collection of numbers into a private key suitable for doing
         actual cryptographic operations.
 
-        :param backend: An instance of
+        :param backend: An optional instance of
             :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`.
 
         :returns: A new instance of :class:`EllipticCurvePrivateKey`.
@@ -181,12 +189,12 @@
 
         The affine y component of the public point used for verifying.
 
-    .. method:: public_key(backend)
+    .. method:: public_key(backend=None)
 
         Convert a collection of numbers into a public key suitable for doing
         actual cryptographic operations.
 
-        :param backend: An instance of
+        :param backend: An optional instance of
             :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`.
 
         :raises ValueError: Raised if the point is invalid for the curve.
@@ -249,6 +257,10 @@
     key, derivation of multiple keys, and destroys any structure that may be
     present.
 
+    Note that while elliptic curve keys can be used for both signing and key
+    exchange, this is `bad cryptographic practice`_. Instead, users should
+    generate separate signing and ECDH keys.
+
     .. warning::
 
         This example does not give `forward secrecy`_ and is only provided as a
@@ -257,18 +269,17 @@
 
     .. doctest::
 
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives import hashes
         >>> from cryptography.hazmat.primitives.asymmetric import ec
         >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
         >>> # Generate a private key for use in the exchange.
         >>> server_private_key = ec.generate_private_key(
-        ...     ec.SECP384R1(), default_backend()
+        ...     ec.SECP384R1()
         ... )
         >>> # In a real handshake the peer is a remote client. For this
         >>> # example we'll generate another local private key though.
         >>> peer_private_key = ec.generate_private_key(
-        ...     ec.SECP384R1(), default_backend()
+        ...     ec.SECP384R1()
         ... )
         >>> shared_key = server_private_key.exchange(
         ...     ec.ECDH(), peer_private_key.public_key())
@@ -278,7 +289,6 @@
         ...     length=32,
         ...     salt=None,
         ...     info=b'handshake data',
-        ...     backend=default_backend()
         ... ).derive(shared_key)
         >>> # And now we can demonstrate that the handshake performed in the
         >>> # opposite direction gives the same final value
@@ -290,7 +300,6 @@
         ...     length=32,
         ...     salt=None,
         ...     info=b'handshake data',
-        ...     backend=default_backend()
         ... ).derive(same_shared_key)
         >>> derived_key == same_derived_key
         True
@@ -303,19 +312,18 @@
 
     .. doctest::
 
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives import hashes
         >>> from cryptography.hazmat.primitives.asymmetric import ec
         >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
         >>> # Generate a private key for use in the exchange.
         >>> private_key = ec.generate_private_key(
-        ...     ec.SECP384R1(), default_backend()
+        ...     ec.SECP384R1()
         ... )
         >>> # In a real handshake the peer_public_key will be received from the
         >>> # other party. For this example we'll generate another private key
         >>> # and get a public key from that.
         >>> peer_public_key = ec.generate_private_key(
-        ...     ec.SECP384R1(), default_backend()
+        ...     ec.SECP384R1()
         ... ).public_key()
         >>> shared_key = private_key.exchange(ec.ECDH(), peer_public_key)
         >>> # Perform key derivation.
@@ -324,14 +332,13 @@
         ...     length=32,
         ...     salt=None,
         ...     info=b'handshake data',
-        ...     backend=default_backend()
         ... ).derive(shared_key)
         >>> # For the next handshake we MUST generate another private key.
         >>> private_key_2 = ec.generate_private_key(
-        ...     ec.SECP384R1(), default_backend()
+        ...     ec.SECP384R1()
         ... )
         >>> peer_public_key_2 = ec.generate_private_key(
-        ...     ec.SECP384R1(), default_backend()
+        ...     ec.SECP384R1()
         ... ).public_key()
         >>> shared_key_2 = private_key_2.exchange(ec.ECDH(), peer_public_key_2)
         >>> derived_key_2 = HKDF(
@@ -339,7 +346,6 @@
         ...     length=32,
         ...     salt=None,
         ...     info=b'handshake data',
-        ...     backend=default_backend()
         ... ).derive(shared_key_2)
 
 Elliptic Curves
@@ -601,7 +607,16 @@
         :param signature_algorithm: An instance of
             :class:`EllipticCurveSignatureAlgorithm`, such as :class:`ECDSA`.
 
-        :return bytes: Signature.
+        :return bytes: The signature as a ``bytes`` object, whose contents are
+            DER encoded as described in :rfc:`3279`. This can be decoded using
+            :func:`~cryptography.hazmat.primitives.asymmetric.utils.decode_dss_signature`,
+            which returns the decoded tuple ``(r, s)``.
+
+    .. attribute:: curve
+
+        :type: :class:`EllipticCurve`
+
+        The EllipticCurve that this key is on.
 
     .. attribute:: key_size
 
@@ -633,7 +648,8 @@
         :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` or
         :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`),
         format (
-        :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.TraditionalOpenSSL`
+        :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.TraditionalOpenSSL`,
+        :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.OpenSSH`
         or
         :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`)
         and encryption algorithm (such as
@@ -704,7 +720,10 @@
         Verify one block of data was signed by the private key associated
         with this public key.
 
-        :param bytes signature: The signature to verify.
+        :param bytes signature: The DER-encoded signature to verify.
+            A raw signature may be DER-encoded by splitting it into the ``r``
+            and ``s`` components and passing them into
+            :func:`~cryptography.hazmat.primitives.asymmetric.utils.encode_dss_signature`.
 
         :param bytes data: The message string that was signed.
 
@@ -761,12 +780,10 @@
 
 .. doctest::
 
-    >>> from cryptography.hazmat.backends import default_backend
-    >>> from cryptography.hazmat.primitives import hashes
-    >>> from cryptography.hazmat.primitives.asymmetric import ec
     >>> from cryptography.hazmat.primitives import serialization
+    >>> from cryptography.hazmat.primitives.asymmetric import ec
 
-    >>> private_key = ec.generate_private_key(ec.SECP384R1(), default_backend())
+    >>> private_key = ec.generate_private_key(ec.SECP384R1())
 
     >>> serialized_private = private_key.private_bytes(
     ...     encoding=serialization.Encoding.PEM,
@@ -806,14 +823,12 @@
 
     >>> loaded_public_key = serialization.load_pem_public_key(
     ...     serialized_public,
-    ...     backend=default_backend()
     ... )
 
     >>> loaded_private_key = serialization.load_pem_private_key(
     ...     serialized_private,
     ...     # or password=None, if in plain text
     ...     password=b'testpassword',
-    ...     backend=default_backend()
     ... )
 
 
@@ -926,6 +941,21 @@
 
         Corresponds to the dotted string ``"1.3.132.0.39"``.
 
+.. function:: get_curve_for_oid(oid)
+
+    .. versionadded:: 2.6
+
+    A function that takes an :class:`~cryptography.x509.ObjectIdentifier`
+    and returns the associated elliptic curve class.
+
+    :param oid: An instance of
+        :class:`~cryptography.x509.ObjectIdentifier`.
+
+    :returns: The matching elliptic curve class. The returned class conforms
+        to the :class:`EllipticCurve` interface.
+
+    :raises LookupError: Raised if no elliptic curve is found that matches
+        the provided object identifier.
 
 .. _`FIPS 186-3`: https://csrc.nist.gov/csrc/media/publications/fips/186/3/archive/2009-06-25/documents/fips_186-3.pdf
 .. _`FIPS 186-4`: https://csrc.nist.gov/publications/detail/fips/186/4/final
@@ -939,4 +969,5 @@
 .. _`ECDSA`: https://en.wikipedia.org/wiki/ECDSA
 .. _`EdDSA`: https://en.wikipedia.org/wiki/EdDSA
 .. _`forward secrecy`: https://en.wikipedia.org/wiki/Forward_secrecy
-.. _`SEC 1 v2.0`: http://www.secg.org/sec1-v2.pdf
+.. _`SEC 1 v2.0`: https://www.secg.org/sec1-v2.pdf
+.. _`bad cryptographic practice`: https://crypto.stackexchange.com/a/3313
diff --git a/docs/hazmat/primitives/asymmetric/ed25519.rst b/docs/hazmat/primitives/asymmetric/ed25519.rst
new file mode 100644
index 0000000..47d95ec
--- /dev/null
+++ b/docs/hazmat/primitives/asymmetric/ed25519.rst
@@ -0,0 +1,168 @@
+.. hazmat::
+
+Ed25519 signing
+===============
+
+.. currentmodule:: cryptography.hazmat.primitives.asymmetric.ed25519
+
+
+Ed25519 is an elliptic curve signing algorithm using `EdDSA`_ and
+`Curve25519`_. If you do not have legacy interoperability concerns then you
+should strongly consider using this signature algorithm.
+
+
+Signing & Verification
+~~~~~~~~~~~~~~~~~~~~~~
+
+.. doctest::
+
+    >>> from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
+    >>> private_key = Ed25519PrivateKey.generate()
+    >>> signature = private_key.sign(b"my authenticated message")
+    >>> public_key = private_key.public_key()
+    >>> # Raises InvalidSignature if verification fails
+    >>> public_key.verify(signature, b"my authenticated message")
+
+Key interfaces
+~~~~~~~~~~~~~~
+
+.. class:: Ed25519PrivateKey
+
+    .. versionadded:: 2.6
+
+    .. classmethod:: generate()
+
+        Generate an Ed25519 private key.
+
+        :returns: :class:`Ed25519PrivateKey`
+
+    .. classmethod:: from_private_bytes(data)
+
+        :param data: 32 byte private key.
+        :type data: :term:`bytes-like`
+
+        :returns: :class:`Ed25519PrivateKey`
+
+        .. doctest::
+
+            >>> from cryptography.hazmat.primitives import serialization
+            >>> from cryptography.hazmat.primitives.asymmetric import ed25519
+            >>> private_key = ed25519.Ed25519PrivateKey.generate()
+            >>> private_bytes = private_key.private_bytes(
+            ...     encoding=serialization.Encoding.Raw,
+            ...     format=serialization.PrivateFormat.Raw,
+            ...     encryption_algorithm=serialization.NoEncryption()
+            ... )
+            >>> loaded_private_key = ed25519.Ed25519PrivateKey.from_private_bytes(private_bytes)
+
+
+    .. method:: public_key()
+
+        :returns: :class:`Ed25519PublicKey`
+
+    .. method:: sign(data)
+
+        :param bytes data: The data to sign.
+
+        :returns bytes: The 64 byte signature.
+
+    .. method:: private_bytes(encoding, format, encryption_algorithm)
+
+        Allows serialization of the key to bytes. Encoding (
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`, or
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
+        format (
+        :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`,
+        :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.OpenSSH`
+        or
+        :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
+        ) are chosen to define the exact serialization.
+
+        :param encoding: A value from the
+            :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+        :param format: A value from the
+            :class:`~cryptography.hazmat.primitives.serialization.PrivateFormat`
+            enum. If the ``encoding`` is
+            :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
+            then ``format`` must be
+            :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
+            , otherwise it must be
+            :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8` or
+            :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.OpenSSH`.
+
+        :param encryption_algorithm: An instance of an object conforming to the
+            :class:`~cryptography.hazmat.primitives.serialization.KeySerializationEncryption`
+            interface.
+
+        :return bytes: Serialized key.
+
+.. class:: Ed25519PublicKey
+
+    .. versionadded:: 2.6
+
+    .. classmethod:: from_public_bytes(data)
+
+        :param bytes data: 32 byte public key.
+
+        :returns: :class:`Ed25519PublicKey`
+
+        .. doctest::
+
+            >>> from cryptography.hazmat.primitives import serialization
+            >>> from cryptography.hazmat.primitives.asymmetric import ed25519
+            >>> private_key = ed25519.Ed25519PrivateKey.generate()
+            >>> public_key = private_key.public_key()
+            >>> public_bytes = public_key.public_bytes(
+            ...     encoding=serialization.Encoding.Raw,
+            ...     format=serialization.PublicFormat.Raw
+            ... )
+            >>> loaded_public_key = ed25519.Ed25519PublicKey.from_public_bytes(public_bytes)
+
+    .. method:: public_bytes(encoding, format)
+
+        Allows serialization of the key to bytes. Encoding (
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`,
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.OpenSSH`,
+        or
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
+        format (
+        :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`,
+        :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.OpenSSH`
+        , or
+        :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`
+        ) are chosen to define the exact serialization.
+
+        :param encoding: A value from the
+            :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+        :param format: A value from the
+            :class:`~cryptography.hazmat.primitives.serialization.PublicFormat`
+            enum. If the ``encoding`` is
+            :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
+            then ``format`` must be
+            :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`.
+            If ``encoding`` is
+            :attr:`~cryptography.hazmat.primitives.serialization.Encoding.OpenSSH`
+            then ``format`` must be
+            :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.OpenSSH`.
+            In all other cases ``format`` must be
+            :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`.
+
+        :returns bytes: The public key bytes.
+
+    .. method:: verify(signature, data)
+
+        :param bytes signature: The signature to verify.
+
+        :param bytes data: The data to verify.
+
+        :raises cryptography.exceptions.InvalidSignature: Raised when the
+            signature cannot be verified.
+
+
+
+.. _`EdDSA`: https://en.wikipedia.org/wiki/EdDSA
+.. _`Curve25519`: https://en.wikipedia.org/wiki/Curve25519
diff --git a/docs/hazmat/primitives/asymmetric/ed448.rst b/docs/hazmat/primitives/asymmetric/ed448.rst
new file mode 100644
index 0000000..fb79dcb
--- /dev/null
+++ b/docs/hazmat/primitives/asymmetric/ed448.rst
@@ -0,0 +1,131 @@
+.. hazmat::
+
+Ed448 signing
+=============
+
+.. currentmodule:: cryptography.hazmat.primitives.asymmetric.ed448
+
+
+Ed448 is an elliptic curve signing algorithm using `EdDSA`_.
+
+
+Signing & Verification
+~~~~~~~~~~~~~~~~~~~~~~
+
+.. doctest::
+
+    >>> from cryptography.hazmat.primitives.asymmetric.ed448 import Ed448PrivateKey
+    >>> private_key = Ed448PrivateKey.generate()
+    >>> signature = private_key.sign(b"my authenticated message")
+    >>> public_key = private_key.public_key()
+    >>> # Raises InvalidSignature if verification fails
+    >>> public_key.verify(signature, b"my authenticated message")
+
+Key interfaces
+~~~~~~~~~~~~~~
+
+.. class:: Ed448PrivateKey
+
+    .. versionadded:: 2.6
+
+    .. classmethod:: generate()
+
+        Generate an Ed448 private key.
+
+        :returns: :class:`Ed448PrivateKey`
+
+    .. classmethod:: from_private_bytes(data)
+
+        :param data: 57 byte private key.
+        :type data: :term:`bytes-like`
+
+        :returns: :class:`Ed448PrivateKey`
+
+    .. method:: public_key()
+
+        :returns: :class:`Ed448PublicKey`
+
+    .. method:: sign(data)
+
+        :param bytes data: The data to sign.
+
+        :returns bytes: The 114 byte signature.
+
+    .. method:: private_bytes(encoding, format, encryption_algorithm)
+
+        Allows serialization of the key to bytes. Encoding (
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`, or
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
+        format (
+        :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`
+        or
+        :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
+        ) are chosen to define the exact serialization.
+
+        :param encoding: A value from the
+            :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+        :param format: A value from the
+            :class:`~cryptography.hazmat.primitives.serialization.PrivateFormat`
+            enum. If the ``encoding`` is
+            :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
+            then ``format`` must be
+            :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
+            , otherwise it must be
+            :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`.
+
+        :param encryption_algorithm: An instance of an object conforming to the
+            :class:`~cryptography.hazmat.primitives.serialization.KeySerializationEncryption`
+            interface.
+
+        :return bytes: Serialized key.
+
+.. class:: Ed448PublicKey
+
+    .. versionadded:: 2.6
+
+    .. classmethod:: from_public_bytes(data)
+
+        :param bytes data: 57 byte public key.
+
+        :returns: :class:`Ed448PublicKey`
+
+    .. method:: public_bytes(encoding, format)
+
+        Allows serialization of the key to bytes. Encoding (
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`, or
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
+        format (
+        :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`
+        or
+        :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`
+        ) are chosen to define the exact serialization.
+
+        :param encoding: A value from the
+            :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+        :param format: A value from the
+            :class:`~cryptography.hazmat.primitives.serialization.PublicFormat`
+            enum. If the ``encoding`` is
+            :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
+            then ``format`` must be
+            :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`
+            , otherwise it must be
+            :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`.
+
+        :returns bytes: The public key bytes.
+
+    .. method:: verify(signature, data)
+
+        :param bytes signature: The signature to verify.
+
+        :param bytes data: The data to verify.
+
+        :raises cryptography.exceptions.InvalidSignature: Raised when the
+            signature cannot be verified.
+
+
+
+.. _`EdDSA`: https://en.wikipedia.org/wiki/EdDSA
diff --git a/docs/hazmat/primitives/asymmetric/index.rst b/docs/hazmat/primitives/asymmetric/index.rst
index 1561c59..c27e178 100644
--- a/docs/hazmat/primitives/asymmetric/index.rst
+++ b/docs/hazmat/primitives/asymmetric/index.rst
@@ -23,7 +23,9 @@
 .. toctree::
     :maxdepth: 1
 
+    ed25519
     x25519
+    ed448
     x448
     ec
     rsa
diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst
index dab9096..33f402b 100644
--- a/docs/hazmat/primitives/asymmetric/rsa.rst
+++ b/docs/hazmat/primitives/asymmetric/rsa.rst
@@ -14,10 +14,14 @@
 of bytes, RSA keys have a complex internal structure with `specific
 mathematical properties`_.
 
-.. function:: generate_private_key(public_exponent, key_size, backend)
+.. function:: generate_private_key(public_exponent, key_size, backend=None)
 
     .. versionadded:: 0.5
 
+    .. versionchanged:: 3.0
+
+        Tightened restrictions on ``public_exponent``.
+
     Generates a new RSA private key using the provided ``backend``.
     ``key_size`` describes how many :term:`bits` long the key should be. Larger
     keys provide more security; currently ``1024`` and below are considered
@@ -28,24 +32,22 @@
 
     .. doctest::
 
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives.asymmetric import rsa
         >>> private_key = rsa.generate_private_key(
         ...     public_exponent=65537,
         ...     key_size=2048,
-        ...     backend=default_backend()
         ... )
 
     :param int public_exponent: The public exponent of the new key.
-        Usually one of the small Fermat primes 3, 5, 17, 257, 65537. If in
-        doubt you should `use 65537`_.
+        Either 65537 or 3 (for legacy purposes). Almost everyone should
+        `use 65537`_.
 
     :param int key_size: The length of the modulus in :term:`bits`. For keys
         generated in 2015 it is strongly recommended to be
         `at least 2048`_ (See page 41). It must not be less than 512.
         Some backends may have additional limitations.
 
-    :param backend: A backend which implements
+    :param backend: An optional backend which implements
         :class:`~cryptography.hazmat.backends.interfaces.RSABackend`.
 
     :return: An instance of
@@ -64,14 +66,12 @@
 
 .. code-block:: pycon
 
-    >>> from cryptography.hazmat.backends import default_backend
     >>> from cryptography.hazmat.primitives import serialization
 
     >>> with open("path/to/key.pem", "rb") as key_file:
     ...     private_key = serialization.load_pem_private_key(
     ...         key_file.read(),
     ...         password=None,
-    ...         backend=default_backend()
     ...     )
 
 Serialized keys may optionally be encrypted on disk using a password. In this
@@ -167,7 +167,7 @@
 
     >>> from cryptography.hazmat.primitives.asymmetric import utils
     >>> chosen_hash = hashes.SHA256()
-    >>> hasher = hashes.Hash(chosen_hash, default_backend())
+    >>> hasher = hashes.Hash(chosen_hash)
     >>> hasher.update(b"data & ")
     >>> hasher.update(b"more data")
     >>> digest = hasher.finalize()
@@ -217,7 +217,7 @@
 .. doctest::
 
     >>> chosen_hash = hashes.SHA256()
-    >>> hasher = hashes.Hash(chosen_hash, default_backend())
+    >>> hasher = hashes.Hash(chosen_hash)
     >>> hasher.update(b"data & ")
     >>> hasher.update(b"more data")
     >>> digest = hasher.finalize()
@@ -342,6 +342,11 @@
     :class:`OAEP` should be preferred for encryption and :class:`PSS` should be
     preferred for signatures.
 
+    .. warning::
+
+        Our implementation of PKCS1 v1.5 decryption is not constant time. See
+        :doc:`/limitations` for details.
+
 
 .. function:: calculate_max_pss_salt_length(key, hash_algorithm)
 
@@ -399,9 +404,9 @@
 
         The public exponent.
 
-    .. method:: public_key(backend)
+    .. method:: public_key(backend=None)
 
-        :param backend: An instance of
+        :param backend: An optional instance of
             :class:`~cryptography.hazmat.backends.interfaces.RSABackend`.
 
         :returns: A new instance of
@@ -466,9 +471,9 @@
         A `Chinese remainder theorem`_ coefficient used to speed up RSA
         operations. Calculated as: q\ :sup:`-1` mod p
 
-    .. method:: private_key(backend)
+    .. method:: private_key(backend=None)
 
-        :param backend: A new instance of
+        :param backend: An optional instance of
             :class:`~cryptography.hazmat.backends.interfaces.RSABackend`.
 
         :returns: An instance of
@@ -607,7 +612,8 @@
         :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` or
         :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`),
         format (
-        :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.TraditionalOpenSSL`
+        :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.TraditionalOpenSSL`,
+        :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.OpenSSH`
         or
         :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`)
         and encryption algorithm (such as
@@ -708,6 +714,55 @@
         :raises cryptography.exceptions.InvalidSignature: If the signature does
             not validate.
 
+    .. method:: recover_data_from_signature(signature, padding, algorithm)
+
+        .. versionadded:: 3.3
+
+        Recovers the signed data from the signature. The data 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.
+
+        The ``algorithm`` parameter can also be set to ``None`` to recover all
+        the data present in the signature, without regard to its format or the
+        hash algorithm used for its creation.
+
+        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.
+
+        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:
+
+        - 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).
+
+        :param bytes signature: The signature.
+
+        :param padding: An instance of
+            :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`.
+            Recovery is only supported with some of the padding types. (Currently
+            only with
+            :class:`~cryptography.hazmat.primitives.asymmetric.padding.PKCS1v15`).
+
+        :param algorithm: An instance of
+            :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
+            Can be ``None`` to return the all the data present in the signature.
+
+        :return bytes: The signed data.
+
+        :raises cryptography.exceptions.InvalidSignature: If the signature is
+            invalid.
+
+        :raises cryptography.exceptions.UnsupportedAlgorithm: If signature
+            data recovery is not supported with the provided ``padding`` type.
 
 .. class:: RSAPublicKeyWithSerialization
 
diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst
index dbb2bb6..2324340 100644
--- a/docs/hazmat/primitives/asymmetric/serialization.rst
+++ b/docs/hazmat/primitives/asymmetric/serialization.rst
@@ -88,10 +88,9 @@
 
     .. doctest::
 
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives.asymmetric import dsa, rsa
         >>> from cryptography.hazmat.primitives.serialization import load_pem_private_key
-        >>> key = load_pem_private_key(pem_data, password=None, backend=default_backend())
+        >>> key = load_pem_private_key(pem_data, password=None)
         >>> if isinstance(key, rsa.RSAPrivateKey):
         ...     signature = sign_with_rsa_key(key, message)
         ... elif isinstance(key, dsa.DSAPrivateKey):
@@ -126,7 +125,7 @@
     extract the public key with
     :meth:`Certificate.public_key <cryptography.x509.Certificate.public_key>`.
 
-.. function:: load_pem_private_key(data, password, backend)
+.. function:: load_pem_private_key(data, password, backend=None)
 
     .. versionadded:: 0.6
 
@@ -140,7 +139,7 @@
         be ``None`` if the private key is not encrypted.
     :type data: :term:`bytes-like`
 
-    :param backend: An instance of
+    :param backend: An optional instance of
         :class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`.
 
     :returns: One of
@@ -159,10 +158,9 @@
         password was supplied.
 
     :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized key
-        is of a type that is not supported by the backend or if the key is
-        encrypted with a symmetric cipher that is not supported by the backend.
+        is of a type that is not supported by the backend.
 
-.. function:: load_pem_public_key(data, backend)
+.. function:: load_pem_public_key(data, backend=None)
 
     .. versionadded:: 0.6
 
@@ -173,13 +171,13 @@
     .. doctest::
 
         >>> from cryptography.hazmat.primitives.serialization import load_pem_public_key
-        >>> key = load_pem_public_key(public_pem_data, backend=default_backend())
+        >>> key = load_pem_public_key(public_pem_data)
         >>> isinstance(key, rsa.RSAPublicKey)
         True
 
     :param bytes data: The PEM encoded key data.
 
-    :param backend: An instance of
+    :param backend: An optional instance of
         :class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`.
 
 
@@ -197,7 +195,7 @@
     :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized key
         is of a type that is not supported by the backend.
 
-.. function:: load_pem_parameters(data, backend)
+.. function:: load_pem_parameters(data, backend=None)
 
     .. versionadded:: 2.0
 
@@ -208,13 +206,13 @@
 
         >>> from cryptography.hazmat.primitives.serialization import load_pem_parameters
         >>> from cryptography.hazmat.primitives.asymmetric import dh
-        >>> parameters = load_pem_parameters(parameters_pem_data, backend=default_backend())
+        >>> parameters = load_pem_parameters(parameters_pem_data)
         >>> isinstance(parameters, dh.DHParameters)
         True
 
     :param bytes data: The PEM encoded parameters data.
 
-    :param backend: An instance of
+    :param backend: An optional instance of
         :class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`.
 
 
@@ -236,7 +234,7 @@
 know whether it is a public or private key the loading functions will handle
 the rest.
 
-.. function:: load_der_private_key(data, password, backend)
+.. function:: load_der_private_key(data, password, backend=None)
 
     .. versionadded:: 0.8
 
@@ -250,7 +248,7 @@
         be ``None`` if the private key is not encrypted.
     :type password: :term:`bytes-like`
 
-    :param backend: An instance of
+    :param backend: An optional instance of
         :class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`.
 
     :returns: One of
@@ -268,20 +266,18 @@
         not encrypted. Or if the key was encrypted but no
         password was supplied.
 
-    :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized key is of a type that
-        is not supported by the backend or if the key is encrypted with a
-        symmetric cipher that is not supported by the backend.
+    :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized key
+        is of a type that is not supported by the backend.
 
     .. doctest::
 
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives.asymmetric import rsa
         >>> from cryptography.hazmat.primitives.serialization import load_der_private_key
-        >>> key = load_der_private_key(der_data, password=None, backend=default_backend())
+        >>> key = load_der_private_key(der_data, password=None)
         >>> isinstance(key, rsa.RSAPrivateKey)
         True
 
-.. function:: load_der_public_key(data, backend)
+.. function:: load_der_public_key(data, backend=None)
 
     .. versionadded:: 0.8
 
@@ -291,7 +287,7 @@
 
     :param bytes data: The DER encoded key data.
 
-    :param backend: An instance of
+    :param backend: An optional instance of
         :class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`.
 
     :returns: One of
@@ -310,14 +306,13 @@
 
     .. doctest::
 
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives.asymmetric import rsa
         >>> from cryptography.hazmat.primitives.serialization import load_der_public_key
-        >>> key = load_der_public_key(public_der_data, backend=default_backend())
+        >>> key = load_der_public_key(public_der_data)
         >>> isinstance(key, rsa.RSAPublicKey)
         True
 
-.. function:: load_der_parameters(data, backend)
+.. function:: load_der_parameters(data, backend=None)
 
     .. versionadded:: 2.0
 
@@ -326,7 +321,7 @@
 
     :param bytes data: The DER encoded parameters data.
 
-    :param backend: An instance of
+    :param backend: An optional instance of
         :class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`.
 
     :returns: Currently only
@@ -341,10 +336,9 @@
 
     .. doctest::
 
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives.asymmetric import dh
         >>> from cryptography.hazmat.primitives.serialization import load_der_parameters
-        >>> parameters = load_der_parameters(parameters_der_data, backend=default_backend())
+        >>> parameters = load_der_parameters(parameters_der_data)
         >>> isinstance(parameters, dh.DHParameters)
         True
 
@@ -369,20 +363,18 @@
 ``ssh-rsa``. ECDSA keys have a slightly different format, they begin with
 ``ecdsa-sha2-{curve}``.
 
-.. function:: load_ssh_public_key(data, backend)
+.. function:: load_ssh_public_key(data, backend=None)
 
     .. versionadded:: 0.7
 
-    Deserialize a public key from OpenSSH (:rfc:`4253`) encoded data to an
+    Deserialize a public key from OpenSSH (:rfc:`4253` and
+    `PROTOCOL.certkeys`_) encoded data to an
     instance of the public key type for the specified backend.
 
-    .. note::
+    :param data: The OpenSSH encoded key data.
+    :type data: :term:`bytes-like`
 
-        Currently Ed25519 keys are not supported.
-
-    :param bytes data: The OpenSSH encoded key data.
-
-    :param backend: A backend which implements
+    :param backend: An optional backend which implements
         :class:`~cryptography.hazmat.backends.interfaces.RSABackend`,
         :class:`~cryptography.hazmat.backends.interfaces.DSABackend`, or
         :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`
@@ -391,8 +383,9 @@
     :returns: One of
         :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
         :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
-        or
         :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
+        , or
+        :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey`,
         depending on the contents of ``data``.
 
     :raises ValueError: If the OpenSSH data could not be properly decoded or
@@ -401,6 +394,58 @@
     :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized
         key is of a type that is not supported.
 
+OpenSSH Private Key
+~~~~~~~~~~~~~~~~~~~
+
+The format used by OpenSSH to store private keys, as approximately specified
+in `PROTOCOL.key`_.
+
+An example ECDSA key in OpenSSH format::
+
+    -----BEGIN OPENSSH PRIVATE KEY-----
+    b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
+    1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQRI0fWnI1CxX7qYqp0ih6bxjhGmUrZK
+    /Axf8vhM8Db3oH7CFR+JdL715lUdu4XCWvQZKVf60/h3kBFhuxQC23XjAAAAqKPzVaOj81
+    WjAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEjR9acjULFfupiq
+    nSKHpvGOEaZStkr8DF/y+EzwNvegfsIVH4l0vvXmVR27hcJa9BkpV/rT+HeQEWG7FALbde
+    MAAAAga/VGV2asRlL3kXXao0aochQ59nXHA2xEGeAoQd952r0AAAAJbWFya29AdmZmAQID
+    BAUGBw==
+    -----END OPENSSH PRIVATE KEY-----
+
+.. function:: load_ssh_private_key(data, password, backend=None)
+
+    .. versionadded:: 3.0
+
+    Deserialize a private key from OpenSSH encoded data to an
+    instance of the private key type for the specified backend.
+
+    :param data: The PEM encoded OpenSSH private key data.
+    :type data: :term:`bytes-like`
+
+    :param bytes password: Password bytes to use to decrypt
+        password-protected key. Or ``None`` if not needed.
+
+    :param backend: An optional backend which implements
+        :class:`~cryptography.hazmat.backends.interfaces.RSABackend`,
+        :class:`~cryptography.hazmat.backends.interfaces.DSABackend`, or
+        :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`
+        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`
+        or
+        :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey`,
+        depending on the contents of ``data``.
+
+    :raises ValueError: If the OpenSSH data could not be properly decoded,
+        if the key is not in the proper format or the incorrect password
+        was provided.
+
+    :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized
+        key is of a type that is not supported.
+
 PKCS12
 ~~~~~~
 
@@ -415,7 +460,7 @@
     ``cryptography`` only supports a single private key and associated
     certificates when parsing PKCS12 files at this time.
 
-.. function:: load_key_and_certificates(data, password, backend)
+.. function:: load_key_and_certificates(data, password, backend=None)
 
     .. versionadded:: 2.5
 
@@ -428,7 +473,7 @@
         if the PKCS12 is not encrypted.
     :type password: :term:`bytes-like`
 
-    :param backend: A backend instance.
+    :param backend: An optional backend instance.
 
     :returns: A tuple of
         ``(private_key, certificate, additional_certificates)``.
@@ -438,6 +483,240 @@
         ``additional_certificates`` is a list of all other
         :class:`~cryptography.x509.Certificate` instances in the PKCS12 object.
 
+.. function:: serialize_key_and_certificates(name, key, cert, cas, encryption_algorithm)
+
+    .. versionadded:: 3.0
+
+    .. warning::
+
+        PKCS12 encryption is not secure and should not be used as a security
+        mechanism. Wrap a PKCS12 blob in a more secure envelope if you need
+        to store or send it safely. Encryption is provided for compatibility
+        reasons only.
+
+    Serialize a PKCS12 blob.
+
+    .. note::
+
+        Due to `a bug in Firefox`_ it's not possible to load unencrypted PKCS12
+        blobs in Firefox.
+
+    :param name: The friendly name to use for the supplied certificate and key.
+    :type name: bytes
+
+    :param key: The private key to include in the structure.
+    :type key: An
+        :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization`
+        ,
+        :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization`
+        , or
+        :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKeyWithSerialization`
+        object.
+
+    :param cert: The certificate associated with the private key.
+    :type cert: :class:`~cryptography.x509.Certificate` or ``None``
+
+    :param cas: An optional set of certificates to also include in the structure.
+    :type cas: list of :class:`~cryptography.x509.Certificate` or ``None``
+
+    :param encryption_algorithm: The encryption algorithm that should be used
+        for the key and certificate. An instance of an object conforming to the
+        :class:`~cryptography.hazmat.primitives.serialization.KeySerializationEncryption`
+        interface. PKCS12 encryption is **very weak** and should not be used
+        as a security boundary.
+
+    :return bytes: Serialized PKCS12.
+
+PKCS7
+~~~~~
+
+.. currentmodule:: cryptography.hazmat.primitives.serialization.pkcs7
+
+PKCS7 is a format described in :rfc:`2315`, among other specifications. It can
+contain certificates, CRLs, and much more. PKCS7 files commonly have a ``p7b``,
+``p7m``, or ``p7s`` file suffix but other suffixes are also seen in the wild.
+
+.. note::
+
+    ``cryptography`` only supports parsing certificates from PKCS7 files at
+    this time.
+
+.. function:: load_pem_pkcs7_certificates(data)
+
+    .. versionadded:: 3.1
+
+    Deserialize a PEM encoded PKCS7 blob to a list of certificates. PKCS7 can
+    contain many other types of data, including CRLs, but this function will
+    ignore everything except certificates.
+
+    :param data: The data.
+    :type data: bytes
+
+    :returns: A list of :class:`~cryptography.x509.Certificate`.
+
+    :raises ValueError: If the PKCS7 data could not be loaded.
+
+    :raises cryptography.exceptions.UnsupportedAlgorithm: If the PKCS7 data
+        is of a type that is not supported.
+
+.. function:: load_der_pkcs7_certificates(data)
+
+    .. versionadded:: 3.1
+
+    Deserialize a DER encoded PKCS7 blob to a list of certificates. PKCS7 can
+    contain many other types of data, including CRLs, but this function will
+    ignore everything except certificates.
+
+    :param data: The data.
+    :type data: bytes
+
+    :returns: A list of :class:`~cryptography.x509.Certificate`.
+
+    :raises ValueError: If the PKCS7 data could not be loaded.
+
+    :raises cryptography.exceptions.UnsupportedAlgorithm: If the PKCS7 data
+        is of a type that is not supported.
+
+.. testsetup::
+
+    ca_key = b"""
+    -----BEGIN PRIVATE KEY-----
+    MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgA8Zqz5vLeR0ePZUe
+    jBfdyMmnnI4U5uAJApWTsMn/RuWhRANCAAQY/8+7+Tm49d3D7sBAiwZ1BqtPzdgs
+    UiROH+AQRme1XxW5Yr07zwxvvhr3tKEPtLnLboazUPlsUb/Bgte+xfkF
+    -----END PRIVATE KEY-----
+    """.strip()
+
+    ca_cert = b"""
+    -----BEGIN CERTIFICATE-----
+    MIIBUTCB96ADAgECAgIDCTAKBggqhkjOPQQDAjAnMQswCQYDVQQGEwJVUzEYMBYG
+    A1UEAwwPY3J5cHRvZ3JhcGh5IENBMB4XDTE3MDEwMTEyMDEwMFoXDTM4MTIzMTA4
+    MzAwMFowJzELMAkGA1UEBhMCVVMxGDAWBgNVBAMMD2NyeXB0b2dyYXBoeSBDQTBZ
+    MBMGByqGSM49AgEGCCqGSM49AwEHA0IABBj/z7v5Obj13cPuwECLBnUGq0/N2CxS
+    JE4f4BBGZ7VfFblivTvPDG++Gve0oQ+0uctuhrNQ+WxRv8GC177F+QWjEzARMA8G
+    A1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSQAwRgIhANES742XWm64tkGnz8Dn
+    pG6u2lHkZFQr3oaVvPcemvlbAiEA0WGGzmYx5C9UvfXIK7NEziT4pQtyESE0uRVK
+    Xw4nMqk=
+    -----END CERTIFICATE-----
+    """.strip()
+
+
+.. class:: PKCS7SignatureBuilder
+
+    The PKCS7 signature builder can create both basic PKCS7 signed messages as
+    well as S/MIME messages, which are commonly used in email. S/MIME has
+    multiple versions, but this implements a subset of :rfc:`2632`, also known
+    as S/MIME Version 3.
+
+    .. versionadded:: 3.2
+
+    .. doctest::
+
+        >>> from cryptography import x509
+        >>> from cryptography.hazmat.primitives import hashes, serialization
+        >>> from cryptography.hazmat.primitives.serialization import pkcs7
+        >>> cert = x509.load_pem_x509_certificate(ca_cert)
+        >>> key = serialization.load_pem_private_key(ca_key, None)
+        >>> options = [pkcs7.PKCS7Options.DetachedSignature]
+        >>> pkcs7.PKCS7SignatureBuilder().set_data(
+        ...     b"data to sign"
+        ... ).add_signer(
+        ...     cert, key, hashes.SHA256()
+        ... ).sign(
+        ...     serialization.Encoding.SMIME, options
+        ... )
+        b'...'
+
+    .. method:: set_data(data)
+
+        :param data: The data to be hashed and signed.
+        :type data: :term:`bytes-like`
+
+    .. method:: add_signer(certificate, private_key, hash_algorithm)
+
+        :param certificate: The :class:`~cryptography.x509.Certificate`.
+
+        :param private_key: The
+            :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey` or
+            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`
+            associated with the certificate provided.
+
+        :param hash_algorithm: The
+            :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` that
+            will be used to generate the signature. This must be an instance of
+            :class:`~cryptography.hazmat.primitives.hashes.SHA1`,
+            :class:`~cryptography.hazmat.primitives.hashes.SHA224`,
+            :class:`~cryptography.hazmat.primitives.hashes.SHA256`,
+            :class:`~cryptography.hazmat.primitives.hashes.SHA384`, or
+            :class:`~cryptography.hazmat.primitives.hashes.SHA512`.
+
+    .. method:: add_certificate(certificate)
+
+        Add an additional certificate (typically used to help build a
+        verification chain) to the PKCS7 structure. This method may
+        be called multiple times to add as many certificates as desired.
+
+        :param certificate: The :class:`~cryptography.x509.Certificate` to add.
+
+    .. method:: sign(encoding, options, backend=None)
+
+        :param encoding: :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+            :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`,
+            or :attr:`~cryptography.hazmat.primitives.serialization.Encoding.SMIME`.
+
+        :param options: A list of
+            :class:`~cryptography.hazmat.primitives.serialization.pkcs7.PKCS7Options`.
+
+        :return bytes: The signed PKCS7 message.
+
+        :param backend: An optional backend.
+
+
+.. class:: PKCS7Options
+
+    .. versionadded:: 3.2
+
+    An enumeration of options for PKCS7 signature creation.
+
+    .. attribute:: Text
+
+        The text option adds ``text/plain`` headers to an S/MIME message when
+        serializing to
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.SMIME`.
+        This option is disallowed with ``DER`` serialization.
+
+    .. attribute:: Binary
+
+        Signing normally converts line endings (LF to CRLF). When
+        passing this option the data will not be converted.
+
+    .. attribute:: DetachedSignature
+
+        Don't embed the signed data within the ASN.1. When signing with
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.SMIME`
+        this also results in the data being added as clear text before the
+        PEM encoded structure.
+
+    .. attribute:: NoCapabilities
+
+        PKCS7 structures contain a ``MIMECapabilities`` section inside the
+        ``authenticatedAttributes``. Passing this as an option removes
+        ``MIMECapabilities``.
+
+    .. attribute:: NoAttributes
+
+        PKCS7 structures contain an ``authenticatedAttributes`` section.
+        Passing this as an option removes that section. Note that if you
+        pass ``NoAttributes`` you can't pass ``NoCapabilities`` since
+        ``NoAttributes`` removes ``MIMECapabilities`` and more.
+
+    .. attribute:: NoCerts
+
+        Don't include the signer's certificate in the PKCS7 structure. This can
+        reduce the size of the signature but requires that the recipient can
+        obtain the signer's certificate by other means (for example from a
+        previously signed message).
+
 Serialization Formats
 ~~~~~~~~~~~~~~~~~~~~~
 
@@ -486,6 +765,22 @@
         A raw format used by :doc:`/hazmat/primitives/asymmetric/x448`. It is a
         binary format and is invalid for other key types.
 
+    .. attribute:: OpenSSH
+
+        .. versionadded:: 3.0
+
+        Custom private key format for OpenSSH, internals are based on SSH protocol
+        and not ASN1.  Requires
+        :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`
+        encoding.
+
+        A PEM encoded OpenSSH key will look like::
+
+            -----BEGIN OPENSSH PRIVATE KEY-----
+            ...
+            -----END OPENSSH PRIVATE KEY-----
+
+
 .. class:: PublicFormat
 
     .. versionadded:: 0.8
@@ -615,6 +910,12 @@
         The format used by elliptic curve point encodings. This is a binary
         format.
 
+    .. attribute:: SMIME
+
+        .. versionadded:: 3.2
+
+        An output format used for PKCS7. This is a text format.
+
 
 Serialization Encryption Types
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -646,5 +947,8 @@
     Do not encrypt.
 
 
+.. _`a bug in Firefox`: https://bugzilla.mozilla.org/show_bug.cgi?id=773111
 .. _`PKCS3`: https://www.teletrust.de/fileadmin/files/oid/oid_pkcs-3v1-4.pdf
-.. _`SEC 1 v2.0`: http://www.secg.org/sec1-v2.pdf
+.. _`SEC 1 v2.0`: https://www.secg.org/sec1-v2.pdf
+.. _`PROTOCOL.key`: https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
+.. _`PROTOCOL.certkeys`: https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.certkeys
diff --git a/docs/hazmat/primitives/asymmetric/utils.rst b/docs/hazmat/primitives/asymmetric/utils.rst
index f46acb2..487926e 100644
--- a/docs/hazmat/primitives/asymmetric/utils.rst
+++ b/docs/hazmat/primitives/asymmetric/utils.rst
@@ -57,7 +57,6 @@
     .. doctest::
 
         >>> import hashlib
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives import hashes
         >>> from cryptography.hazmat.primitives.asymmetric import (
         ...    padding, rsa, utils
@@ -65,7 +64,6 @@
         >>> private_key = rsa.generate_private_key(
         ...     public_exponent=65537,
         ...     key_size=2048,
-        ...     backend=default_backend()
         ... )
         >>> prehashed_msg = hashlib.sha256(b"A message I want to sign").digest()
         >>> signature = private_key.sign(
diff --git a/docs/hazmat/primitives/asymmetric/x25519.rst b/docs/hazmat/primitives/asymmetric/x25519.rst
index ea01fba..014f3d0 100644
--- a/docs/hazmat/primitives/asymmetric/x25519.rst
+++ b/docs/hazmat/primitives/asymmetric/x25519.rst
@@ -21,7 +21,6 @@
 
 .. doctest::
 
-    >>> from cryptography.hazmat.backends import default_backend
     >>> from cryptography.hazmat.primitives import hashes
     >>> from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
     >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
@@ -39,7 +38,6 @@
     ...     length=32,
     ...     salt=None,
     ...     info=b'handshake data',
-    ...     backend=default_backend()
     ... ).derive(shared_key)
     >>> # For the next handshake we MUST generate another private key.
     >>> private_key_2 = X25519PrivateKey.generate()
@@ -50,7 +48,6 @@
     ...     length=32,
     ...     salt=None,
     ...     info=b'handshake data',
-    ...     backend=default_backend()
     ... ).derive(shared_key_2)
 
 Key interfaces
diff --git a/docs/hazmat/primitives/asymmetric/x448.rst b/docs/hazmat/primitives/asymmetric/x448.rst
index 4e1f042..f166355 100644
--- a/docs/hazmat/primitives/asymmetric/x448.rst
+++ b/docs/hazmat/primitives/asymmetric/x448.rst
@@ -21,7 +21,6 @@
 
 .. doctest::
 
-    >>> from cryptography.hazmat.backends import default_backend
     >>> from cryptography.hazmat.primitives import hashes
     >>> from cryptography.hazmat.primitives.asymmetric.x448 import X448PrivateKey
     >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
@@ -39,7 +38,6 @@
     ...     length=32,
     ...     salt=None,
     ...     info=b'handshake data',
-    ...     backend=default_backend()
     ... ).derive(shared_key)
     >>> # For the next handshake we MUST generate another private key.
     >>> private_key_2 = X448PrivateKey.generate()
@@ -50,7 +48,6 @@
     ...     length=32,
     ...     salt=None,
     ...     info=b'handshake data',
-    ...     backend=default_backend()
     ... ).derive(shared_key_2)
 
 Key interfaces
diff --git a/docs/hazmat/primitives/cryptographic-hashes.rst b/docs/hazmat/primitives/cryptographic-hashes.rst
index 24cc70b..4cdc034 100644
--- a/docs/hazmat/primitives/cryptographic-hashes.rst
+++ b/docs/hazmat/primitives/cryptographic-hashes.rst
@@ -5,7 +5,7 @@
 
 .. module:: cryptography.hazmat.primitives.hashes
 
-.. class:: Hash(algorithm, backend)
+.. class:: Hash(algorithm, backend=None)
 
     A cryptographic hash function takes an arbitrary block of data and
     calculates a fixed-size bit string (a digest), such that different data
@@ -20,9 +20,8 @@
 
     .. doctest::
 
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives import hashes
-        >>> digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
+        >>> digest = hashes.Hash(hashes.SHA256())
         >>> digest.update(b"abc")
         >>> digest.update(b"123")
         >>> digest.finalize()
@@ -42,7 +41,7 @@
         :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
         instance such as those described in
         :ref:`below <cryptographic-hash-algorithms>`.
-    :param backend: A
+    :param backend: An optional
         :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
         instance.
 
diff --git a/docs/hazmat/primitives/key-derivation-functions.rst b/docs/hazmat/primitives/key-derivation-functions.rst
index be03b19..62457b2 100644
--- a/docs/hazmat/primitives/key-derivation-functions.rst
+++ b/docs/hazmat/primitives/key-derivation-functions.rst
@@ -26,9 +26,17 @@
     Ideal password storage KDFs will be demanding on both computational and
     memory resources.
 
+
+Variable cost algorithms
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+PBKDF2
+------
+
 .. currentmodule:: cryptography.hazmat.primitives.kdf.pbkdf2
 
-.. class:: PBKDF2HMAC(algorithm, length, salt, iterations, backend)
+.. class:: PBKDF2HMAC(algorithm, length, salt, iterations, backend=None)
 
     .. versionadded:: 0.2
 
@@ -47,8 +55,6 @@
         >>> import os
         >>> from cryptography.hazmat.primitives import hashes
         >>> from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
-        >>> from cryptography.hazmat.backends import default_backend
-        >>> backend = default_backend()
         >>> # Salts should be randomly generated
         >>> salt = os.urandom(16)
         >>> # derive
@@ -57,7 +63,6 @@
         ...     length=32,
         ...     salt=salt,
         ...     iterations=100000,
-        ...     backend=backend
         ... )
         >>> key = kdf.derive(b"my great password")
         >>> # verify
@@ -66,7 +71,6 @@
         ...     length=32,
         ...     salt=salt,
         ...     iterations=100000,
-        ...     backend=backend
         ... )
         >>> kdf.verify(b"my great password", key)
 
@@ -79,9 +83,9 @@
     :param int iterations: The number of iterations to perform of the hash
         function. This can be used to control the length of time the operation
         takes. Higher numbers help mitigate brute force attacks against derived
-        keys. See OWASP's `Password Storage Cheat Sheet`_ for more
-        detailed recommendations if you intend to use this for password storage.
-    :param backend: An instance of
+        keys. A `more detailed description`_ can be consulted for additional
+        information.
+    :param backend: An optional instance of
         :class:`~cryptography.hazmat.backends.interfaces.PBKDF2HMACBackend`.
 
     :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
@@ -130,620 +134,12 @@
         key.
 
 
-.. currentmodule:: cryptography.hazmat.primitives.kdf.hkdf
-
-.. class:: HKDF(algorithm, length, salt, info, backend)
-
-    .. versionadded:: 0.2
-
-    `HKDF`_ (HMAC-based Extract-and-Expand Key Derivation Function) is suitable
-    for deriving keys of a fixed size used for other cryptographic operations.
-
-    .. warning::
-
-        HKDF should not be used for password storage.
-
-    .. doctest::
-
-        >>> import os
-        >>> from cryptography.hazmat.primitives import hashes
-        >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
-        >>> from cryptography.hazmat.backends import default_backend
-        >>> backend = default_backend()
-        >>> salt = os.urandom(16)
-        >>> info = b"hkdf-example"
-        >>> hkdf = HKDF(
-        ...     algorithm=hashes.SHA256(),
-        ...     length=32,
-        ...     salt=salt,
-        ...     info=info,
-        ...     backend=backend
-        ... )
-        >>> key = hkdf.derive(b"input key")
-        >>> hkdf = HKDF(
-        ...     algorithm=hashes.SHA256(),
-        ...     length=32,
-        ...     salt=salt,
-        ...     info=info,
-        ...     backend=backend
-        ... )
-        >>> hkdf.verify(b"input key", key)
-
-    :param algorithm: An instance of
-        :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
-
-    :param int length: The desired length of the derived key in bytes. Maximum
-        is ``255 * (algorithm.digest_size // 8)``.
-
-    :param bytes salt: A salt. Randomizes the KDF's output. Optional, but
-        highly recommended. Ideally as many bits of entropy as the security
-        level of the hash: often that means cryptographically random and as
-        long as the hash output. Worse (shorter, less entropy) salt values can
-        still meaningfully contribute to security. May be reused. Does not have
-        to be secret, but may cause stronger security guarantees if secret; see
-        :rfc:`5869` and the `HKDF paper`_ for more details. If ``None`` is
-        explicitly passed a default salt of ``algorithm.digest_size // 8`` null
-        bytes will be used.
-
-    :param bytes info: Application specific context information.  If ``None``
-        is explicitly passed an empty byte string will be used.
-
-    :param backend: An instance of
-        :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`.
-
-    :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
-        provided ``backend`` does not implement
-        :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
-
-    :raises TypeError: This exception is raised if ``salt`` or ``info`` is not
-                       ``bytes``.
-
-    .. 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``.
-
-        Derives a new key from the input key material by performing both the
-        extract and expand operations.
-
-    .. 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 cryptography.exceptions.AlreadyFinalized: This is raised when
-                                                          :meth:`derive` or
-                                                          :meth:`verify` is
-                                                          called more than
-                                                          once.
-
-        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:: HKDFExpand(algorithm, length, info, backend)
-
-    .. versionadded:: 0.5
-
-    HKDF consists of two stages, extract and expand. This class exposes an
-    expand only version of HKDF that is suitable when the key material is
-    already cryptographically strong.
-
-    .. warning::
-
-        HKDFExpand should only be used if the key material is
-        cryptographically strong. You should use
-        :class:`~cryptography.hazmat.primitives.kdf.hkdf.HKDF` if
-        you are unsure.
-
-    .. doctest::
-
-        >>> import os
-        >>> from cryptography.hazmat.primitives import hashes
-        >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDFExpand
-        >>> from cryptography.hazmat.backends import default_backend
-        >>> backend = default_backend()
-        >>> info = b"hkdf-example"
-        >>> key_material = os.urandom(16)
-        >>> hkdf = HKDFExpand(
-        ...     algorithm=hashes.SHA256(),
-        ...     length=32,
-        ...     info=info,
-        ...     backend=backend
-        ... )
-        >>> key = hkdf.derive(key_material)
-        >>> hkdf = HKDFExpand(
-        ...     algorithm=hashes.SHA256(),
-        ...     length=32,
-        ...     info=info,
-        ...     backend=backend
-        ... )
-        >>> hkdf.verify(key_material, key)
-
-    :param algorithm: An instance of
-        :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
-
-    :param int length: The desired length of the derived key in bytes. Maximum
-        is ``255 * (algorithm.digest_size // 8)``.
-
-    :param bytes info: Application specific context information.  If ``None``
-        is explicitly passed an empty byte string will be used.
-
-    :param backend: An instance of
-        :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`.
-
-    :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
-        provided ``backend`` does not implement
-        :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
-    :raises TypeError: This exception is raised if ``info`` is not ``bytes``.
-
-    .. method:: derive(key_material)
-
-        :param bytes key_material: The input key material.
-        :return bytes: The derived key.
-
-        :raises TypeError: This exception is raised if ``key_material`` is not
-                           ``bytes``.
-
-        Derives a new key from the input key material by performing both the
-        extract and expand operations.
-
-    .. 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 cryptography.exceptions.AlreadyFinalized: This is raised when
-                                                          :meth:`derive` or
-                                                          :meth:`verify` is
-                                                          called more than
-                                                          once.
-        :raises TypeError: This is raised if the provided ``key_material`` is
-            a ``unicode`` object
-
-        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.
-
-.. currentmodule:: cryptography.hazmat.primitives.kdf.concatkdf
-
-.. class:: ConcatKDFHash(algorithm, length, otherinfo, backend)
-
-    .. versionadded:: 1.0
-
-    ConcatKDFHash (Concatenation Key Derivation Function) is defined by the
-    NIST Special Publication `NIST SP 800-56Ar2`_ document, to be used to
-    derive keys for use after a Key Exchange negotiation operation.
-
-    .. warning::
-
-        ConcatKDFHash should not be used for password storage.
-
-    .. doctest::
-
-        >>> import os
-        >>> from cryptography.hazmat.primitives import hashes
-        >>> from cryptography.hazmat.primitives.kdf.concatkdf import ConcatKDFHash
-        >>> from cryptography.hazmat.backends import default_backend
-        >>> backend = default_backend()
-        >>> otherinfo = b"concatkdf-example"
-        >>> ckdf = ConcatKDFHash(
-        ...     algorithm=hashes.SHA256(),
-        ...     length=32,
-        ...     otherinfo=otherinfo,
-        ...     backend=backend
-        ... )
-        >>> key = ckdf.derive(b"input key")
-        >>> ckdf = ConcatKDFHash(
-        ...     algorithm=hashes.SHA256(),
-        ...     length=32,
-        ...     otherinfo=otherinfo,
-        ...     backend=backend
-        ... )
-        >>> ckdf.verify(b"input key", key)
-
-    :param algorithm: An instance of
-        :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
-
-    :param int length: The desired length of the derived key in bytes.
-        Maximum is ``hashlen * (2^32 -1)``.
-
-    :param bytes otherinfo: Application specific context information.
-        If ``None`` is explicitly passed an empty byte string will be used.
-
-    :param backend: An instance of
-        :class:`~cryptography.hazmat.backends.interfaces.HashBackend`.
-
-    :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised
-        if the provided ``backend`` does not implement
-        :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
-
-    :raises TypeError: This exception is raised if ``otherinfo`` is not
-        ``bytes``.
-
-    .. 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``.
-
-        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 cryptography.exceptions.AlreadyFinalized: This is raised when
-                                                          :meth:`derive` or
-                                                          :meth:`verify` is
-                                                          called more than
-                                                          once.
-
-        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:: ConcatKDFHMAC(algorithm, length, salt, otherinfo, backend)
-
-    .. versionadded:: 1.0
-
-    Similar to ConcatKFDHash but uses an HMAC function instead.
-
-    .. warning::
-
-        ConcatKDFHMAC should not be used for password storage.
-
-    .. doctest::
-
-        >>> import os
-        >>> from cryptography.hazmat.primitives import hashes
-        >>> from cryptography.hazmat.primitives.kdf.concatkdf import ConcatKDFHMAC
-        >>> from cryptography.hazmat.backends import default_backend
-        >>> backend = default_backend()
-        >>> salt = os.urandom(16)
-        >>> otherinfo = b"concatkdf-example"
-        >>> ckdf = ConcatKDFHMAC(
-        ...     algorithm=hashes.SHA256(),
-        ...     length=32,
-        ...     salt=salt,
-        ...     otherinfo=otherinfo,
-        ...     backend=backend
-        ... )
-        >>> key = ckdf.derive(b"input key")
-        >>> ckdf = ConcatKDFHMAC(
-        ...     algorithm=hashes.SHA256(),
-        ...     length=32,
-        ...     salt=salt,
-        ...     otherinfo=otherinfo,
-        ...     backend=backend
-        ... )
-        >>> ckdf.verify(b"input key", key)
-
-    :param algorithm: An instance of
-        :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
-
-    :param int length: The desired length of the derived key in bytes. Maximum
-        is ``hashlen * (2^32 -1)``.
-
-    :param bytes salt: A salt. Randomizes the KDF's output. Optional, but
-        highly recommended. Ideally as many bits of entropy as the security
-        level of the hash: often that means cryptographically random and as
-        long as the hash output. Does not have to be secret, but may cause
-        stronger security guarantees if secret; If ``None`` is explicitly
-        passed a default salt of ``algorithm.block_size`` null bytes will be
-        used.
-
-    :param bytes otherinfo: Application specific context information.
-        If ``None`` is explicitly passed an empty byte string will be used.
-
-    :param backend: An instance of
-        :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`.
-
-    :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
-        provided ``backend`` does not implement
-        :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
-
-    :raises TypeError: This exception is raised if ``salt`` or ``otherinfo``
-        is not ``bytes``.
-
-    .. method:: derive(key_material)
-
-        :param bytes key_material: The input key material.
-        :return bytes: The derived key.
-        :raises TypeError: This exception is raised if ``key_material`` is not
-                           ``bytes``.
-
-        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 cryptography.exceptions.AlreadyFinalized: This is raised when
-                                                          :meth:`derive` or
-                                                          :meth:`verify` is
-                                                          called more than
-                                                          once.
-
-        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.
-
-.. currentmodule:: cryptography.hazmat.primitives.kdf.x963kdf
-
-.. class:: X963KDF(algorithm, length, otherinfo, backend)
-
-    .. versionadded:: 1.1
-
-    X963KDF (ANSI X9.63 Key Derivation Function) is defined by ANSI
-    in the `ANSI X9.63:2001`_ document, to be used to derive keys for use
-    after a Key Exchange negotiation operation.
-
-    SECG in `SEC 1 v2.0`_ recommends that
-    :class:`~cryptography.hazmat.primitives.kdf.concatkdf.ConcatKDFHash` be
-    used for new projects. This KDF should only be used for backwards
-    compatibility with pre-existing protocols.
-
-
-    .. warning::
-
-        X963KDF should not be used for password storage.
-
-    .. doctest::
-
-        >>> import os
-        >>> from cryptography.hazmat.primitives import hashes
-        >>> from cryptography.hazmat.primitives.kdf.x963kdf import X963KDF
-        >>> from cryptography.hazmat.backends import default_backend
-        >>> backend = default_backend()
-        >>> sharedinfo = b"ANSI X9.63 Example"
-        >>> xkdf = X963KDF(
-        ...     algorithm=hashes.SHA256(),
-        ...     length=32,
-        ...     sharedinfo=sharedinfo,
-        ...     backend=backend
-        ... )
-        >>> key = xkdf.derive(b"input key")
-        >>> xkdf = X963KDF(
-        ...     algorithm=hashes.SHA256(),
-        ...     length=32,
-        ...     sharedinfo=sharedinfo,
-        ...     backend=backend
-        ... )
-        >>> xkdf.verify(b"input key", key)
-
-    :param algorithm: An instance of
-        :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
-
-    :param int length: The desired length of the derived key in bytes.
-        Maximum is ``hashlen * (2^32 -1)``.
-
-    :param bytes sharedinfo: Application specific context information.
-        If ``None`` is explicitly passed an empty byte string will be used.
-
-    :param backend: A cryptography backend
-        :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
-        instance.
-
-    :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised
-        if the provided ``backend`` does not implement
-        :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
-
-    :raises TypeError: This exception is raised if ``sharedinfo`` is not
-        ``bytes``.
-
-    .. 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``.
-
-        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 cryptography.exceptions.AlreadyFinalized: This is raised when
-                                                          :meth:`derive` or
-                                                          :meth:`verify` is
-                                                          called more than
-                                                          once.
-
-        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.
-
-
-.. currentmodule:: cryptography.hazmat.primitives.kdf.kbkdf
-
-.. class:: KBKDFHMAC(algorithm, mode, length, rlen, llen, location,\
-           label, context, fixed, backend)
-
-    .. versionadded:: 1.4
-
-    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::
-
-        KBKDFHMAC should not be used for password storage.
-
-    .. doctest::
-
-        >>> import os
-        >>> from cryptography.hazmat.primitives import hashes
-        >>> from cryptography.hazmat.primitives.kdf.kbkdf import (
-        ...    CounterLocation, KBKDFHMAC, Mode
-        ... )
-        >>> from cryptography.hazmat.backends import default_backend
-        >>> backend = default_backend()
-        >>> label = b"KBKDF HMAC Label"
-        >>> context = b"KBKDF HMAC Context"
-        >>> kdf = KBKDFHMAC(
-        ...     algorithm=hashes.SHA256(),
-        ...     mode=Mode.CounterMode,
-        ...     length=32,
-        ...     rlen=4,
-        ...     llen=4,
-        ...     location=CounterLocation.BeforeFixed,
-        ...     label=label,
-        ...     context=context,
-        ...     fixed=None,
-        ...     backend=backend
-        ... )
-        >>> key = kdf.derive(b"input key")
-        >>> kdf = KBKDFHMAC(
-        ...     algorithm=hashes.SHA256(),
-        ...     mode=Mode.CounterMode,
-        ...     length=32,
-        ...     rlen=4,
-        ...     llen=4,
-        ...     location=CounterLocation.BeforeFixed,
-        ...     label=label,
-        ...     context=context,
-        ...     fixed=None,
-        ...     backend=backend
-        ... )
-        >>> kdf.verify(b"input key", key)
-
-    :param algorithm: An instance of
-        :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
-
-    :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: A cryptography backend
-        :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
-        instance.
-
-    :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised
-        if the provided ``backend`` does not implement
-        :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
-
-    :raises TypeError: This exception is raised if ``label`` or ``context``
-        is not ``bytes``. Also raised if ``rlen`` or ``llen`` is not ``int``.
-
-    :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``.
-
-        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 cryptography.exceptions.AlreadyFinalized: This is raised when
-                                                          :meth:`derive` or
-                                                          :meth:`verify` is
-                                                          called more than
-                                                          once.
-
-        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.
-
-    .. attribute:: CounterMode
-
-        The output of the PRF is computed with a counter
-        as the iteration variable.
-
-.. class:: CounterLocation
-
-    An enumeration for the key based key derivative counter location.
-
-    .. attribute:: BeforeFixed
-
-        The counter iteration variable will be concatenated before
-        the fixed input data.
-
-    .. attribute:: AfterFixed
-
-        The counter iteration variable will be concatenated after
-        the fixed input data.
+Scrypt
+------
 
 .. currentmodule:: cryptography.hazmat.primitives.kdf.scrypt
 
-.. class:: Scrypt(salt, length, n, r, p, backend)
+.. class:: Scrypt(salt, length, n, r, p, backend=None)
 
     .. versionadded:: 1.6
 
@@ -759,8 +155,6 @@
 
         >>> import os
         >>> from cryptography.hazmat.primitives.kdf.scrypt import Scrypt
-        >>> from cryptography.hazmat.backends import default_backend
-        >>> backend = default_backend()
         >>> salt = os.urandom(16)
         >>> # derive
         >>> kdf = Scrypt(
@@ -769,7 +163,6 @@
         ...     n=2**14,
         ...     r=8,
         ...     p=1,
-        ...     backend=backend
         ... )
         >>> key = kdf.derive(b"my great password")
         >>> # verify
@@ -779,7 +172,6 @@
         ...     n=2**14,
         ...     r=8,
         ...     p=1,
-        ...     backend=backend
         ... )
         >>> kdf.verify(b"my great password", key)
 
@@ -789,6 +181,8 @@
         power of 2.
     :param int r: Block size parameter.
     :param int p: Parallelization parameter.
+    :param backend: An optional instance of
+        :class:`~cryptography.hazmat.backends.interfaces.ScryptBackend`.
 
     The computational and memory cost of Scrypt can be adjusted by manipulating
     the 3 parameters: ``n``, ``r``, and ``p``. In general, the memory cost of
@@ -802,9 +196,6 @@
     minimum value of ``n=2**14`` for interactive logins (t < 100ms), or
     ``n=2**20`` for more sensitive files (t < 5s).
 
-    :param backend: An instance of
-        :class:`~cryptography.hazmat.backends.interfaces.ScryptBackend`.
-
     :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
         provided ``backend`` does not implement
         :class:`~cryptography.hazmat.backends.interfaces.ScryptBackend`
@@ -851,6 +242,640 @@
         checking whether the password a user provides matches the stored derived
         key.
 
+Fixed cost algorithms
+~~~~~~~~~~~~~~~~~~~~~
+
+
+ConcatKDF
+---------
+
+.. currentmodule:: cryptography.hazmat.primitives.kdf.concatkdf
+
+.. class:: ConcatKDFHash(algorithm, length, otherinfo, backend=None)
+
+    .. versionadded:: 1.0
+
+    ConcatKDFHash (Concatenation Key Derivation Function) is defined by the
+    NIST Special Publication `NIST SP 800-56Ar2`_ document, to be used to
+    derive keys for use after a Key Exchange negotiation operation.
+
+    .. warning::
+
+        ConcatKDFHash should not be used for password storage.
+
+    .. doctest::
+
+        >>> import os
+        >>> from cryptography.hazmat.primitives import hashes
+        >>> from cryptography.hazmat.primitives.kdf.concatkdf import ConcatKDFHash
+        >>> otherinfo = b"concatkdf-example"
+        >>> ckdf = ConcatKDFHash(
+        ...     algorithm=hashes.SHA256(),
+        ...     length=32,
+        ...     otherinfo=otherinfo,
+        ... )
+        >>> key = ckdf.derive(b"input key")
+        >>> ckdf = ConcatKDFHash(
+        ...     algorithm=hashes.SHA256(),
+        ...     length=32,
+        ...     otherinfo=otherinfo,
+        ... )
+        >>> ckdf.verify(b"input key", key)
+
+    :param algorithm: An instance of
+        :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
+
+    :param int length: The desired length of the derived key in bytes.
+        Maximum is ``hashlen * (2^32 -1)``.
+
+    :param bytes otherinfo: Application specific context information.
+        If ``None`` is explicitly passed an empty byte string will be used.
+
+    :param backend: An optional instance of
+        :class:`~cryptography.hazmat.backends.interfaces.HashBackend`.
+
+    :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised
+        if the provided ``backend`` does not implement
+        :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
+
+    :raises TypeError: This exception is raised if ``otherinfo`` is not
+        ``bytes``.
+
+    .. 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 cryptography.exceptions.AlreadyFinalized: This is raised when
+                                                          :meth:`derive` or
+                                                          :meth:`verify` is
+                                                          called more than
+                                                          once.
+
+        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 cryptography.exceptions.AlreadyFinalized: This is raised when
+                                                          :meth:`derive` or
+                                                          :meth:`verify` is
+                                                          called more than
+                                                          once.
+
+        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:: ConcatKDFHMAC(algorithm, length, salt, otherinfo, backend=None)
+
+    .. versionadded:: 1.0
+
+    Similar to ConcatKFDHash but uses an HMAC function instead.
+
+    .. warning::
+
+        ConcatKDFHMAC should not be used for password storage.
+
+    .. doctest::
+
+        >>> import os
+        >>> from cryptography.hazmat.primitives import hashes
+        >>> from cryptography.hazmat.primitives.kdf.concatkdf import ConcatKDFHMAC
+        >>> salt = os.urandom(16)
+        >>> otherinfo = b"concatkdf-example"
+        >>> ckdf = ConcatKDFHMAC(
+        ...     algorithm=hashes.SHA256(),
+        ...     length=32,
+        ...     salt=salt,
+        ...     otherinfo=otherinfo,
+        ... )
+        >>> key = ckdf.derive(b"input key")
+        >>> ckdf = ConcatKDFHMAC(
+        ...     algorithm=hashes.SHA256(),
+        ...     length=32,
+        ...     salt=salt,
+        ...     otherinfo=otherinfo,
+        ... )
+        >>> ckdf.verify(b"input key", key)
+
+    :param algorithm: An instance of
+        :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
+
+    :param int length: The desired length of the derived key in bytes. Maximum
+        is ``hashlen * (2^32 -1)``.
+
+    :param bytes salt: A salt. Randomizes the KDF's output. Optional, but
+        highly recommended. Ideally as many bits of entropy as the security
+        level of the hash: often that means cryptographically random and as
+        long as the hash output. Does not have to be secret, but may cause
+        stronger security guarantees if secret; If ``None`` is explicitly
+        passed a default salt of ``algorithm.block_size`` null bytes will be
+        used.
+
+    :param bytes otherinfo: Application specific context information.
+        If ``None`` is explicitly passed an empty byte string will be used.
+
+    :param backend: An optional instance of
+        :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`.
+
+    :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
+        provided ``backend`` does not implement
+        :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
+
+    :raises TypeError: This exception is raised if ``salt`` or ``otherinfo``
+        is not ``bytes``.
+
+    .. method:: derive(key_material)
+
+        :param bytes key_material: The input key material.
+        :return bytes: The derived key.
+        :raises TypeError: This exception is raised if ``key_material`` is not
+                           ``bytes``.
+        :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+                                                          :meth:`derive` or
+                                                          :meth:`verify` is
+                                                          called more than
+                                                          once.
+
+        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 cryptography.exceptions.AlreadyFinalized: This is raised when
+                                                          :meth:`derive` or
+                                                          :meth:`verify` is
+                                                          called more than
+                                                          once.
+
+        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.
+
+
+HKDF
+----
+
+.. currentmodule:: cryptography.hazmat.primitives.kdf.hkdf
+
+.. class:: HKDF(algorithm, length, salt, info, backend=None)
+
+    .. versionadded:: 0.2
+
+    `HKDF`_ (HMAC-based Extract-and-Expand Key Derivation Function) is suitable
+    for deriving keys of a fixed size used for other cryptographic operations.
+
+    .. warning::
+
+        HKDF should not be used for password storage.
+
+    .. doctest::
+
+        >>> import os
+        >>> from cryptography.hazmat.primitives import hashes
+        >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
+        >>> salt = os.urandom(16)
+        >>> info = b"hkdf-example"
+        >>> hkdf = HKDF(
+        ...     algorithm=hashes.SHA256(),
+        ...     length=32,
+        ...     salt=salt,
+        ...     info=info,
+        ... )
+        >>> key = hkdf.derive(b"input key")
+        >>> hkdf = HKDF(
+        ...     algorithm=hashes.SHA256(),
+        ...     length=32,
+        ...     salt=salt,
+        ...     info=info,
+        ... )
+        >>> hkdf.verify(b"input key", key)
+
+    :param algorithm: An instance of
+        :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
+
+    :param int length: The desired length of the derived key in bytes. Maximum
+        is ``255 * (algorithm.digest_size // 8)``.
+
+    :param bytes salt: A salt. Randomizes the KDF's output. Optional, but
+        highly recommended. Ideally as many bits of entropy as the security
+        level of the hash: often that means cryptographically random and as
+        long as the hash output. Worse (shorter, less entropy) salt values can
+        still meaningfully contribute to security. May be reused. Does not have
+        to be secret, but may cause stronger security guarantees if secret; see
+        :rfc:`5869` and the `HKDF paper`_ for more details. If ``None`` is
+        explicitly passed a default salt of ``algorithm.digest_size // 8`` null
+        bytes will be used.
+
+    :param bytes info: Application specific context information.  If ``None``
+        is explicitly passed an empty byte string will be used.
+
+    :param backend: An optional instance of
+        :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`.
+
+    :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
+        provided ``backend`` does not implement
+        :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
+
+    :raises TypeError: This exception is raised if ``salt`` or ``info`` is not
+                       ``bytes``.
+
+    .. 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 cryptography.exceptions.AlreadyFinalized: This is raised when
+                                                          :meth:`derive` or
+                                                          :meth:`verify` is
+                                                          called more than
+                                                          once.
+
+        Derives a new key from the input key material by performing both the
+        extract and expand operations.
+
+    .. 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 cryptography.exceptions.AlreadyFinalized: This is raised when
+                                                          :meth:`derive` or
+                                                          :meth:`verify` is
+                                                          called more than
+                                                          once.
+
+        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:: HKDFExpand(algorithm, length, info, backend=None)
+
+    .. versionadded:: 0.5
+
+    HKDF consists of two stages, extract and expand. This class exposes an
+    expand only version of HKDF that is suitable when the key material is
+    already cryptographically strong.
+
+    .. warning::
+
+        HKDFExpand should only be used if the key material is
+        cryptographically strong. You should use
+        :class:`~cryptography.hazmat.primitives.kdf.hkdf.HKDF` if
+        you are unsure.
+
+    .. doctest::
+
+        >>> import os
+        >>> from cryptography.hazmat.primitives import hashes
+        >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDFExpand
+        >>> info = b"hkdf-example"
+        >>> key_material = os.urandom(16)
+        >>> hkdf = HKDFExpand(
+        ...     algorithm=hashes.SHA256(),
+        ...     length=32,
+        ...     info=info,
+        ... )
+        >>> key = hkdf.derive(key_material)
+        >>> hkdf = HKDFExpand(
+        ...     algorithm=hashes.SHA256(),
+        ...     length=32,
+        ...     info=info,
+        ... )
+        >>> hkdf.verify(key_material, key)
+
+    :param algorithm: An instance of
+        :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
+
+    :param int length: The desired length of the derived key in bytes. Maximum
+        is ``255 * (algorithm.digest_size // 8)``.
+
+    :param bytes info: Application specific context information.  If ``None``
+        is explicitly passed an empty byte string will be used.
+
+    :param backend: An optional instance of
+        :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`.
+
+    :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
+        provided ``backend`` does not implement
+        :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
+    :raises TypeError: This exception is raised if ``info`` is not ``bytes``.
+
+    .. method:: derive(key_material)
+
+        :param bytes key_material: The input key material.
+        :return bytes: The derived key.
+
+        :raises TypeError: This exception is raised if ``key_material`` is not
+                           ``bytes``.
+        :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+                                                          :meth:`derive` or
+                                                          :meth:`verify` is
+                                                          called more than
+                                                          once.
+
+        Derives a new key from the input key material by performing both the
+        extract and expand operations.
+
+    .. 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 cryptography.exceptions.AlreadyFinalized: This is raised when
+                                                          :meth:`derive` or
+                                                          :meth:`verify` is
+                                                          called more than
+                                                          once.
+        :raises TypeError: This is raised if the provided ``key_material`` is
+            a ``unicode`` object
+
+        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.
+
+
+KBKDF
+-----
+
+.. currentmodule:: cryptography.hazmat.primitives.kdf.kbkdf
+
+.. class:: KBKDFHMAC(algorithm, mode, length, rlen, llen, location,\
+           label, context, fixed, backend=None)
+
+    .. versionadded:: 1.4
+
+    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::
+
+        KBKDFHMAC should not be used for password storage.
+
+    .. doctest::
+
+        >>> import os
+        >>> from cryptography.hazmat.primitives import hashes
+        >>> from cryptography.hazmat.primitives.kdf.kbkdf import (
+        ...    CounterLocation, KBKDFHMAC, Mode
+        ... )
+        >>> label = b"KBKDF HMAC Label"
+        >>> context = b"KBKDF HMAC Context"
+        >>> kdf = KBKDFHMAC(
+        ...     algorithm=hashes.SHA256(),
+        ...     mode=Mode.CounterMode,
+        ...     length=32,
+        ...     rlen=4,
+        ...     llen=4,
+        ...     location=CounterLocation.BeforeFixed,
+        ...     label=label,
+        ...     context=context,
+        ...     fixed=None,
+        ... )
+        >>> key = kdf.derive(b"input key")
+        >>> kdf = KBKDFHMAC(
+        ...     algorithm=hashes.SHA256(),
+        ...     mode=Mode.CounterMode,
+        ...     length=32,
+        ...     rlen=4,
+        ...     llen=4,
+        ...     location=CounterLocation.BeforeFixed,
+        ...     label=label,
+        ...     context=context,
+        ...     fixed=None,
+        ... )
+        >>> kdf.verify(b"input key", key)
+
+    :param algorithm: An instance of
+        :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
+
+    :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.HMACBackend`.
+
+    :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised
+        if the provided ``backend`` does not implement
+        :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
+
+    :raises TypeError: This exception is raised if ``label`` or ``context``
+        is not ``bytes``. Also raised if ``rlen`` or ``llen`` is not ``int``.
+
+    :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 cryptography.exceptions.AlreadyFinalized: This is raised when
+                                                          :meth:`derive` or
+                                                          :meth:`verify` is
+                                                          called more than
+                                                          once.
+
+        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 cryptography.exceptions.AlreadyFinalized: This is raised when
+                                                          :meth:`derive` or
+                                                          :meth:`verify` is
+                                                          called more than
+                                                          once.
+
+        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.
+
+    .. attribute:: CounterMode
+
+        The output of the PRF is computed with a counter
+        as the iteration variable.
+
+.. class:: CounterLocation
+
+    An enumeration for the key based key derivative counter location.
+
+    .. attribute:: BeforeFixed
+
+        The counter iteration variable will be concatenated before
+        the fixed input data.
+
+    .. attribute:: AfterFixed
+
+        The counter iteration variable will be concatenated after
+        the fixed input data.
+
+
+X963KDF
+-------
+
+.. currentmodule:: cryptography.hazmat.primitives.kdf.x963kdf
+
+.. class:: X963KDF(algorithm, length, otherinfo, backend=None)
+
+    .. versionadded:: 1.1
+
+    X963KDF (ANSI X9.63 Key Derivation Function) is defined by ANSI
+    in the `ANSI X9.63:2001`_ document, to be used to derive keys for use
+    after a Key Exchange negotiation operation.
+
+    SECG in `SEC 1 v2.0`_ recommends that
+    :class:`~cryptography.hazmat.primitives.kdf.concatkdf.ConcatKDFHash` be
+    used for new projects. This KDF should only be used for backwards
+    compatibility with pre-existing protocols.
+
+
+    .. warning::
+
+        X963KDF should not be used for password storage.
+
+    .. doctest::
+
+        >>> import os
+        >>> from cryptography.hazmat.primitives import hashes
+        >>> from cryptography.hazmat.primitives.kdf.x963kdf import X963KDF
+        >>> sharedinfo = b"ANSI X9.63 Example"
+        >>> xkdf = X963KDF(
+        ...     algorithm=hashes.SHA256(),
+        ...     length=32,
+        ...     sharedinfo=sharedinfo,
+        ... )
+        >>> key = xkdf.derive(b"input key")
+        >>> xkdf = X963KDF(
+        ...     algorithm=hashes.SHA256(),
+        ...     length=32,
+        ...     sharedinfo=sharedinfo,
+        ... )
+        >>> xkdf.verify(b"input key", key)
+
+    :param algorithm: An instance of
+        :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
+
+    :param int length: The desired length of the derived key in bytes.
+        Maximum is ``hashlen * (2^32 -1)``.
+
+    :param bytes sharedinfo: Application specific context information.
+        If ``None`` is explicitly passed an empty byte string will be used.
+
+    :param backend: An optional instance of
+        :class:`~cryptography.hazmat.backends.interfaces.HashBackend`.
+
+    :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised
+        if the provided ``backend`` does not implement
+        :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
+
+    :raises TypeError: This exception is raised if ``sharedinfo`` is not
+        ``bytes``.
+
+    .. 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 cryptography.exceptions.AlreadyFinalized: This is raised when
+                                                          :meth:`derive` or
+                                                          :meth:`verify` is
+                                                          called more than
+                                                          once.
+
+        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 cryptography.exceptions.AlreadyFinalized: This is raised when
+                                                          :meth:`derive` or
+                                                          :meth:`verify` is
+                                                          called more than
+                                                          once.
+
+        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.
+
+
 Interface
 ~~~~~~~~~
 
@@ -904,8 +929,8 @@
 .. _`NIST SP 800-108`: https://csrc.nist.gov/publications/detail/sp/800-108/final
 .. _`NIST SP 800-56Ar2`: https://csrc.nist.gov/publications/detail/sp/800-56a/rev-2/final
 .. _`ANSI X9.63:2001`: https://webstore.ansi.org
-.. _`SEC 1 v2.0`: http://www.secg.org/sec1-v2.pdf
-.. _`Password Storage Cheat Sheet`: https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet
+.. _`SEC 1 v2.0`: https://www.secg.org/sec1-v2.pdf
+.. _`more detailed description`: https://security.stackexchange.com/a/3993/43116
 .. _`PBKDF2`: https://en.wikipedia.org/wiki/PBKDF2
 .. _`key stretching`: https://en.wikipedia.org/wiki/Key_stretching
 .. _`HKDF`: https://en.wikipedia.org/wiki/HKDF
diff --git a/docs/hazmat/primitives/keywrap.rst b/docs/hazmat/primitives/keywrap.rst
index 1c15f9d..9d8abbd 100644
--- a/docs/hazmat/primitives/keywrap.rst
+++ b/docs/hazmat/primitives/keywrap.rst
@@ -11,7 +11,7 @@
 protections offered by key wrapping are also offered by using authenticated
 :doc:`symmetric encryption </hazmat/primitives/symmetric-encryption>`.
 
-.. function:: aes_key_wrap(wrapping_key, key_to_wrap, backend)
+.. function:: aes_key_wrap(wrapping_key, key_to_wrap, backend=None)
 
     .. versionadded:: 1.1
 
@@ -22,14 +22,14 @@
 
     :param bytes key_to_wrap: The key to wrap.
 
-    :param backend: A
+    :param backend: An optional
         :class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
         instance that supports
         :class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES`.
 
     :return bytes: The wrapped key as bytes.
 
-.. function:: aes_key_unwrap(wrapping_key, wrapped_key, backend)
+.. function:: aes_key_unwrap(wrapping_key, wrapped_key, backend=None)
 
     .. versionadded:: 1.1
 
@@ -40,7 +40,7 @@
 
     :param bytes wrapped_key: The wrapped key.
 
-    :param backend: A
+    :param backend: An optional
         :class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
         instance that supports
         :class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES`.
@@ -50,7 +50,7 @@
     :raises cryptography.hazmat.primitives.keywrap.InvalidUnwrap: This is
         raised if the key is not successfully unwrapped.
 
-.. function:: aes_key_wrap_with_padding(wrapping_key, key_to_wrap, backend)
+.. function:: aes_key_wrap_with_padding(wrapping_key, key_to_wrap, backend=None)
 
     .. versionadded:: 2.2
 
@@ -61,14 +61,14 @@
 
     :param bytes key_to_wrap: The key to wrap.
 
-    :param backend: A
+    :param backend: An optional
         :class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
         instance that supports
         :class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES`.
 
     :return bytes: The wrapped key as bytes.
 
-.. function:: aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend)
+.. function:: aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend=None)
 
     .. versionadded:: 2.2
 
@@ -79,7 +79,7 @@
 
     :param bytes wrapped_key: The wrapped key.
 
-    :param backend: A
+    :param backend: An optional
         :class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
         instance that supports
         :class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES`.
diff --git a/docs/hazmat/primitives/mac/cmac.rst b/docs/hazmat/primitives/mac/cmac.rst
index a5b13ca..b40a90a 100644
--- a/docs/hazmat/primitives/mac/cmac.rst
+++ b/docs/hazmat/primitives/mac/cmac.rst
@@ -17,7 +17,7 @@
 
 A subset of CMAC with the AES-128 algorithm is described in :rfc:`4493`.
 
-.. class:: CMAC(algorithm, backend)
+.. class:: CMAC(algorithm, backend=None)
 
     .. versionadded:: 0.4
 
@@ -26,10 +26,9 @@
 
     .. doctest::
 
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives import cmac
         >>> from cryptography.hazmat.primitives.ciphers import algorithms
-        >>> c = cmac.CMAC(algorithms.AES(key), backend=default_backend())
+        >>> c = cmac.CMAC(algorithms.AES(key))
         >>> c.update(b"message to authenticate")
         >>> c.finalize()
         b'CT\x1d\xc8\x0e\x15\xbe4e\xdb\xb6\x84\xca\xd9Xk'
@@ -47,7 +46,7 @@
 
     .. doctest::
 
-        >>> c = cmac.CMAC(algorithms.AES(key), backend=default_backend())
+        >>> c = cmac.CMAC(algorithms.AES(key))
         >>> c.update(b"message to authenticate")
         >>> c.verify(b"an incorrect signature")
         Traceback (most recent call last):
@@ -56,7 +55,7 @@
 
     :param algorithm: An instance of
         :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`.
-    :param backend: An instance of
+    :param backend: An optional instance of
         :class:`~cryptography.hazmat.backends.interfaces.CMACBackend`.
     :raises TypeError: This is raised if the provided ``algorithm`` is not an instance of
         :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`
diff --git a/docs/hazmat/primitives/mac/hmac.rst b/docs/hazmat/primitives/mac/hmac.rst
index 9d11694..3695270 100644
--- a/docs/hazmat/primitives/mac/hmac.rst
+++ b/docs/hazmat/primitives/mac/hmac.rst
@@ -15,7 +15,7 @@
 secret key. You can use an HMAC to verify both the integrity and authenticity
 of a message.
 
-.. class:: HMAC(key, algorithm, backend)
+.. class:: HMAC(key, algorithm, backend=None)
 
     HMAC objects take a ``key`` and a
     :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` instance.
@@ -27,9 +27,8 @@
 
     .. doctest::
 
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives import hashes, hmac
-        >>> h = hmac.HMAC(key, hashes.SHA256(), backend=default_backend())
+        >>> 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'
@@ -47,7 +46,7 @@
 
     .. doctest::
 
-        >>> h = hmac.HMAC(key, hashes.SHA256(), backend=default_backend())
+        >>> h = hmac.HMAC(key, hashes.SHA256())
         >>> h.update(b"message to hash")
         >>> h.verify(b"an incorrect signature")
         Traceback (most recent call last):
@@ -60,7 +59,7 @@
         :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
         instance such as those described in
         :ref:`Cryptographic Hashes <cryptographic-hash-algorithms>`.
-    :param backend: An
+    :param backend: An optional
         :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
         instance.
 
diff --git a/docs/hazmat/primitives/mac/index.rst b/docs/hazmat/primitives/mac/index.rst
index 86c407c..8bfe29e 100644
--- a/docs/hazmat/primitives/mac/index.rst
+++ b/docs/hazmat/primitives/mac/index.rst
@@ -3,48 +3,17 @@
 Message authentication codes
 ============================
 
-While cryptography supports both the CMAC and HMAC algorithms, we strongly
-recommend that HMAC should be used unless you have a good reason otherwise.
+While cryptography supports multiple MAC algorithms, we strongly
+recommend that HMAC should be used unless you have a very specific need.
 
 For more information on why HMAC is preferred, see `Use cases for CMAC vs.
 HMAC?`_
 
-HMAC and CMAC both use the ``MACContext`` interface:
-
-.. currentmodule:: cryptography.hazmat.primitives.mac
-
-.. class:: MACContext
-
-    .. versionadded:: 0.7
-
-    .. method:: update(data)
-
-        :param bytes data: The data you want to authenticate.
-
-    .. method:: finalize()
-
-        :return: The message authentication code.
-
-    .. method:: copy()
-
-        :return: A
-            :class:`~cryptography.hazmat.primitives.mac.MACContext` that
-            is a copy of the current context.
-
-    .. method:: verify(signature)
-
-        :param bytes signature: The signature to verify.
-
-        :raises cryptography.exceptions.InvalidSignature: This is raised when
-            the provided signature does not match the expected signature.
-
-
-
-.. _`CMAC`: https://en.wikipedia.org/wiki/CMAC
-.. _`Use cases for CMAC vs. HMAC?`: https://crypto.stackexchange.com/questions/15721/use-cases-for-cmac-vs-hmac
-
 .. toctree::
     :maxdepth: 1
 
     cmac
     hmac
+    poly1305
+
+.. _`Use cases for CMAC vs. HMAC?`: https://crypto.stackexchange.com/questions/15721/use-cases-for-cmac-vs-hmac
diff --git a/docs/hazmat/primitives/mac/poly1305.rst b/docs/hazmat/primitives/mac/poly1305.rst
new file mode 100644
index 0000000..7504a07
--- /dev/null
+++ b/docs/hazmat/primitives/mac/poly1305.rst
@@ -0,0 +1,132 @@
+.. hazmat::
+
+Poly1305
+========
+
+.. currentmodule:: cryptography.hazmat.primitives.poly1305
+
+.. testsetup::
+
+    key = b"\x01" * 32
+
+Poly1305 is an authenticator that takes a 32-byte key and a message and
+produces a 16-byte tag. This tag is used to authenticate the message. Each key
+**must** only be used once. Using the same key to generate tags for multiple
+messages allows an attacker to forge tags. Poly1305 is described in
+:rfc:`7539`.
+
+.. class:: Poly1305(key)
+
+    .. versionadded:: 2.7
+
+    .. warning::
+
+        Using the same key to generate tags for multiple messages allows an
+        attacker to forge tags. Always generate a new key per message you want
+        to authenticate. If you are using this as a MAC for
+        symmetric encryption please use
+        :class:`~cryptography.hazmat.primitives.ciphers.aead.ChaCha20Poly1305`
+        instead.
+
+    .. doctest::
+
+        >>> from cryptography.hazmat.primitives import poly1305
+        >>> p = poly1305.Poly1305(key)
+        >>> p.update(b"message to authenticate")
+        >>> p.finalize()
+        b'T\xae\xff3\xbdW\xef\xd5r\x01\xe2n=\xb7\xd2h'
+
+    To check that a given tag is correct use the :meth:`verify` method.
+    You will receive an exception if the tag is wrong:
+
+    .. doctest::
+
+        >>> p = poly1305.Poly1305(key)
+        >>> p.update(b"message to authenticate")
+        >>> p.verify(b"an incorrect tag")
+        Traceback (most recent call last):
+        ...
+        cryptography.exceptions.InvalidSignature: Value did not match computed tag.
+
+    :param key: Secret key as ``bytes``.
+    :type key: :term:`bytes-like`
+    :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
+        the version of OpenSSL ``cryptography`` is compiled against does not
+        support this algorithm.
+
+    .. method:: update(data)
+
+        :param data: The bytes to hash and authenticate.
+        :type data: :term:`bytes-like`
+        :raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize`
+        :raises TypeError: This exception is raised if ``data`` is not ``bytes``.
+
+    .. method:: verify(tag)
+
+        Finalize the current context and securely compare the MAC to
+        ``tag``.
+
+        :param bytes tag: The bytes to compare against.
+        :raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize`
+        :raises cryptography.exceptions.InvalidSignature: If tag does not
+                                                          match.
+        :raises TypeError: This exception is raised if ``tag`` is not
+                           ``bytes``.
+
+        .. method:: finalize()
+
+        Finalize the current context and return the message authentication code
+        as bytes.
+
+        After ``finalize`` has been called this object can no longer be used
+        and :meth:`update`, :meth:`verify`, and :meth:`finalize`
+        will raise an :class:`~cryptography.exceptions.AlreadyFinalized`
+        exception.
+
+        :return bytes: The message authentication code as bytes.
+        :raises cryptography.exceptions.AlreadyFinalized:
+
+    .. classmethod:: generate_tag(key, data)
+
+        A single step alternative to do sign operations. Returns the message
+        authentication code as ``bytes`` for the given ``key`` and ``data``.
+
+        :param key: Secret key as ``bytes``.
+        :type key: :term:`bytes-like`
+        :param data: The bytes to hash and authenticate.
+        :type data: :term:`bytes-like`
+        :return bytes: The message authentication code as bytes.
+        :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
+            the version of OpenSSL ``cryptography`` is compiled against does not
+            support this algorithm.
+        :raises TypeError: This exception is raised if ``key`` or ``data`` are
+            not ``bytes``.
+
+        .. doctest::
+
+            >>> poly1305.Poly1305.generate_tag(key, b"message to authenticate")
+            b'T\xae\xff3\xbdW\xef\xd5r\x01\xe2n=\xb7\xd2h'
+
+    .. classmethod:: verify_tag(key, data, tag)
+
+        A single step alternative to do verify operations. Securely compares the
+        MAC to ``tag``, using the given ``key`` and ``data``.
+
+        :param key: Secret key as ``bytes``.
+        :type key: :term:`bytes-like`
+        :param data: The bytes to hash and authenticate.
+        :type data: :term:`bytes-like`
+        :param bytes tag: The bytes to compare against.
+        :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
+            the version of OpenSSL ``cryptography`` is compiled against does not
+            support this algorithm.
+        :raises TypeError: This exception is raised if ``key``, ``data`` or
+            ``tag`` are not ``bytes``.
+        :raises cryptography.exceptions.InvalidSignature: If tag does not match.
+
+        .. doctest::
+
+            >>> poly1305.Poly1305.verify_tag(key, b"message to authenticate", b"an incorrect tag")
+            Traceback (most recent call last):
+            ...
+            cryptography.exceptions.InvalidSignature: Value did not match computed tag.
diff --git a/docs/hazmat/primitives/padding.rst b/docs/hazmat/primitives/padding.rst
index 9581df8..99d500a 100644
--- a/docs/hazmat/primitives/padding.rst
+++ b/docs/hazmat/primitives/padding.rst
@@ -107,7 +107,8 @@
 
     .. method:: update(data)
 
-        :param bytes data: The data you wish to pass into the context.
+        :param data: The data you wish to pass into the context.
+        :type data: :term:`bytes-like`
         :return bytes: Returns the data that was padded or unpadded.
         :raises TypeError: Raised if data is not bytes.
         :raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize`.
diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst
index 21d12a3..8551acb 100644
--- a/docs/hazmat/primitives/symmetric-encryption.rst
+++ b/docs/hazmat/primitives/symmetric-encryption.rst
@@ -11,7 +11,8 @@
 encryption is **not** sufficient for most applications because it only
 provides secrecy but not authenticity. That means an attacker can't see the
 message but an attacker can create bogus messages and force the application to
-decrypt them.
+decrypt them. In many contexts, a lack of authentication on encrypted messages
+can result in a loss of secrecy as well.
 
 For this reason it is **strongly** recommended to combine encryption with a
 message authentication code, such as :doc:`HMAC </hazmat/primitives/mac/hmac>`,
@@ -20,7 +21,7 @@
 **To minimize the risk of security issues you should evaluate Fernet to see if
 it fits your needs before implementing anything using this module.**
 
-.. class:: Cipher(algorithm, mode, backend)
+.. class:: Cipher(algorithm, mode, backend=None)
 
     Cipher objects combine an algorithm such as
     :class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES` with a
@@ -33,25 +34,23 @@
 
         >>> import os
         >>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
-        >>> from cryptography.hazmat.backends import default_backend
-        >>> backend = default_backend()
         >>> key = os.urandom(32)
         >>> iv = os.urandom(16)
-        >>> cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)
+        >>> cipher = Cipher(algorithms.AES(key), modes.CBC(iv))
         >>> encryptor = cipher.encryptor()
         >>> ct = encryptor.update(b"a secret message") + encryptor.finalize()
         >>> decryptor = cipher.decryptor()
         >>> decryptor.update(ct) + decryptor.finalize()
         b'a secret message'
 
-    :param algorithms: A
+    :param algorithm: A
         :class:`~cryptography.hazmat.primitives.ciphers.CipherAlgorithm`
         instance such as those described
         :ref:`below <symmetric-encryption-algorithms>`.
     :param mode: A :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode`
         instance such as those described
         :ref:`below <symmetric-encryption-modes>`.
-    :param backend: A
+    :param backend: An optional
         :class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
         instance.
 
@@ -147,10 +146,9 @@
     .. doctest::
 
         >>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
-        >>> from cryptography.hazmat.backends import default_backend
         >>> nonce = os.urandom(16)
         >>> algorithm = algorithms.ChaCha20(key, nonce)
-        >>> cipher = Cipher(algorithm, mode=None, backend=default_backend())
+        >>> cipher = Cipher(algorithm, mode=None)
         >>> encryptor = cipher.encryptor()
         >>> ct = encryptor.update(b"a secret message")
         >>> decryptor = cipher.decryptor()
@@ -231,9 +229,8 @@
     .. doctest::
 
         >>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
-        >>> from cryptography.hazmat.backends import default_backend
         >>> algorithm = algorithms.ARC4(key)
-        >>> cipher = Cipher(algorithm, mode=None, backend=default_backend())
+        >>> cipher = Cipher(algorithm, mode=None)
         >>> encryptor = cipher.encryptor()
         >>> ct = encryptor.update(b"a secret message")
         >>> decryptor = cipher.decryptor()
@@ -418,9 +415,6 @@
     :raises ValueError: This is raised if ``len(tag) < min_tag_length`` or the
         ``initialization_vector`` is too short.
 
-    :raises NotImplementedError: This is raised if the version of the OpenSSL
-        backend used is 1.0.1 or earlier.
-
     An example of securely encrypting and decrypting data with ``AES`` in the
     ``GCM`` mode looks like:
 
@@ -428,7 +422,6 @@
 
         import os
 
-        from cryptography.hazmat.backends import default_backend
         from cryptography.hazmat.primitives.ciphers import (
             Cipher, algorithms, modes
         )
@@ -442,7 +435,6 @@
             encryptor = Cipher(
                 algorithms.AES(key),
                 modes.GCM(iv),
-                backend=default_backend()
             ).encryptor()
 
             # associated_data will be authenticated but not encrypted,
@@ -461,7 +453,6 @@
             decryptor = Cipher(
                 algorithms.AES(key),
                 modes.GCM(iv, tag),
-                backend=default_backend()
             ).decryptor()
 
             # We put associated_data back in or the tag will fail to verify
@@ -598,11 +589,9 @@
 
             >>> import os
             >>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
-            >>> from cryptography.hazmat.backends import default_backend
-            >>> backend = default_backend()
             >>> key = os.urandom(32)
             >>> iv = os.urandom(16)
-            >>> cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)
+            >>> cipher = Cipher(algorithms.AES(key), modes.CBC(iv))
             >>> encryptor = cipher.encryptor()
             >>> # the buffer needs to be at least len(data) + n - 1 where n is cipher/mode block size in bytes
             >>> buf = bytearray(31)
@@ -681,18 +670,12 @@
 
     .. method:: finalize_with_tag(tag)
 
-        .. note::
-
-            This method is not supported when compiled against OpenSSL 1.0.1.
-
         :param bytes tag: The tag bytes to verify after decryption.
         :return bytes: Returns the remainder of the data.
         :raises ValueError: This is raised when the data provided isn't
             a multiple of the algorithm's block size, if ``min_tag_length`` is
             less than 4, or if ``len(tag) < min_tag_length``.
             ``min_tag_length`` is an argument to the ``GCM`` constructor.
-        :raises NotImplementedError: This is raised if the version of the
-            OpenSSL backend used is 1.0.1 or earlier.
 
         If the authentication tag was not already supplied to the constructor
         of the :class:`~cryptography.hazmat.primitives.ciphers.modes.GCM` mode
@@ -828,7 +811,7 @@
 .. _`Communications Security Establishment`: https://www.cse-cst.gc.ca
 .. _`encrypt`: https://ssd.eff.org/en/module/what-should-i-know-about-encryption
 .. _`CRYPTREC`: https://www.cryptrec.go.jp/english/
-.. _`significant patterns in the output`: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_.28ECB.29
+.. _`significant patterns in the output`: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_(ECB)
 .. _`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
diff --git a/docs/hazmat/primitives/twofactor.rst b/docs/hazmat/primitives/twofactor.rst
index 51625df..1d2ab45 100644
--- a/docs/hazmat/primitives/twofactor.rst
+++ b/docs/hazmat/primitives/twofactor.rst
@@ -18,7 +18,7 @@
 
 .. currentmodule:: cryptography.hazmat.primitives.twofactor.hotp
 
-.. class:: HOTP(key, length, algorithm, backend, enforce_key_length=True)
+.. class:: HOTP(key, length, algorithm, backend=None, enforce_key_length=True)
 
     .. versionadded:: 0.3
 
@@ -33,11 +33,10 @@
     .. doctest::
 
         >>> import os
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives.twofactor.hotp import HOTP
         >>> from cryptography.hazmat.primitives.hashes import SHA1
         >>> key = os.urandom(20)
-        >>> hotp = HOTP(key, 6, SHA1(), backend=default_backend())
+        >>> hotp = HOTP(key, 6, SHA1())
         >>> hotp_value = hotp.generate(0)
         >>> hotp.verify(hotp_value, 0)
 
@@ -49,15 +48,15 @@
     :param cryptography.hazmat.primitives.hashes.HashAlgorithm algorithm: A
         :class:`~cryptography.hazmat.primitives.hashes`
         instance.
-    :param backend: A
+    :param backend: An optional
         :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
         instance.
     :param enforce_key_length: A boolean flag defaulting to True that toggles
         whether a minimum key length of 128 :term:`bits` is enforced. This
         exists to work around the fact that as documented in `Issue #2915`_,
         the Google Authenticator PAM module by default generates 80 bit keys.
-        If this flag is set to False, the application develop should implement
-        additional checks of the key length before passing it into
+        If this flag is set to False, the application developer should
+        implement additional checks of the key length before passing it into
         :class:`~cryptography.hazmat.primitives.twofactor.hotp.HOTP`.
 
         .. versionadded:: 1.5
@@ -129,7 +128,7 @@
         assert look_ahead >= 0
         correct_counter = None
 
-        otp = HOTP(key, 6, default_backend())
+        otp = HOTP(key, 6)
         for count in range(counter, counter + look_ahead):
             try:
                 otp.verify(hotp, count)
@@ -141,7 +140,7 @@
 
 .. currentmodule:: cryptography.hazmat.primitives.twofactor.totp
 
-.. class:: TOTP(key, length, algorithm, time_step, backend, enforce_key_length=True)
+.. class:: TOTP(key, length, algorithm, time_step, backend=None, enforce_key_length=True)
 
     TOTP objects take a ``key``, ``length``, ``algorithm`` and ``time_step``
     parameter. The ``key`` should be :doc:`randomly generated bytes
@@ -155,11 +154,10 @@
 
         >>> import os
         >>> import time
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives.twofactor.totp import TOTP
         >>> from cryptography.hazmat.primitives.hashes import SHA1
         >>> key = os.urandom(20)
-        >>> totp = TOTP(key, 8, SHA1(), 30, backend=default_backend())
+        >>> totp = TOTP(key, 8, SHA1(), 30)
         >>> time_value = time.time()
         >>> totp_value = totp.generate(time_value)
         >>> totp.verify(totp_value, time_value)
@@ -173,7 +171,7 @@
         :class:`~cryptography.hazmat.primitives.hashes`
         instance.
     :param int time_step: The time step size. The recommended size is 30.
-    :param backend: A
+    :param backend: An optional
         :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
         instance.
     :param enforce_key_length: A boolean flag defaulting to True that toggles
diff --git a/docs/index.rst b/docs/index.rst
index 9ff8664..ec3913f 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -19,7 +19,8 @@
     '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`_.
+recommend `Crypto 101, by Laurens Van Houtven`_ and `The Cryptopals Crypto
+Challenges`_.
 
 Installation
 ------------
@@ -67,7 +68,6 @@
     exceptions
     random-numbers
     hazmat/backends/index
-    hazmat/bindings/index
 
 .. toctree::
     :maxdepth: 2
@@ -92,3 +92,4 @@
     :doc:`get in touch </community>`.
 
 .. _`Crypto 101, by Laurens Van Houtven`: https://www.crypto101.io/
+.. _`The Cryptopals Crypto Challenges`: https://cryptopals.com/
diff --git a/docs/installation.rst b/docs/installation.rst
index 5b2854d..ea46255 100644
--- a/docs/installation.rst
+++ b/docs/installation.rst
@@ -10,29 +10,26 @@
 Supported platforms
 -------------------
 
-Currently we test ``cryptography`` on Python 2.7, 3.4+, and
-PyPy 5.4+ on these operating systems.
+Currently we test ``cryptography`` on Python 2.7, 3.6+,
+PyPy 7.3.1, and PyPy3 7.3.1 on these operating systems.
 
 * x86-64 CentOS 7.x
-* macOS 10.12 Sierra, 10.11 El Capitan
-* x86-64 Ubuntu 14.04, 16.04, and rolling
-* x86-64 Debian Wheezy (7.x), Jessie (8.x), Stretch (9.x), and Sid (unstable)
+* x86-64 & AArch64 CentOS 8.x
+* x86-64 Fedora (latest)
+* x86-64 macOS 10.15 Catalina
+* x86-64 & AArch64 Ubuntu 18.04, 20.04
+* x86-64 Ubuntu rolling
+* x86-64 Debian Stretch (9.x), Buster (10.x), Bullseye (11.x), and Sid
+  (unstable)
 * x86-64 Alpine (latest)
-* 32-bit and 64-bit Python on 64-bit Windows Server 2012
+* 32-bit and 64-bit Python on 64-bit Windows Server 2019
 
 We test compiling with ``clang`` as well as ``gcc`` and use the following
 OpenSSL releases:
 
-* ``OpenSSL 1.0.1``
-* ``OpenSSL 1.0.1e-fips`` (``RHEL/CentOS 7``)
-* ``OpenSSL 1.0.1f``
-* ``OpenSSL 1.0.2-latest``
 * ``OpenSSL 1.1.0-latest``
 * ``OpenSSL 1.1.1-latest``
 
-.. warning::
-    Cryptography 2.4 has deprecated support for OpenSSL 1.0.1.
-
 
 Building cryptography on Windows
 --------------------------------
@@ -46,12 +43,11 @@
     $ pip install cryptography
 
 If you prefer to compile it yourself you'll need to have OpenSSL installed.
-You can compile OpenSSL yourself as well or use the binaries we build for our
-release infrastructure (`openssl-release`_). Be sure to download the proper
-version for your architecture and Python (2010 works for Python 2.7, 3.3,
-and 3.4 while 2015 is required for 3.5 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:
+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:
 
 .. code-block:: console
 
@@ -74,10 +70,10 @@
 Building cryptography on Linux
 ------------------------------
 
-``cryptography`` ships a ``manylinux1`` wheel (as of 2.0) so all dependencies
-are included. For users on pip 8.1 or above running on a ``manylinux1``
-compatible distribution (almost everything except Alpine) all you should
-need to do is:
+``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:
 
 .. code-block:: console
 
@@ -121,8 +117,8 @@
 ~~~~~~~~
 
 You should now be able to build and install cryptography. To avoid getting
-the pre-built wheel on ``manylinux1`` distributions you'll need to use
-``--no-binary``.
+the pre-built wheel on ``manylinux`` compatible distributions you'll need to
+use ``--no-binary``.
 
 .. code-block:: console
 
@@ -162,9 +158,9 @@
 ~~~~~~~~~~~~~
 
 Cryptography ships statically-linked wheels for macOS, Windows, and Linux (via
-``manylinux1``). This allows compatible environments to use the most recent
+``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 ``manylinux1`` compatible so
+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
@@ -228,7 +224,7 @@
 If you want to build cryptography yourself or are on an older macOS version,
 cryptography requires the presence of a C compiler, development headers, and
 the proper libraries. On macOS much of this is provided by Apple's Xcode
-development tools.  To install the Xcode command line tools (on macOS 10.9+)
+development tools.  To install the Xcode command line tools (on macOS 10.10+)
 open a terminal window and run:
 
 .. code-block:: console
@@ -279,7 +275,7 @@
 
 .. _`Homebrew`: https://brew.sh
 .. _`MacPorts`: https://www.macports.org
-.. _`openssl-release`: https://ci.cryptography.io/job/cryptography-support-jobs/job/openssl-release-1.1/
+.. _`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
diff --git a/docs/limitations.rst b/docs/limitations.rst
index 503bdfe..5763ecd 100644
--- a/docs/limitations.rst
+++ b/docs/limitations.rst
@@ -1,19 +1,44 @@
 Known security limitations
---------------------------
+==========================
 
-Lack of secure memory wiping
-============================
+Secure memory wiping
+--------------------
 
 `Memory wiping`_ is used to protect secret data or key material from attackers
-with access to uninitialized memory. This can be either because the attacker
-has some kind of local user access or because of how other software uses
-uninitialized memory.
+with access to deallocated memory. This is a defense-in-depth measure against
+vulnerabilities that leak application memory.
 
-Python exposes no API for us to implement this reliably and as such almost all
-software in Python is potentially vulnerable to this attack. The
+Many ``cryptography`` APIs which accept ``bytes`` also accept types which
+implement the buffer interface. Thus, users wishing to do so can pass
+``memoryview`` or another mutable type to ``cryptography`` APIs, and overwrite
+the contents once the data is no longer needed.
+
+However, ``cryptography`` does not clear memory by default, as there is no way
+to clear immutable structures such as ``bytes``. As a result, ``cryptography``,
+like almost all software in Python is potentially vulnerable to this attack. The
 `CERT secure coding guidelines`_ assesses this issue as "Severity: medium,
 Likelihood: unlikely, Remediation Cost: expensive to repair" and we do not
 consider this a high risk for most users.
 
-.. _`Memory wiping`:  https://blogs.msdn.microsoft.com/oldnewthing/20130529-00/?p=4223/
-.. _`CERT secure coding guidelines`: https://www.securecoding.cert.org/confluence/display/c/MEM03-C.+Clear+sensitive+information+stored+in+reusable+resources
+RSA PKCS1 v1.5 constant time decryption
+---------------------------------------
+
+RSA decryption has several different modes, one of which is PKCS1 v1.5. When
+used in online contexts, a secure protocol implementation requires that peers
+not be able to tell whether RSA PKCS1 v1.5 decryption failed or succeeded,
+even by timing variability.
+
+``cryptography`` does not provide an API that makes this possible, due to the
+fact that RSA decryption raises an exception on failure, which takes a
+different amount of time than returning a value in the success case.
+
+For this reason, at present, we recommend not implementing online protocols
+that use RSA PKCS1 v1.5 decryption with ``cryptography`` -- independent of this
+limitation, such protocols generally have poor security properties due to their
+lack of forward security.
+
+If a constant time RSA PKCS1 v1.5 decryption API is truly required, you should
+contribute one to ``cryptography``.
+
+.. _`Memory wiping`:  https://devblogs.microsoft.com/oldnewthing/?p=4223
+.. _`CERT secure coding guidelines`: https://wiki.sei.cmu.edu/confluence/display/c/MEM03-C.+Clear+sensitive+information+stored+in+reusable+resources
diff --git a/docs/security.rst b/docs/security.rst
index 01845a4..d11f270 100644
--- a/docs/security.rst
+++ b/docs/security.rst
@@ -9,9 +9,9 @@
 --------------
 
 In addition to ``cryptography``'s code, we're also concerned with the security
-of the infrastructure we run (primarily ``cryptography.io`` and
-``ci.cryptography.io``). If you discover a security vulnerability in our
-infrastructure, we ask you to report it using the same procedure.
+of the infrastructure we run (primarily ``cryptography.io``).  If you discover
+a security vulnerability in our infrastructure, we ask you to report it using
+the same procedure.
 
 What is a security issue?
 -------------------------
@@ -53,10 +53,9 @@
 tracker.
 
 If you believe you've identified a security issue with ``cryptography``, please
-report it to ``alex.gaynor@gmail.com``. Messages may be optionally encrypted
-with PGP using key fingerprint
-``F7FC 698F AAE2 D2EF BECD  E98E D1B3 ADC0 E023 8CA6`` (this public key is
-available from most commonly-used key servers).
+report it to ``alex.gaynor@gmail.com`` and/or ``paul.l.kehrer@gmail.com``. You
+should verify that your MTA uses TLS to ensure the confidentiality of your
+message.
 
 Once you've submitted an issue via email, you should receive an acknowledgment
 within 48 hours, and depending on the action to be taken, you may receive
@@ -72,9 +71,9 @@
 --------------------------------
 
 As of versions 0.5, 1.0.1, and 2.0.0, ``cryptography`` statically links OpenSSL
-on Windows, macOS, and Linux respectively, to ease installation. Due to this,
-``cryptography`` will release a new version whenever OpenSSL has a security or
-bug fix release to avoid shipping insecure software.
+in binary distributions for Windows, macOS, and Linux respectively, to ease
+installation. Due to this, ``cryptography`` will release a new version whenever
+OpenSSL has a security or bug fix release to avoid shipping insecure software.
 
 Like all our other releases, this will be announced on the mailing list and we
 strongly recommend that you upgrade as soon as possible.
diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt
index 7e08f12..f0486e0 100644
--- a/docs/spelling_wordlist.txt
+++ b/docs/spelling_wordlist.txt
@@ -1,14 +1,18 @@
+AArch
 accessor
 affine
 Authenticator
+authenticator
 backend
 Backends
 backends
 bcrypt
+Bleichenbacher
 Blowfish
 boolean
 Botan
 Brainpool
+Bullseye
 Capitan
 changelog
 Changelog
@@ -17,11 +21,13 @@
 committer
 committers
 conda
+CPython
 Cryptanalysis
 crypto
 cryptographic
 cryptographically
 Debian
+deallocated
 decrypt
 decrypts
 Decrypts
@@ -50,9 +56,9 @@
 hazmat
 Homebrew
 hostname
-idna
 indistinguishability
 initialisms
+interoperability
 interoperable
 introspectability
 invariants
@@ -76,6 +82,7 @@
 personalization
 pickleable
 plaintext
+Poly
 pre
 precompute
 preprocessor
@@ -83,6 +90,7 @@
 presentational
 pseudorandom
 pyOpenSSL
+pytest
 relicensed
 responder
 runtime
@@ -95,6 +103,7 @@
 syscall
 Tanja
 testability
+Thawte
 timestamp
 timestamps
 tunable
diff --git a/docs/x509/ocsp.rst b/docs/x509/ocsp.rst
index d3815d6..0c2d07a 100644
--- a/docs/x509/ocsp.rst
+++ b/docs/x509/ocsp.rst
@@ -167,12 +167,11 @@
 
     .. doctest::
 
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives import serialization
         >>> from cryptography.hazmat.primitives.hashes import SHA1
         >>> from cryptography.x509 import load_pem_x509_certificate, ocsp
-        >>> cert = load_pem_x509_certificate(pem_cert, default_backend())
-        >>> issuer = load_pem_x509_certificate(pem_issuer, default_backend())
+        >>> 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())
@@ -292,27 +291,35 @@
         :attr:`~cryptography.x509.ocsp.OCSPResponseStatus.SUCCESSFUL` response.
 
         :param private_key: The
-            :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`
-            or
-            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`
+            :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`,
+            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`,
+            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`,
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey` or
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
             that will be used to sign the certificate.
 
         :param algorithm: The
             :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` that
-            will be used to generate the signature.
+            will be used to generate the signature.  This must be ``None`` if
+            the ``private_key`` is an
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey`
+            or an
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
+            and an instance of a
+            :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+            otherwise.
 
         :returns: A new :class:`~cryptography.x509.ocsp.OCSPResponse`.
 
     .. doctest::
 
         >>> import datetime
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives import hashes, serialization
         >>> from cryptography.x509 import load_pem_x509_certificate, ocsp
-        >>> cert = load_pem_x509_certificate(pem_cert, default_backend())
-        >>> issuer = load_pem_x509_certificate(pem_issuer, default_backend())
-        >>> responder_cert = load_pem_x509_certificate(pem_responder_cert, default_backend())
-        >>> responder_key = serialization.load_pem_private_key(pem_responder_key, None, default_backend())
+        >>> cert = load_pem_x509_certificate(pem_cert)
+        >>> issuer = load_pem_x509_certificate(pem_issuer)
+        >>> 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.
         >>> builder = builder.add_response(
@@ -341,7 +348,6 @@
 
     .. doctest::
 
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives import hashes, serialization
         >>> from cryptography.x509 import load_pem_x509_certificate, ocsp
         >>> response = ocsp.OCSPResponseBuilder.build_unsuccessful(
@@ -434,7 +440,10 @@
 
         Returns the
         :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` which
-        was used in signing this response.
+        was used in signing this response.  Can be ``None`` if signature
+        did not use separate hash
+        (:attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED25519`,
+        :attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED448`).
 
     .. attribute:: signature
 
@@ -589,6 +598,14 @@
 
         The extensions encoded in the response.
 
+    .. attribute:: single_extensions
+
+        .. versionadded:: 2.9
+
+        :type: :class:`~cryptography.x509.Extensions`
+
+        The single extensions encoded in the response.
+
     .. method:: public_bytes(encoding)
 
         :param encoding: The encoding to use. Only
diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst
index b2278d5..a46c5d6 100644
--- a/docs/x509/reference.rst
+++ b/docs/x509/reference.rst
@@ -22,22 +22,20 @@
 
     pem_req_data = b"""
     -----BEGIN CERTIFICATE REQUEST-----
-    MIIC0zCCAbsCAQAwWTELMAkGA1UEBhMCVVMxETAPBgNVBAgMCElsbGlub2lzMRAw
-    DgYDVQQHDAdDaGljYWdvMREwDwYDVQQKDAhyNTA5IExMQzESMBAGA1UEAwwJaGVs
-    bG8uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqhZx+Mo9VRd9
-    vsnWWa6NBCws21rZ0+1B/JGgB4hDsZS7iDE4Bj5z4idheFRtl8bBbdjPknq7BfoF
-    8v15Zq/Zv7i2xMSDL+LUrTBZezRd4bRTGqCm6YJ5EYkhqdcqeZleHCFImguHoq1J
-    Fh0+kObQrTHXw3ZP57a3o1IvyIUA3nNoCBL0QQhwBXaDXOojMKNR+bqB5ve8GS1y
-    Elr0AM/+cJsfaIahNQUgFKx3Eu3GeEOMKYOAG1lycgdQdmTUybLrT3U7vkClTseM
-    xHg1r5En7ALjONIhqRuq3rddYahrP8HXozb3zUy3cJ7P6IeaosuvNzvMXOX9P6HD
-    Ha9urDAJ1wIDAQABoDUwMwYJKoZIhvcNAQkOMSYwJDAiBgNVHREEGzAZggl3b3Js
-    ZC5jb22CDHdoYXRldmVyLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEAS4Ro6h+z52SK
-    YSLCYARpnEu/rmh4jdqndt8naqcNb6uLx9mlKZ2W9on9XDjnSdQD9q+ZP5aZfESw
-    R0+rJhW9ZrNa/g1pt6M24ihclHYDAxYMWxT1z/TXXGM3TmZZ6gfYlNE1kkBuODHa
-    UYsR/1Ht1E1EsmmUimt2n+zQR2K8T9Coa+boaUW/GsTEuz1aaJAkj5ZvTDiIhRG4
-    AOCqFZOLAQmCCNgJnnspD9hDz/Ons085LF5wnYjN4/Nsk5tS6AGs3xjZ3jPoOGGn
-    82WQ9m4dBGoVDZXsobVTaN592JEYwN5iu72zRn7Einb4V4H5y3yD2dD4yWPlt4pk
-    5wFkeYsZEA==
+    MIICcDCCAVgCAQAwDTELMAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+    DwAwggEKAoIBAQCb+ec0zYAYLzk/MDdDJYvzdvEO2ZUrBYM6z1r8NedwpJfxUWqC
+    hvK1cpc9EbQeCwS1eooTIGoNveeCrwL+pWdmf1sh6gz7SsxdN/07nyhSM8M6Xkec
+    +tGrjyi1H/N1afwWXox3WcvBNbxu3Df5RKLDb0yt9aqhmJylbl/tbvgJesXymwmp
+    Rc1vXL0fOedUtuAJ3xQ15M0pgLF8qDn4lySJz25x76pMYPeN5/a7x+SR/jj81kep
+    VaVpuh/2hePV5uwUX3uWoj5sAkrBCifi4NPge0Npd6KeKVvXytLOymH/4+WvV719
+    wCO+MyrkhpdHSakJDTIaQIxsqVeVVKdPLAPJAgMBAAGgHjAcBgkqhkiG9w0BCQcx
+    DwwNY2hhbGxlbmdlIG1lITANBgkqhkiG9w0BAQsFAAOCAQEAMmgeSa8szbjPFD/4
+    vcPBr/vBEROFGgL8mX3o5pF9gpr7nRjhLKBkgJvlRm6Ma3Xvdfc/r5Hp2ZBTA7sZ
+    ZYhyeezGfCQN/Qhda1v+sCwG58IjvGfCSS7Y5tGlEBQ4MDf0Q7PYPSxaNUEBH7vo
+    +M7U+nFuNSmyWlt6SFBSkohZkWoVSGx3KsAO+SAHYZ7JtqsAS/dm7Dflp8KxeDg7
+    wzGBDQRpGF4CpI1VQjGSJQXSEdD+J7mtvBEOD34abRfV6zOUGzOOo3NWE6wNpYgt
+    0A7gVlzSYpdwqjBdvACfXR2r/mu+4KkAvYh8WwCiTcYgGjl2pT1bO4hEmcJ0RSWy
+    /fGD8Q==
     -----END CERTIFICATE REQUEST-----
     """.strip()
 
@@ -151,7 +149,7 @@
 Loading Certificates
 ~~~~~~~~~~~~~~~~~~~~
 
-.. function:: load_pem_x509_certificate(data, backend)
+.. function:: load_pem_x509_certificate(data, backend=None)
 
     .. versionadded:: 0.7
 
@@ -161,7 +159,7 @@
 
     :param bytes data: The PEM encoded certificate data.
 
-    :param backend: A backend supporting the
+    :param backend: An optional backend supporting the
         :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
         interface.
 
@@ -170,12 +168,11 @@
     .. doctest::
 
         >>> from cryptography import x509
-        >>> from cryptography.hazmat.backends import default_backend
-        >>> cert = x509.load_pem_x509_certificate(pem_data, default_backend())
+        >>> cert = x509.load_pem_x509_certificate(pem_data)
         >>> cert.serial_number
         2
 
-.. function:: load_der_x509_certificate(data, backend)
+.. function:: load_der_x509_certificate(data, backend=None)
 
     .. versionadded:: 0.7
 
@@ -185,7 +182,7 @@
 
     :param bytes data: The DER encoded certificate data.
 
-    :param backend: A backend supporting the
+    :param backend: An optional backend supporting the
         :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
         interface.
 
@@ -194,7 +191,7 @@
 Loading Certificate Revocation Lists
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. function:: load_pem_x509_crl(data, backend)
+.. function:: load_pem_x509_crl(data, backend=None)
 
     .. versionadded:: 1.1
 
@@ -204,7 +201,7 @@
 
     :param bytes data: The PEM encoded request data.
 
-    :param backend: A backend supporting the
+    :param backend: An optional backend supporting the
         :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
         interface.
 
@@ -214,13 +211,12 @@
     .. doctest::
 
         >>> from cryptography import x509
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives import hashes
-        >>> crl = x509.load_pem_x509_crl(pem_crl_data, default_backend())
+        >>> crl = x509.load_pem_x509_crl(pem_crl_data)
         >>> isinstance(crl.signature_hash_algorithm, hashes.SHA256)
         True
 
-.. function:: load_der_x509_crl(data, backend)
+.. function:: load_der_x509_crl(data, backend=None)
 
     .. versionadded:: 1.1
 
@@ -229,7 +225,7 @@
 
     :param bytes data: The DER encoded request data.
 
-    :param backend: A backend supporting the
+    :param backend: An optional backend supporting the
         :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
         interface.
 
@@ -239,7 +235,7 @@
 Loading Certificate Signing Requests
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. function:: load_pem_x509_csr(data, backend)
+.. function:: load_pem_x509_csr(data, backend=None)
 
     .. versionadded:: 0.9
 
@@ -250,7 +246,7 @@
 
     :param bytes data: The PEM encoded request data.
 
-    :param backend: A backend supporting the
+    :param backend: An optional backend supporting the
         :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
         interface.
 
@@ -260,13 +256,12 @@
     .. doctest::
 
         >>> from cryptography import x509
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives import hashes
-        >>> csr = x509.load_pem_x509_csr(pem_req_data, default_backend())
-        >>> isinstance(csr.signature_hash_algorithm, hashes.SHA1)
+        >>> csr = x509.load_pem_x509_csr(pem_req_data)
+        >>> isinstance(csr.signature_hash_algorithm, hashes.SHA256)
         True
 
-.. function:: load_der_x509_csr(data, backend)
+.. function:: load_der_x509_csr(data, backend=None)
 
     .. versionadded:: 0.9
 
@@ -275,7 +270,7 @@
 
     :param bytes data: The DER encoded request data.
 
-    :param backend: A backend supporting the
+    :param backend: An optional backend supporting the
         :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
         interface.
 
@@ -335,10 +330,12 @@
 
         The public key associated with the certificate.
 
-        :returns:
-            :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey` or
-            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey` or
-            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
+        :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.ed25519.Ed25519PublicKey` or
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey`
 
         .. doctest::
 
@@ -393,7 +390,10 @@
 
         Returns the
         :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` which
-        was used in signing this certificate.
+        was used in signing this certificate.  Can be ``None`` if signature
+        did not use separate hash
+        (:attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED25519`,
+        :attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED448`).
 
         .. doctest::
 
@@ -429,16 +429,13 @@
         :raises cryptography.x509.UnsupportedGeneralNameType: If an extension
             contains a general name that is not supported.
 
-        :raises UnicodeError: If an extension contains IDNA encoding that is
-            invalid or not compliant with IDNA 2008.
-
         .. doctest::
 
             >>> for ext in cert.extensions:
             ...     print(ext)
             <Extension(oid=<ObjectIdentifier(oid=2.5.29.35, name=authorityKeyIdentifier)>, critical=False, value=<AuthorityKeyIdentifier(key_identifier=b'\xe4}_\xd1\\\x95\x86\x08,\x05\xae\xbeu\xb6e\xa7\xd9]\xa8f', authority_cert_issuer=None, authority_cert_serial_number=None)>)>
             <Extension(oid=<ObjectIdentifier(oid=2.5.29.14, name=subjectKeyIdentifier)>, critical=False, value=<SubjectKeyIdentifier(digest=b'X\x01\x84$\x1b\xbc+R\x94J=\xa5\x10r\x14Q\xf5\xaf:\xc9')>)>
-            <Extension(oid=<ObjectIdentifier(oid=2.5.29.15, name=keyUsage)>, critical=True, value=<KeyUsage(digital_signature=False, content_commitment=False, key_encipherment=False, data_encipherment=False, key_agreement=False, key_cert_sign=True, crl_sign=True, encipher_only=None, decipher_only=None)>)>
+            <Extension(oid=<ObjectIdentifier(oid=2.5.29.15, name=keyUsage)>, critical=True, value=<KeyUsage(digital_signature=False, content_commitment=False, key_encipherment=False, data_encipherment=False, key_agreement=False, key_cert_sign=True, crl_sign=True, encipher_only=False, decipher_only=False)>)>
             <Extension(oid=<ObjectIdentifier(oid=2.5.29.32, name=certificatePolicies)>, critical=False, value=<CertificatePolicies([<PolicyInformation(policy_identifier=<ObjectIdentifier(oid=2.16.840.1.101.3.2.1.48.1, name=Unknown OID)>, policy_qualifiers=None)>])>)>
             <Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name=basicConstraints)>, critical=True, value=<BasicConstraints(ca=True, path_length=None)>)>
 
@@ -474,8 +471,8 @@
 
            >>> from cryptography.hazmat.primitives.serialization import load_pem_public_key
            >>> from cryptography.hazmat.primitives.asymmetric import padding
-           >>> issuer_public_key = load_pem_public_key(pem_issuer_public_key, default_backend())
-           >>> cert_to_check = x509.load_pem_x509_certificate(pem_data_to_check, default_backend())
+           >>> issuer_public_key = load_pem_public_key(pem_issuer_public_key)
+           >>> cert_to_check = x509.load_pem_x509_certificate(pem_data_to_check)
            >>> issuer_public_key.verify(
            ...     cert_to_check.signature,
            ...     cert_to_check.tbs_certificate_bytes,
@@ -551,7 +548,10 @@
 
         Returns the
         :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` which
-        was used in signing this CRL.
+        was used in signing this CRL.  Can be ``None`` if signature
+        did not use separate hash
+        (:attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED25519`,
+        :attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED448`).
 
         .. doctest::
 
@@ -601,7 +601,7 @@
 
         :type: :class:`datetime.datetime`
 
-        A naïve datetime representing when the this CRL was last updated.
+        A naïve datetime representing when this CRL was last updated.
 
         .. doctest::
 
@@ -668,7 +668,6 @@
     .. doctest::
 
         >>> from cryptography import x509
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives import hashes
         >>> from cryptography.hazmat.primitives.asymmetric import rsa
         >>> from cryptography.x509.oid import NameOID
@@ -677,7 +676,6 @@
         >>> private_key = rsa.generate_private_key(
         ...     public_exponent=65537,
         ...     key_size=2048,
-        ...     backend=default_backend()
         ... )
         >>> public_key = private_key.public_key()
         >>> builder = x509.CertificateBuilder()
@@ -702,7 +700,6 @@
         ... )
         >>> certificate = builder.sign(
         ...     private_key=private_key, algorithm=hashes.SHA256(),
-        ...     backend=default_backend()
         ... )
         >>> isinstance(certificate, x509.Certificate)
         True
@@ -727,8 +724,10 @@
 
         :param public_key: The subject's public key. This can be one of
             :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
-            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey` or
-            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
+            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
+            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`,
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey` or
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey`.
 
     .. method:: serial_number(serial_number)
 
@@ -775,21 +774,30 @@
         :param critical: Set to ``True`` if the extension must be understood and
              handled by whoever reads the certificate.
 
-    .. method:: sign(private_key, algorithm, backend)
+    .. method:: sign(private_key, algorithm, backend=None)
 
         Sign the certificate using the CA's private key.
 
         :param private_key: The
             :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`,
-            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey` or
-            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`
+            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`,
+            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`,
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey` or
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
             that will be used to sign the certificate.
 
         :param algorithm: The
             :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` that
-            will be used to generate the signature.
+            will be used to generate the signature. This must be ``None`` if
+            the ``private_key`` is an
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey`
+            or an
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
+            and an instance of a
+            :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+            otherwise.
 
-        :param backend: Backend that will be used to build the certificate.
+        :param backend: An optional backend used to build the certificate.
             Must support the
             :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
             interface.
@@ -808,10 +816,12 @@
 
         The public key associated with the request.
 
-        :returns:
-            :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey` or
-            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey` or
-            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
+        :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.ed25519.Ed25519PublicKey` or
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey`.
 
         .. doctest::
 
@@ -832,12 +842,15 @@
 
         Returns the
         :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` which
-        was used in signing this request.
+        was used in signing this request.  Can be ``None`` if signature
+        did not use separate hash
+        (:attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED25519`,
+        :attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED448`).
 
         .. doctest::
 
             >>> from cryptography.hazmat.primitives import hashes
-            >>> isinstance(csr.signature_hash_algorithm, hashes.SHA1)
+            >>> isinstance(csr.signature_hash_algorithm, hashes.SHA256)
             True
 
     .. attribute:: signature_algorithm_oid
@@ -853,7 +866,7 @@
         .. doctest::
 
             >>> csr.signature_algorithm_oid
-            <ObjectIdentifier(oid=1.2.840.113549.1.1.5, name=sha1WithRSAEncryption)>
+            <ObjectIdentifier(oid=1.2.840.113549.1.1.11, name=sha256WithRSAEncryption)>
 
     .. attribute:: extensions
 
@@ -867,9 +880,17 @@
         :raises cryptography.x509.UnsupportedGeneralNameType: If an extension
             contains a general name that is not supported.
 
-        :raises UnicodeError: If an extension contains IDNA encoding that is
-            invalid or not compliant with IDNA 2008.
+    .. method:: get_attribute_for_oid(oid)
 
+        .. versionadded:: 3.0
+
+        :param oid: An :class:`ObjectIdentifier` instance.
+
+        :returns: The bytes value of the attribute or an exception if not
+            found.
+
+        :raises cryptography.x509.AttributeNotFound: If the request does
+            not have the attribute requested.
 
     .. method:: public_bytes(encoding)
 
@@ -918,7 +939,6 @@
     .. doctest::
 
         >>> from cryptography import x509
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives import hashes
         >>> from cryptography.hazmat.primitives.asymmetric import rsa
         >>> from cryptography.x509.oid import NameOID
@@ -927,7 +947,6 @@
         >>> private_key = rsa.generate_private_key(
         ...     public_exponent=65537,
         ...     key_size=2048,
-        ...     backend=default_backend()
         ... )
         >>> builder = x509.CertificateRevocationListBuilder()
         >>> builder = builder.issuer_name(x509.Name([
@@ -939,11 +958,10 @@
         ...     333
         ... ).revocation_date(
         ...     datetime.datetime.today()
-        ... ).build(default_backend())
+        ... ).build()
         >>> builder = builder.add_revoked_certificate(revoked_cert)
         >>> crl = builder.sign(
         ...     private_key=private_key, algorithm=hashes.SHA256(),
-        ...     backend=default_backend()
         ... )
         >>> len(crl)
         1
@@ -994,21 +1012,30 @@
             obtained from an existing CRL or created with
             :class:`~cryptography.x509.RevokedCertificateBuilder`.
 
-    .. method:: sign(private_key, algorithm, backend)
+    .. method:: sign(private_key, algorithm, backend=None)
 
         Sign this CRL using the CA's private key.
 
         :param private_key: The
             :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`,
-            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey` or
-            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`
+            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`,
+            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`,
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey` or
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
             that will be used to sign the certificate.
 
         :param algorithm: The
             :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` that
             will be used to generate the signature.
+            This must be ``None`` if the ``private_key`` is an
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey`
+            or an
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
+            and an instance of a
+            :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+            otherwise.
 
-        :param backend: Backend that will be used to build the CRL.
+        :param backend: An optional backend used to build the CRL.
             Must support the
             :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
             interface.
@@ -1071,12 +1098,11 @@
     .. doctest::
 
         >>> from cryptography import x509
-        >>> from cryptography.hazmat.backends import default_backend
         >>> import datetime
         >>> builder = x509.RevokedCertificateBuilder()
         >>> builder = builder.revocation_date(datetime.datetime.today())
         >>> builder = builder.serial_number(3333)
-        >>> revoked_certificate = builder.build(default_backend())
+        >>> revoked_certificate = builder.build()
         >>> isinstance(revoked_certificate, x509.RevokedCertificate)
         True
 
@@ -1104,11 +1130,11 @@
         :param critical: Set to ``True`` if the extension must be understood and
              handled.
 
-    .. method:: build(backend)
+    .. method:: build(backend=None)
 
         Create a revoked certificate object using the provided backend.
 
-        :param backend: Backend that will be used to build the revoked
+        :param backend: An optional backend used to build the revoked
             certificate.  Must support the
             :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
             interface.
@@ -1125,14 +1151,12 @@
     .. doctest::
 
         >>> from cryptography import x509
-        >>> from cryptography.hazmat.backends import default_backend
         >>> from cryptography.hazmat.primitives import hashes
         >>> from cryptography.hazmat.primitives.asymmetric import rsa
-        >>> from cryptography.x509.oid import NameOID
+        >>> from cryptography.x509.oid import AttributeOID, NameOID
         >>> private_key = rsa.generate_private_key(
         ...     public_exponent=65537,
         ...     key_size=2048,
-        ...     backend=default_backend()
         ... )
         >>> builder = x509.CertificateSigningRequestBuilder()
         >>> builder = builder.subject_name(x509.Name([
@@ -1141,8 +1165,11 @@
         >>> builder = builder.add_extension(
         ...     x509.BasicConstraints(ca=False, path_length=None), critical=True,
         ... )
+        >>> builder = builder.add_attribute(
+        ...     AttributeOID.CHALLENGE_PASSWORD, b"changeit"
+        ... )
         >>> request = builder.sign(
-        ...     private_key, hashes.SHA256(), default_backend()
+        ...     private_key, hashes.SHA256()
         ... )
         >>> isinstance(request, x509.CertificateSigningRequest)
         True
@@ -1163,17 +1190,29 @@
         :returns: A new
             :class:`~cryptography.x509.CertificateSigningRequestBuilder`.
 
-    .. method:: sign(private_key, algorithm, backend)
+    .. method:: add_attribute(oid, value)
 
-        :param backend: Backend that will be used to sign the request.
+        .. versionadded:: 3.0
+
+        :param oid: An :class:`ObjectIdentifier` instance.
+        :param value: The value of the attribute.
+        :type value: bytes
+        :returns: A new
+            :class:`~cryptography.x509.CertificateSigningRequestBuilder`.
+
+    .. method:: sign(private_key, algorithm, backend=None)
+
+        :param backend: An optional backend used to sign the request.
             Must support the
             :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
             interface.
 
         :param private_key: The
             :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`,
-            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey` or
-            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`
+            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`,
+            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`,
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey` or
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
             that will be used to sign the request.  When the request is
             signed by a certificate authority, the private key's associated
             public key will be stored in the resulting certificate.
@@ -1181,6 +1220,13 @@
         :param algorithm: The
             :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
             that will be used to generate the request signature.
+            This must be ``None`` if the ``private_key`` is an
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey`
+            or an
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
+            and an instance of a
+            :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+            otherwise.
 
         :returns: A new
             :class:`~cryptography.x509.CertificateSigningRequest`.
@@ -1236,11 +1282,11 @@
             >>> cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME)
             [<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value='Good CA')>]
 
-    .. method:: public_bytes(backend)
+    .. method:: public_bytes(backend=None)
 
         .. versionadded:: 1.6
 
-        :param backend: A backend supporting the
+        :param backend: An optional backend supporting the
             :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
             interface.
 
@@ -1348,17 +1394,10 @@
 
     .. versionadded:: 0.9
 
-    .. versionchanged:: 2.1
+    .. versionchanged:: 3.1
 
-    .. warning::
-
-        Starting with version 2.1 :term:`U-label` input is deprecated. If
-        passing an internationalized domain name (IDN) you should first IDNA
-        encode the value and then pass the result as a string. Accessing
-        ``value`` will return the :term:`A-label` encoded form even if you pass
-        a U-label. This breaks backwards compatibility, but only for
-        internationalized domain names.
-
+        :term:`U-label` support has been removed. Encode them to
+        :term:`A-label` before use.
 
     This corresponds to an email address. For example, ``user@example.com``.
 
@@ -1366,6 +1405,8 @@
         internationalized domain name then it must be encoded to an
         :term:`A-label` string before being passed.
 
+    :raises ValueError: If the provided string is not an :term:`A-label`.
+
     .. attribute:: value
 
         :type: :term:`text`
@@ -1374,16 +1415,10 @@
 
     .. versionadded:: 0.9
 
-    .. versionchanged:: 2.1
+    .. versionchanged:: 3.1
 
-    .. warning::
-
-        Starting with version 2.1 :term:`U-label` input is deprecated. If
-        passing an internationalized domain name (IDN) you should first IDNA
-        encode the value and then pass the result as a string. Accessing
-        ``value`` will return the :term:`A-label` encoded form even if you pass
-        a U-label. This breaks backwards compatibility, but only for
-        internationalized domain names.
+        :term:`U-label` support has been removed. Encode them to
+        :term:`A-label` before use.
 
     This corresponds to a domain name. For example, ``cryptography.io``.
 
@@ -1391,6 +1426,8 @@
         name then it must be encoded to an :term:`A-label` string before being
         passed.
 
+    :raises ValueError: If the provided string is not an :term:`A-label`.
+
         :type: :term:`text`
 
     .. attribute:: value
@@ -1411,16 +1448,10 @@
 
     .. versionadded:: 0.9
 
-    .. versionchanged:: 2.1
+    .. versionchanged:: 3.1
 
-    .. warning::
-
-        Starting with version 2.1 :term:`U-label` input is deprecated. If
-        passing an internationalized domain name (IDN) you should first IDNA
-        encode the value and then pass the result as a string. Accessing
-        ``value`` will return the :term:`A-label` encoded form even if you pass
-        a U-label. This breaks backwards compatibility, but only for
-        internationalized domain names.
+        :term:`U-label` support has been removed. Encode them to
+        :term:`A-label` before use.
 
     This corresponds to a uniform resource identifier.  For example,
     ``https://cryptography.io``.
@@ -1429,6 +1460,8 @@
         name then it must be encoded to an :term:`A-label` string before
         being passed.
 
+    :raises ValueError: If the provided string is not an :term:`A-label`.
+
     .. attribute:: value
 
         :type: :term:`text`
@@ -1821,7 +1854,7 @@
 
         :type: A list of :class:`GeneralName` instances or None
 
-        The :class:`Name` of the issuer's issuer.
+        The :class:`GeneralName` (one or multiple) of the issuer's issuer.
 
     .. attribute:: authority_cert_serial_number
 
@@ -1853,17 +1886,16 @@
         section 4.2.1.2.
 
         :param public_key: One of
-            :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`
-            ,
-            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`
-            , or
-            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`.
+            :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.ed25519.Ed25519PublicKey` or
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey`.
 
         .. doctest::
 
             >>> from cryptography import x509
-            >>> from cryptography.hazmat.backends import default_backend
-            >>> issuer_cert = x509.load_pem_x509_certificate(pem_data, default_backend())
+            >>> issuer_cert = x509.load_pem_x509_certificate(pem_data)
             >>> x509.AuthorityKeyIdentifier.from_issuer_public_key(issuer_cert.public_key())
             <AuthorityKeyIdentifier(key_identifier=b'X\x01\x84$\x1b\xbc+R\x94J=\xa5\x10r\x14Q\xf5\xaf:\xc9', authority_cert_issuer=None, authority_cert_serial_number=None)>
 
@@ -1892,10 +1924,9 @@
         .. doctest::
 
             >>> from cryptography import x509
-            >>> from cryptography.hazmat.backends import default_backend
-            >>> issuer_cert = x509.load_pem_x509_certificate(pem_data, default_backend())
-            >>> ski = issuer_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier)
-            >>> x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(ski)
+            >>> issuer_cert = x509.load_pem_x509_certificate(pem_data)
+            >>> ski_ext = issuer_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier)
+            >>> x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(ski_ext.value)
             <AuthorityKeyIdentifier(key_identifier=b'X\x01\x84$\x1b\xbc+R\x94J=\xa5\x10r\x14Q\xf5\xaf:\xc9', authority_cert_issuer=None, authority_cert_serial_number=None)>
 
 .. class:: SubjectKeyIdentifier(digest)
@@ -1931,19 +1962,18 @@
         recommendation in :rfc:`5280` section 4.2.1.2.
 
         :param public_key: One of
-            :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`
-            ,
-            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`
-            , or
-            :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`.
+            :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.ed25519.Ed25519PublicKey` or
+            :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey`.
 
         .. doctest::
 
             >>> from cryptography import x509
-            >>> from cryptography.hazmat.backends import default_backend
-            >>> csr = x509.load_pem_x509_csr(pem_req_data, default_backend())
+            >>> csr = x509.load_pem_x509_csr(pem_req_data)
             >>> x509.SubjectKeyIdentifier.from_public_key(csr.public_key())
-            <SubjectKeyIdentifier(digest=b'\xdb\xaa\xf0\x06\x11\xdbD\xfe\xbf\x93\x03\x8av\x88WP7\xa6\x91\xf7')>
+            <SubjectKeyIdentifier(digest=b'\x8c"\x98\xe2\xb5\xbf]\xe8*2\xf8\xd2\'?\x00\xd2\xc7#\xe4c')>
 
 .. class:: SubjectAlternativeName(general_names)
 
@@ -1976,9 +2006,8 @@
         .. doctest::
 
             >>> from cryptography import x509
-            >>> from cryptography.hazmat.backends import default_backend
             >>> from cryptography.hazmat.primitives import hashes
-            >>> cert = x509.load_pem_x509_certificate(cryptography_cert_pem, default_backend())
+            >>> cert = x509.load_pem_x509_certificate(cryptography_cert_pem)
             >>> # Get the subjectAltName extension from the certificate
             >>> ext = cert.extensions.get_extension_for_oid(ExtensionOID.SUBJECT_ALTERNATIVE_NAME)
             >>> # Get the dNSName entries from the SAN extension
@@ -2057,6 +2086,33 @@
         Returns :attr:`~cryptography.x509.oid.ExtensionOID.PRECERT_POISON`.
 
 
+.. class:: SignedCertificateTimestamps(scts)
+
+    .. versionadded:: 3.0
+
+    This extension contains
+    :class:`~cryptography.x509.certificate_transparency.SignedCertificateTimestamp`
+    instances. These can be used to verify that the certificate is included
+    in a public Certificate Transparency log. This extension is only found
+    in OCSP responses. For SCTs in an X.509 certificate see
+    :class:`~cryptography.x509.PrecertificateSignedCertificateTimestamps`.
+
+    It is an iterable containing one or more
+    :class:`~cryptography.x509.certificate_transparency.SignedCertificateTimestamp`
+    objects.
+
+    :param list scts: A ``list`` of
+        :class:`~cryptography.x509.certificate_transparency.SignedCertificateTimestamp`
+        objects.
+
+    .. attribute:: oid
+
+        :type: :class:`ObjectIdentifier`
+
+        Returns
+        :attr:`~cryptography.x509.oid.ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS`.
+
+
 .. class:: DeltaCRLIndicator(crl_number)
 
     .. versionadded:: 2.1
@@ -2104,6 +2160,29 @@
         :attr:`~cryptography.x509.oid.ExtensionOID.AUTHORITY_INFORMATION_ACCESS`.
 
 
+.. class:: SubjectInformationAccess(descriptions)
+
+    .. versionadded:: 3.0
+
+    The subject information access extension indicates how to access
+    information and services for the subject of the certificate in which
+    the extension appears. When the subject is a CA, information and
+    services may include certificate validation services and CA policy
+    data. When the subject is an end entity, the information describes
+    the type of services offered and how to access them. It is an iterable,
+    containing one or more :class:`~cryptography.x509.AccessDescription`
+    instances.
+
+    :param list descriptions: A list of :class:`AccessDescription` objects.
+
+    .. attribute:: oid
+
+        :type: :class:`ObjectIdentifier`
+
+        Returns
+        :attr:`~cryptography.x509.oid.ExtensionOID.SUBJECT_INFORMATION_ACCESS`.
+
+
 .. class:: AccessDescription(access_method, access_location)
 
     .. versionadded:: 0.9
@@ -2113,16 +2192,23 @@
         :type: :class:`ObjectIdentifier`
 
         The access method defines what the ``access_location`` means. It must
-        be either
+        be
         :attr:`~cryptography.x509.oid.AuthorityInformationAccessOID.OCSP` or
-        :attr:`~cryptography.x509.oid.AuthorityInformationAccessOID.CA_ISSUERS`.
+        :attr:`~cryptography.x509.oid.AuthorityInformationAccessOID.CA_ISSUERS`
+        when used with :class:`~cryptography.x509.AuthorityInformationAccess`
+        or
+        :attr:`~cryptography.x509.oid.SubjectInformationAccessOID.CA_REPOSITORY`
+        when used with :class:`~cryptography.x509.SubjectInformationAccess`.
+
         If it is
         :attr:`~cryptography.x509.oid.AuthorityInformationAccessOID.OCSP`
         the access location will be where to obtain OCSP
         information for the certificate. If it is
         :attr:`~cryptography.x509.oid.AuthorityInformationAccessOID.CA_ISSUERS`
         the access location will provide additional information about the
-        issuing certificate.
+        issuing certificate. Finally, if it is
+        :attr:`~cryptography.x509.oid.SubjectInformationAccessOID.CA_REPOSITORY`
+        the access location will be the location of the CA's repository.
 
     .. attribute:: access_location
 
@@ -2418,7 +2504,9 @@
     .. versionadded:: 1.2
 
     A generic extension class used to hold the raw value of extensions that
-    ``cryptography`` does not know how to parse.
+    ``cryptography`` does not know how to parse. This can also be used when
+    creating new certificates, CRLs, or OCSP requests and responses to encode
+    extensions that ``cryptography`` does not know how to generate.
 
     .. attribute:: oid
 
@@ -2441,6 +2529,18 @@
 
     :param list policies: A list of :class:`PolicyInformation` instances.
 
+    As an example of how ``CertificatePolicies`` might be used, if you wanted
+    to check if a certificated contained the CAB Forum's "domain-validated"
+    policy, you might write code like:
+
+    .. code-block:: python
+
+        def contains_domain_validated(policies):
+            return any(
+                policy.oid.dotted_string == "2.23.140.1.2.1"
+                for policy in policies
+            )
+
     .. attribute:: oid
 
         .. versionadded:: 1.0
@@ -2752,6 +2852,12 @@
 
         Corresponds to the dotted string ``"2.5.4.17"``.
 
+    .. attribute:: UNSTRUCTURED_NAME
+
+        .. versionadded:: 3.0
+
+        Corresponds to the dotted string ``"1.2.840.113549.1.9.2"``.
+
 
 .. class:: SignatureAlgorithmOID
 
@@ -2836,6 +2942,20 @@
         Corresponds to the dotted string ``"2.16.840.1.101.3.4.3.2"``. This is
         a SHA256 digest signed by a DSA key.
 
+    .. attribute:: ED25519
+
+        .. versionadded:: 2.8
+
+        Corresponds to the dotted string ``"1.3.101.112"``. This is a signature
+        using an ed25519 key.
+
+    .. attribute:: ED448
+
+        .. versionadded:: 2.8
+
+        Corresponds to the dotted string ``"1.3.101.113"``. This is a signature
+        using an ed448 key.
+
 
 .. class:: ExtendedKeyUsageOID
 
@@ -2878,7 +2998,12 @@
         .. versionadded:: 2.0
 
         Corresponds to the dotted string ``"2.5.29.37.0"``. This is used to
-        denote that a certificate may be used for _any_ purposes.
+        denote that a certificate may be used for _any_ purposes. However,
+        :rfc:`5280` additionally notes that applications that require the
+        presence of a particular purpose _MAY_ reject certificates that include
+        the ``anyExtendedKeyUsage`` OID but not the particular OID expected for
+        the application. Therefore, the presence of this OID does not mean a
+        given application will accept the certificate for all purposes.
 
 
 .. class:: AuthorityInformationAccessOID
@@ -2898,6 +3023,17 @@
         :class:`~cryptography.x509.AccessDescription` objects.
 
 
+.. class:: SubjectInformationAccessOID
+
+    .. versionadded:: 3.0
+
+    .. attribute:: CA_REPOSITORY
+
+        Corresponds to the dotted string ``"1.3.6.1.5.5.7.48.5"``. Used as the
+        identifier for CA repository data in
+        :class:`~cryptography.x509.AccessDescription` objects.
+
+
 .. class:: CertificatePoliciesOID
 
     .. versionadded:: 1.0
@@ -2975,6 +3111,14 @@
         for the :class:`~cryptography.x509.AuthorityInformationAccess` extension
         type.
 
+    .. attribute:: SUBJECT_INFORMATION_ACCESS
+
+        .. versionadded:: 3.0
+
+        Corresponds to the dotted string ``"1.3.6.1.5.5.7.1.11"``. The
+        identifier for the :class:`~cryptography.x509.SubjectInformationAccess`
+        extension type.
+
     .. attribute:: INHIBIT_ANY_POLICY
 
         Corresponds to the dotted string ``"2.5.29.54"``. The identifier
@@ -3018,6 +3162,12 @@
 
         Corresponds to the dotted string ``"1.3.6.1.4.1.11129.2.4.3"``.
 
+    .. attribute:: SIGNED_CERTIFICATE_TIMESTAMPS
+
+        .. versionadded:: 3.0
+
+        Corresponds to the dotted string ``"1.3.6.1.4.1.11129.2.4.5"``.
+
     .. attribute:: POLICY_CONSTRAINTS
 
         Corresponds to the dotted string ``"2.5.29.36"``. The identifier for the
@@ -3060,6 +3210,19 @@
 
         Corresponds to the dotted string ``"1.3.6.1.5.5.7.48.1.2"``.
 
+
+.. class:: AttributeOID
+
+    .. versionadded:: 3.0
+
+    .. attribute:: CHALLENGE_PASSWORD
+
+        Corresponds to the dotted string ``"1.2.840.113549.1.9.7"``.
+
+    .. attribute:: UNSTRUCTURED_NAME
+
+        Corresponds to the dotted string ``"1.2.840.113549.1.9.2"``.
+
 Helper Functions
 ~~~~~~~~~~~~~~~~
 .. currentmodule:: cryptography.x509
@@ -3107,6 +3270,18 @@
 
         Returns the OID.
 
+.. class:: AttributeNotFound
+
+    This is raised when calling
+    :meth:`CertificateSigningRequest.get_attribute_for_oid` with
+    an attribute OID that is not present in the request.
+
+    .. attribute:: oid
+
+        :type: :class:`ObjectIdentifier`
+
+        Returns the OID.
+
 .. class:: UnsupportedGeneralNameType
 
     This is raised when a certificate contains an unsupported general name
diff --git a/docs/x509/tutorial.rst b/docs/x509/tutorial.rst
index d34b350..f5ca416 100644
--- a/docs/x509/tutorial.rst
+++ b/docs/x509/tutorial.rst
@@ -27,14 +27,12 @@
 
 .. code-block:: pycon
 
-    >>> from cryptography.hazmat.backends import default_backend
     >>> from cryptography.hazmat.primitives import serialization
     >>> from cryptography.hazmat.primitives.asymmetric import rsa
     >>> # Generate our key
     >>> key = rsa.generate_private_key(
     ...     public_exponent=65537,
     ...     key_size=2048,
-    ...     backend=default_backend()
     ... )
     >>> # Write our key to disk for safe keeping
     >>> with open("path/to/store/key.pem", "wb") as f:
@@ -63,7 +61,7 @@
     >>> csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([
     ...     # Provide various details about who we are.
     ...     x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
-    ...     x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"CA"),
+    ...     x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"California"),
     ...     x509.NameAttribute(NameOID.LOCALITY_NAME, u"San Francisco"),
     ...     x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"My Company"),
     ...     x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"),
@@ -76,7 +74,7 @@
     ...     ]),
     ...     critical=False,
     ... # Sign the CSR with our private key.
-    ... ).sign(key, hashes.SHA256(), default_backend())
+    ... ).sign(key, hashes.SHA256())
     >>> # Write our CSR out to disk.
     >>> with open("path/to/csr.pem", "wb") as f:
     ...     f.write(csr.public_bytes(serialization.Encoding.PEM))
@@ -105,7 +103,6 @@
     >>> key = rsa.generate_private_key(
     ...     public_exponent=65537,
     ...     key_size=2048,
-    ...     backend=default_backend()
     ... )
     >>> # Write our key to disk for safe keeping
     >>> with open("path/to/store/key.pem", "wb") as f:
@@ -123,7 +120,7 @@
     >>> # subject and issuer are always the same.
     >>> subject = issuer = x509.Name([
     ...     x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
-    ...     x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"CA"),
+    ...     x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"California"),
     ...     x509.NameAttribute(NameOID.LOCALITY_NAME, u"San Francisco"),
     ...     x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"My Company"),
     ...     x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"),
@@ -145,7 +142,7 @@
     ...     x509.SubjectAlternativeName([x509.DNSName(u"localhost")]),
     ...     critical=False,
     ... # Sign our certificate with our private key
-    ... ).sign(key, hashes.SHA256(), default_backend())
+    ... ).sign(key, hashes.SHA256())
     >>> # Write our certificate out to disk.
     >>> with open("path/to/certificate.pem", "wb") as f:
     ...     f.write(cert.public_bytes(serialization.Encoding.PEM))
diff --git a/pyproject.toml b/pyproject.toml
index 7d64f99..667f29e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,7 +1,14 @@
 [build-system]
-# Must be kept in sync with `setup_requirements` in `setup.py`
 requires = [
-    "setuptools>=18.5",
+    # The minimum setuptools version is specific to the PEP 517 backend,
+    # and may be stricter than the version required in `setup.py`
+    "setuptools>=40.6.0",
     "wheel",
-    "cffi>=1.8,!=1.11.3; python_implementation != 'PyPy'",
+    # Must be kept in sync with the `setup_requirements` in `setup.py`
+    "cffi>=1.12; platform_python_implementation != 'PyPy'",
 ]
+build-backend = "setuptools.build_meta"
+
+[tool.black]
+line-length = 79
+target-version = ["py27"]
diff --git a/release.py b/release.py
index d7c18d1..5f3f251 100644
--- a/release.py
+++ b/release.py
@@ -7,122 +7,136 @@
 import getpass
 import glob
 import io
+import json
 import os
 import subprocess
 import time
+import zipfile
 
 import click
 
-from clint.textui.progress import Bar as ProgressBar
-
 import requests
 
 
-JENKINS_URL = (
-    "https://ci.cryptography.io/job/cryptography-support-jobs/"
-    "job/wheel-builder"
-)
-
-
 def run(*args, **kwargs):
     print("[running] {0}".format(list(args)))
     subprocess.check_call(list(args), **kwargs)
 
 
-def wait_for_build_completed(session):
-    # Wait 20 seconds before actually checking if the build is complete, to
-    # ensure that it had time to really start.
-    time.sleep(20)
+def wait_for_build_complete_github_actions(session, token, run_url):
     while True:
         response = session.get(
-            "{0}/lastBuild/api/json/".format(JENKINS_URL),
+            run_url,
             headers={
-                "Accept": "application/json",
-            }
+                "Content-Type": "application/json",
+                "Authorization": "token {}".format(token),
+            },
         )
         response.raise_for_status()
-        if not response.json()["building"]:
-            assert response.json()["result"] == "SUCCESS"
+        if response.json()["conclusion"] is not None:
             break
-        time.sleep(0.1)
+        time.sleep(3)
 
 
-def download_artifacts(session):
+def download_artifacts_github_actions(session, token, run_url):
     response = session.get(
-        "{0}/lastBuild/api/json/".format(JENKINS_URL),
+        run_url,
         headers={
-            "Accept": "application/json"
-        }
+            "Content-Type": "application/json",
+            "Authorization": "token {}".format(token),
+        },
     )
     response.raise_for_status()
-    json_response = response.json()
-    assert not json_response["building"]
-    assert json_response["result"] == "SUCCESS"
 
+    response = session.get(
+        response.json()["artifacts_url"],
+        headers={
+            "Content-Type": "application/json",
+            "Authorization": "token {}".format(token),
+        },
+    )
+    response.raise_for_status()
     paths = []
-
-    for artifact in json_response["artifacts"]:
+    for artifact in response.json()["artifacts"]:
         response = session.get(
-            "{0}artifact/{1}".format(
-                json_response["url"], artifact["relativePath"]
-            ), stream=True
+            artifact["archive_download_url"],
+            headers={
+                "Content-Type": "application/json",
+                "Authorization": "token {}".format(token),
+            },
         )
-        assert response.headers["content-length"]
-        print("Downloading {0}".format(artifact["fileName"]))
-        bar = ProgressBar(
-            expected_size=int(response.headers["content-length"]),
-            filled_char="="
-        )
-        content = io.BytesIO()
-        for data in response.iter_content(chunk_size=8192):
-            content.write(data)
-            bar.show(content.tell())
-        assert bar.expected_size == content.tell()
-        bar.done()
-        out_path = os.path.join(
-            os.path.dirname(__file__),
-            "dist",
-            artifact["fileName"],
-        )
-        with open(out_path, "wb") as f:
-            f.write(content.getvalue())
-        paths.append(out_path)
+        with zipfile.ZipFile(io.BytesIO(response.content)) as z:
+            for name in z.namelist():
+                if not name.endswith(".whl"):
+                    continue
+                p = z.open(name)
+                out_path = os.path.join(
+                    os.path.dirname(__file__),
+                    "dist",
+                    os.path.basename(name),
+                )
+                with open(out_path, "wb") as f:
+                    f.write(p.read())
+                paths.append(out_path)
     return paths
 
 
+def build_github_actions_wheels(token, version):
+    session = requests.Session()
+
+    response = session.post(
+        "https://api.github.com/repos/pyca/cryptography/actions/workflows/"
+        "wheel-builder.yml/dispatches",
+        headers={
+            "Content-Type": "application/json",
+            "Accept": "application/vnd.github.v3+json",
+            "Authorization": "token {}".format(token),
+        },
+        data=json.dumps({"ref": "master", "inputs": {"version": version}}),
+    )
+    response.raise_for_status()
+
+    # Give it a few seconds for the run to kick off.
+    time.sleep(5)
+    response = session.get(
+        (
+            "https://api.github.com/repos/pyca/cryptography/actions/workflows/"
+            "wheel-builder.yml/runs?event=workflow_dispatch"
+        ),
+        headers={
+            "Content-Type": "application/json",
+            "Authorization": "token {}".format(token),
+        },
+    )
+    response.raise_for_status()
+    run_url = response.json()["workflow_runs"][0]["url"]
+    wait_for_build_complete_github_actions(session, token, run_url)
+    return download_artifacts_github_actions(session, token, run_url)
+
+
 @click.command()
 @click.argument("version")
 def release(version):
     """
     ``version`` should be a string like '0.4' or '1.0'.
     """
+    github_token = getpass.getpass("Github person access token: ")
+
     run("git", "tag", "-s", version, "-m", "{0} release".format(version))
     run("git", "push", "--tags")
 
     run("python", "setup.py", "sdist")
     run("python", "setup.py", "sdist", "bdist_wheel", cwd="vectors/")
 
-    packages = (
-        glob.glob("dist/cryptography-{0}*".format(version)) +
-        glob.glob("vectors/dist/cryptography_vectors-{0}*".format(version))
+    packages = glob.glob("dist/cryptography-{0}*".format(version)) + glob.glob(
+        "vectors/dist/cryptography_vectors-{0}*".format(version)
     )
     run("twine", "upload", "-s", *packages)
 
-    session = requests.Session()
-
-    token = getpass.getpass("Input the Jenkins token: ")
-    response = session.get(
-        "{0}/buildWithParameters".format(JENKINS_URL),
-        params={
-            "token": token,
-            "BUILD_VERSION": version,
-            "cause": "Building wheels for {0}".format(version)
-        }
+    github_actions_wheel_paths = build_github_actions_wheels(
+        github_token, version
     )
-    response.raise_for_status()
-    wait_for_build_completed(session)
-    paths = download_artifacts(session)
-    run("twine", "upload", *paths)
+    run("twine", "upload", *github_actions_wheel_paths)
 
 
 if __name__ == "__main__":
diff --git a/setup.py b/setup.py
index 5b29d32..4ebbc1b 100644
--- a/setup.py
+++ b/setup.py
@@ -8,27 +8,11 @@
 
 import os
 import platform
-import subprocess
 import sys
-from distutils.command.build import build
 
-import pkg_resources
-
-import setuptools
 from setuptools import find_packages, setup
-from setuptools.command.install import install
-from setuptools.command.test import test
 
 
-if (
-    pkg_resources.parse_version(setuptools.__version__) <
-    pkg_resources.parse_version("18.5")
-):
-    raise RuntimeError(
-        "cryptography requires setuptools 18.5 or newer, please upgrade to a "
-        "newer version of setuptools"
-    )
-
 base_dir = os.path.dirname(__file__)
 src_dir = os.path.join(base_dir, "src")
 
@@ -38,13 +22,11 @@
 
 about = {}
 with open(os.path.join(src_dir, "cryptography", "__about__.py")) as f:
-    exec(f.read(), about)
+    exec (f.read(), about)
 
 
-VECTORS_DEPENDENCY = "cryptography_vectors=={0}".format(about['__version__'])
-
 # `setup_requirements` must be kept in sync with `pyproject.toml`
-setup_requirements = ["cffi>=1.8,!=1.11.3"]
+setup_requirements = ["cffi>=1.12"]
 
 if platform.python_implementation() == "PyPy":
     if sys.pypy_version_info < (5, 4):
@@ -53,273 +35,112 @@
             "PyPy to use this library."
         )
 
-test_requirements = [
-    "pytest>=3.6.0,!=3.9.0,!=3.9.1,!=3.9.2",
-    "pretend",
-    "iso8601",
-    "pytz",
-    "hypothesis>=1.11.4,!=3.79.2",
-]
-
-
-# If there's no vectors locally that probably means we are in a tarball and
-# need to go and get the matching vectors package from PyPi
-if not os.path.exists(os.path.join(base_dir, "vectors/setup.py")):
-    test_requirements.append(VECTORS_DEPENDENCY)
-
-
-class PyTest(test):
-    def finalize_options(self):
-        test.finalize_options(self)
-        self.test_args = []
-        self.test_suite = True
-
-        # This means there's a vectors/ folder with the package in here.
-        # cd into it, install the vectors package and then refresh sys.path
-        if VECTORS_DEPENDENCY not in test_requirements:
-            subprocess.check_call(
-                [sys.executable, "setup.py", "install"], cwd="vectors"
-            )
-            pkg_resources.get_distribution("cryptography_vectors").activate()
-
-    def run_tests(self):
-        # Import here because in module scope the eggs are not loaded.
-        import pytest
-        test_args = [os.path.join(base_dir, "tests")]
-        errno = pytest.main(test_args)
-        sys.exit(errno)
-
-
-def keywords_with_side_effects(argv):
-    """
-    Get a dictionary with setup keywords that (can) have side effects.
-
-    :param argv: A list of strings with command line arguments.
-    :returns: A dictionary with keyword arguments for the ``setup()`` function.
-
-    This setup.py script uses the setuptools 'setup_requires' feature because
-    this is required by the cffi package to compile extension modules. The
-    purpose of ``keywords_with_side_effects()`` is to avoid triggering the cffi
-    build process as a result of setup.py invocations that don't need the cffi
-    module to be built (setup.py serves the dual purpose of exposing package
-    metadata).
-
-    All of the options listed by ``python setup.py --help`` that print
-    information should be recognized here. The commands ``clean``,
-    ``egg_info``, ``register``, ``sdist`` and ``upload`` are also recognized.
-    Any combination of these options and commands is also supported.
-
-    This function was originally based on the `setup.py script`_ of SciPy (see
-    also the discussion in `pip issue #25`_).
-
-    .. _pip issue #25: https://github.com/pypa/pip/issues/25
-    .. _setup.py script: https://github.com/scipy/scipy/blob/master/setup.py
-    """
-    no_setup_requires_arguments = (
-        '-h', '--help',
-        '-n', '--dry-run',
-        '-q', '--quiet',
-        '-v', '--verbose',
-        '-V', '--version',
-        '--author',
-        '--author-email',
-        '--classifiers',
-        '--contact',
-        '--contact-email',
-        '--description',
-        '--egg-base',
-        '--fullname',
-        '--help-commands',
-        '--keywords',
-        '--licence',
-        '--license',
-        '--long-description',
-        '--maintainer',
-        '--maintainer-email',
-        '--name',
-        '--no-user-cfg',
-        '--obsoletes',
-        '--platforms',
-        '--provides',
-        '--requires',
-        '--url',
-        'clean',
-        'egg_info',
-        'register',
-        'sdist',
-        'upload',
-    )
-
-    def is_short_option(argument):
-        """Check whether a command line argument is a short option."""
-        return len(argument) >= 2 and argument[0] == '-' and argument[1] != '-'
-
-    def expand_short_options(argument):
-        """Expand combined short options into canonical short options."""
-        return ('-' + char for char in argument[1:])
-
-    def argument_without_setup_requirements(argv, i):
-        """Check whether a command line argument needs setup requirements."""
-        if argv[i] in no_setup_requires_arguments:
-            # Simple case: An argument which is either an option or a command
-            # which doesn't need setup requirements.
-            return True
-        elif (is_short_option(argv[i]) and
-              all(option in no_setup_requires_arguments
-                  for option in expand_short_options(argv[i]))):
-            # Not so simple case: Combined short options none of which need
-            # setup requirements.
-            return True
-        elif argv[i - 1:i] == ['--egg-base']:
-            # Tricky case: --egg-info takes an argument which should not make
-            # us use setup_requires (defeating the purpose of this code).
-            return True
-        else:
-            return False
-
-    if all(argument_without_setup_requirements(argv, i)
-           for i in range(1, len(argv))):
-        return {
-            "cmdclass": {
-                "build": DummyBuild,
-                "install": DummyInstall,
-                "test": DummyPyTest,
-            }
-        }
-    else:
-        cffi_modules = [
-            "src/_cffi_src/build_openssl.py:ffi",
-            "src/_cffi_src/build_constant_time.py:ffi",
-            "src/_cffi_src/build_padding.py:ffi",
-        ]
-
-        return {
-            "setup_requires": setup_requirements,
-            "cmdclass": {
-                "test": PyTest,
-            },
-            "cffi_modules": cffi_modules
-        }
-
-
-setup_requires_error = ("Requested setup command that needs 'setup_requires' "
-                        "while command line arguments implied a side effect "
-                        "free command or option.")
-
-
-class DummyBuild(build):
-    """
-    This class makes it very obvious when ``keywords_with_side_effects()`` has
-    incorrectly interpreted the command line arguments to ``setup.py build`` as
-    one of the 'side effect free' commands or options.
-    """
-
-    def run(self):
-        raise RuntimeError(setup_requires_error)
-
-
-class DummyInstall(install):
-    """
-    This class makes it very obvious when ``keywords_with_side_effects()`` has
-    incorrectly interpreted the command line arguments to ``setup.py install``
-    as one of the 'side effect free' commands or options.
-    """
-
-    def run(self):
-        raise RuntimeError(setup_requires_error)
-
-
-class DummyPyTest(test):
-    """
-    This class makes it very obvious when ``keywords_with_side_effects()`` has
-    incorrectly interpreted the command line arguments to ``setup.py test`` as
-    one of the 'side effect free' commands or options.
-    """
-
-    def run_tests(self):
-        raise RuntimeError(setup_requires_error)
-
 
 with open(os.path.join(base_dir, "README.rst")) as f:
     long_description = f.read()
 
 
-setup(
-    name=about["__title__"],
-    version=about["__version__"],
-
-    description=about["__summary__"],
-    long_description=long_description,
-    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 :: 2",
-        "Programming Language :: Python :: 2.7",
-        "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.4",
-        "Programming Language :: Python :: 3.5",
-        "Programming Language :: Python :: 3.6",
-        "Programming Language :: Python :: 3.7",
-        "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='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*',
-
-    install_requires=[
-        "asn1crypto >= 0.21.0",
-        "six >= 1.4.1",
-    ] + setup_requirements,
-    tests_require=test_requirements,
-    extras_require={
-        ":python_version < '3'": ["enum34", "ipaddress"],
-
-        "test": test_requirements,
-        "docs": [
-            "sphinx >= 1.6.5,!=1.8.0",
-            "sphinx_rtd_theme",
+try:
+    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 :: 2",
+            "Programming Language :: Python :: 2.7",
+            "Programming Language :: Python :: 3",
+            "Programming Language :: Python :: 3.6",
+            "Programming Language :: Python :: 3.7",
+            "Programming Language :: Python :: 3.8",
+            "Programming Language :: Python :: 3.9",
+            "Programming Language :: Python :: Implementation :: CPython",
+            "Programming Language :: Python :: Implementation :: PyPy",
+            "Topic :: Security :: Cryptography",
         ],
-        "docstest": [
-            "doc8",
-            "pyenchant >= 1.6.11",
-            "twine >= 1.12.0",
-            "sphinxcontrib-spelling >= 4.0.1",
+        package_dir={"": "src"},
+        packages=find_packages(
+            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.*"
+        ),
+        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",
+                "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",
+            ],
+            "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",
+            "src/_cffi_src/build_padding.py:ffi",
         ],
-        "pep8test": [
-            "flake8",
-            "flake8-import-order",
-            "pep8-naming",
-        ],
-        # This extra is for the U-label support that was deprecated in
-        # cryptography 2.1. If you need this deprecated path install with
-        # pip install cryptography[idna]
-        "idna": [
-            "idna >= 2.1",
-        ]
-    },
-
-    # for cffi
-    zip_safe=False,
-    ext_package="cryptography.hazmat.bindings",
-    **keywords_with_side_effects(sys.argv)
-)
+    )
+except:  # noqa: E722
+    # Note: This is a bare exception that re-raises so that we don't interfere
+    # with anything the installation machinery might want to do. Because we
+    # print this for any exception this msg can appear (e.g. in verbose logs)
+    # even if there's no failure. For example, SetupRequirementsError is raised
+    # 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.
+    print(
+        """
+    =============================DEBUG ASSISTANCE=============================
+    If you are seeing a compilation error please try the following steps to
+    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
+       instructions for your platform.
+    3) Check our frequently asked questions for more information:
+       https://cryptography.io/en/latest/faq.html
+    =============================DEBUG ASSISTANCE=============================
+    """
+    )
+    raise
diff --git a/src/_cffi_src/build_constant_time.py b/src/_cffi_src/build_constant_time.py
deleted file mode 100644
index 7a11f7b..0000000
--- a/src/_cffi_src/build_constant_time.py
+++ /dev/null
@@ -1,27 +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.
-
-from __future__ import absolute_import, division, print_function
-
-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/constant_time.h"
-)) as f:
-    types = f.read()
-
-with open(os.path.join(
-    os.path.dirname(__file__), "hazmat_src/constant_time.c"
-)) as f:
-    functions = f.read()
-
-ffi = build_ffi(
-    module_name="_constant_time",
-    cdef_source=types,
-    verify_source=functions,
-    extra_link_args=extra_link_args(compiler_type()),
-)
diff --git a/src/_cffi_src/build_openssl.py b/src/_cffi_src/build_openssl.py
index 456b869..4380c33 100644
--- a/src/_cffi_src/build_openssl.py
+++ b/src/_cffi_src/build_openssl.py
@@ -6,9 +6,14 @@
 
 import os
 import sys
+from distutils import dist
+from distutils.ccompiler import get_default_compiler
+from distutils.command.config import config
 
 from _cffi_src.utils import (
-    build_ffi_for_binding, compiler_type, extra_link_args
+    build_ffi_for_binding,
+    compiler_type,
+    extra_link_args,
 )
 
 
@@ -17,23 +22,28 @@
         return []
     # OpenSSL goes by a different library name on different operating systems.
     if platform == "win32" and compiler_type() == "msvc":
-        windows_link_legacy_openssl = os.environ.get(
-            "CRYPTOGRAPHY_WINDOWS_LINK_LEGACY_OPENSSL", None
-        )
-        if windows_link_legacy_openssl is None:
-            # Link against the 1.1.0 names
-            libs = ["libssl", "libcrypto"]
-        else:
-            # Link against the 1.0.2 and lower names
-            libs = ["libeay32", "ssleay32"]
-        return libs + ["advapi32", "crypt32", "gdi32", "user32", "ws2_32"]
+        return [
+            "libssl",
+            "libcrypto",
+            "advapi32",
+            "crypt32",
+            "gdi32",
+            "user32",
+            "ws2_32",
+        ]
     else:
         # darwin, linux, mingw all use this path
         # In some circumstances, the order in which these libs are
         # specified on the linker command-line is significant;
         # libssl must come before libcrypto
         # (https://marc.info/?l=openssl-users&m=135361825921871)
-        return ["ssl", "crypto"]
+        # -lpthread required due to usage of pthread an potential
+        # existance of a static part containing e.g. pthread_atfork
+        # (https://github.com/pyca/cryptography/issues/5084)
+        if sys.platform == "zos":
+            return ["ssl", "crypto"]
+        else:
+            return ["ssl", "crypto", "pthread"]
 
 
 def _extra_compile_args(platform):
@@ -41,12 +51,24 @@
     We set -Wconversion args here so that we only do Wconversion checks on the
     code we're compiling and not on cffi itself (as passing -Wconversion in
     CFLAGS would do). We set no error on sign conversion because some
-    function signatures in OpenSSL have changed from long -> unsigned long
-    in the past. Since that isn't a precision issue we don't care.
-    When we drop support for CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 we can
-    revisit this.
+    function signatures in LibreSSL differ from OpenSSL have changed on long
+    vs. unsigned long in the past. Since that isn't a precision issue we don't
+    care.
     """
-    if platform not in ["win32", "hp-ux11", "sunos5"]:
+    # make sure the compiler used supports the flags to be added
+    is_gcc = False
+    if get_default_compiler() == "unix":
+        d = dist.Distribution()
+        cmd = config(d)
+        cmd._check_compiler()
+        is_gcc = (
+            "gcc" in cmd.compiler.compiler[0]
+            or "clang" in cmd.compiler.compiler[0]
+        )
+    if is_gcc or not (
+        platform in ["win32", "hp-ux11", "sunos5"]
+        or platform.startswith("aix")
+    ):
         return ["-Wconversion", "-Wno-error=sign-conversion"]
     else:
         return []
@@ -58,7 +80,6 @@
     modules=[
         # This goes first so we can define some cryptography-wide symbols.
         "cryptography",
-
         "aes",
         "asn1",
         "bignum",
@@ -95,13 +116,6 @@
         "callbacks",
     ],
     libraries=_get_openssl_libraries(sys.platform),
-    # These args are passed here so that we only do Wconversion checks on the
-    # code we're compiling and not on cffi itself (as passing -Wconversion in
-    # CFLAGS would do). We set no error on sign convesrion because some
-    # function signatures in OpenSSL have changed from long -> unsigned long
-    # in the past. Since that isn't a precision issue we don't care.
-    # When we drop support for CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 we can
-    # revisit this.
     extra_compile_args=_extra_compile_args(sys.platform),
     extra_link_args=extra_link_args(compiler_type()),
 )
diff --git a/src/_cffi_src/build_padding.py b/src/_cffi_src/build_padding.py
index 4c5096a..207f4a6 100644
--- a/src/_cffi_src/build_padding.py
+++ b/src/_cffi_src/build_padding.py
@@ -9,14 +9,14 @@
 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:
+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:
+with open(
+    os.path.join(os.path.dirname(__file__), "hazmat_src/padding.c")
+) as f:
     functions = f.read()
 
 ffi = build_ffi(
diff --git a/src/_cffi_src/hazmat_src/constant_time.c b/src/_cffi_src/hazmat_src/constant_time.c
deleted file mode 100644
index 0a48fe8..0000000
--- a/src/_cffi_src/hazmat_src/constant_time.c
+++ /dev/null
@@ -1,22 +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_constant_time_bytes_eq(uint8_t *a, size_t len_a,
-                                            uint8_t *b, size_t len_b) {
-    size_t i = 0;
-    uint8_t mismatch = 0;
-    if (len_a != len_b) {
-        return 0;
-    }
-    for (i = 0; i < len_a; i++) {
-        mismatch |= a[i] ^ b[i];
-    }
-
-    /* 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 */
-    return (mismatch & 1) == 0;
-}
diff --git a/src/_cffi_src/hazmat_src/constant_time.h b/src/_cffi_src/hazmat_src/constant_time.h
deleted file mode 100644
index 593479f..0000000
--- a/src/_cffi_src/hazmat_src/constant_time.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_constant_time_bytes_eq(uint8_t *, size_t, uint8_t *,
-                                            size_t);
diff --git a/src/_cffi_src/openssl/aes.py b/src/_cffi_src/openssl/aes.py
index 028c92c..25ef3ec 100644
--- a/src/_cffi_src/openssl/aes.py
+++ b/src/_cffi_src/openssl/aes.py
@@ -9,18 +9,10 @@
 """
 
 TYPES = """
-static const int Cryptography_HAS_AES_WRAP;
-
-struct aes_key_st {
-    ...;
-};
-typedef struct aes_key_st AES_KEY;
+typedef ... AES_KEY;
 """
 
 FUNCTIONS = """
-int AES_set_encrypt_key(const unsigned char *, const int, AES_KEY *);
-int AES_set_decrypt_key(const unsigned char *, const int, AES_KEY *);
-
 int AES_wrap_key(AES_KEY *, const unsigned char *, unsigned char *,
                  const unsigned char *, unsigned int);
 int AES_unwrap_key(AES_KEY *, const unsigned char *, unsigned char *,
@@ -28,5 +20,4 @@
 """
 
 CUSTOMIZATIONS = """
-static const long Cryptography_HAS_AES_WRAP = 1;
 """
diff --git a/src/_cffi_src/openssl/asn1.py b/src/_cffi_src/openssl/asn1.py
index 82bf797..da55b67 100644
--- a/src/_cffi_src/openssl/asn1.py
+++ b/src/_cffi_src/openssl/asn1.py
@@ -27,7 +27,10 @@
 typedef ... ASN1_OBJECT;
 typedef struct asn1_string_st ASN1_STRING;
 typedef struct asn1_string_st ASN1_UTF8STRING;
-typedef ... ASN1_TYPE;
+typedef struct {
+    int type;
+    ...;
+} ASN1_TYPE;
 typedef ... ASN1_GENERALIZEDTIME;
 typedef ... ASN1_ENUMERATED;
 typedef ... ASN1_NULL;
@@ -59,7 +62,6 @@
 /*  ASN1 TIME */
 ASN1_TIME *ASN1_TIME_new(void);
 void ASN1_TIME_free(ASN1_TIME *);
-ASN1_TIME *ASN1_TIME_set(ASN1_TIME *, time_t);
 int ASN1_TIME_set_string(ASN1_TIME *, const char *);
 
 /*  ASN1 GENERALIZEDTIME */
diff --git a/src/_cffi_src/openssl/bignum.py b/src/_cffi_src/openssl/bignum.py
index a352f5a..7510183 100644
--- a/src/_cffi_src/openssl/bignum.py
+++ b/src/_cffi_src/openssl/bignum.py
@@ -52,6 +52,7 @@
 int BN_num_bits(const BIGNUM *);
 
 int BN_cmp(const BIGNUM *, const BIGNUM *);
+int BN_is_negative(const BIGNUM *);
 int BN_add(BIGNUM *, const BIGNUM *, const BIGNUM *);
 int BN_sub(BIGNUM *, const BIGNUM *, const BIGNUM *);
 int BN_nnmod(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
diff --git a/src/_cffi_src/openssl/bio.py b/src/_cffi_src/openssl/bio.py
index d65775a..52d57c6 100644
--- a/src/_cffi_src/openssl/bio.py
+++ b/src/_cffi_src/openssl/bio.py
@@ -15,6 +15,7 @@
 
 FUNCTIONS = """
 int BIO_free(BIO *);
+void BIO_free_all(BIO *);
 BIO *BIO_new_file(const char *, const char *);
 BIO *BIO_new_dgram(int, int);
 size_t BIO_ctrl_pending(BIO *);
@@ -40,10 +41,4 @@
 """
 
 CUSTOMIZATIONS = """
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-int BIO_up_ref(BIO *b) {
-    CRYPTO_add(&b->references, 1, CRYPTO_LOCK_BIO);
-    return 1;
-}
-#endif
 """
diff --git a/src/_cffi_src/openssl/callbacks.py b/src/_cffi_src/openssl/callbacks.py
index 75c6201..19301b9 100644
--- a/src/_cffi_src/openssl/callbacks.py
+++ b/src/_cffi_src/openssl/callbacks.py
@@ -5,21 +5,7 @@
 from __future__ import absolute_import, division, print_function
 
 INCLUDES = """
-#include <openssl/ssl.h>
-#include <openssl/x509.h>
-#include <openssl/x509_vfy.h>
-#include <openssl/crypto.h>
-
-#ifdef _WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
-#include <Wincrypt.h>
-#include <Winsock2.h>
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#include <pthread.h>
-#endif
+#include <string.h>
 """
 
 TYPES = """
@@ -33,112 +19,10 @@
 """
 
 FUNCTIONS = """
-int Cryptography_setup_ssl_threads(void);
 int Cryptography_pem_password_cb(char *, int, int, void *);
 """
 
 CUSTOMIZATIONS = """
-/* This code is derived from the locking code found in the Python _ssl module's
-   locking callback for OpenSSL.
-
-   Copyright 2001-2016 Python Software Foundation; All Rights Reserved.
-
-   It has been subsequently modified to use cross platform locking without
-   using CPython APIs by Armin Rigo of the PyPy project.
-*/
-
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
-#ifdef _WIN32
-typedef CRITICAL_SECTION Cryptography_mutex;
-static __inline void cryptography_mutex_init(Cryptography_mutex *mutex) {
-    InitializeCriticalSection(mutex);
-}
-static __inline void cryptography_mutex_lock(Cryptography_mutex *mutex) {
-    EnterCriticalSection(mutex);
-}
-static __inline void cryptography_mutex_unlock(Cryptography_mutex *mutex) {
-    LeaveCriticalSection(mutex);
-}
-#else
-typedef pthread_mutex_t Cryptography_mutex;
-#define ASSERT_STATUS(call)                                             \
-    if ((call) != 0) {                                                  \
-        perror("Fatal error in callback initialization: " #call);       \
-        abort();                                                        \
-    }
-static inline void cryptography_mutex_init(Cryptography_mutex *mutex) {
-#if !defined(pthread_mutexattr_default)
-#  define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL)
-#endif
-    ASSERT_STATUS(pthread_mutex_init(mutex, pthread_mutexattr_default));
-}
-static inline void cryptography_mutex_lock(Cryptography_mutex *mutex) {
-    ASSERT_STATUS(pthread_mutex_lock(mutex));
-}
-static inline void cryptography_mutex_unlock(Cryptography_mutex *mutex) {
-    ASSERT_STATUS(pthread_mutex_unlock(mutex));
-}
-#endif
-
-
-static unsigned int _ssl_locks_count = 0;
-static Cryptography_mutex *_ssl_locks = NULL;
-
-static void _ssl_thread_locking_function(int mode, int n, const char *file,
-                                         int line) {
-    /* this function is needed to perform locking on shared data
-       structures. (Note that OpenSSL uses a number of global data
-       structures that will be implicitly shared whenever multiple
-       threads use OpenSSL.) Multi-threaded applications will
-       crash at random if it is not set.
-
-       locking_function() must be able to handle up to
-       CRYPTO_num_locks() different mutex locks. It sets the n-th
-       lock if mode & CRYPTO_LOCK, and releases it otherwise.
-
-       file and line are the file number of the function setting the
-       lock. They can be useful for debugging.
-    */
-
-    if ((_ssl_locks == NULL) ||
-        (n < 0) || ((unsigned)n >= _ssl_locks_count)) {
-        return;
-    }
-
-    if (mode & CRYPTO_LOCK) {
-        cryptography_mutex_lock(_ssl_locks + n);
-    } else {
-        cryptography_mutex_unlock(_ssl_locks + n);
-    }
-}
-
-static void init_mutexes(void) {
-    int i;
-    for (i = 0; i < _ssl_locks_count; i++) {
-        cryptography_mutex_init(_ssl_locks + i);
-    }
-}
-
-
-int Cryptography_setup_ssl_threads(void) {
-    if (_ssl_locks == NULL) {
-        _ssl_locks_count = CRYPTO_num_locks();
-        _ssl_locks = calloc(_ssl_locks_count, sizeof(Cryptography_mutex));
-        if (_ssl_locks == NULL) {
-            return 0;
-        }
-        init_mutexes();
-        CRYPTO_set_locking_callback(_ssl_thread_locking_function);
-#ifndef _WIN32
-        pthread_atfork(NULL, NULL, &init_mutexes);
-#endif
-    }
-    return 1;
-}
-#else
-int (*Cryptography_setup_ssl_threads)(void) = NULL;
-#endif
-
 typedef struct {
     char *password;
     int length;
diff --git a/src/_cffi_src/openssl/cmac.py b/src/_cffi_src/openssl/cmac.py
index f976647..557abd1 100644
--- a/src/_cffi_src/openssl/cmac.py
+++ b/src/_cffi_src/openssl/cmac.py
@@ -11,7 +11,6 @@
 """
 
 TYPES = """
-static const int Cryptography_HAS_CMAC;
 typedef ... CMAC_CTX;
 """
 
@@ -25,5 +24,4 @@
 """
 
 CUSTOMIZATIONS = """
-static const long Cryptography_HAS_CMAC = 1;
 """
diff --git a/src/_cffi_src/openssl/crypto.py b/src/_cffi_src/openssl/crypto.py
index 03672d5..6064a4e 100644
--- a/src/_cffi_src/openssl/crypto.py
+++ b/src/_cffi_src/openssl/crypto.py
@@ -9,7 +9,6 @@
 """
 
 TYPES = """
-static const long Cryptography_HAS_LOCKING_CALLBACKS;
 static const long Cryptography_HAS_MEM_FUNCTIONS;
 static const long Cryptography_HAS_OPENSSL_CLEANUP;
 
@@ -23,28 +22,11 @@
 static const int OPENSSL_BUILT_ON;
 static const int OPENSSL_PLATFORM;
 static const int OPENSSL_DIR;
-static const int CRYPTO_MEM_CHECK_ON;
-static const int CRYPTO_MEM_CHECK_OFF;
-static const int CRYPTO_MEM_CHECK_ENABLE;
-static const int CRYPTO_MEM_CHECK_DISABLE;
-static const int CRYPTO_LOCK;
-static const int CRYPTO_UNLOCK;
-static const int CRYPTO_READ;
-static const int CRYPTO_LOCK_SSL;
 """
 
 FUNCTIONS = """
-int CRYPTO_mem_ctrl(int);
-
-void CRYPTO_cleanup_all_ex_data(void);
 void OPENSSL_cleanup(void);
 
-/* as of 1.1.0 OpenSSL does its own locking *angelic chorus*. These functions
-   have become macros that are no ops */
-int CRYPTO_num_locks(void);
-void CRYPTO_set_locking_callback(void(*)(int, int, const char *, int));
-void (*CRYPTO_get_locking_callback(void))(int, int, const char *, int);
-
 /* SSLeay was removed in 1.1.0 */
 unsigned long SSLeay(void);
 const char *SSLeay_version(int);
@@ -56,8 +38,6 @@
 void *OPENSSL_malloc(size_t);
 void OPENSSL_free(void *);
 
-/* This was removed in 1.1.0 */
-void CRYPTO_lock(int, int, const char *, int);
 
 /* Signature changed significantly in 1.1.0, only expose there for sanity */
 int Cryptography_CRYPTO_set_mem_functions(
@@ -94,26 +74,8 @@
 # define OPENSSL_PLATFORM        SSLEAY_PLATFORM
 # define OPENSSL_DIR             SSLEAY_DIR
 #endif
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
-static const long Cryptography_HAS_LOCKING_CALLBACKS = 1;
-#else
-static const long Cryptography_HAS_LOCKING_CALLBACKS = 0;
-#if !defined(CRYPTO_LOCK)
-static const long CRYPTO_LOCK = 0;
-#endif
-#if !defined(CRYPTO_UNLOCK)
-static const long CRYPTO_UNLOCK = 0;
-#endif
-#if !defined(CRYPTO_READ)
-static const long CRYPTO_READ = 0;
-#endif
-#if !defined(CRYPTO_LOCK_SSL)
-static const long CRYPTO_LOCK_SSL = 0;
-#endif
-void (*CRYPTO_lock)(int, int, const char *, int) = NULL;
-#endif
 
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
+#if CRYPTOGRAPHY_IS_LIBRESSL
 static const long Cryptography_HAS_OPENSSL_CLEANUP = 0;
 
 void (*OPENSSL_cleanup)(void) = NULL;
diff --git a/src/_cffi_src/openssl/cryptography.py b/src/_cffi_src/openssl/cryptography.py
index e16fc57..f24bee5 100644
--- a/src/_cffi_src/openssl/cryptography.py
+++ b/src/_cffi_src/openssl/cryptography.py
@@ -33,38 +33,31 @@
 #include <Winsock2.h>
 #endif
 
-#define CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER \
-    (CRYPTOGRAPHY_IS_LIBRESSL && LIBRESSL_VERSION_NUMBER >= 0x2070000fL)
-
-#define CRYPTOGRAPHY_OPENSSL_102_OR_GREATER \
-    (OPENSSL_VERSION_NUMBER >= 0x10002000 && !CRYPTOGRAPHY_IS_LIBRESSL)
-#define CRYPTOGRAPHY_OPENSSL_102L_OR_GREATER \
-    (OPENSSL_VERSION_NUMBER >= 0x100020cf && !CRYPTOGRAPHY_IS_LIBRESSL)
-#define CRYPTOGRAPHY_OPENSSL_110_OR_GREATER \
-    (OPENSSL_VERSION_NUMBER >= 0x10100000 && !CRYPTOGRAPHY_IS_LIBRESSL)
 #define CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER \
     (OPENSSL_VERSION_NUMBER >= 0x1010006f && !CRYPTOGRAPHY_IS_LIBRESSL)
 
-#define CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 \
-    (OPENSSL_VERSION_NUMBER < 0x10002000 || CRYPTOGRAPHY_IS_LIBRESSL)
-#define CRYPTOGRAPHY_OPENSSL_LESS_THAN_102I \
-    (OPENSSL_VERSION_NUMBER < 0x1000209f || CRYPTOGRAPHY_IS_LIBRESSL)
-#define CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 \
-    (OPENSSL_VERSION_NUMBER < 0x10100000 || CRYPTOGRAPHY_IS_LIBRESSL)
 #define CRYPTOGRAPHY_OPENSSL_LESS_THAN_110J \
     (OPENSSL_VERSION_NUMBER < 0x101000af || CRYPTOGRAPHY_IS_LIBRESSL)
 #define CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 \
     (OPENSSL_VERSION_NUMBER < 0x10101000 || CRYPTOGRAPHY_IS_LIBRESSL)
+#define CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B \
+    (OPENSSL_VERSION_NUMBER < 0x10101020 || CRYPTOGRAPHY_IS_LIBRESSL)
+#define CRYPTOGRAPHY_OPENSSL_LESS_THAN_111D \
+    (OPENSSL_VERSION_NUMBER < 0x10101040 || CRYPTOGRAPHY_IS_LIBRESSL)
+#if (CRYPTOGRAPHY_OPENSSL_LESS_THAN_111D && !CRYPTOGRAPHY_IS_LIBRESSL && \
+    !defined(OPENSSL_NO_ENGINE)) || defined(USE_OSRANDOM_RNG_FOR_TESTING)
+#define CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE 1
+#else
+#define CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE 0
+#endif
 """
 
 TYPES = """
-static const int CRYPTOGRAPHY_OPENSSL_102L_OR_GREATER;
-static const int CRYPTOGRAPHY_OPENSSL_110_OR_GREATER;
 static const int CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER;
 
-static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_102I;
-static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_102;
 static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_111;
+static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B;
+static const int CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE;
 
 static const int CRYPTOGRAPHY_IS_LIBRESSL;
 """
diff --git a/src/_cffi_src/openssl/ct.py b/src/_cffi_src/openssl/ct.py
index 71125dd..5f06706 100644
--- a/src/_cffi_src/openssl/ct.py
+++ b/src/_cffi_src/openssl/ct.py
@@ -5,7 +5,7 @@
 from __future__ import absolute_import, division, print_function
 
 INCLUDES = """
-#if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
+#if CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER && !defined(OPENSSL_NO_CT)
 #include <openssl/ct.h>
 
 typedef STACK_OF(SCT) Cryptography_STACK_OF_SCT;
@@ -50,13 +50,14 @@
 
 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 *);
 
-int sk_SCT_push(Cryptography_STACK_OF_SCT *, SCT *);
-Cryptography_STACK_OF_SCT *sk_SCT_new_null(void);
 SCT *SCT_new(void);
 int SCT_set1_log_id(SCT *, unsigned char *, size_t);
 void SCT_set_timestamp(SCT *, uint64_t);
@@ -65,7 +66,7 @@
 """
 
 CUSTOMIZATIONS = """
-#if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
+#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;
@@ -85,7 +86,12 @@
     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;
@@ -96,12 +102,13 @@
 
 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;
-int (*sk_SCT_push)(Cryptography_STACK_OF_SCT *, SCT *) = NULL;
-Cryptography_STACK_OF_SCT *(*sk_SCT_new_null)(void) = 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;
diff --git a/src/_cffi_src/openssl/dh.py b/src/_cffi_src/openssl/dh.py
index b0fd21f..947a5a8 100644
--- a/src/_cffi_src/openssl/dh.py
+++ b/src/_cffi_src/openssl/dh.py
@@ -18,15 +18,8 @@
 DH *DH_new(void);
 void DH_free(DH *);
 int DH_size(const DH *);
-int DH_check_pub_key(const DH *, const BIGNUM *, int *);
 int DH_generate_key(DH *);
 int DH_compute_key(unsigned char *, const BIGNUM *, DH *);
-int DH_set_ex_data(DH *, int, void *);
-void *DH_get_ex_data(DH *, int);
-DH *d2i_DHparams(DH **, const unsigned char **, long);
-int i2d_DHparams(const DH *, unsigned char **);
-int DHparams_print_fp(FILE *, const DH *);
-int DHparams_print(BIO *, const DH *);
 DH *DHparams_dup(DH *);
 
 /* added in 1.1.0 when the DH struct was opaqued */
@@ -45,79 +38,7 @@
 """
 
 CUSTOMIZATIONS = """
-/* These functions were added in OpenSSL 1.1.0 */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-void DH_get0_pqg(const DH *dh,
-                 const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
-{
-    if (p != NULL)
-        *p = dh->p;
-    if (q != NULL)
-        *q = dh->q;
-    if (g != NULL)
-        *g = dh->g;
-}
-
-int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
-{
-    /* If the fields p and g in d are NULL, the corresponding input
-     * parameters MUST be non-NULL.  q may remain NULL.
-     */
-    if ((dh->p == NULL && p == NULL)
-        || (dh->g == NULL && g == NULL))
-        return 0;
-
-    if (p != NULL) {
-        BN_free(dh->p);
-        dh->p = p;
-    }
-    if (q != NULL) {
-        BN_free(dh->q);
-        dh->q = q;
-    }
-    if (g != NULL) {
-        BN_free(dh->g);
-        dh->g = g;
-    }
-
-    if (q != NULL) {
-        dh->length = BN_num_bits(q);
-    }
-
-    return 1;
-}
-
-void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
-{
-    if (pub_key != NULL)
-        *pub_key = dh->pub_key;
-    if (priv_key != NULL)
-        *priv_key = dh->priv_key;
-}
-
-int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
-{
-    /* If the field pub_key in dh is NULL, the corresponding input
-     * parameters MUST be non-NULL.  The priv_key field may
-     * be left NULL.
-     */
-    if (dh->pub_key == NULL && pub_key == NULL)
-        return 0;
-
-    if (pub_key != NULL) {
-        BN_free(dh->pub_key);
-        dh->pub_key = pub_key;
-    }
-    if (priv_key != NULL) {
-        BN_free(dh->priv_key);
-        dh->priv_key = priv_key;
-    }
-
-    return 1;
-}
-#endif
-
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
+#if CRYPTOGRAPHY_IS_LIBRESSL
 #ifndef DH_CHECK_Q_NOT_PRIME
 #define DH_CHECK_Q_NOT_PRIME            0x10
 #endif
diff --git a/src/_cffi_src/openssl/dsa.py b/src/_cffi_src/openssl/dsa.py
index a4a87c3..3a29006 100644
--- a/src/_cffi_src/openssl/dsa.py
+++ b/src/_cffi_src/openssl/dsa.py
@@ -34,70 +34,4 @@
 """
 
 CUSTOMIZATIONS = """
-/* These functions were added in OpenSSL 1.1.0 */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-void DSA_get0_pqg(const DSA *d,
-                  const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
-{
-    if (p != NULL)
-        *p = d->p;
-    if (q != NULL)
-        *q = d->q;
-    if (g != NULL)
-        *g = d->g;
-}
-int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
-{
-    /* If the fields p, q and g in d are NULL, the corresponding input
-     * parameters MUST be non-NULL.
-     */
-    if ((d->p == NULL && p == NULL)
-        || (d->q == NULL && q == NULL)
-        || (d->g == NULL && g == NULL))
-        return 0;
-
-    if (p != NULL) {
-        BN_free(d->p);
-        d->p = p;
-    }
-    if (q != NULL) {
-        BN_free(d->q);
-        d->q = q;
-    }
-    if (g != NULL) {
-        BN_free(d->g);
-        d->g = g;
-    }
-
-    return 1;
-}
-void DSA_get0_key(const DSA *d,
-                  const BIGNUM **pub_key, const BIGNUM **priv_key)
-{
-    if (pub_key != NULL)
-        *pub_key = d->pub_key;
-    if (priv_key != NULL)
-        *priv_key = d->priv_key;
-}
-int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
-{
-    /* If the field pub_key in d is NULL, the corresponding input
-     * parameters MUST be non-NULL.  The priv_key field may
-     * be left NULL.
-     */
-    if (d->pub_key == NULL && pub_key == NULL)
-        return 0;
-
-    if (pub_key != NULL) {
-        BN_free(d->pub_key);
-        d->pub_key = pub_key;
-    }
-    if (priv_key != NULL) {
-        BN_free(d->priv_key);
-        d->priv_key = priv_key;
-    }
-
-    return 1;
-}
-#endif
 """
diff --git a/src/_cffi_src/openssl/ec.py b/src/_cffi_src/openssl/ec.py
index 66bcadc..6432fc2 100644
--- a/src/_cffi_src/openssl/ec.py
+++ b/src/_cffi_src/openssl/ec.py
@@ -10,9 +10,7 @@
 """
 
 TYPES = """
-static const int Cryptography_HAS_EC;
 static const int Cryptography_HAS_EC2M;
-static const int Cryptography_HAS_EC_1_0_2;
 
 static const int OPENSSL_EC_NAMED_CURVE;
 
@@ -106,11 +104,11 @@
 int EC_METHOD_get_field_type(const EC_METHOD *);
 
 const char *EC_curve_nid2nist(int);
+
+int EC_GROUP_get_asn1_flag(const EC_GROUP *);
 """
 
 CUSTOMIZATIONS = """
-static const long Cryptography_HAS_EC = 1;
-
 #if defined(OPENSSL_NO_EC2M)
 static const long Cryptography_HAS_EC2M = 0;
 
@@ -125,11 +123,4 @@
 #else
 static const long Cryptography_HAS_EC2M = 1;
 #endif
-
-#if (!CRYPTOGRAPHY_IS_LIBRESSL && CRYPTOGRAPHY_OPENSSL_LESS_THAN_102)
-static const long Cryptography_HAS_EC_1_0_2 = 0;
-const char *(*EC_curve_nid2nist)(int) = NULL;
-#else
-static const long Cryptography_HAS_EC_1_0_2 = 1;
-#endif
 """
diff --git a/src/_cffi_src/openssl/ecdh.py b/src/_cffi_src/openssl/ecdh.py
index 043635c..c73cc9f 100644
--- a/src/_cffi_src/openssl/ecdh.py
+++ b/src/_cffi_src/openssl/ecdh.py
@@ -9,8 +9,6 @@
 """
 
 TYPES = """
-static const int Cryptography_HAS_ECDH;
-static const int Cryptography_HAS_SET_ECDH_AUTO;
 """
 
 FUNCTIONS = """
@@ -20,12 +18,4 @@
 """
 
 CUSTOMIZATIONS = """
-static const long Cryptography_HAS_ECDH = 1;
-
-#ifndef SSL_CTX_set_ecdh_auto
-static const long Cryptography_HAS_SET_ECDH_AUTO = 0;
-long (*SSL_CTX_set_ecdh_auto)(SSL_CTX *, int) = NULL;
-#else
-static const long Cryptography_HAS_SET_ECDH_AUTO = 1;
-#endif
 """
diff --git a/src/_cffi_src/openssl/ecdsa.py b/src/_cffi_src/openssl/ecdsa.py
index 44a778a..3134e24 100644
--- a/src/_cffi_src/openssl/ecdsa.py
+++ b/src/_cffi_src/openssl/ecdsa.py
@@ -9,8 +9,6 @@
 """
 
 TYPES = """
-static const int Cryptography_HAS_ECDSA;
-
 typedef ... ECDSA_SIG;
 
 typedef ... CRYPTO_EX_new;
@@ -19,12 +17,6 @@
 """
 
 FUNCTIONS = """
-ECDSA_SIG *ECDSA_SIG_new();
-void ECDSA_SIG_free(ECDSA_SIG *);
-int i2d_ECDSA_SIG(const ECDSA_SIG *, unsigned char **);
-ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **s, const unsigned char **, long);
-ECDSA_SIG *ECDSA_do_sign(const unsigned char *, int, EC_KEY *);
-int ECDSA_do_verify(const unsigned char *, int, const ECDSA_SIG *, EC_KEY *);
 int ECDSA_sign(int, const unsigned char *, int, unsigned char *,
                unsigned int *, EC_KEY *);
 int ECDSA_verify(int, const unsigned char *, int, const unsigned char *, int,
@@ -34,5 +26,4 @@
 """
 
 CUSTOMIZATIONS = """
-static const long Cryptography_HAS_ECDSA = 1;
 """
diff --git a/src/_cffi_src/openssl/engine.py b/src/_cffi_src/openssl/engine.py
index 45ce952..24cdd42 100644
--- a/src/_cffi_src/openssl/engine.py
+++ b/src/_cffi_src/openssl/engine.py
@@ -10,124 +10,56 @@
 
 TYPES = """
 typedef ... ENGINE;
-typedef ... RSA_METHOD;
-typedef ... DSA_METHOD;
-typedef ... DH_METHOD;
-typedef struct {
-    int (*bytes)(unsigned char *, int);
-    int (*pseudorand)(unsigned char *, int);
-    int (*status)();
-    ...;
-} RAND_METHOD;
-typedef int (*ENGINE_GEN_INT_FUNC_PTR)(ENGINE *);
-typedef ... *ENGINE_CTRL_FUNC_PTR;
-typedef ... *ENGINE_LOAD_KEY_PTR;
-typedef ... *ENGINE_CIPHERS_PTR;
-typedef ... *ENGINE_DIGESTS_PTR;
-typedef ... ENGINE_CMD_DEFN;
 typedef ... UI_METHOD;
 
-static const unsigned int ENGINE_METHOD_RSA;
-static const unsigned int ENGINE_METHOD_DSA;
-static const unsigned int ENGINE_METHOD_RAND;
-static const unsigned int ENGINE_METHOD_CIPHERS;
-static const unsigned int ENGINE_METHOD_DIGESTS;
-static const unsigned int ENGINE_METHOD_ALL;
-static const unsigned int ENGINE_METHOD_NONE;
-
-static const int ENGINE_R_CONFLICTING_ENGINE_ID;
+static const long Cryptography_HAS_ENGINE;
 """
 
 FUNCTIONS = """
-ENGINE *ENGINE_get_first(void);
-ENGINE *ENGINE_get_last(void);
-ENGINE *ENGINE_get_next(ENGINE *);
-ENGINE *ENGINE_get_prev(ENGINE *);
-int ENGINE_add(ENGINE *);
-int ENGINE_remove(ENGINE *);
 ENGINE *ENGINE_by_id(const char *);
 int ENGINE_init(ENGINE *);
 int ENGINE_finish(ENGINE *);
-void ENGINE_load_builtin_engines(void);
-ENGINE *ENGINE_get_default_RSA(void);
-ENGINE *ENGINE_get_default_DSA(void);
-ENGINE *ENGINE_get_default_DH(void);
 ENGINE *ENGINE_get_default_RAND(void);
-ENGINE *ENGINE_get_cipher_engine(int);
-ENGINE *ENGINE_get_digest_engine(int);
-int ENGINE_set_default_RSA(ENGINE *);
-int ENGINE_set_default_DSA(ENGINE *);
-int ENGINE_set_default_DH(ENGINE *);
 int ENGINE_set_default_RAND(ENGINE *);
-int ENGINE_set_default_ciphers(ENGINE *);
-int ENGINE_set_default_digests(ENGINE *);
-int ENGINE_set_default_string(ENGINE *, const char *);
-int ENGINE_set_default(ENGINE *, unsigned int);
-unsigned int ENGINE_get_table_flags(void);
-void ENGINE_set_table_flags(unsigned int);
-int ENGINE_register_RSA(ENGINE *);
-void ENGINE_unregister_RSA(ENGINE *);
-void ENGINE_register_all_RSA(void);
-int ENGINE_register_DSA(ENGINE *);
-void ENGINE_unregister_DSA(ENGINE *);
-void ENGINE_register_all_DSA(void);
-int ENGINE_register_DH(ENGINE *);
-void ENGINE_unregister_DH(ENGINE *);
-void ENGINE_register_all_DH(void);
-int ENGINE_register_RAND(ENGINE *);
 void ENGINE_unregister_RAND(ENGINE *);
-void ENGINE_register_all_RAND(void);
-int ENGINE_register_ciphers(ENGINE *);
-void ENGINE_unregister_ciphers(ENGINE *);
-void ENGINE_register_all_ciphers(void);
-int ENGINE_register_digests(ENGINE *);
-void ENGINE_unregister_digests(ENGINE *);
-void ENGINE_register_all_digests(void);
-int ENGINE_register_complete(ENGINE *);
-int ENGINE_register_all_complete(void);
-int ENGINE_ctrl(ENGINE *, int, long, void *, void (*)(void));
-int ENGINE_cmd_is_executable(ENGINE *, int);
 int ENGINE_ctrl_cmd(ENGINE *, const char *, long, void *, void (*)(void), int);
-int ENGINE_ctrl_cmd_string(ENGINE *, const char *, const char *, int);
-
-ENGINE *ENGINE_new(void);
 int ENGINE_free(ENGINE *);
-int ENGINE_up_ref(ENGINE *);
-int ENGINE_set_id(ENGINE *, const char *);
-int ENGINE_set_name(ENGINE *, const char *);
-int ENGINE_set_RSA(ENGINE *, const RSA_METHOD *);
-int ENGINE_set_DSA(ENGINE *, const DSA_METHOD *);
-int ENGINE_set_DH(ENGINE *, const DH_METHOD *);
-int ENGINE_set_RAND(ENGINE *, const RAND_METHOD *);
-int ENGINE_set_destroy_function(ENGINE *, ENGINE_GEN_INT_FUNC_PTR);
-int ENGINE_set_init_function(ENGINE *, ENGINE_GEN_INT_FUNC_PTR);
-int ENGINE_set_finish_function(ENGINE *, ENGINE_GEN_INT_FUNC_PTR);
-int ENGINE_set_ctrl_function(ENGINE *, ENGINE_CTRL_FUNC_PTR);
-int ENGINE_set_load_privkey_function(ENGINE *, ENGINE_LOAD_KEY_PTR);
-int ENGINE_set_load_pubkey_function(ENGINE *, ENGINE_LOAD_KEY_PTR);
-int ENGINE_set_ciphers(ENGINE *, ENGINE_CIPHERS_PTR);
-int ENGINE_set_digests(ENGINE *, ENGINE_DIGESTS_PTR);
-int ENGINE_set_flags(ENGINE *, int);
-int ENGINE_set_cmd_defns(ENGINE *, const ENGINE_CMD_DEFN *);
-const char *ENGINE_get_id(const ENGINE *);
 const char *ENGINE_get_name(const ENGINE *);
-const RSA_METHOD *ENGINE_get_RSA(const ENGINE *);
-const DSA_METHOD *ENGINE_get_DSA(const ENGINE *);
-const DH_METHOD *ENGINE_get_DH(const ENGINE *);
-const RAND_METHOD *ENGINE_get_RAND(const ENGINE *);
 
-const EVP_CIPHER *ENGINE_get_cipher(ENGINE *, int);
-const EVP_MD *ENGINE_get_digest(ENGINE *, int);
-int ENGINE_get_flags(const ENGINE *);
-const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *);
+// These bindings are unused by cryptography or pyOpenSSL but are present
+// for advanced users who need them.
+int ENGINE_ctrl_cmd_string(ENGINE *, const char *, const char *, int);
+void ENGINE_load_builtin_engines(void);
 EVP_PKEY *ENGINE_load_private_key(ENGINE *, const char *, UI_METHOD *, void *);
 EVP_PKEY *ENGINE_load_public_key(ENGINE *, const char *, UI_METHOD *, void *);
-void ENGINE_add_conf_module(void);
-/* these became macros in 1.1.0 */
-void ENGINE_load_openssl(void);
-void ENGINE_load_dynamic(void);
-void ENGINE_cleanup(void);
 """
 
 CUSTOMIZATIONS = """
+#ifdef OPENSSL_NO_ENGINE
+static const long Cryptography_HAS_ENGINE = 0;
+
+ENGINE *(*ENGINE_by_id)(const char *) = NULL;
+int (*ENGINE_init)(ENGINE *) = NULL;
+int (*ENGINE_finish)(ENGINE *) = NULL;
+ENGINE *(*ENGINE_get_default_RAND)(void) = NULL;
+int (*ENGINE_set_default_RAND)(ENGINE *) = NULL;
+void (*ENGINE_unregister_RAND)(ENGINE *) = NULL;
+int (*ENGINE_ctrl_cmd)(ENGINE *, const char *, long, void *,
+                       void (*)(void), int) = NULL;
+
+int (*ENGINE_free)(ENGINE *) = NULL;
+const char *(*ENGINE_get_id)(const ENGINE *) = NULL;
+const char *(*ENGINE_get_name)(const ENGINE *) = NULL;
+
+int (*ENGINE_ctrl_cmd_string)(ENGINE *, const char *, const char *,
+                              int) = NULL;
+void (*ENGINE_load_builtin_engines)(void) = NULL;
+EVP_PKEY *(*ENGINE_load_private_key)(ENGINE *, const char *, UI_METHOD *,
+                                     void *) = NULL;
+EVP_PKEY *(*ENGINE_load_public_key)(ENGINE *, const char *,
+                                    UI_METHOD *, void *) = NULL;
+
+#else
+static const long Cryptography_HAS_ENGINE = 1;
+#endif
 """
diff --git a/src/_cffi_src/openssl/err.py b/src/_cffi_src/openssl/err.py
index d4033f5..0dd7414 100644
--- a/src/_cffi_src/openssl/err.py
+++ b/src/_cffi_src/openssl/err.py
@@ -9,141 +9,24 @@
 """
 
 TYPES = """
-static const int Cryptography_HAS_EC_CODES;
-static const int Cryptography_HAS_RSA_R_PKCS_DECODING_ERROR;
-static const int Cryptography_HAS_EVP_R_MEMORY_LIMIT_EXCEEDED;
+static const int EVP_F_EVP_ENCRYPTFINAL_EX;
+static const int EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH;
+static const int EVP_R_BAD_DECRYPT;
+static const int EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM;
+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 ERR_LIB_DH;
 static const int ERR_LIB_EVP;
-static const int ERR_LIB_EC;
 static const int ERR_LIB_PEM;
 static const int ERR_LIB_ASN1;
-static const int ERR_LIB_RSA;
 static const int ERR_LIB_PKCS12;
-static const int ERR_LIB_SSL;
-static const int ERR_LIB_X509;
-
-static const int ERR_R_MALLOC_FAILURE;
-static const int EVP_R_MEMORY_LIMIT_EXCEEDED;
-
-static const int ASN1_R_BOOLEAN_IS_WRONG_LENGTH;
-static const int ASN1_R_BUFFER_TOO_SMALL;
-static const int ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER;
-static const int ASN1_R_DATA_IS_WRONG;
-static const int ASN1_R_DECODE_ERROR;
-static const int ASN1_R_DEPTH_EXCEEDED;
-static const int ASN1_R_ENCODE_ERROR;
-static const int ASN1_R_ERROR_GETTING_TIME;
-static const int ASN1_R_ERROR_LOADING_SECTION;
-static const int ASN1_R_MSTRING_WRONG_TAG;
-static const int ASN1_R_NESTED_ASN1_STRING;
-static const int ASN1_R_NO_MATCHING_CHOICE_TYPE;
-static const int ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM;
-static const int ASN1_R_UNKNOWN_OBJECT_TYPE;
-static const int ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE;
-static const int ASN1_R_UNKNOWN_TAG;
-static const int ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE;
-static const int ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE;
-static const int ASN1_R_UNSUPPORTED_TYPE;
-static const int ASN1_R_WRONG_TAG;
-static const int ASN1_R_NO_CONTENT_TYPE;
-static const int ASN1_R_NO_MULTIPART_BODY_FAILURE;
-static const int ASN1_R_NO_MULTIPART_BOUNDARY;
-static const int ASN1_R_HEADER_TOO_LONG;
-
-static const int DH_R_INVALID_PUBKEY;
-
-static const int EVP_F_EVP_ENCRYPTFINAL_EX;
-
-static const int EVP_R_AES_KEY_SETUP_FAILED;
-static const int EVP_R_BAD_DECRYPT;
-static const int EVP_R_CIPHER_PARAMETER_ERROR;
-static const int EVP_R_CTRL_NOT_IMPLEMENTED;
-static const int EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED;
-static const int EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH;
-static const int EVP_R_DECODE_ERROR;
-static const int EVP_R_DIFFERENT_KEY_TYPES;
-static const int EVP_R_INITIALIZATION_ERROR;
-static const int EVP_R_INPUT_NOT_INITIALIZED;
-static const int EVP_R_INVALID_KEY_LENGTH;
-static const int EVP_R_KEYGEN_FAILURE;
-static const int EVP_R_MISSING_PARAMETERS;
-static const int EVP_R_NO_CIPHER_SET;
-static const int EVP_R_NO_DIGEST_SET;
-static const int EVP_R_PUBLIC_KEY_NOT_RSA;
-static const int EVP_R_UNKNOWN_PBE_ALGORITHM;
-static const int EVP_R_UNSUPPORTED_CIPHER;
-static const int EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION;
-static const int EVP_R_UNSUPPORTED_KEYLENGTH;
-static const int EVP_R_UNSUPPORTED_SALT_TYPE;
-static const int EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM;
-static const int EVP_R_WRONG_FINAL_BLOCK_LENGTH;
-static const int EVP_R_CAMELLIA_KEY_SETUP_FAILED;
-
-static const int EC_R_UNKNOWN_GROUP;
-
-static const int PEM_R_BAD_BASE64_DECODE;
-static const int PEM_R_BAD_DECRYPT;
-static const int PEM_R_BAD_END_LINE;
-static const int PEM_R_BAD_IV_CHARS;
-static const int PEM_R_BAD_PASSWORD_READ;
-static const int PEM_R_ERROR_CONVERTING_PRIVATE_KEY;
-static const int PEM_R_NO_START_LINE;
-static const int PEM_R_NOT_DEK_INFO;
-static const int PEM_R_NOT_ENCRYPTED;
-static const int PEM_R_NOT_PROC_TYPE;
-static const int PEM_R_PROBLEMS_GETTING_PASSWORD;
-static const int PEM_R_READ_KEY;
-static const int PEM_R_SHORT_HEADER;
-static const int PEM_R_UNSUPPORTED_CIPHER;
-static const int PEM_R_UNSUPPORTED_ENCRYPTION;
-
-static const int PKCS12_R_PKCS12_CIPHERFINAL_ERROR;
-
-static const int RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE;
-static const int RSA_R_DATA_TOO_LARGE_FOR_MODULUS;
-static const int RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY;
-static const int RSA_R_BLOCK_TYPE_IS_NOT_01;
-static const int RSA_R_BLOCK_TYPE_IS_NOT_02;
-static const int RSA_R_PKCS_DECODING_ERROR;
-static const int RSA_R_OAEP_DECODING_ERROR;
 
 static const int SSL_TLSEXT_ERR_OK;
-static const int SSL_TLSEXT_ERR_ALERT_WARNING;
 static const int SSL_TLSEXT_ERR_ALERT_FATAL;
 static const int SSL_TLSEXT_ERR_NOACK;
 
-static const int SSL_AD_CLOSE_NOTIFY;
-static const int SSL_AD_UNEXPECTED_MESSAGE;
-static const int SSL_AD_BAD_RECORD_MAC;
-static const int SSL_AD_RECORD_OVERFLOW;
-static const int SSL_AD_DECOMPRESSION_FAILURE;
-static const int SSL_AD_HANDSHAKE_FAILURE;
-static const int SSL_AD_BAD_CERTIFICATE;
-static const int SSL_AD_UNSUPPORTED_CERTIFICATE;
-static const int SSL_AD_CERTIFICATE_REVOKED;
-static const int SSL_AD_CERTIFICATE_EXPIRED;
-static const int SSL_AD_CERTIFICATE_UNKNOWN;
-static const int SSL_AD_ILLEGAL_PARAMETER;
-static const int SSL_AD_UNKNOWN_CA;
-static const int SSL_AD_ACCESS_DENIED;
-static const int SSL_AD_DECODE_ERROR;
-static const int SSL_AD_DECRYPT_ERROR;
-static const int SSL_AD_PROTOCOL_VERSION;
-static const int SSL_AD_INSUFFICIENT_SECURITY;
-static const int SSL_AD_INTERNAL_ERROR;
-static const int SSL_AD_USER_CANCELLED;
-static const int SSL_AD_NO_RENEGOTIATION;
-
-static const int SSL_AD_UNSUPPORTED_EXTENSION;
-static const int SSL_AD_CERTIFICATE_UNOBTAINABLE;
-static const int SSL_AD_UNRECOGNIZED_NAME;
-static const int SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
-static const int SSL_AD_BAD_CERTIFICATE_HASH_VALUE;
-static const int SSL_AD_UNKNOWN_PSK_IDENTITY;
-
 static const int X509_R_CERT_ALREADY_IN_HASH_TABLE;
-static const int X509_R_KEY_VALUES_MISMATCH;
 """
 
 FUNCTIONS = """
@@ -153,7 +36,6 @@
 const char *ERR_reason_error_string(unsigned long);
 unsigned long ERR_get_error(void);
 unsigned long ERR_peek_error(void);
-unsigned long ERR_peek_last_error(void);
 void ERR_clear_error(void);
 void ERR_put_error(int, int, int, const char *, int);
 
@@ -164,19 +46,4 @@
 """
 
 CUSTOMIZATIONS = """
-static const long Cryptography_HAS_EC_CODES = 1;
-
-#ifdef RSA_R_PKCS_DECODING_ERROR
-static const long Cryptography_HAS_RSA_R_PKCS_DECODING_ERROR = 1;
-#else
-static const long Cryptography_HAS_RSA_R_PKCS_DECODING_ERROR = 0;
-static const long RSA_R_PKCS_DECODING_ERROR = 0;
-#endif
-
-#ifdef EVP_R_MEMORY_LIMIT_EXCEEDED
-static const long Cryptography_HAS_EVP_R_MEMORY_LIMIT_EXCEEDED = 1;
-#else
-static const long EVP_R_MEMORY_LIMIT_EXCEEDED = 0;
-static const long Cryptography_HAS_EVP_R_MEMORY_LIMIT_EXCEEDED = 0;
-#endif
 """
diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py
index 9ae6025..ab7cfeb 100644
--- a/src/_cffi_src/openssl/evp.py
+++ b/src/_cffi_src/openssl/evp.py
@@ -25,14 +25,12 @@
 static const int EVP_PKEY_ED25519;
 static const int EVP_PKEY_X448;
 static const int EVP_PKEY_ED448;
+static const int EVP_PKEY_POLY1305;
 static const int EVP_MAX_MD_SIZE;
 static const int EVP_CTRL_AEAD_SET_IVLEN;
 static const int EVP_CTRL_AEAD_GET_TAG;
 static const int EVP_CTRL_AEAD_SET_TAG;
 
-static const int Cryptography_HAS_GCM;
-static const int Cryptography_HAS_PBKDF2_HMAC;
-static const int Cryptography_HAS_PKEY_CTX;
 static const int Cryptography_HAS_SCRYPT;
 static const int Cryptography_HAS_EVP_PKEY_DHX;
 static const int Cryptography_HAS_EVP_PKEY_get_set_tls_encodedpoint;
@@ -43,23 +41,12 @@
 
 FUNCTIONS = """
 const EVP_CIPHER *EVP_get_cipherbyname(const char *);
-int EVP_EncryptInit_ex(EVP_CIPHER_CTX *, const EVP_CIPHER *, ENGINE *,
-                       const unsigned char *, const unsigned char *);
 int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *, int);
-int EVP_EncryptUpdate(EVP_CIPHER_CTX *, unsigned char *, int *,
-                      const unsigned char *, int);
-int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *, unsigned char *, int *);
-int EVP_DecryptInit_ex(EVP_CIPHER_CTX *, const EVP_CIPHER *, ENGINE *,
-                       const unsigned char *, const unsigned char *);
-int EVP_DecryptUpdate(EVP_CIPHER_CTX *, unsigned char *, int *,
-                      const unsigned char *, int);
-int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *, unsigned char *, int *);
 int EVP_CipherInit_ex(EVP_CIPHER_CTX *, const EVP_CIPHER *, ENGINE *,
                       const unsigned char *, const unsigned char *, int);
 int EVP_CipherUpdate(EVP_CIPHER_CTX *, unsigned char *, int *,
                      const unsigned char *, int);
 int EVP_CipherFinal_ex(EVP_CIPHER_CTX *, unsigned char *, int *);
-int EVP_CIPHER_block_size(const EVP_CIPHER *);
 int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *);
 EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
 void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *);
@@ -72,8 +59,6 @@
 int EVP_DigestFinal_ex(EVP_MD_CTX *, unsigned char *, unsigned int *);
 int EVP_DigestFinalXOF(EVP_MD_CTX *, unsigned char *, size_t);
 const EVP_MD *EVP_get_digestbyname(const char *);
-const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *);
-int EVP_MD_size(const EVP_MD *);
 
 EVP_PKEY *EVP_PKEY_new(void);
 void EVP_PKEY_free(EVP_PKEY *);
@@ -97,22 +82,14 @@
 int EVP_VerifyFinal(EVP_MD_CTX *, const unsigned char *, unsigned int,
                     EVP_PKEY *);
 
-const EVP_MD *EVP_md5(void);
-const EVP_MD *EVP_sha1(void);
-const EVP_MD *EVP_ripemd160(void);
-const EVP_MD *EVP_sha224(void);
-const EVP_MD *EVP_sha256(void);
-const EVP_MD *EVP_sha384(void);
-const EVP_MD *EVP_sha512(void);
-
 int EVP_DigestSignInit(EVP_MD_CTX *, EVP_PKEY_CTX **, const EVP_MD *,
                        ENGINE *, EVP_PKEY *);
+int EVP_DigestSignUpdate(EVP_MD_CTX *, const void *, size_t);
+int EVP_DigestSignFinal(EVP_MD_CTX *, unsigned char *, size_t *);
 int EVP_DigestVerifyInit(EVP_MD_CTX *, EVP_PKEY_CTX **, const EVP_MD *,
                          ENGINE *, EVP_PKEY *);
 
 
-int PKCS5_PBKDF2_HMAC_SHA1(const char *, int, const unsigned char *, int, int,
-                           int, unsigned char *);
 
 EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *, ENGINE *);
 EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int, ENGINE *);
@@ -124,6 +101,9 @@
 int EVP_PKEY_verify_init(EVP_PKEY_CTX *);
 int EVP_PKEY_verify(EVP_PKEY_CTX *, const unsigned char *, size_t,
                     const unsigned char *, size_t);
+int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *);
+int EVP_PKEY_verify_recover(EVP_PKEY_CTX *, unsigned char *,
+                            size_t *, const unsigned char *, size_t);
 int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *);
 int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *);
 
@@ -131,18 +111,6 @@
 int EVP_PKEY_set1_DSA(EVP_PKEY *, DSA *);
 int EVP_PKEY_set1_DH(EVP_PKEY *, DH *);
 
-int EVP_PKEY_get_attr_count(const EVP_PKEY *);
-int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *, int, int);
-X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *, int);
-X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *, int);
-int EVP_PKEY_add1_attr(EVP_PKEY *, X509_ATTRIBUTE *);
-int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *, const ASN1_OBJECT *, int,
-                              const unsigned char *, int);
-int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *, int, int,
-                              const unsigned char *, int);
-int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *, const char *, int,
-                              const unsigned char *, int);
-
 int EVP_PKEY_cmp(const EVP_PKEY *, const EVP_PKEY *);
 
 int EVP_PKEY_keygen_init(EVP_PKEY_CTX *);
@@ -155,11 +123,12 @@
 int EVP_PKEY_id(const EVP_PKEY *);
 int Cryptography_EVP_PKEY_id(const EVP_PKEY *);
 
-/* in 1.1.0 _create and _destroy were renamed to _new and _free. The following
-   two functions wrap both the old and new functions so we can call them
-   without worrying about what OpenSSL we're running against. */
+EVP_MD_CTX *EVP_MD_CTX_new(void);
+void EVP_MD_CTX_free(EVP_MD_CTX *);
+/* Backwards compat aliases for pyOpenSSL */
 EVP_MD_CTX *Cryptography_EVP_MD_CTX_new(void);
 void Cryptography_EVP_MD_CTX_free(EVP_MD_CTX *);
+
 /* Added in 1.1.1 */
 int EVP_DigestSign(EVP_MD_CTX *, unsigned char *, size_t *,
                    const unsigned char *, size_t);
@@ -170,25 +139,15 @@
 int EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *, const unsigned char *,
                                    size_t);
 
-/* PKCS8_PRIV_KEY_INFO * became const in 1.1.0 */
-EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *);
-
 /* EVP_PKEY * became const in 1.1.0 */
 int EVP_PKEY_bits(EVP_PKEY *);
 
-/* became a macro in 1.1.0 */
-void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *);
-
 void OpenSSL_add_all_algorithms(void);
 int EVP_PKEY_assign_RSA(EVP_PKEY *, RSA *);
-int EVP_PKEY_assign_DSA(EVP_PKEY *, DSA *);
 
-int EVP_PKEY_assign_EC_KEY(EVP_PKEY *, EC_KEY *);
 EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *);
 int EVP_PKEY_set1_EC_KEY(EVP_PKEY *, EC_KEY *);
 
-int EVP_MD_CTX_block_size(const EVP_MD_CTX *);
-int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *);
 int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *, int, int, void *);
 
 int PKCS5_PBKDF2_HMAC(const char *, int, const unsigned char *, int, int,
@@ -209,11 +168,6 @@
 """
 
 CUSTOMIZATIONS = """
-const long Cryptography_HAS_GCM = 1;
-
-const long Cryptography_HAS_PBKDF2_HMAC = 1;
-const long Cryptography_HAS_PKEY_CTX = 1;
-
 #ifdef EVP_PKEY_DHX
 const long Cryptography_HAS_EVP_PKEY_DHX = 1;
 #else
@@ -224,22 +178,14 @@
 int Cryptography_EVP_PKEY_id(const EVP_PKEY *key) {
     return EVP_PKEY_id(key);
 }
-
 EVP_MD_CTX *Cryptography_EVP_MD_CTX_new(void) {
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
-    return EVP_MD_CTX_create();
-#else
     return EVP_MD_CTX_new();
-#endif
 }
-void Cryptography_EVP_MD_CTX_free(EVP_MD_CTX *ctx) {
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
-    EVP_MD_CTX_destroy(ctx);
-#else
-    EVP_MD_CTX_free(ctx);
-#endif
+void Cryptography_EVP_MD_CTX_free(EVP_MD_CTX *md) {
+    EVP_MD_CTX_free(md);
 }
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 || defined(OPENSSL_NO_SCRYPT)
+
+#if CRYPTOGRAPHY_IS_LIBRESSL || defined(OPENSSL_NO_SCRYPT)
 static const long Cryptography_HAS_SCRYPT = 0;
 int (*EVP_PBE_scrypt)(const char *, size_t, const unsigned char *, size_t,
                       uint64_t, uint64_t, uint64_t, uint64_t, unsigned char *,
@@ -248,7 +194,7 @@
 static const long Cryptography_HAS_SCRYPT = 1;
 #endif
 
-#if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
+#if !CRYPTOGRAPHY_IS_LIBRESSL
 static const long Cryptography_HAS_EVP_PKEY_get_set_tls_encodedpoint = 1;
 #else
 static const long Cryptography_HAS_EVP_PKEY_get_set_tls_encodedpoint = 0;
@@ -317,4 +263,10 @@
 #ifndef EVP_PKEY_ED448
 #define EVP_PKEY_ED448 NID_ED448
 #endif
+
+/* This is tied to poly1305 support so we reuse the Cryptography_HAS_POLY1305
+   conditional to remove it. */
+#ifndef EVP_PKEY_POLY1305
+#define EVP_PKEY_POLY1305 NID_poly1305
+#endif
 """
diff --git a/src/_cffi_src/openssl/hmac.py b/src/_cffi_src/openssl/hmac.py
index b006e64..2e0e33f 100644
--- a/src/_cffi_src/openssl/hmac.py
+++ b/src/_cffi_src/openssl/hmac.py
@@ -18,31 +18,9 @@
 int HMAC_Final(HMAC_CTX *, unsigned char *, unsigned int *);
 int HMAC_CTX_copy(HMAC_CTX *, HMAC_CTX *);
 
-HMAC_CTX *Cryptography_HMAC_CTX_new(void);
-void Cryptography_HMAC_CTX_free(HMAC_CTX *ctx);
+HMAC_CTX *HMAC_CTX_new(void);
+void HMAC_CTX_free(HMAC_CTX *ctx);
 """
 
 CUSTOMIZATIONS = """
-HMAC_CTX *Cryptography_HMAC_CTX_new(void) {
-#if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
-    return HMAC_CTX_new();
-#else
-    /* This uses OPENSSL_zalloc in 1.1.0, which is malloc + memset */
-    HMAC_CTX *ctx = (HMAC_CTX *)OPENSSL_malloc(sizeof(HMAC_CTX));
-    memset(ctx, 0, sizeof(HMAC_CTX));
-    return ctx;
-#endif
-}
-
-
-void Cryptography_HMAC_CTX_free(HMAC_CTX *ctx) {
-#if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
-    return HMAC_CTX_free(ctx);
-#else
-    if (ctx != NULL) {
-        HMAC_CTX_cleanup(ctx);
-        OPENSSL_free(ctx);
-    }
-#endif
-}
 """
diff --git a/src/_cffi_src/openssl/nid.py b/src/_cffi_src/openssl/nid.py
index 4117b93..9ef88cd 100644
--- a/src/_cffi_src/openssl/nid.py
+++ b/src/_cffi_src/openssl/nid.py
@@ -9,252 +9,44 @@
 """
 
 TYPES = """
-static const int Cryptography_HAS_X25519;
-static const int Cryptography_HAS_X448;
 static const int Cryptography_HAS_ED448;
 static const int Cryptography_HAS_ED25519;
+static const int Cryptography_HAS_POLY1305;
 
 static const int NID_undef;
-static const int NID_dsa;
-static const int NID_dsaWithSHA;
-static const int NID_dsaWithSHA1;
-static const int NID_md2;
-static const int NID_md4;
-static const int NID_md5;
-static const int NID_mdc2;
-static const int NID_ripemd160;
-static const int NID_sha;
-static const int NID_sha1;
-static const int NID_sha256;
-static const int NID_sha384;
-static const int NID_sha512;
-static const int NID_sha224;
-static const int NID_sha;
-static const int NID_ecdsa_with_SHA1;
-static const int NID_ecdsa_with_SHA224;
-static const int NID_ecdsa_with_SHA256;
-static const int NID_ecdsa_with_SHA384;
-static const int NID_ecdsa_with_SHA512;
 static const int NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
-static const int NID_X9_62_c2pnb163v1;
-static const int NID_X9_62_c2pnb163v2;
-static const int NID_X9_62_c2pnb163v3;
-static const int NID_X9_62_c2pnb176v1;
-static const int NID_X9_62_c2tnb191v1;
-static const int NID_X9_62_c2tnb191v2;
-static const int NID_X9_62_c2tnb191v3;
-static const int NID_X9_62_c2onb191v4;
-static const int NID_X9_62_c2onb191v5;
-static const int NID_X9_62_c2pnb208w1;
-static const int NID_X9_62_c2tnb239v1;
-static const int NID_X9_62_c2tnb239v2;
-static const int NID_X9_62_c2tnb239v3;
-static const int NID_X9_62_c2onb239v4;
-static const int NID_X9_62_c2onb239v5;
-static const int NID_X9_62_c2pnb272w1;
-static const int NID_X9_62_c2pnb304w1;
-static const int NID_X9_62_c2tnb359v1;
-static const int NID_X9_62_c2pnb368w1;
-static const int NID_X9_62_c2tnb431r1;
-static const int NID_X9_62_prime192v1;
-static const int NID_X9_62_prime192v2;
-static const int NID_X9_62_prime192v3;
-static const int NID_X9_62_prime239v1;
-static const int NID_X9_62_prime239v2;
-static const int NID_X9_62_prime239v3;
-static const int NID_X9_62_prime256v1;
-static const int NID_secp112r1;
-static const int NID_secp112r2;
-static const int NID_secp128r1;
-static const int NID_secp128r2;
-static const int NID_secp160k1;
-static const int NID_secp160r1;
-static const int NID_secp160r2;
-static const int NID_sect163k1;
-static const int NID_sect163r1;
-static const int NID_sect163r2;
-static const int NID_secp192k1;
-static const int NID_secp224k1;
-static const int NID_secp224r1;
-static const int NID_secp256k1;
-static const int NID_secp384r1;
-static const int NID_secp521r1;
-static const int NID_sect113r1;
-static const int NID_sect113r2;
-static const int NID_sect131r1;
-static const int NID_sect131r2;
-static const int NID_sect193r1;
-static const int NID_sect193r2;
-static const int NID_sect233k1;
-static const int NID_sect233r1;
-static const int NID_sect239k1;
-static const int NID_sect283k1;
-static const int NID_sect283r1;
-static const int NID_sect409k1;
-static const int NID_sect409r1;
-static const int NID_sect571k1;
-static const int NID_sect571r1;
 static const int NID_X25519;
 static const int NID_X448;
 static const int NID_ED25519;
 static const int NID_ED448;
-static const int NID_wap_wsg_idm_ecid_wtls1;
-static const int NID_wap_wsg_idm_ecid_wtls3;
-static const int NID_wap_wsg_idm_ecid_wtls4;
-static const int NID_wap_wsg_idm_ecid_wtls5;
-static const int NID_wap_wsg_idm_ecid_wtls6;
-static const int NID_wap_wsg_idm_ecid_wtls7;
-static const int NID_wap_wsg_idm_ecid_wtls8;
-static const int NID_wap_wsg_idm_ecid_wtls9;
-static const int NID_wap_wsg_idm_ecid_wtls10;
-static const int NID_wap_wsg_idm_ecid_wtls11;
-static const int NID_wap_wsg_idm_ecid_wtls12;
-static const int NID_ipsec3;
-static const int NID_ipsec4;
-static const char *const SN_X9_62_c2pnb163v1;
-static const char *const SN_X9_62_c2pnb163v2;
-static const char *const SN_X9_62_c2pnb163v3;
-static const char *const SN_X9_62_c2pnb176v1;
-static const char *const SN_X9_62_c2tnb191v1;
-static const char *const SN_X9_62_c2tnb191v2;
-static const char *const SN_X9_62_c2tnb191v3;
-static const char *const SN_X9_62_c2onb191v4;
-static const char *const SN_X9_62_c2onb191v5;
-static const char *const SN_X9_62_c2pnb208w1;
-static const char *const SN_X9_62_c2tnb239v1;
-static const char *const SN_X9_62_c2tnb239v2;
-static const char *const SN_X9_62_c2tnb239v3;
-static const char *const SN_X9_62_c2onb239v4;
-static const char *const SN_X9_62_c2onb239v5;
-static const char *const SN_X9_62_c2pnb272w1;
-static const char *const SN_X9_62_c2pnb304w1;
-static const char *const SN_X9_62_c2tnb359v1;
-static const char *const SN_X9_62_c2pnb368w1;
-static const char *const SN_X9_62_c2tnb431r1;
-static const char *const SN_X9_62_prime192v1;
-static const char *const SN_X9_62_prime192v2;
-static const char *const SN_X9_62_prime192v3;
-static const char *const SN_X9_62_prime239v1;
-static const char *const SN_X9_62_prime239v2;
-static const char *const SN_X9_62_prime239v3;
-static const char *const SN_X9_62_prime256v1;
-static const char *const SN_secp112r1;
-static const char *const SN_secp112r2;
-static const char *const SN_secp128r1;
-static const char *const SN_secp128r2;
-static const char *const SN_secp160k1;
-static const char *const SN_secp160r1;
-static const char *const SN_secp160r2;
-static const char *const SN_sect163k1;
-static const char *const SN_sect163r1;
-static const char *const SN_sect163r2;
-static const char *const SN_secp192k1;
-static const char *const SN_secp224k1;
-static const char *const SN_secp224r1;
-static const char *const SN_secp256k1;
-static const char *const SN_secp384r1;
-static const char *const SN_secp521r1;
-static const char *const SN_sect113r1;
-static const char *const SN_sect113r2;
-static const char *const SN_sect131r1;
-static const char *const SN_sect131r2;
-static const char *const SN_sect193r1;
-static const char *const SN_sect193r2;
-static const char *const SN_sect233k1;
-static const char *const SN_sect233r1;
-static const char *const SN_sect239k1;
-static const char *const SN_sect283k1;
-static const char *const SN_sect283r1;
-static const char *const SN_sect409k1;
-static const char *const SN_sect409r1;
-static const char *const SN_sect571k1;
-static const char *const SN_sect571r1;
-static const char *const SN_wap_wsg_idm_ecid_wtls1;
-static const char *const SN_wap_wsg_idm_ecid_wtls3;
-static const char *const SN_wap_wsg_idm_ecid_wtls4;
-static const char *const SN_wap_wsg_idm_ecid_wtls5;
-static const char *const SN_wap_wsg_idm_ecid_wtls6;
-static const char *const SN_wap_wsg_idm_ecid_wtls7;
-static const char *const SN_wap_wsg_idm_ecid_wtls8;
-static const char *const SN_wap_wsg_idm_ecid_wtls9;
-static const char *const SN_wap_wsg_idm_ecid_wtls10;
-static const char *const SN_wap_wsg_idm_ecid_wtls11;
-static const char *const SN_wap_wsg_idm_ecid_wtls12;
-static const char *const SN_ipsec3;
-static const char *const SN_ipsec4;
+static const int NID_poly1305;
 
-static const int NID_subject_key_identifier;
-static const int NID_authority_key_identifier;
-static const int NID_policy_constraints;
-static const int NID_ext_key_usage;
-static const int NID_info_access;
-static const int NID_key_usage;
 static const int NID_subject_alt_name;
-static const int NID_issuer_alt_name;
-static const int NID_basic_constraints;
-static const int NID_issuing_distribution_point;
-static const int NID_certificate_issuer;
-static const int NID_name_constraints;
-static const int NID_crl_distribution_points;
-static const int NID_certificate_policies;
-static const int NID_inhibit_any_policy;
-
-static const int NID_private_key_usage_period;
-static const int NID_crl_number;
 static const int NID_crl_reason;
-static const int NID_invalidity_date;
-static const int NID_delta_crl;
-static const int NID_any_policy;
-static const int NID_policy_mappings;
-static const int NID_target_information;
-static const int NID_no_rev_avail;
 
-static const int NID_commonName;
-static const int NID_countryName;
-static const int NID_localityName;
-static const int NID_stateOrProvinceName;
-static const int NID_organizationName;
-static const int NID_organizationalUnitName;
-static const int NID_serialNumber;
-static const int NID_surname;
-static const int NID_givenName;
-static const int NID_title;
-static const int NID_generationQualifier;
-static const int NID_dnQualifier;
-static const int NID_pseudonym;
-static const int NID_domainComponent;
-static const int NID_pkcs9_emailAddress;
-
-static const int NID_ad_OCSP;
-static const int NID_ad_ca_issuers;
+static const int NID_pkcs7_signed;
 """
 
 FUNCTIONS = """
 """
 
 CUSTOMIZATIONS = """
-#ifndef NID_X25519
-static const long Cryptography_HAS_X25519 = 0;
-static const int NID_X25519 = 0;
-#else
-static const long Cryptography_HAS_X25519 = 1;
-#endif
 #ifndef NID_ED25519
 static const long Cryptography_HAS_ED25519 = 0;
 static const int NID_ED25519 = 0;
 #else
 static const long Cryptography_HAS_ED25519 = 1;
 #endif
-#ifndef NID_X448
-static const long Cryptography_HAS_X448 = 0;
-static const int NID_X448 = 0;
-#else
-static const long Cryptography_HAS_X448 = 1;
-#endif
 #ifndef NID_ED448
 static const long Cryptography_HAS_ED448 = 0;
 static const int NID_ED448 = 0;
 #else
 static const long Cryptography_HAS_ED448 = 1;
 #endif
+#ifndef NID_poly1305
+static const long Cryptography_HAS_POLY1305 = 0;
+static const int NID_poly1305 = 0;
+#else
+static const long Cryptography_HAS_POLY1305 = 1;
+#endif
 """
diff --git a/src/_cffi_src/openssl/objects.py b/src/_cffi_src/openssl/objects.py
index 265ac75..236903d 100644
--- a/src/_cffi_src/openssl/objects.py
+++ b/src/_cffi_src/openssl/objects.py
@@ -20,21 +20,13 @@
 """
 
 FUNCTIONS = """
-ASN1_OBJECT *OBJ_nid2obj(int);
 const char *OBJ_nid2ln(int);
 const char *OBJ_nid2sn(int);
 int OBJ_obj2nid(const ASN1_OBJECT *);
-int OBJ_ln2nid(const char *);
 int OBJ_sn2nid(const char *);
 int OBJ_txt2nid(const char *);
 ASN1_OBJECT *OBJ_txt2obj(const char *, int);
 int OBJ_obj2txt(char *, int, const ASN1_OBJECT *, int);
-int OBJ_cmp(const ASN1_OBJECT *, const ASN1_OBJECT *);
-ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *);
-int OBJ_create(const char *, const char *, const char *);
-void OBJ_NAME_do_all(int, void (*) (const OBJ_NAME *, void *), void *);
-/* OBJ_cleanup became a macro in 1.1.0 */
-void OBJ_cleanup(void);
 """
 
 CUSTOMIZATIONS = """
diff --git a/src/_cffi_src/openssl/ocsp.py b/src/_cffi_src/openssl/ocsp.py
index 829314a..c3d034c 100644
--- a/src/_cffi_src/openssl/ocsp.py
+++ b/src/_cffi_src/openssl/ocsp.py
@@ -46,8 +46,6 @@
 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);
-int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *);
-X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *, 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 *);
@@ -59,7 +57,6 @@
 OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *, OCSP_CERTID *, int,
                                         int, ASN1_TIME *, ASN1_TIME *,
                                         ASN1_TIME *);
-int OCSP_basic_add1_nonce(OCSP_BASICRESP *, unsigned char *, int);
 int OCSP_basic_add1_cert(OCSP_BASICRESP *, X509 *);
 int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *, X509_EXTENSION *, int);
 int OCSP_basic_sign(OCSP_BASICRESP *, X509 *, EVP_PKEY *, const EVP_MD *,
@@ -69,7 +66,6 @@
 
 OCSP_REQUEST *OCSP_REQUEST_new(void);
 void OCSP_REQUEST_free(OCSP_REQUEST *);
-int OCSP_request_add1_nonce(OCSP_REQUEST *, unsigned char *, int);
 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 *);
@@ -82,7 +78,7 @@
 
 CUSTOMIZATIONS = """
 #if ( \
-    CRYPTOGRAPHY_OPENSSL_110_OR_GREATER && \
+    !CRYPTOGRAPHY_IS_LIBRESSL && \
     CRYPTOGRAPHY_OPENSSL_LESS_THAN_110J \
     )
 /* These structs come from ocsp_lcl.h and are needed to de-opaque the struct
@@ -109,7 +105,7 @@
 };
 #endif
 
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
+#if CRYPTOGRAPHY_IS_LIBRESSL
 /* These functions are all taken from ocsp_cl.c in OpenSSL 1.1.0 */
 const OCSP_CERTID *OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *single)
 {
@@ -151,7 +147,7 @@
 #if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110J
 const X509_ALGOR *OCSP_resp_get0_tbs_sigalg(const OCSP_BASICRESP *bs)
 {
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
+#if CRYPTOGRAPHY_IS_LIBRESSL
     return bs->signatureAlgorithm;
 #else
     return &bs->signatureAlgorithm;
@@ -160,7 +156,7 @@
 
 const OCSP_RESPDATA *OCSP_resp_get0_respdata(const OCSP_BASICRESP *bs)
 {
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
+#if CRYPTOGRAPHY_IS_LIBRESSL
     return bs->tbsResponseData;
 #else
     return &bs->tbsResponseData;
diff --git a/src/_cffi_src/openssl/pem.py b/src/_cffi_src/openssl/pem.py
index 55519bb..3f279c4 100644
--- a/src/_cffi_src/openssl/pem.py
+++ b/src/_cffi_src/openssl/pem.py
@@ -24,13 +24,9 @@
 
 int PEM_write_bio_PKCS8PrivateKey(BIO *, EVP_PKEY *, const EVP_CIPHER *,
                                   char *, int, pem_password_cb *, void *);
-int PEM_write_bio_PKCS8PrivateKey_nid(BIO *, EVP_PKEY *, int, char *, int,
-                                      pem_password_cb *, void *);
 
 int i2d_PKCS8PrivateKey_bio(BIO *, EVP_PKEY *, const EVP_CIPHER *,
                             char *, int, pem_password_cb *, void *);
-int i2d_PKCS8PrivateKey_nid_bio(BIO *, EVP_PKEY *, int,
-                                char *, int, pem_password_cb *, void *);
 
 int i2d_PKCS7_bio(BIO *, PKCS7 *);
 PKCS7 *d2i_PKCS7_bio(BIO *, PKCS7 **);
@@ -46,17 +42,11 @@
 
 int PEM_write_bio_X509_CRL(BIO *, X509_CRL *);
 
-X509 *PEM_read_bio_X509_AUX(BIO *, X509 **, pem_password_cb *, void *);
-
 PKCS7 *PEM_read_bio_PKCS7(BIO *, PKCS7 **, pem_password_cb *, void *);
 int PEM_write_bio_PKCS7(BIO *, PKCS7 *);
 
 DH *PEM_read_bio_DHparams(BIO *, DH **, pem_password_cb *, void *);
 
-DSA *PEM_read_bio_DSAPrivateKey(BIO *, DSA **, pem_password_cb *, void *);
-
-RSA *PEM_read_bio_RSAPrivateKey(BIO *, RSA **, pem_password_cb *, void *);
-
 int PEM_write_bio_DSAPrivateKey(BIO *, DSA *, const EVP_CIPHER *,
                                 unsigned char *, int,
                                 pem_password_cb *, void *);
@@ -65,12 +55,8 @@
                                 unsigned char *, int,
                                 pem_password_cb *, void *);
 
-DSA *PEM_read_bio_DSA_PUBKEY(BIO *, DSA **, pem_password_cb *, void *);
-
 RSA *PEM_read_bio_RSAPublicKey(BIO *, RSA **, pem_password_cb *, void *);
 
-int PEM_write_bio_DSA_PUBKEY(BIO *, DSA *);
-
 int PEM_write_bio_RSAPublicKey(BIO *, const RSA *);
 
 EVP_PKEY *PEM_read_bio_PUBKEY(BIO *, EVP_PKEY **, pem_password_cb *, void *);
diff --git a/src/_cffi_src/openssl/pkcs7.py b/src/_cffi_src/openssl/pkcs7.py
index 1bece5b..c22263d 100644
--- a/src/_cffi_src/openssl/pkcs7.py
+++ b/src/_cffi_src/openssl/pkcs7.py
@@ -24,6 +24,7 @@
 typedef ... PKCS7_DIGEST;
 typedef ... PKCS7_ENCRYPT;
 typedef ... PKCS7_ENVELOPE;
+typedef ... PKCS7_SIGNER_INFO;
 
 typedef struct {
     ASN1_OBJECT *type;
@@ -51,33 +52,28 @@
 static const int PKCS7_NOVERIFY;
 static const int PKCS7_STREAM;
 static const int PKCS7_TEXT;
+static const int PKCS7_PARTIAL;
 """
 
 FUNCTIONS = """
-PKCS7 *SMIME_read_PKCS7(BIO *, BIO **);
-int SMIME_write_PKCS7(BIO *, PKCS7 *, BIO *, int);
-
 void PKCS7_free(PKCS7 *);
-
 PKCS7 *PKCS7_sign(X509 *, EVP_PKEY *, Cryptography_STACK_OF_X509 *,
-                  BIO *, int);
+                   BIO *, int);
+int SMIME_write_PKCS7(BIO *, PKCS7 *, BIO *, int);
+int PEM_write_bio_PKCS7_stream(BIO *, PKCS7 *, BIO *, int);
+PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *, X509 *, EVP_PKEY *,
+                                         const EVP_MD *, int);
+int PKCS7_final(PKCS7 *, BIO *, int);
+/* Included verify due to external consumer, see
+   https://github.com/pyca/cryptography/issues/5433 */
 int PKCS7_verify(PKCS7 *, Cryptography_STACK_OF_X509 *, X509_STORE *, BIO *,
                  BIO *, int);
-Cryptography_STACK_OF_X509 *PKCS7_get0_signers(PKCS7 *,
-                                               Cryptography_STACK_OF_X509 *,
-                                               int);
+PKCS7 *SMIME_read_PKCS7(BIO *, BIO **);
 
-PKCS7 *PKCS7_encrypt(Cryptography_STACK_OF_X509 *, BIO *,
-                     const EVP_CIPHER *, int);
-int PKCS7_decrypt(PKCS7 *, EVP_PKEY *, X509 *, BIO *, int);
-
-BIO *PKCS7_dataInit(PKCS7 *, BIO *);
-int PKCS7_type_is_encrypted(PKCS7 *);
 int PKCS7_type_is_signed(PKCS7 *);
 int PKCS7_type_is_enveloped(PKCS7 *);
 int PKCS7_type_is_signedAndEnveloped(PKCS7 *);
 int PKCS7_type_is_data(PKCS7 *);
-int PKCS7_type_is_digest(PKCS7 *);
 """
 
 CUSTOMIZATIONS = ""
diff --git a/src/_cffi_src/openssl/rand.py b/src/_cffi_src/openssl/rand.py
index 6865392..1bc2ec0 100644
--- a/src/_cffi_src/openssl/rand.py
+++ b/src/_cffi_src/openssl/rand.py
@@ -9,10 +9,11 @@
 """
 
 TYPES = """
-static const long Cryptography_HAS_EGD;
+typedef ... RAND_METHOD;
 """
 
 FUNCTIONS = """
+int RAND_set_rand_method(const RAND_METHOD *);
 void RAND_add(const void *, int, double);
 int RAND_status(void);
 int RAND_bytes(unsigned char *, int);
@@ -21,11 +22,7 @@
    1 we'll just lie about the signature to preserve compatibility for
    pyOpenSSL (which calls this in its rand.py as of mid-2016) */
 void ERR_load_RAND_strings(void);
-
-/* RAND_cleanup became a macro in 1.1.0 */
-void RAND_cleanup(void);
 """
 
 CUSTOMIZATIONS = """
-static const long Cryptography_HAS_EGD = 0;
 """
diff --git a/src/_cffi_src/openssl/rsa.py b/src/_cffi_src/openssl/rsa.py
index 216e633..92b8fa4 100644
--- a/src/_cffi_src/openssl/rsa.py
+++ b/src/_cffi_src/openssl/rsa.py
@@ -17,7 +17,6 @@
 static const int RSA_PKCS1_PSS_PADDING;
 static const int RSA_F4;
 
-static const int Cryptography_HAS_PSS_PADDING;
 static const int Cryptography_HAS_RSA_OAEP_MD;
 static const int Cryptography_HAS_RSA_OAEP_LABEL;
 """
@@ -25,19 +24,10 @@
 FUNCTIONS = """
 RSA *RSA_new(void);
 void RSA_free(RSA *);
-int RSA_size(const RSA *);
 int RSA_generate_key_ex(RSA *, int, BIGNUM *, BN_GENCB *);
 int RSA_check_key(const RSA *);
 RSA *RSAPublicKey_dup(RSA *);
 int RSA_blinding_on(RSA *, BN_CTX *);
-int RSA_public_encrypt(int, const unsigned char *, unsigned char *,
-                       RSA *, int);
-int RSA_private_encrypt(int, const unsigned char *, unsigned char *,
-                        RSA *, int);
-int RSA_public_decrypt(int, const unsigned char *, unsigned char *,
-                       RSA *, int);
-int RSA_private_decrypt(int, const unsigned char *, unsigned char *,
-                        RSA *, int);
 int RSA_print(BIO *, const RSA *, int);
 
 /* added in 1.1.0 when the RSA struct was opaqued */
@@ -58,127 +48,14 @@
 """
 
 CUSTOMIZATIONS = """
-static const long Cryptography_HAS_PSS_PADDING = 1;
-
-#if defined(EVP_PKEY_CTX_set_rsa_oaep_md)
+#if !CRYPTOGRAPHY_IS_LIBRESSL
 static const long Cryptography_HAS_RSA_OAEP_MD = 1;
-#else
-static const long Cryptography_HAS_RSA_OAEP_MD = 0;
-int (*EVP_PKEY_CTX_set_rsa_oaep_md)(EVP_PKEY_CTX *, EVP_MD *) = NULL;
-#endif
-
-#if defined(EVP_PKEY_CTX_set0_rsa_oaep_label)
 static const long Cryptography_HAS_RSA_OAEP_LABEL = 1;
 #else
+static const long Cryptography_HAS_RSA_OAEP_MD = 0;
 static const long Cryptography_HAS_RSA_OAEP_LABEL = 0;
+int (*EVP_PKEY_CTX_set_rsa_oaep_md)(EVP_PKEY_CTX *, EVP_MD *) = NULL;
 int (*EVP_PKEY_CTX_set0_rsa_oaep_label)(EVP_PKEY_CTX *, unsigned char *,
                                         int) = NULL;
 #endif
-
-/* These functions were added in OpenSSL 1.1.0 */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
-{
-    /* If the fields n and e in r are NULL, the corresponding input
-     * parameters MUST be non-NULL for n and e.  d may be
-     * left NULL (in case only the public key is used).
-     */
-    if ((r->n == NULL && n == NULL)
-        || (r->e == NULL && e == NULL))
-        return 0;
-
-    if (n != NULL) {
-        BN_free(r->n);
-        r->n = n;
-    }
-    if (e != NULL) {
-        BN_free(r->e);
-        r->e = e;
-    }
-    if (d != NULL) {
-        BN_free(r->d);
-        r->d = d;
-    }
-
-    return 1;
-}
-
-int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
-{
-    /* If the fields p and q in r are NULL, the corresponding input
-     * parameters MUST be non-NULL.
-     */
-    if ((r->p == NULL && p == NULL)
-        || (r->q == NULL && q == NULL))
-        return 0;
-
-    if (p != NULL) {
-        BN_free(r->p);
-        r->p = p;
-    }
-    if (q != NULL) {
-        BN_free(r->q);
-        r->q = q;
-    }
-
-    return 1;
-}
-
-int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
-{
-    /* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input
-     * parameters MUST be non-NULL.
-     */
-    if ((r->dmp1 == NULL && dmp1 == NULL)
-        || (r->dmq1 == NULL && dmq1 == NULL)
-        || (r->iqmp == NULL && iqmp == NULL))
-        return 0;
-
-    if (dmp1 != NULL) {
-        BN_free(r->dmp1);
-        r->dmp1 = dmp1;
-    }
-    if (dmq1 != NULL) {
-        BN_free(r->dmq1);
-        r->dmq1 = dmq1;
-    }
-    if (iqmp != NULL) {
-        BN_free(r->iqmp);
-        r->iqmp = iqmp;
-    }
-
-    return 1;
-}
-
-void RSA_get0_key(const RSA *r,
-                  const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
-{
-    if (n != NULL)
-        *n = r->n;
-    if (e != NULL)
-        *e = r->e;
-    if (d != NULL)
-        *d = r->d;
-}
-
-void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
-{
-    if (p != NULL)
-        *p = r->p;
-    if (q != NULL)
-        *q = r->q;
-}
-
-void RSA_get0_crt_params(const RSA *r,
-                         const BIGNUM **dmp1, const BIGNUM **dmq1,
-                         const BIGNUM **iqmp)
-{
-    if (dmp1 != NULL)
-        *dmp1 = r->dmp1;
-    if (dmq1 != NULL)
-        *dmq1 = r->dmq1;
-    if (iqmp != NULL)
-        *iqmp = r->iqmp;
-}
-#endif
 """
diff --git a/src/_cffi_src/openssl/src/osrandom_engine.c b/src/_cffi_src/openssl/src/osrandom_engine.c
index 697381c..a84857b 100644
--- a/src/_cffi_src/openssl/src/osrandom_engine.c
+++ b/src/_cffi_src/openssl/src/osrandom_engine.c
@@ -17,6 +17,9 @@
 #include <poll.h>
 #endif
 
+#if CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE
+/* OpenSSL has ENGINE support and is older than 1.1.1d (the first version that
+ * properly implements fork safety in its RNG) so build the engine. */
 static const char *Cryptography_osrandom_engine_id = "osrandom";
 
 /****************************************************************************
@@ -94,7 +97,18 @@
     ino_t st_ino;
 } urandom_cache = { -1 };
 
-static int set_cloexec(int fd) {
+static int open_cloexec(const char *path) {
+    int open_flags = O_RDONLY;
+#ifdef O_CLOEXEC
+    open_flags |= O_CLOEXEC;
+#endif
+
+    int fd = open(path, open_flags);
+    if (fd == -1) {
+        return -1;
+    }
+
+#ifndef O_CLOEXEC
     int flags = fcntl(fd, F_GETFD);
     if (flags == -1) {
         return -1;
@@ -102,7 +116,8 @@
     if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
         return -1;
     }
-    return 0;
+#endif
+    return fd;
 }
 
 #ifdef __linux__
@@ -114,13 +129,10 @@
 static int wait_on_devrandom(void) {
     struct pollfd pfd = {};
     int ret = 0;
-    int random_fd = open("/dev/random", O_RDONLY);
+    int random_fd = open_cloexec("/dev/random");
     if (random_fd < 0) {
         return -1;
     }
-    if (set_cloexec(random_fd) < 0) {
-        return -1;
-    }
     pfd.fd = random_fd;
     pfd.events = POLLIN;
     pfd.revents = 0;
@@ -154,13 +166,10 @@
         }
 #endif
 
-        fd = open("/dev/urandom", O_RDONLY);
+        fd = open_cloexec("/dev/urandom");
         if (fd < 0) {
             goto error;
         }
-        if (set_cloexec(fd) < 0) {
-            goto error;
-        }
         if (fstat(fd, &st)) {
             goto error;
         }
@@ -243,7 +252,7 @@
 #if !defined(__APPLE__)
     getentropy_works = CRYPTOGRAPHY_OSRANDOM_GETENTROPY_WORKS;
 #else
-    if (&getentropy != NULL) {
+    if (__builtin_available(macOS 10.12, *)) {
         getentropy_works = CRYPTOGRAPHY_OSRANDOM_GETENTROPY_WORKS;
     } else {
         getentropy_works = CRYPTOGRAPHY_OSRANDOM_GETENTROPY_FALLBACK;
@@ -269,7 +278,11 @@
         while (size > 0) {
             /* OpenBSD and macOS restrict maximum buffer size to 256. */
             len = size > 256 ? 256 : size;
+/* on mac, availability is already checked using `__builtin_available` above */
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunguarded-availability"
             res = getentropy(buffer, (size_t)len);
+#pragma clang diagnostic pop
             if (res < 0) {
                 ERR_Cryptography_OSRandom_error(
                     CRYPTOGRAPHY_OSRANDOM_F_RAND_BYTES,
@@ -516,7 +529,7 @@
             ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_INVALID_ARGUMENT);
             return 0;
         }
-        strncpy((char *)p, name, len);
+        strcpy((char *)p, name);
         return (int)len;
     default:
         ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
@@ -632,3 +645,16 @@
 
     return 1;
 }
+
+#else
+/* If OpenSSL has no ENGINE support then we don't want
+ * to compile the osrandom engine, but we do need some
+ * placeholders */
+static const char *Cryptography_osrandom_engine_id = "no-engine-support";
+static const char *Cryptography_osrandom_engine_name = "osrandom_engine disabled";
+
+int Cryptography_add_osrandom_engine(void) {
+    return 0;
+}
+
+#endif
diff --git a/src/_cffi_src/openssl/src/osrandom_engine.h b/src/_cffi_src/openssl/src/osrandom_engine.h
index 53f957f..93d918b 100644
--- a/src/_cffi_src/openssl/src/osrandom_engine.h
+++ b/src/_cffi_src/openssl/src/osrandom_engine.h
@@ -1,10 +1,14 @@
+#ifndef OPENSSL_NO_ENGINE
+/* OpenSSL has ENGINE support so include all of this. */
 #ifdef _WIN32
   #include <Wincrypt.h>
 #else
   #include <fcntl.h>
   #include <unistd.h>
    /* for defined(BSD) */
-  #include <sys/param.h>
+  #ifndef __MVS__
+    #include <sys/param.h>
+  #endif
 
   #ifdef BSD
     /* for SYS_getentropy */
@@ -24,6 +28,20 @@
     #ifndef GRND_NONBLOCK
       #define GRND_NONBLOCK 0x0001
     #endif /* GRND_NONBLOCK */
+
+    #ifndef SYS_getrandom
+      /* We only bother to define the constants for platforms where we ship
+       * wheels, since that's the predominant way you get a situation where
+       * you don't have SYS_getrandom at compile time but do have the syscall
+       * at runtime */
+      #if defined(__x86_64__)
+        #define SYS_getrandom 318
+      #elif defined(__i386__)
+        #define SYS_getrandom 355
+      #elif defined(__aarch64__)
+        #define SYS_getrandom 278
+      #endif
+    #endif
   #endif /* __linux__ */
 #endif /* _WIN32 */
 
@@ -97,3 +115,4 @@
 #define CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_INIT_FAILED_UNEXPECTED 402
 #define CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_FAILED 403
 #define CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_NOT_INIT 404
+#endif
diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py
index 2218095..9400f11 100644
--- a/src/_cffi_src/openssl/ssl.py
+++ b/src/_cffi_src/openssl/ssl.py
@@ -13,26 +13,18 @@
 TYPES = """
 static const long Cryptography_HAS_SSL_ST;
 static const long Cryptography_HAS_TLS_ST;
-static const long Cryptography_HAS_SSL2;
 static const long Cryptography_HAS_SSL3_METHOD;
 static const long Cryptography_HAS_TLSv1_1;
 static const long Cryptography_HAS_TLSv1_2;
 static const long Cryptography_HAS_TLSv1_3;
 static const long Cryptography_HAS_SECURE_RENEGOTIATION;
-static const long Cryptography_HAS_COMPRESSION;
-static const long Cryptography_HAS_TLSEXT_STATUS_REQ_CB;
-static const long Cryptography_HAS_STATUS_REQ_OCSP_RESP;
-static const long Cryptography_HAS_TLSEXT_STATUS_REQ_TYPE;
-static const long Cryptography_HAS_GET_SERVER_TMP_KEY;
-static const long Cryptography_HAS_SSL_CTX_SET_CLIENT_CERT_ENGINE;
 static const long Cryptography_HAS_SSL_CTX_CLEAR_OPTIONS;
 static const long Cryptography_HAS_DTLS;
-static const long Cryptography_HAS_GENERIC_DTLS_METHOD;
 static const long Cryptography_HAS_SIGALGS;
 static const long Cryptography_HAS_PSK;
-static const long Cryptography_HAS_CIPHER_DETAILS;
-
-/* Internally invented symbol to tell us if SNI is supported */
+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
@@ -51,6 +43,7 @@
 static const long Cryptography_HAS_NEXTPROTONEG;
 static const long Cryptography_HAS_SET_CERT_CB;
 static const long Cryptography_HAS_CUSTOM_EXT;
+static const long Cryptography_HAS_SRTP;
 
 static const long SSL_FILETYPE_PEM;
 static const long SSL_FILETYPE_ASN1;
@@ -139,8 +132,6 @@
 static const long TLS_ST_BEFORE;
 static const long TLS_ST_OK;
 
-static const long OPENSSL_NPN_NEGOTIATED;
-
 typedef ... SSL_METHOD;
 typedef ... SSL_CTX;
 
@@ -153,7 +144,6 @@
 
 typedef ... SSL_CIPHER;
 typedef ... Cryptography_STACK_OF_SSL_CIPHER;
-typedef ... COMP_METHOD;
 
 typedef struct {
     const char *name;
@@ -166,20 +156,10 @@
 const char *SSL_state_string_long(const SSL *);
 SSL_SESSION *SSL_get1_session(SSL *);
 int SSL_set_session(SSL *, SSL_SESSION *);
-int SSL_get_verify_mode(const SSL *);
-void SSL_set_verify(SSL *, int, int (*)(int, X509_STORE_CTX *));
-void SSL_set_verify_depth(SSL *, int);
-int SSL_get_verify_depth(const SSL *);
-int (*SSL_get_verify_callback(const SSL *))(int, X509_STORE_CTX *);
-void SSL_set_info_callback(SSL *ssl, void (*)(const SSL *, int, int));
-void (*SSL_get_info_callback(const SSL *))(const SSL *, int, int);
 SSL *SSL_new(SSL_CTX *);
 void SSL_free(SSL *);
 int SSL_set_fd(SSL *, int);
-SSL_CTX *SSL_get_SSL_CTX(const SSL *);
 SSL_CTX *SSL_set_SSL_CTX(SSL *, SSL_CTX *);
-BIO *SSL_get_rbio(const SSL *);
-BIO *SSL_get_wbio(const SSL *);
 void SSL_set_bio(SSL *, BIO *, BIO *);
 void SSL_set_connect_state(SSL *);
 void SSL_set_accept_state(SSL *);
@@ -195,28 +175,22 @@
 
 /* Added in 1.0.2 */
 X509_VERIFY_PARAM *SSL_get0_param(SSL *);
-
-int SSL_use_certificate(SSL *, X509 *);
-int SSL_use_certificate_ASN1(SSL *, const unsigned char *, int);
-int SSL_use_certificate_file(SSL *, const char *, int);
-int SSL_use_PrivateKey(SSL *, EVP_PKEY *);
-int SSL_use_PrivateKey_ASN1(int, SSL *, const unsigned char *, long);
-int SSL_use_PrivateKey_file(SSL *, const char *, int);
-int SSL_check_private_key(const SSL *);
+X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *);
 
 int SSL_get_sigalgs(SSL *, int, int *, int *, int *, unsigned char *,
                     unsigned char *);
 
 Cryptography_STACK_OF_X509 *SSL_get_peer_cert_chain(const SSL *);
+Cryptography_STACK_OF_X509 *SSL_get0_verified_chain(const SSL *);
 Cryptography_STACK_OF_X509_NAME *SSL_get_client_CA_list(const SSL *);
 
 int SSL_get_error(const SSL *, int);
+long SSL_get_verify_result(const SSL *ssl);
 int SSL_do_handshake(SSL *);
 int SSL_shutdown(SSL *);
 int SSL_renegotiate(SSL *);
 int SSL_renegotiate_pending(SSL *);
 const char *SSL_get_cipher_list(const SSL *, int);
-Cryptography_STACK_OF_SSL_CIPHER *SSL_get_ciphers(const SSL *);
 
 /*  context */
 void SSL_CTX_free(SSL_CTX *);
@@ -224,7 +198,6 @@
 int SSL_CTX_set_default_verify_paths(SSL_CTX *);
 void SSL_CTX_set_verify(SSL_CTX *, int, int (*)(int, X509_STORE_CTX *));
 void SSL_CTX_set_verify_depth(SSL_CTX *, int);
-int (*SSL_CTX_get_verify_callback(const SSL_CTX *))(int, X509_STORE_CTX *);
 int SSL_CTX_get_verify_mode(const SSL_CTX *);
 int SSL_CTX_get_verify_depth(const SSL_CTX *);
 int SSL_CTX_set_cipher_list(SSL_CTX *, const char *);
@@ -232,11 +205,9 @@
 void SSL_CTX_set_default_passwd_cb(SSL_CTX *, pem_password_cb *);
 void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *, void *);
 int SSL_CTX_use_certificate(SSL_CTX *, X509 *);
-int SSL_CTX_use_certificate_ASN1(SSL_CTX *, int, const unsigned char *);
 int SSL_CTX_use_certificate_file(SSL_CTX *, const char *, int);
 int SSL_CTX_use_certificate_chain_file(SSL_CTX *, const char *);
 int SSL_CTX_use_PrivateKey(SSL_CTX *, EVP_PKEY *);
-int SSL_CTX_use_PrivateKey_ASN1(int, SSL_CTX *, const unsigned char *, long);
 int SSL_CTX_use_PrivateKey_file(SSL_CTX *, const char *, int);
 int SSL_CTX_check_private_key(const SSL_CTX *);
 void SSL_CTX_set_cert_verify_callback(SSL_CTX *,
@@ -282,6 +253,10 @@
 void SSL_CTX_set_info_callback(SSL_CTX *, void (*)(const SSL *, int, int));
 void (*SSL_CTX_get_info_callback(SSL_CTX *))(const SSL *, int, int);
 
+void SSL_CTX_set_keylog_callback(SSL_CTX *,
+                                 void (*)(const SSL *, const char *));
+void (*SSL_CTX_get_keylog_callback(SSL_CTX *))(const SSL *, const char *);
+
 long SSL_CTX_set1_sigalgs_list(SSL_CTX *, const char *);
 
 /*  SSL_SESSION */
@@ -326,38 +301,36 @@
 int SSL_SESSION_has_ticket(const SSL_SESSION *);
 long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *);
 
-/* not a macro, but older OpenSSLs don't pass the args as const */
-char *SSL_CIPHER_description(const SSL_CIPHER *, char *, int);
-int SSL_SESSION_print(BIO *, const SSL_SESSION *);
-
-/* not macros, but will be conditionally bound so can't live in functions */
-const COMP_METHOD *SSL_get_current_compression(SSL *);
-const COMP_METHOD *SSL_get_current_expansion(SSL *);
-const char *SSL_COMP_get_name(const COMP_METHOD *);
-int SSL_CTX_set_client_cert_engine(SSL_CTX *, ENGINE *);
-
 unsigned long SSL_set_mode(SSL *, unsigned long);
+unsigned long SSL_clear_mode(SSL *, unsigned long);
 unsigned long SSL_get_mode(SSL *);
 
 unsigned long SSL_set_options(SSL *, unsigned long);
 unsigned long SSL_get_options(SSL *);
 
-void SSL_set_app_data(SSL *, char *);
-char * SSL_get_app_data(SSL *);
-void SSL_set_read_ahead(SSL *, int);
-
 int SSL_want_read(const SSL *);
 int SSL_want_write(const SSL *);
 
 long SSL_total_renegotiations(SSL *);
 long SSL_get_secure_renegotiation_support(SSL *);
 
+long SSL_CTX_set_min_proto_version(SSL_CTX *, int);
+long SSL_CTX_set_max_proto_version(SSL_CTX *, int);
+long SSL_set_min_proto_version(SSL *, int);
+long SSL_set_max_proto_version(SSL *, int);
+
+long SSL_CTX_get_min_proto_version(SSL_CTX *);
+long SSL_CTX_get_max_proto_version(SSL_CTX *);
+long SSL_get_min_proto_version(SSL *);
+long SSL_get_max_proto_version(SSL *);
+
 /* Defined as unsigned long because SSL_OP_ALL is greater than signed 32-bit
    and Windows defines long as 32-bit. */
 unsigned long SSL_CTX_set_options(SSL_CTX *, unsigned long);
 unsigned long SSL_CTX_clear_options(SSL_CTX *, unsigned long);
 unsigned long SSL_CTX_get_options(SSL_CTX *);
 unsigned long SSL_CTX_set_mode(SSL_CTX *, unsigned long);
+unsigned long SSL_CTX_clear_mode(SSL_CTX *, unsigned long);
 unsigned long SSL_CTX_get_mode(SSL_CTX *);
 unsigned long SSL_CTX_set_session_cache_mode(SSL_CTX *, unsigned long);
 unsigned long SSL_CTX_get_session_cache_mode(SSL_CTX *);
@@ -369,10 +342,6 @@
 
 /*  methods */
 
-/*
- * TLSv1_1 and TLSv1_2 are recent additions.  Only sufficiently new versions of
- * OpenSSL support them.
- */
 const SSL_METHOD *TLSv1_1_method(void);
 const SSL_METHOD *TLSv1_1_server_method(void);
 const SSL_METHOD *TLSv1_1_client_method(void);
@@ -402,6 +371,10 @@
 const SSL_METHOD *SSLv23_server_method(void);
 const SSL_METHOD *SSLv23_client_method(void);
 
+const SSL_METHOD *TLS_method(void);
+const SSL_METHOD *TLS_server_method(void);
+const SSL_METHOD *TLS_client_method(void);
+
 /*- These aren't macros these arguments are all const X on openssl > 1.0.x -*/
 SSL_CTX *SSL_CTX_new(SSL_METHOD *);
 long SSL_CTX_get_timeout(const SSL_CTX *);
@@ -432,25 +405,9 @@
 
 long SSL_session_reused(SSL *);
 
-void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *,
-                                           int (*)(SSL *,
-                                                   const unsigned char **,
-                                                   unsigned int *,
-                                                   void *),
-                                           void *);
-void SSL_CTX_set_next_proto_select_cb(SSL_CTX *,
-                                      int (*)(SSL *,
-                                              unsigned char **,
-                                              unsigned char *,
-                                              const unsigned char *,
-                                              unsigned int,
-                                              void *),
-                                      void *);
 int SSL_select_next_proto(unsigned char **, unsigned char *,
                           const unsigned char *, unsigned int,
                           const unsigned char *, unsigned int);
-void SSL_get0_next_proto_negotiated(const SSL *,
-                                    const unsigned char **, unsigned *);
 
 int sk_SSL_CIPHER_num(Cryptography_STACK_OF_SSL_CIPHER *);
 const SSL_CIPHER *sk_SSL_CIPHER_value(Cryptography_STACK_OF_SSL_CIPHER *, int);
@@ -478,9 +435,6 @@
 void SSL_CTX_set_cert_cb(SSL_CTX *, int (*)(SSL *, void *), void *);
 void SSL_set_cert_cb(SSL *, int (*)(SSL *, void *), void *);
 
-/* Added in 1.0.2 */
-const SSL_METHOD *SSL_CTX_get_ssl_method(SSL_CTX *);
-
 int SSL_SESSION_set1_id_context(SSL_SESSION *, const unsigned char *,
                                 unsigned int);
 /* Added in 1.1.0 for the great opaquing of structs */
@@ -551,75 +505,33 @@
 """
 
 CUSTOMIZATIONS = """
-/* Added in 1.0.2 but we need it in all versions now due to the great
-   opaquing. */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_102
-/* from ssl/ssl_lib.c */
-const SSL_METHOD *SSL_CTX_get_ssl_method(SSL_CTX *ctx) {
-    return ctx->method;
-}
+// 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;
+#else
+static const long Cryptography_HAS_VERIFIED_CHAIN = 1;
 #endif
 
-/* Added in 1.1.0 in the great opaquing, but we need to define it for older
-   OpenSSLs. Such is our burden. */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-/* from ssl/ssl_lib.c */
-size_t SSL_get_client_random(const SSL *ssl, unsigned char *out, size_t outlen)
-{
-    if (outlen == 0)
-        return sizeof(ssl->s3->client_random);
-    if (outlen > sizeof(ssl->s3->client_random))
-        outlen = sizeof(ssl->s3->client_random);
-    memcpy(out, ssl->s3->client_random, outlen);
-    return outlen;
-}
-/* Added in 1.1.0 as well */
-/* from ssl/ssl_lib.c */
-size_t SSL_get_server_random(const SSL *ssl, unsigned char *out, size_t outlen)
-{
-    if (outlen == 0)
-        return sizeof(ssl->s3->server_random);
-    if (outlen > sizeof(ssl->s3->server_random))
-        outlen = sizeof(ssl->s3->server_random);
-    memcpy(out, ssl->s3->server_random, outlen);
-    return outlen;
-}
-/* Added in 1.1.0 as well */
-/* from ssl/ssl_lib.c */
-size_t SSL_SESSION_get_master_key(const SSL_SESSION *session,
-                               unsigned char *out, size_t outlen)
-{
-    if (session->master_key_length < 0) {
-        /* Should never happen */
-        return 0;
-    }
-    if (outlen == 0)
-        return session->master_key_length;
-    if (outlen > (size_t)session->master_key_length)
-        outlen = session->master_key_length;
-    memcpy(out, session->master_key, outlen);
-    return outlen;
-}
-/* from ssl/ssl_sess.c */
-int SSL_SESSION_has_ticket(const SSL_SESSION *s)
-{
-    return (s->tlsext_ticklen > 0) ? 1 : 0;
-}
-/* from ssl/ssl_sess.c */
-unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s)
-{
-    return s->tlsext_tick_lifetime_hint;
-}
+#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_111
+static const long Cryptography_HAS_KEYLOG = 0;
+void (*SSL_CTX_set_keylog_callback)(SSL_CTX *,
+                                    void (*) (const SSL *, const char *)
+                                    ) = NULL;
+void (*(*SSL_CTX_get_keylog_callback)(SSL_CTX *))(
+                                                  const SSL *,
+                                                  const char *
+                                                  ) = NULL;
+#else
+static const long Cryptography_HAS_KEYLOG = 1;
 #endif
 
 static const long Cryptography_HAS_SECURE_RENEGOTIATION = 1;
 
-/* Cryptography now compiles out all SSLv2 bindings. This exists to allow
- * clients that use it to check for SSLv2 support to keep functioning as
- * expected.
- */
-static const long Cryptography_HAS_SSL2 = 0;
-
 #ifdef OPENSSL_NO_SSL3_METHOD
 static const long Cryptography_HAS_SSL3_METHOD = 0;
 SSL_METHOD* (*SSLv3_method)(void) = NULL;
@@ -629,10 +541,6 @@
 static const long Cryptography_HAS_SSL3_METHOD = 1;
 #endif
 
-static const long Cryptography_HAS_TLSEXT_HOSTNAME = 1;
-static const long Cryptography_HAS_TLSEXT_STATUS_REQ_CB = 1;
-static const long Cryptography_HAS_STATUS_REQ_OCSP_RESP = 1;
-static const long Cryptography_HAS_TLSEXT_STATUS_REQ_TYPE = 1;
 static const long Cryptography_HAS_RELEASE_BUFFERS = 1;
 static const long Cryptography_HAS_OP_NO_COMPRESSION = 1;
 static const long Cryptography_HAS_TLSv1_1 = 1;
@@ -640,38 +548,10 @@
 static const long Cryptography_HAS_SSL_OP_MSIE_SSLV2_RSA_PADDING = 1;
 static const long Cryptography_HAS_SSL_OP_NO_TICKET = 1;
 static const long Cryptography_HAS_SSL_SET_SSL_CTX = 1;
-static const long Cryptography_HAS_NEXTPROTONEG = 1;
-
-/* SSL_get0_param was added in OpenSSL 1.0.2. */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 && !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-X509_VERIFY_PARAM *(*SSL_get0_param)(SSL *) = NULL;
-#else
-#endif
-
-/* ALPN was added in OpenSSL 1.0.2. */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 && !CRYPTOGRAPHY_IS_LIBRESSL
-int (*SSL_CTX_set_alpn_protos)(SSL_CTX *,
-                               const unsigned char *,
-                               unsigned) = NULL;
-int (*SSL_set_alpn_protos)(SSL *, const unsigned char *, unsigned) = NULL;
-void (*SSL_CTX_set_alpn_select_cb)(SSL_CTX *,
-                                   int (*) (SSL *,
-                                            const unsigned char **,
-                                            unsigned char *,
-                                            const unsigned char *,
-                                            unsigned int,
-                                            void *),
-                                   void *) = NULL;
-void (*SSL_get0_alpn_selected)(const SSL *,
-                               const unsigned char **,
-                               unsigned *) = NULL;
-static const long Cryptography_HAS_ALPN = 0;
-#else
+static const long Cryptography_HAS_NEXTPROTONEG = 0;
 static const long Cryptography_HAS_ALPN = 1;
-#endif
 
-/* SSL_CTX_set_cert_cb was added in OpenSSL 1.0.2. */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_102
+#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;
 static const long Cryptography_HAS_SET_CERT_CB = 0;
@@ -679,31 +559,11 @@
 static const long Cryptography_HAS_SET_CERT_CB = 1;
 #endif
 
-
-/* In OpenSSL 1.0.2i+ the handling of COMP_METHOD when OPENSSL_NO_COMP was
-   changed and we no longer need to typedef void */
-#if (defined(OPENSSL_NO_COMP) && CRYPTOGRAPHY_OPENSSL_LESS_THAN_102I) || \
-    CRYPTOGRAPHY_IS_LIBRESSL
-static const long Cryptography_HAS_COMPRESSION = 0;
-typedef void COMP_METHOD;
-#else
-static const long Cryptography_HAS_COMPRESSION = 1;
-#endif
-
-#if defined(SSL_CTRL_GET_SERVER_TMP_KEY)
-static const long Cryptography_HAS_GET_SERVER_TMP_KEY = 1;
-#else
-static const long Cryptography_HAS_GET_SERVER_TMP_KEY = 0;
-long (*SSL_get_server_tmp_key)(SSL *, EVP_PKEY **) = NULL;
-#endif
-
-static const long Cryptography_HAS_SSL_CTX_SET_CLIENT_CERT_ENGINE = 1;
-
 static const long Cryptography_HAS_SSL_CTX_CLEAR_OPTIONS = 1;
 
 /* in OpenSSL 1.1.0 the SSL_ST values were renamed to TLS_ST and several were
    removed */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
+#if CRYPTOGRAPHY_IS_LIBRESSL
 static const long Cryptography_HAS_SSL_ST = 1;
 #else
 static const long Cryptography_HAS_SSL_ST = 0;
@@ -712,7 +572,7 @@
 static const long SSL_ST_INIT = 0;
 static const long SSL_ST_RENEGOTIATE = 0;
 #endif
-#if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
+#if !CRYPTOGRAPHY_IS_LIBRESSL
 static const long Cryptography_HAS_TLS_ST = 1;
 #else
 static const long Cryptography_HAS_TLS_ST = 0;
@@ -720,17 +580,11 @@
 static const long TLS_ST_OK = 0;
 #endif
 
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_102
-static const long Cryptography_HAS_GENERIC_DTLS_METHOD = 0;
-const SSL_METHOD *(*DTLS_method)(void) = NULL;
-const SSL_METHOD *(*DTLS_server_method)(void) = NULL;
-const SSL_METHOD *(*DTLS_client_method)(void) = NULL;
+#if CRYPTOGRAPHY_IS_LIBRESSL
 static const long SSL_OP_NO_DTLSv1 = 0;
 static const long SSL_OP_NO_DTLSv1_2 = 0;
 long (*DTLS_set_link_mtu)(SSL *, long) = NULL;
 long (*DTLS_get_link_min_mtu)(SSL *) = NULL;
-#else
-static const long Cryptography_HAS_GENERIC_DTLS_METHOD = 1;
 #endif
 
 static const long Cryptography_HAS_DTLS = 1;
@@ -753,7 +607,7 @@
     return r;
 }
 
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_102
+#if CRYPTOGRAPHY_IS_LIBRESSL
 static const long Cryptography_HAS_SIGALGS = 0;
 const int (*SSL_get_sigalgs)(SSL *, int, int *, int *, int *, unsigned char *,
                              unsigned char *) = NULL;
@@ -785,53 +639,41 @@
 static const long Cryptography_HAS_PSK = 1;
 #endif
 
-/*
- * Custom extensions were added in 1.0.2. 1.1.1 is adding a more general
- * SSL_CTX_add_custom_ext function, but we're not binding that yet.
- */
-#if CRYPTOGRAPHY_OPENSSL_102_OR_GREATER
+#if !CRYPTOGRAPHY_IS_LIBRESSL
 static const long Cryptography_HAS_CUSTOM_EXT = 1;
 #else
 static const long Cryptography_HAS_CUSTOM_EXT = 0;
-
 typedef int (*custom_ext_add_cb)(SSL *, unsigned int,
                                  const unsigned char **,
                                  size_t *, int *,
                                  void *);
-
 typedef void (*custom_ext_free_cb)(SSL *, unsigned int,
                                    const unsigned char *,
                                    void *);
-
 typedef int (*custom_ext_parse_cb)(SSL *, unsigned int,
                                    const unsigned char *,
                                    size_t, int *,
                                    void *);
-
 int (*SSL_CTX_add_client_custom_ext)(SSL_CTX *, unsigned int,
                                      custom_ext_add_cb,
                                      custom_ext_free_cb, void *,
                                      custom_ext_parse_cb,
                                      void *) = NULL;
-
 int (*SSL_CTX_add_server_custom_ext)(SSL_CTX *, unsigned int,
                                      custom_ext_add_cb,
                                      custom_ext_free_cb, void *,
                                      custom_ext_parse_cb,
                                      void *) = NULL;
-
 int (*SSL_extension_supported)(unsigned int) = NULL;
 #endif
 
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-int (*SSL_CIPHER_is_aead)(const SSL_CIPHER *) = NULL;
-int (*SSL_CIPHER_get_cipher_nid)(const SSL_CIPHER *) = NULL;
-int (*SSL_CIPHER_get_digest_nid)(const SSL_CIPHER *) = NULL;
-int (*SSL_CIPHER_get_kx_nid)(const SSL_CIPHER *) = NULL;
-int (*SSL_CIPHER_get_auth_nid)(const SSL_CIPHER *) = NULL;
-static const long Cryptography_HAS_CIPHER_DETAILS = 0;
+#ifndef OPENSSL_NO_SRTP
+static const long Cryptography_HAS_SRTP = 1;
 #else
-static const long Cryptography_HAS_CIPHER_DETAILS = 1;
+static const long Cryptography_HAS_SRTP = 0;
+int (*SSL_CTX_set_tlsext_use_srtp)(SSL_CTX *, const char *) = NULL;
+int (*SSL_set_tlsext_use_srtp)(SSL *, const char *) = NULL;
+SRTP_PROTECTION_PROFILE * (*SSL_get_selected_srtp_profile)(SSL *) = NULL;
 #endif
 
 #if CRYPTOGRAPHY_OPENSSL_LESS_THAN_111
@@ -849,4 +691,15 @@
 #else
 static const long Cryptography_HAS_TLSv1_3 = 1;
 #endif
+
+#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 && !CRYPTOGRAPHY_IS_LIBRESSL
+static const long Cryptography_HAS_GET_PROTO_VERSION = 0;
+
+long (*SSL_CTX_get_min_proto_version)(SSL_CTX *) = NULL;
+long (*SSL_CTX_get_max_proto_version)(SSL_CTX *) = NULL;
+long (*SSL_get_min_proto_version)(SSL *) = NULL;
+long (*SSL_get_max_proto_version)(SSL *) = NULL;
+#else
+static const long Cryptography_HAS_GET_PROTO_VERSION = 1;
+#endif
 """
diff --git a/src/_cffi_src/openssl/x509.py b/src/_cffi_src/openssl/x509.py
index 748c6c8..24946ea 100644
--- a/src/_cffi_src/openssl/x509.py
+++ b/src/_cffi_src/openssl/x509.py
@@ -30,13 +30,10 @@
 } X509_ALGOR;
 
 typedef ... X509_ATTRIBUTE;
-typedef ... X509_CINF;
 typedef ... X509_EXTENSION;
 typedef ... X509_EXTENSIONS;
 typedef ... X509_REQ;
-typedef ... X509_REQ_INFO;
 typedef ... X509_REVOKED;
-typedef ... X509_CRL_INFO;
 typedef ... X509_CRL;
 typedef ... X509;
 
@@ -44,39 +41,6 @@
 
 typedef ... PKCS8_PRIV_KEY_INFO;
 
-static const int X509_FLAG_COMPAT;
-static const int X509_FLAG_NO_HEADER;
-static const int X509_FLAG_NO_VERSION;
-static const int X509_FLAG_NO_SERIAL;
-static const int X509_FLAG_NO_SIGNAME;
-static const int X509_FLAG_NO_ISSUER;
-static const int X509_FLAG_NO_VALIDITY;
-static const int X509_FLAG_NO_SUBJECT;
-static const int X509_FLAG_NO_PUBKEY;
-static const int X509_FLAG_NO_EXTENSIONS;
-static const int X509_FLAG_NO_SIGDUMP;
-static const int X509_FLAG_NO_AUX;
-static const int X509_FLAG_NO_ATTRIBUTES;
-
-static const int XN_FLAG_SEP_MASK;
-static const int XN_FLAG_COMPAT;
-static const int XN_FLAG_SEP_COMMA_PLUS;
-static const int XN_FLAG_SEP_CPLUS_SPC;
-static const int XN_FLAG_SEP_SPLUS_SPC;
-static const int XN_FLAG_SEP_MULTILINE;
-static const int XN_FLAG_DN_REV;
-static const int XN_FLAG_FN_MASK;
-static const int XN_FLAG_FN_SN;
-static const int XN_FLAG_FN_LN;
-static const int XN_FLAG_FN_OID;
-static const int XN_FLAG_FN_NONE;
-static const int XN_FLAG_SPC_EQ;
-static const int XN_FLAG_DUMP_UNKNOWN_FIELDS;
-static const int XN_FLAG_FN_ALIGN;
-static const int XN_FLAG_RFC2253;
-static const int XN_FLAG_ONELINE;
-static const int XN_FLAG_MULTILINE;
-
 typedef void (*sk_X509_EXTENSION_freefunc)(X509_EXTENSION *);
 """
 
@@ -108,14 +72,11 @@
 int X509_set_issuer_name(X509 *, X509_NAME *);
 
 int X509_add_ext(X509 *, X509_EXTENSION *, int);
-X509_EXTENSION *X509_delete_ext(X509 *, int);
 X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *);
 
 ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *);
 void X509_EXTENSION_free(X509_EXTENSION *);
 
-int i2d_X509(X509 *, unsigned char **);
-
 int X509_REQ_set_version(X509_REQ *, long);
 X509_REQ *X509_REQ_new(void);
 void X509_REQ_free(X509_REQ *);
@@ -123,13 +84,17 @@
 int X509_REQ_set_subject_name(X509_REQ *, X509_NAME *);
 int X509_REQ_sign(X509_REQ *, EVP_PKEY *, const EVP_MD *);
 int X509_REQ_verify(X509_REQ *, EVP_PKEY *);
-int X509_REQ_digest(const X509_REQ *, const EVP_MD *,
-                    unsigned char *, unsigned int *);
 EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *);
-int X509_REQ_print(BIO *, X509_REQ *);
 int X509_REQ_print_ex(BIO *, X509_REQ *, unsigned long, unsigned long);
 int X509_REQ_add_extensions(X509_REQ *, X509_EXTENSIONS *);
 X509_EXTENSIONS *X509_REQ_get_extensions(X509_REQ *);
+X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *, int);
+int X509_REQ_get_attr_by_OBJ(const X509_REQ *, const ASN1_OBJECT *, int);
+void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *, int, int, void *);
+ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *, int);
+int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *);
+int X509_REQ_add1_attr_by_OBJ(X509_REQ *, const ASN1_OBJECT *,
+                              int, const unsigned char *, int);
 
 int X509V3_EXT_print(BIO *, X509_EXTENSION *, unsigned long, int);
 ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *);
@@ -186,40 +151,19 @@
 
 const char *X509_verify_cert_error_string(long);
 
-const char *X509_get_default_cert_area(void);
 const char *X509_get_default_cert_dir(void);
 const char *X509_get_default_cert_file(void);
 const char *X509_get_default_cert_dir_env(void);
 const char *X509_get_default_cert_file_env(void);
-const char *X509_get_default_private_dir(void);
 
-int i2d_RSA_PUBKEY(RSA *, unsigned char **);
-RSA *d2i_RSA_PUBKEY(RSA **, const unsigned char **, long);
-RSA *d2i_RSAPublicKey(RSA **, const unsigned char **, long);
-RSA *d2i_RSAPrivateKey(RSA **, const unsigned char **, long);
-int i2d_DSA_PUBKEY(DSA *, unsigned char **);
-DSA *d2i_DSA_PUBKEY(DSA **, const unsigned char **, long);
-DSA *d2i_DSAPublicKey(DSA **, const unsigned char **, long);
-DSA *d2i_DSAPrivateKey(DSA **, const unsigned char **, long);
-
-RSA *d2i_RSAPrivateKey_bio(BIO *, RSA **);
 int i2d_RSAPrivateKey_bio(BIO *, RSA *);
 RSA *d2i_RSAPublicKey_bio(BIO *, RSA **);
 int i2d_RSAPublicKey_bio(BIO *, RSA *);
-RSA *d2i_RSA_PUBKEY_bio(BIO *, RSA **);
-int i2d_RSA_PUBKEY_bio(BIO *, RSA *);
-DSA *d2i_DSA_PUBKEY_bio(BIO *, DSA **);
-int i2d_DSA_PUBKEY_bio(BIO *, DSA *);
-DSA *d2i_DSAPrivateKey_bio(BIO *, DSA **);
 int i2d_DSAPrivateKey_bio(BIO *, DSA *);
 
-PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *,
-                                                 PKCS8_PRIV_KEY_INFO **);
-void PKCS8_PRIV_KEY_INFO_free(PKCS8_PRIV_KEY_INFO *);
 /* These became const X509 in 1.1.0 */
 int X509_get_ext_count(X509 *);
 X509_EXTENSION *X509_get_ext(X509 *, int);
-int X509_get_ext_by_NID(X509 *, int, int);
 X509_NAME *X509_get_subject_name(X509 *);
 X509_NAME *X509_get_issuer_name(X509 *);
 
@@ -242,18 +186,9 @@
 
 int X509_CRL_get0_by_serial(X509_CRL *, X509_REVOKED **, ASN1_INTEGER *);
 
-/* these CRYPTO_EX_DATA functions became macros in 1.1.0 */
-int X509_get_ex_new_index(long, void *, CRYPTO_EX_new *, CRYPTO_EX_dup *,
-                          CRYPTO_EX_free *);
-int X509_set_ex_data(X509 *, int, void *);
-void *X509_get_ex_data(X509 *, int);
-
+X509_REVOKED *X509_REVOKED_dup(X509_REVOKED *);
 X509_REVOKED *Cryptography_X509_REVOKED_dup(X509_REVOKED *);
 
-int i2d_X509_CINF(X509_CINF *, unsigned char **);
-int i2d_X509_CRL_INFO(X509_CRL_INFO *, unsigned char **);
-int i2d_X509_REQ_INFO(X509_REQ_INFO *, unsigned char **);
-
 /* new in 1.0.2 */
 int i2d_re_X509_tbs(X509 *, unsigned char **);
 int X509_get_signature_nid(const X509 *);
@@ -267,6 +202,8 @@
 
 ASN1_TIME *X509_get_notBefore(X509 *);
 ASN1_TIME *X509_get_notAfter(X509 *);
+ASN1_TIME *X509_getm_notBefore(X509 *);
+ASN1_TIME *X509_getm_notAfter(X509 *);
 
 long X509_REQ_get_version(X509_REQ *);
 X509_NAME *X509_REQ_get_subject_name(X509_REQ *);
@@ -295,11 +232,6 @@
 int sk_X509_CRL_push(Cryptography_STACK_OF_X509_CRL *, X509_CRL *);
 X509_CRL *sk_X509_CRL_value(Cryptography_STACK_OF_X509_CRL *, int);
 
-int i2d_RSAPublicKey(RSA *, unsigned char **);
-int i2d_RSAPrivateKey(RSA *, unsigned char **);
-int i2d_DSAPublicKey(DSA *, unsigned char **);
-int i2d_DSAPrivateKey(DSA *, unsigned char **);
-
 long X509_CRL_get_version(X509_CRL *);
 ASN1_TIME *X509_CRL_get_lastUpdate(X509_CRL *);
 ASN1_TIME *X509_CRL_get_nextUpdate(X509_CRL *);
@@ -311,19 +243,14 @@
 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 i2d_EC_PUBKEY(EC_KEY *, unsigned char **);
-EC_KEY *d2i_EC_PUBKEY(EC_KEY **, const unsigned char **, long);
 EC_KEY *d2i_EC_PUBKEY_bio(BIO *, EC_KEY **);
 int i2d_EC_PUBKEY_bio(BIO *, EC_KEY *);
-EC_KEY *d2i_ECPrivateKey(EC_KEY **, const unsigned char **, long);
 EC_KEY *d2i_ECPrivateKey_bio(BIO *, EC_KEY **);
-int i2d_ECPrivateKey(EC_KEY *, unsigned char **);
 int i2d_ECPrivateKey_bio(BIO *, EC_KEY *);
 
-EC_KEY *o2i_ECPublicKey(EC_KEY **, const unsigned char **, long);
-int i2o_ECPublicKey(EC_KEY *, unsigned char **);
-
 // declared in safestack
 int sk_ASN1_OBJECT_num(Cryptography_STACK_OF_ASN1_OBJECT *);
 ASN1_OBJECT *sk_ASN1_OBJECT_value(Cryptography_STACK_OF_ASN1_OBJECT *, int);
@@ -343,30 +270,7 @@
 """
 
 CUSTOMIZATIONS = """
-/* Added in 1.0.2 beta but we need it in all versions now due to the great
-   opaquing. */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 && !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-/* from x509/x_x509.c version 1.0.2 */
-void X509_get0_signature(const ASN1_BIT_STRING **psig,
-                         const X509_ALGOR **palg, const X509 *x)
-{
-    if (psig)
-        *psig = x->signature;
-    if (palg)
-        *palg = x->sig_alg;
-}
-
-int X509_get_signature_nid(const X509 *x)
-{
-    return OBJ_obj2nid(x->sig_alg->algorithm);
-}
-
-#endif
-
-/* Added in 1.0.2 but we need it in all versions now due to the great
-   opaquing. */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_102
-/* from x509/x_x509.c */
+#if CRYPTOGRAPHY_IS_LIBRESSL
 int i2d_re_X509_tbs(X509 *x, unsigned char **pp)
 {
     /* in 1.0.2+ this function also sets x->cert_info->enc.modified = 1
@@ -378,20 +282,13 @@
 }
 #endif
 
-/* X509_REVOKED_dup only exists on 1.0.2+. It is implemented using
-   IMPLEMENT_ASN1_DUP_FUNCTION. The below is the equivalent so we have
-   it available on all OpenSSLs. */
+/* Being kept around for pyOpenSSL */
 X509_REVOKED *Cryptography_X509_REVOKED_dup(X509_REVOKED *rev) {
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_102
-    return ASN1_item_dup(ASN1_ITEM_rptr(X509_REVOKED), rev);
-#else
     return X509_REVOKED_dup(rev);
-#endif
 }
-
 /* Added in 1.1.0 but we need it in all versions now due to the great
    opaquing. */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
+#if CRYPTOGRAPHY_IS_LIBRESSL
 int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp)
 {
     req->req_info->enc.modified = 1;
@@ -401,42 +298,5 @@
     crl->crl->enc.modified = 1;
     return i2d_X509_CRL_INFO(crl->crl, pp);
 }
-
-#if !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-int X509_up_ref(X509 *x) {
-   return CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
-}
-
-const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x)
-{
-    return x->cert_info->signature;
-}
-
-/* from x509/x509_req.c */
-void X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig,
-                             const X509_ALGOR **palg)
-{
-    if (psig != NULL)
-        *psig = req->signature;
-    if (palg != NULL)
-        *palg = req->sig_alg;
-}
-void X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig,
-                             const X509_ALGOR **palg)
-{
-    if (psig != NULL)
-        *psig = crl->signature;
-    if (palg != NULL)
-        *palg = crl->sig_alg;
-}
-const ASN1_TIME *X509_REVOKED_get0_revocationDate(const X509_REVOKED *x)
-{
-    return x->revocationDate;
-}
-const ASN1_INTEGER *X509_REVOKED_get0_serialNumber(const X509_REVOKED *x)
-{
-    return x->serialNumber;
-}
-#endif
 #endif
 """
diff --git a/src/_cffi_src/openssl/x509_vfy.py b/src/_cffi_src/openssl/x509_vfy.py
index 42da3b1..ba3d3db 100644
--- a/src/_cffi_src/openssl/x509_vfy.py
+++ b/src/_cffi_src/openssl/x509_vfy.py
@@ -19,11 +19,8 @@
 """
 
 TYPES = """
-static const long Cryptography_HAS_102_VERIFICATION_ERROR_CODES;
-static const long Cryptography_HAS_102_VERIFICATION_PARAMS;
+static const long Cryptography_HAS_102_VERIFICATION;
 static const long Cryptography_HAS_110_VERIFICATION_PARAMS;
-static const long Cryptography_HAS_X509_V_FLAG_TRUSTED_FIRST;
-static const long Cryptography_HAS_X509_V_FLAG_PARTIAL_CHAIN;
 static const long Cryptography_HAS_X509_STORE_CTX_GET_ISSUER;
 
 typedef ... Cryptography_STACK_OF_ASN1_OBJECT;
@@ -222,67 +219,22 @@
 """
 
 CUSTOMIZATIONS = """
-/* OpenSSL 1.0.2+ verification parameters and error codes */
-#if CRYPTOGRAPHY_OPENSSL_102_OR_GREATER
-static const long Cryptography_HAS_102_VERIFICATION_ERROR_CODES = 1;
-static const long Cryptography_HAS_102_VERIFICATION_PARAMS = 1;
+#if !CRYPTOGRAPHY_IS_LIBRESSL
+static const long Cryptography_HAS_102_VERIFICATION = 1;
 #else
-static const long Cryptography_HAS_102_VERIFICATION_ERROR_CODES = 0;
-static const long Cryptography_HAS_102_VERIFICATION_PARAMS = 0;
-
+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;
-/* These 3 defines are unavailable in LibreSSL 2.5.x, but may be added
-   in the future... */
-#ifndef X509_V_ERR_HOSTNAME_MISMATCH
-static const long X509_V_ERR_HOSTNAME_MISMATCH = 0;
-#endif
-#ifndef X509_V_ERR_EMAIL_MISMATCH
-static const long X509_V_ERR_EMAIL_MISMATCH = 0;
-#endif
-#ifndef X509_V_ERR_IP_ADDRESS_MISMATCH
-static const long X509_V_ERR_IP_ADDRESS_MISMATCH = 0;
-#endif
-#ifndef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT
-static const long X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT = 0;
-#endif
-#ifndef X509_CHECK_FLAG_NO_WILDCARDS
-static const long X509_CHECK_FLAG_NO_WILDCARDS = 0;
-#endif
-#ifndef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS
-static const long X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS = 0;
-#endif
-#ifndef X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS
-static const long X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS = 0;
-#endif
-#ifndef X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS
-static const long X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS = 0;
-#endif
-
-/* X509_V_FLAG_TRUSTED_FIRST is also new in 1.0.2+, but it is added separately
-   below because it shows up in some earlier 3rd party OpenSSL packages. */
 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;
-
-#if !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-int (*X509_VERIFY_PARAM_set1_host)(X509_VERIFY_PARAM *, const char *,
-                                   size_t) = NULL;
-int (*X509_VERIFY_PARAM_set1_email)(X509_VERIFY_PARAM *, const char *,
-                                    size_t) = NULL;
-int (*X509_VERIFY_PARAM_set1_ip)(X509_VERIFY_PARAM *, const unsigned char *,
-                                 size_t) = NULL;
-int (*X509_VERIFY_PARAM_set1_ip_asc)(X509_VERIFY_PARAM *, const char *) = NULL;
-void (*X509_VERIFY_PARAM_set_hostflags)(X509_VERIFY_PARAM *,
-                                        unsigned int) = NULL;
-#endif
 #endif
 
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 || CRYPTOGRAPHY_IS_LIBRESSL
+#if CRYPTOGRAPHY_IS_LIBRESSL
 static const long Cryptography_HAS_110_VERIFICATION_PARAMS = 0;
 #ifndef X509_CHECK_FLAG_NEVER_CHECK_SUBJECT
 static const long X509_CHECK_FLAG_NEVER_CHECK_SUBJECT = 0;
@@ -291,45 +243,7 @@
 static const long Cryptography_HAS_110_VERIFICATION_PARAMS = 1;
 #endif
 
-/* OpenSSL 1.0.2+ or Solaris's backport */
-#ifdef X509_V_FLAG_PARTIAL_CHAIN
-static const long Cryptography_HAS_X509_V_FLAG_PARTIAL_CHAIN = 1;
-#else
-static const long Cryptography_HAS_X509_V_FLAG_PARTIAL_CHAIN = 0;
-static const long X509_V_FLAG_PARTIAL_CHAIN = 0;
-#endif
-
-/* OpenSSL 1.0.2+, *or* Fedora 20's flavor of OpenSSL 1.0.1e... */
-#ifdef X509_V_FLAG_TRUSTED_FIRST
-static const long Cryptography_HAS_X509_V_FLAG_TRUSTED_FIRST = 1;
-#else
-static const long Cryptography_HAS_X509_V_FLAG_TRUSTED_FIRST = 0;
-static const long X509_V_FLAG_TRUSTED_FIRST = 0;
-#endif
-
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-Cryptography_STACK_OF_X509_OBJECT *X509_STORE_get0_objects(X509_STORE *ctx) {
-    return ctx->objs;
-}
-X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *store) {
-    return store->param;
-}
-int X509_OBJECT_get_type(const X509_OBJECT *x) {
-    return x->type;
-}
-
-/* from x509/x509_vfy.c */
-X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx)
-{
-    return ctx->cert;
-}
-
-X509 *X509_OBJECT_get0_X509(X509_OBJECT *x) {
-    return x->data.x509;
-}
-#endif
-
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
+#if CRYPTOGRAPHY_IS_LIBRESSL
 static const long Cryptography_HAS_X509_STORE_CTX_GET_ISSUER = 0;
 typedef void *X509_STORE_CTX_get_issuer_fn;
 X509_STORE_CTX_get_issuer_fn (*X509_STORE_get_get_issuer)(X509_STORE *) = NULL;
diff --git a/src/_cffi_src/openssl/x509name.py b/src/_cffi_src/openssl/x509name.py
index f88c8b0..1fbe26a 100644
--- a/src/_cffi_src/openssl/x509name.py
+++ b/src/_cffi_src/openssl/x509name.py
@@ -35,7 +35,7 @@
 int X509_NAME_get_index_by_NID(X509_NAME *, int, int);
 int X509_NAME_cmp(const X509_NAME *, const X509_NAME *);
 X509_NAME *X509_NAME_dup(X509_NAME *);
-int Cryptography_X509_NAME_ENTRY_set(X509_NAME_ENTRY *);
+int X509_NAME_ENTRY_set(X509_NAME_ENTRY *);
 /* These became const X509_NAME * in 1.1.0 */
 int X509_NAME_entry_count(X509_NAME *);
 X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *, int);
@@ -75,13 +75,4 @@
 """
 
 CUSTOMIZATIONS = """
-#if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
-int Cryptography_X509_NAME_ENTRY_set(X509_NAME_ENTRY *ne) {
-    return X509_NAME_ENTRY_set(ne);
-}
-#else
-int Cryptography_X509_NAME_ENTRY_set(X509_NAME_ENTRY *ne) {
-    return ne->set;
-}
-#endif
 """
diff --git a/src/_cffi_src/openssl/x509v3.py b/src/_cffi_src/openssl/x509v3.py
index 193d2e2..5968120 100644
--- a/src/_cffi_src/openssl/x509v3.py
+++ b/src/_cffi_src/openssl/x509v3.py
@@ -177,6 +177,7 @@
 typedef void (*sk_GENERAL_NAME_freefunc)(GENERAL_NAME *);
 typedef void (*sk_DIST_POINT_freefunc)(DIST_POINT *);
 typedef void (*sk_POLICYINFO_freefunc)(POLICYINFO *);
+typedef void (*sk_ACCESS_DESCRIPTION_freefunc)(ACCESS_DESCRIPTION *);
 """
 
 
@@ -228,6 +229,8 @@
     Cryptography_STACK_OF_ACCESS_DESCRIPTION *, int
 );
 void sk_ACCESS_DESCRIPTION_free(Cryptography_STACK_OF_ACCESS_DESCRIPTION *);
+void sk_ACCESS_DESCRIPTION_pop_free(Cryptography_STACK_OF_ACCESS_DESCRIPTION *,
+                              sk_ACCESS_DESCRIPTION_freefunc);
 int sk_ACCESS_DESCRIPTION_push(Cryptography_STACK_OF_ACCESS_DESCRIPTION *,
                                ACCESS_DESCRIPTION *);
 
diff --git a/src/_cffi_src/utils.py b/src/_cffi_src/utils.py
index d3dd18a..56745a3 100644
--- a/src/_cffi_src/utils.py
+++ b/src/_cffi_src/utils.py
@@ -4,6 +4,7 @@
 
 from __future__ import absolute_import, division, print_function
 
+import os
 import sys
 from distutils.ccompiler import new_compiler
 from distutils.dist import Distribution
@@ -11,8 +12,21 @@
 from cffi import FFI
 
 
-def build_ffi_for_binding(module_name, module_prefix, modules, libraries=[],
-                          extra_compile_args=[], extra_link_args=[]):
+# Load the cryptography __about__ to get the current package version
+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)
+
+
+def build_ffi_for_binding(
+    module_name,
+    module_prefix,
+    modules,
+    libraries=[],
+    extra_compile_args=[],
+    extra_link_args=[],
+):
     """
     Modules listed in ``modules`` should have the following attributes:
 
@@ -36,10 +50,7 @@
         includes.append(module.INCLUDES)
         customizations.append(module.CUSTOMIZATIONS)
 
-    verify_source = "\n".join(
-        includes +
-        customizations
-    )
+    verify_source = "\n".join(includes + customizations)
     ffi = build_ffi(
         module_name,
         cdef_source="\n".join(types + functions),
@@ -52,9 +63,20 @@
     return ffi
 
 
-def build_ffi(module_name, cdef_source, verify_source, libraries=[],
-              extra_compile_args=[], extra_link_args=[]):
+def build_ffi(
+    module_name,
+    cdef_source,
+    verify_source,
+    libraries=[],
+    extra_compile_args=[],
+    extra_link_args=[],
+):
     ffi = FFI()
+    # Always add the CRYPTOGRAPHY_PACKAGE_VERSION to the shared object
+    cdef_source += "\nstatic const char *const CRYPTOGRAPHY_PACKAGE_VERSION;"
+    verify_source += '\n#define CRYPTOGRAPHY_PACKAGE_VERSION "{}"'.format(
+        about["__version__"]
+    )
     ffi.cdef(cdef_source)
     ffi.set_source(
         module_name,
@@ -67,10 +89,10 @@
 
 
 def extra_link_args(compiler_type):
-    if compiler_type == 'msvc':
+    if compiler_type == "msvc":
         # Enable NX and ASLR for Windows builds on MSVC. These are enabled by
         # default on Python 3.3+ but not on 2.x.
-        return ['/NXCOMPAT', '/DYNAMICBASE']
+        return ["/NXCOMPAT", "/DYNAMICBASE"]
     else:
         return []
 
@@ -82,7 +104,7 @@
     """
     dist = Distribution()
     dist.parse_config_files()
-    cmd = dist.get_command_obj('build')
+    cmd = dist.get_command_obj("build")
     cmd.ensure_finalized()
     compiler = new_compiler(compiler=cmd.compiler)
     return compiler.compiler_type
diff --git a/src/cryptography/Android.bp b/src/cryptography/Android.bp
index 876fd3d..9bf4b22 100644
--- a/src/cryptography/Android.bp
+++ b/src/cryptography/Android.bp
@@ -37,12 +37,12 @@
         "hazmat/primitives/ciphers/*.py",
         "hazmat/bindings/*.py",
         "hazmat/bindings/openssl/*.py",
-	"x509/*.py",
+        "x509/*.py",
     ],
     version: {
         py2: {
-            enabled: true,
-        },
+	    enabled: true,
+	},
         py3: {
             enabled: true,
         },
@@ -50,7 +50,6 @@
     libs: [
         "py-asn1crypto",
         "py-cffi",
-        "py-enum34",
         "py-ipaddress",
         "py-six",
     ],
@@ -63,7 +62,6 @@
 filegroup {
     name: "py-cryptography-libs",
     srcs: [
-        "hazmat/bindings/_constant_time.so",
         "hazmat/bindings/_openssl.so",
         "hazmat/bindings/_padding.so",
     ],
diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py
index 02f81f6..f816509 100644
--- a/src/cryptography/__about__.py
+++ b/src/cryptography/__about__.py
@@ -5,19 +5,27 @@
 from __future__ import absolute_import, division, print_function
 
 __all__ = [
-    "__title__", "__summary__", "__uri__", "__version__", "__author__",
-    "__email__", "__license__", "__copyright__",
+    "__title__",
+    "__summary__",
+    "__uri__",
+    "__version__",
+    "__author__",
+    "__email__",
+    "__license__",
+    "__copyright__",
 ]
 
 __title__ = "cryptography"
-__summary__ = ("cryptography is a package which provides cryptographic recipes"
-               " and primitives to Python developers.")
+__summary__ = (
+    "cryptography is a package which provides cryptographic recipes"
+    " and primitives to Python developers."
+)
 __uri__ = "https://github.com/pyca/cryptography"
 
-__version__ = "2.5"
+__version__ = "3.3.2"
 
 __author__ = "The cryptography developers"
 __email__ = "cryptography-dev@python.org"
 
 __license__ = "BSD or Apache License, Version 2.0"
-__copyright__ = "Copyright 2013-2017 {0}".format(__author__)
+__copyright__ = "Copyright 2013-2021 {}".format(__author__)
diff --git a/src/cryptography/__init__.py b/src/cryptography/__init__.py
index 6da0b38..465671e 100644
--- a/src/cryptography/__init__.py
+++ b/src/cryptography/__init__.py
@@ -4,13 +4,38 @@
 
 from __future__ import absolute_import, division, print_function
 
+import sys
+import warnings
+
 from cryptography.__about__ import (
-    __author__, __copyright__, __email__, __license__, __summary__, __title__,
-    __uri__, __version__
+    __author__,
+    __copyright__,
+    __email__,
+    __license__,
+    __summary__,
+    __title__,
+    __uri__,
+    __version__,
 )
+from cryptography.utils import CryptographyDeprecationWarning
 
 
 __all__ = [
-    "__title__", "__summary__", "__uri__", "__version__", "__author__",
-    "__email__", "__license__", "__copyright__",
+    "__title__",
+    "__summary__",
+    "__uri__",
+    "__version__",
+    "__author__",
+    "__email__",
+    "__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/exceptions.py b/src/cryptography/exceptions.py
index 648cf9d..1d52d7d 100644
--- a/src/cryptography/exceptions.py
+++ b/src/cryptography/exceptions.py
@@ -19,6 +19,7 @@
     UNSUPPORTED_X509 = 8
     UNSUPPORTED_EXCHANGE_ALGORITHM = 9
     UNSUPPORTED_DIFFIE_HELLMAN = 10
+    UNSUPPORTED_MAC = 11
 
 
 class UnsupportedAlgorithm(Exception):
diff --git a/src/cryptography/fernet.py b/src/cryptography/fernet.py
index b990def..00c2528 100644
--- a/src/cryptography/fernet.py
+++ b/src/cryptography/fernet.py
@@ -14,7 +14,7 @@
 
 from cryptography import utils
 from cryptography.exceptions import InvalidSignature
-from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.backends import _get_backend
 from cryptography.hazmat.primitives import hashes, padding
 from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
 from cryptography.hazmat.primitives.hmac import HMAC
@@ -29,8 +29,7 @@
 
 class Fernet(object):
     def __init__(self, key, backend=None):
-        if backend is None:
-            backend = default_backend()
+        backend = _get_backend(backend)
 
         key = base64.urlsafe_b64decode(key)
         if len(key) != 32:
@@ -47,7 +46,9 @@
         return base64.urlsafe_b64encode(os.urandom(32))
 
     def encrypt(self, data):
-        current_time = int(time.time())
+        return self.encrypt_at_time(data, int(time.time()))
+
+    def encrypt_at_time(self, data, current_time):
         iv = os.urandom(16)
         return self._encrypt_from_parts(data, current_time, iv)
 
@@ -72,7 +73,15 @@
 
     def decrypt(self, token, ttl=None):
         timestamp, data = Fernet._get_unverified_token_data(token)
-        return self._decrypt_data(data, timestamp, ttl)
+        return self._decrypt_data(data, timestamp, ttl, int(time.time()))
+
+    def decrypt_at_time(self, token, ttl, current_time):
+        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)
 
     def extract_timestamp(self, token):
         timestamp, data = Fernet._get_unverified_token_data(token)
@@ -92,7 +101,7 @@
             raise InvalidToken
 
         try:
-            timestamp, = struct.unpack(">Q", data[1:9])
+            (timestamp,) = struct.unpack(">Q", data[1:9])
         except struct.error:
             raise InvalidToken
         return timestamp, data
@@ -105,8 +114,7 @@
         except InvalidSignature:
             raise InvalidToken
 
-    def _decrypt_data(self, data, timestamp, ttl):
-        current_time = int(time.time())
+    def _decrypt_data(self, data, timestamp, ttl, current_time):
         if ttl is not None:
             if timestamp + ttl < current_time:
                 raise InvalidToken
@@ -146,13 +154,16 @@
         self._fernets = fernets
 
     def encrypt(self, msg):
-        return self._fernets[0].encrypt(msg)
+        return self.encrypt_at_time(msg, int(time.time()))
+
+    def encrypt_at_time(self, msg, current_time):
+        return self._fernets[0].encrypt_at_time(msg, current_time)
 
     def rotate(self, msg):
         timestamp, data = Fernet._get_unverified_token_data(msg)
         for f in self._fernets:
             try:
-                p = f._decrypt_data(data, timestamp, None)
+                p = f._decrypt_data(data, timestamp, None, None)
                 break
             except InvalidToken:
                 pass
@@ -169,3 +180,11 @@
             except InvalidToken:
                 pass
         raise InvalidToken
+
+    def decrypt_at_time(self, msg, ttl, current_time):
+        for f in self._fernets:
+            try:
+                return f.decrypt_at_time(msg, ttl, current_time)
+            except InvalidToken:
+                pass
+        raise InvalidToken
diff --git a/src/cryptography/hazmat/_der.py b/src/cryptography/hazmat/_der.py
new file mode 100644
index 0000000..462b911
--- /dev/null
+++ b/src/cryptography/hazmat/_der.py
@@ -0,0 +1,156 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import six
+
+from cryptography.utils import int_from_bytes, 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):
+        self.data = memoryview(data)
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, exc_type, exc_value, tb):
+        if exc_value is None:
+            self.check_empty()
+
+    def is_empty(self):
+        return len(self.data) == 0
+
+    def check_empty(self):
+        if not self.is_empty():
+            raise ValueError("Invalid DER input: trailing data")
+
+    def read_byte(self):
+        if len(self.data) < 1:
+            raise ValueError("Invalid DER input: insufficient data")
+        ret = six.indexbytes(self.data, 0)
+        self.data = self.data[1:]
+        return ret
+
+    def read_bytes(self, n):
+        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):
+        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):
+        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):
+        with self:
+            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:
+            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)
+        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)
+            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):
+    if not isinstance(x, six.integer_types):
+        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, *children):
+    length = 0
+    for child in children:
+        length += len(child)
+    chunks = [six.int2byte(tag)]
+    if length < 0x80:
+        chunks.append(six.int2byte(length))
+    else:
+        length_bytes = int_to_bytes(length)
+        chunks.append(six.int2byte(0x80 | len(length_bytes)))
+        chunks.append(length_bytes)
+    chunks.extend(children)
+    return b"".join(chunks)
diff --git a/src/cryptography/hazmat/_oid.py b/src/cryptography/hazmat/_oid.py
index cfe906c..de2771a 100644
--- a/src/cryptography/hazmat/_oid.py
+++ b/src/cryptography/hazmat/_oid.py
@@ -19,26 +19,36 @@
         # range 0..39.  All nodes must be integers.
         for node in nodes:
             try:
-                intnodes.append(int(node, 0))
+                node_value = int(node, 10)
             except ValueError:
                 raise ValueError(
-                    "Malformed OID: %s (non-integer nodes)" % (
-                        self._dotted_string))
+                    "Malformed OID: %s (non-integer nodes)"
+                    % (self._dotted_string)
+                )
+            if node_value < 0:
+                raise ValueError(
+                    "Malformed OID: %s (negative-integer nodes)"
+                    % (self._dotted_string)
+                )
+            intnodes.append(node_value)
 
         if len(nodes) < 2:
             raise ValueError(
-                "Malformed OID: %s (insufficient number of nodes)" % (
-                    self._dotted_string))
+                "Malformed OID: %s (insufficient number of nodes)"
+                % (self._dotted_string)
+            )
 
         if intnodes[0] > 2:
             raise ValueError(
-                "Malformed OID: %s (first node outside valid range)" % (
-                    self._dotted_string))
+                "Malformed OID: %s (first node outside valid range)"
+                % (self._dotted_string)
+            )
 
         if intnodes[0] < 2 and intnodes[1] >= 40:
             raise ValueError(
-                "Malformed OID: %s (second node outside valid range)" % (
-                    self._dotted_string))
+                "Malformed OID: %s (second node outside valid range)"
+                % (self._dotted_string)
+            )
 
     def __eq__(self, other):
         if not isinstance(other, ObjectIdentifier):
@@ -50,9 +60,8 @@
         return not self == other
 
     def __repr__(self):
-        return "<ObjectIdentifier(oid={0}, name={1})>".format(
-            self.dotted_string,
-            self._name
+        return "<ObjectIdentifier(oid={}, name={})>".format(
+            self.dotted_string, self._name
         )
 
     def __hash__(self):
@@ -62,6 +71,7 @@
     def _name(self):
         # Lazy import to avoid an import cycle
         from cryptography.x509.oid import _OID_NAMES
+
         return _OID_NAMES.get(self, "Unknown OID")
 
     dotted_string = utils.read_only_property("_dotted_string")
diff --git a/src/cryptography/hazmat/backends/__init__.py b/src/cryptography/hazmat/backends/__init__.py
index 565bde7..1563936 100644
--- a/src/cryptography/hazmat/backends/__init__.py
+++ b/src/cryptography/hazmat/backends/__init__.py
@@ -13,6 +13,14 @@
 
     if _default_backend is None:
         from cryptography.hazmat.backends.openssl.backend import backend
+
         _default_backend = backend
 
     return _default_backend
+
+
+def _get_backend(backend):
+    if backend is None:
+        return default_backend()
+    else:
+        return backend
diff --git a/src/cryptography/hazmat/backends/interfaces.py b/src/cryptography/hazmat/backends/interfaces.py
index 0a476b9..418980a 100644
--- a/src/cryptography/hazmat/backends/interfaces.py
+++ b/src/cryptography/hazmat/backends/interfaces.py
@@ -57,7 +57,7 @@
     @abc.abstractmethod
     def create_hmac_ctx(self, key, algorithm):
         """
-        Create a MACContext for calculating a message authentication code.
+        Create a context for calculating a message authentication code.
         """
 
 
@@ -72,7 +72,7 @@
     @abc.abstractmethod
     def create_cmac_ctx(self, algorithm):
         """
-        Create a MACContext for calculating a message authentication code.
+        Create a context for calculating a message authentication code.
         """
 
 
@@ -86,8 +86,9 @@
         """
 
     @abc.abstractmethod
-    def derive_pbkdf2_hmac(self, algorithm, length, salt, iterations,
-                           key_material):
+    def derive_pbkdf2_hmac(
+        self, algorithm, length, salt, iterations, key_material
+    ):
         """
         Return length bytes derived from provided PBKDF2 parameters.
         """
diff --git a/src/cryptography/hazmat/backends/openssl/aead.py b/src/cryptography/hazmat/backends/openssl/aead.py
index 73195ff..4494916 100644
--- a/src/cryptography/hazmat/backends/openssl/aead.py
+++ b/src/cryptography/hazmat/backends/openssl/aead.py
@@ -13,15 +13,18 @@
 
 def _aead_cipher_name(cipher):
     from cryptography.hazmat.primitives.ciphers.aead import (
-        AESCCM, AESGCM, ChaCha20Poly1305
+        AESCCM,
+        AESGCM,
+        ChaCha20Poly1305,
     )
+
     if isinstance(cipher, ChaCha20Poly1305):
         return b"chacha20-poly1305"
     elif isinstance(cipher, AESCCM):
-        return "aes-{0}-ccm".format(len(cipher._key) * 8).encode("ascii")
+        return "aes-{}-ccm".format(len(cipher._key) * 8).encode("ascii")
     else:
         assert isinstance(cipher, AESGCM)
-        return "aes-{0}-gcm".format(len(cipher._key) * 8).encode("ascii")
+        return "aes-{}-gcm".format(len(cipher._key) * 8).encode("ascii")
 
 
 def _aead_setup(backend, cipher_name, key, nonce, tag, tag_len, operation):
@@ -30,18 +33,21 @@
     ctx = backend._lib.EVP_CIPHER_CTX_new()
     ctx = backend._ffi.gc(ctx, backend._lib.EVP_CIPHER_CTX_free)
     res = backend._lib.EVP_CipherInit_ex(
-        ctx, evp_cipher,
+        ctx,
+        evp_cipher,
         backend._ffi.NULL,
         backend._ffi.NULL,
         backend._ffi.NULL,
-        int(operation == _ENCRYPT)
+        int(operation == _ENCRYPT),
     )
     backend.openssl_assert(res != 0)
     res = backend._lib.EVP_CIPHER_CTX_set_key_length(ctx, len(key))
     backend.openssl_assert(res != 0)
     res = backend._lib.EVP_CIPHER_CTX_ctrl(
-        ctx, backend._lib.EVP_CTRL_AEAD_SET_IVLEN, len(nonce),
-        backend._ffi.NULL
+        ctx,
+        backend._lib.EVP_CTRL_AEAD_SET_IVLEN,
+        len(nonce),
+        backend._ffi.NULL,
     )
     backend.openssl_assert(res != 0)
     if operation == _DECRYPT:
@@ -49,10 +55,11 @@
             ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, len(tag), tag
         )
         backend.openssl_assert(res != 0)
-    else:
+    elif cipher_name.endswith(b"-ccm"):
         res = backend._lib.EVP_CIPHER_CTX_ctrl(
             ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, tag_len, backend._ffi.NULL
         )
+        backend.openssl_assert(res != 0)
 
     nonce_ptr = backend._ffi.from_buffer(nonce)
     key_ptr = backend._ffi.from_buffer(key)
@@ -62,7 +69,7 @@
         backend._ffi.NULL,
         key_ptr,
         nonce_ptr,
-        int(operation == _ENCRYPT)
+        int(operation == _ENCRYPT),
     )
     backend.openssl_assert(res != 0)
     return ctx
@@ -71,11 +78,7 @@
 def _set_length(backend, ctx, data_len):
     intptr = backend._ffi.new("int *")
     res = backend._lib.EVP_CipherUpdate(
-        ctx,
-        backend._ffi.NULL,
-        intptr,
-        backend._ffi.NULL,
-        data_len
+        ctx, backend._ffi.NULL, intptr, backend._ffi.NULL, data_len
     )
     backend.openssl_assert(res != 0)
 
@@ -98,6 +101,7 @@
 
 def _encrypt(backend, cipher, nonce, data, associated_data, tag_length):
     from cryptography.hazmat.primitives.ciphers.aead import AESCCM
+
     cipher_name = _aead_cipher_name(cipher)
     ctx = _aead_setup(
         backend, cipher_name, cipher._key, nonce, None, tag_length, _ENCRYPT
@@ -125,6 +129,7 @@
 
 def _decrypt(backend, cipher, nonce, data, associated_data, tag_length):
     from cryptography.hazmat.primitives.ciphers.aead import AESCCM
+
     if len(data) < tag_length:
         raise InvalidTag
     tag = data[-tag_length:]
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index 0a9bc53..45d4a1a 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -4,84 +4,166 @@
 
 from __future__ import absolute_import, division, print_function
 
-import base64
 import collections
 import contextlib
 import itertools
+import warnings
 from contextlib import contextmanager
 
-import asn1crypto.core
-
 import six
 from six.moves import range
 
 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.backends.interfaces import (
-    CMACBackend, CipherBackend, DERSerializationBackend, DHBackend, DSABackend,
-    EllipticCurveBackend, HMACBackend, HashBackend, PBKDF2HMACBackend,
-    PEMSerializationBackend, RSABackend, ScryptBackend, X509Backend
+    CMACBackend,
+    CipherBackend,
+    DERSerializationBackend,
+    DHBackend,
+    DSABackend,
+    EllipticCurveBackend,
+    HMACBackend,
+    HashBackend,
+    PBKDF2HMACBackend,
+    PEMSerializationBackend,
+    RSABackend,
+    ScryptBackend,
+    X509Backend,
 )
 from cryptography.hazmat.backends.openssl import aead
 from cryptography.hazmat.backends.openssl.ciphers import _CipherContext
 from cryptography.hazmat.backends.openssl.cmac import _CMACContext
 from cryptography.hazmat.backends.openssl.decode_asn1 import (
-    _CRL_ENTRY_REASON_ENUM_TO_CODE, _Integers
+    _CRL_ENTRY_REASON_ENUM_TO_CODE,
+    _CRL_EXTENSION_HANDLERS,
+    _EXTENSION_HANDLERS_BASE,
+    _EXTENSION_HANDLERS_SCT,
+    _OCSP_BASICRESP_EXTENSION_HANDLERS,
+    _OCSP_REQ_EXTENSION_HANDLERS,
+    _OCSP_SINGLERESP_EXTENSION_HANDLERS_SCT,
+    _REVOKED_EXTENSION_HANDLERS,
+    _X509ExtensionParser,
 )
 from cryptography.hazmat.backends.openssl.dh import (
-    _DHParameters, _DHPrivateKey, _DHPublicKey, _dh_params_dup
+    _DHParameters,
+    _DHPrivateKey,
+    _DHPublicKey,
+    _dh_params_dup,
 )
 from cryptography.hazmat.backends.openssl.dsa import (
-    _DSAParameters, _DSAPrivateKey, _DSAPublicKey
+    _DSAParameters,
+    _DSAPrivateKey,
+    _DSAPublicKey,
 )
 from cryptography.hazmat.backends.openssl.ec import (
-    _EllipticCurvePrivateKey, _EllipticCurvePublicKey
+    _EllipticCurvePrivateKey,
+    _EllipticCurvePublicKey,
+)
+from cryptography.hazmat.backends.openssl.ed25519 import (
+    _Ed25519PrivateKey,
+    _Ed25519PublicKey,
+)
+from cryptography.hazmat.backends.openssl.ed448 import (
+    _ED448_KEY_SIZE,
+    _Ed448PrivateKey,
+    _Ed448PublicKey,
 )
 from cryptography.hazmat.backends.openssl.encode_asn1 import (
     _CRL_ENTRY_EXTENSION_ENCODE_HANDLERS,
-    _CRL_EXTENSION_ENCODE_HANDLERS, _EXTENSION_ENCODE_HANDLERS,
+    _CRL_EXTENSION_ENCODE_HANDLERS,
+    _EXTENSION_ENCODE_HANDLERS,
     _OCSP_BASICRESP_EXTENSION_ENCODE_HANDLERS,
     _OCSP_REQUEST_EXTENSION_ENCODE_HANDLERS,
-    _encode_asn1_int_gc, _encode_asn1_str_gc, _encode_name_gc, _txt2obj_gc,
+    _encode_asn1_int_gc,
+    _encode_asn1_str_gc,
+    _encode_name_gc,
+    _txt2obj_gc,
 )
 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
+    _OCSPRequest,
+    _OCSPResponse,
+)
+from cryptography.hazmat.backends.openssl.poly1305 import (
+    _POLY1305_KEY_SIZE,
+    _Poly1305Context,
 )
 from cryptography.hazmat.backends.openssl.rsa import (
-    _RSAPrivateKey, _RSAPublicKey
+    _RSAPrivateKey,
+    _RSAPublicKey,
 )
 from cryptography.hazmat.backends.openssl.x25519 import (
-    _X25519PrivateKey, _X25519PublicKey
+    _X25519PrivateKey,
+    _X25519PublicKey,
 )
 from cryptography.hazmat.backends.openssl.x448 import (
-    _X448PrivateKey, _X448PublicKey
+    _X448PrivateKey,
+    _X448PublicKey,
 )
 from cryptography.hazmat.backends.openssl.x509 import (
-    _Certificate, _CertificateRevocationList,
-    _CertificateSigningRequest, _RevokedCertificate
+    _Certificate,
+    _CertificateRevocationList,
+    _CertificateSigningRequest,
+    _RevokedCertificate,
 )
 from cryptography.hazmat.bindings.openssl import binding
 from cryptography.hazmat.primitives import hashes, serialization
-from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
+from cryptography.hazmat.primitives.asymmetric import (
+    dh,
+    dsa,
+    ec,
+    ed25519,
+    ed448,
+    rsa,
+)
 from cryptography.hazmat.primitives.asymmetric.padding import (
-    MGF1, OAEP, PKCS1v15, PSS
+    MGF1,
+    OAEP,
+    PKCS1v15,
+    PSS,
 )
 from cryptography.hazmat.primitives.ciphers.algorithms import (
-    AES, ARC4, Blowfish, CAST5, Camellia, ChaCha20, IDEA, SEED, TripleDES
+    AES,
+    ARC4,
+    Blowfish,
+    CAST5,
+    Camellia,
+    ChaCha20,
+    IDEA,
+    SEED,
+    TripleDES,
 )
 from cryptography.hazmat.primitives.ciphers.modes import (
-    CBC, CFB, CFB8, CTR, ECB, GCM, OFB, XTS
+    CBC,
+    CFB,
+    CFB8,
+    CTR,
+    ECB,
+    GCM,
+    OFB,
+    XTS,
 )
 from cryptography.hazmat.primitives.kdf import scrypt
-from cryptography.hazmat.primitives.serialization import ssh
+from cryptography.hazmat.primitives.serialization import pkcs7, ssh
 from cryptography.x509 import ocsp
 
 
 _MemoryBIO = collections.namedtuple("_MemoryBIO", ["bio", "char_ptr"])
 
 
+# Not actually supported, just used as a marker for some serialization tests.
+class _RC2(object):
+    pass
+
+
 @utils.register_interface(CipherBackend)
 @utils.register_interface(CMACBackend)
 @utils.register_interface(DERSerializationBackend)
@@ -101,39 +183,93 @@
     """
     OpenSSL API binding interfaces.
     """
+
     name = "openssl"
 
+    # FIPS has opinions about acceptable algorithms and key sizes, but the
+    # disallowed algorithms are still present in OpenSSL. They just error if
+    # you try to use them. To avoid that we allowlist the algorithms in
+    # FIPS 140-3. This isn't ideal, but FIPS 140-3 is trash so here we are.
+    _fips_aead = {
+        b"aes-128-ccm",
+        b"aes-192-ccm",
+        b"aes-256-ccm",
+        b"aes-128-gcm",
+        b"aes-192-gcm",
+        b"aes-256-gcm",
+    }
+    _fips_ciphers = (AES, TripleDES)
+    _fips_hashes = (
+        hashes.SHA1,
+        hashes.SHA224,
+        hashes.SHA256,
+        hashes.SHA384,
+        hashes.SHA512,
+        hashes.SHA512_224,
+        hashes.SHA512_256,
+        hashes.SHA3_224,
+        hashes.SHA3_256,
+        hashes.SHA3_384,
+        hashes.SHA3_512,
+        hashes.SHAKE128,
+        hashes.SHAKE256,
+    )
+    _fips_rsa_min_key_size = 2048
+    _fips_rsa_min_public_exponent = 65537
+    _fips_dsa_min_modulus = 1 << 2048
+    _fips_dh_min_key_size = 2048
+    _fips_dh_min_modulus = 1 << _fips_dh_min_key_size
+
     def __init__(self):
         self._binding = binding.Binding()
         self._ffi = self._binding.ffi
         self._lib = self._binding.lib
+        self._fips_enabled = self._is_fips_enabled()
 
         self._cipher_registry = {}
         self._register_default_ciphers()
-        self.activate_osrandom_engine()
+        self._register_x509_ext_parsers()
+        self._register_x509_encoders()
+        if self._fips_enabled and self._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE:
+            warnings.warn(
+                "OpenSSL FIPS mode is enabled. Can't enable DRBG fork safety.",
+                UserWarning,
+            )
+        else:
+            self.activate_osrandom_engine()
         self._dh_types = [self._lib.EVP_PKEY_DH]
         if self._lib.Cryptography_HAS_EVP_PKEY_DHX:
             self._dh_types.append(self._lib.EVP_PKEY_DHX)
 
-    def openssl_assert(self, ok):
-        return binding._openssl_assert(self._lib, ok)
+    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 mode == 0:
+            # OpenSSL without FIPS pushes an error on the error stack
+            self._lib.ERR_clear_error()
+        return bool(mode)
 
     def activate_builtin_random(self):
-        # Obtain a new structural reference.
-        e = self._lib.ENGINE_get_default_RAND()
-        if e != self._ffi.NULL:
-            self._lib.ENGINE_unregister_RAND(e)
-            # Reset the RNG to use the new engine.
-            self._lib.RAND_cleanup()
-            # decrement the structural reference from get_default_RAND
-            res = self._lib.ENGINE_finish(e)
-            self.openssl_assert(res == 1)
+        if self._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE:
+            # Obtain a new structural reference.
+            e = self._lib.ENGINE_get_default_RAND()
+            if e != self._ffi.NULL:
+                self._lib.ENGINE_unregister_RAND(e)
+                # Reset the RNG to use the built-in.
+                res = self._lib.RAND_set_rand_method(self._ffi.NULL)
+                self.openssl_assert(res == 1)
+                # decrement the structural reference from get_default_RAND
+                res = self._lib.ENGINE_finish(e)
+                self.openssl_assert(res == 1)
 
     @contextlib.contextmanager
     def _get_osurandom_engine(self):
         # Fetches an engine by id and returns it. This creates a structural
         # reference.
-        e = self._lib.ENGINE_by_id(self._binding._osrandom_engine_id)
+        e = self._lib.ENGINE_by_id(self._lib.Cryptography_osrandom_engine_id)
         self.openssl_assert(e != self._ffi.NULL)
         # Initialize the engine for use. This adds a functional reference.
         res = self._lib.ENGINE_init(e)
@@ -150,30 +286,32 @@
             self.openssl_assert(res == 1)
 
     def activate_osrandom_engine(self):
-        # Unregister and free the current engine.
-        self.activate_builtin_random()
-        with self._get_osurandom_engine() as e:
-            # Set the engine as the default RAND provider.
-            res = self._lib.ENGINE_set_default_RAND(e)
+        if self._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE:
+            # Unregister and free the current engine.
+            self.activate_builtin_random()
+            with self._get_osurandom_engine() as e:
+                # Set the engine as the default RAND provider.
+                res = self._lib.ENGINE_set_default_RAND(e)
+                self.openssl_assert(res == 1)
+            # Reset the RNG to use the engine
+            res = self._lib.RAND_set_rand_method(self._ffi.NULL)
             self.openssl_assert(res == 1)
-        # Reset the RNG to use the new engine.
-        self._lib.RAND_cleanup()
 
     def osrandom_engine_implementation(self):
         buf = self._ffi.new("char[]", 64)
         with self._get_osurandom_engine() as e:
-            res = self._lib.ENGINE_ctrl_cmd(e, b"get_implementation",
-                                            len(buf), buf,
-                                            self._ffi.NULL, 0)
+            res = self._lib.ENGINE_ctrl_cmd(
+                e, b"get_implementation", len(buf), buf, self._ffi.NULL, 0
+            )
             self.openssl_assert(res > 0)
-        return self._ffi.string(buf).decode('ascii')
+        return self._ffi.string(buf).decode("ascii")
 
     def openssl_version_text(self):
         """
         Friendly string name of the loaded OpenSSL library. This is not
         necessarily the same version as it was compiled against.
 
-        Example: OpenSSL 1.0.1e 11 Feb 2013
+        Example: OpenSSL 1.1.1d  10 Sep 2019
         """
         return self._ffi.string(
             self._lib.OpenSSL_version(self._lib.OPENSSL_VERSION)
@@ -187,7 +325,7 @@
 
     def _evp_md_from_algorithm(self, algorithm):
         if algorithm.name == "blake2b" or algorithm.name == "blake2s":
-            alg = "{0}{1}".format(
+            alg = "{}{}".format(
                 algorithm.name, algorithm.digest_size * 8
             ).encode("ascii")
         else:
@@ -202,6 +340,9 @@
         return evp_md
 
     def hash_supported(self, algorithm):
+        if self._fips_enabled and not isinstance(algorithm, self._fips_hashes):
+            return False
+
         evp_md = self._evp_md_from_algorithm(algorithm)
         return evp_md != self._ffi.NULL
 
@@ -212,6 +353,8 @@
         return _HashContext(self, algorithm)
 
     def cipher_supported(self, cipher, mode):
+        if self._fips_enabled and not isinstance(cipher, self._fips_ciphers):
+            return False
         try:
             adapter = self._cipher_registry[type(cipher), type(mode)]
         except KeyError:
@@ -221,8 +364,10 @@
 
     def register_cipher_adapter(self, cipher_cls, mode_cls, adapter):
         if (cipher_cls, mode_cls) in self._cipher_registry:
-            raise ValueError("Duplicate registration for: {0} {1}.".format(
-                cipher_cls, mode_cls)
+            raise ValueError(
+                "Duplicate registration for: {} {}.".format(
+                    cipher_cls, mode_cls
+                )
             )
         self._cipher_registry[cipher_cls, mode_cls] = adapter
 
@@ -231,36 +376,28 @@
             self.register_cipher_adapter(
                 AES,
                 mode_cls,
-                GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}")
+                GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}"),
             )
         for mode_cls in [CBC, CTR, ECB, OFB, CFB]:
             self.register_cipher_adapter(
                 Camellia,
                 mode_cls,
-                GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}")
+                GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}"),
             )
         for mode_cls in [CBC, CFB, CFB8, OFB]:
             self.register_cipher_adapter(
-                TripleDES,
-                mode_cls,
-                GetCipherByName("des-ede3-{mode.name}")
+                TripleDES, mode_cls, GetCipherByName("des-ede3-{mode.name}")
             )
         self.register_cipher_adapter(
-            TripleDES,
-            ECB,
-            GetCipherByName("des-ede3")
+            TripleDES, ECB, GetCipherByName("des-ede3")
         )
         for mode_cls in [CBC, CFB, OFB, ECB]:
             self.register_cipher_adapter(
-                Blowfish,
-                mode_cls,
-                GetCipherByName("bf-{mode.name}")
+                Blowfish, mode_cls, GetCipherByName("bf-{mode.name}")
             )
         for mode_cls in [CBC, CFB, OFB, ECB]:
             self.register_cipher_adapter(
-                SEED,
-                mode_cls,
-                GetCipherByName("seed-{mode.name}")
+                SEED, mode_cls, GetCipherByName("seed-{mode.name}")
             )
         for cipher_cls, mode_cls in itertools.product(
             [CAST5, IDEA],
@@ -269,20 +406,84 @@
             self.register_cipher_adapter(
                 cipher_cls,
                 mode_cls,
-                GetCipherByName("{cipher.name}-{mode.name}")
+                GetCipherByName("{cipher.name}-{mode.name}"),
             )
+        self.register_cipher_adapter(ARC4, type(None), GetCipherByName("rc4"))
+        # We don't actually support RC2, this is just used by some tests.
+        self.register_cipher_adapter(_RC2, type(None), GetCipherByName("rc2"))
         self.register_cipher_adapter(
-            ARC4,
-            type(None),
-            GetCipherByName("rc4")
-        )
-        self.register_cipher_adapter(
-            ChaCha20,
-            type(None),
-            GetCipherByName("chacha20")
+            ChaCha20, type(None), GetCipherByName("chacha20")
         )
         self.register_cipher_adapter(AES, XTS, _get_xts_cipher)
 
+    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()
+
+        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,
+            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,
+        )
+        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,
+        )
+        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,
+        )
+        self._ocsp_req_ext_parser = _X509ExtensionParser(
+            self,
+            ext_count=self._lib.OCSP_REQUEST_get_ext_count,
+            get_ext=self._lib.OCSP_REQUEST_get_ext,
+            handlers=_OCSP_REQ_EXTENSION_HANDLERS,
+        )
+        self._ocsp_basicresp_ext_parser = _X509ExtensionParser(
+            self,
+            ext_count=self._lib.OCSP_BASICRESP_get_ext_count,
+            get_ext=self._lib.OCSP_BASICRESP_get_ext,
+            handlers=_OCSP_BASICRESP_EXTENSION_HANDLERS,
+        )
+        self._ocsp_singleresp_ext_parser = _X509ExtensionParser(
+            self,
+            ext_count=self._lib.OCSP_SINGLERESP_get_ext_count,
+            get_ext=self._lib.OCSP_SINGLERESP_get_ext,
+            handlers=singleresp_handlers,
+        )
+
+    def _register_x509_encoders(self):
+        self._extension_encode_handlers = _EXTENSION_ENCODE_HANDLERS.copy()
+        self._crl_extension_encode_handlers = (
+            _CRL_EXTENSION_ENCODE_HANDLERS.copy()
+        )
+        self._crl_entry_extension_encode_handlers = (
+            _CRL_ENTRY_EXTENSION_ENCODE_HANDLERS.copy()
+        )
+        self._ocsp_request_extension_encode_handlers = (
+            _OCSP_REQUEST_EXTENSION_ENCODE_HANDLERS.copy()
+        )
+        self._ocsp_basicresp_extension_encode_handlers = (
+            _OCSP_BASICRESP_EXTENSION_ENCODE_HANDLERS.copy()
+        )
+
     def create_symmetric_encryption_ctx(self, cipher, mode):
         return _CipherContext(self, cipher, mode, _CipherContext._ENCRYPT)
 
@@ -292,8 +493,9 @@
     def pbkdf2_hmac_supported(self, algorithm):
         return self.hmac_supported(algorithm)
 
-    def derive_pbkdf2_hmac(self, algorithm, length, salt, iterations,
-                           key_material):
+    def derive_pbkdf2_hmac(
+        self, algorithm, length, salt, iterations, key_material
+    ):
         buf = self._ffi.new("unsigned char[]", length)
         evp_md = self._evp_md_non_null_from_algorithm(algorithm)
         key_material_ptr = self._ffi.from_buffer(key_material)
@@ -305,7 +507,7 @@
             iterations,
             evp_md,
             length,
-            buf
+            buf,
         )
         self.openssl_assert(res == 1)
         return self._ffi.buffer(buf)[:]
@@ -313,6 +515,9 @@
     def _consume_errors(self):
         return binding._consume_errors(self._lib)
 
+    def _consume_errors_with_text(self):
+        return binding._consume_errors_with_text(self._lib)
+
     def _bn_to_int(self, bn):
         assert bn != self._ffi.NULL
 
@@ -323,7 +528,10 @@
             bin_len = self._lib.BN_bn2bin(bn, bin_ptr)
             # A zero length means the BN has value 0
             self.openssl_assert(bin_len >= 0)
-            return int.from_bytes(self._ffi.buffer(bin_ptr)[:bin_len], "big")
+            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)
@@ -382,8 +590,11 @@
         return _RSAPrivateKey(self, rsa_cdata, evp_pkey)
 
     def generate_rsa_parameters_supported(self, public_exponent, key_size):
-        return (public_exponent >= 3 and public_exponent & 1 != 0 and
-                key_size >= 512)
+        return (
+            public_exponent >= 3
+            and public_exponent & 1 != 0
+            and key_size >= 512
+        )
 
     def load_rsa_private_numbers(self, numbers):
         rsa._check_private_key_components(
@@ -394,7 +605,7 @@
             numbers.dmq1,
             numbers.iqmp,
             numbers.public_numbers.e,
-            numbers.public_numbers.n
+            numbers.public_numbers.n,
         )
         rsa_cdata = self._lib.RSA_new()
         self.openssl_assert(rsa_cdata != self._ffi.NULL)
@@ -413,8 +624,6 @@
         self.openssl_assert(res == 1)
         res = self._lib.RSA_set0_crt_params(rsa_cdata, dmp1, dmq1, iqmp)
         self.openssl_assert(res == 1)
-        res = self._lib.RSA_blinding_on(rsa_cdata, self._ffi.NULL)
-        self.openssl_assert(res == 1)
         evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata)
 
         return _RSAPrivateKey(self, rsa_cdata, evp_pkey)
@@ -452,9 +661,7 @@
         BIO is finished with.
         """
         data_ptr = self._ffi.from_buffer(data)
-        bio = self._lib.BIO_new_mem_buf(
-            data_ptr, len(data)
-        )
+        bio = self._lib.BIO_new_mem_buf(data_ptr, len(data))
         self.openssl_assert(bio != self._ffi.NULL)
 
         return _MemoryBIO(self._ffi.gc(bio, self._lib.BIO_free), data_ptr)
@@ -509,12 +716,18 @@
             self.openssl_assert(dh_cdata != self._ffi.NULL)
             dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free)
             return _DHPrivateKey(self, dh_cdata, evp_pkey)
+        elif key_type == getattr(self._lib, "EVP_PKEY_ED25519", None):
+            # EVP_PKEY_ED25519 is not present in OpenSSL < 1.1.1
+            return _Ed25519PrivateKey(self, evp_pkey)
         elif key_type == getattr(self._lib, "EVP_PKEY_X448", None):
             # EVP_PKEY_X448 is not present in OpenSSL < 1.1.1
             return _X448PrivateKey(self, evp_pkey)
         elif key_type == getattr(self._lib, "EVP_PKEY_X25519", None):
             # EVP_PKEY_X25519 is not present in OpenSSL < 1.1.0
             return _X25519PrivateKey(self, evp_pkey)
+        elif key_type == getattr(self._lib, "EVP_PKEY_ED448", None):
+            # EVP_PKEY_ED448 is not present in OpenSSL < 1.1.1
+            return _Ed448PrivateKey(self, evp_pkey)
         else:
             raise UnsupportedAlgorithm("Unsupported key type.")
 
@@ -546,25 +759,32 @@
             self.openssl_assert(dh_cdata != self._ffi.NULL)
             dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free)
             return _DHPublicKey(self, dh_cdata, evp_pkey)
+        elif key_type == getattr(self._lib, "EVP_PKEY_ED25519", None):
+            # EVP_PKEY_ED25519 is not present in OpenSSL < 1.1.1
+            return _Ed25519PublicKey(self, evp_pkey)
         elif key_type == getattr(self._lib, "EVP_PKEY_X448", None):
             # EVP_PKEY_X448 is not present in OpenSSL < 1.1.1
             return _X448PublicKey(self, evp_pkey)
         elif key_type == getattr(self._lib, "EVP_PKEY_X25519", None):
             # EVP_PKEY_X25519 is not present in OpenSSL < 1.1.0
             return _X25519PublicKey(self, evp_pkey)
+        elif key_type == getattr(self._lib, "EVP_PKEY_ED448", None):
+            # EVP_PKEY_X25519 is not present in OpenSSL < 1.1.1
+            return _Ed448PublicKey(self, evp_pkey)
         else:
             raise UnsupportedAlgorithm("Unsupported key type.")
 
     def _oaep_hash_supported(self, algorithm):
         if self._lib.Cryptography_HAS_RSA_OAEP_MD:
             return isinstance(
-                algorithm, (
+                algorithm,
+                (
                     hashes.SHA1,
                     hashes.SHA224,
                     hashes.SHA256,
                     hashes.SHA384,
                     hashes.SHA512,
-                )
+                ),
             )
         else:
             return isinstance(algorithm, hashes.SHA1)
@@ -576,27 +796,34 @@
             return self.hash_supported(padding._mgf._algorithm)
         elif isinstance(padding, OAEP) and isinstance(padding._mgf, MGF1):
             return (
-                self._oaep_hash_supported(padding._mgf._algorithm) and
-                self._oaep_hash_supported(padding._algorithm) and
-                (
-                    (padding._label is None or len(padding._label) == 0) or
-                    self._lib.Cryptography_HAS_RSA_OAEP_LABEL == 1
+                self._oaep_hash_supported(padding._mgf._algorithm)
+                and self._oaep_hash_supported(padding._algorithm)
+                and (
+                    (padding._label is None or len(padding._label) == 0)
+                    or self._lib.Cryptography_HAS_RSA_OAEP_LABEL == 1
                 )
             )
         else:
             return False
 
     def generate_dsa_parameters(self, key_size):
-        if key_size not in (1024, 2048, 3072):
-            raise ValueError("Key size must be 1024 or 2048 or 3072 bits.")
+        if key_size not in (1024, 2048, 3072, 4096):
+            raise ValueError(
+                "Key size must be 1024, 2048, 3072, or 4096 bits."
+            )
 
         ctx = self._lib.DSA_new()
         self.openssl_assert(ctx != self._ffi.NULL)
         ctx = self._ffi.gc(ctx, self._lib.DSA_free)
 
         res = self._lib.DSA_generate_parameters_ex(
-            ctx, key_size, self._ffi.NULL, 0,
-            self._ffi.NULL, self._ffi.NULL, self._ffi.NULL
+            ctx,
+            key_size,
+            self._ffi.NULL,
+            0,
+            self._ffi.NULL,
+            self._ffi.NULL,
+            self._ffi.NULL,
         )
 
         self.openssl_assert(res == 1)
@@ -692,20 +919,37 @@
     def create_cmac_ctx(self, algorithm):
         return _CMACContext(self, algorithm)
 
-    def create_x509_csr(self, builder, private_key, algorithm):
-        if not isinstance(algorithm, hashes.HashAlgorithm):
-            raise TypeError('Algorithm must be a registered hash algorithm.')
-
-        if (
-            isinstance(algorithm, hashes.MD5) and not
-            isinstance(private_key, rsa.RSAPrivateKey)
+    def _x509_check_signature_params(self, private_key, algorithm):
+        if isinstance(
+            private_key, (ed25519.Ed25519PrivateKey, ed448.Ed448PrivateKey)
+        ):
+            if algorithm is not None:
+                raise ValueError(
+                    "algorithm must be None when signing via ed25519 or ed448"
+                )
+        elif not isinstance(
+            private_key,
+            (rsa.RSAPrivateKey, dsa.DSAPrivateKey, ec.EllipticCurvePrivateKey),
+        ):
+            raise TypeError(
+                "Key must be an rsa, dsa, ec, ed25519, or ed448 private key."
+            )
+        elif not isinstance(algorithm, hashes.HashAlgorithm):
+            raise TypeError("Algorithm must be a registered hash algorithm.")
+        elif isinstance(algorithm, hashes.MD5) and not isinstance(
+            private_key, rsa.RSAPrivateKey
         ):
             raise ValueError(
-                "MD5 is not a supported hash algorithm for EC/DSA CSRs"
+                "MD5 hash algorithm is only supported with RSA keys"
             )
 
+    def create_x509_csr(self, builder, private_key, algorithm):
+        if not isinstance(builder, x509.CertificateSigningRequestBuilder):
+            raise TypeError("Builder type mismatch.")
+        self._x509_check_signature_params(private_key, algorithm)
+
         # Resolve the signature algorithm.
-        evp_md = self._evp_md_non_null_from_algorithm(algorithm)
+        evp_md = self._evp_md_x509_null_if_eddsa(private_key, algorithm)
 
         # Create an empty request.
         x509_req = self._lib.X509_REQ_new()
@@ -724,9 +968,7 @@
 
         # 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)
         self.openssl_assert(res == 1)
 
         # Add extensions.
@@ -735,60 +977,55 @@
         sk_extension = self._ffi.gc(
             sk_extension,
             lambda x: self._lib.sk_X509_EXTENSION_pop_free(
-                x, self._ffi.addressof(
+                x,
+                self._ffi.addressof(
                     self._lib._original_lib, "X509_EXTENSION_free"
-                )
-            )
+                ),
+            ),
         )
         # Don't GC individual extensions because the memory is owned by
         # sk_extensions and will be freed along with it.
         self._create_x509_extensions(
             extensions=builder._extensions,
-            handlers=_EXTENSION_ENCODE_HANDLERS,
+            handlers=self._extension_encode_handlers,
             x509_obj=sk_extension,
             add_func=self._lib.sk_X509_EXTENSION_insert,
-            gc=False
+            gc=False,
         )
         res = self._lib.X509_REQ_add_extensions(x509_req, sk_extension)
         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
-        )
-        if res == 0:
-            errors = self._consume_errors()
-            self.openssl_assert(
-                errors[0]._lib_reason_match(
-                    self._lib.ERR_LIB_RSA,
-                    self._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY
-                )
+        # Add attributes (all bytes encoded as ASN1 UTF8_STRING)
+        for attr_oid, attr_val in builder._attributes:
+            obj = _txt2obj_gc(self, attr_oid.dotted_string)
+            res = self._lib.X509_REQ_add1_attr_by_OBJ(
+                x509_req,
+                obj,
+                x509.name._ASN1Type.UTF8String.value,
+                attr_val,
+                len(attr_val),
             )
+            self.openssl_assert(res == 1)
 
-            raise ValueError("Digest too big for RSA key")
+        # Sign the request using the requester's private key.
+        res = self._lib.X509_REQ_sign(x509_req, private_key._evp_pkey, evp_md)
+        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):
         if not isinstance(builder, x509.CertificateBuilder):
-            raise TypeError('Builder type mismatch.')
-        if not isinstance(algorithm, hashes.HashAlgorithm):
-            raise TypeError('Algorithm must be a registered hash algorithm.')
-
-        if (
-            isinstance(algorithm, hashes.MD5) and not
-            isinstance(private_key, rsa.RSAPrivateKey)
-        ):
-            raise ValueError(
-                "MD5 is not a supported hash algorithm for EC/DSA certificates"
-            )
+            raise TypeError("Builder type mismatch.")
+        self._x509_check_signature_params(private_key, algorithm)
 
         # Resolve the signature algorithm.
-        evp_md = self._evp_md_non_null_from_algorithm(algorithm)
+        evp_md = self._evp_md_x509_null_if_eddsa(private_key, algorithm)
 
         # Create an empty certificate.
         x509_cert = self._lib.X509_new()
-        x509_cert = self._ffi.gc(x509_cert, backend._lib.X509_free)
+        x509_cert = self._ffi.gc(x509_cert, self._lib.X509_free)
 
         # Set the x509 version.
         res = self._lib.X509_set_version(x509_cert, builder._version.value)
@@ -813,21 +1050,21 @@
 
         # Set the "not before" time.
         self._set_asn1_time(
-            self._lib.X509_get_notBefore(x509_cert), builder._not_valid_before
+            self._lib.X509_getm_notBefore(x509_cert), builder._not_valid_before
         )
 
         # Set the "not after" time.
         self._set_asn1_time(
-            self._lib.X509_get_notAfter(x509_cert), builder._not_valid_after
+            self._lib.X509_getm_notAfter(x509_cert), builder._not_valid_after
         )
 
         # Add extensions.
         self._create_x509_extensions(
             extensions=builder._extensions,
-            handlers=_EXTENSION_ENCODE_HANDLERS,
+            handlers=self._extension_encode_handlers,
             x509_obj=x509_cert,
             add_func=self._lib.X509_add_ext,
-            gc=True
+            gc=True,
         )
 
         # Set the issuer name.
@@ -837,26 +1074,27 @@
         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, evp_md)
         if res == 0:
-            errors = self._consume_errors()
-            self.openssl_assert(
-                errors[0]._lib_reason_match(
-                    self._lib.ERR_LIB_RSA,
-                    self._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY
-                )
-            )
-            raise ValueError("Digest too big for RSA key")
+            errors = self._consume_errors_with_text()
+            raise ValueError("Signing failed", errors)
 
         return _Certificate(self, x509_cert)
 
+    def _evp_md_x509_null_if_eddsa(self, private_key, algorithm):
+        if isinstance(
+            private_key, (ed25519.Ed25519PrivateKey, ed448.Ed448PrivateKey)
+        ):
+            # OpenSSL requires us to pass NULL for EVP_MD for ed25519/ed448
+            return self._ffi.NULL
+        else:
+            return self._evp_md_non_null_from_algorithm(algorithm)
+
     def _set_asn1_time(self, asn1_time, time):
         if time.year >= 2050:
-            asn1_str = time.strftime('%Y%m%d%H%M%SZ').encode('ascii')
+            asn1_str = time.strftime("%Y%m%d%H%M%SZ").encode("ascii")
         else:
-            asn1_str = time.strftime('%y%m%d%H%M%SZ').encode('ascii')
+            asn1_str = time.strftime("%y%m%d%H%M%SZ").encode("ascii")
         res = self._lib.ASN1_TIME_set_string(asn1_time, asn1_str)
         self.openssl_assert(res == 1)
 
@@ -869,23 +1107,14 @@
 
     def create_x509_crl(self, builder, private_key, algorithm):
         if not isinstance(builder, x509.CertificateRevocationListBuilder):
-            raise TypeError('Builder type mismatch.')
-        if not isinstance(algorithm, hashes.HashAlgorithm):
-            raise TypeError('Algorithm must be a registered hash algorithm.')
+            raise TypeError("Builder type mismatch.")
+        self._x509_check_signature_params(private_key, algorithm)
 
-        if (
-            isinstance(algorithm, hashes.MD5) and not
-            isinstance(private_key, rsa.RSAPrivateKey)
-        ):
-            raise ValueError(
-                "MD5 is not a supported hash algorithm for EC/DSA CRLs"
-            )
-
-        evp_md = self._evp_md_non_null_from_algorithm(algorithm)
+        evp_md = self._evp_md_x509_null_if_eddsa(private_key, algorithm)
 
         # Create an empty CRL.
         x509_crl = self._lib.X509_CRL_new()
-        x509_crl = self._ffi.gc(x509_crl, backend._lib.X509_CRL_free)
+        x509_crl = self._ffi.gc(x509_crl, self._lib.X509_CRL_free)
 
         # Set the x509 CRL version. We only support v2 (integer value 1).
         res = self._lib.X509_CRL_set_version(x509_crl, 1)
@@ -910,44 +1139,33 @@
         # Add extensions.
         self._create_x509_extensions(
             extensions=builder._extensions,
-            handlers=_CRL_EXTENSION_ENCODE_HANDLERS,
+            handlers=self._crl_extension_encode_handlers,
             x509_obj=x509_crl,
             add_func=self._lib.X509_CRL_add_ext,
-            gc=True
+            gc=True,
         )
 
         # 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.Cryptography_X509_REVOKED_dup(
-                revoked_cert._x509_revoked
-            )
+            revoked = self._lib.X509_REVOKED_dup(revoked_cert._x509_revoked)
             self.openssl_assert(revoked != self._ffi.NULL)
             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)
         if res == 0:
-            errors = self._consume_errors()
-            self.openssl_assert(
-                errors[0]._lib_reason_match(
-                    self._lib.ERR_LIB_RSA,
-                    self._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY
-                )
-            )
-            raise ValueError("Digest too big for RSA key")
+            errors = self._consume_errors_with_text()
+            raise ValueError("Signing failed", errors)
 
         return _CertificateRevocationList(self, x509_crl)
 
-    def _create_x509_extensions(self, extensions, handlers, x509_obj,
-                                add_func, gc):
+    def _create_x509_extensions(
+        self, extensions, handlers, x509_obj, add_func, gc
+    ):
         for i, extension in enumerate(extensions):
-            x509_extension = self._create_x509_extension(
-                handlers, extension
-            )
+            x509_extension = self._create_x509_extension(handlers, extension)
             self.openssl_assert(x509_extension != self._ffi.NULL)
 
             if gc:
@@ -968,33 +1186,38 @@
             value = _encode_asn1_str_gc(self, extension.value.value)
             return self._create_raw_x509_extension(extension, value)
         elif isinstance(extension.value, x509.TLSFeature):
-            asn1 = _Integers([x.value for x in extension.value]).dump()
+            asn1 = encode_der(
+                SEQUENCE,
+                *[
+                    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)
         elif isinstance(extension.value, x509.PrecertPoison):
-            asn1 = asn1crypto.core.Null().dump()
-            value = _encode_asn1_str_gc(self, asn1)
+            value = _encode_asn1_str_gc(self, encode_der(NULL))
             return self._create_raw_x509_extension(extension, value)
         else:
             try:
                 encode = handlers[extension.oid]
             except KeyError:
                 raise NotImplementedError(
-                    'Extension not supported: {0}'.format(extension.oid)
+                    "Extension not supported: {}".format(extension.oid)
                 )
 
             ext_struct = encode(self, extension.value)
             nid = self._lib.OBJ_txt2nid(
                 extension.oid.dotted_string.encode("ascii")
             )
-            backend.openssl_assert(nid != self._lib.NID_undef)
+            self.openssl_assert(nid != self._lib.NID_undef)
             return self._lib.X509V3_EXT_i2d(
                 nid, 1 if extension.critical else 0, ext_struct
             )
 
     def create_x509_revoked_certificate(self, builder):
         if not isinstance(builder, x509.RevokedCertificateBuilder):
-            raise TypeError('Builder type mismatch.')
+            raise TypeError("Builder type mismatch.")
 
         x509_revoked = self._lib.X509_REVOKED_new()
         self.openssl_assert(x509_revoked != self._ffi.NULL)
@@ -1010,10 +1233,10 @@
         # add CRL entry extensions
         self._create_x509_extensions(
             extensions=builder._extensions,
-            handlers=_CRL_ENTRY_EXTENSION_ENCODE_HANDLERS,
+            handlers=self._crl_entry_extension_encode_handlers,
             x509_obj=x509_revoked,
             add_func=self._lib.X509_REVOKED_add_ext,
-            gc=True
+            gc=True,
         )
         return _RevokedCertificate(self, None, x509_revoked)
 
@@ -1054,7 +1277,8 @@
         mem_bio = self._bytes_to_bio(data)
         # only DH is supported currently
         dh_cdata = self._lib.PEM_read_bio_DHparams(
-            mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL)
+            mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL
+        )
         if dh_cdata != self._ffi.NULL:
             dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free)
             return _DHParameters(self, dh_cdata)
@@ -1119,9 +1343,7 @@
 
     def load_der_parameters(self, data):
         mem_bio = self._bytes_to_bio(data)
-        dh_cdata = self._lib.d2i_DHparams_bio(
-            mem_bio.bio, self._ffi.NULL
-        )
+        dh_cdata = self._lib.d2i_DHparams_bio(mem_bio.bio, self._ffi.NULL)
         if dh_cdata != self._ffi.NULL:
             dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free)
             return _DHParameters(self, dh_cdata)
@@ -1147,8 +1369,9 @@
         if x509 == self._ffi.NULL:
             self._consume_errors()
             raise ValueError(
-                "Unable to load certificate. See https://cryptography.io/en/la"
-                "test/faq/#why-can-t-i-import-my-pem-file for more details."
+                "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)
@@ -1173,7 +1396,8 @@
             self._consume_errors()
             raise ValueError(
                 "Unable to load CRL. See https://cryptography.io/en/la"
-                "test/faq/#why-can-t-i-import-my-pem-file for more details."
+                "test/faq.html#why-can-t-i-import-my-pem-file for more"
+                " details."
             )
 
         x509_crl = self._ffi.gc(x509_crl, self._lib.X509_CRL_free)
@@ -1197,8 +1421,9 @@
         if x509_req == self._ffi.NULL:
             self._consume_errors()
             raise ValueError(
-                "Unable to load request. See https://cryptography.io/en/la"
-                "test/faq/#why-can-t-i-import-my-pem-file for more details."
+                "Unable to load request. See https://cryptography.io/en/"
+                "latest/faq.html#why-can-t-i-import-my-pem-file for more"
+                " details."
             )
 
         x509_req = self._ffi.gc(x509_req, self._lib.X509_REQ_free)
@@ -1235,8 +1460,7 @@
 
         if evp_pkey == self._ffi.NULL:
             if userdata.error != 0:
-                errors = self._consume_errors()
-                self.openssl_assert(errors)
+                self._consume_errors()
                 if userdata.error == -1:
                     raise TypeError(
                         "Password was not given but private key is encrypted"
@@ -1244,7 +1468,7 @@
                 else:
                     assert userdata.error == -2
                     raise ValueError(
-                        "Passwords longer than {0} bytes are not supported "
+                        "Passwords longer than {} bytes are not supported "
                         "by this backend.".format(userdata.maxsize - 1)
                     )
             else:
@@ -1254,12 +1478,12 @@
 
         if password is not None and userdata.called == 0:
             raise TypeError(
-                "Password was given but private key is not encrypted.")
+                "Password was given but private key is not encrypted."
+            )
 
         assert (
-            (password is not None and userdata.called == 1) or
-            password is None
-        )
+            password is not None and userdata.called == 1
+        ) or password is None
 
         return convert_func(evp_pkey)
 
@@ -1267,46 +1491,34 @@
         errors = self._consume_errors()
 
         if not errors:
-            raise ValueError("Could not deserialize key data.")
-
-        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
+            raise ValueError(
+                "Could not deserialize key data. The data may be in an "
+                "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,
         ):
             raise ValueError("Bad decrypt. Incorrect password?")
 
-        elif (
-            errors[0]._lib_reason_match(
-                self._lib.ERR_LIB_EVP, self._lib.EVP_R_UNKNOWN_PBE_ALGORITHM
-            ) or errors[0]._lib_reason_match(
-                self._lib.ERR_LIB_PEM, self._lib.PEM_R_UNSUPPORTED_ENCRYPTION
-            )
-        ):
-            raise UnsupportedAlgorithm(
-                "PEM data is encrypted with an unsupported cipher",
-                _Reasons.UNSUPPORTED_CIPHER
-            )
-
         elif any(
             error._lib_reason_match(
                 self._lib.ERR_LIB_EVP,
-                self._lib.EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM
+                self._lib.EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM,
             )
             for error in errors
         ):
             raise ValueError("Unsupported public key algorithm.")
 
         else:
-            assert errors[0].lib in (
-                self._lib.ERR_LIB_EVP,
-                self._lib.ERR_LIB_PEM,
-                self._lib.ERR_LIB_ASN1,
+            raise ValueError(
+                "Could not deserialize key data. The data may be in an "
+                "incorrect format or it may be encrypted with an unsupported "
+                "algorithm."
             )
-            raise ValueError("Could not deserialize key data.")
 
     def elliptic_curve_supported(self, curve):
         try:
@@ -1317,14 +1529,7 @@
         group = self._lib.EC_GROUP_new_by_curve_name(curve_nid)
 
         if group == self._ffi.NULL:
-            errors = self._consume_errors()
-            self.openssl_assert(
-                curve_nid == self._lib.NID_undef or
-                errors[0]._lib_reason_match(
-                    self._lib.ERR_LIB_EC,
-                    self._lib.EC_R_UNKNOWN_GROUP
-                )
-            )
+            self._consume_errors()
             return False
         else:
             self.openssl_assert(curve_nid != self._lib.NID_undef)
@@ -1356,8 +1561,8 @@
             return _EllipticCurvePrivateKey(self, ec_cdata, evp_pkey)
         else:
             raise UnsupportedAlgorithm(
-                "Backend object does not support {0}.".format(curve.name),
-                _Reasons.UNSUPPORTED_ELLIPTIC_CURVE
+                "Backend object does not support {}.".format(curve.name),
+                _Reasons.UNSUPPORTED_ELLIPTIC_CURVE,
             )
 
     def load_elliptic_curve_private_numbers(self, numbers):
@@ -1372,7 +1577,8 @@
         self.openssl_assert(res == 1)
 
         ec_cdata = self._ec_key_set_public_key_affine_coordinates(
-            ec_cdata, public.x, public.y)
+            ec_cdata, public.x, public.y
+        )
 
         evp_pkey = self._ec_cdata_to_evp_pkey(ec_cdata)
 
@@ -1381,7 +1587,8 @@
     def load_elliptic_curve_public_numbers(self, numbers):
         ec_cdata = self._ec_key_new_by_curve(numbers.curve)
         ec_cdata = self._ec_key_set_public_key_affine_coordinates(
-            ec_cdata, numbers.x, numbers.y)
+            ec_cdata, numbers.x, numbers.y
+        )
         evp_pkey = self._ec_cdata_to_evp_pkey(ec_cdata)
 
         return _EllipticCurvePublicKey(self, ec_cdata, evp_pkey)
@@ -1419,8 +1626,9 @@
         value = self._ffi.gc(value, self._lib.BN_clear_free)
 
         with self._tmp_bn_ctx() as bn_ctx:
-            res = self._lib.EC_POINT_mul(group, point, value, self._ffi.NULL,
-                                         self._ffi.NULL, bn_ctx)
+            res = self._lib.EC_POINT_mul(
+                group, point, value, self._ffi.NULL, self._ffi.NULL, bn_ctx
+            )
             self.openssl_assert(res == 1)
 
             bn_x = self._lib.BN_CTX_get(bn_ctx)
@@ -1442,6 +1650,9 @@
 
     def _ec_key_new_by_curve(self, curve):
         curve_nid = self._elliptic_curve_to_nid(curve)
+        return self._ec_key_new_by_curve_nid(curve_nid)
+
+    def _ec_key_new_by_curve_nid(self, curve_nid):
         ec_cdata = self._lib.EC_KEY_new_by_curve_name(curve_nid)
         self.openssl_assert(ec_cdata != self._ffi.NULL)
         return self._ffi.gc(ec_cdata, self._lib.EC_KEY_free)
@@ -1472,15 +1683,13 @@
         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
-        )
+        certid = self._lib.OCSP_cert_to_id(evp_md, cert._x509, issuer._x509)
         self.openssl_assert(certid != self._ffi.NULL)
         onereq = self._lib.OCSP_request_add0_id(ocsp_req, certid)
         self.openssl_assert(onereq != self._ffi.NULL)
         self._create_x509_extensions(
             extensions=builder._extensions,
-            handlers=_OCSP_REQUEST_EXTENSION_ENCODE_HANDLERS,
+            handlers=self._ocsp_request_extension_encode_handlers,
             x509_obj=ocsp_req,
             add_func=self._lib.OCSP_REQUEST_add_ext,
             gc=True,
@@ -1488,6 +1697,8 @@
         return _OCSPRequest(self, ocsp_req)
 
     def _create_ocsp_basic_response(self, builder, private_key, algorithm):
+        self._x509_check_signature_params(private_key, algorithm)
+
         basic = self._lib.OCSP_BASICRESP_new()
         self.openssl_assert(basic != self._ffi.NULL)
         basic = self._ffi.gc(basic, self._lib.OCSP_BASICRESP_free)
@@ -1495,8 +1706,9 @@
             builder._response._algorithm
         )
         certid = self._lib.OCSP_cert_to_id(
-            evp_md, builder._response._cert._x509,
-            builder._response._issuer._x509
+            evp_md,
+            builder._response._cert._x509,
+            builder._response._issuer._x509,
         )
         self.openssl_assert(certid != self._ffi.NULL)
         certid = self._ffi.gc(certid, self._lib.OCSP_CERTID_free)
@@ -1528,11 +1740,11 @@
             reason,
             rev_time,
             this_update,
-            next_update
+            next_update,
         )
         self.openssl_assert(res != self._ffi.NULL)
         # okay, now sign the basic structure
-        evp_md = self._evp_md_non_null_from_algorithm(algorithm)
+        evp_md = self._evp_md_x509_null_if_eddsa(private_key, algorithm)
         responder_cert, responder_encoding = builder._responder_id
         flags = self._lib.OCSP_NOCERTS
         if responder_encoding is ocsp.OCSPResponderEncoding.HASH:
@@ -1545,30 +1757,33 @@
 
         self._create_x509_extensions(
             extensions=builder._extensions,
-            handlers=_OCSP_BASICRESP_EXTENSION_ENCODE_HANDLERS,
+            handlers=self._ocsp_basicresp_extension_encode_handlers,
             x509_obj=basic,
             add_func=self._lib.OCSP_BASICRESP_add_ext,
             gc=True,
         )
 
         res = self._lib.OCSP_basic_sign(
-            basic, responder_cert._x509, private_key._evp_pkey,
-            evp_md, self._ffi.NULL, flags
+            basic,
+            responder_cert._x509,
+            private_key._evp_pkey,
+            evp_md,
+            self._ffi.NULL,
+            flags,
         )
         if res != 1:
-            errors = self._consume_errors()
-            self.openssl_assert(
-                errors[0]._lib_reason_match(
-                    self._lib.ERR_LIB_X509,
-                    self._lib.X509_R_KEY_VALUES_MISMATCH
-                )
+            errors = self._consume_errors_with_text()
+            raise ValueError(
+                "Error while signing. responder_cert must be signed "
+                "by private_key",
+                errors,
             )
-            raise ValueError("responder_cert must be signed by private_key")
 
         return basic
 
-    def create_ocsp_response(self, response_status, builder, private_key,
-                             algorithm):
+    def create_ocsp_response(
+        self, response_status, builder, private_key, algorithm
+    ):
         if response_status is ocsp.OCSPResponseStatus.SUCCESSFUL:
             basic = self._create_ocsp_basic_response(
                 builder, private_key, algorithm
@@ -1584,9 +1799,8 @@
         return _OCSPResponse(self, ocsp_resp)
 
     def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve):
-        return (
-            self.elliptic_curve_supported(curve) and
-            isinstance(algorithm, ec.ECDH)
+        return self.elliptic_curve_supported(curve) and isinstance(
+            algorithm, ec.ECDH
         )
 
     def _ec_cdata_to_evp_pkey(self, ec_cdata):
@@ -1600,18 +1814,15 @@
         Get the NID for a curve name.
         """
 
-        curve_aliases = {
-            "secp192r1": "prime192v1",
-            "secp256r1": "prime256v1"
-        }
+        curve_aliases = {"secp192r1": "prime192v1", "secp256r1": "prime256v1"}
 
         curve_name = curve_aliases.get(curve.name, curve.name)
 
         curve_nid = self._lib.OBJ_sn2nid(curve_name.encode())
         if curve_nid == self._lib.NID_undef:
             raise UnsupportedAlgorithm(
-                "{0} is not a supported elliptic curve".format(curve.name),
-                _Reasons.UNSUPPORTED_ELLIPTIC_CURVE
+                "{} is not a supported elliptic curve".format(curve.name),
+                _Reasons.UNSUPPORTED_ELLIPTIC_CURVE,
             )
         return curve_nid
 
@@ -1674,47 +1885,32 @@
 
         return ctx
 
-    def _private_key_bytes(self, encoding, format, encryption_algorithm,
-                           evp_pkey, cdata):
+    def _private_key_bytes(
+        self, encoding, format, encryption_algorithm, key, evp_pkey, cdata
+    ):
+        # validate argument types
+        if not isinstance(encoding, serialization.Encoding):
+            raise TypeError("encoding must be an item from the Encoding enum")
         if not isinstance(format, serialization.PrivateFormat):
             raise TypeError(
                 "format must be an item from the PrivateFormat enum"
             )
-
-        # X9.62 encoding is only valid for EC public keys
-        if encoding is serialization.Encoding.X962:
-            raise ValueError("X9.62 format is only valid for EC public keys")
-
-        # Raw format and encoding are only valid for X25519, Ed25519, X448, and
-        # Ed448 keys. We capture those cases before this method is called so if
-        # we see those enum values here it means the caller has passed them to
-        # a key that doesn't support raw type
-        if format is serialization.PrivateFormat.Raw:
-            raise ValueError("raw format is invalid with this key or encoding")
-
-        if encoding is serialization.Encoding.Raw:
-            raise ValueError("raw encoding is invalid with this key or format")
-
-        if not isinstance(encryption_algorithm,
-                          serialization.KeySerializationEncryption):
+        if not isinstance(
+            encryption_algorithm, serialization.KeySerializationEncryption
+        ):
             raise TypeError(
                 "Encryption algorithm must be a KeySerializationEncryption "
                 "instance"
             )
 
+        # validate password
         if isinstance(encryption_algorithm, serialization.NoEncryption):
             password = b""
-            passlen = 0
-            evp_cipher = self._ffi.NULL
-        elif isinstance(encryption_algorithm,
-                        serialization.BestAvailableEncryption):
-            # This is a curated value that we will update over time.
-            evp_cipher = self._lib.EVP_get_cipherbyname(
-                b"aes-256-cbc"
-            )
+        elif isinstance(
+            encryption_algorithm, serialization.BestAvailableEncryption
+        ):
             password = encryption_algorithm.password
-            passlen = len(password)
-            if passlen > 1023:
+            if len(password) > 1023:
                 raise ValueError(
                     "Passwords longer than 1023 bytes are not supported by "
                     "this backend"
@@ -1722,183 +1918,156 @@
         else:
             raise ValueError("Unsupported encryption type")
 
-        key_type = self._lib.EVP_PKEY_id(evp_pkey)
-        if encoding is serialization.Encoding.PEM:
-            if format is serialization.PrivateFormat.PKCS8:
+        # PKCS8 + PEM/DER
+        if format is serialization.PrivateFormat.PKCS8:
+            if encoding is serialization.Encoding.PEM:
                 write_bio = self._lib.PEM_write_bio_PKCS8PrivateKey
-                key = evp_pkey
+            elif encoding is serialization.Encoding.DER:
+                write_bio = self._lib.i2d_PKCS8PrivateKey_bio
             else:
-                assert format is serialization.PrivateFormat.TraditionalOpenSSL
+                raise ValueError("Unsupported encoding for PKCS8")
+            return self._private_key_bytes_via_bio(
+                write_bio, evp_pkey, password
+            )
+
+        # TraditionalOpenSSL + PEM/DER
+        if format is serialization.PrivateFormat.TraditionalOpenSSL:
+            if self._fips_enabled and not isinstance(
+                encryption_algorithm, serialization.NoEncryption
+            ):
+                raise ValueError(
+                    "Encrypted traditional OpenSSL format is not "
+                    "supported in FIPS mode."
+                )
+            key_type = self._lib.EVP_PKEY_id(evp_pkey)
+
+            if encoding is serialization.Encoding.PEM:
                 if key_type == self._lib.EVP_PKEY_RSA:
                     write_bio = self._lib.PEM_write_bio_RSAPrivateKey
                 elif key_type == self._lib.EVP_PKEY_DSA:
                     write_bio = self._lib.PEM_write_bio_DSAPrivateKey
-                else:
-                    assert key_type == self._lib.EVP_PKEY_EC
+                elif key_type == self._lib.EVP_PKEY_EC:
                     write_bio = self._lib.PEM_write_bio_ECPrivateKey
+                else:
+                    raise ValueError(
+                        "Unsupported key type for TraditionalOpenSSL"
+                    )
+                return self._private_key_bytes_via_bio(
+                    write_bio, cdata, password
+                )
 
-                key = cdata
-        elif encoding is serialization.Encoding.DER:
-            if format is serialization.PrivateFormat.TraditionalOpenSSL:
-                if not isinstance(
-                    encryption_algorithm, serialization.NoEncryption
-                ):
+            if encoding is serialization.Encoding.DER:
+                if password:
                     raise ValueError(
                         "Encryption is not supported for DER encoded "
                         "traditional OpenSSL keys"
                     )
+                if key_type == self._lib.EVP_PKEY_RSA:
+                    write_bio = self._lib.i2d_RSAPrivateKey_bio
+                elif key_type == self._lib.EVP_PKEY_EC:
+                    write_bio = self._lib.i2d_ECPrivateKey_bio
+                elif key_type == self._lib.EVP_PKEY_DSA:
+                    write_bio = self._lib.i2d_DSAPrivateKey_bio
+                else:
+                    raise ValueError(
+                        "Unsupported key type for TraditionalOpenSSL"
+                    )
+                return self._bio_func_output(write_bio, cdata)
 
-                return self._private_key_bytes_traditional_der(key_type, cdata)
-            else:
-                assert format is serialization.PrivateFormat.PKCS8
-                write_bio = self._lib.i2d_PKCS8PrivateKey_bio
-                key = evp_pkey
+            raise ValueError("Unsupported encoding for TraditionalOpenSSL")
+
+        # OpenSSH + PEM
+        if format is serialization.PrivateFormat.OpenSSH:
+            if encoding is serialization.Encoding.PEM:
+                return ssh.serialize_ssh_private_key(key, password)
+
+            raise ValueError(
+                "OpenSSH private key format can only be used"
+                " with PEM encoding"
+            )
+
+        # Anything that key-specific code was supposed to handle earlier,
+        # like Raw.
+        raise ValueError("format is invalid with this key")
+
+    def _private_key_bytes_via_bio(self, write_bio, evp_pkey, password):
+        if not password:
+            evp_cipher = self._ffi.NULL
         else:
-            raise TypeError("encoding must be Encoding.PEM or Encoding.DER")
+            # This is a curated value that we will update over time.
+            evp_cipher = self._lib.EVP_get_cipherbyname(b"aes-256-cbc")
 
-        bio = self._create_mem_bio_gc()
-        res = write_bio(
-            bio,
-            key,
+        return self._bio_func_output(
+            write_bio,
+            evp_pkey,
             evp_cipher,
             password,
-            passlen,
+            len(password),
             self._ffi.NULL,
-            self._ffi.NULL
+            self._ffi.NULL,
         )
-        self.openssl_assert(res == 1)
-        return self._read_mem_bio(bio)
 
-    def _private_key_bytes_traditional_der(self, key_type, cdata):
-        if key_type == self._lib.EVP_PKEY_RSA:
-            write_bio = self._lib.i2d_RSAPrivateKey_bio
-        elif key_type == self._lib.EVP_PKEY_EC:
-            write_bio = self._lib.i2d_ECPrivateKey_bio
-        else:
-            self.openssl_assert(key_type == self._lib.EVP_PKEY_DSA)
-            write_bio = self._lib.i2d_DSAPrivateKey_bio
-
+    def _bio_func_output(self, write_bio, *args):
         bio = self._create_mem_bio_gc()
-        res = write_bio(bio, cdata)
+        res = write_bio(bio, *args)
         self.openssl_assert(res == 1)
         return self._read_mem_bio(bio)
 
     def _public_key_bytes(self, encoding, format, key, evp_pkey, cdata):
         if not isinstance(encoding, serialization.Encoding):
             raise TypeError("encoding must be an item from the Encoding enum")
-
-        # Compressed/UncompressedPoint are only valid for EC keys and those
-        # cases are handled by the ECPublicKey public_bytes method before this
-        # method is called
-        if format in (serialization.PublicFormat.UncompressedPoint,
-                      serialization.PublicFormat.CompressedPoint):
-            raise ValueError("Point formats are not valid for this key type")
-
-        # Raw format and encoding are only valid for X25519, Ed25519, X448, and
-        # Ed448 keys. We capture those cases before this method is called so if
-        # we see those enum values here it means the caller has passed them to
-        # a key that doesn't support raw type
-        if format is serialization.PublicFormat.Raw:
-            raise ValueError("raw format is invalid with this key or encoding")
-
-        if encoding is serialization.Encoding.Raw:
-            raise ValueError("raw encoding is invalid with this key or format")
-
-        if (
-            format is serialization.PublicFormat.OpenSSH or
-            encoding is serialization.Encoding.OpenSSH
-        ):
-            if (
-                format is not serialization.PublicFormat.OpenSSH or
-                encoding is not serialization.Encoding.OpenSSH
-            ):
-                raise ValueError(
-                    "OpenSSH format must be used with OpenSSH encoding"
-                )
-            return self._openssh_public_key_bytes(key)
-        elif format is serialization.PublicFormat.SubjectPublicKeyInfo:
-            if encoding is serialization.Encoding.PEM:
-                write_bio = self._lib.PEM_write_bio_PUBKEY
-            else:
-                assert encoding is serialization.Encoding.DER
-                write_bio = self._lib.i2d_PUBKEY_bio
-
-            key = evp_pkey
-        elif format is serialization.PublicFormat.PKCS1:
-            # Only RSA is supported here.
-            assert self._lib.EVP_PKEY_id(evp_pkey) == self._lib.EVP_PKEY_RSA
-            if encoding is serialization.Encoding.PEM:
-                write_bio = self._lib.PEM_write_bio_RSAPublicKey
-            else:
-                assert encoding is serialization.Encoding.DER
-                write_bio = self._lib.i2d_RSAPublicKey_bio
-
-            key = cdata
-        else:
+        if not isinstance(format, serialization.PublicFormat):
             raise TypeError(
                 "format must be an item from the PublicFormat enum"
             )
 
-        bio = self._create_mem_bio_gc()
-        res = write_bio(bio, key)
-        self.openssl_assert(res == 1)
-        return self._read_mem_bio(bio)
-
-    def _openssh_public_key_bytes(self, key):
-        if isinstance(key, rsa.RSAPublicKey):
-            public_numbers = key.public_numbers()
-            return b"ssh-rsa " + base64.b64encode(
-                ssh._ssh_write_string(b"ssh-rsa") +
-                ssh._ssh_write_mpint(public_numbers.e) +
-                ssh._ssh_write_mpint(public_numbers.n)
-            )
-        elif isinstance(key, dsa.DSAPublicKey):
-            public_numbers = key.public_numbers()
-            parameter_numbers = public_numbers.parameter_numbers
-            return b"ssh-dss " + base64.b64encode(
-                ssh._ssh_write_string(b"ssh-dss") +
-                ssh._ssh_write_mpint(parameter_numbers.p) +
-                ssh._ssh_write_mpint(parameter_numbers.q) +
-                ssh._ssh_write_mpint(parameter_numbers.g) +
-                ssh._ssh_write_mpint(public_numbers.y)
-            )
-        else:
-            assert isinstance(key, ec.EllipticCurvePublicKey)
-            public_numbers = key.public_numbers()
-            try:
-                curve_name = {
-                    ec.SECP256R1: b"nistp256",
-                    ec.SECP384R1: b"nistp384",
-                    ec.SECP521R1: b"nistp521",
-                }[type(public_numbers.curve)]
-            except KeyError:
+        # SubjectPublicKeyInfo + PEM/DER
+        if format is serialization.PublicFormat.SubjectPublicKeyInfo:
+            if encoding is serialization.Encoding.PEM:
+                write_bio = self._lib.PEM_write_bio_PUBKEY
+            elif encoding is serialization.Encoding.DER:
+                write_bio = self._lib.i2d_PUBKEY_bio
+            else:
                 raise ValueError(
-                    "Only SECP256R1, SECP384R1, and SECP521R1 curves are "
-                    "supported by the SSH public key format"
+                    "SubjectPublicKeyInfo works only with PEM or DER encoding"
                 )
+            return self._bio_func_output(write_bio, evp_pkey)
 
-            point = key.public_bytes(
-                serialization.Encoding.X962,
-                serialization.PublicFormat.UncompressedPoint
+        # PKCS1 + PEM/DER
+        if format is serialization.PublicFormat.PKCS1:
+            # Only RSA is supported here.
+            key_type = self._lib.EVP_PKEY_id(evp_pkey)
+            if key_type != self._lib.EVP_PKEY_RSA:
+                raise ValueError("PKCS1 format is supported only for RSA keys")
+
+            if encoding is serialization.Encoding.PEM:
+                write_bio = self._lib.PEM_write_bio_RSAPublicKey
+            elif encoding is serialization.Encoding.DER:
+                write_bio = self._lib.i2d_RSAPublicKey_bio
+            else:
+                raise ValueError("PKCS1 works only with PEM or DER encoding")
+            return self._bio_func_output(write_bio, cdata)
+
+        # OpenSSH + OpenSSH
+        if format is serialization.PublicFormat.OpenSSH:
+            if encoding is serialization.Encoding.OpenSSH:
+                return ssh.serialize_ssh_public_key(key)
+
+            raise ValueError(
+                "OpenSSH format must be used with OpenSSH encoding"
             )
-            return b"ecdsa-sha2-" + curve_name + b" " + base64.b64encode(
-                ssh._ssh_write_string(b"ecdsa-sha2-" + curve_name) +
-                ssh._ssh_write_string(curve_name) +
-                ssh._ssh_write_string(point)
-            )
+
+        # Anything that key-specific code was supposed to handle earlier,
+        # like Raw, CompressedPoint, UncompressedPoint
+        raise ValueError("format is invalid with this key")
 
     def _parameter_bytes(self, encoding, format, cdata):
         if encoding is serialization.Encoding.OpenSSH:
-            raise TypeError(
-                "OpenSSH encoding is not supported"
-            )
+            raise TypeError("OpenSSH encoding is not supported")
 
         # Only DH is supported here currently.
         q = self._ffi.new("BIGNUM **")
-        self._lib.DH_get0_pqg(cdata,
-                              self._ffi.NULL,
-                              q,
-                              self._ffi.NULL)
+        self._lib.DH_get0_pqg(cdata, self._ffi.NULL, q, self._ffi.NULL)
         if encoding is serialization.Encoding.PEM:
             if q[0] != self._ffi.NULL:
                 write_bio = self._lib.PEM_write_bio_DHxparams
@@ -1918,8 +2087,12 @@
         return self._read_mem_bio(bio)
 
     def generate_dh_parameters(self, generator, key_size):
-        if key_size < 512:
-            raise ValueError("DH key_size must be at least 512 bits")
+        if key_size < dh._MIN_MODULUS_SIZE:
+            raise ValueError(
+                "DH key_size must be at least {} bits".format(
+                    dh._MIN_MODULUS_SIZE
+                )
+            )
 
         if generator not in (2, 5):
             raise ValueError("DH generator must be 2 or 5")
@@ -1929,10 +2102,7 @@
         dh_param_cdata = self._ffi.gc(dh_param_cdata, self._lib.DH_free)
 
         res = self._lib.DH_generate_parameters_ex(
-            dh_param_cdata,
-            key_size,
-            generator,
-            self._ffi.NULL
+            dh_param_cdata, key_size, generator, self._ffi.NULL
         )
         self.openssl_assert(res == 1)
 
@@ -1956,7 +2126,8 @@
 
     def generate_dh_private_key_and_parameters(self, generator, key_size):
         return self.generate_dh_private_key(
-            self.generate_dh_parameters(generator, key_size))
+            self.generate_dh_parameters(generator, key_size)
+        )
 
     def load_dh_private_numbers(self, numbers):
         parameter_numbers = numbers.public_numbers.parameter_numbers
@@ -1995,12 +2166,10 @@
         # the key to the attacker in exchange for having the full key space
         # available. See: https://crypto.stackexchange.com/questions/12961
         if codes[0] != 0 and not (
-            parameter_numbers.g == 2 and
-            codes[0] ^ self._lib.DH_NOT_SUITABLE_GENERATOR == 0
+            parameter_numbers.g == 2
+            and codes[0] ^ self._lib.DH_NOT_SUITABLE_GENERATOR == 0
         ):
-            raise ValueError(
-                "DH private numbers did not pass safety checks."
-            )
+            raise ValueError("DH private numbers did not pass safety checks.")
 
         evp_pkey = self._dh_cdata_to_evp_pkey(dh_cdata)
 
@@ -2095,11 +2264,11 @@
 
         evp_pkey = self._create_evp_pkey_gc()
         res = self._lib.EVP_PKEY_set_type(evp_pkey, self._lib.NID_X25519)
-        backend.openssl_assert(res == 1)
+        self.openssl_assert(res == 1)
         res = self._lib.EVP_PKEY_set1_tls_encodedpoint(
             evp_pkey, data, len(data)
         )
-        backend.openssl_assert(res == 1)
+        self.openssl_assert(res == 1)
         return _X25519PublicKey(self, evp_pkey)
 
     def x25519_load_private_bytes(self, data):
@@ -2127,7 +2296,7 @@
             ba[0:16] = pkcs8_prefix
             ba[16:] = data
             bio = self._bytes_to_bio(ba)
-            evp_pkey = backend._lib.d2i_PrivateKey_bio(bio.bio, self._ffi.NULL)
+            evp_pkey = self._lib.d2i_PrivateKey_bio(bio.bio, self._ffi.NULL)
 
         self.openssl_assert(evp_pkey != self._ffi.NULL)
         evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free)
@@ -2154,7 +2323,9 @@
         return _X25519PrivateKey(self, evp_pkey)
 
     def x25519_supported(self):
-        return self._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
+        if self._fips_enabled:
+            return False
+        return not self._lib.CRYPTOGRAPHY_IS_LIBRESSL
 
     def x448_load_public_bytes(self, data):
         if len(data) != 56:
@@ -2184,44 +2355,115 @@
         return _X448PrivateKey(self, evp_pkey)
 
     def x448_supported(self):
+        if self._fips_enabled:
+            return False
         return not self._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111
 
+    def ed25519_supported(self):
+        if self._fips_enabled:
+            return False
+        return not self._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B
+
+    def ed25519_load_public_bytes(self, data):
+        utils._check_bytes("data", data)
+
+        if len(data) != ed25519._ED25519_KEY_SIZE:
+            raise ValueError("An Ed25519 public key is 32 bytes long")
+
+        evp_pkey = self._lib.EVP_PKEY_new_raw_public_key(
+            self._lib.NID_ED25519, self._ffi.NULL, data, len(data)
+        )
+        self.openssl_assert(evp_pkey != self._ffi.NULL)
+        evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free)
+
+        return _Ed25519PublicKey(self, evp_pkey)
+
+    def ed25519_load_private_bytes(self, data):
+        if len(data) != ed25519._ED25519_KEY_SIZE:
+            raise ValueError("An Ed25519 private key is 32 bytes long")
+
+        utils._check_byteslike("data", data)
+        data_ptr = self._ffi.from_buffer(data)
+        evp_pkey = self._lib.EVP_PKEY_new_raw_private_key(
+            self._lib.NID_ED25519, self._ffi.NULL, data_ptr, len(data)
+        )
+        self.openssl_assert(evp_pkey != self._ffi.NULL)
+        evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free)
+
+        return _Ed25519PrivateKey(self, evp_pkey)
+
+    def ed25519_generate_key(self):
+        evp_pkey = self._evp_pkey_keygen_gc(self._lib.NID_ED25519)
+        return _Ed25519PrivateKey(self, evp_pkey)
+
+    def ed448_supported(self):
+        if self._fips_enabled:
+            return False
+        return not self._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B
+
+    def ed448_load_public_bytes(self, data):
+        utils._check_bytes("data", data)
+        if len(data) != _ED448_KEY_SIZE:
+            raise ValueError("An Ed448 public key is 57 bytes long")
+
+        evp_pkey = self._lib.EVP_PKEY_new_raw_public_key(
+            self._lib.NID_ED448, self._ffi.NULL, data, len(data)
+        )
+        self.openssl_assert(evp_pkey != self._ffi.NULL)
+        evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free)
+
+        return _Ed448PublicKey(self, evp_pkey)
+
+    def ed448_load_private_bytes(self, data):
+        utils._check_byteslike("data", data)
+        if len(data) != _ED448_KEY_SIZE:
+            raise ValueError("An Ed448 private key is 57 bytes long")
+
+        data_ptr = self._ffi.from_buffer(data)
+        evp_pkey = self._lib.EVP_PKEY_new_raw_private_key(
+            self._lib.NID_ED448, self._ffi.NULL, data_ptr, len(data)
+        )
+        self.openssl_assert(evp_pkey != self._ffi.NULL)
+        evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free)
+
+        return _Ed448PrivateKey(self, evp_pkey)
+
+    def ed448_generate_key(self):
+        evp_pkey = self._evp_pkey_keygen_gc(self._lib.NID_ED448)
+        return _Ed448PrivateKey(self, evp_pkey)
+
     def derive_scrypt(self, key_material, salt, length, n, r, p):
         buf = self._ffi.new("unsigned char[]", length)
         key_material_ptr = self._ffi.from_buffer(key_material)
         res = self._lib.EVP_PBE_scrypt(
-            key_material_ptr, len(key_material), salt, len(salt), n, r, p,
-            scrypt._MEM_LIMIT, buf, length
+            key_material_ptr,
+            len(key_material),
+            salt,
+            len(salt),
+            n,
+            r,
+            p,
+            scrypt._MEM_LIMIT,
+            buf,
+            length,
         )
         if res != 1:
-            errors = self._consume_errors()
-            if not self._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111:
-                # This error is only added to the stack in 1.1.1+
-                self.openssl_assert(
-                    errors[0]._lib_reason_match(
-                        self._lib.ERR_LIB_EVP,
-                        self._lib.ERR_R_MALLOC_FAILURE
-                    ) or
-                    errors[0]._lib_reason_match(
-                        self._lib.ERR_LIB_EVP,
-                        self._lib.EVP_R_MEMORY_LIMIT_EXCEEDED
-                    )
-                )
-
+            errors = self._consume_errors_with_text()
             # memory required formula explained here:
             # https://blog.filippo.io/the-scrypt-parameters/
-            min_memory = 128 * n * r // (1024**2)
+            min_memory = 128 * n * r // (1024 ** 2)
             raise MemoryError(
                 "Not enough memory to derive key. These parameters require"
-                " {} MB of memory.".format(min_memory)
+                " {} MB of memory.".format(min_memory),
+                errors,
             )
         return self._ffi.buffer(buf)[:]
 
     def aead_cipher_supported(self, cipher):
         cipher_name = aead._aead_cipher_name(cipher)
-        return (
-            self._lib.EVP_get_cipherbyname(cipher_name) != self._ffi.NULL
-        )
+        if self._fips_enabled and cipher_name not in self._fips_aead:
+            return False
+        return self._lib.EVP_get_cipherbyname(cipher_name) != self._ffi.NULL
 
     @contextlib.contextmanager
     def _zeroed_bytearray(self, length):
@@ -2306,12 +2548,216 @@
             num = self._lib.sk_X509_num(sk_x509_ptr[0])
             for i in range(num):
                 x509 = self._lib.sk_X509_value(sk_x509, i)
-                x509 = self._ffi.gc(x509, self._lib.X509_free)
                 self.openssl_assert(x509 != self._ffi.NULL)
+                x509 = self._ffi.gc(x509, self._lib.X509_free)
                 additional_certificates.append(_Certificate(self, x509))
 
         return (key, cert, additional_certificates)
 
+    def serialize_key_and_certificates_to_pkcs12(
+        self, name, key, cert, cas, encryption_algorithm
+    ):
+        password = None
+        if name is not None:
+            utils._check_bytes("name", name)
+
+        if isinstance(encryption_algorithm, serialization.NoEncryption):
+            nid_cert = -1
+            nid_key = -1
+            pkcs12_iter = 0
+            mac_iter = 0
+        elif isinstance(
+            encryption_algorithm, serialization.BestAvailableEncryption
+        ):
+            # PKCS12 encryption is hopeless trash and can never be fixed.
+            # This is the least terrible option.
+            nid_cert = self._lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC
+            nid_key = self._lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC
+            # At least we can set this higher than OpenSSL's default
+            pkcs12_iter = 20000
+            # mac_iter chosen for compatibility reasons, see:
+            # https://www.openssl.org/docs/man1.1.1/man3/PKCS12_create.html
+            # Did we mention how lousy PKCS12 encryption is?
+            mac_iter = 1
+            password = encryption_algorithm.password
+        else:
+            raise ValueError("Unsupported key encryption type")
+
+        if cas is None or len(cas) == 0:
+            sk_x509 = self._ffi.NULL
+        else:
+            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):
+                res = self._lib.sk_X509_push(sk_x509, ca._x509)
+                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:
+                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,
+                    sk_x509,
+                    nid_key,
+                    nid_cert,
+                    pkcs12_iter,
+                    mac_iter,
+                    0,
+                )
+
+        self.openssl_assert(p12 != self._ffi.NULL)
+        p12 = self._ffi.gc(p12, self._lib.PKCS12_free)
+
+        bio = self._create_mem_bio_gc()
+        res = self._lib.i2d_PKCS12_bio(bio, p12)
+        self.openssl_assert(res > 0)
+        return self._read_mem_bio(bio)
+
+    def poly1305_supported(self):
+        if self._fips_enabled:
+            return False
+        return self._lib.Cryptography_HAS_POLY1305 == 1
+
+    def create_poly1305_ctx(self, key):
+        utils._check_byteslike("key", key)
+        if len(key) != _POLY1305_KEY_SIZE:
+            raise ValueError("A poly1305 key is 32 bytes long")
+
+        return _Poly1305Context(self, key)
+
+    def load_pem_pkcs7_certificates(self, data):
+        utils._check_bytes("data", data)
+        bio = self._bytes_to_bio(data)
+        p7 = self._lib.PEM_read_bio_PKCS7(
+            bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL
+        )
+        if p7 == self._ffi.NULL:
+            self._consume_errors()
+            raise ValueError("Unable to parse PKCS7 data")
+
+        p7 = self._ffi.gc(p7, self._lib.PKCS7_free)
+        return self._load_pkcs7_certificates(p7)
+
+    def load_der_pkcs7_certificates(self, data):
+        utils._check_bytes("data", data)
+        bio = self._bytes_to_bio(data)
+        p7 = self._lib.d2i_PKCS7_bio(bio.bio, self._ffi.NULL)
+        if p7 == self._ffi.NULL:
+            self._consume_errors()
+            raise ValueError("Unable to parse PKCS7 data")
+
+        p7 = self._ffi.gc(p7, self._lib.PKCS7_free)
+        return self._load_pkcs7_certificates(p7)
+
+    def _load_pkcs7_certificates(self, p7):
+        nid = self._lib.OBJ_obj2nid(p7.type)
+        self.openssl_assert(nid != self._lib.NID_undef)
+        if nid != self._lib.NID_pkcs7_signed:
+            raise UnsupportedAlgorithm(
+                "Only basic signed structures are currently supported. NID"
+                " for this data was {}".format(nid),
+                _Reasons.UNSUPPORTED_SERIALIZATION,
+            )
+
+        sk_x509 = p7.d.sign.cert
+        num = self._lib.sk_X509_num(sk_x509)
+        certs = []
+        for i in range(num):
+            x509 = self._lib.sk_X509_value(sk_x509, i)
+            self.openssl_assert(x509 != self._ffi.NULL)
+            res = self._lib.X509_up_ref(x509)
+            # When OpenSSL is less than 1.1.0 up_ref returns the current
+            # 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))
+
+        return certs
+
+    def pkcs7_sign(self, builder, encoding, options):
+        bio = self._bytes_to_bio(builder._data)
+        init_flags = self._lib.PKCS7_PARTIAL
+        final_flags = 0
+
+        if len(builder._additional_certs) == 0:
+            certs = self._ffi.NULL
+        else:
+            certs = self._lib.sk_X509_new_null()
+            certs = self._ffi.gc(certs, self._lib.sk_X509_free)
+            for cert in builder._additional_certs:
+                res = self._lib.sk_X509_push(certs, cert._x509)
+                self.openssl_assert(res >= 1)
+
+        if pkcs7.PKCS7Options.DetachedSignature in options:
+            # Don't embed the data in the PKCS7 structure
+            init_flags |= self._lib.PKCS7_DETACHED
+            final_flags |= self._lib.PKCS7_DETACHED
+
+        # This just inits a structure for us. However, there
+        # are flags we need to set, joy.
+        p7 = self._lib.PKCS7_sign(
+            self._ffi.NULL,
+            self._ffi.NULL,
+            certs,
+            self._ffi.NULL,
+            init_flags,
+        )
+        self.openssl_assert(p7 != self._ffi.NULL)
+        p7 = self._ffi.gc(p7, self._lib.PKCS7_free)
+        signer_flags = 0
+        # These flags are configurable on a per-signature basis
+        # but we've deliberately chosen to make the API only allow
+        # setting it across all signatures for now.
+        if pkcs7.PKCS7Options.NoCapabilities in options:
+            signer_flags |= self._lib.PKCS7_NOSMIMECAP
+        elif pkcs7.PKCS7Options.NoAttributes in options:
+            signer_flags |= self._lib.PKCS7_NOATTR
+
+        if pkcs7.PKCS7Options.NoCerts in options:
+            signer_flags |= self._lib.PKCS7_NOCERTS
+
+        for certificate, private_key, hash_algorithm in builder._signers:
+            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
+            )
+            self.openssl_assert(p7signerinfo != self._ffi.NULL)
+
+        for option in options:
+            # DetachedSignature, NoCapabilities, and NoAttributes are already
+            # handled so we just need to check these last two options.
+            if option is pkcs7.PKCS7Options.Text:
+                final_flags |= self._lib.PKCS7_TEXT
+            elif option is pkcs7.PKCS7Options.Binary:
+                final_flags |= self._lib.PKCS7_BINARY
+
+        bio_out = self._create_mem_bio_gc()
+        if encoding is serialization.Encoding.SMIME:
+            # This finalizes the structure
+            res = self._lib.SMIME_write_PKCS7(
+                bio_out, p7, bio.bio, final_flags
+            )
+        elif encoding is serialization.Encoding.PEM:
+            res = self._lib.PKCS7_final(p7, bio.bio, final_flags)
+            self.openssl_assert(res == 1)
+            res = self._lib.PEM_write_bio_PKCS7_stream(
+                bio_out, p7, bio.bio, final_flags
+            )
+        else:
+            assert encoding is serialization.Encoding.DER
+            # We need to call finalize here becauase i2d_PKCS7_bio does not
+            # finalize.
+            res = self._lib.PKCS7_final(p7, bio.bio, final_flags)
+            self.openssl_assert(res == 1)
+            res = self._lib.i2d_PKCS7_bio(bio_out, p7)
+        self.openssl_assert(res == 1)
+        return self._read_mem_bio(bio_out)
+
 
 class GetCipherByName(object):
     def __init__(self, fmt):
@@ -2323,7 +2769,7 @@
 
 
 def _get_xts_cipher(backend, cipher, mode):
-    cipher_name = "aes-{0}-xts".format(cipher.key_size // 2)
+    cipher_name = "aes-{}-xts".format(cipher.key_size // 2)
     return backend._lib.EVP_get_cipherbyname(cipher_name.encode("ascii"))
 
 
diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py
index 66ac5fd..ad5dad3 100644
--- a/src/cryptography/hazmat/backends/openssl/ciphers.py
+++ b/src/cryptography/hazmat/backends/openssl/ciphers.py
@@ -17,6 +17,7 @@
 class _CipherContext(object):
     _ENCRYPT = 1
     _DECRYPT = 0
+    _MAX_CHUNK_SIZE = 2 ** 30 - 1
 
     def __init__(self, backend, cipher, mode, operation):
         self._backend = backend
@@ -40,10 +41,11 @@
             adapter = registry[type(cipher), type(mode)]
         except KeyError:
             raise UnsupportedAlgorithm(
-                "cipher {0} in {1} mode is not supported "
+                "cipher {} in {} mode is not supported "
                 "by this backend.".format(
-                    cipher.name, mode.name if mode else mode),
-                _Reasons.UNSUPPORTED_CIPHER
+                    cipher.name, mode.name if mode else mode
+                ),
+                _Reasons.UNSUPPORTED_CIPHER,
             )
 
         evp_cipher = adapter(self._backend, cipher, mode)
@@ -53,7 +55,7 @@
                 msg += "in {0.name} mode ".format(mode)
             msg += (
                 "is not supported by this backend (Your version of OpenSSL "
-                "may be too old. Current version: {0}.)"
+                "may be too old. Current version: {}.)"
             ).format(self._backend.openssl_version_text())
             raise UnsupportedAlgorithm(msg, _Reasons.UNSUPPORTED_CIPHER)
 
@@ -70,11 +72,14 @@
         else:
             iv_nonce = self._backend._ffi.NULL
         # begin init with cipher and operation type
-        res = self._backend._lib.EVP_CipherInit_ex(ctx, evp_cipher,
-                                                   self._backend._ffi.NULL,
-                                                   self._backend._ffi.NULL,
-                                                   self._backend._ffi.NULL,
-                                                   operation)
+        res = self._backend._lib.EVP_CipherInit_ex(
+            ctx,
+            evp_cipher,
+            self._backend._ffi.NULL,
+            self._backend._ffi.NULL,
+            self._backend._ffi.NULL,
+            operation,
+        )
         self._backend.openssl_assert(res != 0)
         # set the key length to handle variable key ciphers
         res = self._backend._lib.EVP_CIPHER_CTX_set_key_length(
@@ -83,26 +88,21 @@
         self._backend.openssl_assert(res != 0)
         if isinstance(mode, modes.GCM):
             res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
-                ctx, self._backend._lib.EVP_CTRL_AEAD_SET_IVLEN,
-                len(iv_nonce), self._backend._ffi.NULL
+                ctx,
+                self._backend._lib.EVP_CTRL_AEAD_SET_IVLEN,
+                len(iv_nonce),
+                self._backend._ffi.NULL,
             )
             self._backend.openssl_assert(res != 0)
             if mode.tag is not None:
                 res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
-                    ctx, self._backend._lib.EVP_CTRL_AEAD_SET_TAG,
-                    len(mode.tag), mode.tag
+                    ctx,
+                    self._backend._lib.EVP_CTRL_AEAD_SET_TAG,
+                    len(mode.tag),
+                    mode.tag,
                 )
                 self._backend.openssl_assert(res != 0)
                 self._tag = mode.tag
-            elif (
-                self._operation == self._DECRYPT and
-                self._backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and
-                not self._backend._lib.CRYPTOGRAPHY_IS_LIBRESSL
-            ):
-                raise NotImplementedError(
-                    "delayed passing of GCM tag requires OpenSSL >= 1.0.2."
-                    " To use this feature please update OpenSSL"
-                )
 
         # pass key/iv
         res = self._backend._lib.EVP_CipherInit_ex(
@@ -111,7 +111,7 @@
             self._backend._ffi.NULL,
             self._backend._ffi.from_buffer(cipher.key),
             iv_nonce,
-            operation
+            operation,
         )
         self._backend.openssl_assert(res != 0)
         # We purposely disable padding here as it's handled higher up in the
@@ -125,36 +125,38 @@
         return bytes(buf[:n])
 
     def update_into(self, data, buf):
-        if len(buf) < (len(data) + self._block_size_bytes - 1):
+        total_data_len = len(data)
+        if len(buf) < (total_data_len + self._block_size_bytes - 1):
             raise ValueError(
-                "buffer must be at least {0} bytes for this "
+                "buffer must be at least {} bytes for this "
                 "payload".format(len(data) + self._block_size_bytes - 1)
             )
 
-        buf = self._backend._ffi.cast(
-            "unsigned char *", self._backend._ffi.from_buffer(buf)
-        )
+        data_processed = 0
+        total_out = 0
         outlen = self._backend._ffi.new("int *")
-        res = self._backend._lib.EVP_CipherUpdate(
-            self._ctx, buf, outlen,
-            self._backend._ffi.from_buffer(data), len(data)
-        )
-        self._backend.openssl_assert(res != 0)
-        return outlen[0]
+        baseoutbuf = self._backend._ffi.from_buffer(buf)
+        baseinbuf = self._backend._ffi.from_buffer(data)
+
+        while data_processed != total_data_len:
+            outbuf = baseoutbuf + total_out
+            inbuf = baseinbuf + data_processed
+            inlen = min(self._MAX_CHUNK_SIZE, total_data_len - data_processed)
+
+            res = self._backend._lib.EVP_CipherUpdate(
+                self._ctx, outbuf, outlen, inbuf, inlen
+            )
+            self._backend.openssl_assert(res != 0)
+            data_processed += inlen
+            total_out += outlen[0]
+
+        return total_out
 
     def finalize(self):
-        # OpenSSL 1.0.1 on Ubuntu 12.04 (and possibly other distributions)
-        # appears to have a bug where you must make at least one call to update
-        # even if you are only using authenticate_additional_data or the
-        # GCM tag will be wrong. An (empty) call to update resolves this
-        # and is harmless for all other versions of OpenSSL.
-        if isinstance(self._mode, modes.GCM):
-            self.update(b"")
-
         if (
-            self._operation == self._DECRYPT and
-            isinstance(self._mode, modes.ModeWithAuthenticationTag) and
-            self.tag is None
+            self._operation == self._DECRYPT
+            and isinstance(self._mode, modes.ModeWithAuthenticationTag)
+            and self.tag is None
         ):
             raise ValueError(
                 "Authentication tag must be provided when decrypting."
@@ -172,47 +174,44 @@
             self._backend.openssl_assert(
                 errors[0]._lib_reason_match(
                     self._backend._lib.ERR_LIB_EVP,
-                    self._backend._lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH
-                )
+                    self._backend._lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH,
+                ),
+                errors=errors,
             )
             raise ValueError(
                 "The length of the provided data is not a multiple of "
                 "the block length."
             )
 
-        if (isinstance(self._mode, modes.GCM) and
-           self._operation == self._ENCRYPT):
+        if (
+            isinstance(self._mode, modes.GCM)
+            and self._operation == self._ENCRYPT
+        ):
             tag_buf = self._backend._ffi.new(
                 "unsigned char[]", self._block_size_bytes
             )
             res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
-                self._ctx, self._backend._lib.EVP_CTRL_AEAD_GET_TAG,
-                self._block_size_bytes, tag_buf
+                self._ctx,
+                self._backend._lib.EVP_CTRL_AEAD_GET_TAG,
+                self._block_size_bytes,
+                tag_buf,
             )
             self._backend.openssl_assert(res != 0)
             self._tag = self._backend._ffi.buffer(tag_buf)[:]
 
         res = self._backend._lib.EVP_CIPHER_CTX_cleanup(self._ctx)
         self._backend.openssl_assert(res == 1)
-        return self._backend._ffi.buffer(buf)[:outlen[0]]
+        return self._backend._ffi.buffer(buf)[: outlen[0]]
 
     def finalize_with_tag(self, tag):
-        if (
-            self._backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and
-            not self._backend._lib.CRYPTOGRAPHY_IS_LIBRESSL
-        ):
-            raise NotImplementedError(
-                "finalize_with_tag requires OpenSSL >= 1.0.2. To use this "
-                "method please update OpenSSL"
-            )
         if len(tag) < self._mode._min_tag_length:
             raise ValueError(
-                "Authentication tag must be {0} bytes or longer.".format(
-                    self._mode._min_tag_length)
+                "Authentication tag must be {} bytes or longer.".format(
+                    self._mode._min_tag_length
+                )
             )
         res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
-            self._ctx, self._backend._lib.EVP_CTRL_AEAD_SET_TAG,
-            len(tag), tag
+            self._ctx, self._backend._lib.EVP_CTRL_AEAD_SET_TAG, len(tag), tag
         )
         self._backend.openssl_assert(res != 0)
         self._tag = tag
@@ -221,8 +220,11 @@
     def authenticate_additional_data(self, data):
         outlen = self._backend._ffi.new("int *")
         res = self._backend._lib.EVP_CipherUpdate(
-            self._ctx, self._backend._ffi.NULL, outlen,
-            self._backend._ffi.from_buffer(data), len(data)
+            self._ctx,
+            self._backend._ffi.NULL,
+            outlen,
+            self._backend._ffi.from_buffer(data),
+            len(data),
         )
         self._backend.openssl_assert(res != 0)
 
diff --git a/src/cryptography/hazmat/backends/openssl/cmac.py b/src/cryptography/hazmat/backends/openssl/cmac.py
index bc88f33..195fc23 100644
--- a/src/cryptography/hazmat/backends/openssl/cmac.py
+++ b/src/cryptography/hazmat/backends/openssl/cmac.py
@@ -7,18 +7,21 @@
 
 from cryptography import utils
 from cryptography.exceptions import (
-    InvalidSignature, UnsupportedAlgorithm, _Reasons
+    InvalidSignature,
+    UnsupportedAlgorithm,
+    _Reasons,
 )
-from cryptography.hazmat.primitives import constant_time, mac
+from cryptography.hazmat.primitives import constant_time
 from cryptography.hazmat.primitives.ciphers.modes import CBC
 
 
-@utils.register_interface(mac.MACContext)
 class _CMACContext(object):
     def __init__(self, backend, algorithm, ctx=None):
         if not backend.cmac_algorithm_supported(algorithm):
-            raise UnsupportedAlgorithm("This backend does not support CMAC.",
-                                       _Reasons.UNSUPPORTED_CIPHER)
+            raise UnsupportedAlgorithm(
+                "This backend does not support CMAC.",
+                _Reasons.UNSUPPORTED_CIPHER,
+            )
 
         self._backend = backend
         self._key = algorithm.key
@@ -38,8 +41,11 @@
 
             key_ptr = self._backend._ffi.from_buffer(self._key)
             res = self._backend._lib.CMAC_Init(
-                ctx, key_ptr, len(self._key),
-                evp_cipher, self._backend._ffi.NULL
+                ctx,
+                key_ptr,
+                len(self._key),
+                evp_cipher,
+                self._backend._ffi.NULL,
             )
             self._backend.openssl_assert(res == 1)
 
@@ -54,9 +60,7 @@
     def finalize(self):
         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
-        )
+        res = self._backend._lib.CMAC_Final(self._ctx, buf, length)
         self._backend.openssl_assert(res == 1)
 
         self._ctx = None
@@ -68,13 +72,9 @@
         copied_ctx = self._backend._ffi.gc(
             copied_ctx, self._backend._lib.CMAC_CTX_free
         )
-        res = self._backend._lib.CMAC_CTX_copy(
-            copied_ctx, self._ctx
-        )
+        res = self._backend._lib.CMAC_CTX_copy(copied_ctx, self._ctx)
         self._backend.openssl_assert(res == 1)
-        return _CMACContext(
-            self._backend, self._algorithm, ctx=copied_ctx
-        )
+        return _CMACContext(self._backend, self._algorithm, ctx=copied_ctx)
 
     def verify(self, signature):
         digest = self.finalize()
diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py
index 007675d..cc9b8c0 100644
--- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py
+++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py
@@ -7,23 +7,20 @@
 import datetime
 import ipaddress
 
-import asn1crypto.core
-
 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
 from cryptography.x509.name import _ASN1_TYPE_TO_ENUM
 from cryptography.x509.oid import (
-    CRLEntryExtensionOID, CertificatePoliciesOID, ExtensionOID,
+    CRLEntryExtensionOID,
+    CertificatePoliciesOID,
+    ExtensionOID,
     OCSPExtensionOID,
 )
 
 
-class _Integers(asn1crypto.core.SequenceOf):
-    _child_spec = asn1crypto.core.Integer
-
-
 def _obj2txt(backend, obj):
     # Set to 80 on the recommendation of
     # https://www.openssl.org/docs/crypto/OBJ_nid2ln.html#return_values
@@ -67,9 +64,9 @@
     for x in range(count):
         entry = backend._lib.X509_NAME_get_entry(x509_name, x)
         attribute = _decode_x509_name_entry(backend, entry)
-        set_id = backend._lib.Cryptography_X509_NAME_ENTRY_set(entry)
+        set_id = backend._lib.X509_NAME_ENTRY_set(entry)
         if set_id != prev_set_id:
-            attributes.append(set([attribute]))
+            attributes.append({attribute})
         else:
             # is in the same RDN a previous entry
             attributes[-1].add(attribute)
@@ -124,10 +121,10 @@
             # 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:])
+            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')
+            prefix = bits.find("0")
             # If no 0 bits are found it is a /32 or /128
             if prefix == -1:
                 prefix = len(bits)
@@ -135,7 +132,7 @@
             if "1" in bits[prefix:]:
                 raise ValueError("Invalid netmask")
 
-            ip = ipaddress.ip_network(base.exploded + u"/{0}".format(prefix))
+            ip = ipaddress.ip_network(base.exploded + u"/{}".format(prefix))
         else:
             ip = ipaddress.ip_address(data)
 
@@ -160,10 +157,10 @@
     else:
         # x400Address or ediPartyName
         raise x509.UnsupportedGeneralNameType(
-            "{0} is not a supported type".format(
+            "{} is not a supported type".format(
                 x509._GENERAL_NAMES.get(gn.type, gn.type)
             ),
-            gn.type
+            gn.type,
         )
 
 
@@ -184,48 +181,57 @@
 
 
 class _X509ExtensionParser(object):
-    def __init__(self, ext_count, get_ext, handlers):
+    def __init__(self, backend, ext_count, get_ext, handlers):
         self.ext_count = ext_count
         self.get_ext = get_ext
         self.handlers = handlers
+        self._backend = backend
 
-    def parse(self, backend, x509_obj):
+    def parse(self, x509_obj):
         extensions = []
         seen_oids = set()
-        for i in range(self.ext_count(backend, x509_obj)):
-            ext = self.get_ext(backend, x509_obj, i)
-            backend.openssl_assert(ext != backend._ffi.NULL)
-            crit = backend._lib.X509_EXTENSION_get_critical(ext)
+        for i in range(self.ext_count(x509_obj)):
+            ext = self.get_ext(x509_obj, i)
+            self._backend.openssl_assert(ext != self._backend._ffi.NULL)
+            crit = self._backend._lib.X509_EXTENSION_get_critical(ext)
             critical = crit == 1
             oid = x509.ObjectIdentifier(
-                _obj2txt(backend, backend._lib.X509_EXTENSION_get_object(ext))
+                _obj2txt(
+                    self._backend,
+                    self._backend._lib.X509_EXTENSION_get_object(ext),
+                )
             )
             if oid in seen_oids:
                 raise x509.DuplicateExtension(
-                    "Duplicate {0} extension found".format(oid), oid
+                    "Duplicate {} extension found".format(oid), oid
                 )
 
             # 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:
-                data = backend._lib.X509_EXTENSION_get_data(ext)
-                parsed = _Integers.load(_asn1_string_to_bytes(backend, data))
+                # 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.native] for x in parsed]
+                    [_TLS_FEATURE_TYPE_TO_ENUM[x] for x in parsed]
                 )
                 extensions.append(x509.Extension(oid, critical, value))
                 seen_oids.add(oid)
                 continue
             elif oid == ExtensionOID.PRECERT_POISON:
-                data = backend._lib.X509_EXTENSION_get_data(ext)
-                parsed = asn1crypto.core.Null.load(
-                    _asn1_string_to_bytes(backend, data)
+                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())
                 )
-                assert parsed == asn1crypto.core.Null()
-                extensions.append(x509.Extension(
-                    oid, critical, x509.PrecertPoison()
-                ))
                 seen_oids.add(oid)
                 continue
 
@@ -233,23 +239,21 @@
                 handler = self.handlers[oid]
             except KeyError:
                 # Dump the DER payload into an UnrecognizedExtension object
-                data = backend._lib.X509_EXTENSION_get_data(ext)
-                backend.openssl_assert(data != backend._ffi.NULL)
-                der = backend._ffi.buffer(data.data, data.length)[:]
+                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)
-                )
+                extensions.append(x509.Extension(oid, critical, unrecognized))
             else:
-                ext_data = backend._lib.X509V3_EXT_d2i(ext)
-                if ext_data == backend._ffi.NULL:
-                    backend._consume_errors()
+                ext_data = self._backend._lib.X509V3_EXT_d2i(ext)
+                if ext_data == self._backend._ffi.NULL:
+                    self._backend._consume_errors()
                     raise ValueError(
-                        "The {0} extension is invalid and can't be "
+                        "The {} extension is invalid and can't be "
                         "parsed".format(oid)
                     )
 
-                value = handler(backend, ext_data)
+                value = handler(self._backend, ext_data)
                 extensions.append(x509.Extension(oid, critical, value))
 
             seen_oids.add(oid)
@@ -271,16 +275,12 @@
             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)
-                )
+                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')
+                    )[:].decode("ascii")
                     qualifiers.append(cpsuri)
                 else:
                     assert pqualid == CertificatePoliciesOID.CPS_USER_NOTICE
@@ -289,9 +289,7 @@
                     )
                     qualifiers.append(user_notice)
 
-        certificate_policies.append(
-            x509.PolicyInformation(oid, qualifiers)
-        )
+        certificate_policies.append(x509.PolicyInformation(oid, qualifiers))
 
     return x509.CertificatePolicies(certificate_policies)
 
@@ -304,13 +302,9 @@
         explicit_text = _asn1_string_to_utf8(backend, un.exptext)
 
     if un.noticeref != backend._ffi.NULL:
-        organization = _asn1_string_to_utf8(
-            backend, un.noticeref.organization
-        )
+        organization = _asn1_string_to_utf8(backend, un.noticeref.organization)
 
-        num = backend._lib.sk_ASN1_INTEGER_num(
-            un.noticeref.noticenos
-        )
+        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(
@@ -319,9 +313,7 @@
             notice_num = _asn1_integer_to_int(backend, asn1_int)
             notice_numbers.append(notice_num)
 
-        notice_reference = x509.NoticeReference(
-            organization, notice_numbers
-        )
+        notice_reference = x509.NoticeReference(organization, notice_numbers)
 
     return x509.UserNotice(notice_reference, explicit_text)
 
@@ -364,9 +356,7 @@
         )[:]
 
     if akid.issuer != backend._ffi.NULL:
-        authority_cert_issuer = _decode_general_names(
-            backend, akid.issuer
-        )
+        authority_cert_issuer = _decode_general_names(backend, akid.issuer)
 
     authority_cert_serial_number = _asn1_integer_to_int_or_none(
         backend, akid.serial
@@ -377,22 +367,40 @@
     )
 
 
-def _decode_authority_information_access(backend, aia):
-    aia = backend._ffi.cast("Cryptography_STACK_OF_ACCESS_DESCRIPTION *", aia)
-    aia = backend._ffi.gc(aia, backend._lib.sk_ACCESS_DESCRIPTION_free)
-    num = backend._lib.sk_ACCESS_DESCRIPTION_num(aia)
+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(aia, i)
+        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_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)
@@ -415,7 +423,7 @@
         key_cert_sign,
         crl_sign,
         encipher_only,
-        decipher_only
+        decipher_only,
     )
 
 
@@ -483,8 +491,13 @@
         only_some_reasons = None
 
     return x509.IssuingDistributionPoint(
-        full_name, relative_name, only_user, only_ca, only_some_reasons,
-        indirect_crl, only_attr
+        full_name,
+        relative_name,
+        only_user,
+        only_ca,
+        only_some_reasons,
+        indirect_crl,
+        only_attr,
     )
 
 
@@ -605,13 +618,9 @@
     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
-        )
+        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)
-        )
+        attributes.add(_decode_x509_name_entry(backend, rn))
 
     relative_name = x509.RelativeDistinguishedName(attributes)
 
@@ -635,10 +644,11 @@
     return x509.InhibitAnyPolicy(skip_certs)
 
 
-def _decode_precert_signed_certificate_timestamps(backend, asn1_scts):
+def _decode_scts(backend, asn1_scts):
     from cryptography.hazmat.backends.openssl.x509 import (
-        _SignedCertificateTimestamp
+        _SignedCertificateTimestamp,
     )
+
     asn1_scts = backend._ffi.cast("Cryptography_STACK_OF_SCT *", asn1_scts)
     asn1_scts = backend._ffi.gc(asn1_scts, backend._lib.SCT_LIST_free)
 
@@ -647,7 +657,17 @@
         sct = backend._lib.sk_SCT_value(asn1_scts, i)
 
         scts.append(_SignedCertificateTimestamp(backend, asn1_scts, sct))
-    return x509.PrecertificateSignedCertificateTimestamps(scts)
+    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 {
@@ -686,7 +706,7 @@
     x509.ReasonFlags.certificate_hold: 6,
     x509.ReasonFlags.remove_from_crl: 8,
     x509.ReasonFlags.privilege_withdrawn: 9,
-    x509.ReasonFlags.aa_compromise: 10
+    x509.ReasonFlags.aa_compromise: 10,
 }
 
 
@@ -698,13 +718,11 @@
     try:
         return x509.CRLReason(_CRL_ENTRY_REASON_CODE_TO_ENUM[code])
     except KeyError:
-        raise ValueError("Unsupported reason code: {0}".format(code))
+        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.cast("ASN1_GENERALIZEDTIME *", inv_date)
     generalized_time = backend._ffi.gc(
         generalized_time, backend._lib.ASN1_GENERALIZEDTIME_free
     )
@@ -758,14 +776,14 @@
     res = backend._lib.ASN1_STRING_to_UTF8(buf, asn1_string)
     if res == -1:
         raise ValueError(
-            "Unsupported ASN1 string type. Type: {0}".format(asn1_string.type)
+            "Unsupported ASN1 string type. Type: {}".format(asn1_string.type)
         )
 
     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)[:].decode('utf8')
+    return backend._ffi.buffer(buf[0], res)[:].decode("utf8")
 
 
 def _parse_asn1_time(backend, asn1_time):
@@ -799,7 +817,7 @@
     return x509.OCSPNonce(_asn1_string_to_bytes(backend, nonce))
 
 
-_EXTENSION_HANDLERS_NO_SCT = {
+_EXTENSION_HANDLERS_BASE = {
     ExtensionOID.BASIC_CONSTRAINTS: _decode_basic_constraints,
     ExtensionOID.SUBJECT_KEY_IDENTIFIER: _decode_subject_key_identifier,
     ExtensionOID.KEY_USAGE: _decode_key_usage,
@@ -809,6 +827,9 @@
     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,
@@ -818,11 +839,11 @@
     ExtensionOID.NAME_CONSTRAINTS: _decode_name_constraints,
     ExtensionOID.POLICY_CONSTRAINTS: _decode_policy_constraints,
 }
-_EXTENSION_HANDLERS = _EXTENSION_HANDLERS_NO_SCT.copy()
-_EXTENSION_HANDLERS[
-    ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS
-] = _decode_precert_signed_certificate_timestamps
-
+_EXTENSION_HANDLERS_SCT = {
+    ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: (
+        _decode_precert_signed_certificate_timestamps
+    )
+}
 
 _REVOKED_EXTENSION_HANDLERS = {
     CRLEntryExtensionOID.CRL_REASON: _decode_crl_reason,
@@ -839,6 +860,7 @@
         _decode_authority_information_access
     ),
     ExtensionOID.ISSUING_DISTRIBUTION_POINT: _decode_issuing_dist_point,
+    ExtensionOID.FRESHEST_CRL: _decode_freshest_crl,
 }
 
 _OCSP_REQ_EXTENSION_HANDLERS = {
@@ -849,44 +871,8 @@
     OCSPExtensionOID.NONCE: _decode_nonce,
 }
 
-_CERTIFICATE_EXTENSION_PARSER_NO_SCT = _X509ExtensionParser(
-    ext_count=lambda backend, x: backend._lib.X509_get_ext_count(x),
-    get_ext=lambda backend, x, i: backend._lib.X509_get_ext(x, i),
-    handlers=_EXTENSION_HANDLERS_NO_SCT
-)
-
-_CERTIFICATE_EXTENSION_PARSER = _X509ExtensionParser(
-    ext_count=lambda backend, x: backend._lib.X509_get_ext_count(x),
-    get_ext=lambda backend, x, i: backend._lib.X509_get_ext(x, i),
-    handlers=_EXTENSION_HANDLERS
-)
-
-_CSR_EXTENSION_PARSER = _X509ExtensionParser(
-    ext_count=lambda backend, x: backend._lib.sk_X509_EXTENSION_num(x),
-    get_ext=lambda backend, x, i: backend._lib.sk_X509_EXTENSION_value(x, i),
-    handlers=_EXTENSION_HANDLERS
-)
-
-_REVOKED_CERTIFICATE_EXTENSION_PARSER = _X509ExtensionParser(
-    ext_count=lambda backend, x: backend._lib.X509_REVOKED_get_ext_count(x),
-    get_ext=lambda backend, x, i: backend._lib.X509_REVOKED_get_ext(x, i),
-    handlers=_REVOKED_EXTENSION_HANDLERS,
-)
-
-_CRL_EXTENSION_PARSER = _X509ExtensionParser(
-    ext_count=lambda backend, x: backend._lib.X509_CRL_get_ext_count(x),
-    get_ext=lambda backend, x, i: backend._lib.X509_CRL_get_ext(x, i),
-    handlers=_CRL_EXTENSION_HANDLERS,
-)
-
-_OCSP_REQ_EXT_PARSER = _X509ExtensionParser(
-    ext_count=lambda backend, x: backend._lib.OCSP_REQUEST_get_ext_count(x),
-    get_ext=lambda backend, x, i: backend._lib.OCSP_REQUEST_get_ext(x, i),
-    handlers=_OCSP_REQ_EXTENSION_HANDLERS,
-)
-
-_OCSP_BASICRESP_EXT_PARSER = _X509ExtensionParser(
-    ext_count=lambda backend, x: backend._lib.OCSP_BASICRESP_get_ext_count(x),
-    get_ext=lambda backend, x, i: backend._lib.OCSP_BASICRESP_get_ext(x, i),
-    handlers=_OCSP_BASICRESP_EXTENSION_HANDLERS,
-)
+_OCSP_SINGLERESP_EXTENSION_HANDLERS_SCT = {
+    ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS: (
+        _decode_signed_certificate_timestamps
+    )
+}
diff --git a/src/cryptography/hazmat/backends/openssl/dh.py b/src/cryptography/hazmat/backends/openssl/dh.py
index 095f062..2862676 100644
--- a/src/cryptography/hazmat/backends/openssl/dh.py
+++ b/src/cryptography/hazmat/backends/openssl/dh.py
@@ -17,8 +17,8 @@
     param_cdata = lib.DHparams_dup(dh_cdata)
     backend.openssl_assert(param_cdata != ffi.NULL)
     param_cdata = ffi.gc(param_cdata, lib.DH_free)
-    if lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102:
-        # In OpenSSL versions < 1.0.2 or libressl DHparams_dup don't copy q
+    if lib.CRYPTOGRAPHY_IS_LIBRESSL:
+        # In libressl DHparams_dup don't copy q
         q = ffi.new("BIGNUM **")
         lib.DH_get0_pqg(dh_cdata, ffi.NULL, q, ffi.NULL)
         q_dup = lib.BN_dup(q[0])
@@ -53,7 +53,7 @@
         return dh.DHParameterNumbers(
             p=self._backend._bn_to_int(p[0]),
             g=self._backend._bn_to_int(g[0]),
-            q=q_val
+            q=q_val,
         )
 
     def generate_private_key(self):
@@ -61,44 +61,27 @@
 
     def parameter_bytes(self, encoding, format):
         if format is not serialization.ParameterFormat.PKCS3:
-            raise ValueError(
-                "Only PKCS3 serialization is supported"
-            )
+            raise ValueError("Only PKCS3 serialization is supported")
         if not self._backend._lib.Cryptography_HAS_EVP_PKEY_DHX:
             q = self._backend._ffi.new("BIGNUM **")
-            self._backend._lib.DH_get0_pqg(self._dh_cdata,
-                                           self._backend._ffi.NULL,
-                                           q,
-                                           self._backend._ffi.NULL)
+            self._backend._lib.DH_get0_pqg(
+                self._dh_cdata,
+                self._backend._ffi.NULL,
+                q,
+                self._backend._ffi.NULL,
+            )
             if q[0] != self._backend._ffi.NULL:
                 raise UnsupportedAlgorithm(
                     "DH X9.42 serialization is not supported",
-                    _Reasons.UNSUPPORTED_SERIALIZATION)
+                    _Reasons.UNSUPPORTED_SERIALIZATION,
+                )
 
-        return self._backend._parameter_bytes(
-            encoding,
-            format,
-            self._dh_cdata
-        )
-
-
-def _handle_dh_compute_key_error(errors, backend):
-    lib = backend._lib
-
-    backend.openssl_assert(
-        errors[0]._lib_reason_match(
-            lib.ERR_LIB_DH, lib.DH_R_INVALID_PUBKEY
-        )
-    )
-
-    raise ValueError("Public key value is invalid for this exchange.")
+        return self._backend._parameter_bytes(encoding, format, self._dh_cdata)
 
 
 def _get_dh_num_bits(backend, dh_cdata):
     p = backend._ffi.new("BIGNUM **")
-    backend._lib.DH_get0_pqg(dh_cdata, p,
-                             backend._ffi.NULL,
-                             backend._ffi.NULL)
+    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])
 
@@ -136,29 +119,32 @@
                 parameter_numbers=dh.DHParameterNumbers(
                     p=self._backend._bn_to_int(p[0]),
                     g=self._backend._bn_to_int(g[0]),
-                    q=q_val
+                    q=q_val,
                 ),
-                y=self._backend._bn_to_int(pub_key[0])
+                y=self._backend._bn_to_int(pub_key[0]),
             ),
-            x=self._backend._bn_to_int(priv_key[0])
+            x=self._backend._bn_to_int(priv_key[0]),
         )
 
     def exchange(self, peer_public_key):
 
         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)
+        self._backend._lib.DH_get0_key(
+            peer_public_key._dh_cdata, pub_key, 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
+            buf, pub_key[0], self._dh_cdata
         )
 
         if res == -1:
-            errors = self._backend._consume_errors()
-            return _handle_dh_compute_key_error(errors, self._backend)
+            errors_with_text = self._backend._consume_errors_with_text()
+            raise ValueError(
+                "Error computing shared key. Public key is likely invalid "
+                "for this exchange.",
+                errors_with_text,
+            )
         else:
             self._backend.openssl_assert(res >= 1)
 
@@ -173,15 +159,16 @@
     def public_key(self):
         dh_cdata = _dh_params_dup(self._dh_cdata, self._backend)
         pub_key = self._backend._ffi.new("BIGNUM **")
-        self._backend._lib.DH_get0_key(self._dh_cdata,
-                                       pub_key, self._backend._ffi.NULL)
+        self._backend._lib.DH_get0_key(
+            self._dh_cdata, pub_key, self._backend._ffi.NULL
+        )
         self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL)
         pub_key_dup = self._backend._lib.BN_dup(pub_key[0])
         self._backend.openssl_assert(pub_key_dup != self._backend._ffi.NULL)
 
-        res = self._backend._lib.DH_set0_key(dh_cdata,
-                                             pub_key_dup,
-                                             self._backend._ffi.NULL)
+        res = self._backend._lib.DH_set0_key(
+            dh_cdata, pub_key_dup, self._backend._ffi.NULL
+        )
         self._backend.openssl_assert(res == 1)
         evp_pkey = self._backend._dh_cdata_to_evp_pkey(dh_cdata)
         return _DHPublicKey(self._backend, dh_cdata, evp_pkey)
@@ -196,21 +183,25 @@
             )
         if not self._backend._lib.Cryptography_HAS_EVP_PKEY_DHX:
             q = self._backend._ffi.new("BIGNUM **")
-            self._backend._lib.DH_get0_pqg(self._dh_cdata,
-                                           self._backend._ffi.NULL,
-                                           q,
-                                           self._backend._ffi.NULL)
+            self._backend._lib.DH_get0_pqg(
+                self._dh_cdata,
+                self._backend._ffi.NULL,
+                q,
+                self._backend._ffi.NULL,
+            )
             if q[0] != self._backend._ffi.NULL:
                 raise UnsupportedAlgorithm(
                     "DH X9.42 serialization is not supported",
-                    _Reasons.UNSUPPORTED_SERIALIZATION)
+                    _Reasons.UNSUPPORTED_SERIALIZATION,
+                )
 
         return self._backend._private_key_bytes(
             encoding,
             format,
             encryption_algorithm,
+            self,
             self._evp_pkey,
-            self._dh_cdata
+            self._dh_cdata,
         )
 
 
@@ -238,16 +229,17 @@
         else:
             q_val = self._backend._bn_to_int(q[0])
         pub_key = self._backend._ffi.new("BIGNUM **")
-        self._backend._lib.DH_get0_key(self._dh_cdata,
-                                       pub_key, self._backend._ffi.NULL)
+        self._backend._lib.DH_get0_key(
+            self._dh_cdata, pub_key, self._backend._ffi.NULL
+        )
         self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL)
         return dh.DHPublicNumbers(
             parameter_numbers=dh.DHParameterNumbers(
                 p=self._backend._bn_to_int(p[0]),
                 g=self._backend._bn_to_int(g[0]),
-                q=q_val
+                q=q_val,
             ),
-            y=self._backend._bn_to_int(pub_key[0])
+            y=self._backend._bn_to_int(pub_key[0]),
         )
 
     def parameters(self):
@@ -262,19 +254,18 @@
 
         if not self._backend._lib.Cryptography_HAS_EVP_PKEY_DHX:
             q = self._backend._ffi.new("BIGNUM **")
-            self._backend._lib.DH_get0_pqg(self._dh_cdata,
-                                           self._backend._ffi.NULL,
-                                           q,
-                                           self._backend._ffi.NULL)
+            self._backend._lib.DH_get0_pqg(
+                self._dh_cdata,
+                self._backend._ffi.NULL,
+                q,
+                self._backend._ffi.NULL,
+            )
             if q[0] != self._backend._ffi.NULL:
                 raise UnsupportedAlgorithm(
                     "DH X9.42 serialization is not supported",
-                    _Reasons.UNSUPPORTED_SERIALIZATION)
+                    _Reasons.UNSUPPORTED_SERIALIZATION,
+                )
 
         return self._backend._public_key_bytes(
-            encoding,
-            format,
-            self,
-            self._evp_pkey,
-            None
+            encoding, format, self, self._evp_pkey, None
         )
diff --git a/src/cryptography/hazmat/backends/openssl/dsa.py b/src/cryptography/hazmat/backends/openssl/dsa.py
index de61f08..0c5faba 100644
--- a/src/cryptography/hazmat/backends/openssl/dsa.py
+++ b/src/cryptography/hazmat/backends/openssl/dsa.py
@@ -7,12 +7,15 @@
 from cryptography import utils
 from cryptography.exceptions import InvalidSignature
 from cryptography.hazmat.backends.openssl.utils import (
-    _calculate_digest_and_algorithm, _check_not_prehashed,
-    _warn_sign_verify_deprecated
+    _calculate_digest_and_algorithm,
+    _check_not_prehashed,
+    _warn_sign_verify_deprecated,
 )
-from cryptography.hazmat.primitives import hashes, serialization
+from cryptography.hazmat.primitives import hashes
 from cryptography.hazmat.primitives.asymmetric import (
-    AsymmetricSignatureContext, AsymmetricVerificationContext, dsa
+    AsymmetricSignatureContext,
+    AsymmetricVerificationContext,
+    dsa,
 )
 
 
@@ -29,7 +32,7 @@
     backend.openssl_assert(res == 1)
     backend.openssl_assert(buflen[0])
 
-    return backend._ffi.buffer(sig_buf)[:buflen[0]]
+    return backend._ffi.buffer(sig_buf)[: buflen[0]]
 
 
 def _dsa_sig_verify(backend, public_key, signature, data):
@@ -98,7 +101,7 @@
         return dsa.DSAParameterNumbers(
             p=self._backend._bn_to_int(p[0]),
             q=self._backend._bn_to_int(q[0]),
-            g=self._backend._bn_to_int(g[0])
+            g=self._backend._bn_to_int(g[0]),
         )
 
     def generate_private_key(self):
@@ -144,11 +147,11 @@
                 parameter_numbers=dsa.DSAParameterNumbers(
                     p=self._backend._bn_to_int(p[0]),
                     q=self._backend._bn_to_int(q[0]),
-                    g=self._backend._bn_to_int(g[0])
+                    g=self._backend._bn_to_int(g[0]),
                 ),
-                y=self._backend._bn_to_int(pub_key[0])
+                y=self._backend._bn_to_int(pub_key[0]),
             ),
-            x=self._backend._bn_to_int(priv_key[0])
+            x=self._backend._bn_to_int(priv_key[0]),
         )
 
     def public_key(self):
@@ -183,8 +186,9 @@
             encoding,
             format,
             encryption_algorithm,
+            self,
             self._evp_pkey,
-            self._dsa_cdata
+            self._dsa_cdata,
         )
 
     def sign(self, data, algorithm):
@@ -235,9 +239,9 @@
             parameter_numbers=dsa.DSAParameterNumbers(
                 p=self._backend._bn_to_int(p[0]),
                 q=self._backend._bn_to_int(q[0]),
-                g=self._backend._bn_to_int(g[0])
+                g=self._backend._bn_to_int(g[0]),
             ),
-            y=self._backend._bn_to_int(pub_key[0])
+            y=self._backend._bn_to_int(pub_key[0]),
         )
 
     def parameters(self):
@@ -248,17 +252,8 @@
         return _DSAParameters(self._backend, dsa_cdata)
 
     def public_bytes(self, encoding, format):
-        if format is serialization.PublicFormat.PKCS1:
-            raise ValueError(
-                "DSA public keys do not support PKCS1 serialization"
-            )
-
         return self._backend._public_key_bytes(
-            encoding,
-            format,
-            self,
-            self._evp_pkey,
-            None
+            encoding, format, self, self._evp_pkey, None
         )
 
     def verify(self, signature, data, algorithm):
diff --git a/src/cryptography/hazmat/backends/openssl/ec.py b/src/cryptography/hazmat/backends/openssl/ec.py
index a8d69bd..05d32ba 100644
--- a/src/cryptography/hazmat/backends/openssl/ec.py
+++ b/src/cryptography/hazmat/backends/openssl/ec.py
@@ -6,15 +6,20 @@
 
 from cryptography import utils
 from cryptography.exceptions import (
-    InvalidSignature, UnsupportedAlgorithm, _Reasons
+    InvalidSignature,
+    UnsupportedAlgorithm,
+    _Reasons,
 )
 from cryptography.hazmat.backends.openssl.utils import (
-    _calculate_digest_and_algorithm, _check_not_prehashed,
-    _warn_sign_verify_deprecated
+    _calculate_digest_and_algorithm,
+    _check_not_prehashed,
+    _warn_sign_verify_deprecated,
 )
 from cryptography.hazmat.primitives import hashes, serialization
 from cryptography.hazmat.primitives.asymmetric import (
-    AsymmetricSignatureContext, AsymmetricVerificationContext, ec
+    AsymmetricSignatureContext,
+    AsymmetricVerificationContext,
+    ec,
 )
 
 
@@ -22,7 +27,8 @@
     if not isinstance(signature_algorithm, ec.ECDSA):
         raise UnsupportedAlgorithm(
             "Unsupported elliptic curve signature algorithm.",
-            _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
+            _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
+        )
 
 
 def _ec_key_curve_sn(backend, ec_key):
@@ -34,14 +40,24 @@
     # an error for now.
     if nid == backend._lib.NID_undef:
         raise NotImplementedError(
-            "ECDSA certificates with unnamed curves are unsupported "
-            "at this time"
+            "ECDSA keys with unnamed curves are unsupported at this time"
+        )
+
+    # This is like the above check, but it also catches the case where you
+    # explicitly encoded a curve with the same parameters as a named curve.
+    # Don't do that.
+    if (
+        not backend._lib.CRYPTOGRAPHY_IS_LIBRESSL
+        and backend._lib.EC_GROUP_get_asn1_flag(group) == 0
+    ):
+        raise NotImplementedError(
+            "ECDSA keys with unnamed curves are unsupported at this time"
         )
 
     curve_name = backend._lib.OBJ_nid2sn(nid)
     backend.openssl_assert(curve_name != backend._ffi.NULL)
 
-    sn = backend._ffi.string(curve_name).decode('ascii')
+    sn = backend._ffi.string(curve_name).decode("ascii")
     return sn
 
 
@@ -62,8 +78,8 @@
         return ec._CURVE_TYPES[sn]()
     except KeyError:
         raise UnsupportedAlgorithm(
-            "{0} is not a supported elliptic curve".format(sn),
-            _Reasons.UNSUPPORTED_ELLIPTIC_CURVE
+            "{} is not a supported elliptic curve".format(sn),
+            _Reasons.UNSUPPORTED_ELLIPTIC_CURVE,
         )
 
 
@@ -77,7 +93,7 @@
         0, data, len(data), sigbuf, siglen_ptr, private_key._ec_key
     )
     backend.openssl_assert(res == 1)
-    return backend._ffi.buffer(sigbuf)[:siglen_ptr[0]]
+    return backend._ffi.buffer(sigbuf)[: siglen_ptr[0]]
 
 
 def _ecdsa_sig_verify(backend, public_key, signature, data):
@@ -127,12 +143,12 @@
 class _EllipticCurvePrivateKey(object):
     def __init__(self, backend, ec_key_cdata, evp_pkey):
         self._backend = backend
-        _mark_asn1_named_ec_curve(backend, ec_key_cdata)
         self._ec_key = ec_key_cdata
         self._evp_pkey = evp_pkey
 
         sn = _ec_key_curve_sn(backend, ec_key_cdata)
         self._curve = _sn_to_elliptic_curve(backend, sn)
+        _mark_asn1_named_ec_curve(backend, ec_key_cdata)
 
     curve = utils.read_only_property("_curve")
 
@@ -156,7 +172,7 @@
         ):
             raise UnsupportedAlgorithm(
                 "This backend does not support the ECDH algorithm.",
-                _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM
+                _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
             )
 
         if peer_public_key.curve.name != self.curve.name:
@@ -183,12 +199,7 @@
         self._backend.openssl_assert(group != self._backend._ffi.NULL)
 
         curve_nid = self._backend._lib.EC_GROUP_get_curve_name(group)
-
-        public_ec_key = self._backend._lib.EC_KEY_new_by_curve_name(curve_nid)
-        self._backend.openssl_assert(public_ec_key != self._backend._ffi.NULL)
-        public_ec_key = self._backend._ffi.gc(
-            public_ec_key, self._backend._lib.EC_KEY_free
-        )
+        public_ec_key = self._backend._ec_key_new_by_curve_nid(curve_nid)
 
         point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key)
         self._backend.openssl_assert(point != self._backend._ffi.NULL)
@@ -205,7 +216,7 @@
         private_value = self._backend._bn_to_int(bn)
         return ec.EllipticCurvePrivateNumbers(
             private_value=private_value,
-            public_numbers=self.public_key().public_numbers()
+            public_numbers=self.public_key().public_numbers(),
         )
 
     def private_bytes(self, encoding, format, encryption_algorithm):
@@ -213,8 +224,9 @@
             encoding,
             format,
             encryption_algorithm,
+            self,
             self._evp_pkey,
-            self._ec_key
+            self._ec_key,
         )
 
     def sign(self, data, signature_algorithm):
@@ -229,12 +241,12 @@
 class _EllipticCurvePublicKey(object):
     def __init__(self, backend, ec_key_cdata, evp_pkey):
         self._backend = backend
-        _mark_asn1_named_ec_curve(backend, ec_key_cdata)
         self._ec_key = ec_key_cdata
         self._evp_pkey = evp_pkey
 
         sn = _ec_key_curve_sn(backend, ec_key_cdata)
         self._curve = _sn_to_elliptic_curve(backend, sn)
+        _mark_asn1_named_ec_curve(backend, ec_key_cdata)
 
     curve = utils.read_only_property("_curve")
 
@@ -253,8 +265,8 @@
         )
 
     def public_numbers(self):
-        get_func, group = (
-            self._backend._ec_key_determine_group_get_func(self._ec_key)
+        get_func, group = self._backend._ec_key_determine_group_get_func(
+            self._ec_key
         )
         point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key)
         self._backend.openssl_assert(point != self._backend._ffi.NULL)
@@ -269,11 +281,7 @@
             x = self._backend._bn_to_int(bn_x)
             y = self._backend._bn_to_int(bn_y)
 
-        return ec.EllipticCurvePublicNumbers(
-            x=x,
-            y=y,
-            curve=self._curve
-        )
+        return ec.EllipticCurvePublicNumbers(x=x, y=y, curve=self._curve)
 
     def _encode_point(self, format):
         if format is serialization.PublicFormat.CompressedPoint:
@@ -300,22 +308,15 @@
         return self._backend._ffi.buffer(buf)[:]
 
     def public_bytes(self, encoding, format):
-        if format is serialization.PublicFormat.PKCS1:
-            raise ValueError(
-                "EC public keys do not support PKCS1 serialization"
-            )
 
         if (
-            encoding is serialization.Encoding.X962 or
-            format is serialization.PublicFormat.CompressedPoint or
-            format is serialization.PublicFormat.UncompressedPoint
+            encoding is serialization.Encoding.X962
+            or format is serialization.PublicFormat.CompressedPoint
+            or format is serialization.PublicFormat.UncompressedPoint
         ):
-            if (
-                encoding is not serialization.Encoding.X962 or
-                format not in (
-                    serialization.PublicFormat.CompressedPoint,
-                    serialization.PublicFormat.UncompressedPoint
-                )
+            if encoding is not serialization.Encoding.X962 or format not in (
+                serialization.PublicFormat.CompressedPoint,
+                serialization.PublicFormat.UncompressedPoint,
             ):
                 raise ValueError(
                     "X962 encoding must be used with CompressedPoint or "
@@ -325,11 +326,7 @@
             return self._encode_point(format)
         else:
             return self._backend._public_key_bytes(
-                encoding,
-                format,
-                self,
-                self._evp_pkey,
-                None
+                encoding, format, self, self._evp_pkey, None
             )
 
     def verify(self, signature, data, signature_algorithm):
diff --git a/src/cryptography/hazmat/backends/openssl/ed25519.py b/src/cryptography/hazmat/backends/openssl/ed25519.py
new file mode 100644
index 0000000..13bec3a
--- /dev/null
+++ b/src/cryptography/hazmat/backends/openssl/ed25519.py
@@ -0,0 +1,145 @@
+# 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
+
+from cryptography import exceptions, utils
+from cryptography.hazmat.primitives import serialization
+from cryptography.hazmat.primitives.asymmetric.ed25519 import (
+    Ed25519PrivateKey,
+    Ed25519PublicKey,
+    _ED25519_KEY_SIZE,
+    _ED25519_SIG_SIZE,
+)
+
+
+@utils.register_interface(Ed25519PublicKey)
+class _Ed25519PublicKey(object):
+    def __init__(self, backend, evp_pkey):
+        self._backend = backend
+        self._evp_pkey = evp_pkey
+
+    def public_bytes(self, encoding, format):
+        if (
+            encoding is serialization.Encoding.Raw
+            or format is serialization.PublicFormat.Raw
+        ):
+            if (
+                encoding is not serialization.Encoding.Raw
+                or format is not serialization.PublicFormat.Raw
+            ):
+                raise ValueError(
+                    "When using Raw both encoding and format must be Raw"
+                )
+
+            return self._raw_public_bytes()
+
+        return self._backend._public_key_bytes(
+            encoding, format, self, self._evp_pkey, None
+        )
+
+    def _raw_public_bytes(self):
+        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(
+            self._evp_pkey, buf, buflen
+        )
+        self._backend.openssl_assert(res == 1)
+        self._backend.openssl_assert(buflen[0] == _ED25519_KEY_SIZE)
+        return self._backend._ffi.buffer(buf, _ED25519_KEY_SIZE)[:]
+
+    def verify(self, signature, data):
+        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(
+            evp_md_ctx, self._backend._lib.EVP_MD_CTX_free
+        )
+        res = self._backend._lib.EVP_DigestVerifyInit(
+            evp_md_ctx,
+            self._backend._ffi.NULL,
+            self._backend._ffi.NULL,
+            self._backend._ffi.NULL,
+            self._evp_pkey,
+        )
+        self._backend.openssl_assert(res == 1)
+        res = self._backend._lib.EVP_DigestVerify(
+            evp_md_ctx, signature, len(signature), data, len(data)
+        )
+        if res != 1:
+            self._backend._consume_errors()
+            raise exceptions.InvalidSignature
+
+
+@utils.register_interface(Ed25519PrivateKey)
+class _Ed25519PrivateKey(object):
+    def __init__(self, backend, evp_pkey):
+        self._backend = backend
+        self._evp_pkey = evp_pkey
+
+    def public_key(self):
+        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(
+            self._evp_pkey, buf, buflen
+        )
+        self._backend.openssl_assert(res == 1)
+        self._backend.openssl_assert(buflen[0] == _ED25519_KEY_SIZE)
+        public_bytes = self._backend._ffi.buffer(buf)[:]
+        return self._backend.ed25519_load_public_bytes(public_bytes)
+
+    def sign(self, data):
+        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(
+            evp_md_ctx, self._backend._lib.EVP_MD_CTX_free
+        )
+        res = self._backend._lib.EVP_DigestSignInit(
+            evp_md_ctx,
+            self._backend._ffi.NULL,
+            self._backend._ffi.NULL,
+            self._backend._ffi.NULL,
+            self._evp_pkey,
+        )
+        self._backend.openssl_assert(res == 1)
+        buf = self._backend._ffi.new("unsigned char[]", _ED25519_SIG_SIZE)
+        buflen = self._backend._ffi.new("size_t *", len(buf))
+        res = self._backend._lib.EVP_DigestSign(
+            evp_md_ctx, buf, buflen, data, len(data)
+        )
+        self._backend.openssl_assert(res == 1)
+        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):
+        if (
+            encoding is serialization.Encoding.Raw
+            or format is serialization.PublicFormat.Raw
+        ):
+            if (
+                format is not serialization.PrivateFormat.Raw
+                or encoding is not serialization.Encoding.Raw
+                or not isinstance(
+                    encryption_algorithm, serialization.NoEncryption
+                )
+            ):
+                raise ValueError(
+                    "When using Raw both encoding and format must be Raw "
+                    "and encryption_algorithm must be NoEncryption()"
+                )
+
+            return self._raw_private_bytes()
+
+        return self._backend._private_key_bytes(
+            encoding, format, encryption_algorithm, self, self._evp_pkey, None
+        )
+
+    def _raw_private_bytes(self):
+        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(
+            self._evp_pkey, buf, buflen
+        )
+        self._backend.openssl_assert(res == 1)
+        self._backend.openssl_assert(buflen[0] == _ED25519_KEY_SIZE)
+        return self._backend._ffi.buffer(buf, _ED25519_KEY_SIZE)[:]
diff --git a/src/cryptography/hazmat/backends/openssl/ed448.py b/src/cryptography/hazmat/backends/openssl/ed448.py
new file mode 100644
index 0000000..6512770
--- /dev/null
+++ b/src/cryptography/hazmat/backends/openssl/ed448.py
@@ -0,0 +1,146 @@
+# 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
+
+from cryptography import exceptions, utils
+from cryptography.hazmat.primitives import serialization
+from cryptography.hazmat.primitives.asymmetric.ed448 import (
+    Ed448PrivateKey,
+    Ed448PublicKey,
+)
+
+_ED448_KEY_SIZE = 57
+_ED448_SIG_SIZE = 114
+
+
+@utils.register_interface(Ed448PublicKey)
+class _Ed448PublicKey(object):
+    def __init__(self, backend, evp_pkey):
+        self._backend = backend
+        self._evp_pkey = evp_pkey
+
+    def public_bytes(self, encoding, format):
+        if (
+            encoding is serialization.Encoding.Raw
+            or format is serialization.PublicFormat.Raw
+        ):
+            if (
+                encoding is not serialization.Encoding.Raw
+                or format is not serialization.PublicFormat.Raw
+            ):
+                raise ValueError(
+                    "When using Raw both encoding and format must be Raw"
+                )
+
+            return self._raw_public_bytes()
+
+        return self._backend._public_key_bytes(
+            encoding, format, self, self._evp_pkey, None
+        )
+
+    def _raw_public_bytes(self):
+        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(
+            self._evp_pkey, buf, buflen
+        )
+        self._backend.openssl_assert(res == 1)
+        self._backend.openssl_assert(buflen[0] == _ED448_KEY_SIZE)
+        return self._backend._ffi.buffer(buf, _ED448_KEY_SIZE)[:]
+
+    def verify(self, signature, data):
+        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(
+            evp_md_ctx, self._backend._lib.EVP_MD_CTX_free
+        )
+        res = self._backend._lib.EVP_DigestVerifyInit(
+            evp_md_ctx,
+            self._backend._ffi.NULL,
+            self._backend._ffi.NULL,
+            self._backend._ffi.NULL,
+            self._evp_pkey,
+        )
+        self._backend.openssl_assert(res == 1)
+        res = self._backend._lib.EVP_DigestVerify(
+            evp_md_ctx, signature, len(signature), data, len(data)
+        )
+        if res != 1:
+            self._backend._consume_errors()
+            raise exceptions.InvalidSignature
+
+
+@utils.register_interface(Ed448PrivateKey)
+class _Ed448PrivateKey(object):
+    def __init__(self, backend, evp_pkey):
+        self._backend = backend
+        self._evp_pkey = evp_pkey
+
+    def public_key(self):
+        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(
+            self._evp_pkey, buf, buflen
+        )
+        self._backend.openssl_assert(res == 1)
+        self._backend.openssl_assert(buflen[0] == _ED448_KEY_SIZE)
+        public_bytes = self._backend._ffi.buffer(buf)[:]
+        return self._backend.ed448_load_public_bytes(public_bytes)
+
+    def sign(self, data):
+        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(
+            evp_md_ctx, self._backend._lib.EVP_MD_CTX_free
+        )
+        res = self._backend._lib.EVP_DigestSignInit(
+            evp_md_ctx,
+            self._backend._ffi.NULL,
+            self._backend._ffi.NULL,
+            self._backend._ffi.NULL,
+            self._evp_pkey,
+        )
+        self._backend.openssl_assert(res == 1)
+        buf = self._backend._ffi.new("unsigned char[]", _ED448_SIG_SIZE)
+        buflen = self._backend._ffi.new("size_t *", len(buf))
+        res = self._backend._lib.EVP_DigestSign(
+            evp_md_ctx, buf, buflen, data, len(data)
+        )
+        self._backend.openssl_assert(res == 1)
+        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):
+        if (
+            encoding is serialization.Encoding.Raw
+            or format is serialization.PublicFormat.Raw
+        ):
+            if (
+                format is not serialization.PrivateFormat.Raw
+                or encoding is not serialization.Encoding.Raw
+                or not isinstance(
+                    encryption_algorithm, serialization.NoEncryption
+                )
+            ):
+                raise ValueError(
+                    "When using Raw both encoding and format must be Raw "
+                    "and encryption_algorithm must be NoEncryption()"
+                )
+
+            return self._raw_private_bytes()
+
+        return self._backend._private_key_bytes(
+            encoding, format, encryption_algorithm, self, self._evp_pkey, None
+        )
+
+    def _raw_private_bytes(self):
+        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(
+            self._evp_pkey, buf, buflen
+        )
+        self._backend.openssl_assert(res == 1)
+        self._backend.openssl_assert(buflen[0] == _ED448_KEY_SIZE)
+        return self._backend._ffi.buffer(buf, _ED448_KEY_SIZE)[:]
diff --git a/src/cryptography/hazmat/backends/openssl/encode_asn1.py b/src/cryptography/hazmat/backends/openssl/encode_asn1.py
index 3557576..0a33200 100644
--- a/src/cryptography/hazmat/backends/openssl/encode_asn1.py
+++ b/src/cryptography/hazmat/backends/openssl/encode_asn1.py
@@ -11,12 +11,15 @@
 
 from cryptography import utils, x509
 from cryptography.hazmat.backends.openssl.decode_asn1 import (
-    _CRL_ENTRY_REASON_ENUM_TO_CODE, _DISTPOINT_TYPE_FULLNAME,
-    _DISTPOINT_TYPE_RELATIVENAME
+    _CRL_ENTRY_REASON_ENUM_TO_CODE,
+    _DISTPOINT_TYPE_FULLNAME,
+    _DISTPOINT_TYPE_RELATIVENAME,
 )
 from cryptography.x509.name import _ASN1Type
 from cryptography.x509.oid import (
-    CRLEntryExtensionOID, ExtensionOID, OCSPExtensionOID,
+    CRLEntryExtensionOID,
+    ExtensionOID,
+    OCSPExtensionOID,
 )
 
 
@@ -94,7 +97,8 @@
                 name_entry, backend._lib.X509_NAME_ENTRY_free
             )
             res = backend._lib.X509_NAME_add_entry(
-                subject, name_entry, -1, set_flag)
+                subject, name_entry, -1, set_flag
+            )
             backend.openssl_assert(res == 1)
             set_flag = -1
     return subject
@@ -120,9 +124,11 @@
 
 def _encode_name_entry(backend, attribute):
     if attribute._type is _ASN1Type.BMPString:
-        value = attribute.value.encode('utf_16_be')
+        value = attribute.value.encode("utf_16_be")
+    elif attribute._type is _ASN1Type.UniversalString:
+        value = attribute.value.encode("utf_32_be")
     else:
-        value = attribute.value.encode('utf8')
+        value = attribute.value.encode("utf8")
 
     obj = _txt2obj_gc(backend, attribute.oid.dotted_string)
 
@@ -172,9 +178,8 @@
 
 def _encode_invalidity_date(backend, invalidity_date):
     time = backend._lib.ASN1_GENERALIZEDTIME_set(
-        backend._ffi.NULL, calendar.timegm(
-            invalidity_date.invalidity_date.timetuple()
-        )
+        backend._ffi.NULL,
+        calendar.timegm(invalidity_date.invalidity_date.timetuple()),
     )
     backend.openssl_assert(time != backend._ffi.NULL)
     time = backend._ffi.gc(time, backend._lib.ASN1_GENERALIZEDTIME_free)
@@ -255,7 +260,7 @@
     Converts a Python string with an ASN.1 object ID in dotted form to a
     ASN1_OBJECT.
     """
-    name = name.encode('ascii')
+    name = name.encode("ascii")
     obj = backend._lib.OBJ_txt2obj(name, 1)
     backend.openssl_assert(obj != backend._ffi.NULL)
     return obj
@@ -341,20 +346,27 @@
     return constraints
 
 
-def _encode_authority_information_access(backend, authority_info_access):
+def _encode_information_access(backend, info_access):
     aia = backend._lib.sk_ACCESS_DESCRIPTION_new_null()
     backend.openssl_assert(aia != backend._ffi.NULL)
     aia = backend._ffi.gc(
-        aia, backend._lib.sk_ACCESS_DESCRIPTION_free
+        aia,
+        lambda x: backend._lib.sk_ACCESS_DESCRIPTION_pop_free(
+            x,
+            backend._ffi.addressof(
+                backend._lib._original_lib, "ACCESS_DESCRIPTION_free"
+            ),
+        ),
     )
-    for access_description in authority_info_access:
+    for access_description in info_access:
         ad = backend._lib.ACCESS_DESCRIPTION_new()
         method = _txt2obj(
             backend, access_description.access_method.dotted_string
         )
-        gn = _encode_general_name(backend, access_description.access_location)
+        _encode_general_name_preallocated(
+            backend, access_description.access_location, ad.location
+        )
         ad.method = method
-        ad.location = gn
         res = backend._lib.sk_ACCESS_DESCRIPTION_push(aia, ad)
         backend.openssl_assert(res >= 1)
 
@@ -385,8 +397,13 @@
 
 
 def _encode_general_name(backend, name):
+    gn = backend._lib.GENERAL_NAME_new()
+    _encode_general_name_preallocated(backend, name, gn)
+    return gn
+
+
+def _encode_general_name_preallocated(backend, name, gn):
     if isinstance(name, x509.DNSName):
-        gn = backend._lib.GENERAL_NAME_new()
         backend.openssl_assert(gn != backend._ffi.NULL)
         gn.type = backend._lib.GEN_DNS
 
@@ -400,32 +417,27 @@
         backend.openssl_assert(res == 1)
         gn.d.dNSName = ia5
     elif isinstance(name, x509.RegisteredID):
-        gn = backend._lib.GENERAL_NAME_new()
         backend.openssl_assert(gn != backend._ffi.NULL)
         gn.type = backend._lib.GEN_RID
         obj = backend._lib.OBJ_txt2obj(
-            name.value.dotted_string.encode('ascii'), 1
+            name.value.dotted_string.encode("ascii"), 1
         )
         backend.openssl_assert(obj != backend._ffi.NULL)
         gn.d.registeredID = obj
     elif isinstance(name, x509.DirectoryName):
-        gn = backend._lib.GENERAL_NAME_new()
         backend.openssl_assert(gn != backend._ffi.NULL)
         dir_name = _encode_name(backend, name.value)
         gn.type = backend._lib.GEN_DIRNAME
         gn.d.directoryName = dir_name
     elif isinstance(name, x509.IPAddress):
-        gn = backend._lib.GENERAL_NAME_new()
         backend.openssl_assert(gn != backend._ffi.NULL)
         if isinstance(name.value, ipaddress.IPv4Network):
-            packed = (
-                name.value.network_address.packed +
-                utils.int_to_bytes(((1 << 32) - name.value.num_addresses), 4)
+            packed = name.value.network_address.packed + utils.int_to_bytes(
+                ((1 << 32) - name.value.num_addresses), 4
             )
         elif isinstance(name.value, ipaddress.IPv6Network):
-            packed = (
-                name.value.network_address.packed +
-                utils.int_to_bytes((1 << 128) - name.value.num_addresses, 16)
+            packed = name.value.network_address.packed + utils.int_to_bytes(
+                (1 << 128) - name.value.num_addresses, 16
             )
         else:
             packed = name.value.packed
@@ -433,13 +445,12 @@
         gn.type = backend._lib.GEN_IPADD
         gn.d.iPAddress = ipaddr
     elif isinstance(name, x509.OtherName):
-        gn = backend._lib.GENERAL_NAME_new()
         backend.openssl_assert(gn != backend._ffi.NULL)
         other_name = backend._lib.OTHERNAME_new()
         backend.openssl_assert(other_name != backend._ffi.NULL)
 
         type_id = backend._lib.OBJ_txt2obj(
-            name.type_id.dotted_string.encode('ascii'), 1
+            name.type_id.dotted_string.encode("ascii"), 1
         )
         backend.openssl_assert(type_id != backend._ffi.NULL)
         data = backend._ffi.new("unsigned char[]", name.value)
@@ -456,7 +467,6 @@
         gn.type = backend._lib.GEN_OTHERNAME
         gn.d.otherName = other_name
     elif isinstance(name, x509.RFC822Name):
-        gn = backend._lib.GENERAL_NAME_new()
         backend.openssl_assert(gn != backend._ffi.NULL)
         # ia5strings are supposed to be ITU T.50 but to allow round-tripping
         # of broken certs that encode utf8 we'll encode utf8 here too.
@@ -465,7 +475,6 @@
         gn.type = backend._lib.GEN_EMAIL
         gn.d.rfc822Name = asn1_str
     elif isinstance(name, x509.UniformResourceIdentifier):
-        gn = backend._lib.GENERAL_NAME_new()
         backend.openssl_assert(gn != backend._ffi.NULL)
         # ia5strings are supposed to be ITU T.50 but to allow round-tripping
         # of broken certs that encode utf8 we'll encode utf8 here too.
@@ -474,11 +483,7 @@
         gn.type = backend._lib.GEN_URI
         gn.d.uniformResourceIdentifier = asn1_str
     else:
-        raise ValueError(
-            "{0} is an unknown GeneralName type".format(name)
-        )
-
-    return gn
+        raise ValueError("{} is an unknown GeneralName type".format(name))
 
 
 def _encode_extended_key_usage(backend, extended_key_usage):
@@ -599,11 +604,21 @@
             gs = backend._lib.GENERAL_SUBTREE_new()
             gs.base = _encode_general_name(backend, name)
             res = backend._lib.sk_GENERAL_SUBTREE_push(general_subtrees, gs)
-            assert res >= 1
+            backend.openssl_assert(res >= 1)
 
         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)
 
@@ -617,26 +632,27 @@
     ExtensionOID.EXTENDED_KEY_USAGE: _encode_extended_key_usage,
     ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _encode_authority_key_identifier,
     ExtensionOID.CERTIFICATE_POLICIES: _encode_certificate_policies,
-    ExtensionOID.AUTHORITY_INFORMATION_ACCESS: (
-        _encode_authority_information_access
-    ),
+    ExtensionOID.AUTHORITY_INFORMATION_ACCESS: _encode_information_access,
+    ExtensionOID.SUBJECT_INFORMATION_ACCESS: _encode_information_access,
     ExtensionOID.CRL_DISTRIBUTION_POINTS: _encode_cdps_freshest_crl,
     ExtensionOID.FRESHEST_CRL: _encode_cdps_freshest_crl,
     ExtensionOID.INHIBIT_ANY_POLICY: _encode_inhibit_any_policy,
     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 = {
     ExtensionOID.ISSUER_ALTERNATIVE_NAME: _encode_alt_name,
     ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _encode_authority_key_identifier,
-    ExtensionOID.AUTHORITY_INFORMATION_ACCESS: (
-        _encode_authority_information_access
-    ),
+    ExtensionOID.AUTHORITY_INFORMATION_ACCESS: _encode_information_access,
     ExtensionOID.CRL_NUMBER: _encode_crl_number_delta_crl_indicator,
     ExtensionOID.DELTA_CRL_INDICATOR: _encode_crl_number_delta_crl_indicator,
     ExtensionOID.ISSUING_DISTRIBUTION_POINT: _encode_issuing_dist_point,
+    ExtensionOID.FRESHEST_CRL: _encode_cdps_freshest_crl,
 }
 
 _CRL_ENTRY_EXTENSION_ENCODE_HANDLERS = {
diff --git a/src/cryptography/hazmat/backends/openssl/hashes.py b/src/cryptography/hazmat/backends/openssl/hashes.py
index 549fa2b..764dce0 100644
--- a/src/cryptography/hazmat/backends/openssl/hashes.py
+++ b/src/cryptography/hazmat/backends/openssl/hashes.py
@@ -18,19 +18,21 @@
         self._backend = backend
 
         if ctx is None:
-            ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new()
+            ctx = self._backend._lib.EVP_MD_CTX_new()
             ctx = self._backend._ffi.gc(
-                ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free
+                ctx, self._backend._lib.EVP_MD_CTX_free
             )
             evp_md = self._backend._evp_md_from_algorithm(algorithm)
             if evp_md == self._backend._ffi.NULL:
                 raise UnsupportedAlgorithm(
-                    "{0} is not a supported hash on this backend.".format(
-                        algorithm.name),
-                    _Reasons.UNSUPPORTED_HASH
+                    "{} is not a supported hash on this backend.".format(
+                        algorithm.name
+                    ),
+                    _Reasons.UNSUPPORTED_HASH,
                 )
-            res = self._backend._lib.EVP_DigestInit_ex(ctx, evp_md,
-                                                       self._backend._ffi.NULL)
+            res = self._backend._lib.EVP_DigestInit_ex(
+                ctx, evp_md, self._backend._ffi.NULL
+            )
             self._backend.openssl_assert(res != 0)
 
         self._ctx = ctx
@@ -38,9 +40,9 @@
     algorithm = utils.read_only_property("_algorithm")
 
     def copy(self):
-        copied_ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new()
+        copied_ctx = self._backend._lib.EVP_MD_CTX_new()
         copied_ctx = self._backend._ffi.gc(
-            copied_ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free
+            copied_ctx, self._backend._lib.EVP_MD_CTX_free
         )
         res = self._backend._lib.EVP_MD_CTX_copy_ex(copied_ctx, self._ctx)
         self._backend.openssl_assert(res != 0)
@@ -58,21 +60,23 @@
             # extendable output functions use a different finalize
             return self._finalize_xof()
         else:
-            buf = self._backend._ffi.new("unsigned char[]",
-                                         self._backend._lib.EVP_MAX_MD_SIZE)
+            buf = self._backend._ffi.new(
+                "unsigned char[]", self._backend._lib.EVP_MAX_MD_SIZE
+            )
             outlen = self._backend._ffi.new("unsigned int *")
             res = self._backend._lib.EVP_DigestFinal_ex(self._ctx, buf, outlen)
             self._backend.openssl_assert(res != 0)
             self._backend.openssl_assert(
                 outlen[0] == self.algorithm.digest_size
             )
-            return self._backend._ffi.buffer(buf)[:outlen[0]]
+            return self._backend._ffi.buffer(buf)[: outlen[0]]
 
     def _finalize_xof(self):
-        buf = self._backend._ffi.new("unsigned char[]",
-                                     self.algorithm.digest_size)
+        buf = self._backend._ffi.new(
+            "unsigned char[]", self.algorithm.digest_size
+        )
         res = self._backend._lib.EVP_DigestFinalXOF(
             self._ctx, buf, self.algorithm.digest_size
         )
         self._backend.openssl_assert(res != 0)
-        return self._backend._ffi.buffer(buf)[:self.algorithm.digest_size]
+        return self._backend._ffi.buffer(buf)[: self.algorithm.digest_size]
diff --git a/src/cryptography/hazmat/backends/openssl/hmac.py b/src/cryptography/hazmat/backends/openssl/hmac.py
index b23ac64..1cc9d99 100644
--- a/src/cryptography/hazmat/backends/openssl/hmac.py
+++ b/src/cryptography/hazmat/backends/openssl/hmac.py
@@ -7,12 +7,13 @@
 
 from cryptography import utils
 from cryptography.exceptions import (
-    InvalidSignature, UnsupportedAlgorithm, _Reasons
+    InvalidSignature,
+    UnsupportedAlgorithm,
+    _Reasons,
 )
-from cryptography.hazmat.primitives import constant_time, hashes, mac
+from cryptography.hazmat.primitives import constant_time, hashes
 
 
-@utils.register_interface(mac.MACContext)
 @utils.register_interface(hashes.HashContext)
 class _HMACContext(object):
     def __init__(self, backend, key, algorithm, ctx=None):
@@ -20,17 +21,16 @@
         self._backend = backend
 
         if ctx is None:
-            ctx = self._backend._lib.Cryptography_HMAC_CTX_new()
+            ctx = self._backend._lib.HMAC_CTX_new()
             self._backend.openssl_assert(ctx != self._backend._ffi.NULL)
-            ctx = self._backend._ffi.gc(
-                ctx, self._backend._lib.Cryptography_HMAC_CTX_free
-            )
+            ctx = self._backend._ffi.gc(ctx, self._backend._lib.HMAC_CTX_free)
             evp_md = self._backend._evp_md_from_algorithm(algorithm)
             if evp_md == self._backend._ffi.NULL:
                 raise UnsupportedAlgorithm(
-                    "{0} is not a supported hash on this backend".format(
-                        algorithm.name),
-                    _Reasons.UNSUPPORTED_HASH
+                    "{} is not a supported hash on this backend".format(
+                        algorithm.name
+                    ),
+                    _Reasons.UNSUPPORTED_HASH,
                 )
             key_ptr = self._backend._ffi.from_buffer(key)
             res = self._backend._lib.HMAC_Init_ex(
@@ -44,10 +44,10 @@
     algorithm = utils.read_only_property("_algorithm")
 
     def copy(self):
-        copied_ctx = self._backend._lib.Cryptography_HMAC_CTX_new()
+        copied_ctx = self._backend._lib.HMAC_CTX_new()
         self._backend.openssl_assert(copied_ctx != self._backend._ffi.NULL)
         copied_ctx = self._backend._ffi.gc(
-            copied_ctx, self._backend._lib.Cryptography_HMAC_CTX_free
+            copied_ctx, self._backend._lib.HMAC_CTX_free
         )
         res = self._backend._lib.HMAC_CTX_copy(copied_ctx, self._ctx)
         self._backend.openssl_assert(res != 0)
@@ -61,13 +61,14 @@
         self._backend.openssl_assert(res != 0)
 
     def finalize(self):
-        buf = self._backend._ffi.new("unsigned char[]",
-                                     self._backend._lib.EVP_MAX_MD_SIZE)
+        buf = self._backend._ffi.new(
+            "unsigned char[]", self._backend._lib.EVP_MAX_MD_SIZE
+        )
         outlen = self._backend._ffi.new("unsigned int *")
         res = self._backend._lib.HMAC_Final(self._ctx, buf, outlen)
         self._backend.openssl_assert(res != 0)
         self._backend.openssl_assert(outlen[0] == self.algorithm.digest_size)
-        return self._backend._ffi.buffer(buf)[:outlen[0]]
+        return self._backend._ffi.buffer(buf)[: outlen[0]]
 
     def verify(self, signature):
         digest = self.finalize()
diff --git a/src/cryptography/hazmat/backends/openssl/ocsp.py b/src/cryptography/hazmat/backends/openssl/ocsp.py
index 16dbbc2..50c02e7 100644
--- a/src/cryptography/hazmat/backends/openssl/ocsp.py
+++ b/src/cryptography/hazmat/backends/openssl/ocsp.py
@@ -9,16 +9,23 @@
 from cryptography import utils, x509
 from cryptography.exceptions import UnsupportedAlgorithm
 from cryptography.hazmat.backends.openssl.decode_asn1 import (
-    _CRL_ENTRY_REASON_CODE_TO_ENUM, _OCSP_BASICRESP_EXT_PARSER,
-    _OCSP_REQ_EXT_PARSER, _asn1_integer_to_int,
-    _asn1_string_to_bytes, _decode_x509_name, _obj2txt,
+    _CRL_ENTRY_REASON_CODE_TO_ENUM,
+    _asn1_integer_to_int,
+    _asn1_string_to_bytes,
+    _decode_x509_name,
+    _obj2txt,
     _parse_asn1_generalized_time,
 )
 from cryptography.hazmat.backends.openssl.x509 import _Certificate
 from cryptography.hazmat.primitives import serialization
 from cryptography.x509.ocsp import (
-    OCSPCertStatus, OCSPRequest, OCSPResponse, OCSPResponseStatus,
-    _CERT_STATUS_TO_ENUM, _OIDS_TO_HASH, _RESPONSE_STATUS_TO_ENUM,
+    OCSPCertStatus,
+    OCSPRequest,
+    OCSPResponse,
+    OCSPResponseStatus,
+    _CERT_STATUS_TO_ENUM,
+    _OIDS_TO_HASH,
+    _RESPONSE_STATUS_TO_ENUM,
 )
 
 
@@ -39,8 +46,11 @@
 def _issuer_key_hash(backend, cert_id):
     key_hash = backend._ffi.new("ASN1_OCTET_STRING **")
     res = backend._lib.OCSP_id_get0_info(
-        backend._ffi.NULL, backend._ffi.NULL,
-        key_hash, backend._ffi.NULL, cert_id
+        backend._ffi.NULL,
+        backend._ffi.NULL,
+        key_hash,
+        backend._ffi.NULL,
+        cert_id,
     )
     backend.openssl_assert(res == 1)
     backend.openssl_assert(key_hash[0] != backend._ffi.NULL)
@@ -50,8 +60,11 @@
 def _issuer_name_hash(backend, cert_id):
     name_hash = backend._ffi.new("ASN1_OCTET_STRING **")
     res = backend._lib.OCSP_id_get0_info(
-        name_hash, backend._ffi.NULL,
-        backend._ffi.NULL, backend._ffi.NULL, cert_id
+        name_hash,
+        backend._ffi.NULL,
+        backend._ffi.NULL,
+        backend._ffi.NULL,
+        cert_id,
     )
     backend.openssl_assert(res == 1)
     backend.openssl_assert(name_hash[0] != backend._ffi.NULL)
@@ -61,8 +74,7 @@
 def _serial_number(backend, cert_id):
     num = backend._ffi.new("ASN1_INTEGER **")
     res = backend._lib.OCSP_id_get0_info(
-        backend._ffi.NULL, backend._ffi.NULL,
-        backend._ffi.NULL, num, cert_id
+        backend._ffi.NULL, backend._ffi.NULL, backend._ffi.NULL, num, cert_id
     )
     backend.openssl_assert(res == 1)
     backend.openssl_assert(num[0] != backend._ffi.NULL)
@@ -72,8 +84,11 @@
 def _hash_algorithm(backend, cert_id):
     asn1obj = backend._ffi.new("ASN1_OBJECT **")
     res = backend._lib.OCSP_id_get0_info(
-        backend._ffi.NULL, asn1obj,
-        backend._ffi.NULL, backend._ffi.NULL, cert_id
+        backend._ffi.NULL,
+        asn1obj,
+        backend._ffi.NULL,
+        backend._ffi.NULL,
+        cert_id,
     )
     backend.openssl_assert(res == 1)
     backend.openssl_assert(asn1obj[0] != backend._ffi.NULL)
@@ -82,7 +97,7 @@
         return _OIDS_TO_HASH[oid]
     except KeyError:
         raise UnsupportedAlgorithm(
-            "Signature algorithm OID: {0} not recognized".format(oid)
+            "Signature algorithm OID: {} not recognized".format(oid)
         )
 
 
@@ -102,9 +117,13 @@
             self._basic = self._backend._ffi.gc(
                 basic, self._backend._lib.OCSP_BASICRESP_free
             )
-            self._backend.openssl_assert(
-                self._backend._lib.OCSP_resp_count(self._basic) == 1
-            )
+            num_resp = self._backend._lib.OCSP_resp_count(self._basic)
+            if num_resp != 1:
+                raise ValueError(
+                    "OCSP response contains more than one SINGLERESP structure"
+                    ", which this library does not support. "
+                    "{} found".format(num_resp)
+                )
             self._single = self._backend._lib.OCSP_resp_get0(self._basic, 0)
             self._backend.openssl_assert(
                 self._single != self._backend._ffi.NULL
@@ -134,7 +153,7 @@
             return x509._SIG_OIDS_TO_HASH[oid]
         except KeyError:
             raise UnsupportedAlgorithm(
-                "Signature algorithm OID:{0} not recognized".format(oid)
+                "Signature algorithm OID:{} not recognized".format(oid)
             )
 
     @property
@@ -317,13 +336,16 @@
     @utils.cached_property
     @_requires_successful_response
     def extensions(self):
-        return _OCSP_BASICRESP_EXT_PARSER.parse(self._backend, self._basic)
+        return self._backend._ocsp_basicresp_ext_parser.parse(self._basic)
+
+    @utils.cached_property
+    @_requires_successful_response
+    def single_extensions(self):
+        return self._backend._ocsp_singleresp_ext_parser.parse(self._single)
 
     def public_bytes(self, encoding):
         if encoding is not serialization.Encoding.DER:
-            raise ValueError(
-                "The only allowed encoding value is 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_RESPONSE_bio(
@@ -338,7 +360,7 @@
     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'
+                "OCSP request contains more than one request"
             )
         self._backend = backend
         self._ocsp_request = ocsp_request
@@ -367,13 +389,11 @@
 
     @utils.cached_property
     def extensions(self):
-        return _OCSP_REQ_EXT_PARSER.parse(self._backend, self._ocsp_request)
+        return self._backend._ocsp_req_ext_parser.parse(self._ocsp_request)
 
     def public_bytes(self, encoding):
         if encoding is not serialization.Encoding.DER:
-            raise ValueError(
-                "The only allowed encoding value is 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)
diff --git a/src/cryptography/hazmat/backends/openssl/poly1305.py b/src/cryptography/hazmat/backends/openssl/poly1305.py
new file mode 100644
index 0000000..5699918
--- /dev/null
+++ b/src/cryptography/hazmat/backends/openssl/poly1305.py
@@ -0,0 +1,65 @@
+# 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
+
+
+from cryptography.exceptions import InvalidSignature
+from cryptography.hazmat.primitives import constant_time
+
+
+_POLY1305_TAG_SIZE = 16
+_POLY1305_KEY_SIZE = 32
+
+
+class _Poly1305Context(object):
+    def __init__(self, backend, key):
+        self._backend = backend
+
+        key_ptr = self._backend._ffi.from_buffer(key)
+        # This function copies the key into OpenSSL-owned memory so we don't
+        # need to retain it ourselves
+        evp_pkey = self._backend._lib.EVP_PKEY_new_raw_private_key(
+            self._backend._lib.NID_poly1305,
+            self._backend._ffi.NULL,
+            key_ptr,
+            len(key),
+        )
+        self._backend.openssl_assert(evp_pkey != self._backend._ffi.NULL)
+        self._evp_pkey = self._backend._ffi.gc(
+            evp_pkey, self._backend._lib.EVP_PKEY_free
+        )
+        ctx = self._backend._lib.EVP_MD_CTX_new()
+        self._backend.openssl_assert(ctx != self._backend._ffi.NULL)
+        self._ctx = self._backend._ffi.gc(
+            ctx, self._backend._lib.EVP_MD_CTX_free
+        )
+        res = self._backend._lib.EVP_DigestSignInit(
+            self._ctx,
+            self._backend._ffi.NULL,
+            self._backend._ffi.NULL,
+            self._backend._ffi.NULL,
+            self._evp_pkey,
+        )
+        self._backend.openssl_assert(res == 1)
+
+    def update(self, data):
+        data_ptr = self._backend._ffi.from_buffer(data)
+        res = self._backend._lib.EVP_DigestSignUpdate(
+            self._ctx, data_ptr, len(data)
+        )
+        self._backend.openssl_assert(res != 0)
+
+    def finalize(self):
+        buf = self._backend._ffi.new("unsigned char[]", _POLY1305_TAG_SIZE)
+        outlen = self._backend._ffi.new("size_t *")
+        res = self._backend._lib.EVP_DigestSignFinal(self._ctx, buf, outlen)
+        self._backend.openssl_assert(res != 0)
+        self._backend.openssl_assert(outlen[0] == _POLY1305_TAG_SIZE)
+        return self._backend._ffi.buffer(buf)[: outlen[0]]
+
+    def verify(self, tag):
+        mac = self.finalize()
+        if not constant_time.bytes_eq(mac, tag):
+            raise InvalidSignature("Value did not match computed tag.")
diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py
index 30d59bd..82cd49c 100644
--- a/src/cryptography/hazmat/backends/openssl/rsa.py
+++ b/src/cryptography/hazmat/backends/openssl/rsa.py
@@ -4,25 +4,34 @@
 
 from __future__ import absolute_import, division, print_function
 
-import math
-
 from cryptography import utils
 from cryptography.exceptions import (
-    InvalidSignature, UnsupportedAlgorithm, _Reasons
+    InvalidSignature,
+    UnsupportedAlgorithm,
+    _Reasons,
 )
 from cryptography.hazmat.backends.openssl.utils import (
-    _calculate_digest_and_algorithm, _check_not_prehashed,
-    _warn_sign_verify_deprecated
+    _calculate_digest_and_algorithm,
+    _check_not_prehashed,
+    _warn_sign_verify_deprecated,
 )
 from cryptography.hazmat.primitives import hashes
 from cryptography.hazmat.primitives.asymmetric import (
-    AsymmetricSignatureContext, AsymmetricVerificationContext, rsa
+    AsymmetricSignatureContext,
+    AsymmetricVerificationContext,
+    rsa,
 )
 from cryptography.hazmat.primitives.asymmetric.padding import (
-    AsymmetricPadding, MGF1, OAEP, PKCS1v15, PSS, calculate_max_pss_salt_length
+    AsymmetricPadding,
+    MGF1,
+    OAEP,
+    PKCS1v15,
+    PSS,
+    calculate_max_pss_salt_length,
 )
 from cryptography.hazmat.primitives.asymmetric.rsa import (
-    RSAPrivateKeyWithSerialization, RSAPublicKeyWithSerialization
+    RSAPrivateKeyWithSerialization,
+    RSAPublicKeyWithSerialization,
 )
 
 
@@ -47,22 +56,20 @@
         if not isinstance(padding._mgf, MGF1):
             raise UnsupportedAlgorithm(
                 "Only MGF1 is supported by this backend.",
-                _Reasons.UNSUPPORTED_MGF
+                _Reasons.UNSUPPORTED_MGF,
             )
 
         if not backend.rsa_padding_supported(padding):
             raise UnsupportedAlgorithm(
                 "This combination of padding and hash algorithm is not "
                 "supported by this backend.",
-                _Reasons.UNSUPPORTED_PADDING
+                _Reasons.UNSUPPORTED_PADDING,
             )
 
     else:
         raise UnsupportedAlgorithm(
-            "{0} is not supported by this backend.".format(
-                padding.name
-            ),
-            _Reasons.UNSUPPORTED_PADDING
+            "{} is not supported by this backend.".format(padding.name),
+            _Reasons.UNSUPPORTED_PADDING,
         )
 
     return _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding)
@@ -76,24 +83,19 @@
         init = backend._lib.EVP_PKEY_decrypt_init
         crypt = backend._lib.EVP_PKEY_decrypt
 
-    pkey_ctx = backend._lib.EVP_PKEY_CTX_new(
-        key._evp_pkey, backend._ffi.NULL
-    )
+    pkey_ctx = backend._lib.EVP_PKEY_CTX_new(key._evp_pkey, backend._ffi.NULL)
     backend.openssl_assert(pkey_ctx != backend._ffi.NULL)
     pkey_ctx = backend._ffi.gc(pkey_ctx, backend._lib.EVP_PKEY_CTX_free)
     res = init(pkey_ctx)
     backend.openssl_assert(res == 1)
-    res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(
-        pkey_ctx, padding_enum)
+    res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding_enum)
     backend.openssl_assert(res > 0)
     buf_size = backend._lib.EVP_PKEY_size(key._evp_pkey)
     backend.openssl_assert(buf_size > 0)
-    if (
-        isinstance(padding, OAEP) and
-        backend._lib.Cryptography_HAS_RSA_OAEP_MD
-    ):
+    if isinstance(padding, OAEP) and backend._lib.Cryptography_HAS_RSA_OAEP_MD:
         mgf1_md = backend._evp_md_non_null_from_algorithm(
-            padding._mgf._algorithm)
+            padding._mgf._algorithm
+        )
         res = backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1_md)
         backend.openssl_assert(res > 0)
         oaep_md = backend._evp_md_non_null_from_algorithm(padding._algorithm)
@@ -101,9 +103,9 @@
         backend.openssl_assert(res > 0)
 
     if (
-        isinstance(padding, OAEP) and
-        padding._label is not None and
-        len(padding._label) > 0
+        isinstance(padding, OAEP)
+        and padding._label is not None
+        and len(padding._label) > 0
     ):
         # set0_rsa_oaep_label takes ownership of the char * so we need to
         # copy it into some new memory
@@ -117,40 +119,19 @@
 
     outlen = backend._ffi.new("size_t *", buf_size)
     buf = backend._ffi.new("unsigned char[]", buf_size)
+    # Everything from this line onwards is written with the goal of being as
+    # constant-time as is practical given the constraints of Python and our
+    # API. See Bleichenbacher's '98 attack on RSA, and its many many variants.
+    # As such, you should not attempt to change this (particularly to "clean it
+    # up") without understanding why it was written this way (see
+    # Chesterton's Fence), and without measuring to verify you have not
+    # introduced observable time differences.
     res = crypt(pkey_ctx, buf, outlen, data, len(data))
+    resbuf = backend._ffi.buffer(buf)[: outlen[0]]
+    backend._lib.ERR_clear_error()
     if res <= 0:
-        _handle_rsa_enc_dec_error(backend, key)
-
-    return backend._ffi.buffer(buf)[:outlen[0]]
-
-
-def _handle_rsa_enc_dec_error(backend, key):
-    errors = backend._consume_errors()
-    backend.openssl_assert(errors)
-    backend.openssl_assert(errors[0].lib == backend._lib.ERR_LIB_RSA)
-    if isinstance(key, _RSAPublicKey):
-        backend.openssl_assert(
-            errors[0].reason == backend._lib.RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE
-        )
-        raise ValueError(
-            "Data too long for key size. Encrypt less data or use a "
-            "larger key size."
-        )
-    else:
-        decoding_errors = [
-            backend._lib.RSA_R_BLOCK_TYPE_IS_NOT_01,
-            backend._lib.RSA_R_BLOCK_TYPE_IS_NOT_02,
-            backend._lib.RSA_R_OAEP_DECODING_ERROR,
-            # Though this error looks similar to the
-            # RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE, this occurs on decrypts,
-            # rather than on encrypts
-            backend._lib.RSA_R_DATA_TOO_LARGE_FOR_MODULUS,
-        ]
-        if backend._lib.Cryptography_HAS_RSA_R_PKCS_DECODING_ERROR:
-            decoding_errors.append(backend._lib.RSA_R_PKCS_DECODING_ERROR)
-
-        backend.openssl_assert(errors[0].reason in decoding_errors)
-        raise ValueError("Decryption failed.")
+        raise ValueError("Encryption/decryption failed.")
+    return resbuf
 
 
 def _rsa_sig_determine_padding(backend, key, padding, algorithm):
@@ -161,49 +142,68 @@
     backend.openssl_assert(pkey_size > 0)
 
     if isinstance(padding, PKCS1v15):
+        # Hash algorithm is ignored for PKCS1v15-padding, may be None.
         padding_enum = backend._lib.RSA_PKCS1_PADDING
     elif isinstance(padding, PSS):
         if not isinstance(padding._mgf, MGF1):
             raise UnsupportedAlgorithm(
                 "Only MGF1 is supported by this backend.",
-                _Reasons.UNSUPPORTED_MGF
+                _Reasons.UNSUPPORTED_MGF,
             )
 
+        # PSS padding requires a hash algorithm
+        if not isinstance(algorithm, hashes.HashAlgorithm):
+            raise TypeError("Expected instance of hashes.HashAlgorithm.")
+
         # Size of key in bytes - 2 is the maximum
         # PSS signature length (salt length is checked later)
         if pkey_size - algorithm.digest_size - 2 < 0:
-            raise ValueError("Digest too large for key size. Use a larger "
-                             "key or different digest.")
+            raise ValueError(
+                "Digest too large for key size. Use a larger "
+                "key or different digest."
+            )
 
         padding_enum = backend._lib.RSA_PKCS1_PSS_PADDING
     else:
         raise UnsupportedAlgorithm(
-            "{0} is not supported by this backend.".format(padding.name),
-            _Reasons.UNSUPPORTED_PADDING
+            "{} is not supported by this backend.".format(padding.name),
+            _Reasons.UNSUPPORTED_PADDING,
         )
 
     return padding_enum
 
 
-def _rsa_sig_setup(backend, padding, algorithm, key, data, init_func):
+# Hash algorithm can be absent (None) to initialize the context without setting
+# any message digest algorithm. This is currently only valid for the PKCS1v15
+# padding type, where it means that the signature data is encoded/decoded
+# as provided, without being wrapped in a DigestInfo structure.
+def _rsa_sig_setup(backend, padding, algorithm, key, init_func):
     padding_enum = _rsa_sig_determine_padding(backend, key, padding, algorithm)
-    evp_md = backend._evp_md_non_null_from_algorithm(algorithm)
     pkey_ctx = backend._lib.EVP_PKEY_CTX_new(key._evp_pkey, backend._ffi.NULL)
     backend.openssl_assert(pkey_ctx != backend._ffi.NULL)
     pkey_ctx = backend._ffi.gc(pkey_ctx, backend._lib.EVP_PKEY_CTX_free)
     res = init_func(pkey_ctx)
     backend.openssl_assert(res == 1)
-    res = backend._lib.EVP_PKEY_CTX_set_signature_md(pkey_ctx, evp_md)
-    if res == 0:
+    if algorithm is not None:
+        evp_md = backend._evp_md_non_null_from_algorithm(algorithm)
+        res = backend._lib.EVP_PKEY_CTX_set_signature_md(pkey_ctx, evp_md)
+        if res == 0:
+            backend._consume_errors()
+            raise UnsupportedAlgorithm(
+                "{} is not supported by this backend for RSA signing.".format(
+                    algorithm.name
+                ),
+                _Reasons.UNSUPPORTED_HASH,
+            )
+    res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding_enum)
+    if res <= 0:
         backend._consume_errors()
         raise UnsupportedAlgorithm(
-            "{0} is not supported by this backend for RSA signing.".format(
-                algorithm.name
+            "{} is not supported for the RSA signature operation.".format(
+                padding.name
             ),
-            _Reasons.UNSUPPORTED_HASH
+            _Reasons.UNSUPPORTED_PADDING,
         )
-    res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding_enum)
-    backend.openssl_assert(res > 0)
     if isinstance(padding, PSS):
         res = backend._lib.EVP_PKEY_CTX_set_rsa_pss_saltlen(
             pkey_ctx, _get_rsa_pss_salt_length(padding, key, algorithm)
@@ -211,7 +211,8 @@
         backend.openssl_assert(res > 0)
 
         mgf1_md = backend._evp_md_non_null_from_algorithm(
-            padding._mgf._algorithm)
+            padding._mgf._algorithm
+        )
         res = backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1_md)
         backend.openssl_assert(res > 0)
 
@@ -220,45 +221,37 @@
 
 def _rsa_sig_sign(backend, padding, algorithm, private_key, data):
     pkey_ctx = _rsa_sig_setup(
-        backend, padding, algorithm, private_key, data,
-        backend._lib.EVP_PKEY_sign_init
+        backend,
+        padding,
+        algorithm,
+        private_key,
+        backend._lib.EVP_PKEY_sign_init,
     )
     buflen = backend._ffi.new("size_t *")
     res = backend._lib.EVP_PKEY_sign(
-        pkey_ctx,
-        backend._ffi.NULL,
-        buflen,
-        data,
-        len(data)
+        pkey_ctx, backend._ffi.NULL, buflen, data, len(data)
     )
     backend.openssl_assert(res == 1)
     buf = backend._ffi.new("unsigned char[]", buflen[0])
-    res = backend._lib.EVP_PKEY_sign(
-        pkey_ctx, buf, buflen, data, len(data))
+    res = backend._lib.EVP_PKEY_sign(pkey_ctx, buf, buflen, data, len(data))
     if res != 1:
-        errors = backend._consume_errors()
-        backend.openssl_assert(errors[0].lib == backend._lib.ERR_LIB_RSA)
-        if (
-            errors[0].reason ==
-            backend._lib.RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE
-        ):
-            reason = ("Salt length too long for key size. Try using "
-                      "MAX_LENGTH instead.")
-        else:
-            backend.openssl_assert(
-                errors[0].reason ==
-                backend._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY
-            )
-            reason = "Digest too large for key size. Use a larger key."
-        raise ValueError(reason)
+        errors = backend._consume_errors_with_text()
+        raise ValueError(
+            "Digest or salt length too long for key size. Use a larger key "
+            "or shorter salt length if you are specifying a PSS salt",
+            errors,
+        )
 
     return backend._ffi.buffer(buf)[:]
 
 
 def _rsa_sig_verify(backend, padding, algorithm, public_key, signature, data):
     pkey_ctx = _rsa_sig_setup(
-        backend, padding, algorithm, public_key, data,
-        backend._lib.EVP_PKEY_verify_init
+        backend,
+        padding,
+        algorithm,
+        public_key,
+        backend._lib.EVP_PKEY_verify_init,
     )
     res = backend._lib.EVP_PKEY_verify(
         pkey_ctx, signature, len(signature), data, len(data)
@@ -272,6 +265,36 @@
         raise InvalidSignature
 
 
+def _rsa_sig_recover(backend, padding, algorithm, public_key, signature):
+    pkey_ctx = _rsa_sig_setup(
+        backend,
+        padding,
+        algorithm,
+        public_key,
+        backend._lib.EVP_PKEY_verify_recover_init,
+    )
+
+    # 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
+    # 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)
+    backend.openssl_assert(maxlen > 0)
+    buf = backend._ffi.new("unsigned char[]", maxlen)
+    buflen = backend._ffi.new("size_t *", maxlen)
+    res = backend._lib.EVP_PKEY_verify_recover(
+        pkey_ctx, buf, buflen, signature, len(signature)
+    )
+    resbuf = backend._ffi.buffer(buf)[: buflen[0]]
+    backend._lib.ERR_clear_error()
+    # Assume that all parameter errors are handled during the setup phase and
+    # any error here is due to invalid signature.
+    if res != 1:
+        raise InvalidSignature
+    return resbuf
+
+
 @utils.register_interface(AsymmetricSignatureContext)
 class _RSASignatureContext(object):
     def __init__(self, backend, private_key, padding, algorithm):
@@ -295,7 +318,7 @@
             self._padding,
             self._algorithm,
             self._private_key,
-            self._hash_ctx.finalize()
+            self._hash_ctx.finalize(),
         )
 
 
@@ -325,21 +348,33 @@
             self._algorithm,
             self._public_key,
             self._signature,
-            self._hash_ctx.finalize()
+            self._hash_ctx.finalize(),
         )
 
 
 @utils.register_interface(RSAPrivateKeyWithSerialization)
 class _RSAPrivateKey(object):
     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)
+
+        # Blinding is on by default in many versions of OpenSSL, but let's
+        # just be conservative here.
+        res = backend._lib.RSA_blinding_on(rsa_cdata, backend._ffi.NULL)
+        backend.openssl_assert(res == 1)
+
         self._backend = backend
         self._rsa_cdata = rsa_cdata
         self._evp_pkey = evp_pkey
 
         n = self._backend._ffi.new("BIGNUM **")
         self._backend._lib.RSA_get0_key(
-            self._rsa_cdata, n, self._backend._ffi.NULL,
-            self._backend._ffi.NULL
+            self._rsa_cdata,
+            n,
+            self._backend._ffi.NULL,
+            self._backend._ffi.NULL,
         )
         self._backend.openssl_assert(n[0] != self._backend._ffi.NULL)
         self._key_size = self._backend._lib.BN_num_bits(n[0])
@@ -352,7 +387,7 @@
         return _RSASignatureContext(self._backend, self, padding, algorithm)
 
     def decrypt(self, ciphertext, padding):
-        key_size_bytes = int(math.ceil(self.key_size / 8.0))
+        key_size_bytes = (self.key_size + 7) // 8
         if key_size_bytes != len(ciphertext):
             raise ValueError("Ciphertext length must be equal to key size.")
 
@@ -362,8 +397,6 @@
         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)
-        res = self._backend._lib.RSA_blinding_on(ctx, self._backend._ffi.NULL)
-        self._backend.openssl_assert(res == 1)
         evp_pkey = self._backend._rsa_cdata_to_evp_pkey(ctx)
         return _RSAPublicKey(self._backend, ctx, evp_pkey)
 
@@ -399,7 +432,7 @@
             public_numbers=rsa.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):
@@ -407,8 +440,9 @@
             encoding,
             format,
             encryption_algorithm,
+            self,
             self._evp_pkey,
-            self._rsa_cdata
+            self._rsa_cdata,
         )
 
     def sign(self, data, padding, algorithm):
@@ -427,8 +461,10 @@
 
         n = self._backend._ffi.new("BIGNUM **")
         self._backend._lib.RSA_get0_key(
-            self._rsa_cdata, n, self._backend._ffi.NULL,
-            self._backend._ffi.NULL
+            self._rsa_cdata,
+            n,
+            self._backend._ffi.NULL,
+            self._backend._ffi.NULL,
         )
         self._backend.openssl_assert(n[0] != self._backend._ffi.NULL)
         self._key_size = self._backend._lib.BN_num_bits(n[0])
@@ -462,11 +498,7 @@
 
     def public_bytes(self, encoding, format):
         return self._backend._public_key_bytes(
-            encoding,
-            format,
-            self,
-            self._evp_pkey,
-            self._rsa_cdata
+            encoding, format, self, self._evp_pkey, self._rsa_cdata
         )
 
     def verify(self, signature, data, padding, algorithm):
@@ -476,3 +508,9 @@
         return _rsa_sig_verify(
             self._backend, padding, algorithm, self, signature, data
         )
+
+    def recover_data_from_signature(self, signature, padding, algorithm):
+        _check_not_prehashed(algorithm)
+        return _rsa_sig_recover(
+            self._backend, padding, algorithm, self, signature
+        )
diff --git a/src/cryptography/hazmat/backends/openssl/utils.py b/src/cryptography/hazmat/backends/openssl/utils.py
index 363f3d2..3d697d1 100644
--- a/src/cryptography/hazmat/backends/openssl/utils.py
+++ b/src/cryptography/hazmat/backends/openssl/utils.py
@@ -17,9 +17,7 @@
     ctx = backend._ffi.gc(ctx, backend._lib.EVP_PKEY_CTX_free)
     res = backend._lib.EVP_PKEY_derive_init(ctx)
     backend.openssl_assert(res == 1)
-    res = backend._lib.EVP_PKEY_derive_set_peer(
-        ctx, peer_public_key._evp_pkey
-    )
+    res = backend._lib.EVP_PKEY_derive_set_peer(ctx, peer_public_key._evp_pkey)
     backend.openssl_assert(res == 1)
     keylen = backend._ffi.new("size_t *")
     res = backend._lib.EVP_PKEY_derive(ctx, backend._ffi.NULL, keylen)
@@ -28,9 +26,7 @@
     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."
-        )
+        raise ValueError("Null shared key derived from public/private pair.")
 
     return backend._ffi.buffer(buf, keylen[0])[:]
 
@@ -56,7 +52,8 @@
     if isinstance(signature_algorithm, Prehashed):
         raise TypeError(
             "Prehashed is only supported in the sign and verify methods. "
-            "It cannot be used with signer or verifier."
+            "It cannot be used with signer, verifier or "
+            "recover_data_from_signature."
         )
 
 
@@ -64,6 +61,6 @@
     warnings.warn(
         "signer and verifier have been deprecated. Please use sign "
         "and verify instead.",
-        utils.PersistentlyDeprecated,
-        stacklevel=3
+        utils.PersistentlyDeprecated2017,
+        stacklevel=3,
     )
diff --git a/src/cryptography/hazmat/backends/openssl/x25519.py b/src/cryptography/hazmat/backends/openssl/x25519.py
index 914f594..4971c54 100644
--- a/src/cryptography/hazmat/backends/openssl/x25519.py
+++ b/src/cryptography/hazmat/backends/openssl/x25519.py
@@ -4,13 +4,12 @@
 
 from __future__ import absolute_import, division, print_function
 
-import warnings
-
 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 (
-    X25519PrivateKey, X25519PublicKey
+    X25519PrivateKey,
+    X25519PublicKey,
 )
 
 
@@ -23,26 +22,14 @@
         self._backend = backend
         self._evp_pkey = evp_pkey
 
-    def public_bytes(self, encoding=None, format=None):
-        if encoding is None or format is None:
-            if encoding is not None or format is not None:
-                raise ValueError("Both encoding and format are required")
-            else:
-                warnings.warn(
-                    "public_bytes now requires encoding and format arguments. "
-                    "Support for calling without arguments will be removed in "
-                    "cryptography 2.7",
-                    utils.DeprecatedIn25,
-                )
-                encoding = serialization.Encoding.Raw
-                format = serialization.PublicFormat.Raw
+    def public_bytes(self, encoding, format):
         if (
-            encoding is serialization.Encoding.Raw or
-            format is serialization.PublicFormat.Raw
+            encoding is serialization.Encoding.Raw
+            or format is serialization.PublicFormat.Raw
         ):
             if (
-                encoding is not serialization.Encoding.Raw or
-                format is not serialization.PublicFormat.Raw
+                encoding is not serialization.Encoding.Raw
+                or format is not serialization.PublicFormat.Raw
             ):
                 raise ValueError(
                     "When using Raw both encoding and format must be Raw"
@@ -50,15 +37,6 @@
 
             return self._raw_public_bytes()
 
-        if (
-            encoding in serialization._PEM_DER and
-            format is not serialization.PublicFormat.SubjectPublicKeyInfo
-        ):
-            raise ValueError(
-                "format must be SubjectPublicKeyInfo when encoding is PEM or "
-                "DER"
-            )
-
         return self._backend._public_key_bytes(
             encoding, format, self, self._evp_pkey, None
         )
@@ -99,37 +77,29 @@
         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
-        )
+        return _evp_pkey_derive(self._backend, self._evp_pkey, peer_public_key)
 
     def private_bytes(self, encoding, format, encryption_algorithm):
         if (
-            encoding is serialization.Encoding.Raw or
-            format is serialization.PublicFormat.Raw
+            encoding is serialization.Encoding.Raw
+            or format is serialization.PublicFormat.Raw
         ):
             if (
-                format is not serialization.PrivateFormat.Raw or
-                encoding is not serialization.Encoding.Raw or not
-                isinstance(encryption_algorithm, serialization.NoEncryption)
+                format is not serialization.PrivateFormat.Raw
+                or encoding is not serialization.Encoding.Raw
+                or not isinstance(
+                    encryption_algorithm, serialization.NoEncryption
+                )
             ):
                 raise ValueError(
                     "When using Raw both encoding and format must be Raw "
-                    "and encryption_algorithm must be NoEncryption"
+                    "and encryption_algorithm must be NoEncryption()"
                 )
 
             return self._raw_private_bytes()
 
-        if (
-            encoding in serialization._PEM_DER and
-            format is not serialization.PrivateFormat.PKCS8
-        ):
-            raise ValueError(
-                "format must be PKCS8 when encoding is PEM or DER"
-            )
-
         return self._backend._private_key_bytes(
-            encoding, format, encryption_algorithm, self._evp_pkey, None
+            encoding, format, encryption_algorithm, self, self._evp_pkey, None
         )
 
     def _raw_private_bytes(self):
@@ -139,9 +109,13 @@
         # using the last 32 bytes, which is the key itself.
         bio = self._backend._create_mem_bio_gc()
         res = self._backend._lib.i2d_PKCS8PrivateKey_bio(
-            bio, self._evp_pkey,
-            self._backend._ffi.NULL, self._backend._ffi.NULL,
-            0, self._backend._ffi.NULL, self._backend._ffi.NULL
+            bio,
+            self._evp_pkey,
+            self._backend._ffi.NULL,
+            self._backend._ffi.NULL,
+            0,
+            self._backend._ffi.NULL,
+            self._backend._ffi.NULL,
         )
         self._backend.openssl_assert(res == 1)
         pkcs8 = self._backend._read_mem_bio(bio)
diff --git a/src/cryptography/hazmat/backends/openssl/x448.py b/src/cryptography/hazmat/backends/openssl/x448.py
index 13e4ce1..7ebcdf8 100644
--- a/src/cryptography/hazmat/backends/openssl/x448.py
+++ b/src/cryptography/hazmat/backends/openssl/x448.py
@@ -8,7 +8,8 @@
 from cryptography.hazmat.backends.openssl.utils import _evp_pkey_derive
 from cryptography.hazmat.primitives import serialization
 from cryptography.hazmat.primitives.asymmetric.x448 import (
-    X448PrivateKey, X448PublicKey
+    X448PrivateKey,
+    X448PublicKey,
 )
 
 _X448_KEY_SIZE = 56
@@ -22,12 +23,12 @@
 
     def public_bytes(self, encoding, format):
         if (
-            encoding is serialization.Encoding.Raw or
-            format is serialization.PublicFormat.Raw
+            encoding is serialization.Encoding.Raw
+            or format is serialization.PublicFormat.Raw
         ):
             if (
-                encoding is not serialization.Encoding.Raw or
-                format is not serialization.PublicFormat.Raw
+                encoding is not serialization.Encoding.Raw
+                or format is not serialization.PublicFormat.Raw
             ):
                 raise ValueError(
                     "When using Raw both encoding and format must be Raw"
@@ -35,15 +36,6 @@
 
             return self._raw_public_bytes()
 
-        if (
-            encoding in serialization._PEM_DER and
-            format is not serialization.PublicFormat.SubjectPublicKeyInfo
-        ):
-            raise ValueError(
-                "format must be SubjectPublicKeyInfo when encoding is PEM or "
-                "DER"
-            )
-
         return self._backend._public_key_bytes(
             encoding, format, self, self._evp_pkey, None
         )
@@ -79,37 +71,29 @@
         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
-        )
+        return _evp_pkey_derive(self._backend, self._evp_pkey, peer_public_key)
 
     def private_bytes(self, encoding, format, encryption_algorithm):
         if (
-            encoding is serialization.Encoding.Raw or
-            format is serialization.PublicFormat.Raw
+            encoding is serialization.Encoding.Raw
+            or format is serialization.PublicFormat.Raw
         ):
             if (
-                format is not serialization.PrivateFormat.Raw or
-                encoding is not serialization.Encoding.Raw or not
-                isinstance(encryption_algorithm, serialization.NoEncryption)
+                format is not serialization.PrivateFormat.Raw
+                or encoding is not serialization.Encoding.Raw
+                or not isinstance(
+                    encryption_algorithm, serialization.NoEncryption
+                )
             ):
                 raise ValueError(
                     "When using Raw both encoding and format must be Raw "
-                    "and encryption_algorithm must be NoEncryption"
+                    "and encryption_algorithm must be NoEncryption()"
                 )
 
             return self._raw_private_bytes()
 
-        if (
-            encoding in serialization._PEM_DER and
-            format is not serialization.PrivateFormat.PKCS8
-        ):
-            raise ValueError(
-                "format must be PKCS8 when encoding is PEM or DER"
-            )
-
         return self._backend._private_key_bytes(
-            encoding, format, encryption_algorithm, self._evp_pkey, None
+            encoding, format, encryption_algorithm, self, self._evp_pkey, None
         )
 
     def _raw_private_bytes(self):
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index ac1838c..4d0dac7 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -6,31 +6,43 @@
 
 import datetime
 import operator
-import warnings
 
 from cryptography import utils, x509
 from cryptography.exceptions import UnsupportedAlgorithm
 from cryptography.hazmat.backends.openssl.decode_asn1 import (
-    _CERTIFICATE_EXTENSION_PARSER, _CERTIFICATE_EXTENSION_PARSER_NO_SCT,
-    _CRL_EXTENSION_PARSER, _CSR_EXTENSION_PARSER,
-    _REVOKED_CERTIFICATE_EXTENSION_PARSER, _asn1_integer_to_int,
-    _asn1_string_to_bytes, _decode_x509_name, _obj2txt, _parse_asn1_time
+    _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
+    _encode_asn1_int_gc,
+    _txt2obj_gc,
 )
 from cryptography.hazmat.primitives import hashes, serialization
 from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
+from cryptography.x509.name import _ASN1Type
 
 
 @utils.register_interface(x509.Certificate)
 class _Certificate(object):
-    def __init__(self, backend, x509):
+    def __init__(self, backend, x509_cert):
         self._backend = backend
-        self._x509 = x509
+        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 "<Certificate(subject={0}, ...)>".format(self.subject)
+        return "<Certificate(subject={}, ...)>".format(self.subject)
 
     def __eq__(self, other):
         if not isinstance(other, x509.Certificate):
@@ -45,31 +57,15 @@
     def __hash__(self):
         return hash(self.public_bytes(serialization.Encoding.DER))
 
+    def __deepcopy__(self, memo):
+        return self
+
     def fingerprint(self, algorithm):
         h = hashes.Hash(algorithm, self._backend)
         h.update(self.public_bytes(serialization.Encoding.DER))
         return h.finalize()
 
-    @property
-    def version(self):
-        version = self._backend._lib.X509_get_version(self._x509)
-        if version == 0:
-            return x509.Version.v1
-        elif version == 2:
-            return x509.Version.v3
-        else:
-            raise x509.InvalidVersion(
-                "{0} is not a valid X509 version".format(version), version
-            )
-
-    @property
-    def serial(self):
-        warnings.warn(
-            "Certificate serial is deprecated, use serial_number instead.",
-            utils.PersistentlyDeprecated,
-            stacklevel=2
-        )
-        return self.serial_number
+    version = utils.read_only_property("_version")
 
     @property
     def serial_number(self):
@@ -90,12 +86,12 @@
 
     @property
     def not_valid_before(self):
-        asn1_time = self._backend._lib.X509_get_notBefore(self._x509)
+        asn1_time = self._backend._lib.X509_getm_notBefore(self._x509)
         return _parse_asn1_time(self._backend, asn1_time)
 
     @property
     def not_valid_after(self):
-        asn1_time = self._backend._lib.X509_get_notAfter(self._x509)
+        asn1_time = self._backend._lib.X509_getm_notAfter(self._x509)
         return _parse_asn1_time(self._backend, asn1_time)
 
     @property
@@ -117,7 +113,7 @@
             return x509._SIG_OIDS_TO_HASH[oid]
         except KeyError:
             raise UnsupportedAlgorithm(
-                "Signature algorithm OID:{0} not recognized".format(oid)
+                "Signature algorithm OID:{} not recognized".format(oid)
             )
 
     @property
@@ -132,14 +128,7 @@
 
     @utils.cached_property
     def extensions(self):
-        if self._backend._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER:
-            return _CERTIFICATE_EXTENSION_PARSER.parse(
-                self._backend, self._x509
-            )
-        else:
-            return _CERTIFICATE_EXTENSION_PARSER_NO_SCT.parse(
-                self._backend, self._x509
-            )
+        return self._backend._certificate_extension_parser.parse(self._x509)
 
     @property
     def signature(self):
@@ -201,13 +190,13 @@
             self._backend,
             self._backend._lib.X509_REVOKED_get0_revocationDate(
                 self._x509_revoked
-            )
+            ),
         )
 
     @utils.cached_property
     def extensions(self):
-        return _REVOKED_CERTIFICATE_EXTENSION_PARSER.parse(
-            self._backend, self._x509_revoked
+        return self._backend._revoked_cert_extension_parser.parse(
+            self._x509_revoked
         )
 
 
@@ -230,9 +219,7 @@
     def fingerprint(self, algorithm):
         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
-        )
+        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)
@@ -257,9 +244,7 @@
         if res == 0:
             return None
         else:
-            self._backend.openssl_assert(
-                revoked[0] != self._backend._ffi.NULL
-            )
+            self._backend.openssl_assert(revoked[0] != self._backend._ffi.NULL)
             return _RevokedCertificate(
                 self._backend, self._sorted_crl, revoked[0]
             )
@@ -271,7 +256,7 @@
             return x509._SIG_OIDS_TO_HASH[oid]
         except KeyError:
             raise UnsupportedAlgorithm(
-                "Signature algorithm OID:{0} not recognized".format(oid)
+                "Signature algorithm OID:{} not recognized".format(oid)
             )
 
     @property
@@ -366,13 +351,17 @@
 
     @utils.cached_property
     def extensions(self):
-        return _CRL_EXTENSION_PARSER.parse(self._backend, self._x509_crl)
+        return self._backend._crl_extension_parser.parse(self._x509_crl)
 
     def is_signature_valid(self, public_key):
-        if not isinstance(public_key, (dsa.DSAPublicKey, rsa.RSAPublicKey,
-                                       ec.EllipticCurvePublicKey)):
-            raise TypeError('Expecting one of DSAPublicKey, RSAPublicKey,'
-                            ' or EllipticCurvePublicKey.')
+        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
         )
@@ -423,7 +412,7 @@
             return x509._SIG_OIDS_TO_HASH[oid]
         except KeyError:
             raise UnsupportedAlgorithm(
-                "Signature algorithm OID:{0} not recognized".format(oid)
+                "Signature algorithm OID:{} not recognized".format(oid)
             )
 
     @property
@@ -442,12 +431,13 @@
         x509_exts = self._backend._ffi.gc(
             x509_exts,
             lambda x: self._backend._lib.sk_X509_EXTENSION_pop_free(
-                x, self._backend._ffi.addressof(
+                x,
+                self._backend._ffi.addressof(
                     self._backend._lib._original_lib, "X509_EXTENSION_free"
-                )
-            )
+                ),
+            ),
         )
-        return _CSR_EXTENSION_PARSER.parse(self._backend, x509_exts)
+        return self._backend._csr_extension_parser.parse(x509_exts)
 
     def public_bytes(self, encoding):
         bio = self._backend._create_mem_bio_gc()
@@ -495,6 +485,47 @@
 
         return True
 
+    def get_attribute_for_oid(self, oid):
+        obj = _txt2obj_gc(self._backend, oid.dotted_string)
+        pos = self._backend._lib.X509_REQ_get_attr_by_OBJ(
+            self._x509_req, obj, -1
+        )
+        if pos == -1:
+            raise x509.AttributeNotFound(
+                "No {} attribute was found".format(oid), oid
+            )
+
+        attr = self._backend._lib.X509_REQ_get_attr(self._x509_req, pos)
+        self._backend.openssl_assert(attr != self._backend._ffi.NULL)
+        # We don't support multiple valued attributes for now.
+        self._backend.openssl_assert(
+            self._backend._lib.X509_ATTRIBUTE_count(attr) == 1
+        )
+        asn1_type = self._backend._lib.X509_ATTRIBUTE_get0_type(attr, 0)
+        self._backend.openssl_assert(asn1_type != self._backend._ffi.NULL)
+        # We need this to ensure that our C type cast is safe.
+        # Also this should always be a sane string type, but we'll see if
+        # that is true in the real world...
+        if asn1_type.type not in (
+            _ASN1Type.UTF8String.value,
+            _ASN1Type.PrintableString.value,
+            _ASN1Type.IA5String.value,
+        ):
+            raise ValueError(
+                "OID {} has a disallowed ASN.1 type: {}".format(
+                    oid, asn1_type.type
+                )
+            )
+
+        data = self._backend._lib.X509_ATTRIBUTE_get0_data(
+            attr, 0, asn1_type.type, self._backend._ffi.NULL
+        )
+        self._backend.openssl_assert(data != self._backend._ffi.NULL)
+        # This cast is safe iff we assert on the type above to ensure
+        # 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
@@ -523,9 +554,9 @@
     def timestamp(self):
         timestamp = self._backend._lib.SCT_get_timestamp(self._sct)
         milliseconds = timestamp % 1000
-        return datetime.datetime.utcfromtimestamp(
-            timestamp // 1000
-        ).replace(microsecond=milliseconds * 1000)
+        return datetime.datetime.utcfromtimestamp(timestamp // 1000).replace(
+            microsecond=milliseconds * 1000
+        )
 
     @property
     def entry_type(self):
diff --git a/src/cryptography/hazmat/bindings/_constant_time.so b/src/cryptography/hazmat/bindings/_constant_time.so
deleted file mode 100644
index 6a34359..0000000
--- a/src/cryptography/hazmat/bindings/_constant_time.so
+++ /dev/null
Binary files differ
diff --git a/src/cryptography/hazmat/bindings/_openssl.so b/src/cryptography/hazmat/bindings/_openssl.so
old mode 100644
new mode 100755
index d896a79..6551c6a
--- a/src/cryptography/hazmat/bindings/_openssl.so
+++ b/src/cryptography/hazmat/bindings/_openssl.so
Binary files differ
diff --git a/src/cryptography/hazmat/bindings/_padding.so b/src/cryptography/hazmat/bindings/_padding.so
old mode 100644
new mode 100755
index a27d09e..5cdc438
--- a/src/cryptography/hazmat/bindings/_padding.so
+++ b/src/cryptography/hazmat/bindings/_padding.so
Binary files differ
diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py
index c0238dc..ca50fed 100644
--- a/src/cryptography/hazmat/bindings/openssl/_conditional.py
+++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py
@@ -13,24 +13,6 @@
     ]
 
 
-def cryptography_has_ec_1_0_2():
-    return [
-        "EC_curve_nid2nist",
-    ]
-
-
-def cryptography_has_set_ecdh_auto():
-    return [
-        "SSL_CTX_set_ecdh_auto",
-    ]
-
-
-def cryptography_has_rsa_r_pkcs_decoding_error():
-    return [
-        "RSA_R_PKCS_DECODING_ERROR"
-    ]
-
-
 def cryptography_has_rsa_oaep_md():
     return [
         "EVP_PKEY_CTX_set_rsa_oaep_md",
@@ -51,78 +33,22 @@
     ]
 
 
-def cryptography_has_alpn():
+def cryptography_has_102_verification():
     return [
-        "SSL_CTX_set_alpn_protos",
-        "SSL_set_alpn_protos",
-        "SSL_CTX_set_alpn_select_cb",
-        "SSL_get0_alpn_selected",
-    ]
-
-
-def cryptography_has_compression():
-    return [
-        "SSL_get_current_compression",
-        "SSL_get_current_expansion",
-        "SSL_COMP_get_name",
-    ]
-
-
-def cryptography_has_get_server_tmp_key():
-    return [
-        "SSL_get_server_tmp_key",
-    ]
-
-
-def cryptography_has_102_verification_error_codes():
-    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_ERR_HOSTNAME_MISMATCH',
-        'X509_V_ERR_EMAIL_MISMATCH',
-        'X509_V_ERR_IP_ADDRESS_MISMATCH'
-    ]
-
-
-def cryptography_has_102_verification_params():
-    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",
-        "X509_VERIFY_PARAM_set1_host",
-        "X509_VERIFY_PARAM_set1_email",
-        "X509_VERIFY_PARAM_set1_ip",
-        "X509_VERIFY_PARAM_set1_ip_asc",
-        "X509_VERIFY_PARAM_set_hostflags",
-        "SSL_get0_param",
-        "X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT",
-        "X509_CHECK_FLAG_NO_WILDCARDS",
-        "X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS",
-        "X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS",
-        "X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS"
     ]
 
 
 def cryptography_has_110_verification_params():
-    return [
-        "X509_CHECK_FLAG_NEVER_CHECK_SUBJECT"
-    ]
-
-
-def cryptography_has_x509_v_flag_trusted_first():
-    return [
-        "X509_V_FLAG_TRUSTED_FIRST",
-    ]
-
-
-def cryptography_has_x509_v_flag_partial_chain():
-    return [
-        "X509_V_FLAG_PARTIAL_CHAIN",
-    ]
+    return ["X509_CHECK_FLAG_NEVER_CHECK_SUBJECT"]
 
 
 def cryptography_has_set_cert_cb():
@@ -148,35 +74,12 @@
     ]
 
 
-def cryptography_has_locking_callbacks():
-    return [
-        "CRYPTO_LOCK",
-        "CRYPTO_UNLOCK",
-        "CRYPTO_READ",
-        "CRYPTO_LOCK_SSL",
-        "CRYPTO_lock",
-        "Cryptography_setup_ssl_threads",
-    ]
-
-
 def cryptography_has_scrypt():
     return [
         "EVP_PBE_scrypt",
     ]
 
 
-def cryptography_has_generic_dtls_method():
-    return [
-        "DTLS_method",
-        "DTLS_server_method",
-        "DTLS_client_method",
-        "SSL_OP_NO_DTLSv1",
-        "SSL_OP_NO_DTLSv1_2",
-        "DTLS_set_link_mtu",
-        "DTLS_get_link_min_mtu",
-    ]
-
-
 def cryptography_has_evp_pkey_dhx():
     return [
         "EVP_PKEY_DHX",
@@ -197,11 +100,12 @@
         "SCT_get0_signature",
         "SCT_get_timestamp",
         "SCT_set_source",
+        "sk_SCT_new_null",
+        "sk_SCT_free",
         "sk_SCT_num",
         "sk_SCT_value",
-        "SCT_LIST_free",
         "sk_SCT_push",
-        "sk_SCT_new_null",
+        "SCT_LIST_free",
         "SCT_new",
         "SCT_set1_log_id",
         "SCT_set_timestamp",
@@ -217,20 +121,6 @@
     ]
 
 
-def cryptography_has_x25519():
-    return [
-        "EVP_PKEY_X25519",
-        "NID_X25519",
-    ]
-
-
-def cryptography_has_x448():
-    return [
-        "EVP_PKEY_X448",
-        "NID_X448",
-    ]
-
-
 def cryptography_has_ed448():
     return [
         "EVP_PKEY_ED448",
@@ -245,6 +135,13 @@
     ]
 
 
+def cryptography_has_poly1305():
+    return [
+        "NID_poly1305",
+        "EVP_PKEY_POLY1305",
+    ]
+
+
 def cryptography_has_oneshot_evp_digest_sign_verify():
     return [
         "EVP_DigestSign",
@@ -267,7 +164,7 @@
 
 def cryptography_has_fips():
     return [
-        "FIPS_set_mode",
+        "FIPS_mode_set",
         "FIPS_mode",
     ]
 
@@ -301,16 +198,6 @@
     ]
 
 
-def cryptography_has_cipher_details():
-    return [
-        "SSL_CIPHER_is_aead",
-        "SSL_CIPHER_get_cipher_nid",
-        "SSL_CIPHER_get_digest_nid",
-        "SSL_CIPHER_get_kx_nid",
-        "SSL_CIPHER_get_auth_nid",
-    ]
-
-
 def cryptography_has_tlsv13():
     return [
         "SSL_OP_NO_TLSv1_3",
@@ -326,6 +213,13 @@
     ]
 
 
+def cryptography_has_keylog():
+    return [
+        "SSL_CTX_set_keylog_callback",
+        "SSL_CTX_get_keylog_callback",
+    ]
+
+
 def cryptography_has_raw_key():
     return [
         "EVP_PKEY_new_raw_private_key",
@@ -335,9 +229,45 @@
     ]
 
 
-def cryptography_has_evp_r_memory_limit_exceeded():
+def cryptography_has_engine():
     return [
-        "EVP_R_MEMORY_LIMIT_EXCEEDED",
+        "ENGINE_by_id",
+        "ENGINE_init",
+        "ENGINE_finish",
+        "ENGINE_get_default_RAND",
+        "ENGINE_set_default_RAND",
+        "ENGINE_unregister_RAND",
+        "ENGINE_ctrl_cmd",
+        "ENGINE_free",
+        "ENGINE_get_name",
+        "Cryptography_add_osrandom_engine",
+        "ENGINE_ctrl_cmd_string",
+        "ENGINE_load_builtin_engines",
+        "ENGINE_load_private_key",
+        "ENGINE_load_public_key",
+    ]
+
+
+def cryptography_has_verified_chain():
+    return [
+        "SSL_get0_verified_chain",
+    ]
+
+
+def cryptography_has_srtp():
+    return [
+        "SSL_CTX_set_tlsext_use_srtp",
+        "SSL_set_tlsext_use_srtp",
+        "SSL_get_selected_srtp_profile",
+    ]
+
+
+def cryptography_has_get_proto_version():
+    return [
+        "SSL_CTX_get_min_proto_version",
+        "SSL_CTX_get_max_proto_version",
+        "SSL_get_min_proto_version",
+        "SSL_get_max_proto_version",
     ]
 
 
@@ -348,50 +278,26 @@
 # lists so we can use coverage to measure which are used.
 CONDITIONAL_NAMES = {
     "Cryptography_HAS_EC2M": cryptography_has_ec2m,
-    "Cryptography_HAS_EC_1_0_2": cryptography_has_ec_1_0_2,
-    "Cryptography_HAS_SET_ECDH_AUTO": cryptography_has_set_ecdh_auto,
-    "Cryptography_HAS_RSA_R_PKCS_DECODING_ERROR": (
-        cryptography_has_rsa_r_pkcs_decoding_error
-    ),
     "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_ALPN": cryptography_has_alpn,
-    "Cryptography_HAS_COMPRESSION": cryptography_has_compression,
-    "Cryptography_HAS_GET_SERVER_TMP_KEY": cryptography_has_get_server_tmp_key,
-    "Cryptography_HAS_102_VERIFICATION_ERROR_CODES": (
-        cryptography_has_102_verification_error_codes
-    ),
-    "Cryptography_HAS_102_VERIFICATION_PARAMS": (
-        cryptography_has_102_verification_params
-    ),
+    "Cryptography_HAS_102_VERIFICATION": cryptography_has_102_verification,
     "Cryptography_HAS_110_VERIFICATION_PARAMS": (
         cryptography_has_110_verification_params
     ),
-    "Cryptography_HAS_X509_V_FLAG_TRUSTED_FIRST": (
-        cryptography_has_x509_v_flag_trusted_first
-    ),
-    "Cryptography_HAS_X509_V_FLAG_PARTIAL_CHAIN": (
-        cryptography_has_x509_v_flag_partial_chain
-    ),
     "Cryptography_HAS_SET_CERT_CB": cryptography_has_set_cert_cb,
     "Cryptography_HAS_SSL_ST": cryptography_has_ssl_st,
     "Cryptography_HAS_TLS_ST": cryptography_has_tls_st,
-    "Cryptography_HAS_LOCKING_CALLBACKS": cryptography_has_locking_callbacks,
     "Cryptography_HAS_SCRYPT": cryptography_has_scrypt,
-    "Cryptography_HAS_GENERIC_DTLS_METHOD": (
-        cryptography_has_generic_dtls_method
-    ),
     "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
     ),
-    "Cryptography_HAS_X25519": cryptography_has_x25519,
-    "Cryptography_HAS_X448": cryptography_has_x448,
     "Cryptography_HAS_ED448": cryptography_has_ed448,
     "Cryptography_HAS_ED25519": cryptography_has_ed25519,
+    "Cryptography_HAS_POLY1305": cryptography_has_poly1305,
     "Cryptography_HAS_ONESHOT_EVP_DIGEST_SIGN_VERIFY": (
         cryptography_has_oneshot_evp_digest_sign_verify
     ),
@@ -403,13 +309,14 @@
     "Cryptography_HAS_PSK": cryptography_has_psk,
     "Cryptography_HAS_CUSTOM_EXT": cryptography_has_custom_ext,
     "Cryptography_HAS_OPENSSL_CLEANUP": cryptography_has_openssl_cleanup,
-    "Cryptography_HAS_CIPHER_DETAILS": cryptography_has_cipher_details,
     "Cryptography_HAS_TLSv1_3": cryptography_has_tlsv13,
+    "Cryptography_HAS_KEYLOG": cryptography_has_keylog,
     "Cryptography_HAS_RAW_KEY": cryptography_has_raw_key,
     "Cryptography_HAS_EVP_DIGESTFINAL_XOF": (
         cryptography_has_evp_digestfinal_xof
     ),
-    "Cryptography_HAS_EVP_R_MEMORY_LIMIT_EXCEEDED": (
-        cryptography_has_evp_r_memory_limit_exceeded
-    ),
+    "Cryptography_HAS_ENGINE": cryptography_has_engine,
+    "Cryptography_HAS_VERIFIED_CHAIN": cryptography_has_verified_chain,
+    "Cryptography_HAS_SRTP": cryptography_has_srtp,
+    "Cryptography_HAS_GET_PROTO_VERSION": cryptography_has_get_proto_version,
 }
diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py
index 0824ea8..7a84a34 100644
--- a/src/cryptography/hazmat/bindings/openssl/binding.py
+++ b/src/cryptography/hazmat/bindings/openssl/binding.py
@@ -7,8 +7,8 @@
 import collections
 import threading
 import types
-import warnings
 
+import cryptography
 from cryptography import utils
 from cryptography.exceptions import InternalError
 from cryptography.hazmat.bindings._openssl import ffi, lib
@@ -51,20 +51,31 @@
     return errors
 
 
-def _openssl_assert(lib, ok):
-    if not ok:
-        errors = _consume_errors(lib)
-        errors_with_text = []
-        for err in errors:
-            buf = ffi.new("char[]", 256)
-            lib.ERR_error_string_n(err.code, buf, len(buf))
-            err_text_reason = ffi.string(buf)
+def _errors_with_text(errors):
+    errors_with_text = []
+    for err in errors:
+        buf = ffi.new("char[]", 256)
+        lib.ERR_error_string_n(err.code, buf, len(buf))
+        err_text_reason = ffi.string(buf)
 
-            errors_with_text.append(
-                _OpenSSLErrorWithText(
-                    err.code, err.lib, err.func, err.reason, err_text_reason
-                )
+        errors_with_text.append(
+            _OpenSSLErrorWithText(
+                err.code, err.lib, err.func, err.reason, err_text_reason
             )
+        )
+
+    return errors_with_text
+
+
+def _consume_errors_with_text(lib):
+    return _errors_with_text(_consume_errors(lib))
+
+
+def _openssl_assert(lib, ok, errors=None):
+    if not ok:
+        if errors is None:
+            errors = _consume_errors(lib)
+        errors_with_text = _errors_with_text(errors)
 
         raise InternalError(
             "Unknown OpenSSL error. This error is commonly encountered when "
@@ -74,7 +85,7 @@
             "please file an issue at https://github.com/pyca/cryptography/"
             "issues with information on how to reproduce "
             "this. ({0!r})".format(errors_with_text),
-            errors_with_text
+            errors_with_text,
         )
 
 
@@ -97,11 +108,11 @@
     """
     OpenSSL API wrapper.
     """
+
     lib = None
     ffi = ffi
     _lib_loaded = False
     _init_lock = threading.Lock()
-    _lock_init_lock = threading.Lock()
 
     def __init__(self):
         self._ensure_ffi_initialized()
@@ -114,10 +125,9 @@
         # reliably clear the error queue. Once we clear it here we will
         # error on any subsequent unexpected item in the stack.
         cls.lib.ERR_clear_error()
-        cls._osrandom_engine_id = cls.lib.Cryptography_osrandom_engine_id
-        cls._osrandom_engine_name = cls.lib.Cryptography_osrandom_engine_name
-        result = cls.lib.Cryptography_add_osrandom_engine()
-        _openssl_assert(cls.lib, result in (1, 2))
+        if cls.lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE:
+            result = cls.lib.Cryptography_add_osrandom_engine()
+            _openssl_assert(cls.lib, result in (1, 2))
 
     @classmethod
     def _ensure_ffi_initialized(cls):
@@ -129,46 +139,34 @@
                 cls.lib.SSL_library_init()
                 # adds all ciphers/digests for EVP
                 cls.lib.OpenSSL_add_all_algorithms()
-                # loads error strings for libcrypto and libssl functions
-                cls.lib.SSL_load_error_strings()
                 cls._register_osrandom_engine()
 
     @classmethod
     def init_static_locks(cls):
-        with cls._lock_init_lock:
-            cls._ensure_ffi_initialized()
-            # Use Python's implementation if available, importing _ssl triggers
-            # the setup for this.
-            __import__("_ssl")
-
-            if (not cls.lib.Cryptography_HAS_LOCKING_CALLBACKS or
-                    cls.lib.CRYPTO_get_locking_callback() != cls.ffi.NULL):
-                return
-
-            # If nothing else has setup a locking callback already, we set up
-            # our own
-            res = lib.Cryptography_setup_ssl_threads()
-            _openssl_assert(cls.lib, res == 1)
+        cls._ensure_ffi_initialized()
 
 
-def _verify_openssl_version(lib):
-    if (
-        lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and
-        not lib.CRYPTOGRAPHY_IS_LIBRESSL
-    ):
-        warnings.warn(
-            "OpenSSL version 1.0.1 is no longer supported by the OpenSSL "
-            "project, please upgrade. A future version of cryptography will "
-            "drop support for it.",
-            utils.CryptographyDeprecationWarning
+def _verify_package_version(version):
+    # Occasionally we run into situations where the version of the Python
+    # package does not match the version of the shared object that is loaded.
+    # This may occur in environments where multiple versions of cryptography
+    # are installed and available in the python path. To avoid errors cropping
+    # up later this code checks that the currently imported package and the
+    # shared object that were loaded have the same version and raise an
+    # ImportError if they do not
+    so_package_version = ffi.string(lib.CRYPTOGRAPHY_PACKAGE_VERSION)
+    if version.encode("ascii") != so_package_version:
+        raise ImportError(
+            "The version of cryptography does not match the loaded "
+            "shared object. This can happen if you have multiple copies of "
+            "cryptography installed in your Python path. Please try creating "
+            "a new virtual environment to resolve this issue. "
+            "Loaded python version: {}, shared object version: {}".format(
+                version, so_package_version
+            )
         )
 
 
-# OpenSSL is not thread safe until the locks are initialized. We call this
-# method in module scope so that it executes with the import lock. On
-# Pythons < 3.4 this import lock is a global lock, which can prevent a race
-# condition registering the OpenSSL locks. On Python 3.4+ the import lock
-# is per module so this approach will not work.
-Binding.init_static_locks()
+_verify_package_version(cryptography.__version__)
 
-_verify_openssl_version(Binding.lib)
+Binding.init_static_locks()
diff --git a/src/cryptography/hazmat/primitives/asymmetric/dh.py b/src/cryptography/hazmat/primitives/asymmetric/dh.py
index 4fc9952..74a311d 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/dh.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/dh.py
@@ -9,9 +9,14 @@
 import six
 
 from cryptography import utils
+from cryptography.hazmat.backends import _get_backend
 
 
-def generate_parameters(generator, key_size, backend):
+_MIN_MODULUS_SIZE = 512
+
+
+def generate_parameters(generator, key_size, backend=None):
+    backend = _get_backend(backend)
     return backend.generate_dh_parameters(generator, key_size)
 
 
@@ -21,8 +26,9 @@
             raise TypeError("x must be an integer.")
 
         if not isinstance(public_numbers, DHPublicNumbers):
-            raise TypeError("public_numbers must be an instance of "
-                            "DHPublicNumbers.")
+            raise TypeError(
+                "public_numbers must be an instance of " "DHPublicNumbers."
+            )
 
         self._x = x
         self._public_numbers = public_numbers
@@ -32,14 +38,15 @@
             return NotImplemented
 
         return (
-            self._x == other._x and
-            self._public_numbers == other._public_numbers
+            self._x == other._x
+            and self._public_numbers == other._public_numbers
         )
 
     def __ne__(self, other):
         return not self == other
 
-    def private_key(self, backend):
+    def private_key(self, backend=None):
+        backend = _get_backend(backend)
         return backend.load_dh_private_numbers(self)
 
     public_numbers = utils.read_only_property("_public_numbers")
@@ -53,7 +60,8 @@
 
         if not isinstance(parameter_numbers, DHParameterNumbers):
             raise TypeError(
-                "parameters must be an instance of DHParameterNumbers.")
+                "parameters must be an instance of DHParameterNumbers."
+            )
 
         self._y = y
         self._parameter_numbers = parameter_numbers
@@ -63,14 +71,15 @@
             return NotImplemented
 
         return (
-            self._y == other._y and
-            self._parameter_numbers == other._parameter_numbers
+            self._y == other._y
+            and self._parameter_numbers == other._parameter_numbers
         )
 
     def __ne__(self, other):
         return not self == other
 
-    def public_key(self, backend):
+    def public_key(self, backend=None):
+        backend = _get_backend(backend)
         return backend.load_dh_public_numbers(self)
 
     y = utils.read_only_property("_y")
@@ -79,9 +88,8 @@
 
 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, six.integer_types) or not isinstance(
+            g, six.integer_types
         ):
             raise TypeError("p and g must be integers")
         if q is not None and not isinstance(q, six.integer_types):
@@ -90,6 +98,11 @@
         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._p = p
         self._g = g
         self._q = q
@@ -99,15 +112,14 @@
             return NotImplemented
 
         return (
-            self._p == other._p and
-            self._g == other._g and
-            self._q == other._q
+            self._p == other._p and self._g == other._g and self._q == other._q
         )
 
     def __ne__(self, other):
         return not self == other
 
-    def parameters(self, backend):
+    def parameters(self, backend=None):
+        backend = _get_backend(backend)
         return backend.load_dh_parameter_numbers(self)
 
     p = utils.read_only_property("_p")
diff --git a/src/cryptography/hazmat/primitives/asymmetric/dsa.py b/src/cryptography/hazmat/primitives/asymmetric/dsa.py
index e380a44..8ccc666 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/dsa.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/dsa.py
@@ -9,6 +9,7 @@
 import six
 
 from cryptography import utils
+from cryptography.hazmat.backends import _get_backend
 
 
 @six.add_metaclass(abc.ABCMeta)
@@ -119,17 +120,21 @@
 DSAPublicKeyWithSerialization = DSAPublicKey
 
 
-def generate_parameters(key_size, backend):
+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):
+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]:
-        raise ValueError("p must be exactly 1024, 2048, or 3072 bits long")
+    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")
 
@@ -150,9 +155,9 @@
 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, six.integer_types)
+            or not isinstance(q, six.integer_types)
+            or not isinstance(g, six.integer_types)
         ):
             raise TypeError(
                 "DSAParameterNumbers p, q, and g arguments must be integers."
@@ -166,7 +171,8 @@
     q = utils.read_only_property("_q")
     g = utils.read_only_property("_g")
 
-    def parameters(self, backend):
+    def parameters(self, backend=None):
+        backend = _get_backend(backend)
         return backend.load_dsa_parameter_numbers(self)
 
     def __eq__(self, other):
@@ -180,9 +186,8 @@
 
     def __repr__(self):
         return (
-            "<DSAParameterNumbers(p={self.p}, q={self.q}, g={self.g})>".format(
-                self=self
-            )
+            "<DSAParameterNumbers(p={self.p}, q={self.q}, "
+            "g={self.g})>".format(self=self)
         )
 
 
@@ -202,7 +207,8 @@
     y = utils.read_only_property("_y")
     parameter_numbers = utils.read_only_property("_parameter_numbers")
 
-    def public_key(self, backend):
+    def public_key(self, backend=None):
+        backend = _get_backend(backend)
         return backend.load_dsa_public_numbers(self)
 
     def __eq__(self, other):
@@ -210,8 +216,8 @@
             return NotImplemented
 
         return (
-            self.y == other.y and
-            self.parameter_numbers == other.parameter_numbers
+            self.y == other.y
+            and self.parameter_numbers == other.parameter_numbers
         )
 
     def __ne__(self, other):
@@ -239,7 +245,8 @@
     x = utils.read_only_property("_x")
     public_numbers = utils.read_only_property("_public_numbers")
 
-    def private_key(self, backend):
+    def private_key(self, backend=None):
+        backend = _get_backend(backend)
         return backend.load_dsa_private_numbers(self)
 
     def __eq__(self, other):
diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py
index 1de0976..c7e694f 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/ec.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py
@@ -11,6 +11,7 @@
 
 from cryptography import utils
 from cryptography.hazmat._oid import ObjectIdentifier
+from cryptography.hazmat.backends import _get_backend
 
 
 class EllipticCurveOID(object):
@@ -166,6 +167,7 @@
             raise ValueError("Unsupported elliptic curve point type")
 
         from cryptography.hazmat.backends.openssl.backend import backend
+
         return backend.load_elliptic_curve_public_bytes(curve, data)
 
 
@@ -289,26 +291,22 @@
 _CURVE_TYPES = {
     "prime192v1": SECP192R1,
     "prime256v1": SECP256R1,
-
     "secp192r1": SECP192R1,
     "secp224r1": SECP224R1,
     "secp256r1": SECP256R1,
     "secp384r1": SECP384R1,
     "secp521r1": SECP521R1,
     "secp256k1": SECP256K1,
-
     "sect163k1": SECT163K1,
     "sect233k1": SECT233K1,
     "sect283k1": SECT283K1,
     "sect409k1": SECT409K1,
     "sect571k1": SECT571K1,
-
     "sect163r2": SECT163R2,
     "sect233r1": SECT233R1,
     "sect283r1": SECT283R1,
     "sect409r1": SECT409R1,
     "sect571r1": SECT571R1,
-
     "brainpoolP256r1": BrainpoolP256R1,
     "brainpoolP384r1": BrainpoolP384R1,
     "brainpoolP512r1": BrainpoolP512R1,
@@ -323,11 +321,13 @@
     algorithm = utils.read_only_property("_algorithm")
 
 
-def generate_private_key(curve, backend):
+def generate_private_key(curve, backend=None):
+    backend = _get_backend(backend)
     return backend.generate_elliptic_curve_private_key(curve)
 
 
-def derive_private_key(private_value, curve, backend):
+def derive_private_key(private_value, curve, backend=None):
+    backend = _get_backend(backend)
     if not isinstance(private_value, six.integer_types):
         raise TypeError("private_value must be an integer type.")
 
@@ -342,9 +342,8 @@
 
 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, six.integer_types) or not isinstance(
+            y, six.integer_types
         ):
             raise TypeError("x and y must be integers.")
 
@@ -355,7 +354,8 @@
         self._x = x
         self._curve = curve
 
-    def public_key(self, backend):
+    def public_key(self, backend=None):
+        backend = _get_backend(backend)
         return backend.load_elliptic_curve_public_numbers(self)
 
     def encode_point(self):
@@ -364,14 +364,15 @@
             " and will be removed in a future version. Please use "
             "EllipticCurvePublicKey.public_bytes to obtain both "
             "compressed and uncompressed point encoding.",
-            utils.DeprecatedIn25,
+            utils.PersistentlyDeprecated2019,
             stacklevel=2,
         )
         # key_size is in bits. Convert to bytes and round up
         byte_length = (self.curve.key_size + 7) // 8
         return (
-            b'\x04' + utils.int_to_bytes(self.x, byte_length) +
-            utils.int_to_bytes(self.y, byte_length)
+            b"\x04"
+            + utils.int_to_bytes(self.x, byte_length)
+            + utils.int_to_bytes(self.y, byte_length)
         )
 
     @classmethod
@@ -383,21 +384,21 @@
             "Support for unsafe construction of public numbers from "
             "encoded data will be removed in a future version. "
             "Please use EllipticCurvePublicKey.from_encoded_point",
-            utils.DeprecatedIn25,
+            utils.PersistentlyDeprecated2019,
             stacklevel=2,
         )
 
-        if data.startswith(b'\x04'):
+        if data.startswith(b"\x04"):
             # 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 = utils.int_from_bytes(data[1 : byte_length + 1], "big")
+                y = utils.int_from_bytes(data[byte_length + 1 :], "big")
                 return cls(x, y, curve)
             else:
-                raise ValueError('Invalid elliptic curve point data length')
+                raise ValueError("Invalid elliptic curve point data length")
         else:
-            raise ValueError('Unsupported elliptic curve point type')
+            raise ValueError("Unsupported elliptic curve point type")
 
     curve = utils.read_only_property("_curve")
     x = utils.read_only_property("_x")
@@ -408,10 +409,10 @@
             return NotImplemented
 
         return (
-            self.x == other.x and
-            self.y == other.y and
-            self.curve.name == other.curve.name and
-            self.curve.key_size == other.curve.key_size
+            self.x == other.x
+            and self.y == other.y
+            and self.curve.name == other.curve.name
+            and self.curve.key_size == other.curve.key_size
         )
 
     def __ne__(self, other):
@@ -441,7 +442,8 @@
         self._private_value = private_value
         self._public_numbers = public_numbers
 
-    def private_key(self, backend):
+    def private_key(self, backend=None):
+        backend = _get_backend(backend)
         return backend.load_elliptic_curve_private_numbers(self)
 
     private_value = utils.read_only_property("_private_value")
@@ -452,8 +454,8 @@
             return NotImplemented
 
         return (
-            self.private_value == other.private_value and
-            self.public_numbers == other.public_numbers
+            self.private_value == other.private_value
+            and self.public_numbers == other.public_numbers
         )
 
     def __ne__(self, other):
@@ -465,3 +467,36 @@
 
 class ECDH(object):
     pass
+
+
+_OID_TO_CURVE = {
+    EllipticCurveOID.SECP192R1: SECP192R1,
+    EllipticCurveOID.SECP224R1: SECP224R1,
+    EllipticCurveOID.SECP256K1: SECP256K1,
+    EllipticCurveOID.SECP256R1: SECP256R1,
+    EllipticCurveOID.SECP384R1: SECP384R1,
+    EllipticCurveOID.SECP521R1: SECP521R1,
+    EllipticCurveOID.BRAINPOOLP256R1: BrainpoolP256R1,
+    EllipticCurveOID.BRAINPOOLP384R1: BrainpoolP384R1,
+    EllipticCurveOID.BRAINPOOLP512R1: BrainpoolP512R1,
+    EllipticCurveOID.SECT163K1: SECT163K1,
+    EllipticCurveOID.SECT163R2: SECT163R2,
+    EllipticCurveOID.SECT233K1: SECT233K1,
+    EllipticCurveOID.SECT233R1: SECT233R1,
+    EllipticCurveOID.SECT283K1: SECT283K1,
+    EllipticCurveOID.SECT283R1: SECT283R1,
+    EllipticCurveOID.SECT409K1: SECT409K1,
+    EllipticCurveOID.SECT409R1: SECT409R1,
+    EllipticCurveOID.SECT571K1: SECT571K1,
+    EllipticCurveOID.SECT571R1: SECT571R1,
+}
+
+
+def get_curve_for_oid(oid):
+    try:
+        return _OID_TO_CURVE[oid]
+    except KeyError:
+        raise LookupError(
+            "The provided object identifier has no matching elliptic "
+            "curve class"
+        )
diff --git a/src/cryptography/hazmat/primitives/asymmetric/ed25519.py b/src/cryptography/hazmat/primitives/asymmetric/ed25519.py
new file mode 100644
index 0000000..2d07a02
--- /dev/null
+++ b/src/cryptography/hazmat/primitives/asymmetric/ed25519.py
@@ -0,0 +1,87 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import abc
+
+import six
+
+from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
+
+
+_ED25519_KEY_SIZE = 32
+_ED25519_SIG_SIZE = 64
+
+
+@six.add_metaclass(abc.ABCMeta)
+class Ed25519PublicKey(object):
+    @classmethod
+    def from_public_bytes(cls, data):
+        from cryptography.hazmat.backends.openssl.backend import backend
+
+        if not backend.ed25519_supported():
+            raise UnsupportedAlgorithm(
+                "ed25519 is not supported by this version of OpenSSL.",
+                _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
+            )
+
+        return backend.ed25519_load_public_bytes(data)
+
+    @abc.abstractmethod
+    def public_bytes(self, encoding, format):
+        """
+        The serialized bytes of the public key.
+        """
+
+    @abc.abstractmethod
+    def verify(self, signature, data):
+        """
+        Verify the signature.
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class Ed25519PrivateKey(object):
+    @classmethod
+    def generate(cls):
+        from cryptography.hazmat.backends.openssl.backend import backend
+
+        if not backend.ed25519_supported():
+            raise UnsupportedAlgorithm(
+                "ed25519 is not supported by this version of OpenSSL.",
+                _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
+            )
+
+        return backend.ed25519_generate_key()
+
+    @classmethod
+    def from_private_bytes(cls, data):
+        from cryptography.hazmat.backends.openssl.backend import backend
+
+        if not backend.ed25519_supported():
+            raise UnsupportedAlgorithm(
+                "ed25519 is not supported by this version of OpenSSL.",
+                _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
+            )
+
+        return backend.ed25519_load_private_bytes(data)
+
+    @abc.abstractmethod
+    def public_key(self):
+        """
+        The Ed25519PublicKey derived from the private key.
+        """
+
+    @abc.abstractmethod
+    def private_bytes(self, encoding, format, encryption_algorithm):
+        """
+        The serialized bytes of the private key.
+        """
+
+    @abc.abstractmethod
+    def sign(self, data):
+        """
+        Signs the data.
+        """
diff --git a/src/cryptography/hazmat/primitives/asymmetric/ed448.py b/src/cryptography/hazmat/primitives/asymmetric/ed448.py
new file mode 100644
index 0000000..520ffcb
--- /dev/null
+++ b/src/cryptography/hazmat/primitives/asymmetric/ed448.py
@@ -0,0 +1,82 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import abc
+
+import six
+
+from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
+
+
+@six.add_metaclass(abc.ABCMeta)
+class Ed448PublicKey(object):
+    @classmethod
+    def from_public_bytes(cls, data):
+        from cryptography.hazmat.backends.openssl.backend import backend
+
+        if not backend.ed448_supported():
+            raise UnsupportedAlgorithm(
+                "ed448 is not supported by this version of OpenSSL.",
+                _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
+            )
+
+        return backend.ed448_load_public_bytes(data)
+
+    @abc.abstractmethod
+    def public_bytes(self, encoding, format):
+        """
+        The serialized bytes of the public key.
+        """
+
+    @abc.abstractmethod
+    def verify(self, signature, data):
+        """
+        Verify the signature.
+        """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class Ed448PrivateKey(object):
+    @classmethod
+    def generate(cls):
+        from cryptography.hazmat.backends.openssl.backend import backend
+
+        if not backend.ed448_supported():
+            raise UnsupportedAlgorithm(
+                "ed448 is not supported by this version of OpenSSL.",
+                _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
+            )
+        return backend.ed448_generate_key()
+
+    @classmethod
+    def from_private_bytes(cls, data):
+        from cryptography.hazmat.backends.openssl.backend import backend
+
+        if not backend.ed448_supported():
+            raise UnsupportedAlgorithm(
+                "ed448 is not supported by this version of OpenSSL.",
+                _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
+            )
+
+        return backend.ed448_load_private_bytes(data)
+
+    @abc.abstractmethod
+    def public_key(self):
+        """
+        The Ed448PublicKey derived from the private key.
+        """
+
+    @abc.abstractmethod
+    def sign(self, data):
+        """
+        Signs the data.
+        """
+
+    @abc.abstractmethod
+    def private_bytes(self, encoding, format, encryption_algorithm):
+        """
+        The serialized bytes of the private key.
+        """
diff --git a/src/cryptography/hazmat/primitives/asymmetric/padding.py b/src/cryptography/hazmat/primitives/asymmetric/padding.py
index a37c3f9..fc8f6e2 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/padding.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/padding.py
@@ -5,7 +5,6 @@
 from __future__ import absolute_import, division, print_function
 
 import abc
-import math
 
 import six
 
@@ -36,8 +35,10 @@
     def __init__(self, mgf, salt_length):
         self._mgf = mgf
 
-        if (not isinstance(salt_length, six.integer_types) and
-                salt_length is not self.MAX_LENGTH):
+        if (
+            not isinstance(salt_length, six.integer_types)
+            and salt_length is not self.MAX_LENGTH
+        ):
             raise TypeError("salt_length must be an integer.")
 
         if salt_length is not self.MAX_LENGTH and salt_length < 0:
@@ -73,7 +74,7 @@
     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
-    emlen = int(math.ceil((key.key_size - 1) / 8.0))
+    emlen = (key.key_size + 6) // 8
     salt_length = emlen - hash_algorithm.digest_size - 2
     assert salt_length >= 0
     return salt_length
diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py
index 27db671..ea16bbf 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py
@@ -5,6 +5,7 @@
 from __future__ import absolute_import, division, print_function
 
 import abc
+
 try:
     # Only available in math in 3.5+
     from math import gcd
@@ -15,6 +16,7 @@
 
 from cryptography import utils
 from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
+from cryptography.hazmat.backends import _get_backend
 from cryptography.hazmat.backends.interfaces import RSABackend
 
 
@@ -104,15 +106,22 @@
         Verifies the signature of the data.
         """
 
+    @abc.abstractmethod
+    def recover_data_from_signature(self, signature, padding, algorithm):
+        """
+        Recovers the original data from the signature.
+        """
+
 
 RSAPublicKeyWithSerialization = RSAPublicKey
 
 
-def generate_private_key(public_exponent, key_size, backend):
+def generate_private_key(public_exponent, key_size, backend=None):
+    backend = _get_backend(backend)
     if not isinstance(backend, RSABackend):
         raise UnsupportedAlgorithm(
             "Backend object does not implement RSABackend.",
-            _Reasons.BACKEND_MISSING_INTERFACE
+            _Reasons.BACKEND_MISSING_INTERFACE,
         )
 
     _verify_rsa_parameters(public_exponent, key_size)
@@ -120,18 +129,19 @@
 
 
 def _verify_rsa_parameters(public_exponent, key_size):
-    if public_exponent < 3:
-        raise ValueError("public_exponent must be >= 3.")
-
-    if public_exponent & 1 == 0:
-        raise ValueError("public_exponent must be odd.")
+    if public_exponent not in (3, 65537):
+        raise ValueError(
+            "public_exponent must be either 3 (for legacy compatibility) or "
+            "65537. Almost everyone should choose 65537 here!"
+        )
 
     if key_size < 512:
         raise ValueError("key_size must be at least 512-bits.")
 
 
-def _check_private_key_components(p, q, private_exponent, dmp1, dmq1, iqmp,
-                                  public_exponent, modulus):
+def _check_private_key_components(
+    p, q, private_exponent, dmp1, dmq1, iqmp, public_exponent, modulus
+):
     if modulus < 3:
         raise ValueError("modulus must be >= 3.")
 
@@ -184,12 +194,12 @@
     """
     Modular Multiplicative Inverse. Returns x such that: (x*e) mod m == 1
     """
-    x1, y1, x2, y2 = 1, 0, 0, 1
+    x1, x2 = 1, 0
     a, b = e, m
     while b > 0:
         q, r = divmod(a, b)
-        xn, yn = x1 - q * x2, y1 - q * y2
-        a, b, x1, y1, x2, y2 = b, r, x2, y2, xn, yn
+        xn = x1 - q * x2
+        a, b, x1, x2 = b, r, x2, xn
     return x1 % m
 
 
@@ -266,15 +276,14 @@
 
 
 class RSAPrivateNumbers(object):
-    def __init__(self, p, q, d, dmp1, dmq1, iqmp,
-                 public_numbers):
+    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, 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)
         ):
             raise TypeError(
                 "RSAPrivateNumbers p, q, d, dmp1, dmq1, iqmp arguments must"
@@ -303,7 +312,8 @@
     iqmp = utils.read_only_property("_iqmp")
     public_numbers = utils.read_only_property("_public_numbers")
 
-    def private_key(self, backend):
+    def private_key(self, backend=None):
+        backend = _get_backend(backend)
         return backend.load_rsa_private_numbers(self)
 
     def __eq__(self, other):
@@ -311,35 +321,36 @@
             return NotImplemented
 
         return (
-            self.p == other.p and
-            self.q == other.q and
-            self.d == other.d and
-            self.dmp1 == other.dmp1 and
-            self.dmq1 == other.dmq1 and
-            self.iqmp == other.iqmp and
-            self.public_numbers == other.public_numbers
+            self.p == other.p
+            and self.q == other.q
+            and self.d == other.d
+            and self.dmp1 == other.dmp1
+            and self.dmq1 == other.dmq1
+            and self.iqmp == other.iqmp
+            and self.public_numbers == other.public_numbers
         )
 
     def __ne__(self, other):
         return not self == other
 
     def __hash__(self):
-        return hash((
-            self.p,
-            self.q,
-            self.d,
-            self.dmp1,
-            self.dmq1,
-            self.iqmp,
-            self.public_numbers,
-        ))
+        return hash(
+            (
+                self.p,
+                self.q,
+                self.d,
+                self.dmp1,
+                self.dmq1,
+                self.iqmp,
+                self.public_numbers,
+            )
+        )
 
 
 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, six.integer_types) or not isinstance(
+            n, six.integer_types
         ):
             raise TypeError("RSAPublicNumbers arguments must be integers.")
 
@@ -349,7 +360,8 @@
     e = utils.read_only_property("_e")
     n = utils.read_only_property("_n")
 
-    def public_key(self, backend):
+    def public_key(self, backend=None):
+        backend = _get_backend(backend)
         return backend.load_rsa_public_numbers(self)
 
     def __repr__(self):
diff --git a/src/cryptography/hazmat/primitives/asymmetric/utils.py b/src/cryptography/hazmat/primitives/asymmetric/utils.py
index ef1e7eb..5f9b677 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/utils.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/utils.py
@@ -4,49 +4,30 @@
 
 from __future__ import absolute_import, division, print_function
 
-import warnings
-
-from asn1crypto.algos import DSASignature
-
-import six
-
 from cryptography import utils
+from cryptography.hazmat._der import (
+    DERReader,
+    INTEGER,
+    SEQUENCE,
+    encode_der,
+    encode_der_integer,
+)
 from cryptography.hazmat.primitives import hashes
 
 
-def decode_rfc6979_signature(signature):
-    warnings.warn(
-        "decode_rfc6979_signature is deprecated and will "
-        "be removed in a future version, use decode_dss_signature instead.",
-        utils.PersistentlyDeprecated,
-        stacklevel=2
-    )
-    return decode_dss_signature(signature)
-
-
 def decode_dss_signature(signature):
-    data = DSASignature.load(signature, strict=True).native
-    return data['r'], data['s']
-
-
-def encode_rfc6979_signature(r, s):
-    warnings.warn(
-        "encode_rfc6979_signature is deprecated and will "
-        "be removed in a future version, use encode_dss_signature instead.",
-        utils.PersistentlyDeprecated,
-        stacklevel=2
-    )
-    return encode_dss_signature(r, s)
+    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):
-    if (
-        not isinstance(r, six.integer_types) or
-        not isinstance(s, six.integer_types)
-    ):
-        raise ValueError("Both r and s must be integers")
-
-    return DSASignature({'r': r, 's': s}).dump()
+    return encode_der(
+        SEQUENCE,
+        encode_der(INTEGER, encode_der_integer(r)),
+        encode_der(INTEGER, encode_der_integer(s)),
+    )
 
 
 class Prehashed(object):
diff --git a/src/cryptography/hazmat/primitives/asymmetric/x25519.py b/src/cryptography/hazmat/primitives/asymmetric/x25519.py
index 4e8badf..fc63691 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/x25519.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/x25519.py
@@ -16,16 +16,17 @@
     @classmethod
     def from_public_bytes(cls, data):
         from cryptography.hazmat.backends.openssl.backend import backend
+
         if not backend.x25519_supported():
             raise UnsupportedAlgorithm(
                 "X25519 is not supported by this version of OpenSSL.",
-                _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM
+                _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
             )
 
         return backend.x25519_load_public_bytes(data)
 
     @abc.abstractmethod
-    def public_bytes(self, encoding=None, format=None):
+    def public_bytes(self, encoding, format):
         """
         The serialized bytes of the public key.
         """
@@ -36,20 +37,22 @@
     @classmethod
     def generate(cls):
         from cryptography.hazmat.backends.openssl.backend import backend
+
         if not backend.x25519_supported():
             raise UnsupportedAlgorithm(
                 "X25519 is not supported by this version of OpenSSL.",
-                _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM
+                _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
             )
         return backend.x25519_generate_key()
 
     @classmethod
     def from_private_bytes(cls, data):
         from cryptography.hazmat.backends.openssl.backend import backend
+
         if not backend.x25519_supported():
             raise UnsupportedAlgorithm(
                 "X25519 is not supported by this version of OpenSSL.",
-                _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM
+                _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
             )
 
         return backend.x25519_load_private_bytes(data)
diff --git a/src/cryptography/hazmat/primitives/asymmetric/x448.py b/src/cryptography/hazmat/primitives/asymmetric/x448.py
index 475e678..3ac067b 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/x448.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/x448.py
@@ -16,10 +16,11 @@
     @classmethod
     def from_public_bytes(cls, data):
         from cryptography.hazmat.backends.openssl.backend import backend
+
         if not backend.x448_supported():
             raise UnsupportedAlgorithm(
                 "X448 is not supported by this version of OpenSSL.",
-                _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM
+                _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
             )
 
         return backend.x448_load_public_bytes(data)
@@ -36,20 +37,22 @@
     @classmethod
     def generate(cls):
         from cryptography.hazmat.backends.openssl.backend import backend
+
         if not backend.x448_supported():
             raise UnsupportedAlgorithm(
                 "X448 is not supported by this version of OpenSSL.",
-                _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM
+                _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
             )
         return backend.x448_generate_key()
 
     @classmethod
     def from_private_bytes(cls, data):
         from cryptography.hazmat.backends.openssl.backend import backend
+
         if not backend.x448_supported():
             raise UnsupportedAlgorithm(
                 "X448 is not supported by this version of OpenSSL.",
-                _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM
+                _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
             )
 
         return backend.x448_load_private_bytes(data)
diff --git a/src/cryptography/hazmat/primitives/ciphers/__init__.py b/src/cryptography/hazmat/primitives/ciphers/__init__.py
index 171b1c6..4380f72 100644
--- a/src/cryptography/hazmat/primitives/ciphers/__init__.py
+++ b/src/cryptography/hazmat/primitives/ciphers/__init__.py
@@ -5,8 +5,13 @@
 from __future__ import absolute_import, division, print_function
 
 from cryptography.hazmat.primitives.ciphers.base import (
-    AEADCipherContext, AEADDecryptionContext, AEADEncryptionContext,
-    BlockCipherAlgorithm, Cipher, CipherAlgorithm, CipherContext
+    AEADCipherContext,
+    AEADDecryptionContext,
+    AEADEncryptionContext,
+    BlockCipherAlgorithm,
+    Cipher,
+    CipherAlgorithm,
+    CipherContext,
 )
 
 
diff --git a/src/cryptography/hazmat/primitives/ciphers/aead.py b/src/cryptography/hazmat/primitives/ciphers/aead.py
index 42e19ad..c8c9395 100644
--- a/src/cryptography/hazmat/primitives/ciphers/aead.py
+++ b/src/cryptography/hazmat/primitives/ciphers/aead.py
@@ -18,7 +18,7 @@
         if not backend.aead_cipher_supported(self):
             raise exceptions.UnsupportedAlgorithm(
                 "ChaCha20Poly1305 is not supported by this version of OpenSSL",
-                exceptions._Reasons.UNSUPPORTED_CIPHER
+                exceptions._Reasons.UNSUPPORTED_CIPHER,
             )
         utils._check_byteslike("key", key)
 
@@ -42,18 +42,14 @@
             )
 
         self._check_params(nonce, data, associated_data)
-        return aead._encrypt(
-            backend, self, nonce, data, associated_data, 16
-        )
+        return aead._encrypt(backend, self, nonce, data, associated_data, 16)
 
     def decrypt(self, nonce, data, associated_data):
         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
-        )
+        return aead._decrypt(backend, self, nonce, data, associated_data, 16)
 
     def _check_params(self, nonce, data, associated_data):
         utils._check_byteslike("nonce", nonce)
@@ -80,12 +76,6 @@
 
         self._tag_length = tag_length
 
-        if not backend.aead_cipher_supported(self):
-            raise exceptions.UnsupportedAlgorithm(
-                "AESCCM is not supported by this version of OpenSSL",
-                exceptions._Reasons.UNSUPPORTED_CIPHER
-            )
-
     @classmethod
     def generate_key(cls, bit_length):
         if not isinstance(bit_length, int):
@@ -126,7 +116,7 @@
         # https://tools.ietf.org/html/rfc3610#section-2.1
         l_val = 15 - len(nonce)
         if 2 ** (8 * l_val) < data_len:
-            raise ValueError("Nonce too long for data")
+            raise ValueError("Data too long for nonce")
 
     def _check_params(self, nonce, data, associated_data):
         utils._check_byteslike("nonce", nonce)
@@ -167,22 +157,18 @@
             )
 
         self._check_params(nonce, data, associated_data)
-        return aead._encrypt(
-            backend, self, nonce, data, associated_data, 16
-        )
+        return aead._encrypt(backend, self, nonce, data, associated_data, 16)
 
     def decrypt(self, nonce, data, associated_data):
         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
-        )
+        return aead._decrypt(backend, self, nonce, data, associated_data, 16)
 
     def _check_params(self, nonce, data, associated_data):
         utils._check_byteslike("nonce", nonce)
         utils._check_bytes("data", data)
         utils._check_bytes("associated_data", associated_data)
-        if len(nonce) == 0:
-            raise ValueError("Nonce must be at least 1 byte")
+        if len(nonce) < 8 or len(nonce) > 128:
+            raise ValueError("Nonce must be between 8 and 128 bytes")
diff --git a/src/cryptography/hazmat/primitives/ciphers/algorithms.py b/src/cryptography/hazmat/primitives/ciphers/algorithms.py
index 1f49fd9..8072ced 100644
--- a/src/cryptography/hazmat/primitives/ciphers/algorithms.py
+++ b/src/cryptography/hazmat/primitives/ciphers/algorithms.py
@@ -6,7 +6,8 @@
 
 from cryptography import utils
 from cryptography.hazmat.primitives.ciphers import (
-    BlockCipherAlgorithm, CipherAlgorithm
+    BlockCipherAlgorithm,
+    CipherAlgorithm,
 )
 from cryptography.hazmat.primitives.ciphers.modes import ModeWithNonce
 
@@ -17,9 +18,11 @@
 
     # Verify that the key size matches the expected key size
     if len(key) * 8 not in algorithm.key_sizes:
-        raise ValueError("Invalid key size ({0}) for {1}.".format(
-            len(key) * 8, algorithm.name
-        ))
+        raise ValueError(
+            "Invalid key size ({}) for {}.".format(
+                len(key) * 8, algorithm.name
+            )
+        )
     return key
 
 
diff --git a/src/cryptography/hazmat/primitives/ciphers/base.py b/src/cryptography/hazmat/primitives/ciphers/base.py
index f857041..dae425a 100644
--- a/src/cryptography/hazmat/primitives/ciphers/base.py
+++ b/src/cryptography/hazmat/primitives/ciphers/base.py
@@ -10,9 +10,13 @@
 
 from cryptography import utils
 from cryptography.exceptions import (
-    AlreadyFinalized, AlreadyUpdated, NotYetFinalized, UnsupportedAlgorithm,
-    _Reasons
+    AlreadyFinalized,
+    AlreadyUpdated,
+    NotYetFinalized,
+    UnsupportedAlgorithm,
+    _Reasons,
 )
+from cryptography.hazmat.backends import _get_backend
 from cryptography.hazmat.backends.interfaces import CipherBackend
 from cryptography.hazmat.primitives.ciphers import modes
 
@@ -94,11 +98,12 @@
 
 
 class Cipher(object):
-    def __init__(self, algorithm, mode, backend):
+    def __init__(self, algorithm, mode, backend=None):
+        backend = _get_backend(backend)
         if not isinstance(backend, CipherBackend):
             raise UnsupportedAlgorithm(
                 "Backend object does not implement CipherBackend.",
-                _Reasons.BACKEND_MISSING_INTERFACE
+                _Reasons.BACKEND_MISSING_INTERFACE,
             )
 
         if not isinstance(algorithm, CipherAlgorithm):
@@ -179,7 +184,7 @@
         self._bytes_processed += data_size
         if self._bytes_processed > self._ctx._mode._MAX_ENCRYPTED_BYTES:
             raise ValueError(
-                "{0} has a maximum encrypted byte limit of {1}".format(
+                "{} has a maximum encrypted byte limit of {}".format(
                     self._ctx._mode.name, self._ctx._mode._MAX_ENCRYPTED_BYTES
                 )
             )
@@ -217,7 +222,7 @@
         self._aad_bytes_processed += len(data)
         if self._aad_bytes_processed > self._ctx._mode._MAX_AAD_BYTES:
             raise ValueError(
-                "{0} has a maximum AAD byte limit of {1}".format(
+                "{} has a maximum AAD byte limit of {}".format(
                     self._ctx._mode.name, self._ctx._mode._MAX_AAD_BYTES
                 )
             )
@@ -230,6 +235,7 @@
     @property
     def tag(self):
         if self._ctx is not None:
-            raise NotYetFinalized("You must finalize encryption before "
-                                  "getting the tag.")
+            raise NotYetFinalized(
+                "You must finalize encryption before " "getting the tag."
+            )
         return self._tag
diff --git a/src/cryptography/hazmat/primitives/ciphers/modes.py b/src/cryptography/hazmat/primitives/ciphers/modes.py
index ad91a6e..0ba0f2b 100644
--- a/src/cryptography/hazmat/primitives/ciphers/modes.py
+++ b/src/cryptography/hazmat/primitives/ciphers/modes.py
@@ -72,9 +72,11 @@
 
 def _check_iv_length(self, algorithm):
     if len(self.initialization_vector) * 8 != algorithm.block_size:
-        raise ValueError("Invalid IV size ({0}) for {1}.".format(
-            len(self.initialization_vector), self.name
-        ))
+        raise ValueError(
+            "Invalid IV size ({}) for {}.".format(
+                len(self.initialization_vector), self.name
+            )
+        )
 
 
 def _check_iv_and_key_length(self, algorithm):
@@ -178,9 +180,11 @@
     def validate_for_algorithm(self, algorithm):
         _check_aes_key_length(self, algorithm)
         if len(self.nonce) * 8 != algorithm.block_size:
-            raise ValueError("Invalid nonce size ({0}) for {1}.".format(
-                len(self.nonce), self.name
-            ))
+            raise ValueError(
+                "Invalid nonce size ({}) for {}.".format(
+                    len(self.nonce), self.name
+                )
+            )
 
 
 @utils.register_interface(Mode)
@@ -192,12 +196,14 @@
     _MAX_AAD_BYTES = (2 ** 64) // 8
 
     def __init__(self, initialization_vector, tag=None, min_tag_length=16):
-        # len(initialization_vector) must in [1, 2 ** 64), but it's impossible
-        # to actually construct a bytes object that large, so we don't check
-        # for it
+        # 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)
-        if len(initialization_vector) == 0:
-            raise ValueError("initialization_vector must be at least 1 byte")
+        if len(initialization_vector) < 8 or len(initialization_vector) > 128:
+            raise ValueError(
+                "initialization_vector must be between 8 and 128 bytes (64 "
+                "and 1024 bits)."
+            )
         self._initialization_vector = initialization_vector
         if tag is not None:
             utils._check_bytes("tag", tag)
@@ -205,8 +211,9 @@
                 raise ValueError("min_tag_length must be >= 4")
             if len(tag) < min_tag_length:
                 raise ValueError(
-                    "Authentication tag must be {0} bytes or longer.".format(
-                        min_tag_length)
+                    "Authentication tag must be {} bytes or longer.".format(
+                        min_tag_length
+                    )
                 )
         self._tag = tag
         self._min_tag_length = min_tag_length
diff --git a/src/cryptography/hazmat/primitives/cmac.py b/src/cryptography/hazmat/primitives/cmac.py
index 1404eac..bf962c9 100644
--- a/src/cryptography/hazmat/primitives/cmac.py
+++ b/src/cryptography/hazmat/primitives/cmac.py
@@ -6,25 +6,26 @@
 
 from cryptography import utils
 from cryptography.exceptions import (
-    AlreadyFinalized, UnsupportedAlgorithm, _Reasons
+    AlreadyFinalized,
+    UnsupportedAlgorithm,
+    _Reasons,
 )
+from cryptography.hazmat.backends import _get_backend
 from cryptography.hazmat.backends.interfaces import CMACBackend
-from cryptography.hazmat.primitives import ciphers, mac
+from cryptography.hazmat.primitives import ciphers
 
 
-@utils.register_interface(mac.MACContext)
 class CMAC(object):
-    def __init__(self, algorithm, backend, ctx=None):
+    def __init__(self, algorithm, backend=None, ctx=None):
+        backend = _get_backend(backend)
         if not isinstance(backend, CMACBackend):
             raise UnsupportedAlgorithm(
                 "Backend object does not implement CMACBackend.",
-                _Reasons.BACKEND_MISSING_INTERFACE
+                _Reasons.BACKEND_MISSING_INTERFACE,
             )
 
         if not isinstance(algorithm, ciphers.BlockCipherAlgorithm):
-            raise TypeError(
-                "Expected instance of BlockCipherAlgorithm."
-            )
+            raise TypeError("Expected instance of BlockCipherAlgorithm.")
         self._algorithm = algorithm
 
         self._backend = backend
@@ -59,7 +60,5 @@
         if self._ctx is None:
             raise AlreadyFinalized("Context was already finalized.")
         return CMAC(
-            self._algorithm,
-            backend=self._backend,
-            ctx=self._ctx.copy()
+            self._algorithm, backend=self._backend, ctx=self._ctx.copy()
         )
diff --git a/src/cryptography/hazmat/primitives/constant_time.py b/src/cryptography/hazmat/primitives/constant_time.py
index 0e987ea..7f41b9e 100644
--- a/src/cryptography/hazmat/primitives/constant_time.py
+++ b/src/cryptography/hazmat/primitives/constant_time.py
@@ -5,31 +5,10 @@
 from __future__ import absolute_import, division, print_function
 
 import hmac
-import warnings
-
-from cryptography import utils
-from cryptography.hazmat.bindings._constant_time import lib
 
 
-if hasattr(hmac, "compare_digest"):
-    def bytes_eq(a, b):
-        if not isinstance(a, bytes) or not isinstance(b, bytes):
-            raise TypeError("a and b must be bytes.")
+def bytes_eq(a, b):
+    if not isinstance(a, bytes) or not isinstance(b, bytes):
+        raise TypeError("a and b must be bytes.")
 
-        return hmac.compare_digest(a, b)
-
-else:
-    warnings.warn(
-        "Support for your Python version is deprecated. The next version of "
-        "cryptography will remove support. Please upgrade to a 2.7.x "
-        "release that supports hmac.compare_digest as soon as possible.",
-        utils.DeprecatedIn23,
-    )
-
-    def bytes_eq(a, b):
-        if not isinstance(a, bytes) or not isinstance(b, bytes):
-            raise TypeError("a and b must be bytes.")
-
-        return lib.Cryptography_constant_time_bytes_eq(
-            a, len(a), b, len(b)
-        ) == 1
+    return hmac.compare_digest(a, b)
diff --git a/src/cryptography/hazmat/primitives/hashes.py b/src/cryptography/hazmat/primitives/hashes.py
index 9be2b60..18e2bab 100644
--- a/src/cryptography/hazmat/primitives/hashes.py
+++ b/src/cryptography/hazmat/primitives/hashes.py
@@ -10,8 +10,11 @@
 
 from cryptography import utils
 from cryptography.exceptions import (
-    AlreadyFinalized, UnsupportedAlgorithm, _Reasons
+    AlreadyFinalized,
+    UnsupportedAlgorithm,
+    _Reasons,
 )
+from cryptography.hazmat.backends import _get_backend
 from cryptography.hazmat.backends.interfaces import HashBackend
 
 
@@ -66,11 +69,12 @@
 
 @utils.register_interface(HashContext)
 class Hash(object):
-    def __init__(self, algorithm, backend, ctx=None):
+    def __init__(self, algorithm, backend=None, ctx=None):
+        backend = _get_backend(backend)
         if not isinstance(backend, HashBackend):
             raise UnsupportedAlgorithm(
                 "Backend object does not implement HashBackend.",
-                _Reasons.BACKEND_MISSING_INTERFACE
+                _Reasons.BACKEND_MISSING_INTERFACE,
             )
 
         if not isinstance(algorithm, HashAlgorithm):
diff --git a/src/cryptography/hazmat/primitives/hmac.py b/src/cryptography/hazmat/primitives/hmac.py
index f7f401d..8c421dc 100644
--- a/src/cryptography/hazmat/primitives/hmac.py
+++ b/src/cryptography/hazmat/primitives/hmac.py
@@ -6,20 +6,23 @@
 
 from cryptography import utils
 from cryptography.exceptions import (
-    AlreadyFinalized, UnsupportedAlgorithm, _Reasons
+    AlreadyFinalized,
+    UnsupportedAlgorithm,
+    _Reasons,
 )
+from cryptography.hazmat.backends import _get_backend
 from cryptography.hazmat.backends.interfaces import HMACBackend
-from cryptography.hazmat.primitives import hashes, mac
+from cryptography.hazmat.primitives import hashes
 
 
-@utils.register_interface(mac.MACContext)
 @utils.register_interface(hashes.HashContext)
 class HMAC(object):
-    def __init__(self, key, algorithm, backend, ctx=None):
+    def __init__(self, key, algorithm, backend=None, ctx=None):
+        backend = _get_backend(backend)
         if not isinstance(backend, HMACBackend):
             raise UnsupportedAlgorithm(
                 "Backend object does not implement HMACBackend.",
-                _Reasons.BACKEND_MISSING_INTERFACE
+                _Reasons.BACKEND_MISSING_INTERFACE,
             )
 
         if not isinstance(algorithm, hashes.HashAlgorithm):
@@ -48,7 +51,7 @@
             self._key,
             self.algorithm,
             backend=self._backend,
-            ctx=self._ctx.copy()
+            ctx=self._ctx.copy(),
         )
 
     def finalize(self):
diff --git a/src/cryptography/hazmat/primitives/kdf/concatkdf.py b/src/cryptography/hazmat/primitives/kdf/concatkdf.py
index 65b25cd..7cc0324 100644
--- a/src/cryptography/hazmat/primitives/kdf/concatkdf.py
+++ b/src/cryptography/hazmat/primitives/kdf/concatkdf.py
@@ -8,8 +8,12 @@
 
 from cryptography import utils
 from cryptography.exceptions import (
-    AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons
+    AlreadyFinalized,
+    InvalidKey,
+    UnsupportedAlgorithm,
+    _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.primitives import constant_time, hashes, hmac
@@ -17,16 +21,15 @@
 
 
 def _int_to_u32be(n):
-    return struct.pack('>I', n)
+    return struct.pack(">I", n)
 
 
 def _common_args_checks(algorithm, length, otherinfo):
     max_length = algorithm.digest_size * (2 ** 32 - 1)
     if length > max_length:
         raise ValueError(
-            "Can not derive keys larger than {0} bits.".format(
-                max_length
-            ))
+            "Can not derive keys larger than {} bits.".format(max_length)
+        )
     if otherinfo is not None:
         utils._check_bytes("otherinfo", otherinfo)
 
@@ -37,7 +40,7 @@
     outlen = 0
     counter = 1
 
-    while (length > outlen):
+    while length > outlen:
         h = auxfn()
         h.update(_int_to_u32be(counter))
         h.update(key_material)
@@ -51,7 +54,8 @@
 
 @utils.register_interface(KeyDerivationFunction)
 class ConcatKDFHash(object):
-    def __init__(self, algorithm, length, otherinfo, backend):
+    def __init__(self, algorithm, length, otherinfo, backend=None):
+        backend = _get_backend(backend)
 
         _common_args_checks(algorithm, length, otherinfo)
         self._algorithm = algorithm
@@ -63,7 +67,7 @@
         if not isinstance(backend, HashBackend):
             raise UnsupportedAlgorithm(
                 "Backend object does not implement HashBackend.",
-                _Reasons.BACKEND_MISSING_INTERFACE
+                _Reasons.BACKEND_MISSING_INTERFACE,
             )
         self._backend = backend
         self._used = False
@@ -75,8 +79,9 @@
         if self._used:
             raise AlreadyFinalized
         self._used = True
-        return _concatkdf_derive(key_material, self._length,
-                                 self._hash, self._otherinfo)
+        return _concatkdf_derive(
+            key_material, self._length, self._hash, self._otherinfo
+        )
 
     def verify(self, key_material, expected_key):
         if not constant_time.bytes_eq(self.derive(key_material), expected_key):
@@ -85,7 +90,8 @@
 
 @utils.register_interface(KeyDerivationFunction)
 class ConcatKDFHMAC(object):
-    def __init__(self, algorithm, length, salt, otherinfo, backend):
+    def __init__(self, algorithm, length, salt, otherinfo, backend=None):
+        backend = _get_backend(backend)
 
         _common_args_checks(algorithm, length, otherinfo)
         self._algorithm = algorithm
@@ -104,7 +110,7 @@
         if not isinstance(backend, HMACBackend):
             raise UnsupportedAlgorithm(
                 "Backend object does not implement HMACBackend.",
-                _Reasons.BACKEND_MISSING_INTERFACE
+                _Reasons.BACKEND_MISSING_INTERFACE,
             )
         self._backend = backend
         self._used = False
@@ -116,8 +122,9 @@
         if self._used:
             raise AlreadyFinalized
         self._used = True
-        return _concatkdf_derive(key_material, self._length,
-                                 self._hmac, self._otherinfo)
+        return _concatkdf_derive(
+            key_material, self._length, self._hmac, self._otherinfo
+        )
 
     def verify(self, key_material, expected_key):
         if not constant_time.bytes_eq(self.derive(key_material), expected_key):
diff --git a/src/cryptography/hazmat/primitives/kdf/hkdf.py b/src/cryptography/hazmat/primitives/kdf/hkdf.py
index 307f91c..9bb6bc2 100644
--- a/src/cryptography/hazmat/primitives/kdf/hkdf.py
+++ b/src/cryptography/hazmat/primitives/kdf/hkdf.py
@@ -8,8 +8,12 @@
 
 from cryptography import utils
 from cryptography.exceptions import (
-    AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons
+    AlreadyFinalized,
+    InvalidKey,
+    UnsupportedAlgorithm,
+    _Reasons,
 )
+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.kdf import KeyDerivationFunction
@@ -17,11 +21,12 @@
 
 @utils.register_interface(KeyDerivationFunction)
 class HKDF(object):
-    def __init__(self, algorithm, length, salt, info, backend):
+    def __init__(self, algorithm, length, salt, info, backend=None):
+        backend = _get_backend(backend)
         if not isinstance(backend, HMACBackend):
             raise UnsupportedAlgorithm(
                 "Backend object does not implement HMACBackend.",
-                _Reasons.BACKEND_MISSING_INTERFACE
+                _Reasons.BACKEND_MISSING_INTERFACE,
             )
 
         self._algorithm = algorithm
@@ -53,11 +58,12 @@
 
 @utils.register_interface(KeyDerivationFunction)
 class HKDFExpand(object):
-    def __init__(self, algorithm, length, info, backend):
+    def __init__(self, algorithm, length, info, backend=None):
+        backend = _get_backend(backend)
         if not isinstance(backend, HMACBackend):
             raise UnsupportedAlgorithm(
                 "Backend object does not implement HMACBackend.",
-                _Reasons.BACKEND_MISSING_INTERFACE
+                _Reasons.BACKEND_MISSING_INTERFACE,
             )
 
         self._algorithm = algorithm
@@ -68,9 +74,8 @@
 
         if length > max_length:
             raise ValueError(
-                "Can not derive keys larger than {0} octets.".format(
-                    max_length
-                ))
+                "Can not derive keys larger than {} octets.".format(max_length)
+            )
 
         self._length = length
 
@@ -95,7 +100,7 @@
             output.append(h.finalize())
             counter += 1
 
-        return b"".join(output)[:self._length]
+        return b"".join(output)[: self._length]
 
     def derive(self, key_material):
         utils._check_byteslike("key_material", key_material)
diff --git a/src/cryptography/hazmat/primitives/kdf/kbkdf.py b/src/cryptography/hazmat/primitives/kdf/kbkdf.py
index 56783a8..8643370 100644
--- a/src/cryptography/hazmat/primitives/kdf/kbkdf.py
+++ b/src/cryptography/hazmat/primitives/kdf/kbkdf.py
@@ -10,8 +10,12 @@
 
 from cryptography import utils
 from cryptography.exceptions import (
-    AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons
+    AlreadyFinalized,
+    InvalidKey,
+    UnsupportedAlgorithm,
+    _Reasons,
 )
+from cryptography.hazmat.backends import _get_backend
 from cryptography.hazmat.backends.interfaces import HMACBackend
 from cryptography.hazmat.primitives import constant_time, hashes, hmac
 from cryptography.hazmat.primitives.kdf import KeyDerivationFunction
@@ -28,24 +32,36 @@
 
 @utils.register_interface(KeyDerivationFunction)
 class KBKDFHMAC(object):
-    def __init__(self, algorithm, mode, length, rlen, llen,
-                 location, label, context, fixed, backend):
+    def __init__(
+        self,
+        algorithm,
+        mode,
+        length,
+        rlen,
+        llen,
+        location,
+        label,
+        context,
+        fixed,
+        backend=None,
+    ):
+        backend = _get_backend(backend)
         if not isinstance(backend, HMACBackend):
             raise UnsupportedAlgorithm(
                 "Backend object does not implement HMACBackend.",
-                _Reasons.BACKEND_MISSING_INTERFACE
+                _Reasons.BACKEND_MISSING_INTERFACE,
             )
 
         if not isinstance(algorithm, hashes.HashAlgorithm):
             raise UnsupportedAlgorithm(
                 "Algorithm supplied is not a supported hash algorithm.",
-                _Reasons.UNSUPPORTED_HASH
+                _Reasons.UNSUPPORTED_HASH,
             )
 
         if not backend.hmac_supported(algorithm):
             raise UnsupportedAlgorithm(
                 "Algorithm supplied is not a supported hmac algorithm.",
-                _Reasons.UNSUPPORTED_HASH
+                _Reasons.UNSUPPORTED_HASH,
             )
 
         if not isinstance(mode, Mode):
@@ -55,8 +71,9 @@
             raise TypeError("location must be of type CounterLocation")
 
         if (label or context) and fixed:
-            raise ValueError("When supplying fixed data, "
-                             "label and context are ignored.")
+            raise ValueError(
+                "When supplying fixed data, " "label and context are ignored."
+            )
 
         if rlen is None or not self._valid_byte_length(rlen):
             raise ValueError("rlen must be between 1 and 4")
@@ -68,10 +85,10 @@
             raise TypeError("llen must be an integer")
 
         if label is None:
-            label = b''
+            label = b""
 
         if context is None:
-            context = b''
+            context = b""
 
         utils._check_bytes("label", label)
         utils._check_bytes("context", context)
@@ -89,7 +106,7 @@
 
     def _valid_byte_length(self, value):
         if not isinstance(value, int):
-            raise TypeError('value must be of type int')
+            raise TypeError("value must be of type int")
 
         value_bin = utils.int_to_bytes(1, value)
         if not 1 <= len(value_bin) <= 4:
@@ -106,7 +123,7 @@
         # inverse floor division (equivalent to ceiling)
         rounds = -(-self._length // self._algorithm.digest_size)
 
-        output = [b'']
+        output = [b""]
 
         # For counter mode, the number of iterations shall not be
         # larger than 2^r-1, where r <= 32 is the binary length of the counter
@@ -114,7 +131,7 @@
         # PRF will not repeat during a particular call to the KDF function.
         r_bin = utils.int_to_bytes(1, self._rlen)
         if rounds > pow(2, len(r_bin) * 8) - 1:
-            raise ValueError('There are too many iterations.')
+            raise ValueError("There are too many iterations.")
 
         for i in range(1, rounds + 1):
             h = hmac.HMAC(key_material, self._algorithm, backend=self._backend)
@@ -130,7 +147,7 @@
 
             output.append(h.finalize())
 
-        return b''.join(output)[:self._length]
+        return b"".join(output)[: self._length]
 
     def _generate_fixed_input(self):
         if self._fixed_data and isinstance(self._fixed_data, bytes):
diff --git a/src/cryptography/hazmat/primitives/kdf/pbkdf2.py b/src/cryptography/hazmat/primitives/kdf/pbkdf2.py
index a47b7bb..5b67d48 100644
--- a/src/cryptography/hazmat/primitives/kdf/pbkdf2.py
+++ b/src/cryptography/hazmat/primitives/kdf/pbkdf2.py
@@ -6,8 +6,12 @@
 
 from cryptography import utils
 from cryptography.exceptions import (
-    AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons
+    AlreadyFinalized,
+    InvalidKey,
+    UnsupportedAlgorithm,
+    _Reasons,
 )
+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.kdf import KeyDerivationFunction
@@ -15,18 +19,20 @@
 
 @utils.register_interface(KeyDerivationFunction)
 class PBKDF2HMAC(object):
-    def __init__(self, algorithm, length, salt, iterations, backend):
+    def __init__(self, algorithm, length, salt, iterations, backend=None):
+        backend = _get_backend(backend)
         if not isinstance(backend, PBKDF2HMACBackend):
             raise UnsupportedAlgorithm(
                 "Backend object does not implement PBKDF2HMACBackend.",
-                _Reasons.BACKEND_MISSING_INTERFACE
+                _Reasons.BACKEND_MISSING_INTERFACE,
             )
 
         if not backend.pbkdf2_hmac_supported(algorithm):
             raise UnsupportedAlgorithm(
-                "{0} is not supported for PBKDF2 by this backend.".format(
-                    algorithm.name),
-                _Reasons.UNSUPPORTED_HASH
+                "{} is not supported for PBKDF2 by this backend.".format(
+                    algorithm.name
+                ),
+                _Reasons.UNSUPPORTED_HASH,
             )
         self._used = False
         self._algorithm = algorithm
@@ -47,7 +53,7 @@
             self._length,
             self._salt,
             self._iterations,
-            key_material
+            key_material,
         )
 
     def verify(self, key_material, expected_key):
diff --git a/src/cryptography/hazmat/primitives/kdf/scrypt.py b/src/cryptography/hazmat/primitives/kdf/scrypt.py
index df9745e..f028646 100644
--- a/src/cryptography/hazmat/primitives/kdf/scrypt.py
+++ b/src/cryptography/hazmat/primitives/kdf/scrypt.py
@@ -8,8 +8,12 @@
 
 from cryptography import utils
 from cryptography.exceptions import (
-    AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons
+    AlreadyFinalized,
+    InvalidKey,
+    UnsupportedAlgorithm,
+    _Reasons,
 )
+from cryptography.hazmat.backends import _get_backend
 from cryptography.hazmat.backends.interfaces import ScryptBackend
 from cryptography.hazmat.primitives import constant_time
 from cryptography.hazmat.primitives.kdf import KeyDerivationFunction
@@ -22,11 +26,12 @@
 
 @utils.register_interface(KeyDerivationFunction)
 class Scrypt(object):
-    def __init__(self, salt, length, n, r, p, backend):
+    def __init__(self, salt, length, n, r, p, backend=None):
+        backend = _get_backend(backend)
         if not isinstance(backend, ScryptBackend):
             raise UnsupportedAlgorithm(
                 "Backend object does not implement ScryptBackend.",
-                _Reasons.BACKEND_MISSING_INTERFACE
+                _Reasons.BACKEND_MISSING_INTERFACE,
             )
 
         self._length = length
diff --git a/src/cryptography/hazmat/primitives/kdf/x963kdf.py b/src/cryptography/hazmat/primitives/kdf/x963kdf.py
index fd9d125..1898d52 100644
--- a/src/cryptography/hazmat/primitives/kdf/x963kdf.py
+++ b/src/cryptography/hazmat/primitives/kdf/x963kdf.py
@@ -8,25 +8,31 @@
 
 from cryptography import utils
 from cryptography.exceptions import (
-    AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons
+    AlreadyFinalized,
+    InvalidKey,
+    UnsupportedAlgorithm,
+    _Reasons,
 )
+from cryptography.hazmat.backends import _get_backend
 from cryptography.hazmat.backends.interfaces import HashBackend
 from cryptography.hazmat.primitives import constant_time, hashes
 from cryptography.hazmat.primitives.kdf import KeyDerivationFunction
 
 
 def _int_to_u32be(n):
-    return struct.pack('>I', n)
+    return struct.pack(">I", n)
 
 
 @utils.register_interface(KeyDerivationFunction)
 class X963KDF(object):
-    def __init__(self, algorithm, length, sharedinfo, backend):
+    def __init__(self, algorithm, length, sharedinfo, backend=None):
+        backend = _get_backend(backend)
 
         max_len = algorithm.digest_size * (2 ** 32 - 1)
         if length > max_len:
             raise ValueError(
-                "Can not derive keys larger than {0} bits.".format(max_len))
+                "Can not derive keys larger than {} bits.".format(max_len)
+            )
         if sharedinfo is not None:
             utils._check_bytes("sharedinfo", sharedinfo)
 
@@ -37,7 +43,7 @@
         if not isinstance(backend, HashBackend):
             raise UnsupportedAlgorithm(
                 "Backend object does not implement HashBackend.",
-                _Reasons.BACKEND_MISSING_INTERFACE
+                _Reasons.BACKEND_MISSING_INTERFACE,
             )
         self._backend = backend
         self._used = False
@@ -61,7 +67,7 @@
             outlen += len(output[-1])
             counter += 1
 
-        return b"".join(output)[:self._length]
+        return b"".join(output)[: self._length]
 
     def verify(self, key_material, expected_key):
         if not constant_time.bytes_eq(self.derive(key_material), expected_key):
diff --git a/src/cryptography/hazmat/primitives/keywrap.py b/src/cryptography/hazmat/primitives/keywrap.py
index f55c519..2439caf 100644
--- a/src/cryptography/hazmat/primitives/keywrap.py
+++ b/src/cryptography/hazmat/primitives/keywrap.py
@@ -6,6 +6,7 @@
 
 import struct
 
+from cryptography.hazmat.backends import _get_backend
 from cryptography.hazmat.primitives.ciphers import Cipher
 from cryptography.hazmat.primitives.ciphers.algorithms import AES
 from cryptography.hazmat.primitives.ciphers.modes import ECB
@@ -33,7 +34,8 @@
     return a + b"".join(r)
 
 
-def aes_key_wrap(wrapping_key, key_to_wrap, backend):
+def aes_key_wrap(wrapping_key, key_to_wrap, backend=None):
+    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")
 
@@ -44,7 +46,7 @@
         raise ValueError("The key to wrap must be a multiple of 8 bytes")
 
     a = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6"
-    r = [key_to_wrap[i:i + 8] for i in range(0, len(key_to_wrap), 8)]
+    r = [key_to_wrap[i : i + 8] for i in range(0, len(key_to_wrap), 8)]
     return _wrap_core(wrapping_key, a, r, backend)
 
 
@@ -55,9 +57,12 @@
     for j in reversed(range(6)):
         for i in reversed(range(n)):
             # pack/unpack are safe as these are always 64-bit chunks
-            atr = struct.pack(
-                ">Q", struct.unpack(">Q", a)[0] ^ ((n * j) + i + 1)
-            ) + r[i]
+            atr = (
+                struct.pack(
+                    ">Q", struct.unpack(">Q", a)[0] ^ ((n * j) + i + 1)
+                )
+                + r[i]
+            )
             # every decryption operation is a discrete 16 byte chunk so
             # it is safe to reuse the decryptor for the entire operation
             b = decryptor.update(atr)
@@ -68,7 +73,8 @@
     return a, r
 
 
-def aes_key_wrap_with_padding(wrapping_key, key_to_wrap, backend):
+def aes_key_wrap_with_padding(wrapping_key, key_to_wrap, backend=None):
+    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")
 
@@ -83,11 +89,12 @@
         assert encryptor.finalize() == b""
         return b
     else:
-        r = [key_to_wrap[i:i + 8] for i in range(0, len(key_to_wrap), 8)]
+        r = [key_to_wrap[i : i + 8] for i in range(0, len(key_to_wrap), 8)]
         return _wrap_core(wrapping_key, aiv, r, backend)
 
 
-def aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend):
+def aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend=None):
+    backend = _get_backend(backend)
     if len(wrapped_key) < 16:
         raise InvalidUnwrap("Must be at least 16 bytes")
 
@@ -103,7 +110,7 @@
         data = b[8:]
         n = 1
     else:
-        r = [wrapped_key[i:i + 8] for i in range(0, len(wrapped_key), 8)]
+        r = [wrapped_key[i : i + 8] for i in range(0, len(wrapped_key), 8)]
         encrypted_aiv = r.pop(0)
         n = len(r)
         a, r = _unwrap_core(wrapping_key, encrypted_aiv, r, backend)
@@ -117,10 +124,9 @@
     (mli,) = struct.unpack(">I", a[4:])
     b = (8 * n) - mli
     if (
-        not bytes_eq(a[:4], b"\xa6\x59\x59\xa6") or not
-        8 * (n - 1) < mli <= 8 * n or (
-            b != 0 and not bytes_eq(data[-b:], b"\x00" * b)
-        )
+        not bytes_eq(a[:4], b"\xa6\x59\x59\xa6")
+        or not 8 * (n - 1) < mli <= 8 * n
+        or (b != 0 and not bytes_eq(data[-b:], b"\x00" * b))
     ):
         raise InvalidUnwrap()
 
@@ -130,7 +136,8 @@
         return data[:-b]
 
 
-def aes_key_unwrap(wrapping_key, wrapped_key, backend):
+def aes_key_unwrap(wrapping_key, wrapped_key, backend=None):
+    backend = _get_backend(backend)
     if len(wrapped_key) < 24:
         raise InvalidUnwrap("Must be at least 24 bytes")
 
@@ -141,7 +148,7 @@
         raise ValueError("The wrapping key must be a valid AES key length")
 
     aiv = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6"
-    r = [wrapped_key[i:i + 8] for i in range(0, len(wrapped_key), 8)]
+    r = [wrapped_key[i : i + 8] for i in range(0, len(wrapped_key), 8)]
     a = r.pop(0)
     a, r = _unwrap_core(wrapping_key, a, r, backend)
     if not bytes_eq(a, aiv):
diff --git a/src/cryptography/hazmat/primitives/mac.py b/src/cryptography/hazmat/primitives/mac.py
deleted file mode 100644
index 4c95190..0000000
--- a/src/cryptography/hazmat/primitives/mac.py
+++ /dev/null
@@ -1,37 +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.
-
-from __future__ import absolute_import, division, print_function
-
-import abc
-
-import six
-
-
-@six.add_metaclass(abc.ABCMeta)
-class MACContext(object):
-    @abc.abstractmethod
-    def update(self, data):
-        """
-        Processes the provided bytes.
-        """
-
-    @abc.abstractmethod
-    def finalize(self):
-        """
-        Returns the message authentication code as bytes.
-        """
-
-    @abc.abstractmethod
-    def copy(self):
-        """
-        Return a MACContext that is a copy of the current context.
-        """
-
-    @abc.abstractmethod
-    def verify(self, signature):
-        """
-        Checks if the generated message authentication code matches the
-        signature.
-        """
diff --git a/src/cryptography/hazmat/primitives/padding.py b/src/cryptography/hazmat/primitives/padding.py
index 170c802..98abffb 100644
--- a/src/cryptography/hazmat/primitives/padding.py
+++ b/src/cryptography/hazmat/primitives/padding.py
@@ -40,14 +40,17 @@
     if buffer_ is None:
         raise AlreadyFinalized("Context was already finalized.")
 
-    utils._check_bytes("data", data)
+    utils._check_byteslike("data", data)
 
-    buffer_ += 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)
 
     finished_blocks = len(buffer_) // (block_size // 8)
 
-    result = buffer_[:finished_blocks * (block_size // 8)]
-    buffer_ = buffer_[finished_blocks * (block_size // 8):]
+    result = buffer_[: finished_blocks * (block_size // 8)]
+    buffer_ = buffer_[finished_blocks * (block_size // 8) :]
 
     return buffer_, result
 
@@ -64,14 +67,17 @@
     if buffer_ is None:
         raise AlreadyFinalized("Context was already finalized.")
 
-    utils._check_bytes("data", data)
+    utils._check_byteslike("data", data)
 
-    buffer_ += 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)
 
     finished_blocks = max(len(buffer_) // (block_size // 8) - 1, 0)
 
-    result = buffer_[:finished_blocks * (block_size // 8)]
-    buffer_ = buffer_[finished_blocks * (block_size // 8):]
+    result = buffer_[: finished_blocks * (block_size // 8)]
+    buffer_ = buffer_[finished_blocks * (block_size // 8) :]
 
     return buffer_, result
 
@@ -113,7 +119,8 @@
 
     def update(self, data):
         self._buffer, result = _byte_padding_update(
-            self._buffer, data, self.block_size)
+            self._buffer, data, self.block_size
+        )
         return result
 
     def _padding(self, size):
@@ -121,7 +128,8 @@
 
     def finalize(self):
         result = _byte_padding_pad(
-            self._buffer, self.block_size, self._padding)
+            self._buffer, self.block_size, self._padding
+        )
         self._buffer = None
         return result
 
@@ -135,13 +143,14 @@
 
     def update(self, data):
         self._buffer, result = _byte_unpadding_update(
-            self._buffer, data, self.block_size)
+            self._buffer, data, self.block_size
+        )
         return result
 
     def finalize(self):
         result = _byte_unpadding_check(
-            self._buffer, self.block_size,
-            lib.Cryptography_check_pkcs7_padding)
+            self._buffer, self.block_size, lib.Cryptography_check_pkcs7_padding
+        )
         self._buffer = None
         return result
 
@@ -167,7 +176,8 @@
 
     def update(self, data):
         self._buffer, result = _byte_padding_update(
-            self._buffer, data, self.block_size)
+            self._buffer, data, self.block_size
+        )
         return result
 
     def _padding(self, size):
@@ -175,7 +185,8 @@
 
     def finalize(self):
         result = _byte_padding_pad(
-            self._buffer, self.block_size, self._padding)
+            self._buffer, self.block_size, self._padding
+        )
         self._buffer = None
         return result
 
@@ -189,12 +200,15 @@
 
     def update(self, data):
         self._buffer, result = _byte_unpadding_update(
-            self._buffer, data, self.block_size)
+            self._buffer, data, self.block_size
+        )
         return result
 
     def finalize(self):
         result = _byte_unpadding_check(
-            self._buffer, self.block_size,
-            lib.Cryptography_check_ansix923_padding)
+            self._buffer,
+            self.block_size,
+            lib.Cryptography_check_ansix923_padding,
+        )
         self._buffer = None
         return result
diff --git a/src/cryptography/hazmat/primitives/poly1305.py b/src/cryptography/hazmat/primitives/poly1305.py
new file mode 100644
index 0000000..6439686
--- /dev/null
+++ b/src/cryptography/hazmat/primitives/poly1305.py
@@ -0,0 +1,58 @@
+# 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
+
+
+from cryptography import utils
+from cryptography.exceptions import (
+    AlreadyFinalized,
+    UnsupportedAlgorithm,
+    _Reasons,
+)
+
+
+class Poly1305(object):
+    def __init__(self, key):
+        from cryptography.hazmat.backends.openssl.backend import backend
+
+        if not backend.poly1305_supported():
+            raise UnsupportedAlgorithm(
+                "poly1305 is not supported by this version of OpenSSL.",
+                _Reasons.UNSUPPORTED_MAC,
+            )
+        self._ctx = backend.create_poly1305_ctx(key)
+
+    def update(self, data):
+        if self._ctx is None:
+            raise AlreadyFinalized("Context was already finalized.")
+        utils._check_byteslike("data", data)
+        self._ctx.update(data)
+
+    def finalize(self):
+        if self._ctx is None:
+            raise AlreadyFinalized("Context was already finalized.")
+        mac = self._ctx.finalize()
+        self._ctx = None
+        return mac
+
+    def verify(self, tag):
+        utils._check_bytes("tag", tag)
+        if self._ctx is None:
+            raise AlreadyFinalized("Context was already finalized.")
+
+        ctx, self._ctx = self._ctx, None
+        ctx.verify(tag)
+
+    @classmethod
+    def generate_tag(cls, key, data):
+        p = Poly1305(key)
+        p.update(data)
+        return p.finalize()
+
+    @classmethod
+    def verify_tag(cls, key, data, tag):
+        p = Poly1305(key)
+        p.update(data)
+        p.verify(tag)
diff --git a/src/cryptography/hazmat/primitives/serialization/__init__.py b/src/cryptography/hazmat/primitives/serialization/__init__.py
index f6d4ce9..c2f9b01 100644
--- a/src/cryptography/hazmat/primitives/serialization/__init__.py
+++ b/src/cryptography/hazmat/primitives/serialization/__init__.py
@@ -5,22 +5,40 @@
 from __future__ import absolute_import, division, print_function
 
 from cryptography.hazmat.primitives.serialization.base import (
-    BestAvailableEncryption, Encoding, KeySerializationEncryption,
-    NoEncryption, ParameterFormat, PrivateFormat, PublicFormat,
-    load_der_parameters, load_der_private_key, load_der_public_key,
-    load_pem_parameters, load_pem_private_key, load_pem_public_key,
+    BestAvailableEncryption,
+    Encoding,
+    KeySerializationEncryption,
+    NoEncryption,
+    ParameterFormat,
+    PrivateFormat,
+    PublicFormat,
+    load_der_parameters,
+    load_der_private_key,
+    load_der_public_key,
+    load_pem_parameters,
+    load_pem_private_key,
+    load_pem_public_key,
 )
 from cryptography.hazmat.primitives.serialization.ssh import (
-    load_ssh_public_key
+    load_ssh_private_key,
+    load_ssh_public_key,
 )
 
 
-_PEM_DER = (Encoding.PEM, Encoding.DER)
-
 __all__ = [
-    "load_der_parameters", "load_der_private_key", "load_der_public_key",
-    "load_pem_parameters", "load_pem_private_key", "load_pem_public_key",
-    "load_ssh_public_key", "Encoding", "PrivateFormat", "PublicFormat",
-    "ParameterFormat", "KeySerializationEncryption", "BestAvailableEncryption",
+    "load_der_parameters",
+    "load_der_private_key",
+    "load_der_public_key",
+    "load_pem_parameters",
+    "load_pem_private_key",
+    "load_pem_public_key",
+    "load_ssh_private_key",
+    "load_ssh_public_key",
+    "Encoding",
+    "PrivateFormat",
+    "PublicFormat",
+    "ParameterFormat",
+    "KeySerializationEncryption",
+    "BestAvailableEncryption",
     "NoEncryption",
 ]
diff --git a/src/cryptography/hazmat/primitives/serialization/base.py b/src/cryptography/hazmat/primitives/serialization/base.py
index 4218ea8..fc27235 100644
--- a/src/cryptography/hazmat/primitives/serialization/base.py
+++ b/src/cryptography/hazmat/primitives/serialization/base.py
@@ -10,29 +10,36 @@
 import six
 
 from cryptography import utils
+from cryptography.hazmat.backends import _get_backend
 
 
-def load_pem_private_key(data, password, backend):
+def load_pem_private_key(data, password, backend=None):
+    backend = _get_backend(backend)
     return backend.load_pem_private_key(data, password)
 
 
-def load_pem_public_key(data, backend):
+def load_pem_public_key(data, backend=None):
+    backend = _get_backend(backend)
     return backend.load_pem_public_key(data)
 
 
-def load_pem_parameters(data, backend):
+def load_pem_parameters(data, backend=None):
+    backend = _get_backend(backend)
     return backend.load_pem_parameters(data)
 
 
-def load_der_private_key(data, password, backend):
+def load_der_private_key(data, password, backend=None):
+    backend = _get_backend(backend)
     return backend.load_der_private_key(data, password)
 
 
-def load_der_public_key(data, backend):
+def load_der_public_key(data, backend=None):
+    backend = _get_backend(backend)
     return backend.load_der_public_key(data)
 
 
-def load_der_parameters(data, backend):
+def load_der_parameters(data, backend=None):
+    backend = _get_backend(backend)
     return backend.load_der_parameters(data)
 
 
@@ -42,12 +49,14 @@
     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):
diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs12.py b/src/cryptography/hazmat/primitives/serialization/pkcs12.py
index 98161d5..201f329 100644
--- a/src/cryptography/hazmat/primitives/serialization/pkcs12.py
+++ b/src/cryptography/hazmat/primitives/serialization/pkcs12.py
@@ -4,6 +4,47 @@
 
 from __future__ import absolute_import, division, print_function
 
+from cryptography import x509
+from cryptography.hazmat.backends import _get_backend
+from cryptography.hazmat.primitives import serialization
+from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
 
-def load_key_and_certificates(data, password, backend):
+
+def load_key_and_certificates(data, password, 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):
+    if key is not None and not isinstance(
+        key,
+        (
+            rsa.RSAPrivateKeyWithSerialization,
+            dsa.DSAPrivateKeyWithSerialization,
+            ec.EllipticCurvePrivateKeyWithSerialization,
+        ),
+    ):
+        raise TypeError("Key must be RSA, DSA, or EllipticCurve private key.")
+    if cert is not None and not isinstance(cert, x509.Certificate):
+        raise TypeError("cert must be a certificate")
+
+    if cas is not None:
+        cas = list(cas)
+        if not all(isinstance(val, x509.Certificate) for val in cas):
+            raise TypeError("all values in cas must be certificates")
+
+    if not isinstance(
+        encryption_algorithm, serialization.KeySerializationEncryption
+    ):
+        raise TypeError(
+            "Key encryption algorithm must be a "
+            "KeySerializationEncryption instance"
+        )
+
+    if key is None and cert is None and not cas:
+        raise ValueError("You must supply at least one of key, cert, or cas")
+
+    backend = _get_backend(None)
+    return backend.serialize_key_and_certificates_to_pkcs12(
+        name, key, cert, cas, encryption_algorithm
+    )
diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs7.py b/src/cryptography/hazmat/primitives/serialization/pkcs7.py
new file mode 100644
index 0000000..1e11e28
--- /dev/null
+++ b/src/cryptography/hazmat/primitives/serialization/pkcs7.py
@@ -0,0 +1,132 @@
+# 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
+
+from enum import Enum
+
+from cryptography import x509
+from cryptography.hazmat.backends import _get_backend
+from cryptography.hazmat.primitives import hashes, serialization
+from cryptography.hazmat.primitives.asymmetric import ec, rsa
+from cryptography.utils import _check_byteslike
+
+
+def load_pem_pkcs7_certificates(data):
+    backend = _get_backend(None)
+    return backend.load_pem_pkcs7_certificates(data)
+
+
+def load_der_pkcs7_certificates(data):
+    backend = _get_backend(None)
+    return backend.load_der_pkcs7_certificates(data)
+
+
+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):
+        _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):
+        if not isinstance(
+            hash_algorithm,
+            (
+                hashes.SHA1,
+                hashes.SHA224,
+                hashes.SHA256,
+                hashes.SHA384,
+                hashes.SHA512,
+            ),
+        ):
+            raise TypeError(
+                "hash_algorithm must be one of hashes.SHA1, SHA224, "
+                "SHA256, SHA384, or SHA512"
+            )
+        if not isinstance(certificate, x509.Certificate):
+            raise TypeError("certificate must be a x509.Certificate")
+
+        if not isinstance(
+            private_key, (rsa.RSAPrivateKey, ec.EllipticCurvePrivateKey)
+        ):
+            raise TypeError("Only RSA & EC keys are supported at this time.")
+
+        return PKCS7SignatureBuilder(
+            self._data,
+            self._signers + [(certificate, private_key, hash_algorithm)],
+        )
+
+    def add_certificate(self, certificate):
+        if not isinstance(certificate, x509.Certificate):
+            raise TypeError("certificate must be a x509.Certificate")
+
+        return PKCS7SignatureBuilder(
+            self._data, self._signers, self._additional_certs + [certificate]
+        )
+
+    def sign(self, encoding, options, backend=None):
+        if len(self._signers) == 0:
+            raise ValueError("Must have at least one signer")
+        if self._data is None:
+            raise ValueError("You must add data to sign")
+        options = list(options)
+        if not all(isinstance(x, PKCS7Options) for x in options):
+            raise ValueError("options must be from the PKCS7Options enum")
+        if encoding not in (
+            serialization.Encoding.PEM,
+            serialization.Encoding.DER,
+            serialization.Encoding.SMIME,
+        ):
+            raise ValueError(
+                "Must be PEM, DER, or SMIME from the Encoding enum"
+            )
+
+        # Text is a meaningless option unless it is accompanied by
+        # DetachedSignature
+        if (
+            PKCS7Options.Text in options
+            and PKCS7Options.DetachedSignature not in options
+        ):
+            raise ValueError(
+                "When passing the Text option you must also pass "
+                "DetachedSignature"
+            )
+
+        if PKCS7Options.Text in options and encoding in (
+            serialization.Encoding.DER,
+            serialization.Encoding.PEM,
+        ):
+            raise ValueError(
+                "The Text option is only available for SMIME serialization"
+            )
+
+        # No attributes implies no capabilities so we'll error if you try to
+        # pass both.
+        if (
+            PKCS7Options.NoAttributes in options
+            and PKCS7Options.NoCapabilities in options
+        ):
+            raise ValueError(
+                "NoAttributes is a superset of NoCapabilities. Do not pass "
+                "both values."
+            )
+
+        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 cb83892..5ecae59 100644
--- a/src/cryptography/hazmat/primitives/serialization/ssh.py
+++ b/src/cryptography/hazmat/primitives/serialization/ssh.py
@@ -4,139 +4,680 @@
 
 from __future__ import absolute_import, division, print_function
 
-import base64
+import binascii
+import os
+import re
 import struct
 
 import six
 
 from cryptography import utils
 from cryptography.exceptions import UnsupportedAlgorithm
-from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
+from cryptography.hazmat.backends import _get_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 (
+    Encoding,
+    NoEncryption,
+    PrivateFormat,
+    PublicFormat,
+)
+
+try:
+    from bcrypt import kdf as _bcrypt_kdf
+
+    _bcrypt_supported = True
+except ImportError:
+    _bcrypt_supported = False
+
+    def _bcrypt_kdf(*args, **kwargs):
+        raise UnsupportedAlgorithm("Need bcrypt module")
 
 
-def load_ssh_public_key(data, backend):
-    key_parts = data.split(b' ', 2)
+try:
+    from base64 import encodebytes as _base64_encode
+except ImportError:
+    from base64 import encodestring as _base64_encode
 
-    if len(key_parts) < 2:
+_SSH_ED25519 = b"ssh-ed25519"
+_SSH_RSA = b"ssh-rsa"
+_SSH_DSA = b"ssh-dss"
+_ECDSA_NISTP256 = b"ecdsa-sha2-nistp256"
+_ECDSA_NISTP384 = b"ecdsa-sha2-nistp384"
+_ECDSA_NISTP521 = b"ecdsa-sha2-nistp521"
+_CERT_SUFFIX = b"-cert-v01@openssh.com"
+
+_SSH_PUBKEY_RC = re.compile(br"\A(\S+)[ \t]+(\S+)")
+_SK_MAGIC = b"openssh-key-v1\0"
+_SK_START = b"-----BEGIN OPENSSH PRIVATE KEY-----"
+_SK_END = b"-----END OPENSSH PRIVATE KEY-----"
+_BCRYPT = b"bcrypt"
+_NONE = b"none"
+_DEFAULT_CIPHER = b"aes256-ctr"
+_DEFAULT_ROUNDS = 16
+_MAX_PASSWORD = 72
+
+# re is only way to work on bytes-like data
+_PEM_RC = re.compile(_SK_START + b"(.*?)" + _SK_END, re.DOTALL)
+
+# padding for max blocksize
+_PADDING = memoryview(bytearray(range(1, 1 + 16)))
+
+# ciphers that are actually used in key wrapping
+_SSH_CIPHERS = {
+    b"aes256-ctr": (algorithms.AES, 32, modes.CTR, 16),
+    b"aes256-cbc": (algorithms.AES, 32, modes.CBC, 16),
+}
+
+# map local curve name to key type
+_ECDSA_KEY_TYPE = {
+    "secp256r1": _ECDSA_NISTP256,
+    "secp384r1": _ECDSA_NISTP384,
+    "secp521r1": _ECDSA_NISTP521,
+}
+
+_U32 = struct.Struct(b">I")
+_U64 = struct.Struct(b">Q")
+
+
+def _ecdsa_key_type(public_key):
+    """Return SSH key_type and curve_name for private key."""
+    curve = public_key.curve
+    if curve.name not in _ECDSA_KEY_TYPE:
         raise ValueError(
-            'Key is not in the proper format or contains extra data.')
+            "Unsupported curve for ssh private key: %r" % curve.name
+        )
+    return _ECDSA_KEY_TYPE[curve.name]
 
-    key_type = key_parts[0]
 
-    if key_type == b'ssh-rsa':
-        loader = _load_ssh_rsa_public_key
-    elif key_type == b'ssh-dss':
-        loader = _load_ssh_dss_public_key
-    elif key_type in [
-        b'ecdsa-sha2-nistp256', b'ecdsa-sha2-nistp384', b'ecdsa-sha2-nistp521',
-    ]:
-        loader = _load_ssh_ecdsa_public_key
+def _ssh_pem_encode(data, prefix=_SK_START + b"\n", suffix=_SK_END + b"\n"):
+    return b"".join([prefix, _base64_encode(data), suffix])
+
+
+def _check_block_size(data, block_len):
+    """Require data to be full blocks"""
+    if not data or len(data) % block_len != 0:
+        raise ValueError("Corrupt data: missing padding")
+
+
+def _check_empty(data):
+    """All data should have been parsed."""
+    if data:
+        raise ValueError("Corrupt data: unparsed data")
+
+
+def _init_cipher(ciphername, password, salt, rounds, backend):
+    """Generate key + iv and return cipher."""
+    if not password:
+        raise ValueError("Key is password-protected.")
+
+    algo, key_len, mode, iv_len = _SSH_CIPHERS[ciphername]
+    seed = _bcrypt_kdf(password, salt, key_len + iv_len, rounds, True)
+    return Cipher(algo(seed[:key_len]), mode(seed[key_len:]), backend)
+
+
+def _get_u32(data):
+    """Uint32"""
+    if len(data) < 4:
+        raise ValueError("Invalid data")
+    return _U32.unpack(data[:4])[0], data[4:]
+
+
+def _get_u64(data):
+    """Uint64"""
+    if len(data) < 8:
+        raise ValueError("Invalid data")
+    return _U64.unpack(data[:8])[0], data[8:]
+
+
+def _get_sshstr(data):
+    """Bytes with u32 length prefix"""
+    n, data = _get_u32(data)
+    if n > len(data):
+        raise ValueError("Invalid data")
+    return data[:n], data[n:]
+
+
+def _get_mpint(data):
+    """Big integer."""
+    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
+
+
+def _to_mpint(val):
+    """Storage format for signed bigint."""
+    if val < 0:
+        raise ValueError("negative mpint not allowed")
+    if not val:
+        return b""
+    nbytes = (val.bit_length() + 8) // 8
+    return utils.int_to_bytes(val, nbytes)
+
+
+class _FragList(object):
+    """Build recursive structure without data copy."""
+
+    def __init__(self, init=None):
+        self.flist = []
+        if init:
+            self.flist.extend(init)
+
+    def put_raw(self, val):
+        """Add plain bytes"""
+        self.flist.append(val)
+
+    def put_u32(self, val):
+        """Big-endian uint32"""
+        self.flist.append(_U32.pack(val))
+
+    def put_sshstr(self, val):
+        """Bytes prefixed with u32 length"""
+        if isinstance(val, (bytes, memoryview, bytearray)):
+            self.put_u32(len(val))
+            self.flist.append(val)
+        else:
+            self.put_u32(val.size())
+            self.flist.extend(val.flist)
+
+    def put_mpint(self, val):
+        """Big-endian bigint prefixed with u32 length"""
+        self.put_sshstr(_to_mpint(val))
+
+    def size(self):
+        """Current number of bytes"""
+        return sum(map(len, self.flist))
+
+    def render(self, dstbuf, pos=0):
+        """Write into bytearray"""
+        for frag in self.flist:
+            flen = len(frag)
+            start, pos = pos, pos + flen
+            dstbuf[start:pos] = frag
+        return pos
+
+    def tobytes(self):
+        """Return as bytes"""
+        buf = memoryview(bytearray(self.size()))
+        self.render(buf)
+        return buf.tobytes()
+
+
+class _SSHFormatRSA(object):
+    """Format for RSA keys.
+
+    Public:
+        mpint e, n
+    Private:
+        mpint n, e, d, iqmp, p, q
+    """
+
+    def get_public(self, data):
+        """RSA public fields"""
+        e, data = _get_mpint(data)
+        n, data = _get_mpint(data)
+        return (e, n), data
+
+    def load_public(self, key_type, data, backend):
+        """Make RSA public key from data."""
+        (e, n), data = self.get_public(data)
+        public_numbers = rsa.RSAPublicNumbers(e, n)
+        public_key = public_numbers.public_key(backend)
+        return public_key, data
+
+    def load_private(self, data, pubfields, backend):
+        """Make RSA private key from data."""
+        n, data = _get_mpint(data)
+        e, data = _get_mpint(data)
+        d, data = _get_mpint(data)
+        iqmp, data = _get_mpint(data)
+        p, data = _get_mpint(data)
+        q, data = _get_mpint(data)
+
+        if (e, n) != pubfields:
+            raise ValueError("Corrupt data: rsa field mismatch")
+        dmp1 = rsa.rsa_crt_dmp1(d, p)
+        dmq1 = rsa.rsa_crt_dmq1(d, q)
+        public_numbers = rsa.RSAPublicNumbers(e, n)
+        private_numbers = rsa.RSAPrivateNumbers(
+            p, q, d, dmp1, dmq1, iqmp, public_numbers
+        )
+        private_key = private_numbers.private_key(backend)
+        return private_key, data
+
+    def encode_public(self, public_key, f_pub):
+        """Write RSA public key"""
+        pubn = public_key.public_numbers()
+        f_pub.put_mpint(pubn.e)
+        f_pub.put_mpint(pubn.n)
+
+    def encode_private(self, private_key, f_priv):
+        """Write RSA private key"""
+        private_numbers = private_key.private_numbers()
+        public_numbers = private_numbers.public_numbers
+
+        f_priv.put_mpint(public_numbers.n)
+        f_priv.put_mpint(public_numbers.e)
+
+        f_priv.put_mpint(private_numbers.d)
+        f_priv.put_mpint(private_numbers.iqmp)
+        f_priv.put_mpint(private_numbers.p)
+        f_priv.put_mpint(private_numbers.q)
+
+
+class _SSHFormatDSA(object):
+    """Format for DSA keys.
+
+    Public:
+        mpint p, q, g, y
+    Private:
+        mpint p, q, g, y, x
+    """
+
+    def get_public(self, data):
+        """DSA public fields"""
+        p, data = _get_mpint(data)
+        q, data = _get_mpint(data)
+        g, data = _get_mpint(data)
+        y, data = _get_mpint(data)
+        return (p, q, g, y), data
+
+    def load_public(self, key_type, data, backend):
+        """Make DSA public key from data."""
+        (p, q, g, y), data = self.get_public(data)
+        parameter_numbers = dsa.DSAParameterNumbers(p, q, g)
+        public_numbers = dsa.DSAPublicNumbers(y, parameter_numbers)
+        self._validate(public_numbers)
+        public_key = public_numbers.public_key(backend)
+        return public_key, data
+
+    def load_private(self, data, pubfields, backend):
+        """Make DSA private key from data."""
+        (p, q, g, y), data = self.get_public(data)
+        x, data = _get_mpint(data)
+
+        if (p, q, g, y) != pubfields:
+            raise ValueError("Corrupt data: dsa field mismatch")
+        parameter_numbers = dsa.DSAParameterNumbers(p, q, g)
+        public_numbers = dsa.DSAPublicNumbers(y, parameter_numbers)
+        self._validate(public_numbers)
+        private_numbers = dsa.DSAPrivateNumbers(x, public_numbers)
+        private_key = private_numbers.private_key(backend)
+        return private_key, data
+
+    def encode_public(self, public_key, f_pub):
+        """Write DSA public key"""
+        public_numbers = public_key.public_numbers()
+        parameter_numbers = public_numbers.parameter_numbers
+        self._validate(public_numbers)
+
+        f_pub.put_mpint(parameter_numbers.p)
+        f_pub.put_mpint(parameter_numbers.q)
+        f_pub.put_mpint(parameter_numbers.g)
+        f_pub.put_mpint(public_numbers.y)
+
+    def encode_private(self, private_key, f_priv):
+        """Write DSA private key"""
+        self.encode_public(private_key.public_key(), f_priv)
+        f_priv.put_mpint(private_key.private_numbers().x)
+
+    def _validate(self, public_numbers):
+        parameter_numbers = public_numbers.parameter_numbers
+        if parameter_numbers.p.bit_length() != 1024:
+            raise ValueError("SSH supports only 1024 bit DSA keys")
+
+
+class _SSHFormatECDSA(object):
+    """Format for ECDSA keys.
+
+    Public:
+        str curve
+        bytes point
+    Private:
+        str curve
+        bytes point
+        mpint secret
+    """
+
+    def __init__(self, ssh_curve_name, curve):
+        self.ssh_curve_name = ssh_curve_name
+        self.curve = curve
+
+    def get_public(self, data):
+        """ECDSA public fields"""
+        curve, data = _get_sshstr(data)
+        point, data = _get_sshstr(data)
+        if curve != self.ssh_curve_name:
+            raise ValueError("Curve name mismatch")
+        if six.indexbytes(point, 0) != 4:
+            raise NotImplementedError("Need uncompressed point")
+        return (curve, point), data
+
+    def load_public(self, key_type, data, backend):
+        """Make ECDSA public key from data."""
+        (curve_name, point), data = self.get_public(data)
+        public_key = ec.EllipticCurvePublicKey.from_encoded_point(
+            self.curve, point.tobytes()
+        )
+        return public_key, data
+
+    def load_private(self, data, pubfields, backend):
+        """Make ECDSA private key from data."""
+        (curve_name, point), data = self.get_public(data)
+        secret, data = _get_mpint(data)
+
+        if (curve_name, point) != pubfields:
+            raise ValueError("Corrupt data: ecdsa field mismatch")
+        private_key = ec.derive_private_key(secret, self.curve, backend)
+        return private_key, data
+
+    def encode_public(self, public_key, f_pub):
+        """Write ECDSA public key"""
+        point = public_key.public_bytes(
+            Encoding.X962, PublicFormat.UncompressedPoint
+        )
+        f_pub.put_sshstr(self.ssh_curve_name)
+        f_pub.put_sshstr(point)
+
+    def encode_private(self, private_key, f_priv):
+        """Write ECDSA private key"""
+        public_key = private_key.public_key()
+        private_numbers = private_key.private_numbers()
+
+        self.encode_public(public_key, f_priv)
+        f_priv.put_mpint(private_numbers.private_value)
+
+
+class _SSHFormatEd25519(object):
+    """Format for Ed25519 keys.
+
+    Public:
+        bytes point
+    Private:
+        bytes point
+        bytes secret_and_point
+    """
+
+    def get_public(self, data):
+        """Ed25519 public fields"""
+        point, data = _get_sshstr(data)
+        return (point,), data
+
+    def load_public(self, key_type, data, backend):
+        """Make Ed25519 public key from data."""
+        (point,), data = self.get_public(data)
+        public_key = ed25519.Ed25519PublicKey.from_public_bytes(
+            point.tobytes()
+        )
+        return public_key, data
+
+    def load_private(self, data, pubfields, backend):
+        """Make Ed25519 private key from data."""
+        (point,), data = self.get_public(data)
+        keypair, data = _get_sshstr(data)
+
+        secret = keypair[:32]
+        point2 = keypair[32:]
+        if point != point2 or (point,) != pubfields:
+            raise ValueError("Corrupt data: ed25519 field mismatch")
+        private_key = ed25519.Ed25519PrivateKey.from_private_bytes(secret)
+        return private_key, data
+
+    def encode_public(self, public_key, f_pub):
+        """Write Ed25519 public key"""
+        raw_public_key = public_key.public_bytes(
+            Encoding.Raw, PublicFormat.Raw
+        )
+        f_pub.put_sshstr(raw_public_key)
+
+    def encode_private(self, private_key, f_priv):
+        """Write Ed25519 private key"""
+        public_key = private_key.public_key()
+        raw_private_key = private_key.private_bytes(
+            Encoding.Raw, PrivateFormat.Raw, NoEncryption()
+        )
+        raw_public_key = public_key.public_bytes(
+            Encoding.Raw, PublicFormat.Raw
+        )
+        f_keypair = _FragList([raw_private_key, raw_public_key])
+
+        self.encode_public(public_key, f_priv)
+        f_priv.put_sshstr(f_keypair)
+
+
+_KEY_FORMATS = {
+    _SSH_RSA: _SSHFormatRSA(),
+    _SSH_DSA: _SSHFormatDSA(),
+    _SSH_ED25519: _SSHFormatEd25519(),
+    _ECDSA_NISTP256: _SSHFormatECDSA(b"nistp256", ec.SECP256R1()),
+    _ECDSA_NISTP384: _SSHFormatECDSA(b"nistp384", ec.SECP384R1()),
+    _ECDSA_NISTP521: _SSHFormatECDSA(b"nistp521", ec.SECP521R1()),
+}
+
+
+def _lookup_kformat(key_type):
+    """Return valid format or throw error"""
+    if not isinstance(key_type, bytes):
+        key_type = memoryview(key_type).tobytes()
+    if key_type in _KEY_FORMATS:
+        return _KEY_FORMATS[key_type]
+    raise UnsupportedAlgorithm("Unsupported key type: %r" % key_type)
+
+
+def load_ssh_private_key(data, password, backend=None):
+    """Load private key from OpenSSH custom encoding."""
+    utils._check_byteslike("data", data)
+    backend = _get_backend(backend)
+    if password is not None:
+        utils._check_bytes("password", password)
+
+    m = _PEM_RC.search(data)
+    if not m:
+        raise ValueError("Not OpenSSH private key format")
+    p1 = m.start(1)
+    p2 = m.end(1)
+    data = binascii.a2b_base64(memoryview(data)[p1:p2])
+    if not data.startswith(_SK_MAGIC):
+        raise ValueError("Not OpenSSH private key format")
+    data = memoryview(data)[len(_SK_MAGIC) :]
+
+    # parse header
+    ciphername, data = _get_sshstr(data)
+    kdfname, data = _get_sshstr(data)
+    kdfoptions, data = _get_sshstr(data)
+    nkeys, data = _get_u32(data)
+    if nkeys != 1:
+        raise ValueError("Only one key supported")
+
+    # load public key data
+    pubdata, data = _get_sshstr(data)
+    pub_key_type, pubdata = _get_sshstr(pubdata)
+    kformat = _lookup_kformat(pub_key_type)
+    pubfields, pubdata = kformat.get_public(pubdata)
+    _check_empty(pubdata)
+
+    # load secret data
+    edata, data = _get_sshstr(data)
+    _check_empty(data)
+
+    if (ciphername, kdfname) != (_NONE, _NONE):
+        ciphername = ciphername.tobytes()
+        if ciphername not in _SSH_CIPHERS:
+            raise UnsupportedAlgorithm("Unsupported cipher: %r" % ciphername)
+        if kdfname != _BCRYPT:
+            raise UnsupportedAlgorithm("Unsupported KDF: %r" % kdfname)
+        blklen = _SSH_CIPHERS[ciphername][3]
+        _check_block_size(edata, blklen)
+        salt, kbuf = _get_sshstr(kdfoptions)
+        rounds, kbuf = _get_u32(kbuf)
+        _check_empty(kbuf)
+        ciph = _init_cipher(
+            ciphername, password, salt.tobytes(), rounds, backend
+        )
+        edata = memoryview(ciph.decryptor().update(edata))
     else:
-        raise UnsupportedAlgorithm('Key type is not supported.')
+        blklen = 8
+        _check_block_size(edata, blklen)
+    ck1, edata = _get_u32(edata)
+    ck2, edata = _get_u32(edata)
+    if ck1 != ck2:
+        raise ValueError("Corrupt data: broken checksum")
 
-    key_body = key_parts[1]
+    # load per-key struct
+    key_type, edata = _get_sshstr(edata)
+    if key_type != pub_key_type:
+        raise ValueError("Corrupt data: key type mismatch")
+    private_key, edata = kformat.load_private(edata, pubfields, backend)
+    comment, edata = _get_sshstr(edata)
+
+    # yes, SSH does padding check *after* all other parsing is done.
+    # need to follow as it writes zero-byte padding too.
+    if edata != _PADDING[: len(edata)]:
+        raise ValueError("Corrupt data: invalid padding")
+
+    return private_key
+
+
+def serialize_ssh_private_key(private_key, password=None):
+    """Serialize private key with OpenSSH custom encoding."""
+    if password is not None:
+        utils._check_bytes("password", password)
+    if password and len(password) > _MAX_PASSWORD:
+        raise ValueError(
+            "Passwords longer than 72 bytes are not supported by "
+            "OpenSSH private key format"
+        )
+
+    if isinstance(private_key, ec.EllipticCurvePrivateKey):
+        key_type = _ecdsa_key_type(private_key.public_key())
+    elif isinstance(private_key, rsa.RSAPrivateKey):
+        key_type = _SSH_RSA
+    elif isinstance(private_key, dsa.DSAPrivateKey):
+        key_type = _SSH_DSA
+    elif isinstance(private_key, ed25519.Ed25519PrivateKey):
+        key_type = _SSH_ED25519
+    else:
+        raise ValueError("Unsupported key type")
+    kformat = _lookup_kformat(key_type)
+
+    # setup parameters
+    f_kdfoptions = _FragList()
+    if password:
+        ciphername = _DEFAULT_CIPHER
+        blklen = _SSH_CIPHERS[ciphername][3]
+        kdfname = _BCRYPT
+        rounds = _DEFAULT_ROUNDS
+        salt = os.urandom(16)
+        f_kdfoptions.put_sshstr(salt)
+        f_kdfoptions.put_u32(rounds)
+        backend = _get_backend(None)
+        ciph = _init_cipher(ciphername, password, salt, rounds, backend)
+    else:
+        ciphername = kdfname = _NONE
+        blklen = 8
+        ciph = None
+    nkeys = 1
+    checkval = os.urandom(4)
+    comment = b""
+
+    # encode public and private parts together
+    f_public_key = _FragList()
+    f_public_key.put_sshstr(key_type)
+    kformat.encode_public(private_key.public_key(), f_public_key)
+
+    f_secrets = _FragList([checkval, checkval])
+    f_secrets.put_sshstr(key_type)
+    kformat.encode_private(private_key, f_secrets)
+    f_secrets.put_sshstr(comment)
+    f_secrets.put_raw(_PADDING[: blklen - (f_secrets.size() % blklen)])
+
+    # top-level structure
+    f_main = _FragList()
+    f_main.put_raw(_SK_MAGIC)
+    f_main.put_sshstr(ciphername)
+    f_main.put_sshstr(kdfname)
+    f_main.put_sshstr(f_kdfoptions)
+    f_main.put_u32(nkeys)
+    f_main.put_sshstr(f_public_key)
+    f_main.put_sshstr(f_secrets)
+
+    # copy result info bytearray
+    slen = f_secrets.size()
+    mlen = f_main.size()
+    buf = memoryview(bytearray(mlen + blklen))
+    f_main.render(buf)
+    ofs = mlen - slen
+
+    # encrypt in-place
+    if ciph is not None:
+        ciph.encryptor().update_into(buf[ofs:mlen], buf[ofs:])
+
+    txt = _ssh_pem_encode(buf[:mlen])
+    buf[ofs:mlen] = bytearray(slen)
+    return txt
+
+
+def load_ssh_public_key(data, backend=None):
+    """Load public key from OpenSSH one-line format."""
+    backend = _get_backend(backend)
+    utils._check_byteslike("data", data)
+
+    m = _SSH_PUBKEY_RC.match(data)
+    if not m:
+        raise ValueError("Invalid line format")
+    key_type = orig_key_type = m.group(1)
+    key_body = m.group(2)
+    with_cert = False
+    if _CERT_SUFFIX == key_type[-len(_CERT_SUFFIX) :]:
+        with_cert = True
+        key_type = key_type[: -len(_CERT_SUFFIX)]
+    kformat = _lookup_kformat(key_type)
 
     try:
-        decoded_data = base64.b64decode(key_body)
-    except TypeError:
-        raise ValueError('Key is not in the proper format.')
+        data = memoryview(binascii.a2b_base64(key_body))
+    except (TypeError, binascii.Error):
+        raise ValueError("Invalid key format")
 
-    inner_key_type, rest = _ssh_read_next_string(decoded_data)
-
-    if inner_key_type != key_type:
-        raise ValueError(
-            'Key header and key body contain different key type values.'
-        )
-
-    return loader(key_type, rest, backend)
+    inner_key_type, data = _get_sshstr(data)
+    if inner_key_type != orig_key_type:
+        raise ValueError("Invalid key format")
+    if with_cert:
+        nonce, data = _get_sshstr(data)
+    public_key, data = kformat.load_public(key_type, data, backend)
+    if with_cert:
+        serial, data = _get_u64(data)
+        cctype, data = _get_u32(data)
+        key_id, data = _get_sshstr(data)
+        principals, data = _get_sshstr(data)
+        valid_after, data = _get_u64(data)
+        valid_before, data = _get_u64(data)
+        crit_options, data = _get_sshstr(data)
+        extensions, data = _get_sshstr(data)
+        reserved, data = _get_sshstr(data)
+        sig_key, data = _get_sshstr(data)
+        signature, data = _get_sshstr(data)
+    _check_empty(data)
+    return public_key
 
 
-def _load_ssh_rsa_public_key(key_type, decoded_data, backend):
-    e, rest = _ssh_read_next_mpint(decoded_data)
-    n, rest = _ssh_read_next_mpint(rest)
+def serialize_ssh_public_key(public_key):
+    """One-line public key format for OpenSSH"""
+    if isinstance(public_key, ec.EllipticCurvePublicKey):
+        key_type = _ecdsa_key_type(public_key)
+    elif isinstance(public_key, rsa.RSAPublicKey):
+        key_type = _SSH_RSA
+    elif isinstance(public_key, dsa.DSAPublicKey):
+        key_type = _SSH_DSA
+    elif isinstance(public_key, ed25519.Ed25519PublicKey):
+        key_type = _SSH_ED25519
+    else:
+        raise ValueError("Unsupported key type")
+    kformat = _lookup_kformat(key_type)
 
-    if rest:
-        raise ValueError('Key body contains extra bytes.')
+    f_pub = _FragList()
+    f_pub.put_sshstr(key_type)
+    kformat.encode_public(public_key, f_pub)
 
-    return rsa.RSAPublicNumbers(e, n).public_key(backend)
-
-
-def _load_ssh_dss_public_key(key_type, decoded_data, backend):
-    p, rest = _ssh_read_next_mpint(decoded_data)
-    q, rest = _ssh_read_next_mpint(rest)
-    g, rest = _ssh_read_next_mpint(rest)
-    y, rest = _ssh_read_next_mpint(rest)
-
-    if rest:
-        raise ValueError('Key body contains extra bytes.')
-
-    parameter_numbers = dsa.DSAParameterNumbers(p, q, g)
-    public_numbers = dsa.DSAPublicNumbers(y, parameter_numbers)
-
-    return public_numbers.public_key(backend)
-
-
-def _load_ssh_ecdsa_public_key(expected_key_type, decoded_data, backend):
-    curve_name, rest = _ssh_read_next_string(decoded_data)
-    data, rest = _ssh_read_next_string(rest)
-
-    if expected_key_type != b"ecdsa-sha2-" + curve_name:
-        raise ValueError(
-            'Key header and key body contain different key type values.'
-        )
-
-    if rest:
-        raise ValueError('Key body contains extra bytes.')
-
-    curve = {
-        b"nistp256": ec.SECP256R1,
-        b"nistp384": ec.SECP384R1,
-        b"nistp521": ec.SECP521R1,
-    }[curve_name]()
-
-    if six.indexbytes(data, 0) != 4:
-        raise NotImplementedError(
-            "Compressed elliptic curve points are not supported"
-        )
-
-    return ec.EllipticCurvePublicKey.from_encoded_point(curve, data)
-
-
-def _ssh_read_next_string(data):
-    """
-    Retrieves the next RFC 4251 string value from the data.
-
-    While the RFC calls these strings, in Python they are bytes objects.
-    """
-    if len(data) < 4:
-        raise ValueError("Key is not in the proper format")
-
-    str_len, = struct.unpack('>I', data[:4])
-    if len(data) < str_len + 4:
-        raise ValueError("Key is not in the proper format")
-
-    return data[4:4 + str_len], data[4 + str_len:]
-
-
-def _ssh_read_next_mpint(data):
-    """
-    Reads the next mpint from the data.
-
-    Currently, all mpints are interpreted as unsigned.
-    """
-    mpint_data, rest = _ssh_read_next_string(data)
-
-    return (
-        utils.int_from_bytes(mpint_data, byteorder='big', signed=False), rest
-    )
-
-
-def _ssh_write_string(data):
-    return struct.pack(">I", len(data)) + data
-
-
-def _ssh_write_mpint(value):
-    data = utils.int_to_bytes(value)
-    if six.indexbytes(data, 0) & 0x80:
-        data = b"\x00" + data
-    return _ssh_write_string(data)
+    pub = binascii.b2a_base64(f_pub.tobytes()).strip()
+    return b"".join([key_type, b" ", pub])
diff --git a/src/cryptography/hazmat/primitives/twofactor/hotp.py b/src/cryptography/hazmat/primitives/twofactor/hotp.py
index 4ad1bdc..c00eec0 100644
--- a/src/cryptography/hazmat/primitives/twofactor/hotp.py
+++ b/src/cryptography/hazmat/primitives/twofactor/hotp.py
@@ -8,9 +8,8 @@
 
 import six
 
-from cryptography.exceptions import (
-    UnsupportedAlgorithm, _Reasons
-)
+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, hmac
 from cryptography.hazmat.primitives.hashes import SHA1, SHA256, SHA512
@@ -19,12 +18,14 @@
 
 
 class HOTP(object):
-    def __init__(self, key, length, algorithm, backend,
-                 enforce_key_length=True):
+    def __init__(
+        self, key, length, algorithm, backend=None, enforce_key_length=True
+    ):
+        backend = _get_backend(backend)
         if not isinstance(backend, HMACBackend):
             raise UnsupportedAlgorithm(
                 "Backend object does not implement HMACBackend.",
-                _Reasons.BACKEND_MISSING_INTERFACE
+                _Reasons.BACKEND_MISSING_INTERFACE,
             )
 
         if len(key) < 16 and enforce_key_length is True:
@@ -59,10 +60,10 @@
         hmac_value = ctx.finalize()
 
         offset = six.indexbytes(hmac_value, len(hmac_value) - 1) & 0b1111
-        p = hmac_value[offset:offset + 4]
-        return struct.unpack(">I", p)[0] & 0x7fffffff
+        p = hmac_value[offset : offset + 4]
+        return struct.unpack(">I", p)[0] & 0x7FFFFFFF
 
     def get_provisioning_uri(self, account_name, counter, issuer):
-        return _generate_uri(self, "hotp", account_name, issuer, [
-            ("counter", int(counter)),
-        ])
+        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 499f282..d59539b 100644
--- a/src/cryptography/hazmat/primitives/twofactor/totp.py
+++ b/src/cryptography/hazmat/primitives/twofactor/totp.py
@@ -4,9 +4,8 @@
 
 from __future__ import absolute_import, division, print_function
 
-from cryptography.exceptions import (
-    UnsupportedAlgorithm, _Reasons
-)
+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
@@ -15,12 +14,20 @@
 
 
 class TOTP(object):
-    def __init__(self, key, length, algorithm, time_step, backend,
-                 enforce_key_length=True):
+    def __init__(
+        self,
+        key,
+        length,
+        algorithm,
+        time_step,
+        backend=None,
+        enforce_key_length=True,
+    ):
+        backend = _get_backend(backend)
         if not isinstance(backend, HMACBackend):
             raise UnsupportedAlgorithm(
                 "Backend object does not implement HMACBackend.",
-                _Reasons.BACKEND_MISSING_INTERFACE
+                _Reasons.BACKEND_MISSING_INTERFACE,
             )
 
         self._time_step = time_step
@@ -35,6 +42,10 @@
             raise InvalidToken("Supplied TOTP value does not match.")
 
     def get_provisioning_uri(self, account_name, issuer):
-        return _generate_uri(self._hotp, "totp", account_name, issuer, [
-            ("period", int(self._time_step)),
-        ])
+        return _generate_uri(
+            self._hotp,
+            "totp",
+            account_name,
+            issuer,
+            [("period", int(self._time_step))],
+        )
diff --git a/src/cryptography/hazmat/primitives/twofactor/utils.py b/src/cryptography/hazmat/primitives/twofactor/utils.py
index 0ed8c4c..0afa1cc 100644
--- a/src/cryptography/hazmat/primitives/twofactor/utils.py
+++ b/src/cryptography/hazmat/primitives/twofactor/utils.py
@@ -23,8 +23,11 @@
 
     uriparts = {
         "type": type_name,
-        "label": ("%s:%s" % (quote(issuer), quote(account_name)) if issuer
-                  else quote(account_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)
diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py
index cbbae3a..bdb3dbf 100644
--- a/src/cryptography/utils.py
+++ b/src/cryptography/utils.py
@@ -20,22 +20,20 @@
 # Several APIs were deprecated with no specific end-of-life date because of the
 # ubiquity of their use. They should not be removed until we agree on when that
 # cycle ends.
-PersistentlyDeprecated = CryptographyDeprecationWarning
-DeprecatedIn21 = CryptographyDeprecationWarning
-DeprecatedIn23 = CryptographyDeprecationWarning
-DeprecatedIn25 = CryptographyDeprecationWarning
+PersistentlyDeprecated2017 = CryptographyDeprecationWarning
+PersistentlyDeprecated2019 = CryptographyDeprecationWarning
 
 
 def _check_bytes(name, value):
     if not isinstance(value, bytes):
-        raise TypeError("{0} must be bytes".format(name))
+        raise TypeError("{} must be bytes".format(name))
 
 
 def _check_byteslike(name, value):
     try:
         memoryview(value)
     except TypeError:
-        raise TypeError("{0} must be bytes-like".format(name))
+        raise TypeError("{} must be bytes-like".format(name))
 
 
 def read_only_property(name):
@@ -47,6 +45,7 @@
         verify_interface(iface, klass)
         iface.register(klass)
         return klass
+
     return register_decorator
 
 
@@ -56,27 +55,33 @@
             verify_interface(iface, klass)
             iface.register(klass)
         return klass
+
     return register_decorator
 
 
 if hasattr(int, "from_bytes"):
     int_from_bytes = int.from_bytes
 else:
+
     def int_from_bytes(data, byteorder, signed=False):
-        assert byteorder == 'big'
+        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'
+            length or (integer.bit_length() + 7) // 8 or 1, "big"
         )
+
+
 else:
+
     def int_to_bytes(integer, length=None):
-        hex_string = '%x' % integer
+        hex_string = "%x" % integer
         if length is None:
             n = len(hex_string)
         else:
@@ -98,7 +103,7 @@
     for method in iface.__abstractmethods__:
         if not hasattr(klass, method):
             raise InterfaceNotImplemented(
-                "{0} is missing a {1!r} method".format(klass, method)
+                "{} is missing a {!r} method".format(klass, method)
             )
         if isinstance(getattr(iface, method), abc.abstractproperty):
             # Can't properly verify these yet.
@@ -107,19 +112,11 @@
         actual = signature(getattr(klass, method))
         if sig != actual:
             raise InterfaceNotImplemented(
-                "{0}.{1}'s signature differs from the expected. Expected: "
-                "{2!r}. Received: {3!r}".format(
-                    klass, method, sig, actual
-                )
+                "{}.{}'s signature differs from the expected. Expected: "
+                "{!r}. Received: {!r}".format(klass, method, sig, actual)
             )
 
 
-# No longer needed as of 2.2, but retained because we have external consumers
-# who use it.
-def bit_length(x):
-    return x.bit_length()
-
-
 class _DeprecatedValue(object):
     def __init__(self, value, message, warning_class):
         self.value = value
@@ -160,7 +157,7 @@
 
 
 def cached_property(func):
-    cached_name = "_cached_{0}".format(func)
+    cached_name = "_cached_{}".format(func)
     sentinel = object()
 
     def inner(instance):
@@ -170,4 +167,5 @@
         result = func(instance)
         setattr(instance, cached_name, result)
         return result
+
     return property(inner)
diff --git a/src/cryptography/x509/__init__.py b/src/cryptography/x509/__init__.py
index b761e26..69630e4 100644
--- a/src/cryptography/x509/__init__.py
+++ b/src/cryptography/x509/__init__.py
@@ -6,39 +6,95 @@
 
 from cryptography.x509 import certificate_transparency
 from cryptography.x509.base import (
-    Certificate, CertificateBuilder, CertificateRevocationList,
+    AttributeNotFound,
+    Certificate,
+    CertificateBuilder,
+    CertificateRevocationList,
     CertificateRevocationListBuilder,
-    CertificateSigningRequest, CertificateSigningRequestBuilder,
-    InvalidVersion, RevokedCertificate, RevokedCertificateBuilder,
-    Version, load_der_x509_certificate, load_der_x509_crl, load_der_x509_csr,
-    load_pem_x509_certificate, load_pem_x509_crl, load_pem_x509_csr,
+    CertificateSigningRequest,
+    CertificateSigningRequestBuilder,
+    InvalidVersion,
+    RevokedCertificate,
+    RevokedCertificateBuilder,
+    Version,
+    load_der_x509_certificate,
+    load_der_x509_crl,
+    load_der_x509_csr,
+    load_pem_x509_certificate,
+    load_pem_x509_crl,
+    load_pem_x509_csr,
     random_serial_number,
 )
 from cryptography.x509.extensions import (
-    AccessDescription, AuthorityInformationAccess,
-    AuthorityKeyIdentifier, BasicConstraints, CRLDistributionPoints,
-    CRLNumber, CRLReason, CertificateIssuer, CertificatePolicies,
-    DeltaCRLIndicator, DistributionPoint, DuplicateExtension, ExtendedKeyUsage,
-    Extension, ExtensionNotFound, ExtensionType, Extensions, FreshestCRL,
-    GeneralNames, InhibitAnyPolicy, InvalidityDate, IssuerAlternativeName,
-    IssuingDistributionPoint, KeyUsage, NameConstraints, NoticeReference,
-    OCSPNoCheck, OCSPNonce, PolicyConstraints, PolicyInformation,
-    PrecertPoison, PrecertificateSignedCertificateTimestamps, ReasonFlags,
-    SubjectAlternativeName, SubjectKeyIdentifier, TLSFeature, TLSFeatureType,
-    UnrecognizedExtension, UserNotice
+    AccessDescription,
+    AuthorityInformationAccess,
+    AuthorityKeyIdentifier,
+    BasicConstraints,
+    CRLDistributionPoints,
+    CRLNumber,
+    CRLReason,
+    CertificateIssuer,
+    CertificatePolicies,
+    DeltaCRLIndicator,
+    DistributionPoint,
+    DuplicateExtension,
+    ExtendedKeyUsage,
+    Extension,
+    ExtensionNotFound,
+    ExtensionType,
+    Extensions,
+    FreshestCRL,
+    GeneralNames,
+    InhibitAnyPolicy,
+    InvalidityDate,
+    IssuerAlternativeName,
+    IssuingDistributionPoint,
+    KeyUsage,
+    NameConstraints,
+    NoticeReference,
+    OCSPNoCheck,
+    OCSPNonce,
+    PolicyConstraints,
+    PolicyInformation,
+    PrecertPoison,
+    PrecertificateSignedCertificateTimestamps,
+    ReasonFlags,
+    SignedCertificateTimestamps,
+    SubjectAlternativeName,
+    SubjectInformationAccess,
+    SubjectKeyIdentifier,
+    TLSFeature,
+    TLSFeatureType,
+    UnrecognizedExtension,
+    UserNotice,
 )
 from cryptography.x509.general_name import (
-    DNSName, DirectoryName, GeneralName, IPAddress, OtherName, RFC822Name,
-    RegisteredID, UniformResourceIdentifier, UnsupportedGeneralNameType,
-    _GENERAL_NAMES
+    DNSName,
+    DirectoryName,
+    GeneralName,
+    IPAddress,
+    OtherName,
+    RFC822Name,
+    RegisteredID,
+    UniformResourceIdentifier,
+    UnsupportedGeneralNameType,
+    _GENERAL_NAMES,
 )
 from cryptography.x509.name import (
-    Name, NameAttribute, RelativeDistinguishedName
+    Name,
+    NameAttribute,
+    RelativeDistinguishedName,
 )
 from cryptography.x509.oid import (
-    AuthorityInformationAccessOID, CRLEntryExtensionOID,
-    CertificatePoliciesOID, ExtendedKeyUsageOID, ExtensionOID, NameOID,
-    ObjectIdentifier, SignatureAlgorithmOID, _SIG_OIDS_TO_HASH
+    AuthorityInformationAccessOID,
+    CRLEntryExtensionOID,
+    CertificatePoliciesOID,
+    ExtendedKeyUsageOID,
+    ExtensionOID,
+    NameOID,
+    ObjectIdentifier,
+    SignatureAlgorithmOID,
+    _SIG_OIDS_TO_HASH,
 )
 
 
@@ -120,6 +176,7 @@
     "load_pem_x509_crl",
     "load_der_x509_crl",
     "random_serial_number",
+    "AttributeNotFound",
     "InvalidVersion",
     "DeltaCRLIndicator",
     "DuplicateExtension",
@@ -142,6 +199,7 @@
     "CRLNumber",
     "KeyUsage",
     "AuthorityInformationAccess",
+    "SubjectInformationAccess",
     "AccessDescription",
     "CertificatePolicies",
     "PolicyInformation",
@@ -186,4 +244,5 @@
     "PrecertificateSignedCertificateTimestamps",
     "PrecertPoison",
     "OCSPNonce",
+    "SignedCertificateTimestamps",
 ]
diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py
index 63c2e3c..f3bc872 100644
--- a/src/cryptography/x509/base.py
+++ b/src/cryptography/x509/base.py
@@ -12,19 +12,40 @@
 import six
 
 from cryptography import utils
-from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
+from cryptography.hazmat.backends import _get_backend
+from cryptography.hazmat.primitives.asymmetric import (
+    dsa,
+    ec,
+    ed25519,
+    ed448,
+    rsa,
+)
 from cryptography.x509.extensions import Extension, ExtensionType
 from cryptography.x509.name import Name
+from cryptography.x509.oid import ObjectIdentifier
 
 
 _EARLIEST_UTC_TIME = datetime.datetime(1950, 1, 1)
 
 
+class AttributeNotFound(Exception):
+    def __init__(self, msg, oid):
+        super(AttributeNotFound, self).__init__(msg)
+        self.oid = oid
+
+
 def _reject_duplicate_extension(extension, extensions):
     # 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.')
+            raise ValueError("This extension has already been set.")
+
+
+def _reject_duplicate_attribute(oid, attributes):
+    # 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):
@@ -46,27 +67,33 @@
     v3 = 2
 
 
-def load_pem_x509_certificate(data, backend):
+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):
+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):
+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):
+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):
+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):
+def load_der_x509_crl(data, backend=None):
+    backend = _get_backend(backend)
     return backend.load_der_x509_crl(data)
 
 
@@ -365,6 +392,12 @@
         Verifies signature of signing request.
         """
 
+    @abc.abstractproperty
+    def get_attribute_for_oid(self):
+        """
+        Get the attribute value for a given OID.
+        """
+
 
 @six.add_metaclass(abc.ABCMeta)
 class RevokedCertificate(object):
@@ -388,22 +421,25 @@
 
 
 class CertificateSigningRequestBuilder(object):
-    def __init__(self, subject_name=None, extensions=[]):
+    def __init__(self, subject_name=None, extensions=[], attributes=[]):
         """
         Creates an empty X.509 certificate request (v1).
         """
         self._subject_name = subject_name
         self._extensions = extensions
+        self._attributes = attributes
 
     def subject_name(self, name):
         """
         Sets the certificate requestor's distinguished name.
         """
         if not isinstance(name, Name):
-            raise TypeError('Expecting x509.Name object.')
+            raise TypeError("Expecting x509.Name object.")
         if self._subject_name is not None:
-            raise ValueError('The subject name may only be set once.')
-        return CertificateSigningRequestBuilder(name, self._extensions)
+            raise ValueError("The subject name may only be set once.")
+        return CertificateSigningRequestBuilder(
+            name, self._extensions, self._attributes
+        )
 
     def add_extension(self, extension, critical):
         """
@@ -416,22 +452,50 @@
         _reject_duplicate_extension(extension, self._extensions)
 
         return CertificateSigningRequestBuilder(
-            self._subject_name, self._extensions + [extension]
+            self._subject_name,
+            self._extensions + [extension],
+            self._attributes,
         )
 
-    def sign(self, private_key, algorithm, backend):
+    def add_attribute(self, oid, value):
+        """
+        Adds an X.509 attribute with an OID and associated value.
+        """
+        if not isinstance(oid, ObjectIdentifier):
+            raise TypeError("oid must be an ObjectIdentifier")
+
+        if not isinstance(value, bytes):
+            raise TypeError("value must be bytes")
+
+        _reject_duplicate_attribute(oid, self._attributes)
+
+        return CertificateSigningRequestBuilder(
+            self._subject_name,
+            self._extensions,
+            self._attributes + [(oid, value)],
+        )
+
+    def sign(self, private_key, algorithm, backend=None):
         """
         Signs the request using the requestor's private key.
         """
+        backend = _get_backend(backend)
         if self._subject_name is None:
             raise ValueError("A CertificateSigningRequest must have a subject")
         return backend.create_x509_csr(self, private_key, algorithm)
 
 
 class CertificateBuilder(object):
-    def __init__(self, issuer_name=None, subject_name=None,
-                 public_key=None, serial_number=None, not_valid_before=None,
-                 not_valid_after=None, extensions=[]):
+    def __init__(
+        self,
+        issuer_name=None,
+        subject_name=None,
+        public_key=None,
+        serial_number=None,
+        not_valid_before=None,
+        not_valid_after=None,
+        extensions=[],
+    ):
         self._version = Version.v3
         self._issuer_name = issuer_name
         self._subject_name = subject_name
@@ -446,13 +510,17 @@
         Sets the CA's distinguished name.
         """
         if not isinstance(name, Name):
-            raise TypeError('Expecting x509.Name object.')
+            raise TypeError("Expecting x509.Name object.")
         if self._issuer_name is not None:
-            raise ValueError('The issuer name may only be set once.')
+            raise ValueError("The issuer name may only be set once.")
         return CertificateBuilder(
-            name, self._subject_name, self._public_key,
-            self._serial_number, self._not_valid_before,
-            self._not_valid_after, self._extensions
+            name,
+            self._subject_name,
+            self._public_key,
+            self._serial_number,
+            self._not_valid_before,
+            self._not_valid_after,
+            self._extensions,
         )
 
     def subject_name(self, name):
@@ -460,29 +528,48 @@
         Sets the requestor's distinguished name.
         """
         if not isinstance(name, Name):
-            raise TypeError('Expecting x509.Name object.')
+            raise TypeError("Expecting x509.Name object.")
         if self._subject_name is not None:
-            raise ValueError('The subject name may only be set once.')
+            raise ValueError("The subject name may only be set once.")
         return CertificateBuilder(
-            self._issuer_name, name, self._public_key,
-            self._serial_number, self._not_valid_before,
-            self._not_valid_after, self._extensions
+            self._issuer_name,
+            name,
+            self._public_key,
+            self._serial_number,
+            self._not_valid_before,
+            self._not_valid_after,
+            self._extensions,
         )
 
     def public_key(self, key):
         """
         Sets the requestor's public key (as found in the signing request).
         """
-        if not isinstance(key, (dsa.DSAPublicKey, rsa.RSAPublicKey,
-                                ec.EllipticCurvePublicKey)):
-            raise TypeError('Expecting one of DSAPublicKey, RSAPublicKey,'
-                            ' or EllipticCurvePublicKey.')
+        if not isinstance(
+            key,
+            (
+                dsa.DSAPublicKey,
+                rsa.RSAPublicKey,
+                ec.EllipticCurvePublicKey,
+                ed25519.Ed25519PublicKey,
+                ed448.Ed448PublicKey,
+            ),
+        ):
+            raise TypeError(
+                "Expecting one of DSAPublicKey, RSAPublicKey,"
+                " EllipticCurvePublicKey, Ed25519PublicKey or"
+                " Ed448PublicKey."
+            )
         if self._public_key is not None:
-            raise ValueError('The public key may only be set once.')
+            raise ValueError("The public key may only be set once.")
         return CertificateBuilder(
-            self._issuer_name, self._subject_name, key,
-            self._serial_number, self._not_valid_before,
-            self._not_valid_after, self._extensions
+            self._issuer_name,
+            self._subject_name,
+            key,
+            self._serial_number,
+            self._not_valid_before,
+            self._not_valid_after,
+            self._extensions,
         )
 
     def serial_number(self, number):
@@ -490,21 +577,26 @@
         Sets the certificate serial number.
         """
         if not isinstance(number, six.integer_types):
-            raise TypeError('Serial number must be of integral type.')
+            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.')
+            raise ValueError("The serial number may only be set once.")
         if number <= 0:
-            raise ValueError('The serial number should be positive.')
+            raise ValueError("The serial number should be positive.")
 
         # ASN.1 integers are always signed, so most significant bit must be
         # zero.
         if number.bit_length() >= 160:  # As defined in RFC 5280
-            raise ValueError('The serial number should not be more than 159 '
-                             'bits.')
+            raise ValueError(
+                "The serial number should not be more than 159 " "bits."
+            )
         return CertificateBuilder(
-            self._issuer_name, self._subject_name,
-            self._public_key, number, self._not_valid_before,
-            self._not_valid_after, self._extensions
+            self._issuer_name,
+            self._subject_name,
+            self._public_key,
+            number,
+            self._not_valid_before,
+            self._not_valid_after,
+            self._extensions,
         )
 
     def not_valid_before(self, time):
@@ -512,22 +604,28 @@
         Sets the certificate activation time.
         """
         if not isinstance(time, datetime.datetime):
-            raise TypeError('Expecting datetime object.')
+            raise TypeError("Expecting datetime object.")
         if self._not_valid_before is not None:
-            raise ValueError('The not valid before may only be set once.')
+            raise ValueError("The not valid before may only be set once.")
         time = _convert_to_naive_utc_time(time)
         if time < _EARLIEST_UTC_TIME:
-            raise ValueError('The not valid before date must be on or after'
-                             ' 1950 January 1).')
+            raise ValueError(
+                "The not valid before date must be on or after"
+                " 1950 January 1)."
+            )
         if self._not_valid_after is not None and time > self._not_valid_after:
             raise ValueError(
-                'The not valid before date must be before the not valid after '
-                'date.'
+                "The not valid before date must be before the not valid after "
+                "date."
             )
         return CertificateBuilder(
-            self._issuer_name, self._subject_name,
-            self._public_key, self._serial_number, time,
-            self._not_valid_after, self._extensions
+            self._issuer_name,
+            self._subject_name,
+            self._public_key,
+            self._serial_number,
+            time,
+            self._not_valid_after,
+            self._extensions,
         )
 
     def not_valid_after(self, time):
@@ -535,23 +633,31 @@
         Sets the certificate expiration time.
         """
         if not isinstance(time, datetime.datetime):
-            raise TypeError('Expecting datetime object.')
+            raise TypeError("Expecting datetime object.")
         if self._not_valid_after is not None:
-            raise ValueError('The not valid after may only be set once.')
+            raise ValueError("The not valid after may only be set once.")
         time = _convert_to_naive_utc_time(time)
         if time < _EARLIEST_UTC_TIME:
-            raise ValueError('The not valid after date must be on or after'
-                             ' 1950 January 1.')
-        if (self._not_valid_before is not None and
-                time < self._not_valid_before):
             raise ValueError(
-                'The not valid after date must be after the not valid before '
-                'date.'
+                "The not valid after date must be on or after"
+                " 1950 January 1."
+            )
+        if (
+            self._not_valid_before is not None
+            and time < self._not_valid_before
+        ):
+            raise ValueError(
+                "The not valid after date must be after the not valid before "
+                "date."
             )
         return CertificateBuilder(
-            self._issuer_name, self._subject_name,
-            self._public_key, self._serial_number, self._not_valid_before,
-            time, self._extensions
+            self._issuer_name,
+            self._subject_name,
+            self._public_key,
+            self._serial_number,
+            self._not_valid_before,
+            time,
+            self._extensions,
         )
 
     def add_extension(self, extension, critical):
@@ -565,15 +671,20 @@
         _reject_duplicate_extension(extension, self._extensions)
 
         return CertificateBuilder(
-            self._issuer_name, self._subject_name,
-            self._public_key, self._serial_number, self._not_valid_before,
-            self._not_valid_after, self._extensions + [extension]
+            self._issuer_name,
+            self._subject_name,
+            self._public_key,
+            self._serial_number,
+            self._not_valid_before,
+            self._not_valid_after,
+            self._extensions + [extension],
         )
 
-    def sign(self, private_key, algorithm, backend):
+    def sign(self, private_key, algorithm, backend=None):
         """
         Signs the certificate using the CA's private key.
         """
+        backend = _get_backend(backend)
         if self._subject_name is None:
             raise ValueError("A certificate must have a subject name")
 
@@ -596,8 +707,14 @@
 
 
 class CertificateRevocationListBuilder(object):
-    def __init__(self, issuer_name=None, last_update=None, next_update=None,
-                 extensions=[], revoked_certificates=[]):
+    def __init__(
+        self,
+        issuer_name=None,
+        last_update=None,
+        next_update=None,
+        extensions=[],
+        revoked_certificates=[],
+    ):
         self._issuer_name = issuer_name
         self._last_update = last_update
         self._next_update = next_update
@@ -606,48 +723,59 @@
 
     def issuer_name(self, issuer_name):
         if not isinstance(issuer_name, Name):
-            raise TypeError('Expecting x509.Name object.')
+            raise TypeError("Expecting x509.Name object.")
         if self._issuer_name is not None:
-            raise ValueError('The issuer name may only be set once.')
+            raise ValueError("The issuer name may only be set once.")
         return CertificateRevocationListBuilder(
-            issuer_name, self._last_update, self._next_update,
-            self._extensions, self._revoked_certificates
+            issuer_name,
+            self._last_update,
+            self._next_update,
+            self._extensions,
+            self._revoked_certificates,
         )
 
     def last_update(self, last_update):
         if not isinstance(last_update, datetime.datetime):
-            raise TypeError('Expecting datetime object.')
+            raise TypeError("Expecting datetime object.")
         if self._last_update is not None:
-            raise ValueError('Last update may only be set once.')
+            raise ValueError("Last update may only be set once.")
         last_update = _convert_to_naive_utc_time(last_update)
         if last_update < _EARLIEST_UTC_TIME:
-            raise ValueError('The last update date must be on or after'
-                             ' 1950 January 1.')
+            raise ValueError(
+                "The last update date must be on or after" " 1950 January 1."
+            )
         if self._next_update is not None and last_update > self._next_update:
             raise ValueError(
-                'The last update date must be before the next update date.'
+                "The last update date must be before the next update date."
             )
         return CertificateRevocationListBuilder(
-            self._issuer_name, last_update, self._next_update,
-            self._extensions, self._revoked_certificates
+            self._issuer_name,
+            last_update,
+            self._next_update,
+            self._extensions,
+            self._revoked_certificates,
         )
 
     def next_update(self, next_update):
         if not isinstance(next_update, datetime.datetime):
-            raise TypeError('Expecting datetime object.')
+            raise TypeError("Expecting datetime object.")
         if self._next_update is not None:
-            raise ValueError('Last update may only be set once.')
+            raise ValueError("Last update may only be set once.")
         next_update = _convert_to_naive_utc_time(next_update)
         if next_update < _EARLIEST_UTC_TIME:
-            raise ValueError('The last update date must be on or after'
-                             ' 1950 January 1.')
+            raise ValueError(
+                "The last update date must be on or after" " 1950 January 1."
+            )
         if self._last_update is not None and next_update < self._last_update:
             raise ValueError(
-                'The next update date must be after the last update date.'
+                "The next update date must be after the last update date."
             )
         return CertificateRevocationListBuilder(
-            self._issuer_name, self._last_update, next_update,
-            self._extensions, self._revoked_certificates
+            self._issuer_name,
+            self._last_update,
+            next_update,
+            self._extensions,
+            self._revoked_certificates,
         )
 
     def add_extension(self, extension, critical):
@@ -660,8 +788,11 @@
         extension = Extension(extension.oid, critical, extension)
         _reject_duplicate_extension(extension, self._extensions)
         return CertificateRevocationListBuilder(
-            self._issuer_name, self._last_update, self._next_update,
-            self._extensions + [extension], self._revoked_certificates
+            self._issuer_name,
+            self._last_update,
+            self._next_update,
+            self._extensions + [extension],
+            self._revoked_certificates,
         )
 
     def add_revoked_certificate(self, revoked_certificate):
@@ -672,12 +803,15 @@
             raise TypeError("Must be an instance of RevokedCertificate")
 
         return CertificateRevocationListBuilder(
-            self._issuer_name, self._last_update,
-            self._next_update, self._extensions,
-            self._revoked_certificates + [revoked_certificate]
+            self._issuer_name,
+            self._last_update,
+            self._next_update,
+            self._extensions,
+            self._revoked_certificates + [revoked_certificate],
         )
 
-    def sign(self, private_key, algorithm, backend):
+    def sign(self, private_key, algorithm, backend=None):
+        backend = _get_backend(backend)
         if self._issuer_name is None:
             raise ValueError("A CRL must have an issuer name")
 
@@ -691,38 +825,41 @@
 
 
 class RevokedCertificateBuilder(object):
-    def __init__(self, serial_number=None, revocation_date=None,
-                 extensions=[]):
+    def __init__(
+        self, serial_number=None, revocation_date=None, extensions=[]
+    ):
         self._serial_number = serial_number
         self._revocation_date = revocation_date
         self._extensions = extensions
 
     def serial_number(self, number):
         if not isinstance(number, six.integer_types):
-            raise TypeError('Serial number must be of integral type.')
+            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.')
+            raise ValueError("The serial number may only be set once.")
         if number <= 0:
-            raise ValueError('The serial number should be positive')
+            raise ValueError("The serial number should be positive")
 
         # ASN.1 integers are always signed, so most significant bit must be
         # zero.
         if number.bit_length() >= 160:  # As defined in RFC 5280
-            raise ValueError('The serial number should not be more than 159 '
-                             'bits.')
+            raise ValueError(
+                "The serial number should not be more than 159 " "bits."
+            )
         return RevokedCertificateBuilder(
             number, self._revocation_date, self._extensions
         )
 
     def revocation_date(self, time):
         if not isinstance(time, datetime.datetime):
-            raise TypeError('Expecting datetime object.')
+            raise TypeError("Expecting datetime object.")
         if self._revocation_date is not None:
-            raise ValueError('The revocation date may only be set once.')
+            raise ValueError("The revocation date may only be set once.")
         time = _convert_to_naive_utc_time(time)
         if time < _EARLIEST_UTC_TIME:
-            raise ValueError('The revocation date must be on or after'
-                             ' 1950 January 1.')
+            raise ValueError(
+                "The revocation date must be on or after" " 1950 January 1."
+            )
         return RevokedCertificateBuilder(
             self._serial_number, time, self._extensions
         )
@@ -734,11 +871,13 @@
         extension = Extension(extension.oid, critical, extension)
         _reject_duplicate_extension(extension, self._extensions)
         return RevokedCertificateBuilder(
-            self._serial_number, self._revocation_date,
-            self._extensions + [extension]
+            self._serial_number,
+            self._revocation_date,
+            self._extensions + [extension],
         )
 
-    def build(self, backend):
+    def build(self, backend=None):
+        backend = _get_backend(backend)
         if self._serial_number is None:
             raise ValueError("A revoked certificate must have a serial number")
         if self._revocation_date is None:
diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py
index 88afa31..130ba69 100644
--- a/src/cryptography/x509/extensions.py
+++ b/src/cryptography/x509/extensions.py
@@ -10,21 +10,28 @@
 import ipaddress
 from enum import Enum
 
-from asn1crypto.keys import PublicKeyInfo
-
 import six
 
 from cryptography import utils
+from cryptography.hazmat._der import (
+    BIT_STRING,
+    DERReader,
+    OBJECT_IDENTIFIER,
+    SEQUENCE,
+)
 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.x509.certificate_transparency import (
-    SignedCertificateTimestamp
+    SignedCertificateTimestamp,
 )
 from cryptography.x509.general_name import GeneralName, IPAddress, OtherName
 from cryptography.x509.name import RelativeDistinguishedName
 from cryptography.x509.oid import (
-    CRLEntryExtensionOID, ExtensionOID, OCSPExtensionOID, ObjectIdentifier,
+    CRLEntryExtensionOID,
+    ExtensionOID,
+    OCSPExtensionOID,
+    ObjectIdentifier,
 )
 
 
@@ -37,20 +44,50 @@
     elif isinstance(public_key, EllipticCurvePublicKey):
         data = public_key.public_bytes(
             serialization.Encoding.X962,
-            serialization.PublicFormat.UncompressedPoint
+            serialization.PublicFormat.UncompressedPoint,
         )
     else:
         # This is a very slow way to do this.
         serialized = public_key.public_bytes(
             serialization.Encoding.DER,
-            serialization.PublicFormat.SubjectPublicKeyInfo
+            serialization.PublicFormat.SubjectPublicKeyInfo,
         )
 
-        data = bytes(PublicKeyInfo.load(serialized)['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)
+
+        # 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.read_byte() != 0:
+            raise ValueError("Invalid public key encoding")
+
+        data = public_key.data
 
     return hashlib.sha1(data).digest()
 
 
+def _make_sequence_methods(field_name):
+    def len_method(self):
+        return len(getattr(self, field_name))
+
+    def iter_method(self):
+        return iter(getattr(self, field_name))
+
+    def getitem_method(self, idx):
+        return getattr(self, field_name)[idx]
+
+    return len_method, iter_method, getitem_method
+
+
 class DuplicateExtension(Exception):
     def __init__(self, msg, oid):
         super(DuplicateExtension, self).__init__(msg)
@@ -81,7 +118,7 @@
             if ext.oid == oid:
                 return ext
 
-        raise ExtensionNotFound("No {0} extension was found".format(oid), oid)
+        raise ExtensionNotFound("No {} extension was found".format(oid), oid)
 
     def get_extension_for_class(self, extclass):
         if extclass is UnrecognizedExtension:
@@ -96,22 +133,13 @@
                 return ext
 
         raise ExtensionNotFound(
-            "No {0} extension was found".format(extclass), extclass.oid
+            "No {} extension was found".format(extclass), extclass.oid
         )
 
-    def __iter__(self):
-        return iter(self._extensions)
-
-    def __len__(self):
-        return len(self._extensions)
-
-    def __getitem__(self, idx):
-        return self._extensions[idx]
+    __len__, __iter__, __getitem__ = _make_sequence_methods("_extensions")
 
     def __repr__(self):
-        return (
-            "<Extensions({0})>".format(self._extensions)
-        )
+        return "<Extensions({})>".format(self._extensions)
 
 
 @utils.register_interface(ExtensionType)
@@ -137,7 +165,7 @@
         return hash(self.crl_number)
 
     def __repr__(self):
-        return "<CRLNumber({0})>".format(self.crl_number)
+        return "<CRLNumber({})>".format(self.crl_number)
 
     crl_number = utils.read_only_property("_crl_number")
 
@@ -146,8 +174,12 @@
 class AuthorityKeyIdentifier(object):
     oid = ExtensionOID.AUTHORITY_KEY_IDENTIFIER
 
-    def __init__(self, key_identifier, authority_cert_issuer,
-                 authority_cert_serial_number):
+    def __init__(
+        self,
+        key_identifier,
+        authority_cert_issuer,
+        authority_cert_serial_number,
+    ):
         if (authority_cert_issuer is None) != (
             authority_cert_serial_number is None
         ):
@@ -169,9 +201,7 @@
         if authority_cert_serial_number is not None and not isinstance(
             authority_cert_serial_number, six.integer_types
         ):
-            raise TypeError(
-                "authority_cert_serial_number must be an integer"
-            )
+            raise TypeError("authority_cert_serial_number must be an integer")
 
         self._key_identifier = key_identifier
         self._authority_cert_issuer = authority_cert_issuer
@@ -183,15 +213,15 @@
         return cls(
             key_identifier=digest,
             authority_cert_issuer=None,
-            authority_cert_serial_number=None
+            authority_cert_serial_number=None,
         )
 
     @classmethod
     def from_issuer_subject_key_identifier(cls, ski):
         return cls(
-            key_identifier=ski.value.digest,
+            key_identifier=ski.digest,
             authority_cert_issuer=None,
-            authority_cert_serial_number=None
+            authority_cert_serial_number=None,
         )
 
     def __repr__(self):
@@ -207,10 +237,10 @@
             return NotImplemented
 
         return (
-            self.key_identifier == other.key_identifier and
-            self.authority_cert_issuer == other.authority_cert_issuer and
-            self.authority_cert_serial_number ==
-            other.authority_cert_serial_number
+            self.key_identifier == other.key_identifier
+            and self.authority_cert_issuer == other.authority_cert_issuer
+            and self.authority_cert_serial_number
+            == other.authority_cert_serial_number
         )
 
     def __ne__(self, other):
@@ -221,9 +251,9 @@
             aci = None
         else:
             aci = tuple(self.authority_cert_issuer)
-        return hash((
-            self.key_identifier, aci, self.authority_cert_serial_number
-        ))
+        return hash(
+            (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")
@@ -275,14 +305,10 @@
 
         self._descriptions = descriptions
 
-    def __iter__(self):
-        return iter(self._descriptions)
-
-    def __len__(self):
-        return len(self._descriptions)
+    __len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions")
 
     def __repr__(self):
-        return "<AuthorityInformationAccess({0})>".format(self._descriptions)
+        return "<AuthorityInformationAccess({})>".format(self._descriptions)
 
     def __eq__(self, other):
         if not isinstance(other, AuthorityInformationAccess):
@@ -293,8 +319,37 @@
     def __ne__(self, other):
         return not self == other
 
-    def __getitem__(self, idx):
-        return self._descriptions[idx]
+    def __hash__(self):
+        return hash(tuple(self._descriptions))
+
+
+@utils.register_interface(ExtensionType)
+class SubjectInformationAccess(object):
+    oid = ExtensionOID.SUBJECT_INFORMATION_ACCESS
+
+    def __init__(self, descriptions):
+        descriptions = list(descriptions)
+        if not all(isinstance(x, AccessDescription) for x in descriptions):
+            raise TypeError(
+                "Every item in the descriptions list must be an "
+                "AccessDescription"
+            )
+
+        self._descriptions = descriptions
+
+    __len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions")
+
+    def __repr__(self):
+        return "<SubjectInformationAccess({})>".format(self._descriptions)
+
+    def __eq__(self, other):
+        if not isinstance(other, SubjectInformationAccess):
+            return NotImplemented
+
+        return self._descriptions == other._descriptions
+
+    def __ne__(self, other):
+        return not self == other
 
     def __hash__(self):
         return hash(tuple(self._descriptions))
@@ -322,8 +377,8 @@
             return NotImplemented
 
         return (
-            self.access_method == other.access_method and
-            self.access_location == other.access_location
+            self.access_method == other.access_method
+            and self.access_location == other.access_location
         )
 
     def __ne__(self, other):
@@ -347,9 +402,8 @@
         if path_length is not None and not ca:
             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)
+        if path_length is not None and (
+            not isinstance(path_length, six.integer_types) or path_length < 0
         ):
             raise TypeError(
                 "path_length must be a non-negative integer or None"
@@ -362,8 +416,9 @@
     path_length = utils.read_only_property("_path_length")
 
     def __repr__(self):
-        return ("<BasicConstraints(ca={0.ca}, "
-                "path_length={0.path_length})>").format(self)
+        return (
+            "<BasicConstraints(ca={0.ca}, " "path_length={0.path_length})>"
+        ).format(self)
 
     def __eq__(self, other):
         if not isinstance(other, BasicConstraints):
@@ -422,14 +477,12 @@
 
         self._distribution_points = distribution_points
 
-    def __iter__(self):
-        return iter(self._distribution_points)
-
-    def __len__(self):
-        return len(self._distribution_points)
+    __len__, __iter__, __getitem__ = _make_sequence_methods(
+        "_distribution_points"
+    )
 
     def __repr__(self):
-        return "<CRLDistributionPoints({0})>".format(self._distribution_points)
+        return "<CRLDistributionPoints({})>".format(self._distribution_points)
 
     def __eq__(self, other):
         if not isinstance(other, CRLDistributionPoints):
@@ -440,9 +493,6 @@
     def __ne__(self, other):
         return not self == other
 
-    def __getitem__(self, idx):
-        return self._distribution_points[idx]
-
     def __hash__(self):
         return hash(tuple(self._distribution_points))
 
@@ -463,14 +513,12 @@
 
         self._distribution_points = distribution_points
 
-    def __iter__(self):
-        return iter(self._distribution_points)
-
-    def __len__(self):
-        return len(self._distribution_points)
+    __len__, __iter__, __getitem__ = _make_sequence_methods(
+        "_distribution_points"
+    )
 
     def __repr__(self):
-        return "<FreshestCRL({0})>".format(self._distribution_points)
+        return "<FreshestCRL({})>".format(self._distribution_points)
 
     def __eq__(self, other):
         if not isinstance(other, FreshestCRL):
@@ -481,9 +529,6 @@
     def __ne__(self, other):
         return not self == other
 
-    def __getitem__(self, idx):
-        return self._distribution_points[idx]
-
     def __hash__(self):
         return hash(tuple(self._distribution_points))
 
@@ -516,14 +561,15 @@
                     "crl_issuer must be None or a list of general names"
                 )
 
-        if reasons and (not isinstance(reasons, frozenset) or not all(
-            isinstance(x, ReasonFlags) for x in reasons
-        )):
+        if reasons and (
+            not isinstance(reasons, frozenset)
+            or not all(isinstance(x, ReasonFlags) for x in reasons)
+        ):
             raise TypeError("reasons must be None or frozenset of ReasonFlags")
 
         if reasons and (
-            ReasonFlags.unspecified in reasons or
-            ReasonFlags.remove_from_crl in reasons
+            ReasonFlags.unspecified in reasons
+            or ReasonFlags.remove_from_crl in reasons
         ):
             raise ValueError(
                 "unspecified and remove_from_crl are not valid reasons in a "
@@ -544,8 +590,8 @@
     def __repr__(self):
         return (
             "<DistributionPoint(full_name={0.full_name}, relative_name={0.rela"
-            "tive_name}, reasons={0.reasons}, crl_issuer={0.crl_issuer})>"
-            .format(self)
+            "tive_name}, reasons={0.reasons}, "
+            "crl_issuer={0.crl_issuer})>".format(self)
         )
 
     def __eq__(self, other):
@@ -553,10 +599,10 @@
             return NotImplemented
 
         return (
-            self.full_name == other.full_name and
-            self.relative_name == other.relative_name and
-            self.reasons == other.reasons and
-            self.crl_issuer == other.crl_issuer
+            self.full_name == other.full_name
+            and self.relative_name == other.relative_name
+            and self.reasons == other.reasons
+            and self.crl_issuer == other.crl_issuer
         )
 
     def __ne__(self, other):
@@ -635,8 +681,8 @@
             return NotImplemented
 
         return (
-            self.require_explicit_policy == other.require_explicit_policy and
-            self.inhibit_policy_mapping == other.inhibit_policy_mapping
+            self.require_explicit_policy == other.require_explicit_policy
+            and self.inhibit_policy_mapping == other.inhibit_policy_mapping
         )
 
     def __ne__(self, other):
@@ -669,14 +715,10 @@
 
         self._policies = policies
 
-    def __iter__(self):
-        return iter(self._policies)
-
-    def __len__(self):
-        return len(self._policies)
+    __len__, __iter__, __getitem__ = _make_sequence_methods("_policies")
 
     def __repr__(self):
-        return "<CertificatePolicies({0})>".format(self._policies)
+        return "<CertificatePolicies({})>".format(self._policies)
 
     def __eq__(self, other):
         if not isinstance(other, CertificatePolicies):
@@ -687,9 +729,6 @@
     def __ne__(self, other):
         return not self == other
 
-    def __getitem__(self, idx):
-        return self._policies[idx]
-
     def __hash__(self):
         return hash(tuple(self._policies))
 
@@ -704,8 +743,8 @@
         if policy_qualifiers:
             policy_qualifiers = list(policy_qualifiers)
             if not all(
-                    isinstance(x, (six.text_type, UserNotice))
-                    for x in policy_qualifiers
+                isinstance(x, (six.text_type, UserNotice))
+                for x in policy_qualifiers
             ):
                 raise TypeError(
                     "policy_qualifiers must be a list of strings and/or "
@@ -725,8 +764,8 @@
             return NotImplemented
 
         return (
-            self.policy_identifier == other.policy_identifier and
-            self.policy_qualifiers == other.policy_qualifiers
+            self.policy_identifier == other.policy_identifier
+            and self.policy_qualifiers == other.policy_qualifiers
         )
 
     def __ne__(self, other):
@@ -767,8 +806,8 @@
             return NotImplemented
 
         return (
-            self.notice_reference == other.notice_reference and
-            self.explicit_text == other.explicit_text
+            self.notice_reference == other.notice_reference
+            and self.explicit_text == other.explicit_text
         )
 
     def __ne__(self, other):
@@ -786,9 +825,7 @@
         self._organization = organization
         notice_numbers = list(notice_numbers)
         if not all(isinstance(x, int) for x in notice_numbers):
-            raise TypeError(
-                "notice_numbers must be a list of integers"
-            )
+            raise TypeError("notice_numbers must be a list of integers")
 
         self._notice_numbers = notice_numbers
 
@@ -803,8 +840,8 @@
             return NotImplemented
 
         return (
-            self.organization == other.organization and
-            self.notice_numbers == other.notice_numbers
+            self.organization == other.organization
+            and self.notice_numbers == other.notice_numbers
         )
 
     def __ne__(self, other):
@@ -830,14 +867,10 @@
 
         self._usages = usages
 
-    def __iter__(self):
-        return iter(self._usages)
-
-    def __len__(self):
-        return len(self._usages)
+    __len__, __iter__, __getitem__ = _make_sequence_methods("_usages")
 
     def __repr__(self):
-        return "<ExtendedKeyUsage({0})>".format(self._usages)
+        return "<ExtendedKeyUsage({})>".format(self._usages)
 
     def __eq__(self, other):
         if not isinstance(other, ExtendedKeyUsage):
@@ -856,11 +889,41 @@
 class OCSPNoCheck(object):
     oid = ExtensionOID.OCSP_NO_CHECK
 
+    def __eq__(self, other):
+        if not isinstance(other, OCSPNoCheck):
+            return NotImplemented
+
+        return True
+
+    def __ne__(self, other):
+        return not self == other
+
+    def __hash__(self):
+        return hash(OCSPNoCheck)
+
+    def __repr__(self):
+        return "<OCSPNoCheck()>"
+
 
 @utils.register_interface(ExtensionType)
 class PrecertPoison(object):
     oid = ExtensionOID.PRECERT_POISON
 
+    def __eq__(self, other):
+        if not isinstance(other, PrecertPoison):
+            return NotImplemented
+
+        return True
+
+    def __ne__(self, other):
+        return not self == other
+
+    def __hash__(self):
+        return hash(PrecertPoison)
+
+    def __repr__(self):
+        return "<PrecertPoison()>"
+
 
 @utils.register_interface(ExtensionType)
 class TLSFeature(object):
@@ -869,8 +932,8 @@
     def __init__(self, features):
         features = list(features)
         if (
-            not all(isinstance(x, TLSFeatureType) for x in features) or
-            len(features) == 0
+            not all(isinstance(x, TLSFeatureType) for x in features)
+            or len(features) == 0
         ):
             raise TypeError(
                 "features must be a list of elements from the TLSFeatureType "
@@ -879,11 +942,7 @@
 
         self._features = features
 
-    def __iter__(self):
-        return iter(self._features)
-
-    def __len__(self):
-        return len(self._features)
+    __len__, __iter__, __getitem__ = _make_sequence_methods("_features")
 
     def __repr__(self):
         return "<TLSFeature(features={0._features})>".format(self)
@@ -894,9 +953,6 @@
 
         return self._features == other._features
 
-    def __getitem__(self, idx):
-        return self._features[idx]
-
     def __ne__(self, other):
         return not self == other
 
@@ -915,7 +971,7 @@
     status_request_v2 = 17
 
 
-_TLS_FEATURE_TYPE_TO_ENUM = dict((x.value, x) for x in TLSFeatureType)
+_TLS_FEATURE_TYPE_TO_ENUM = {x.value: x for x in TLSFeatureType}
 
 
 @utils.register_interface(ExtensionType)
@@ -953,9 +1009,18 @@
 class KeyUsage(object):
     oid = ExtensionOID.KEY_USAGE
 
-    def __init__(self, digital_signature, content_commitment, key_encipherment,
-                 data_encipherment, key_agreement, key_cert_sign, crl_sign,
-                 encipher_only, decipher_only):
+    def __init__(
+        self,
+        digital_signature,
+        content_commitment,
+        key_encipherment,
+        data_encipherment,
+        key_agreement,
+        key_cert_sign,
+        crl_sign,
+        encipher_only,
+        decipher_only,
+    ):
         if not key_agreement and (encipher_only or decipher_only):
             raise ValueError(
                 "encipher_only and decipher_only can only be true when "
@@ -1003,45 +1068,55 @@
             encipher_only = self.encipher_only
             decipher_only = self.decipher_only
         except ValueError:
-            encipher_only = None
-            decipher_only = None
+            # Users found None confusing because even though encipher/decipher
+            # have no meaning unless key_agreement is true, to construct an
+            # instance of the class you still need to pass False.
+            encipher_only = False
+            decipher_only = False
 
-        return ("<KeyUsage(digital_signature={0.digital_signature}, "
-                "content_commitment={0.content_commitment}, "
-                "key_encipherment={0.key_encipherment}, "
-                "data_encipherment={0.data_encipherment}, "
-                "key_agreement={0.key_agreement}, "
-                "key_cert_sign={0.key_cert_sign}, crl_sign={0.crl_sign}, "
-                "encipher_only={1}, decipher_only={2})>").format(
-                    self, encipher_only, decipher_only)
+        return (
+            "<KeyUsage(digital_signature={0.digital_signature}, "
+            "content_commitment={0.content_commitment}, "
+            "key_encipherment={0.key_encipherment}, "
+            "data_encipherment={0.data_encipherment}, "
+            "key_agreement={0.key_agreement}, "
+            "key_cert_sign={0.key_cert_sign}, crl_sign={0.crl_sign}, "
+            "encipher_only={1}, decipher_only={2})>"
+        ).format(self, encipher_only, decipher_only)
 
     def __eq__(self, other):
         if not isinstance(other, KeyUsage):
             return NotImplemented
 
         return (
-            self.digital_signature == other.digital_signature and
-            self.content_commitment == other.content_commitment and
-            self.key_encipherment == other.key_encipherment and
-            self.data_encipherment == other.data_encipherment and
-            self.key_agreement == other.key_agreement and
-            self.key_cert_sign == other.key_cert_sign and
-            self.crl_sign == other.crl_sign and
-            self._encipher_only == other._encipher_only and
-            self._decipher_only == other._decipher_only
+            self.digital_signature == other.digital_signature
+            and self.content_commitment == other.content_commitment
+            and self.key_encipherment == other.key_encipherment
+            and self.data_encipherment == other.data_encipherment
+            and self.key_agreement == other.key_agreement
+            and self.key_cert_sign == other.key_cert_sign
+            and self.crl_sign == other.crl_sign
+            and self._encipher_only == other._encipher_only
+            and self._decipher_only == other._decipher_only
         )
 
     def __ne__(self, other):
         return not self == other
 
     def __hash__(self):
-        return hash((
-            self.digital_signature, self.content_commitment,
-            self.key_encipherment, self.data_encipherment,
-            self.key_agreement, self.key_cert_sign,
-            self.crl_sign, self._encipher_only,
-            self._decipher_only
-        ))
+        return hash(
+            (
+                self.digital_signature,
+                self.content_commitment,
+                self.key_encipherment,
+                self.data_encipherment,
+                self.key_agreement,
+                self.key_cert_sign,
+                self.crl_sign,
+                self._encipher_only,
+                self._decipher_only,
+            )
+        )
 
 
 @utils.register_interface(ExtensionType)
@@ -1051,9 +1126,7 @@
     def __init__(self, permitted_subtrees, excluded_subtrees):
         if permitted_subtrees is not None:
             permitted_subtrees = list(permitted_subtrees)
-            if not all(
-                isinstance(x, GeneralName) for x in permitted_subtrees
-            ):
+            if not all(isinstance(x, GeneralName) for x in permitted_subtrees):
                 raise TypeError(
                     "permitted_subtrees must be a list of GeneralName objects "
                     "or None"
@@ -1063,9 +1136,7 @@
 
         if excluded_subtrees is not None:
             excluded_subtrees = list(excluded_subtrees)
-            if not all(
-                isinstance(x, GeneralName) for x in excluded_subtrees
-            ):
+            if not all(isinstance(x, GeneralName) for x in excluded_subtrees):
                 raise TypeError(
                     "excluded_subtrees must be a list of GeneralName objects "
                     "or None"
@@ -1087,17 +1158,21 @@
             return NotImplemented
 
         return (
-            self.excluded_subtrees == other.excluded_subtrees and
-            self.permitted_subtrees == other.permitted_subtrees
+            self.excluded_subtrees == other.excluded_subtrees
+            and self.permitted_subtrees == other.permitted_subtrees
         )
 
     def __ne__(self, other):
         return not self == other
 
     def _validate_ip_name(self, tree):
-        if any(isinstance(name, IPAddress) and not isinstance(
-            name.value, (ipaddress.IPv4Network, ipaddress.IPv6Network)
-        ) for name in tree):
+        if any(
+            isinstance(name, IPAddress)
+            and not isinstance(
+                name.value, (ipaddress.IPv4Network, ipaddress.IPv6Network)
+            )
+            for name in tree
+        ):
             raise TypeError(
                 "IPAddress name constraints must be an IPv4Network or"
                 " IPv6Network object"
@@ -1145,17 +1220,19 @@
     value = utils.read_only_property("_value")
 
     def __repr__(self):
-        return ("<Extension(oid={0.oid}, critical={0.critical}, "
-                "value={0.value})>").format(self)
+        return (
+            "<Extension(oid={0.oid}, critical={0.critical}, "
+            "value={0.value})>"
+        ).format(self)
 
     def __eq__(self, other):
         if not isinstance(other, Extension):
             return NotImplemented
 
         return (
-            self.oid == other.oid and
-            self.critical == other.critical and
-            self.value == other.value
+            self.oid == other.oid
+            and self.critical == other.critical
+            and self.value == other.value
         )
 
     def __ne__(self, other):
@@ -1176,11 +1253,7 @@
 
         self._general_names = general_names
 
-    def __iter__(self):
-        return iter(self._general_names)
-
-    def __len__(self):
-        return len(self._general_names)
+    __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
 
     def get_values_for_type(self, type):
         # Return the value of each GeneralName, except for OtherName instances
@@ -1192,7 +1265,7 @@
         return list(objs)
 
     def __repr__(self):
-        return "<GeneralNames({0})>".format(self._general_names)
+        return "<GeneralNames({})>".format(self._general_names)
 
     def __eq__(self, other):
         if not isinstance(other, GeneralNames):
@@ -1203,9 +1276,6 @@
     def __ne__(self, other):
         return not self == other
 
-    def __getitem__(self, idx):
-        return self._general_names[idx]
-
     def __hash__(self):
         return hash(tuple(self._general_names))
 
@@ -1217,17 +1287,13 @@
     def __init__(self, general_names):
         self._general_names = GeneralNames(general_names)
 
-    def __iter__(self):
-        return iter(self._general_names)
-
-    def __len__(self):
-        return len(self._general_names)
+    __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
 
     def get_values_for_type(self, type):
         return self._general_names.get_values_for_type(type)
 
     def __repr__(self):
-        return "<SubjectAlternativeName({0})>".format(self._general_names)
+        return "<SubjectAlternativeName({})>".format(self._general_names)
 
     def __eq__(self, other):
         if not isinstance(other, SubjectAlternativeName):
@@ -1235,9 +1301,6 @@
 
         return self._general_names == other._general_names
 
-    def __getitem__(self, idx):
-        return self._general_names[idx]
-
     def __ne__(self, other):
         return not self == other
 
@@ -1252,17 +1315,13 @@
     def __init__(self, general_names):
         self._general_names = GeneralNames(general_names)
 
-    def __iter__(self):
-        return iter(self._general_names)
-
-    def __len__(self):
-        return len(self._general_names)
+    __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
 
     def get_values_for_type(self, type):
         return self._general_names.get_values_for_type(type)
 
     def __repr__(self):
-        return "<IssuerAlternativeName({0})>".format(self._general_names)
+        return "<IssuerAlternativeName({})>".format(self._general_names)
 
     def __eq__(self, other):
         if not isinstance(other, IssuerAlternativeName):
@@ -1273,9 +1332,6 @@
     def __ne__(self, other):
         return not self == other
 
-    def __getitem__(self, idx):
-        return self._general_names[idx]
-
     def __hash__(self):
         return hash(self._general_names)
 
@@ -1287,17 +1343,13 @@
     def __init__(self, general_names):
         self._general_names = GeneralNames(general_names)
 
-    def __iter__(self):
-        return iter(self._general_names)
-
-    def __len__(self):
-        return len(self._general_names)
+    __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
 
     def get_values_for_type(self, type):
         return self._general_names.get_values_for_type(type)
 
     def __repr__(self):
-        return "<CertificateIssuer({0})>".format(self._general_names)
+        return "<CertificateIssuer({})>".format(self._general_names)
 
     def __eq__(self, other):
         if not isinstance(other, CertificateIssuer):
@@ -1308,9 +1360,6 @@
     def __ne__(self, other):
         return not self == other
 
-    def __getitem__(self, idx):
-        return self._general_names[idx]
-
     def __hash__(self):
         return hash(self._general_names)
 
@@ -1326,7 +1375,7 @@
         self._reason = reason
 
     def __repr__(self):
-        return "<CRLReason(reason={0})>".format(self._reason)
+        return "<CRLReason(reason={})>".format(self._reason)
 
     def __eq__(self, other):
         if not isinstance(other, CRLReason):
@@ -1354,7 +1403,7 @@
         self._invalidity_date = invalidity_date
 
     def __repr__(self):
-        return "<InvalidityDate(invalidity_date={0})>".format(
+        return "<InvalidityDate(invalidity_date={})>".format(
             self._invalidity_date
         )
 
@@ -1389,20 +1438,13 @@
             )
         self._signed_certificate_timestamps = signed_certificate_timestamps
 
-    def __iter__(self):
-        return iter(self._signed_certificate_timestamps)
-
-    def __len__(self):
-        return len(self._signed_certificate_timestamps)
-
-    def __getitem__(self, idx):
-        return self._signed_certificate_timestamps[idx]
+    __len__, __iter__, __getitem__ = _make_sequence_methods(
+        "_signed_certificate_timestamps"
+    )
 
     def __repr__(self):
-        return (
-            "<PrecertificateSignedCertificateTimestamps({0})>".format(
-                list(self)
-            )
+        return "<PrecertificateSignedCertificateTimestamps({})>".format(
+            list(self)
         )
 
     def __hash__(self):
@@ -1413,8 +1455,47 @@
             return NotImplemented
 
         return (
-            self._signed_certificate_timestamps ==
-            other._signed_certificate_timestamps
+            self._signed_certificate_timestamps
+            == other._signed_certificate_timestamps
+        )
+
+    def __ne__(self, other):
+        return not self == other
+
+
+@utils.register_interface(ExtensionType)
+class SignedCertificateTimestamps(object):
+    oid = ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS
+
+    def __init__(self, signed_certificate_timestamps):
+        signed_certificate_timestamps = list(signed_certificate_timestamps)
+        if not all(
+            isinstance(sct, SignedCertificateTimestamp)
+            for sct in signed_certificate_timestamps
+        ):
+            raise TypeError(
+                "Every item in the signed_certificate_timestamps list must be "
+                "a SignedCertificateTimestamp"
+            )
+        self._signed_certificate_timestamps = signed_certificate_timestamps
+
+    __len__, __iter__, __getitem__ = _make_sequence_methods(
+        "_signed_certificate_timestamps"
+    )
+
+    def __repr__(self):
+        return "<SignedCertificateTimestamps({})>".format(list(self))
+
+    def __hash__(self):
+        return hash(tuple(self._signed_certificate_timestamps))
+
+    def __eq__(self, other):
+        if not isinstance(other, SignedCertificateTimestamps):
+            return NotImplemented
+
+        return (
+            self._signed_certificate_timestamps
+            == other._signed_certificate_timestamps
         )
 
     def __ne__(self, other):
@@ -1453,23 +1534,27 @@
 class IssuingDistributionPoint(object):
     oid = ExtensionOID.ISSUING_DISTRIBUTION_POINT
 
-    def __init__(self, full_name, relative_name, only_contains_user_certs,
-                 only_contains_ca_certs, only_some_reasons, indirect_crl,
-                 only_contains_attribute_certs):
-        if (
-            only_some_reasons and (
-                not isinstance(only_some_reasons, frozenset) or not all(
-                    isinstance(x, ReasonFlags) for x in only_some_reasons
-                )
-            )
+    def __init__(
+        self,
+        full_name,
+        relative_name,
+        only_contains_user_certs,
+        only_contains_ca_certs,
+        only_some_reasons,
+        indirect_crl,
+        only_contains_attribute_certs,
+    ):
+        if only_some_reasons and (
+            not isinstance(only_some_reasons, frozenset)
+            or not all(isinstance(x, ReasonFlags) for x in only_some_reasons)
         ):
             raise TypeError(
                 "only_some_reasons must be None or frozenset of ReasonFlags"
             )
 
         if only_some_reasons and (
-            ReasonFlags.unspecified in only_some_reasons or
-            ReasonFlags.remove_from_crl in only_some_reasons
+            ReasonFlags.unspecified in only_some_reasons
+            or ReasonFlags.remove_from_crl in only_some_reasons
         ):
             raise ValueError(
                 "unspecified and remove_from_crl are not valid reasons in an "
@@ -1477,10 +1562,10 @@
             )
 
         if not (
-            isinstance(only_contains_user_certs, bool) and
-            isinstance(only_contains_ca_certs, bool) and
-            isinstance(indirect_crl, bool) and
-            isinstance(only_contains_attribute_certs, bool)
+            isinstance(only_contains_user_certs, bool)
+            and isinstance(only_contains_ca_certs, bool)
+            and isinstance(indirect_crl, bool)
+            and isinstance(only_contains_attribute_certs, bool)
         ):
             raise TypeError(
                 "only_contains_user_certs, only_contains_ca_certs, "
@@ -1489,8 +1574,10 @@
             )
 
         crl_constraints = [
-            only_contains_user_certs, only_contains_ca_certs,
-            indirect_crl, only_contains_attribute_certs
+            only_contains_user_certs,
+            only_contains_ca_certs,
+            indirect_crl,
+            only_contains_attribute_certs,
         ]
 
         if len([x for x in crl_constraints if x]) > 1:
@@ -1500,12 +1587,16 @@
                 "indirect_crl, only_contains_attribute_certs"
             )
 
-        if (
-            not any([
-                only_contains_user_certs, only_contains_ca_certs,
-                indirect_crl, only_contains_attribute_certs, full_name,
-                relative_name, only_some_reasons
-            ])
+        if not any(
+            [
+                only_contains_user_certs,
+                only_contains_ca_certs,
+                indirect_crl,
+                only_contains_attribute_certs,
+                full_name,
+                relative_name,
+                only_some_reasons,
+            ]
         ):
             raise ValueError(
                 "Cannot create empty extension: "
@@ -1540,29 +1631,31 @@
             return NotImplemented
 
         return (
-            self.full_name == other.full_name and
-            self.relative_name == other.relative_name and
-            self.only_contains_user_certs == other.only_contains_user_certs and
-            self.only_contains_ca_certs == other.only_contains_ca_certs and
-            self.only_some_reasons == other.only_some_reasons and
-            self.indirect_crl == other.indirect_crl and
-            self.only_contains_attribute_certs ==
-            other.only_contains_attribute_certs
+            self.full_name == other.full_name
+            and self.relative_name == other.relative_name
+            and self.only_contains_user_certs == other.only_contains_user_certs
+            and self.only_contains_ca_certs == other.only_contains_ca_certs
+            and self.only_some_reasons == other.only_some_reasons
+            and self.indirect_crl == other.indirect_crl
+            and self.only_contains_attribute_certs
+            == other.only_contains_attribute_certs
         )
 
     def __ne__(self, other):
         return not self == other
 
     def __hash__(self):
-        return hash((
-            self.full_name,
-            self.relative_name,
-            self.only_contains_user_certs,
-            self.only_contains_ca_certs,
-            self.only_some_reasons,
-            self.indirect_crl,
-            self.only_contains_attribute_certs,
-        ))
+        return hash(
+            (
+                self.full_name,
+                self.relative_name,
+                self.only_contains_user_certs,
+                self.only_contains_ca_certs,
+                self.only_some_reasons,
+                self.indirect_crl,
+                self.only_contains_attribute_certs,
+            )
+        )
 
     full_name = utils.read_only_property("_full_name")
     relative_name = utils.read_only_property("_relative_name")
@@ -1592,9 +1685,8 @@
 
     def __repr__(self):
         return (
-            "<UnrecognizedExtension(oid={0.oid}, value={0.value!r})>".format(
-                self
-            )
+            "<UnrecognizedExtension(oid={0.oid}, "
+            "value={0.value!r})>".format(self)
         )
 
     def __eq__(self, other):
diff --git a/src/cryptography/x509/general_name.py b/src/cryptography/x509/general_name.py
index 1b0f8c8..9be9d8c 100644
--- a/src/cryptography/x509/general_name.py
+++ b/src/cryptography/x509/general_name.py
@@ -6,11 +6,9 @@
 
 import abc
 import ipaddress
-import warnings
 from email.utils import parseaddr
 
 import six
-from six.moves import urllib_parse
 
 from cryptography import utils
 from cryptography.x509.name import Name
@@ -30,20 +28,6 @@
 }
 
 
-def _lazy_import_idna():
-    # Import idna lazily becase it allocates a decent amount of memory, and
-    # we're only using it in deprecated paths.
-    try:
-        import idna
-        return idna
-    except ImportError:
-        raise ImportError(
-            "idna is not installed, but a deprecated feature that requires it"
-            " was used. See: https://cryptography.io/en/latest/faq/#importe"
-            "rror-idna-is-not-installed"
-        )
-
-
 class UnsupportedGeneralNameType(Exception):
     def __init__(self, msg, type):
         super(UnsupportedGeneralNameType, self).__init__(msg)
@@ -66,14 +50,10 @@
             try:
                 value.encode("ascii")
             except UnicodeEncodeError:
-                value = self._idna_encode(value)
-                warnings.warn(
+                raise ValueError(
                     "RFC822Name values should be passed as an A-label string. "
                     "This means unicode characters should be encoded via "
-                    "idna. Support for passing unicode strings (aka U-label) "
-                    "will be removed in a future version.",
-                    utils.DeprecatedIn21,
-                    stacklevel=2,
+                    "a library like idna."
                 )
         else:
             raise TypeError("value must be string")
@@ -94,12 +74,6 @@
         instance._value = value
         return instance
 
-    def _idna_encode(self, value):
-        idna = _lazy_import_idna()
-        _, address = parseaddr(value)
-        parts = address.split(u"@")
-        return parts[0] + "@" + idna.encode(parts[1]).decode("ascii")
-
     def __repr__(self):
         return "<RFC822Name(value={0!r})>".format(self.value)
 
@@ -116,16 +90,6 @@
         return hash(self.value)
 
 
-def _idna_encode(value):
-    idna = _lazy_import_idna()
-    # Retain prefixes '*.' for common/alt names and '.' for name constraints
-    for prefix in ['*.', '.']:
-        if value.startswith(prefix):
-            value = value[len(prefix):]
-            return prefix + idna.encode(value).decode("ascii")
-    return idna.encode(value).decode("ascii")
-
-
 @utils.register_interface(GeneralName)
 class DNSName(object):
     def __init__(self, value):
@@ -133,14 +97,10 @@
             try:
                 value.encode("ascii")
             except UnicodeEncodeError:
-                value = _idna_encode(value)
-                warnings.warn(
+                raise ValueError(
                     "DNSName values should be passed as an A-label string. "
                     "This means unicode characters should be encoded via "
-                    "idna. Support for passing unicode strings (aka U-label) "
-                    "will be removed in a future version.",
-                    utils.DeprecatedIn21,
-                    stacklevel=2,
+                    "a library like idna."
                 )
         else:
             raise TypeError("value must be string")
@@ -178,14 +138,10 @@
             try:
                 value.encode("ascii")
             except UnicodeEncodeError:
-                value = self._idna_encode(value)
-                warnings.warn(
+                raise ValueError(
                     "URI values should be passed as an A-label string. "
                     "This means unicode characters should be encoded via "
-                    "idna. Support for passing unicode strings (aka U-label) "
-                    " will be removed in a future version.",
-                    utils.DeprecatedIn21,
-                    stacklevel=2,
+                    "a library like idna."
                 )
         else:
             raise TypeError("value must be string")
@@ -200,29 +156,6 @@
         instance._value = value
         return instance
 
-    def _idna_encode(self, value):
-        idna = _lazy_import_idna()
-        parsed = urllib_parse.urlparse(value)
-        if parsed.port:
-            netloc = (
-                idna.encode(parsed.hostname) +
-                ":{0}".format(parsed.port).encode("ascii")
-            ).decode("ascii")
-        else:
-            netloc = idna.encode(parsed.hostname).decode("ascii")
-
-        # Note that building a URL in this fashion means it should be
-        # semantically indistinguishable from the original but is not
-        # guaranteed to be exactly the same.
-        return urllib_parse.urlunparse((
-            parsed.scheme,
-            netloc,
-            parsed.path,
-            parsed.params,
-            parsed.query,
-            parsed.fragment
-        ))
-
     def __repr__(self):
         return "<UniformResourceIdentifier(value={0!r})>".format(self.value)
 
@@ -250,7 +183,7 @@
     value = utils.read_only_property("_value")
 
     def __repr__(self):
-        return "<DirectoryName(value={0})>".format(self.value)
+        return "<DirectoryName(value={})>".format(self.value)
 
     def __eq__(self, other):
         if not isinstance(other, DirectoryName):
@@ -276,7 +209,7 @@
     value = utils.read_only_property("_value")
 
     def __repr__(self):
-        return "<RegisteredID(value={0})>".format(self.value)
+        return "<RegisteredID(value={})>".format(self.value)
 
     def __eq__(self, other):
         if not isinstance(other, RegisteredID):
@@ -300,8 +233,8 @@
                 ipaddress.IPv4Address,
                 ipaddress.IPv6Address,
                 ipaddress.IPv4Network,
-                ipaddress.IPv6Network
-            )
+                ipaddress.IPv6Network,
+            ),
         ):
             raise TypeError(
                 "value must be an instance of ipaddress.IPv4Address, "
@@ -314,7 +247,7 @@
     value = utils.read_only_property("_value")
 
     def __repr__(self):
-        return "<IPAddress(value={0})>".format(self.value)
+        return "<IPAddress(value={})>".format(self.value)
 
     def __eq__(self, other):
         if not isinstance(other, IPAddress):
@@ -344,8 +277,9 @@
     value = utils.read_only_property("_value")
 
     def __repr__(self):
-        return "<OtherName(type_id={0}, value={1!r})>".format(
-            self.type_id, self.value)
+        return "<OtherName(type_id={}, value={!r})>".format(
+            self.type_id, self.value
+        )
 
     def __eq__(self, other):
         if not isinstance(other, OtherName):
diff --git a/src/cryptography/x509/name.py b/src/cryptography/x509/name.py
index 026b79c..0be876a 100644
--- a/src/cryptography/x509/name.py
+++ b/src/cryptography/x509/name.py
@@ -9,6 +9,7 @@
 import six
 
 from cryptography import utils
+from cryptography.hazmat.backends import _get_backend
 from cryptography.x509.oid import NameOID, ObjectIdentifier
 
 
@@ -25,7 +26,7 @@
     BMPString = 30
 
 
-_ASN1_TYPE_TO_ENUM = dict((i.value, i) for i in _ASN1Type)
+_ASN1_TYPE_TO_ENUM = {i.value: i for i in _ASN1Type}
 _SENTINEL = object()
 _NAMEOID_DEFAULT_TYPE = {
     NameOID.COUNTRY_NAME: _ASN1Type.PrintableString,
@@ -39,35 +40,38 @@
 #: Short attribute names from RFC 4514:
 #: https://tools.ietf.org/html/rfc4514#page-7
 _NAMEOID_TO_NAME = {
-    NameOID.COMMON_NAME: 'CN',
-    NameOID.LOCALITY_NAME: 'L',
-    NameOID.STATE_OR_PROVINCE_NAME: 'ST',
-    NameOID.ORGANIZATION_NAME: 'O',
-    NameOID.ORGANIZATIONAL_UNIT_NAME: 'OU',
-    NameOID.COUNTRY_NAME: 'C',
-    NameOID.STREET_ADDRESS: 'STREET',
-    NameOID.DOMAIN_COMPONENT: 'DC',
-    NameOID.USER_ID: 'UID',
+    NameOID.COMMON_NAME: "CN",
+    NameOID.LOCALITY_NAME: "L",
+    NameOID.STATE_OR_PROVINCE_NAME: "ST",
+    NameOID.ORGANIZATION_NAME: "O",
+    NameOID.ORGANIZATIONAL_UNIT_NAME: "OU",
+    NameOID.COUNTRY_NAME: "C",
+    NameOID.STREET_ADDRESS: "STREET",
+    NameOID.DOMAIN_COMPONENT: "DC",
+    NameOID.USER_ID: "UID",
 }
 
 
 def _escape_dn_value(val):
     """Escape special characters in RFC4514 Distinguished Name value."""
 
-    # See https://tools.ietf.org/html/rfc4514#section-2.4
-    val = val.replace('\\', '\\\\')
-    val = val.replace('"', '\\"')
-    val = val.replace('+', '\\+')
-    val = val.replace(',', '\\,')
-    val = val.replace(';', '\\;')
-    val = val.replace('<', '\\<')
-    val = val.replace('>', '\\>')
-    val = val.replace('\0', '\\00')
+    if not val:
+        return ""
 
-    if val[0] in ('#', ' '):
-        val = '\\' + val
-    if val[-1] == ' ':
-        val = val[:-1] + '\\ '
+    # See https://tools.ietf.org/html/rfc4514#section-2.4
+    val = val.replace("\\", "\\\\")
+    val = val.replace('"', '\\"')
+    val = val.replace("+", "\\+")
+    val = val.replace(",", "\\,")
+    val = val.replace(";", "\\;")
+    val = val.replace("<", "\\<")
+    val = val.replace(">", "\\>")
+    val = val.replace("\0", "\\00")
+
+    if val[0] in ("#", " "):
+        val = "\\" + val
+    if val[-1] == " ":
+        val = val[:-1] + "\\ "
 
     return val
 
@@ -80,22 +84,17 @@
             )
 
         if not isinstance(value, six.text_type):
-            raise TypeError(
-                "value argument must be a text type."
-            )
+            raise TypeError("value argument must be a text type.")
 
         if (
-            oid == NameOID.COUNTRY_NAME or
-            oid == NameOID.JURISDICTION_COUNTRY_NAME
+            oid == NameOID.COUNTRY_NAME
+            or oid == NameOID.JURISDICTION_COUNTRY_NAME
         ):
             if len(value.encode("utf8")) != 2:
                 raise ValueError(
                     "Country name must be a 2 character country code"
                 )
 
-        if len(value) == 0:
-            raise ValueError("Value cannot be an empty string")
-
         # The appropriate ASN1 string type varies by OID and is defined across
         # multiple RFCs including 2459, 3280, and 5280. In general UTF8String
         # is preferred (2459), but 3280 and 5280 specify several OIDs with
@@ -123,16 +122,13 @@
         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" % (key, _escape_dn_value(self.value))
 
     def __eq__(self, other):
         if not isinstance(other, NameAttribute):
             return NotImplemented
 
-        return (
-            self.oid == other.oid and
-            self.value == other.value
-        )
+        return self.oid == other.oid and self.value == other.value
 
     def __ne__(self, other):
         return not self == other
@@ -169,7 +165,7 @@
         Within each RDN, attributes are joined by '+', although that is rarely
         used in certificates.
         """
-        return '+'.join(attr.rfc4514_string() for attr in self._attributes)
+        return "+".join(attr.rfc4514_string() for attr in self._attributes)
 
     def __eq__(self, other):
         if not isinstance(other, RelativeDistinguishedName):
@@ -190,7 +186,7 @@
         return len(self._attributes)
 
     def __repr__(self):
-        return "<RelativeDistinguishedName({0})>".format(self.rfc4514_string())
+        return "<RelativeDistinguishedName({})>".format(self.rfc4514_string())
 
 
 class Name(object):
@@ -216,9 +212,12 @@
         An X.509 name is a two-level structure: a list of sets of attributes.
         Each list element is separated by ',' and within each list element, set
         elements are separated by '+'. The latter is almost never used in
-        real world certificates.
+        real world certificates. According to RFC4514 section 2.1 the
+        RDNSequence must be reversed when converting to string representation.
         """
-        return ','.join(attr.rfc4514_string() for attr in self._attributes)
+        return ",".join(
+            attr.rfc4514_string() for attr in reversed(self._attributes)
+        )
 
     def get_attributes_for_oid(self, oid):
         return [i for i in self if i.oid == oid]
@@ -227,7 +226,8 @@
     def rdns(self):
         return self._attributes
 
-    def public_bytes(self, backend):
+    def public_bytes(self, backend=None):
+        backend = _get_backend(backend)
         return backend.x509_name_bytes(self)
 
     def __eq__(self, other):
@@ -253,4 +253,9 @@
         return sum(len(rdn) for rdn in self._attributes)
 
     def __repr__(self):
-        return "<Name({0})>".format(self.rfc4514_string())
+        rdns = ",".join(attr.rfc4514_string() for attr in self._attributes)
+
+        if six.PY2:
+            return "<Name({})>".format(rdns.encode("utf8"))
+        else:
+            return "<Name({})>".format(rdns)
diff --git a/src/cryptography/x509/ocsp.py b/src/cryptography/x509/ocsp.py
index aae9b62..f8e2722 100644
--- a/src/cryptography/x509/ocsp.py
+++ b/src/cryptography/x509/ocsp.py
@@ -13,7 +13,9 @@
 from cryptography import x509
 from cryptography.hazmat.primitives import hashes
 from cryptography.x509.base import (
-    _EARLIEST_UTC_TIME, _convert_to_naive_utc_time, _reject_duplicate_extension
+    _EARLIEST_UTC_TIME,
+    _convert_to_naive_utc_time,
+    _reject_duplicate_extension,
 )
 
 
@@ -40,10 +42,13 @@
     UNAUTHORIZED = 6
 
 
-_RESPONSE_STATUS_TO_ENUM = dict((x.value, x) for x in OCSPResponseStatus)
+_RESPONSE_STATUS_TO_ENUM = {x.value: x for x in OCSPResponseStatus}
 _ALLOWED_HASHES = (
-    hashes.SHA1, hashes.SHA224, hashes.SHA256,
-    hashes.SHA384, hashes.SHA512
+    hashes.SHA1,
+    hashes.SHA224,
+    hashes.SHA256,
+    hashes.SHA384,
+    hashes.SHA512,
 )
 
 
@@ -60,16 +65,18 @@
     UNKNOWN = 2
 
 
-_CERT_STATUS_TO_ENUM = dict((x.value, x) for x in OCSPCertStatus)
+_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)
 
 
@@ -83,9 +90,8 @@
             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)
+        if not isinstance(cert, x509.Certificate) or not isinstance(
+            issuer, x509.Certificate
         ):
             raise TypeError("cert and issuer must be a Certificate")
 
@@ -104,6 +110,7 @@
 
     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")
 
@@ -111,20 +118,27 @@
 
 
 class _SingleResponse(object):
-    def __init__(self, cert, issuer, algorithm, cert_status, this_update,
-                 next_update, revocation_time, revocation_reason):
-        if (
-            not isinstance(cert, x509.Certificate) or
-            not isinstance(issuer, x509.Certificate)
+    def __init__(
+        self,
+        cert,
+        issuer,
+        algorithm,
+        cert_status,
+        this_update,
+        next_update,
+        revocation_time,
+        revocation_reason,
+    ):
+        if not isinstance(cert, x509.Certificate) or not isinstance(
+            issuer, x509.Certificate
         ):
             raise TypeError("cert and issuer must be a Certificate")
 
         _verify_algorithm(algorithm)
         if not isinstance(this_update, datetime.datetime):
             raise TypeError("this_update must be a datetime object")
-        if (
-            next_update is not None and
-            not isinstance(next_update, datetime.datetime)
+        if next_update is not None and not isinstance(
+            next_update, datetime.datetime
         ):
             raise TypeError("next_update must be a datetime object or None")
 
@@ -155,12 +169,13 @@
 
             revocation_time = _convert_to_naive_utc_time(revocation_time)
             if revocation_time < _EARLIEST_UTC_TIME:
-                raise ValueError('The revocation_time must be on or after'
-                                 ' 1950 January 1.')
+                raise ValueError(
+                    "The revocation_time must be on or after"
+                    " 1950 January 1."
+                )
 
-            if (
-                revocation_reason is not None and
-                not isinstance(revocation_reason, x509.ReasonFlags)
+            if revocation_reason is not None and not isinstance(
+                revocation_reason, x509.ReasonFlags
             ):
                 raise TypeError(
                     "revocation_reason must be an item from the ReasonFlags "
@@ -173,25 +188,43 @@
 
 
 class OCSPResponseBuilder(object):
-    def __init__(self, response=None, responder_id=None, certs=None,
-                 extensions=[]):
+    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):
+    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
+            cert,
+            issuer,
+            algorithm,
+            cert_status,
+            this_update,
+            next_update,
+            revocation_time,
+            revocation_reason,
         )
         return OCSPResponseBuilder(
-            singleresp, self._responder_id,
-            self._certs, self._extensions,
+            singleresp,
+            self._responder_id,
+            self._certs,
+            self._extensions,
         )
 
     def responder_id(self, encoding, responder_cert):
@@ -205,8 +238,10 @@
             )
 
         return OCSPResponseBuilder(
-            self._response, (responder_cert, encoding),
-            self._certs, self._extensions,
+            self._response,
+            (responder_cert, encoding),
+            self._certs,
+            self._extensions,
         )
 
     def certificates(self, certs):
@@ -218,8 +253,10 @@
         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,
+            self._response,
+            self._responder_id,
+            certs,
+            self._extensions,
         )
 
     def add_extension(self, extension, critical):
@@ -230,20 +267,20 @@
         _reject_duplicate_extension(extension, self._extensions)
 
         return OCSPResponseBuilder(
-            self._response, self._responder_id,
-            self._certs, self._extensions + [extension],
+            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")
 
-        if not isinstance(algorithm, hashes.HashAlgorithm):
-            raise TypeError("Algorithm must be a registered hash algorithm.")
-
         return backend.create_ocsp_response(
             OCSPResponseStatus.SUCCESSFUL, self, private_key, algorithm
         )
@@ -251,6 +288,7 @@
     @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"
@@ -286,6 +324,7 @@
         """
         The serial number of the cert whose status is being checked
         """
+
     @abc.abstractmethod
     def public_bytes(self, encoding):
         """
@@ -420,3 +459,9 @@
         """
         The list of response extensions. Not single response extensions.
         """
+
+    @abc.abstractproperty
+    def single_extensions(self):
+        """
+        The list of single response extensions. Not response extensions.
+        """
diff --git a/src/cryptography/x509/oid.py b/src/cryptography/x509/oid.py
index ec19007..2bf606e 100644
--- a/src/cryptography/x509/oid.py
+++ b/src/cryptography/x509/oid.py
@@ -31,12 +31,11 @@
     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_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")
-    )
+    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):
@@ -76,6 +75,10 @@
     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):
@@ -96,6 +99,11 @@
     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 = {
@@ -113,7 +121,12 @@
     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.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,
 }
 
 
@@ -132,12 +145,21 @@
     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",
@@ -165,7 +187,10 @@
     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",
@@ -181,6 +206,17 @@
     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",
@@ -196,6 +232,10 @@
     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",
@@ -208,9 +248,7 @@
     ExtensionOID.EXTENDED_KEY_USAGE: "extendedKeyUsage",
     ExtensionOID.FRESHEST_CRL: "freshestCRL",
     ExtensionOID.INHIBIT_ANY_POLICY: "inhibitAnyPolicy",
-    ExtensionOID.ISSUING_DISTRIBUTION_POINT: (
-        "issuingDistributionPoint"
-    ),
+    ExtensionOID.ISSUING_DISTRIBUTION_POINT: ("issuingDistributionPoint"),
     ExtensionOID.AUTHORITY_INFORMATION_ACCESS: "authorityInfoAccess",
     ExtensionOID.SUBJECT_INFORMATION_ACCESS: "subjectInfoAccess",
     ExtensionOID.OCSP_NO_CHECK: "OCSPNoCheck",
@@ -219,7 +257,9 @@
     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/tests/conftest.py b/tests/conftest.py
index d858b4f..ece7a11 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -9,12 +9,18 @@
 from cryptography.hazmat.backends.openssl import backend as openssl_backend
 
 from .utils import (
-    check_backend_support, load_wycheproof_tests, skip_if_wycheproof_none
+    check_backend_support,
+    load_wycheproof_tests,
 )
 
 
 def pytest_report_header(config):
-    return "OpenSSL: {0}".format(openssl_backend.openssl_version_text())
+    return "\n".join(
+        [
+            "OpenSSL: {}".format(openssl_backend.openssl_version_text()),
+            "FIPS Enabled: {}".format(openssl_backend._fips_enabled),
+        ]
+    )
 
 
 def pytest_addoption(parser):
@@ -23,8 +29,7 @@
 
 def pytest_generate_tests(metafunc):
     if "wycheproof" in metafunc.fixturenames:
-        wycheproof = metafunc.config.getoption("--wycheproof-root")
-        skip_if_wycheproof_none(wycheproof)
+        wycheproof = metafunc.config.getoption("--wycheproof-root", skip=True)
 
         testcases = []
         marker = metafunc.definition.get_closest_marker("wycheproof_tests")
@@ -33,6 +38,12 @@
         metafunc.parametrize("wycheproof", testcases)
 
 
+def pytest_runtest_setup(item):
+    if openssl_backend._fips_enabled:
+        for marker in item.iter_markers(name="skip_fips"):
+            pytest.skip(marker.kwargs["reason"])
+
+
 @pytest.fixture()
 def backend(request):
     required_interfaces = [
@@ -43,7 +54,7 @@
         isinstance(openssl_backend, iface) for iface in required_interfaces
     ):
         pytest.skip(
-            "OpenSSL doesn't implement required interfaces: {0}".format(
+            "OpenSSL doesn't implement required interfaces: {}".format(
                 required_interfaces
             )
         )
diff --git a/tests/hazmat/backends/test_no_backend.py b/tests/hazmat/backends/test_no_backend.py
new file mode 100644
index 0000000..6786692
--- /dev/null
+++ b/tests/hazmat/backends/test_no_backend.py
@@ -0,0 +1,16 @@
+# 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
+
+from cryptography.hazmat.backends import _get_backend, default_backend
+
+
+def test_get_backend_no_backend():
+    assert _get_backend(None) is default_backend()
+
+
+def test_get_backend():
+    faux_backend = object()
+    assert _get_backend(faux_backend) is faux_backend
diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py
index 0aa72d8..eab868f 100644
--- a/tests/hazmat/backends/test_openssl.py
+++ b/tests/hazmat/backends/test_openssl.py
@@ -10,16 +10,12 @@
 import sys
 import textwrap
 
-from pkg_resources import parse_version
-
 import pytest
 
 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.backend import Backend, backend
 from cryptography.hazmat.backends.openssl.ec import _sn_to_elliptic_curve
 from cryptography.hazmat.primitives import hashes, serialization
 from cryptography.hazmat.primitives.asymmetric import dh, dsa, padding
@@ -29,16 +25,21 @@
 
 from ..primitives.fixtures_rsa import RSA_KEY_2048, RSA_KEY_512
 from ...doubles import (
-    DummyAsymmetricPadding, DummyCipherAlgorithm, DummyHashAlgorithm, DummyMode
+    DummyAsymmetricPadding,
+    DummyCipherAlgorithm,
+    DummyHashAlgorithm,
+    DummyMode,
 )
 from ...utils import (
-    load_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm
+    load_nist_vectors,
+    load_vectors_from_file,
+    raises_unsupported_algorithm,
 )
 from ...x509.test_x509 import _load_cert
 
 
 def skip_if_libre_ssl(openssl_version):
-    if u'LibreSSL' in openssl_version:
+    if u"LibreSSL" in openssl_version:
         pytest.skip("LibreSSL hard-codes RAND_bytes to use arc4random.")
 
 
@@ -68,10 +69,9 @@
         if it starts with OpenSSL or LibreSSL as that appears
         to be true for every OpenSSL-alike.
         """
-        assert (
-            backend.openssl_version_text().startswith("OpenSSL") or
-            backend.openssl_version_text().startswith("LibreSSL")
-        )
+        assert backend.openssl_version_text().startswith(
+            "OpenSSL"
+        ) or backend.openssl_version_text().startswith("LibreSSL")
 
     def test_openssl_version_number(self):
         assert backend.openssl_version_number() > 0
@@ -89,10 +89,12 @@
         b.register_cipher_adapter(
             DummyCipherAlgorithm,
             type(mode),
-            lambda backend, cipher, mode: backend._ffi.NULL
+            lambda backend, cipher, mode: backend._ffi.NULL,
         )
         cipher = Cipher(
-            DummyCipherAlgorithm(), mode, backend=b,
+            DummyCipherAlgorithm(),
+            mode,
+            backend=b,
         )
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER):
             cipher.encryptor()
@@ -104,8 +106,9 @@
 
     def test_consume_errors(self):
         for i in range(10):
-            backend._lib.ERR_put_error(backend._lib.ERR_LIB_EVP, 0, 0,
-                                       b"test_openssl.py", -1)
+            backend._lib.ERR_put_error(
+                backend._lib.ERR_LIB_EVP, 0, 0, b"test_openssl.py", -1
+            )
 
         assert backend._lib.ERR_peek_error() != 0
 
@@ -124,17 +127,11 @@
         cipher = backend._lib.EVP_get_cipherbyname(b"aes-256-cbc")
         assert cipher != backend._ffi.NULL
 
-    def test_error_strings_loaded(self):
-        buf = backend._ffi.new("char[]", 256)
-        backend._lib.ERR_error_string_n(101183626, buf, len(buf))
-        assert b"data not multiple of block length" in backend._ffi.string(buf)
-
     def test_unknown_error_in_cipher_finalize(self):
         cipher = Cipher(AES(b"\0" * 16), CBC(b"\0" * 16), backend=backend)
         enc = cipher.encryptor()
         enc.update(b"\0")
-        backend._lib.ERR_put_error(0, 0, 1,
-                                   b"test_openssl.py", -1)
+        backend._lib.ERR_put_error(0, 0, 1, b"test_openssl.py", -1)
         with pytest.raises(InternalError):
             enc.finalize()
 
@@ -170,6 +167,11 @@
         assert backend._bn_to_int(bn) == 0
 
 
+@pytest.mark.skipif(
+    not backend._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE,
+    reason="Requires OpenSSL with ENGINE support and OpenSSL < 1.1.1d",
+)
+@pytest.mark.skip_fips(reason="osrandom engine disabled for FIPS")
 class TestOpenSSLRandomEngine(object):
     def setup(self):
         # The default RAND engine is global and shared between
@@ -178,7 +180,7 @@
         # that engine in teardown.
         current_default = backend._lib.ENGINE_get_default_RAND()
         name = backend._lib.ENGINE_get_name(current_default)
-        assert name == backend._binding._osrandom_engine_name
+        assert name == backend._lib.Cryptography_osrandom_engine_name
 
     def teardown(self):
         # we need to reset state to being default. backend is a shared global
@@ -186,10 +188,11 @@
         backend.activate_osrandom_engine()
         current_default = backend._lib.ENGINE_get_default_RAND()
         name = backend._lib.ENGINE_get_name(current_default)
-        assert name == backend._binding._osrandom_engine_name
+        assert name == backend._lib.Cryptography_osrandom_engine_name
 
-    @pytest.mark.skipif(sys.executable is None,
-                        reason="No Python interpreter available.")
+    @pytest.mark.skipif(
+        sys.executable is None, reason="No Python interpreter available."
+    )
     def test_osrandom_engine_is_default(self, tmpdir):
         engine_printer = textwrap.dedent(
             """
@@ -203,7 +206,7 @@
             assert res == 1
             """
         )
-        engine_name = tmpdir.join('engine_name')
+        engine_name = tmpdir.join("engine_name")
 
         # If we're running tests via ``python setup.py test`` in a clean
         # environment then all of our dependencies are going to be installed
@@ -214,7 +217,7 @@
         env = os.environ.copy()
         env["PYTHONPATH"] = os.pathsep.join(sys.path)
 
-        with engine_name.open('w') as out:
+        with engine_name.open("w") as out:
             subprocess.check_call(
                 [sys.executable, "-c", engine_printer],
                 env=env,
@@ -223,10 +226,10 @@
             )
 
         osrandom_engine_name = backend._ffi.string(
-            backend._binding._osrandom_engine_name
+            backend._lib.Cryptography_osrandom_engine_name
         )
 
-        assert engine_name.read().encode('ascii') == osrandom_engine_name
+        assert engine_name.read().encode("ascii") == osrandom_engine_name
 
     def test_osrandom_sanity_check(self):
         # This test serves as a check against catastrophic failure.
@@ -242,7 +245,7 @@
         backend.activate_osrandom_engine()
         e = backend._lib.ENGINE_get_default_RAND()
         name = backend._lib.ENGINE_get_name(e)
-        assert name == backend._binding._osrandom_engine_name
+        assert name == backend._lib.Cryptography_osrandom_engine_name
         res = backend._lib.ENGINE_free(e)
         assert res == 1
 
@@ -250,7 +253,7 @@
         e = backend._lib.ENGINE_get_default_RAND()
         assert e != backend._ffi.NULL
         name = backend._lib.ENGINE_get_name(e)
-        assert name == backend._binding._osrandom_engine_name
+        assert name == backend._lib.Cryptography_osrandom_engine_name
         res = backend._lib.ENGINE_free(e)
         assert res == 1
         backend.activate_builtin_random()
@@ -267,33 +270,55 @@
 
     def test_osrandom_engine_implementation(self):
         name = backend.osrandom_engine_implementation()
-        assert name in ['/dev/urandom', 'CryptGenRandom', 'getentropy',
-                        'getrandom']
-        if sys.platform.startswith('linux'):
-            assert name in ['getrandom', '/dev/urandom']
-        if sys.platform == 'darwin':
-            # macOS 10.12+ supports getentropy
-            if parse_version(os.uname()[2]) >= parse_version("16.0"):
-                assert name == 'getentropy'
-            else:
-                assert name == '/dev/urandom'
-        if sys.platform == 'win32':
-            assert name == 'CryptGenRandom'
+        assert name in [
+            "/dev/urandom",
+            "CryptGenRandom",
+            "getentropy",
+            "getrandom",
+        ]
+        if sys.platform.startswith("linux"):
+            assert name in ["getrandom", "/dev/urandom"]
+        if sys.platform == "darwin":
+            assert name in ["getentropy", "/dev/urandom"]
+        if sys.platform == "win32":
+            assert name == "CryptGenRandom"
 
     def test_activate_osrandom_already_default(self):
         e = backend._lib.ENGINE_get_default_RAND()
         name = backend._lib.ENGINE_get_name(e)
-        assert name == backend._binding._osrandom_engine_name
+        assert name == backend._lib.Cryptography_osrandom_engine_name
         res = backend._lib.ENGINE_free(e)
         assert res == 1
         backend.activate_osrandom_engine()
         e = backend._lib.ENGINE_get_default_RAND()
         name = backend._lib.ENGINE_get_name(e)
-        assert name == backend._binding._osrandom_engine_name
+        assert name == backend._lib.Cryptography_osrandom_engine_name
         res = backend._lib.ENGINE_free(e)
         assert res == 1
 
 
+@pytest.mark.skipif(
+    backend._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE,
+    reason="Requires OpenSSL without ENGINE support or OpenSSL >=1.1.1d",
+)
+class TestOpenSSLNoEngine(object):
+    def test_no_engine_support(self):
+        assert (
+            backend._ffi.string(backend._lib.Cryptography_osrandom_engine_id)
+            == b"no-engine-support"
+        )
+        assert (
+            backend._ffi.string(backend._lib.Cryptography_osrandom_engine_name)
+            == b"osrandom_engine disabled"
+        )
+
+    def test_activate_builtin_random_does_nothing(self):
+        backend.activate_builtin_random()
+
+    def test_activate_osrandom_does_nothing(self):
+        backend.activate_osrandom_engine()
+
+
 class TestOpenSSLRSA(object):
     def test_generate_rsa_parameters_supported(self):
         assert backend.generate_rsa_parameters_supported(1, 1024) is False
@@ -310,17 +335,24 @@
 
     def test_cant_generate_insecure_tiny_key(self):
         with pytest.raises(ValueError):
-            backend.generate_rsa_private_key(public_exponent=65537,
-                                             key_size=511)
+            backend.generate_rsa_private_key(
+                public_exponent=65537, key_size=511
+            )
 
         with pytest.raises(ValueError):
-            backend.generate_rsa_private_key(public_exponent=65537,
-                                             key_size=256)
+            backend.generate_rsa_private_key(
+                public_exponent=65537, key_size=256
+            )
 
     def test_rsa_padding_unsupported_pss_mgf1_hash(self):
-        assert backend.rsa_padding_supported(
-            padding.PSS(mgf=padding.MGF1(DummyHashAlgorithm()), salt_length=0)
-        ) is False
+        assert (
+            backend.rsa_padding_supported(
+                padding.PSS(
+                    mgf=padding.MGF1(DummyHashAlgorithm()), salt_length=0
+                )
+            )
+            is False
+        )
 
     def test_rsa_padding_unsupported(self):
         assert backend.rsa_padding_supported(DummyAsymmetricPadding()) is False
@@ -329,22 +361,28 @@
         assert backend.rsa_padding_supported(padding.PKCS1v15()) is True
 
     def test_rsa_padding_supported_pss(self):
-        assert backend.rsa_padding_supported(
-            padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=0)
-        ) is True
+        assert (
+            backend.rsa_padding_supported(
+                padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=0)
+            )
+            is True
+        )
 
     def test_rsa_padding_supported_oaep(self):
-        assert backend.rsa_padding_supported(
-            padding.OAEP(
-                mgf=padding.MGF1(algorithm=hashes.SHA1()),
-                algorithm=hashes.SHA1(),
-                label=None
-            ),
-        ) is True
+        assert (
+            backend.rsa_padding_supported(
+                padding.OAEP(
+                    mgf=padding.MGF1(algorithm=hashes.SHA1()),
+                    algorithm=hashes.SHA1(),
+                    label=None,
+                ),
+            )
+            is True
+        )
 
     @pytest.mark.skipif(
         backend._lib.Cryptography_HAS_RSA_OAEP_MD == 0,
-        reason="Requires OpenSSL with rsa_oaep_md (1.0.2+)"
+        reason="Requires OpenSSL with rsa_oaep_md (1.0.2+)",
     )
     def test_rsa_padding_supported_oaep_sha2_combinations(self):
         hashalgs = [
@@ -355,30 +393,37 @@
             hashes.SHA512(),
         ]
         for mgf1alg, oaepalg in itertools.product(hashalgs, hashalgs):
-            assert backend.rsa_padding_supported(
-                padding.OAEP(
-                    mgf=padding.MGF1(algorithm=mgf1alg),
-                    algorithm=oaepalg,
-                    label=None
-                ),
-            ) is True
+            assert (
+                backend.rsa_padding_supported(
+                    padding.OAEP(
+                        mgf=padding.MGF1(algorithm=mgf1alg),
+                        algorithm=oaepalg,
+                        label=None,
+                    ),
+                )
+                is True
+            )
 
     def test_rsa_padding_unsupported_mgf(self):
-        assert backend.rsa_padding_supported(
-            padding.OAEP(
-                mgf=DummyMGF(),
-                algorithm=hashes.SHA1(),
-                label=None
-            ),
-        ) is False
+        assert (
+            backend.rsa_padding_supported(
+                padding.OAEP(
+                    mgf=DummyMGF(), algorithm=hashes.SHA1(), label=None
+                ),
+            )
+            is False
+        )
 
-        assert backend.rsa_padding_supported(
-            padding.PSS(mgf=DummyMGF(), salt_length=0)
-        ) is False
+        assert (
+            backend.rsa_padding_supported(
+                padding.PSS(mgf=DummyMGF(), salt_length=0)
+            )
+            is False
+        )
 
     @pytest.mark.skipif(
         backend._lib.Cryptography_HAS_RSA_OAEP_MD == 1,
-        reason="Requires OpenSSL without rsa_oaep_md (< 1.0.2)"
+        reason="Requires OpenSSL without rsa_oaep_md (< 1.0.2)",
     )
     def test_unsupported_mgf1_hash_algorithm_decrypt(self):
         private_key = RSA_KEY_512.private_key(backend)
@@ -388,13 +433,13 @@
                 padding.OAEP(
                     mgf=padding.MGF1(algorithm=hashes.SHA256()),
                     algorithm=hashes.SHA1(),
-                    label=None
-                )
+                    label=None,
+                ),
             )
 
     @pytest.mark.skipif(
         backend._lib.Cryptography_HAS_RSA_OAEP_MD == 1,
-        reason="Requires OpenSSL without rsa_oaep_md (< 1.0.2)"
+        reason="Requires OpenSSL without rsa_oaep_md (< 1.0.2)",
     )
     def test_unsupported_oaep_hash_algorithm_decrypt(self):
         private_key = RSA_KEY_512.private_key(backend)
@@ -404,8 +449,8 @@
                 padding.OAEP(
                     mgf=padding.MGF1(algorithm=hashes.SHA1()),
                     algorithm=hashes.SHA256(),
-                    label=None
-                )
+                    label=None,
+                ),
             )
 
     def test_unsupported_mgf1_hash_algorithm_md5_decrypt(self):
@@ -416,8 +461,8 @@
                 padding.OAEP(
                     mgf=padding.MGF1(algorithm=hashes.MD5()),
                     algorithm=hashes.MD5(),
-                    label=None
-                )
+                    label=None,
+                ),
             )
 
 
@@ -437,6 +482,16 @@
             )
 
 
+class TestOpenSSLSignX509CSR(object):
+    def test_requires_csr_builder(self):
+        private_key = RSA_KEY_2048.private_key(backend)
+
+        with pytest.raises(TypeError):
+            backend.create_x509_csr(
+                object(), private_key, DummyHashAlgorithm()
+            )
+
+
 class TestOpenSSLSignX509CertificateRevocationList(object):
     def test_invalid_builder(self):
         private_key = RSA_KEY_2048.private_key(backend)
@@ -492,14 +547,15 @@
         with pytest.raises(ValueError):
             load_vectors_from_file(
                 os.path.join(
-                    "asymmetric", "Traditional_OpenSSL_Serialization",
-                    "key1.pem"
+                    "asymmetric",
+                    "Traditional_OpenSSL_Serialization",
+                    "key1.pem",
                 ),
                 lambda pemfile: (
                     backend.load_pem_private_key(
                         pemfile.read().encode(), password
                     )
-                )
+                ),
             )
 
 
@@ -518,7 +574,7 @@
             key.private_bytes(
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.PKCS8,
-                serialization.BestAvailableEncryption(password)
+                serialization.BestAvailableEncryption(password),
             )
 
 
@@ -527,9 +583,9 @@
         cert = _load_cert(
             os.path.join("x509", "e-trust.ru.der"),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
-        if backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102I:
+        if backend._lib.CRYPTOGRAPHY_IS_LIBRESSL:
             with pytest.raises(ValueError) as exc:
                 cert.subject
 
@@ -538,42 +594,49 @@
             # 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"
+            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)")
+    reason="Requires OpenSSL without EVP_PKEY_DHX (< 1.0.2)",
+)
 @pytest.mark.requires_backend_interface(interface=DHBackend)
 class TestOpenSSLDHSerialization(object):
-
     @pytest.mark.parametrize(
         "vector",
         load_vectors_from_file(
-            os.path.join("asymmetric", "DH", "RFC5114.txt"),
-            load_nist_vectors))
+            os.path.join("asymmetric", "DH", "RFC5114.txt"), load_nist_vectors
+        ),
+    )
     def test_dh_serialization_with_q_unsupported(self, backend, vector):
-        parameters = dh.DHParameterNumbers(int(vector["p"], 16),
-                                           int(vector["g"], 16),
-                                           int(vector["q"], 16))
+        parameters = dh.DHParameterNumbers(
+            int(vector["p"], 16), int(vector["g"], 16), int(vector["q"], 16)
+        )
         public = dh.DHPublicNumbers(int(vector["ystatcavs"], 16), parameters)
         private = dh.DHPrivateNumbers(int(vector["xstatcavs"], 16), public)
         private_key = private.private_key(backend)
         public_key = private_key.public_key()
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION):
-            private_key.private_bytes(serialization.Encoding.PEM,
-                                      serialization.PrivateFormat.PKCS8,
-                                      serialization.NoEncryption())
+            private_key.private_bytes(
+                serialization.Encoding.PEM,
+                serialization.PrivateFormat.PKCS8,
+                serialization.NoEncryption(),
+            )
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION):
             public_key.public_bytes(
                 serialization.Encoding.PEM,
-                serialization.PublicFormat.SubjectPublicKeyInfo)
+                serialization.PublicFormat.SubjectPublicKeyInfo,
+            )
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION):
             parameters.parameters(backend).parameter_bytes(
-                serialization.Encoding.PEM,
-                serialization.ParameterFormat.PKCS3)
+                serialization.Encoding.PEM, serialization.ParameterFormat.PKCS3
+            )
 
     @pytest.mark.parametrize(
         ("key_path", "loader_func"),
@@ -585,14 +648,14 @@
             (
                 os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.der"),
                 serialization.load_der_private_key,
-            )
-        ]
+            ),
+        ],
     )
-    def test_private_load_dhx_unsupported(self, key_path, loader_func,
-                                          backend):
+    def test_private_load_dhx_unsupported(
+        self, key_path, loader_func, backend
+    ):
         key_bytes = load_vectors_from_file(
-            key_path,
-            lambda pemfile: pemfile.read(), mode="rb"
+            key_path, lambda pemfile: pemfile.read(), mode="rb"
         )
         with pytest.raises(ValueError):
             loader_func(key_bytes, None, backend)
@@ -607,14 +670,12 @@
             (
                 os.path.join("asymmetric", "DH", "dhpub_rfc5114_2.der"),
                 serialization.load_der_public_key,
-            )
-        ]
+            ),
+        ],
     )
-    def test_public_load_dhx_unsupported(self, key_path, loader_func,
-                                         backend):
+    def test_public_load_dhx_unsupported(self, key_path, loader_func, backend):
         key_bytes = load_vectors_from_file(
-            key_path,
-            lambda pemfile: pemfile.read(), mode="rb"
+            key_path, lambda pemfile: pemfile.read(), mode="rb"
         )
         with pytest.raises(ValueError):
             loader_func(key_bytes, backend)
diff --git a/tests/hazmat/backends/test_openssl_memleak.py b/tests/hazmat/backends/test_openssl_memleak.py
index 1db103b..d8bc866 100644
--- a/tests/hazmat/backends/test_openssl_memleak.py
+++ b/tests/hazmat/backends/test_openssl_memleak.py
@@ -128,7 +128,9 @@
     env = os.environ.copy()
     env["PYTHONPATH"] = os.pathsep.join(sys.path)
     argv = [
-        sys.executable, "-c", "{0}\n\n{1}".format(s, MEMORY_LEAK_SCRIPT)
+        sys.executable,
+        "-c",
+        "{}\n\n{}".format(s, MEMORY_LEAK_SCRIPT),
     ] + argv
     # Shell out to a fresh Python process because OpenSSL does not allow you to
     # install new memory hooks after the first malloc/free occurs.
@@ -156,62 +158,86 @@
 def skip_if_memtesting_not_supported():
     return pytest.mark.skipif(
         not Binding().lib.Cryptography_HAS_MEM_FUNCTIONS,
-        reason="Requires OpenSSL memory functions (>=1.1.0)"
+        reason="Requires OpenSSL memory functions (>=1.1.0)",
     )
 
 
+@pytest.mark.skip_fips(reason="FIPS self-test sets allow_customize = 0")
 @skip_if_memtesting_not_supported()
 class TestAssertNoMemoryLeaks(object):
     def test_no_leak_no_malloc(self):
-        assert_no_memory_leaks(textwrap.dedent("""
+        assert_no_memory_leaks(
+            textwrap.dedent(
+                """
         def func():
             pass
-        """))
+        """
+            )
+        )
 
     def test_no_leak_free(self):
-        assert_no_memory_leaks(textwrap.dedent("""
+        assert_no_memory_leaks(
+            textwrap.dedent(
+                """
         def func():
             from cryptography.hazmat.bindings.openssl.binding import Binding
             b = Binding()
             name = b.lib.X509_NAME_new()
             b.lib.X509_NAME_free(name)
-        """))
+        """
+            )
+        )
 
     def test_no_leak_gc(self):
-        assert_no_memory_leaks(textwrap.dedent("""
+        assert_no_memory_leaks(
+            textwrap.dedent(
+                """
         def func():
             from cryptography.hazmat.bindings.openssl.binding import Binding
             b = Binding()
             name = b.lib.X509_NAME_new()
             b.ffi.gc(name, b.lib.X509_NAME_free)
-        """))
+        """
+            )
+        )
 
     def test_leak(self):
         with pytest.raises(AssertionError):
-            assert_no_memory_leaks(textwrap.dedent("""
+            assert_no_memory_leaks(
+                textwrap.dedent(
+                    """
             def func():
                 from cryptography.hazmat.bindings.openssl.binding import (
                     Binding
                 )
                 b = Binding()
                 b.lib.X509_NAME_new()
-            """))
+            """
+                )
+            )
 
     def test_errors(self):
         with pytest.raises(ValueError):
-            assert_no_memory_leaks(textwrap.dedent("""
+            assert_no_memory_leaks(
+                textwrap.dedent(
+                    """
             def func():
                 raise ZeroDivisionError
-            """))
+            """
+                )
+            )
 
 
+@pytest.mark.skip_fips(reason="FIPS self-test sets allow_customize = 0")
 @skip_if_memtesting_not_supported()
 class TestOpenSSLMemoryLeaks(object):
-    @pytest.mark.parametrize("path", [
-        "x509/PKITS_data/certs/ValidcRLIssuerTest28EE.crt",
-    ])
-    def test_x509_certificate_extensions(self, path):
-        assert_no_memory_leaks(textwrap.dedent("""
+    @pytest.mark.parametrize(
+        "path", ["x509/PKITS_data/certs/ValidcRLIssuerTest28EE.crt"]
+    )
+    def test_der_x509_certificate_extensions(self, path):
+        assert_no_memory_leaks(
+            textwrap.dedent(
+                """
         def func(path):
             from cryptography import x509
             from cryptography.hazmat.backends.openssl import backend
@@ -224,10 +250,37 @@
                 )
 
             cert.extensions
-        """), [path])
+        """
+            ),
+            [path],
+        )
+
+    @pytest.mark.parametrize("path", ["x509/cryptography.io.pem"])
+    def test_pem_x509_certificate_extensions(self, path):
+        assert_no_memory_leaks(
+            textwrap.dedent(
+                """
+        def func(path):
+            from cryptography import x509
+            from cryptography.hazmat.backends.openssl import backend
+
+            import cryptography_vectors
+
+            with cryptography_vectors.open_vector_file(path, "rb") as f:
+                cert = x509.load_pem_x509_certificate(
+                    f.read(), backend
+                )
+
+            cert.extensions
+        """
+            ),
+            [path],
+        )
 
     def test_x509_csr_extensions(self):
-        assert_no_memory_leaks(textwrap.dedent("""
+        assert_no_memory_leaks(
+            textwrap.dedent(
+                """
         def func():
             from cryptography import x509
             from cryptography.hazmat.backends.openssl import backend
@@ -244,10 +297,14 @@
             ).sign(private_key, hashes.SHA256(), backend)
 
             cert.extensions
-        """))
+        """
+            )
+        )
 
     def test_ec_private_numbers_private_key(self):
-        assert_no_memory_leaks(textwrap.dedent("""
+        assert_no_memory_leaks(
+            textwrap.dedent(
+                """
         def func():
             from cryptography.hazmat.backends.openssl import backend
             from cryptography.hazmat.primitives.asymmetric import ec
@@ -269,26 +326,38 @@
                     )
                 )
             ).private_key(backend)
-        """))
+        """
+            )
+        )
 
     def test_ec_derive_private_key(self):
-        assert_no_memory_leaks(textwrap.dedent("""
+        assert_no_memory_leaks(
+            textwrap.dedent(
+                """
         def func():
             from cryptography.hazmat.backends.openssl import backend
             from cryptography.hazmat.primitives.asymmetric import ec
             ec.derive_private_key(1, ec.SECP256R1(), backend)
-        """))
+        """
+            )
+        )
 
     def test_x25519_pubkey_from_private_key(self):
-        assert_no_memory_leaks(textwrap.dedent("""
+        assert_no_memory_leaks(
+            textwrap.dedent(
+                """
         def func():
             from cryptography.hazmat.primitives.asymmetric import x25519
             private_key = x25519.X25519PrivateKey.generate()
             private_key.public_key()
-        """))
+        """
+            )
+        )
 
     def test_create_ocsp_request(self):
-        assert_no_memory_leaks(textwrap.dedent("""
+        assert_no_memory_leaks(
+            textwrap.dedent(
+                """
         def func():
             from cryptography import x509
             from cryptography.hazmat.backends.openssl import backend
@@ -306,14 +375,18 @@
                 cert, cert, hashes.SHA1()
             ).add_extension(x509.OCSPNonce(b"0000"), False)
             req = builder.build()
-        """))
+        """
+            )
+        )
 
-    @pytest.mark.parametrize("path", [
-        "pkcs12/cert-aes256cbc-no-key.p12",
-        "pkcs12/cert-key-aes256cbc.p12",
-    ])
+    @pytest.mark.parametrize(
+        "path",
+        ["pkcs12/cert-aes256cbc-no-key.p12", "pkcs12/cert-key-aes256cbc.p12"],
+    )
     def test_load_pkcs12_key_and_certificates(self, path):
-        assert_no_memory_leaks(textwrap.dedent("""
+        assert_no_memory_leaks(
+            textwrap.dedent(
+                """
         def func(path):
             from cryptography import x509
             from cryptography.hazmat.backends.openssl import backend
@@ -324,10 +397,15 @@
                 pkcs12.load_key_and_certificates(
                     f.read(), b"cryptography", backend
                 )
-        """), [path])
+        """
+            ),
+            [path],
+        )
 
     def test_create_crl_with_idp(self):
-        assert_no_memory_leaks(textwrap.dedent("""
+        assert_no_memory_leaks(
+            textwrap.dedent(
+                """
         def func():
             import datetime
             from cryptography import x509
@@ -369,4 +447,109 @@
             crl.extensions.get_extension_for_class(
                 x509.IssuingDistributionPoint
             )
-        """))
+        """
+            )
+        )
+
+    def test_create_certificate_with_extensions(self):
+        assert_no_memory_leaks(
+            textwrap.dedent(
+                """
+        def func():
+            import datetime
+
+            from cryptography import x509
+            from cryptography.hazmat.backends.openssl import backend
+            from cryptography.hazmat.primitives import hashes
+            from cryptography.hazmat.primitives.asymmetric import ec
+            from cryptography.x509.oid import (
+                AuthorityInformationAccessOID, ExtendedKeyUsageOID, NameOID
+            )
+
+            private_key = ec.generate_private_key(ec.SECP256R1(), backend)
+
+            not_valid_before = datetime.datetime.now()
+            not_valid_after = not_valid_before + datetime.timedelta(days=365)
+
+            aia = x509.AuthorityInformationAccess([
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.OCSP,
+                    x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+                ),
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.CA_ISSUERS,
+                    x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
+                )
+            ])
+            sans = [u'*.example.org', u'foobar.example.net']
+            san = x509.SubjectAlternativeName(list(map(x509.DNSName, sans)))
+
+            ski = x509.SubjectKeyIdentifier.from_public_key(
+                private_key.public_key()
+            )
+            eku = x509.ExtendedKeyUsage([
+                ExtendedKeyUsageOID.CLIENT_AUTH,
+                ExtendedKeyUsageOID.SERVER_AUTH,
+                ExtendedKeyUsageOID.CODE_SIGNING,
+            ])
+
+            builder = x509.CertificateBuilder().serial_number(
+                777
+            ).issuer_name(x509.Name([
+                x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
+            ])).subject_name(x509.Name([
+                x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
+            ])).public_key(
+                private_key.public_key()
+            ).add_extension(
+                aia, critical=False
+            ).not_valid_before(
+                not_valid_before
+            ).not_valid_after(
+                not_valid_after
+            )
+
+            cert = builder.sign(private_key, hashes.SHA256(), backend)
+            cert.extensions
+        """
+            )
+        )
+
+    def test_write_pkcs12_key_and_certificates(self):
+        assert_no_memory_leaks(
+            textwrap.dedent(
+                """
+        def func():
+            import os
+            from cryptography import x509
+            from cryptography.hazmat.backends.openssl import backend
+            from cryptography.hazmat.primitives import serialization
+            from cryptography.hazmat.primitives.serialization import pkcs12
+            import cryptography_vectors
+
+            path = os.path.join('x509', 'custom', 'ca', 'ca.pem')
+            with cryptography_vectors.open_vector_file(path, "rb") as f:
+                cert = x509.load_pem_x509_certificate(
+                    f.read(), backend
+                )
+            path2 = os.path.join('x509', 'custom', 'dsa_selfsigned_ca.pem')
+            with cryptography_vectors.open_vector_file(path2, "rb") as f:
+                cert2 = x509.load_pem_x509_certificate(
+                    f.read(), backend
+                )
+            path3 = os.path.join('x509', 'letsencryptx3.pem')
+            with cryptography_vectors.open_vector_file(path3, "rb") as f:
+                cert3 = x509.load_pem_x509_certificate(
+                    f.read(), backend
+                )
+            key_path = os.path.join("x509", "custom", "ca", "ca_key.pem")
+            with cryptography_vectors.open_vector_file(key_path, "rb") as f:
+                key = serialization.load_pem_private_key(
+                    f.read(), None, backend
+                )
+            encryption = serialization.NoEncryption()
+            pkcs12.serialize_key_and_certificates(
+                b"name", key, cert, [cert2, cert3], encryption)
+        """
+            )
+        )
diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py
index fb1e62f..4bc046b 100644
--- a/tests/hazmat/bindings/test_openssl.py
+++ b/tests/hazmat/bindings/test_openssl.py
@@ -8,7 +8,10 @@
 
 from cryptography.exceptions import InternalError
 from cryptography.hazmat.bindings.openssl.binding import (
-    Binding, _consume_errors, _openssl_assert
+    Binding,
+    _consume_errors,
+    _openssl_assert,
+    _verify_package_version,
 )
 
 
@@ -19,18 +22,6 @@
         assert binding.lib
         assert binding.ffi
 
-    def test_crypto_lock_init(self):
-        b = Binding()
-
-        b.init_static_locks()
-        lock_cb = b.lib.CRYPTO_get_locking_callback()
-        if b.lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER:
-            assert lock_cb == b.ffi.NULL
-            assert b.lib.Cryptography_HAS_LOCKING_CALLBACKS == 0
-        else:
-            assert lock_cb != b.ffi.NULL
-            assert b.lib.Cryptography_HAS_LOCKING_CALLBACKS == 1
-
     def test_add_engine_more_than_once(self):
         b = Binding()
         b._register_osrandom_engine()
@@ -82,7 +73,7 @@
     def test_conditional_removal(self):
         b = Binding()
 
-        if b.lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER:
+        if not b.lib.CRYPTOGRAPHY_IS_LIBRESSL:
             assert b.lib.TLS_ST_OK
         else:
             with pytest.raises(AttributeError):
@@ -95,7 +86,7 @@
             b.lib.EVP_F_EVP_ENCRYPTFINAL_EX,
             b.lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH,
             b"",
-            -1
+            -1,
         )
         with pytest.raises(InternalError) as exc_info:
             _openssl_assert(b.lib, False)
@@ -114,7 +105,11 @@
             b.lib.EVP_F_EVP_ENCRYPTFINAL_EX,
             b.lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH,
             b"",
-            -1
+            -1,
         )
         b._register_osrandom_engine()
         assert _consume_errors(b.lib) == []
+
+    def test_version_mismatch(self):
+        with pytest.raises(ImportError):
+            _verify_package_version("nottherightversion")
diff --git a/tests/hazmat/primitives/fixtures_dh.py b/tests/hazmat/primitives/fixtures_dh.py
new file mode 100644
index 0000000..b766c42
--- /dev/null
+++ b/tests/hazmat/primitives/fixtures_dh.py
@@ -0,0 +1,26 @@
+# 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
+
+from cryptography.hazmat.primitives.asymmetric import dh
+
+FFDH3072_P = dh.DHParameterNumbers(
+    p=int(
+        "ffffffffffffffffadf85458a2bb4a9aafdc5620273d3cf1d8b9c583ce2d3695a9e"
+        "13641146433fbcc939dce249b3ef97d2fe363630c75d8f681b202aec4617ad3df1e"
+        "d5d5fd65612433f51f5f066ed0856365553ded1af3b557135e7f57c935984f0c70e"
+        "0e68b77e2a689daf3efe8721df158a136ade73530acca4f483a797abc0ab182b324"
+        "fb61d108a94bb2c8e3fbb96adab760d7f4681d4f42a3de394df4ae56ede76372bb1"
+        "90b07a7c8ee0a6d709e02fce1cdf7e2ecc03404cd28342f619172fe9ce98583ff8e"
+        "4f1232eef28183c3fe3b1b4c6fad733bb5fcbc2ec22005c58ef1837d1683b2c6f34"
+        "a26c1b2effa886b4238611fcfdcde355b3b6519035bbc34f4def99c023861b46fc9"
+        "d6e6c9077ad91d2691f7f7ee598cb0fac186d91caefe130985139270b4130c93bc4"
+        "37944f4fd4452e2d74dd364f2e21e71f54bff5cae82ab9c9df69ee86d2bc522363a"
+        "0dabc521979b0deada1dbf9a42d5c4484e0abcd06bfa53ddef3c1b20ee3fd59d7c2"
+        "5e41d2b66c62e37ffffffffffffffff",
+        16,
+    ),
+    g=2,
+)
diff --git a/tests/hazmat/primitives/fixtures_dsa.py b/tests/hazmat/primitives/fixtures_dsa.py
index dd947ae..d4568ea 100644
--- a/tests/hazmat/primitives/fixtures_dsa.py
+++ b/tests/hazmat/primitives/fixtures_dsa.py
@@ -5,7 +5,9 @@
 from __future__ import absolute_import, division, print_function
 
 from cryptography.hazmat.primitives.asymmetric.dsa import (
-    DSAParameterNumbers, DSAPrivateNumbers, DSAPublicNumbers
+    DSAParameterNumbers,
+    DSAPrivateNumbers,
+    DSAPublicNumbers,
 )
 
 
@@ -13,140 +15,147 @@
     public_numbers=DSAPublicNumbers(
         parameter_numbers=DSAParameterNumbers(
             p=int(
-                'd38311e2cd388c3ed698e82fdf88eb92b5a9a483dc88005d4b725ef34'
-                '1eabb47cf8a7a8a41e792a156b7ce97206c4f9c5ce6fc5ae7912102b6'
-                'b502e59050b5b21ce263dddb2044b652236f4d42ab4b5d6aa73189cef'
-                '1ace778d7845a5c1c1c7147123188f8dc551054ee162b634d60f097f7'
-                '19076640e20980a0093113a8bd73', 16
+                "d38311e2cd388c3ed698e82fdf88eb92b5a9a483dc88005d4b725ef34"
+                "1eabb47cf8a7a8a41e792a156b7ce97206c4f9c5ce6fc5ae7912102b6"
+                "b502e59050b5b21ce263dddb2044b652236f4d42ab4b5d6aa73189cef"
+                "1ace778d7845a5c1c1c7147123188f8dc551054ee162b634d60f097f7"
+                "19076640e20980a0093113a8bd73",
+                16,
             ),
-            q=int('96c5390a8b612c0e422bb2b0ea194a3ec935a281', 16),
+            q=int("96c5390a8b612c0e422bb2b0ea194a3ec935a281", 16),
             g=int(
-                '06b7861abbd35cc89e79c52f68d20875389b127361ca66822138ce499'
-                '1d2b862259d6b4548a6495b195aa0e0b6137ca37eb23b94074d3c3d30'
-                '0042bdf15762812b6333ef7b07ceba78607610fcc9ee68491dbc1e34c'
-                'd12615474e52b18bc934fb00c61d39e7da8902291c4434a4e2224c3f4'
-                'fd9f93cd6f4f17fc076341a7e7d9', 16
-            )
+                "06b7861abbd35cc89e79c52f68d20875389b127361ca66822138ce499"
+                "1d2b862259d6b4548a6495b195aa0e0b6137ca37eb23b94074d3c3d30"
+                "0042bdf15762812b6333ef7b07ceba78607610fcc9ee68491dbc1e34c"
+                "d12615474e52b18bc934fb00c61d39e7da8902291c4434a4e2224c3f4"
+                "fd9f93cd6f4f17fc076341a7e7d9",
+                16,
+            ),
         ),
         y=int(
-            '6f26d98d41de7d871b6381851c9d91fa03942092ab6097e76422070edb71d'
-            'b44ff568280fdb1709f8fc3feab39f1f824adaeb2a298088156ac31af1aa0'
-            '4bf54f475bdcfdcf2f8a2dd973e922d83e76f016558617603129b21c70bf7'
-            'd0e5dc9e68fe332e295b65876eb9a12fe6fca9f1a1ce80204646bf99b5771'
-            'd249a6fea627', 16
-        )
+            "6f26d98d41de7d871b6381851c9d91fa03942092ab6097e76422070edb71d"
+            "b44ff568280fdb1709f8fc3feab39f1f824adaeb2a298088156ac31af1aa0"
+            "4bf54f475bdcfdcf2f8a2dd973e922d83e76f016558617603129b21c70bf7"
+            "d0e5dc9e68fe332e295b65876eb9a12fe6fca9f1a1ce80204646bf99b5771"
+            "d249a6fea627",
+            16,
+        ),
     ),
-    x=int('8185fee9cc7c0e91fd85503274f1cd5a3fd15a49', 16)
+    x=int("8185fee9cc7c0e91fd85503274f1cd5a3fd15a49", 16),
 )
 
 DSA_KEY_2048 = DSAPrivateNumbers(
     public_numbers=DSAPublicNumbers(
         parameter_numbers=DSAParameterNumbers(
             p=int(
-                'ea1fb1af22881558ef93be8a5f8653c5a559434c49c8c2c12ace5e9c4'
-                '1434c9cf0a8e9498acb0f4663c08b4484eace845f6fb17dac62c98e70'
-                '6af0fc74e4da1c6c2b3fbf5a1d58ff82fc1a66f3e8b12252c40278fff'
-                '9dd7f102eed2cb5b7323ebf1908c234d935414dded7f8d244e54561b0'
-                'dca39b301de8c49da9fb23df33c6182e3f983208c560fb5119fbf78eb'
-                'e3e6564ee235c6a15cbb9ac247baba5a423bc6582a1a9d8a2b4f0e9e3'
-                'd9dbac122f750dd754325135257488b1f6ecabf21bff2947fe0d3b2cb'
-                '7ffe67f4e7fcdf1214f6053e72a5bb0dd20a0e9fe6db2df0a908c36e9'
-                '5e60bf49ca4368b8b892b9c79f61ef91c47567c40e1f80ac5aa66ef7',
-                16
+                "ea1fb1af22881558ef93be8a5f8653c5a559434c49c8c2c12ace5e9c4"
+                "1434c9cf0a8e9498acb0f4663c08b4484eace845f6fb17dac62c98e70"
+                "6af0fc74e4da1c6c2b3fbf5a1d58ff82fc1a66f3e8b12252c40278fff"
+                "9dd7f102eed2cb5b7323ebf1908c234d935414dded7f8d244e54561b0"
+                "dca39b301de8c49da9fb23df33c6182e3f983208c560fb5119fbf78eb"
+                "e3e6564ee235c6a15cbb9ac247baba5a423bc6582a1a9d8a2b4f0e9e3"
+                "d9dbac122f750dd754325135257488b1f6ecabf21bff2947fe0d3b2cb"
+                "7ffe67f4e7fcdf1214f6053e72a5bb0dd20a0e9fe6db2df0a908c36e9"
+                "5e60bf49ca4368b8b892b9c79f61ef91c47567c40e1f80ac5aa66ef7",
+                16,
             ),
             q=int(
-                '8ec73f3761caf5fdfe6e4e82098bf10f898740dcb808204bf6b18f507'
-                '192c19d', 16
+                "8ec73f3761caf5fdfe6e4e82098bf10f898740dcb808204bf6b18f507"
+                "192c19d",
+                16,
             ),
             g=int(
-                'e4c4eca88415b23ecf811c96e48cd24200fe916631a68a684e6ccb6b1'
-                '913413d344d1d8d84a333839d88eee431521f6e357c16e6a93be111a9'
-                '8076739cd401bab3b9d565bf4fb99e9d185b1e14d61c93700133f908b'
-                'ae03e28764d107dcd2ea7674217622074bb19efff482f5f5c1a86d555'
-                '1b2fc68d1c6e9d8011958ef4b9c2a3a55d0d3c882e6ad7f9f0f3c6156'
-                '8f78d0706b10a26f23b4f197c322b825002284a0aca91807bba98ece9'
-                '12b80e10cdf180cf99a35f210c1655fbfdd74f13b1b5046591f840387'
-                '3d12239834dd6c4eceb42bf7482e1794a1601357b629ddfa971f2ed27'
-                '3b146ec1ca06d0adf55dd91d65c37297bda78c6d210c0bc26e558302',
-                16
-            )
+                "e4c4eca88415b23ecf811c96e48cd24200fe916631a68a684e6ccb6b1"
+                "913413d344d1d8d84a333839d88eee431521f6e357c16e6a93be111a9"
+                "8076739cd401bab3b9d565bf4fb99e9d185b1e14d61c93700133f908b"
+                "ae03e28764d107dcd2ea7674217622074bb19efff482f5f5c1a86d555"
+                "1b2fc68d1c6e9d8011958ef4b9c2a3a55d0d3c882e6ad7f9f0f3c6156"
+                "8f78d0706b10a26f23b4f197c322b825002284a0aca91807bba98ece9"
+                "12b80e10cdf180cf99a35f210c1655fbfdd74f13b1b5046591f840387"
+                "3d12239834dd6c4eceb42bf7482e1794a1601357b629ddfa971f2ed27"
+                "3b146ec1ca06d0adf55dd91d65c37297bda78c6d210c0bc26e558302",
+                16,
+            ),
         ),
         y=int(
-            '6b32e31ab9031dc4dd0b5039a78d07826687ab087ae6de4736f5b0434e125'
-            '3092e8a0b231f9c87f3fc8a4cb5634eb194bf1b638b7a7889620ce6711567'
-            'e36aa36cda4604cfaa601a45918371d4ccf68d8b10a50a0460eb1dc0fff62'
-            'ef5e6ee4d473e18ea4a66c196fb7e677a49b48241a0b4a97128eff30fa437'
-            '050501a584f8771e7280d26d5af30784039159c11ebfea10b692fd0a58215'
-            'eeb18bff117e13f08db792ed4151a218e4bed8dddfb0793225bd1e9773505'
-            '166f4bd8cedbb286ea28232972da7bae836ba97329ba6b0a36508e50a52a7'
-            '675e476d4d4137eae13f22a9d2fefde708ba8f34bf336c6e76331761e4b06'
-            '17633fe7ec3f23672fb19d27', 16
-        )
+            "6b32e31ab9031dc4dd0b5039a78d07826687ab087ae6de4736f5b0434e125"
+            "3092e8a0b231f9c87f3fc8a4cb5634eb194bf1b638b7a7889620ce6711567"
+            "e36aa36cda4604cfaa601a45918371d4ccf68d8b10a50a0460eb1dc0fff62"
+            "ef5e6ee4d473e18ea4a66c196fb7e677a49b48241a0b4a97128eff30fa437"
+            "050501a584f8771e7280d26d5af30784039159c11ebfea10b692fd0a58215"
+            "eeb18bff117e13f08db792ed4151a218e4bed8dddfb0793225bd1e9773505"
+            "166f4bd8cedbb286ea28232972da7bae836ba97329ba6b0a36508e50a52a7"
+            "675e476d4d4137eae13f22a9d2fefde708ba8f34bf336c6e76331761e4b06"
+            "17633fe7ec3f23672fb19d27",
+            16,
+        ),
     ),
     x=int(
-        '405772da6e90d809e77d5de796562a2dd4dfd10ef00a83a3aba6bd818a0348a1',
-        16
-    )
+        "405772da6e90d809e77d5de796562a2dd4dfd10ef00a83a3aba6bd818a0348a1", 16
+    ),
 )
 
 DSA_KEY_3072 = DSAPrivateNumbers(
     public_numbers=DSAPublicNumbers(
         parameter_numbers=DSAParameterNumbers(
             p=int(
-                'f335666dd1339165af8b9a5e3835adfe15c158e4c3c7bd53132e7d582'
-                '8c352f593a9a787760ce34b789879941f2f01f02319f6ae0b756f1a84'
-                '2ba54c85612ed632ee2d79ef17f06b77c641b7b080aff52a03fc2462e'
-                '80abc64d223723c236deeb7d201078ec01ca1fbc1763139e25099a84e'
-                'c389159c409792080736bd7caa816b92edf23f2c351f90074aa5ea265'
-                '1b372f8b58a0a65554db2561d706a63685000ac576b7e4562e262a142'
-                '85a9c6370b290e4eb7757527d80b6c0fd5df831d36f3d1d35f12ab060'
-                '548de1605fd15f7c7aafed688b146a02c945156e284f5b71282045aba'
-                '9844d48b5df2e9e7a5887121eae7d7b01db7cdf6ff917cd8eb50c6bf1'
-                'd54f90cce1a491a9c74fea88f7e7230b047d16b5a6027881d6f154818'
-                'f06e513faf40c8814630e4e254f17a47bfe9cb519b98289935bf17673'
-                'ae4c8033504a20a898d0032ee402b72d5986322f3bdfb27400561f747'
-                '6cd715eaabb7338b854e51fc2fa026a5a579b6dcea1b1c0559c13d3c1'
-                '136f303f4b4d25ad5b692229957', 16
+                "f335666dd1339165af8b9a5e3835adfe15c158e4c3c7bd53132e7d582"
+                "8c352f593a9a787760ce34b789879941f2f01f02319f6ae0b756f1a84"
+                "2ba54c85612ed632ee2d79ef17f06b77c641b7b080aff52a03fc2462e"
+                "80abc64d223723c236deeb7d201078ec01ca1fbc1763139e25099a84e"
+                "c389159c409792080736bd7caa816b92edf23f2c351f90074aa5ea265"
+                "1b372f8b58a0a65554db2561d706a63685000ac576b7e4562e262a142"
+                "85a9c6370b290e4eb7757527d80b6c0fd5df831d36f3d1d35f12ab060"
+                "548de1605fd15f7c7aafed688b146a02c945156e284f5b71282045aba"
+                "9844d48b5df2e9e7a5887121eae7d7b01db7cdf6ff917cd8eb50c6bf1"
+                "d54f90cce1a491a9c74fea88f7e7230b047d16b5a6027881d6f154818"
+                "f06e513faf40c8814630e4e254f17a47bfe9cb519b98289935bf17673"
+                "ae4c8033504a20a898d0032ee402b72d5986322f3bdfb27400561f747"
+                "6cd715eaabb7338b854e51fc2fa026a5a579b6dcea1b1c0559c13d3c1"
+                "136f303f4b4d25ad5b692229957",
+                16,
             ),
             q=int(
-                'd3eba6521240694015ef94412e08bf3cf8d635a455a398d6f210f6169'
-                '041653b', 16
+                "d3eba6521240694015ef94412e08bf3cf8d635a455a398d6f210f6169"
+                "041653b",
+                16,
             ),
             g=int(
-                'ce84b30ddf290a9f787a7c2f1ce92c1cbf4ef400e3cd7ce4978db2104'
-                'd7394b493c18332c64cec906a71c3778bd93341165dee8e6cd4ca6f13'
-                'afff531191194ada55ecf01ff94d6cf7c4768b82dd29cd131aaf202ae'
-                'fd40e564375285c01f3220af4d70b96f1395420d778228f1461f5d0b8'
-                'e47357e87b1fe3286223b553e3fc9928f16ae3067ded6721bedf1d1a0'
-                '1bfd22b9ae85fce77820d88cdf50a6bde20668ad77a707d1c60fcc5d5'
-                '1c9de488610d0285eb8ff721ff141f93a9fb23c1d1f7654c07c46e588'
-                '36d1652828f71057b8aff0b0778ef2ca934ea9d0f37daddade2d823a4'
-                'd8e362721082e279d003b575ee59fd050d105dfd71cd63154efe431a0'
-                '869178d9811f4f231dc5dcf3b0ec0f2b0f9896c32ec6c7ee7d60aa971'
-                '09e09224907328d4e6acd10117e45774406c4c947da8020649c3168f6'
-                '90e0bd6e91ac67074d1d436b58ae374523deaf6c93c1e6920db4a080b'
-                '744804bb073cecfe83fa9398cf150afa286dc7eb7949750cf5001ce10'
-                '4e9187f7e16859afa8fd0d775ae', 16
-            )
+                "ce84b30ddf290a9f787a7c2f1ce92c1cbf4ef400e3cd7ce4978db2104"
+                "d7394b493c18332c64cec906a71c3778bd93341165dee8e6cd4ca6f13"
+                "afff531191194ada55ecf01ff94d6cf7c4768b82dd29cd131aaf202ae"
+                "fd40e564375285c01f3220af4d70b96f1395420d778228f1461f5d0b8"
+                "e47357e87b1fe3286223b553e3fc9928f16ae3067ded6721bedf1d1a0"
+                "1bfd22b9ae85fce77820d88cdf50a6bde20668ad77a707d1c60fcc5d5"
+                "1c9de488610d0285eb8ff721ff141f93a9fb23c1d1f7654c07c46e588"
+                "36d1652828f71057b8aff0b0778ef2ca934ea9d0f37daddade2d823a4"
+                "d8e362721082e279d003b575ee59fd050d105dfd71cd63154efe431a0"
+                "869178d9811f4f231dc5dcf3b0ec0f2b0f9896c32ec6c7ee7d60aa971"
+                "09e09224907328d4e6acd10117e45774406c4c947da8020649c3168f6"
+                "90e0bd6e91ac67074d1d436b58ae374523deaf6c93c1e6920db4a080b"
+                "744804bb073cecfe83fa9398cf150afa286dc7eb7949750cf5001ce10"
+                "4e9187f7e16859afa8fd0d775ae",
+                16,
+            ),
         ),
         y=int(
-            '814824e435e1e6f38daa239aad6dad21033afce6a3ebd35c1359348a0f241'
-            '8871968c2babfc2baf47742148828f8612183178f126504da73566b6bab33'
-            'ba1f124c15aa461555c2451d86c94ee21c3e3fc24c55527e01b1f03adcdd8'
-            'ec5cb08082803a7b6a829c3e99eeb332a2cf5c035b0ce0078d3d414d31fa4'
-            '7e9726be2989b8d06da2e6cd363f5a7d1515e3f4925e0b32adeae3025cc5a'
-            '996f6fd27494ea408763de48f3bb39f6a06514b019899b312ec570851637b'
-            '8865cff3a52bf5d54ad5a19e6e400a2d33251055d0a440b50d53f4791391d'
-            'c754ad02b9eab74c46b4903f9d76f824339914db108057af7cde657d41766'
-            'a99991ac8787694f4185d6f91d7627048f827b405ec67bf2fe56141c4c581'
-            'd8c317333624e073e5879a82437cb0c7b435c0ce434e15965db1315d64895'
-            '991e6bbe7dac040c42052408bbc53423fd31098248a58f8a67da3a39895cd'
-            '0cc927515d044c1e3cb6a3259c3d0da354cce89ea3552c59609db10ee9899'
-            '86527436af21d9485ddf25f90f7dff6d2bae', 16
-        )
+            "814824e435e1e6f38daa239aad6dad21033afce6a3ebd35c1359348a0f241"
+            "8871968c2babfc2baf47742148828f8612183178f126504da73566b6bab33"
+            "ba1f124c15aa461555c2451d86c94ee21c3e3fc24c55527e01b1f03adcdd8"
+            "ec5cb08082803a7b6a829c3e99eeb332a2cf5c035b0ce0078d3d414d31fa4"
+            "7e9726be2989b8d06da2e6cd363f5a7d1515e3f4925e0b32adeae3025cc5a"
+            "996f6fd27494ea408763de48f3bb39f6a06514b019899b312ec570851637b"
+            "8865cff3a52bf5d54ad5a19e6e400a2d33251055d0a440b50d53f4791391d"
+            "c754ad02b9eab74c46b4903f9d76f824339914db108057af7cde657d41766"
+            "a99991ac8787694f4185d6f91d7627048f827b405ec67bf2fe56141c4c581"
+            "d8c317333624e073e5879a82437cb0c7b435c0ce434e15965db1315d64895"
+            "991e6bbe7dac040c42052408bbc53423fd31098248a58f8a67da3a39895cd"
+            "0cc927515d044c1e3cb6a3259c3d0da354cce89ea3552c59609db10ee9899"
+            "86527436af21d9485ddf25f90f7dff6d2bae",
+            16,
+        ),
     ),
     x=int(
-        'b2764c46113983777d3e7e97589f1303806d14ad9f2f1ef033097de954b17706',
-        16
-    )
+        "b2764c46113983777d3e7e97589f1303806d14ad9f2f1ef033097de954b17706", 16
+    ),
 )
diff --git a/tests/hazmat/primitives/fixtures_ec.py b/tests/hazmat/primitives/fixtures_ec.py
index 21c6903..d1d0a46 100644
--- a/tests/hazmat/primitives/fixtures_ec.py
+++ b/tests/hazmat/primitives/fixtures_ec.py
@@ -9,288 +9,272 @@
 
 EC_KEY_SECT571R1 = ec.EllipticCurvePrivateNumbers(
     private_value=int(
-        '213997069697108634621868251335076179190383272087548888968788698953'
-        '131928375431570122753130054966269038244076049869476736547896549201'
-        '7388482714521707824160638375437887802901'
+        "213997069697108634621868251335076179190383272087548888968788698953"
+        "131928375431570122753130054966269038244076049869476736547896549201"
+        "7388482714521707824160638375437887802901"
     ),
     public_numbers=ec.EllipticCurvePublicNumbers(
         curve=ec.SECT571R1(),
         x=int(
-            '42585672410900520895287019432267514156432686681290164230262278'
-            '54789182447139054594501570747809649335533486119017169439209005'
-            '883737780433424425566023654583165324498640038089'
+            "42585672410900520895287019432267514156432686681290164230262278"
+            "54789182447139054594501570747809649335533486119017169439209005"
+            "883737780433424425566023654583165324498640038089"
         ),
         y=int(
-            '13822523320209387572500458104799806851658024537477228250738334'
-            '46977851514777531296572763848253279034733550774927720436494321'
-            '97281333379623823457479233585424800362717541750'
-        )
-    )
+            "13822523320209387572500458104799806851658024537477228250738334"
+            "46977851514777531296572763848253279034733550774927720436494321"
+            "97281333379623823457479233585424800362717541750"
+        ),
+    ),
 )
 
 EC_KEY_SECT409R1 = ec.EllipticCurvePrivateNumbers(
     private_value=int(
-        '604993237916498765317587097853603474519114726157206838874832379003'
-        '281871982139714656205843929472002062791572217653118715727'
+        "604993237916498765317587097853603474519114726157206838874832379003"
+        "281871982139714656205843929472002062791572217653118715727"
     ),
     public_numbers=ec.EllipticCurvePublicNumbers(
         curve=ec.SECT409R1(),
         x=int(
-            '76237701339268928039087238870073679814646664010783544301589269'
-            '2272579213400205907766385199643053767195204247826349822350081'
+            "76237701339268928039087238870073679814646664010783544301589269"
+            "2272579213400205907766385199643053767195204247826349822350081"
         ),
         y=int(
-            '10056668929618383045204866060110626563392345494925302478351744'
-            '01475129090774493235522729123877384838835703483224447476728811'
-        )
-    )
+            "10056668929618383045204866060110626563392345494925302478351744"
+            "01475129090774493235522729123877384838835703483224447476728811"
+        ),
+    ),
 )
 
 EC_KEY_SECT283R1 = ec.EllipticCurvePrivateNumbers(
     private_value=int(
-        '589705077255658434962118789801402573495547207239917043241273753671'
-        '0603230261342427657'
+        "589705077255658434962118789801402573495547207239917043241273753671"
+        "0603230261342427657"
     ),
     public_numbers=ec.EllipticCurvePublicNumbers(
         curve=ec.SECT283R1(),
         x=int(
-            '10694213430317013187241490088760888472172922291550831393222973'
-            '531614941756901942108493'
+            "10694213430317013187241490088760888472172922291550831393222973"
+            "531614941756901942108493"
         ),
         y=int(
-            '11461553100313943515373601367527399649593366728262918214942116'
-            '4359557613202950705170'
-        )
-    )
+            "11461553100313943515373601367527399649593366728262918214942116"
+            "4359557613202950705170"
+        ),
+    ),
 )
 
 EC_KEY_SECT233R1 = ec.EllipticCurvePrivateNumbers(
     private_value=int(
-        '343470067105388144757135261232658742142830154753739648095101899829'
-        '8288'
+        "343470067105388144757135261232658742142830154753739648095101899829"
+        "8288"
     ),
     public_numbers=ec.EllipticCurvePublicNumbers(
         curve=ec.SECT233R1(),
         x=int(
-            '74494951569151557692195071465128140646140765188698294062550374'
-            '71118267'
+            "74494951569151557692195071465128140646140765188698294062550374"
+            "71118267"
         ),
         y=int(
-            '48699150823022962508544923825876164485917001162461401797511748'
-            '44872205'
-        )
-    )
+            "48699150823022962508544923825876164485917001162461401797511748"
+            "44872205"
+        ),
+    ),
 )
 
 EC_KEY_SECT163R2 = ec.EllipticCurvePrivateNumbers(
-    private_value=int(
-        '11788436193853888218177032687141056784083668635'
-    ),
+    private_value=int("11788436193853888218177032687141056784083668635"),
     public_numbers=ec.EllipticCurvePublicNumbers(
         curve=ec.SECT163R2(),
-        x=int(
-            '5247234453330640212490501030772203801908103222463'
-        ),
-        y=int(
-            '3172513801099088785224248292142866317754124455206'
-        )
-    )
+        x=int("5247234453330640212490501030772203801908103222463"),
+        y=int("3172513801099088785224248292142866317754124455206"),
+    ),
 )
 
 EC_KEY_SECT571K1 = ec.EllipticCurvePrivateNumbers(
     private_value=int(
-        '592811051234886966121888758661314648311634839499582476726008738218'
-        '165015048237934517672316204181933804884636855291118594744334592153'
-        '883208936227914544246799490897169723387'
+        "592811051234886966121888758661314648311634839499582476726008738218"
+        "165015048237934517672316204181933804884636855291118594744334592153"
+        "883208936227914544246799490897169723387"
     ),
     public_numbers=ec.EllipticCurvePublicNumbers(
         curve=ec.SECT571K1(),
         x=int(
-            '81362471461936552203898455874182916939857774872643607884250052'
-            '29301336524105230729653881789373412990921493551253481866317181'
-            '50644729351721577822595637058949405764944491655'
+            "81362471461936552203898455874182916939857774872643607884250052"
+            "29301336524105230729653881789373412990921493551253481866317181"
+            "50644729351721577822595637058949405764944491655"
         ),
         y=int(
-            '14058041260812945396067821061063618047896814719828637241661260'
-            '31235681542401975593036630733881695595289523801041910183736211'
-            '587294494888450327374439795428519848065589000434'
-        )
-    )
+            "14058041260812945396067821061063618047896814719828637241661260"
+            "31235681542401975593036630733881695595289523801041910183736211"
+            "587294494888450327374439795428519848065589000434"
+        ),
+    ),
 )
 
 EC_KEY_SECT409K1 = ec.EllipticCurvePrivateNumbers(
     private_value=int(
-        '110321743150399087059465162400463719641470113494908091197354523708'
-        '934106732952992153105338671368548199643686444619485307877'
+        "110321743150399087059465162400463719641470113494908091197354523708"
+        "934106732952992153105338671368548199643686444619485307877"
     ),
     public_numbers=ec.EllipticCurvePublicNumbers(
         curve=ec.SECT409K1(),
         x=int(
-            '62280214209410363493525178797944995742119600145953755916426161'
-            '0790364158569265348038207313261547476506319796469776797725796'
+            "62280214209410363493525178797944995742119600145953755916426161"
+            "0790364158569265348038207313261547476506319796469776797725796"
         ),
         y=int(
-            '46653883749102474289095010108777579907422472804577185369332018'
-            '7318642669590280811057512951467298158275464566214288556375885'
-        )
-    )
+            "46653883749102474289095010108777579907422472804577185369332018"
+            "7318642669590280811057512951467298158275464566214288556375885"
+        ),
+    ),
 )
 
 EC_KEY_SECT283K1 = ec.EllipticCurvePrivateNumbers(
     private_value=int(
-        '182508394415444014156574733141549331538128234395356466108310015130'
-        '3868915489347291850'
+        "182508394415444014156574733141549331538128234395356466108310015130"
+        "3868915489347291850"
     ),
     public_numbers=ec.EllipticCurvePublicNumbers(
         curve=ec.SECT283K1(),
         x=int(
-            '31141647206111886426350703123670451554123180910379592764773885'
-            '2959123367428352287032'
+            "31141647206111886426350703123670451554123180910379592764773885"
+            "2959123367428352287032"
         ),
         y=int(
-            '71787460144483665964585187837283963089964760704065205376175384'
-            '58957627834444017112582'
-        )
-    )
+            "71787460144483665964585187837283963089964760704065205376175384"
+            "58957627834444017112582"
+        ),
+    ),
 )
 
 EC_KEY_SECT233K1 = ec.EllipticCurvePrivateNumbers(
     private_value=int(
-        '172670089647474613734091436081960550801254775902629891892394471086'
-        '2070'
+        "172670089647474613734091436081960550801254775902629891892394471086"
+        "2070"
     ),
     public_numbers=ec.EllipticCurvePublicNumbers(
         curve=ec.SECT233K1(),
         x=int(
-            '55693911474339510991521579392202889561373678973929426354737048'
-            '68129172'
+            "55693911474339510991521579392202889561373678973929426354737048"
+            "68129172"
         ),
         y=int(
-            '11025856248546376145959939911850923631416718241836051344384802'
-            '737277815'
-        )
-    )
+            "11025856248546376145959939911850923631416718241836051344384802"
+            "737277815"
+        ),
+    ),
 )
 
 EC_KEY_SECT163K1 = ec.EllipticCurvePrivateNumbers(
-    private_value=int(
-        '3699303791425402204035307605170569820290317991287'
-    ),
+    private_value=int("3699303791425402204035307605170569820290317991287"),
     public_numbers=ec.EllipticCurvePublicNumbers(
         curve=ec.SECT163K1(),
-        x=int(
-            '4479755902310063321544063130576409926980094120721'
-        ),
-        y=int(
-            '3051218481937171839039826690648109285113977745779'
-        )
-    )
+        x=int("4479755902310063321544063130576409926980094120721"),
+        y=int("3051218481937171839039826690648109285113977745779"),
+    ),
 )
 
 EC_KEY_SECP521R1 = ec.EllipticCurvePrivateNumbers(
     private_value=int(
-        '662751235215460886290293902658128847495347691199214706697089140769'
-        '672273950767961331442265530524063943548846724348048614239791498442'
-        '5997823106818915698960565'
+        "662751235215460886290293902658128847495347691199214706697089140769"
+        "672273950767961331442265530524063943548846724348048614239791498442"
+        "5997823106818915698960565"
     ),
     public_numbers=ec.EllipticCurvePublicNumbers(
         curve=ec.SECP521R1(),
         x=int(
-            '12944742826257420846659527752683763193401384271391513286022917'
-            '29910013082920512632908350502247952686156279140016049549948975'
-            '670668730618745449113644014505462'
+            "12944742826257420846659527752683763193401384271391513286022917"
+            "29910013082920512632908350502247952686156279140016049549948975"
+            "670668730618745449113644014505462"
         ),
         y=int(
-            '10784108810271976186737587749436295782985563640368689081052886'
-            '16296815984553198866894145509329328086635278430266482551941240'
-            '591605833440825557820439734509311'
-        )
-    )
+            "10784108810271976186737587749436295782985563640368689081052886"
+            "16296815984553198866894145509329328086635278430266482551941240"
+            "591605833440825557820439734509311"
+        ),
+    ),
 )
 
 EC_KEY_SECP384R1 = ec.EllipticCurvePrivateNumbers(
     private_value=int(
-        '280814107134858470598753916394807521398239633534281633982576099083'
-        '35787109896602102090002196616273211495718603965098'
+        "280814107134858470598753916394807521398239633534281633982576099083"
+        "35787109896602102090002196616273211495718603965098"
     ),
     public_numbers=ec.EllipticCurvePublicNumbers(
         curve=ec.SECP384R1(),
         x=int(
-            '10036914308591746758780165503819213553101287571902957054148542'
-            '504671046744460374996612408381962208627004841444205030'
+            "10036914308591746758780165503819213553101287571902957054148542"
+            "504671046744460374996612408381962208627004841444205030"
         ),
         y=int(
-            '17337335659928075994560513699823544906448896792102247714689323'
-            '575406618073069185107088229463828921069465902299522926'
-        )
-    )
+            "17337335659928075994560513699823544906448896792102247714689323"
+            "575406618073069185107088229463828921069465902299522926"
+        ),
+    ),
 )
 
 EC_KEY_SECP256R1 = ec.EllipticCurvePrivateNumbers(
     private_value=int(
-        '271032978511595617649844168316234344656921218699414461240502635010'
-        '25776962849'
+        "271032978511595617649844168316234344656921218699414461240502635010"
+        "25776962849"
     ),
     public_numbers=ec.EllipticCurvePublicNumbers(
         curve=ec.SECP256R1(),
         x=int(
-            '49325986169170464532722748935508337546545346352733747948730305'
-            '442770101441241'
+            "49325986169170464532722748935508337546545346352733747948730305"
+            "442770101441241"
         ),
         y=int(
-            '51709162888529903487188595007092772817469799707382623884187518'
-            '455962250433661'
-        )
-    )
+            "51709162888529903487188595007092772817469799707382623884187518"
+            "455962250433661"
+        ),
+    ),
 )
 
 EC_KEY_SECP256K1 = ec.EllipticCurvePrivateNumbers(
     private_value=int(
-        '683341569008473593765879222774207677458810362976327530563215318048'
-        '64380736732'
+        "683341569008473593765879222774207677458810362976327530563215318048"
+        "64380736732"
     ),
     public_numbers=ec.EllipticCurvePublicNumbers(
         curve=ec.SECP256K1(),
         x=int(
-            '59251322975795306609293064274738085741081547489119277536110995'
-            '120127593127884'
+            "59251322975795306609293064274738085741081547489119277536110995"
+            "120127593127884"
         ),
         y=int(
-            '10334192001480392039227801832201340147605940717841294644187071'
-            '8261641142297801'
-        )
-    )
+            "10334192001480392039227801832201340147605940717841294644187071"
+            "8261641142297801"
+        ),
+    ),
 )
 
 EC_KEY_SECP224R1 = ec.EllipticCurvePrivateNumbers(
     private_value=int(
-        '234854340492774342642505519082413233282383066880756900834047566251'
-        '50'
+        "234854340492774342642505519082413233282383066880756900834047566251"
+        "50"
     ),
     public_numbers=ec.EllipticCurvePublicNumbers(
         curve=ec.SECP224R1(),
         x=int(
-            '51165676638271204691095081341581621487998422645261573824239666'
-            '1214'
+            "51165676638271204691095081341581621487998422645261573824239666"
+            "1214"
         ),
         y=int(
-            '14936601450555711309158397172719963843891926209168533453717969'
-            '1265'
-        )
-    )
+            "14936601450555711309158397172719963843891926209168533453717969"
+            "1265"
+        ),
+    ),
 )
 
 EC_KEY_SECP192R1 = ec.EllipticCurvePrivateNumbers(
     private_value=int(
-        '4534766128536179420071447168915990251715442361606049349869'
+        "4534766128536179420071447168915990251715442361606049349869"
     ),
     public_numbers=ec.EllipticCurvePublicNumbers(
         curve=ec.SECP192R1(),
-        x=int(
-            '5415069751170397888083674339683360671310515485781457536999'
-        ),
-        y=int(
-            '18671605334415960797751252911958331304288357195986572776'
-        )
-    )
+        x=int("5415069751170397888083674339683360671310515485781457536999"),
+        y=int("18671605334415960797751252911958331304288357195986572776"),
+    ),
 )
diff --git a/tests/hazmat/primitives/fixtures_rsa.py b/tests/hazmat/primitives/fixtures_rsa.py
index a531783..2c06272 100644
--- a/tests/hazmat/primitives/fixtures_rsa.py
+++ b/tests/hazmat/primitives/fixtures_rsa.py
@@ -5,7 +5,8 @@
 from __future__ import absolute_import, division, print_function
 
 from cryptography.hazmat.primitives.asymmetric.rsa import (
-    RSAPrivateNumbers, RSAPublicNumbers
+    RSAPrivateNumbers,
+    RSAPublicNumbers,
 )
 
 
@@ -18,7 +19,8 @@
     ),
     d=int(
         "272869352cacf9c866c4e107acc95d4c608ca91460a93d28588d51cfccc07f449"
-        "18bbe7660f9f16adc2b4ed36ca310ef3d63b79bd447456e3505736a45a6ed21", 16
+        "18bbe7660f9f16adc2b4ed36ca310ef3d63b79bd447456e3505736a45a6ed21",
+        16,
     ),
     dmp1=int(
         "addff2ec7564c6b64bc670d250b6f24b0b8db6b2810099813b7e7658cecf5c39", 16
@@ -34,178 +36,239 @@
         n=int(
             "ae5411f963c50e3267fafcf76381c8b1e5f7b741fdb2a544bcf48bd607b10c991"
             "90caeb8011dc22cf83d921da55ec32bd05cac3ee02ca5e1dbef93952850b525",
-            16
+            16,
         ),
-    )
+    ),
 )
 
 RSA_KEY_512_ALT = RSAPrivateNumbers(
     p=int(
-        "febe19c29a0b50fefa4f7b1832f84df1caf9be8242da25c9d689e18226e67ce5",
-        16),
+        "febe19c29a0b50fefa4f7b1832f84df1caf9be8242da25c9d689e18226e67ce5", 16
+    ),
     q=int(
-        "eb616c639dd999feda26517e1c77b6878f363fe828c4e6670ec1787f28b1e731",
-        16),
+        "eb616c639dd999feda26517e1c77b6878f363fe828c4e6670ec1787f28b1e731", 16
+    ),
     d=int(
         "80edecfde704a806445a4cc782b85d3f36f17558f385654ea767f006470fdfcbda5e2"
-        "206839289d3f419b4e4fb8e1acee1b4fb9c591f69b64ec83937f5829241", 16),
+        "206839289d3f419b4e4fb8e1acee1b4fb9c591f69b64ec83937f5829241",
+        16,
+    ),
     dmp1=int(
-        "7f4fa06e2a3077a54691cc5216bf13ad40a4b9fa3dd0ea4bca259487484baea5",
-        16),
+        "7f4fa06e2a3077a54691cc5216bf13ad40a4b9fa3dd0ea4bca259487484baea5", 16
+    ),
     dmq1=int(
-        "35eaa70d5a8711c352ed1c15ab27b0e3f46614d575214535ae279b166597fac1",
-        16),
+        "35eaa70d5a8711c352ed1c15ab27b0e3f46614d575214535ae279b166597fac1", 16
+    ),
     iqmp=int(
-        "cc1f272de6846851ec80cb89a02dbac78f44b47bc08f53b67b4651a3acde8b19",
-        16),
+        "cc1f272de6846851ec80cb89a02dbac78f44b47bc08f53b67b4651a3acde8b19", 16
+    ),
     public_numbers=RSAPublicNumbers(
         e=65537,
         n=int(
             "ea397388b999ef0f7e7416fa000367efd9a0ba0deddd3f8160d1c36d62267f210"
             "fbd9c97abeb6654450ff03e7601b8caa6c6f4cba18f0b52c179d17e8f258ad5",
-            16),
-    )
+            16,
+        ),
+    ),
 )
 
 RSA_KEY_522 = RSAPrivateNumbers(
     p=int(
         "1a8aab9a069f92b52fdf05824f2846223dc27adfc806716a247a77d4c36885e4bf",
-        16),
+        16,
+    ),
     q=int(
         "19e8d620d177ec54cdb733bb1915e72ef644b1202b889ceb524613efa49c07eb4f",
-        16),
+        16,
+    ),
     d=int(
         "10b8a7c0a92c1ae2d678097d69db3bfa966b541fb857468291d48d1b52397ea2bac0d"
-        "4370c159015c7219e3806a01bbafaffdd46f86e3da1e2d1fe80a0369ccd745", 16),
+        "4370c159015c7219e3806a01bbafaffdd46f86e3da1e2d1fe80a0369ccd745",
+        16,
+    ),
     dmp1=int(
-        "3eb6277f66e6e2dcf89f1b8529431f730839dbd9a3e49555159bc8470eee886e5",
-        16),
+        "3eb6277f66e6e2dcf89f1b8529431f730839dbd9a3e49555159bc8470eee886e5", 16
+    ),
     dmq1=int(
         "184b4d74aa54c361e51eb23fee4eae5e4786b37b11b6e0447af9c0b9c4e4953c5b",
-        16),
+        16,
+    ),
     iqmp=int(
-        "f80e9ab4fa7b35d0d232ef51c4736d1f2dcf2c7b1dd8716211b1bf1337e74f8ae",
-        16),
+        "f80e9ab4fa7b35d0d232ef51c4736d1f2dcf2c7b1dd8716211b1bf1337e74f8ae", 16
+    ),
     public_numbers=RSAPublicNumbers(
         e=65537,
         n=int(
             "2afaea0e0bb6fca037da7d190b5270a6c665bc18e7a456f7e69beaac4433db748"
             "ba99acdd14697e453bca596eb35b47f2d48f1f85ef08ce5109dad557a9cf85ebf"
-            "1", 16),
+            "1",
+            16,
+        ),
     ),
 )
 
 RSA_KEY_599 = RSAPrivateNumbers(
     p=int(
         "cf95d20be0c7af69f4b3d909f65d858c26d1a7ef34da8e3977f4fa230580e58814b54"
-        "24be99", 16),
+        "24be99",
+        16,
+    ),
     q=int(
         "6052be4b28debd4265fe12ace5aa4a0c4eb8d63ff8853c66824b35622161eb48a3bc8"
-        "c3ada5", 16),
+        "c3ada5",
+        16,
+    ),
     d=int(
         "69d9adc465e61585d3142d7cc8dd30605e8d1cbbf31009bc2cd5538dc40528d5d68ee"
         "fe6a42d23674b6ec76e192351bf368c8968f0392110bf1c2825dbcff071270b80adcc"
-        "fa1d19d00a1", 16),
+        "fa1d19d00a1",
+        16,
+    ),
     dmp1=int(
         "a86d10edde456687fba968b1f298d2e07226adb1221b2a466a93f3d83280f0bb46c20"
-        "2b6811", 16),
+        "2b6811",
+        16,
+    ),
     dmq1=int(
         "40d570e08611e6b1da94b95d46f8e7fe80be48f7a5ff8838375b08039514a399b11c2"
-        "80735", 16),
+        "80735",
+        16,
+    ),
     iqmp=int(
         "cd051cb0ea68b88765c041262ace2ec4db11dab14afd192742e34d5da3328637fabdf"
-        "bae26e", 16),
+        "bae26e",
+        16,
+    ),
     public_numbers=RSAPublicNumbers(
         e=65537,
         n=int(
             "4e1b470fe00642426f3808e74c959632dd67855a4c503c5b7876ccf4dc7f6a1a4"
             "9107b90d26daf0a7879a6858218345fbc6e59f01cd095ca5647c27c25265e6c47"
-            "4fea89537191c7073d9d", 16),
-    )
+            "4fea89537191c7073d9d",
+            16,
+        ),
+    ),
 )
 
 RSA_KEY_745 = RSAPrivateNumbers(
     p=int(
         "1c5a0cfe9a86debd19eca33ba961f15bc598aa7983a545ce775b933afc89eb51bcf90"
-        "836257fdd060d4b383240241d", 16
+        "836257fdd060d4b383240241d",
+        16,
     ),
     q=int(
         "fb2634f657f82ee6b70553382c4e2ed26b947c97ce2f0016f1b282cf2998184ad0527"
-        "a9eead826dd95fe06b57a025", 16
+        "a9eead826dd95fe06b57a025",
+        16,
     ),
     d=int(
         "402f30f976bc07d15ff0779abff127b20a8b6b1d0024cc2ad8b6762d38f174f81e792"
         "3b49d80bdbdd80d9675cbc7b2793ec199a0430eb5c84604dacfdb29259ae6a1a44676"
-        "22f0b23d4cb0f5cb1db4b8173c8d9d3e57a74dbd200d2141", 16),
+        "22f0b23d4cb0f5cb1db4b8173c8d9d3e57a74dbd200d2141",
+        16,
+    ),
     dmp1=int(
         "e5e95b7751a6649f199be21bef7a51c9e49821d945b6fc5f538b4a670d8762c375b00"
-        "8e70f31d52b3ea2bd14c3101", 16),
+        "8e70f31d52b3ea2bd14c3101",
+        16,
+    ),
     dmq1=int(
         "12b85d5843645f72990fcf8d2f58408b34b3a3b9d9078dd527fceb5d2fb7839008092"
-        "dd4aca2a1fb00542801dcef5", 16),
+        "dd4aca2a1fb00542801dcef5",
+        16,
+    ),
     iqmp=int(
         "5672740d947f621fc7969e3a44ec26736f3f819863d330e63e9409e139d20753551ac"
-        "c16544dd2bdadb9dee917440", 16),
+        "c16544dd2bdadb9dee917440",
+        16,
+    ),
     public_numbers=RSAPublicNumbers(
         e=65537,
         n=int(
             "1bd085f92237774d34013b477ceebbb2f2feca71118db9b7429341477947e7b1d"
             "04e8c43ede3c52bb25781af58d4ff81289f301eac62dc3bcd7dafd7a4d5304e9f"
-            "308e766952fbf2b62373e66611fa53189987dbef9f7243dcbbeb25831", 16),
-    )
+            "308e766952fbf2b62373e66611fa53189987dbef9f7243dcbbeb25831",
+            16,
+        ),
+    ),
 )
 
 RSA_KEY_768 = RSAPrivateNumbers(
     p=int(
         "f80c0061b607f93206b68e208906498d68c6e396faf457150cf975c8f849848465869"
-        "7ecd402313397088044c4c2071b", 16),
+        "7ecd402313397088044c4c2071b",
+        16,
+    ),
     q=int(
         "e5b5dbecc93c6d306fc14e6aa9737f9be2728bc1a326a8713d2849b34c1cb54c63468"
-        "3a68abb1d345dbf15a3c492cf55", 16),
+        "3a68abb1d345dbf15a3c492cf55",
+        16,
+    ),
     d=int(
         "d44601442255ffa331212c60385b5e898555c75c0272632ff42d57c4b16ca97dbca9f"
         "d6d99cd2c9fd298df155ed5141b4be06c651934076133331d4564d73faed7ce98e283"
-        "2f7ce3949bc183be7e7ca34f6dd04a9098b6c73649394b0a76c541", 16),
+        "2f7ce3949bc183be7e7ca34f6dd04a9098b6c73649394b0a76c541",
+        16,
+    ),
     dmp1=int(
         "a5763406fa0b65929661ce7b2b8c73220e43a5ebbfe99ff15ddf464fd238105ad4f2a"
-        "c83818518d70627d8908703bb03", 16),
+        "c83818518d70627d8908703bb03",
+        16,
+    ),
     dmq1=int(
         "cb467a9ef899a39a685aecd4d0ad27b0bfdc53b68075363c373d8eb2bed8eccaf3533"
-        "42f4db735a9e087b7539c21ba9d", 16),
+        "42f4db735a9e087b7539c21ba9d",
+        16,
+    ),
     iqmp=int(
         "5fe86bd3aee0c4d09ef11e0530a78a4534c9b833422813b5c934a450c8e564d8097a0"
-        "6fd74f1ebe2d5573782093f587a", 16),
+        "6fd74f1ebe2d5573782093f587a",
+        16,
+    ),
     public_numbers=RSAPublicNumbers(
         e=65537,
         n=int(
             "de92f1eb5f4abf426b6cac9dd1e9bf57132a4988b4ed3f8aecc15e251028bd6df"
             "46eb97c711624af7db15e6430894d1b640c13929329241ee094f5a4fe1a20bc9b"
             "75232320a72bc567207ec54d6b48dccb19737cf63acc1021abb337f19130f7",
-            16),
-    )
+            16,
+        ),
+    ),
 )
 
 RSA_KEY_1024 = RSAPrivateNumbers(
     p=int(
         "ea4d9d9a1a068be44b9a5f8f6de0512b2c5ba1fb804a4655babba688e6e890b347c1a"
-        "7426685a929337f513ae4256f0b7e5022d642237f960c5b24b96bee8e51", 16),
+        "7426685a929337f513ae4256f0b7e5022d642237f960c5b24b96bee8e51",
+        16,
+    ),
     q=int(
         "cffb33e400d6f08b410d69deb18a85cf0ed88fcca9f32d6f2f66c62143d49aff92c11"
-        "4de937d4f1f62d4635ee89af99ce86d38a2b05310f3857c7b5d586ac8f9", 16),
+        "4de937d4f1f62d4635ee89af99ce86d38a2b05310f3857c7b5d586ac8f9",
+        16,
+    ),
     d=int(
         "3d12d46d04ce942fb99be7bf30587b8cd3e21d75a2720e7bda1b867f1d418d91d8b9f"
         "e1c00181fdde94f2faf33b4e6f800a1b3ae3b972ccb6d5079dcb6c794070ac8306d59"
         "c00b58b7a9a81122a6b055832de7c72334a07494d8e7c9fbeed2cc37e011d9e6bfc6e"
-        "9bcddbef7f0f5771d9cf82cd4b268c97ec684575c24b6c881", 16),
+        "9bcddbef7f0f5771d9cf82cd4b268c97ec684575c24b6c881",
+        16,
+    ),
     dmp1=int(
         "470f2b11257b7ec9ca34136f487f939e6861920ad8a9ae132a02e74af5dceaa5b4c98"
-        "2949ccb44b67e2bcad2f58674db237fe250e0d62b47b28fa1dfaa603b41", 16),
+        "2949ccb44b67e2bcad2f58674db237fe250e0d62b47b28fa1dfaa603b41",
+        16,
+    ),
     dmq1=int(
         "c616e8317d6b3ae8272973709b80e8397256697ff14ea03389de454f619f99915a617"
-        "45319fefbe154ec1d49441a772c2f63f7d15c478199afc60469bfd0d561", 16),
+        "45319fefbe154ec1d49441a772c2f63f7d15c478199afc60469bfd0d561",
+        16,
+    ),
     iqmp=int(
         "d15e7c9ad357dfcd5dbdc8427680daf1006761bcfba93a7f86589ad88832a8d564b1c"
-        "d4291a658c96fbaea7ca588795820902d85caebd49c2d731e3fe0243130", 16),
+        "d4291a658c96fbaea7ca588795820902d85caebd49c2d731e3fe0243130",
+        16,
+    ),
     public_numbers=RSAPublicNumbers(
         e=65537,
         n=int(
@@ -213,31 +276,44 @@
             "ede07be3bed0e355d48e0dfab1e4fb5187adf42d7d3fb0401c082acb8481bf17f"
             "0e871f8877be04c3a1197d40aa260e2e0c48ed3fd2b93dc3fc0867591f67f3cd6"
             "0a77adee1d68a8c3730a5702485f6ac9ede7f0fd2918e037ee4cc1fc1b4c9",
-            16),
-    )
+            16,
+        ),
+    ),
 )
 
 RSA_KEY_1025 = RSAPrivateNumbers(
     p=int(
         "18e9bfb7071725da04d31c103fa3563648c69def43a204989214eb57b0c8b299f9ef3"
-        "5dda79a62d8d67fd2a9b69fbd8d0490aa2edc1e111a2b8eb7c737bb691a5", 16),
+        "5dda79a62d8d67fd2a9b69fbd8d0490aa2edc1e111a2b8eb7c737bb691a5",
+        16,
+    ),
     q=int(
         "d8eccaeeb95815f3079d13685f3f72ca2bf2550b349518049421375df88ca9bbb4ba8"
-        "cb0e3502203c9eeae174112509153445d251313e4711a102818c66fcbb7", 16),
+        "cb0e3502203c9eeae174112509153445d251313e4711a102818c66fcbb7",
+        16,
+    ),
     d=int(
         "fe9ac54910b8b1bc948a03511c54cab206a1d36d50d591124109a48abb7480977ccb0"
         "47b4d4f1ce7b0805df2d4fa3fe425f49b78535a11f4b87a4eba0638b3340c23d4e6b2"
         "1ecebe9d5364ea6ead2d47b27836019e6ecb407000a50dc95a8614c9d0031a6e3a524"
-        "d2345cfb76e15c1f69d5ba35bdfb6ec63bcb115a757ef79d9", 16),
+        "d2345cfb76e15c1f69d5ba35bdfb6ec63bcb115a757ef79d9",
+        16,
+    ),
     dmp1=int(
         "18537e81006a68ea76d590cc88e73bd26bc38d09c977959748e5265c0ce21c0b5fd26"
-        "53d975f97ef759b809f791487a8fff1264bf561627fb4527a3f0bbb72c85", 16),
+        "53d975f97ef759b809f791487a8fff1264bf561627fb4527a3f0bbb72c85",
+        16,
+    ),
     dmq1=int(
         "c807eac5a1f1e1239f04b04dd16eff9a00565127a91046fa89e1eb5d6301cace85447"
-        "4d1f47b0332bd35b4214b66e9166953241538f761f30d969272ee214f17", 16),
+        "4d1f47b0332bd35b4214b66e9166953241538f761f30d969272ee214f17",
+        16,
+    ),
     iqmp=int(
         "133aa74dd41fe70fa244f07d0c4091a22f8c8f0134fe6aea9ec8b55383b758fefe358"
-        "2beec36eca91715eee7d21931f24fa9e97e8e3a50f9cd0f731574a5eafcc", 16),
+        "2beec36eca91715eee7d21931f24fa9e97e8e3a50f9cd0f731574a5eafcc",
+        16,
+    ),
     public_numbers=RSAPublicNumbers(
         e=65537,
         n=int(
@@ -245,31 +321,44 @@
             "bf276fe3523f38f5ddaf3ea9aa88486a9d8760ff732489075862bee0e599de5c5"
             "f509b4519f4f446521bad15cd279a498fe1e89107ce0d237e3103d7c5eb801666"
             "42e2924b152aebff97b71fdd2d68ebb45034cc784e2e822ff6d1edf98af3f3",
-            16),
-    )
+            16,
+        ),
+    ),
 )
 
 RSA_KEY_1026 = RSAPrivateNumbers(
     p=int(
         "1fcbfb8719c5bdb5fe3eb0937c76bb096e750b9442dfe31d6a877a13aed2a6a4e9f79"
-        "40f815f1c307dd6bc2b4b207bb6fe5be3a15bd2875a957492ce197cdedb1", 16),
+        "40f815f1c307dd6bc2b4b207bb6fe5be3a15bd2875a957492ce197cdedb1",
+        16,
+    ),
     q=int(
         "1f704a0f6b8966dd52582fdc08227dd3dbaeaa781918b41144b692711091b4ca4eb62"
-        "985c3513853828ce8739001dfba9a9a7f1a23cbcaf74280be925e2e7b50d", 16),
+        "985c3513853828ce8739001dfba9a9a7f1a23cbcaf74280be925e2e7b50d",
+        16,
+    ),
     d=int(
         "c67975e35a1d0d0b3ebfca736262cf91990cb31cf4ac473c0c816f3bc2720bcba2475"
         "e8d0de8535d257816c0fc53afc1b597eada8b229069d6ef2792fc23f59ffb4dc6c3d9"
         "0a3c462082025a4cba7561296dd3d8870c4440d779406f00879afe2c681e7f5ee055e"
-        "ff829e6e55883ec20830c72300762e6e3a333d94b4dbe4501", 16),
+        "ff829e6e55883ec20830c72300762e6e3a333d94b4dbe4501",
+        16,
+    ),
     dmp1=int(
         "314730ca7066c55d086a9fbdf3670ef7cef816b9efea8b514b882ae9d647217cf41d7"
-        "e9989269dc9893d02e315cb81f058c49043c2cac47adea58bdf5e20e841", 16),
+        "e9989269dc9893d02e315cb81f058c49043c2cac47adea58bdf5e20e841",
+        16,
+    ),
     dmq1=int(
         "1da28a9d687ff7cfeebc2439240de7505a8796376968c8ec723a2b669af8ce53d9c88"
-        "af18540bd78b2da429014923fa435f22697ac60812d7ca9c17a557f394cd", 16),
+        "af18540bd78b2da429014923fa435f22697ac60812d7ca9c17a557f394cd",
+        16,
+    ),
     iqmp=int(
         "727947b57b8a36acd85180522f1b381bce5fdbd962743b3b14af98a36771a80f58ddd"
-        "62675d72a5935190da9ddc6fd6d6d5e9e9f805a2e92ab8d56b820493cdf", 16),
+        "62675d72a5935190da9ddc6fd6d6d5e9e9f805a2e92ab8d56b820493cdf",
+        16,
+    ),
     public_numbers=RSAPublicNumbers(
         e=65537,
         n=int(
@@ -277,31 +366,44 @@
             "9cfae6ab0446da18e26f33e1d753bc1cc03585c100cf0ab5ef056695706fc8b0c"
             "9c710cd73fe6e5beda70f515a96fabd3cc5ac49efcb2594b220ff3b603fcd927f"
             "6a0838ef04bf52f3ed9eab801f09e5aed1613ddeb946ed0fbb02060b3a36fd",
-            16),
-    )
+            16,
+        ),
+    ),
 )
 
 RSA_KEY_1027 = RSAPrivateNumbers(
     p=int(
         "30135e54cfb072c3d3eaf2000f3ed92ceafc85efc867b9d4bf5612f2978c432040093"
-        "4829f741c0f002b54af2a4433ff872b6321ef00ff1e72cba4e0ced937c7d", 16),
+        "4829f741c0f002b54af2a4433ff872b6321ef00ff1e72cba4e0ced937c7d",
+        16,
+    ),
     q=int(
         "1d01a8aead6f86b78c875f18edd74214e06535d65da054aeb8e1851d6f3319b4fb6d8"
-        "6b01e07d19f8261a1ded7dc08116345509ab9790e3f13e65c037e5bb7e27", 16),
+        "6b01e07d19f8261a1ded7dc08116345509ab9790e3f13e65c037e5bb7e27",
+        16,
+    ),
     d=int(
         "21cf4477df79561c7818731da9b9c88cd793f1b4b8e175bd0bfb9c0941a4dc648ecf1"
         "6d96b35166c9ea116f4c2eb33ce1c231e641a37c25e54c17027bdec08ddafcb83642e"
         "795a0dd133155ccc5eed03b6e745930d9ac7cfe91f9045149f33295af03a2198c660f"
-        "08d8150d13ce0e2eb02f21ac75d63b55822f77bd5be8d07619", 16),
+        "08d8150d13ce0e2eb02f21ac75d63b55822f77bd5be8d07619",
+        16,
+    ),
     dmp1=int(
         "173fb695931e845179511c18b546b265cb79b517c135902377281bdf9f34205e1f399"
-        "4603ad63e9f6e7885ea73a929f03fa0d6bed943051ce76cddde2d89d434d", 16),
+        "4603ad63e9f6e7885ea73a929f03fa0d6bed943051ce76cddde2d89d434d",
+        16,
+    ),
     dmq1=int(
         "10956b387b2621327da0c3c8ffea2af8be967ee25163222746c28115a406e632a7f12"
-        "5a9397224f1fa5c116cd3a313e5c508d31db2deb83b6e082d213e33f7fcf", 16),
+        "5a9397224f1fa5c116cd3a313e5c508d31db2deb83b6e082d213e33f7fcf",
+        16,
+    ),
     iqmp=int(
         "234f833949f2c0d797bc6a0e906331e17394fa8fbc8449395766d3a8d222cf6167c48"
-        "8e7fe1fe9721d3e3b699a595c8e6f063d92bd840dbc84d763b2b37002109", 16),
+        "8e7fe1fe9721d3e3b699a595c8e6f063d92bd840dbc84d763b2b37002109",
+        16,
+    ),
     public_numbers=RSAPublicNumbers(
         e=65537,
         n=int(
@@ -309,31 +411,44 @@
             "0a5ae9f579ef1fd7e42937f921eb3123c4a045cc47a2159fbbf904783e654954c"
             "42294c30a95c15db7c7b91f136244e548f62474b137087346c5522e54f226f49d"
             "6c93bc58cb39972e41bde452bb3ae9d60eb93e5e1ce91d222138d9890c7d0b",
-            16),
-    )
+            16,
+        ),
+    ),
 )
 
 RSA_KEY_1028 = RSAPrivateNumbers(
     p=int(
         "359d17378fae8e9160097daee78a206bd52efe1b757c12a6da8026cc4fc4bb2620f12"
-        "b8254f4db6aed8228be8ee3e5a27ec7d31048602f01edb00befd209e8c75", 16),
+        "b8254f4db6aed8228be8ee3e5a27ec7d31048602f01edb00befd209e8c75",
+        16,
+    ),
     q=int(
         "33a2e70b93d397c46e63b273dcd3dcfa64291342a6ce896e1ec8f1c0edc44106550f3"
-        "c06e7d3ca6ea29eccf3f6ab5ac6235c265313d6ea8e8767e6a343f616581", 16),
+        "c06e7d3ca6ea29eccf3f6ab5ac6235c265313d6ea8e8767e6a343f616581",
+        16,
+    ),
     d=int(
         "880640088d331aa5c0f4cf2887809a420a2bc086e671e6ffe4e47a8c80792c038a314"
         "9a8e45ef9a72816ab45b36e3af6800351067a6b2751843d4232413146bb575491463a"
         "8addd06ce3d1bcf7028ec6c5d938c545a20f0a40214b5c574ca7e840062b2b5f8ed49"
-        "4b144bb2113677c4b10519177fee1d4f5fb8a1c159b0b47c01", 16),
+        "4b144bb2113677c4b10519177fee1d4f5fb8a1c159b0b47c01",
+        16,
+    ),
     dmp1=int(
         "75f8c52dad2c1cea26b8bba63236ee4059489e3d2db766136098bcc6b67fde8f77cd3"
-        "640035107bfb1ffc6480983cfb84fe0c3be008424ebc968a7db7e01f005", 16),
+        "640035107bfb1ffc6480983cfb84fe0c3be008424ebc968a7db7e01f005",
+        16,
+    ),
     dmq1=int(
         "3893c59469e4ede5cd0e6ff9837ca023ba9b46ff40c60ccf1bec10f7d38db5b1ba817"
-        "6c41a3f750ec4203b711455aca06d1e0adffc5cffa42bb92c7cb77a6c01", 16),
+        "6c41a3f750ec4203b711455aca06d1e0adffc5cffa42bb92c7cb77a6c01",
+        16,
+    ),
     iqmp=int(
         "ad32aafae3c962ac25459856dc8ef1f733c3df697eced29773677f435d186cf759d1a"
-        "5563dd421ec47b4d7e7f12f29647c615166d9c43fc49001b29089344f65", 16),
+        "5563dd421ec47b4d7e7f12f29647c615166d9c43fc49001b29089344f65",
+        16,
+    ),
     public_numbers=RSAPublicNumbers(
         e=65537,
         n=int(
@@ -341,31 +456,44 @@
             "e3510c68073954d3ba4deb38643e7a820a4cf06e75f7f82eca545d412bd637819"
             "45c28d406e95a6cced5ae924a8bfa4f3def3e0250d91246c269ec40c89c93a85a"
             "cd3770ba4d2e774732f43abe94394de43fb57f93ca25f7a59d75d400a3eff5",
-            16),
-    )
+            16,
+        ),
+    ),
 )
 
 RSA_KEY_1029 = RSAPrivateNumbers(
     p=int(
         "66f33e513c0b6b6adbf041d037d9b1f0ebf8de52812a3ac397a963d3f71ba64b3ad04"
-        "e4d4b5e377e6fa22febcac292c907dc8dcfe64c807fd9a7e3a698850d983", 16),
+        "e4d4b5e377e6fa22febcac292c907dc8dcfe64c807fd9a7e3a698850d983",
+        16,
+    ),
     q=int(
         "3b47a89a19022461dcc2d3c05b501ee76955e8ce3cf821beb4afa85a21a26fd7203db"
-        "deb8941f1c60ada39fd6799f6c07eb8554113f1020460ec40e93cd5f6b21", 16),
+        "deb8941f1c60ada39fd6799f6c07eb8554113f1020460ec40e93cd5f6b21",
+        16,
+    ),
     d=int(
         "280c42af8b1c719821f2f6e2bf5f3dd53c81b1f3e1e7cc4fce6e2f830132da0665bde"
         "bc1e307106b112b52ad5754867dddd028116cf4471bc14a58696b99524b1ad8f05b31"
         "cf47256e54ab4399b6a073b2c0452441438dfddf47f3334c13c5ec86ece4d33409056"
-        "139328fafa992fb5f5156f25f9b21d3e1c37f156d963d97e41", 16),
+        "139328fafa992fb5f5156f25f9b21d3e1c37f156d963d97e41",
+        16,
+    ),
     dmp1=int(
         "198c7402a4ec10944c50ab8488d7b5991c767e75eb2817bd427dff10335ae141fa2e8"
-        "7c016dc22d975cac229b9ffdf7d943ddfd3a04b8bf82e83c3b32c5698b11", 16),
+        "7c016dc22d975cac229b9ffdf7d943ddfd3a04b8bf82e83c3b32c5698b11",
+        16,
+    ),
     dmq1=int(
         "15fd30c7687b68ef7c2a30cdeb913ec56c4757c218cf9a04d995470797ee5f3a17558"
-        "fbb6d00af245d2631d893b382da48a72bc8a613024289895952ab245b0c1", 16),
+        "fbb6d00af245d2631d893b382da48a72bc8a613024289895952ab245b0c1",
+        16,
+    ),
     iqmp=int(
         "4f8fde17e84557a3f4e242d889e898545ab55a1a8e075c9bb0220173ccffe84659abe"
-        "a235104f82e32750309389d4a52af57dbb6e48d831917b6efeb190176570", 16),
+        "a235104f82e32750309389d4a52af57dbb6e48d831917b6efeb190176570",
+        16,
+    ),
     public_numbers=RSAPublicNumbers(
         e=65537,
         n=int(
@@ -373,31 +501,44 @@
             "99a9f74981c3eeaaf947d5c2d64a1a80f5c5108a49a715c3f7be95a016b8d3300"
             "965ead4a4df76e642d761526803e9434d4ec61b10cb50526d4dcaef02593085de"
             "d8c331c1b27b200a45628403065efcb2c0a0ca1f75d648d40a007fbfbf2cae3",
-            16),
-    )
+            16,
+        ),
+    ),
 )
 
 RSA_KEY_1030 = RSAPrivateNumbers(
     p=int(
         "6f4ac8a8172ef1154cf7f80b5e91de723c35a4c512860bfdbafcc3b994a2384bf7796"
-        "3a2dd0480c7e04d5d418629651a0de8979add6f47b23da14c27a682b69c9", 16),
+        "3a2dd0480c7e04d5d418629651a0de8979add6f47b23da14c27a682b69c9",
+        16,
+    ),
     q=int(
         "65a9f83e07dea5b633e036a9dccfb32c46bf53c81040a19c574c3680838fc6d28bde9"
-        "55c0ff18b30481d4ab52a9f5e9f835459b1348bbb563ad90b15a682fadb3", 16),
+        "55c0ff18b30481d4ab52a9f5e9f835459b1348bbb563ad90b15a682fadb3",
+        16,
+    ),
     d=int(
         "290db707b3e1a96445ae8ea93af55a9f211a54ebe52995c2eb28085d1e3f09c986e73"
         "a00010c8e4785786eaaa5c85b98444bd93b585d0c24363ccc22c482e150a3fd900176"
         "86968e4fa20423ae72823b0049defceccb39bb34aa4ef64e6b14463b76d6a871c859e"
-        "37285455b94b8e1527d1525b1682ac6f7c8fd79d576c55318c1", 16),
+        "37285455b94b8e1527d1525b1682ac6f7c8fd79d576c55318c1",
+        16,
+    ),
     dmp1=int(
         "23f7fa84010225dea98297032dac5d45745a2e07976605681acfe87e0920a8ab3caf5"
-        "9d9602f3d63dc0584f75161fd8fff20c626c21c5e02a85282276a74628a9", 16),
+        "9d9602f3d63dc0584f75161fd8fff20c626c21c5e02a85282276a74628a9",
+        16,
+    ),
     dmq1=int(
         "18ebb657765464a8aa44bf019a882b72a2110a77934c54915f70e6375088b10331982"
-        "962bce1c7edd8ef9d3d95aa2566d2a99da6ebab890b95375919408d00f33", 16),
+        "962bce1c7edd8ef9d3d95aa2566d2a99da6ebab890b95375919408d00f33",
+        16,
+    ),
     iqmp=int(
         "3d59d208743c74054151002d77dcdfc55af3d41357e89af88d7eef2767be54c290255"
-        "9258d85cf2a1083c035a33e65a1ca46dc8b706847c1c6434cef7b71a9dae", 16),
+        "9258d85cf2a1083c035a33e65a1ca46dc8b706847c1c6434cef7b71a9dae",
+        16,
+    ),
     public_numbers=RSAPublicNumbers(
         e=65537,
         n=int(
@@ -405,31 +546,44 @@
             "8fcdbb6b4e12168304f587999f9d96a421fc80cb933a490df85d25883e6a88750"
             "d6bd8b3d4117251eee8f45e70e6daac7dbbd92a9103c623a09355cf00e3f16168"
             "e38b9c4cb5b368deabbed8df466bc6835eaba959bc1c2f4ec32a09840becc8b",
-            16),
-    )
+            16,
+        ),
+    ),
 )
 
 RSA_KEY_1031 = RSAPrivateNumbers(
     p=int(
         "c0958c08e50137db989fb7cc93abf1984543e2f955d4f43fb2967f40105e79274c852"
-        "293fa06ce63ca8436155e475ed6d1f73fea4c8e2516cc79153e3dc83e897", 16),
+        "293fa06ce63ca8436155e475ed6d1f73fea4c8e2516cc79153e3dc83e897",
+        16,
+    ),
     q=int(
         "78cae354ea5d6862e5d71d20273b7cddb8cdfab25478fe865180676b04250685c4d03"
-        "30c216574f7876a7b12dfe69f1661d3b0cea6c2c0dcfb84050f817afc28d", 16),
+        "30c216574f7876a7b12dfe69f1661d3b0cea6c2c0dcfb84050f817afc28d",
+        16,
+    ),
     d=int(
         "1d55cc02b17a5d25bfb39f2bc58389004d0d7255051507f75ef347cdf5519d1a00f4b"
         "d235ce4171bfab7bdb7a6dcfae1cf41433fb7da5923cc84f15a675c0b83492c95dd99"
         "a9fc157aea352ffdcbb5d59dbc3662171d5838d69f130678ee27841a79ef64f679ce9"
-        "3821fa69c03f502244c04b737edad8967def8022a144feaab29", 16),
+        "3821fa69c03f502244c04b737edad8967def8022a144feaab29",
+        16,
+    ),
     dmp1=int(
         "5b1c2504ec3a984f86b4414342b5bcf59a0754f13adf25b2a0edbc43f5ba8c3cc061d"
-        "80b03e5866d059968f0d10a98deaeb4f7830436d76b22cf41f2914e13eff", 16),
+        "80b03e5866d059968f0d10a98deaeb4f7830436d76b22cf41f2914e13eff",
+        16,
+    ),
     dmq1=int(
         "6c361e1819691ab5d67fb2a8f65c958d301cdf24d90617c68ec7005edfb4a7b638cde"
-        "79d4b61cfba5c86e8c0ccf296bc7f611cb8d4ae0e072a0f68552ec2d5995", 16),
+        "79d4b61cfba5c86e8c0ccf296bc7f611cb8d4ae0e072a0f68552ec2d5995",
+        16,
+    ),
     iqmp=int(
         "b7d61945fdc8b92e075b15554bab507fa8a18edd0a18da373ec6c766c71eece61136a"
-        "84b90b6d01741d40458bfad17a9bee9d4a8ed2f6e270782dc3bf5d58b56e", 16),
+        "84b90b6d01741d40458bfad17a9bee9d4a8ed2f6e270782dc3bf5d58b56e",
+        16,
+    ),
     public_numbers=RSAPublicNumbers(
         e=65537,
         n=int(
@@ -437,38 +591,51 @@
             "9f73da0690581691626d8a7cf5d972cced9c2091ccf999024b23b4e6dc6d99f80"
             "a454737dec0caffaebe4a3fac250ed02079267c8f39620b5ae3e125ca35338522"
             "dc9353ecac19cb2fe3b9e3a9291619dbb1ea3a7c388e9ee6469fbf5fb22892b",
-            16),
-    )
+            16,
+        ),
+    ),
 )
 
 RSA_KEY_1536 = RSAPrivateNumbers(
     p=int(
         "f1a65fa4e2aa6e7e2b560251e8a4cd65b625ad9f04f6571785782d1c213d91c961637"
         "0c572f2783caf2899f7fb690cf99a0184257fbd4b071b212c88fb348279a5387e61f1"
-        "17e9c62980c45ea863fa9292087c0f66ecdcde6443d5a37268bf71", 16),
+        "17e9c62980c45ea863fa9292087c0f66ecdcde6443d5a37268bf71",
+        16,
+    ),
     q=int(
         "e54c2cbc3839b1da6ae6fea45038d986d6f523a3ae76051ba20583aab711ea5965cf5"
         "3cf54128cc9573f7460bba0fd6758a57aaf240c391790fb38ab473d83ef735510c53d"
-        "1d10c31782e8fd7da42615e33565745c30a5e6ceb2a3ae0666cc35", 16),
+        "1d10c31782e8fd7da42615e33565745c30a5e6ceb2a3ae0666cc35",
+        16,
+    ),
     d=int(
         "7bcad87e23da2cb2a8c328883fabce06e1f8e9b776c8bf253ad9884e6200e3bd9bd3b"
         "a2cbe87d3854527bf005ba5d878c5b0fa20cfb0a2a42884ae95ca12bf7304285e9214"
         "5e992f7006c7c0ae839ad550da495b143bec0f4806c7f44caed45f3ccc6dc44cfaf30"
         "7abdb757e3d28e41c2d21366835c0a41e50a95af490ac03af061d2feb36ac0afb87be"
         "a13fb0f0c5a410727ebedb286c77f9469473fae27ef2c836da6071ef7efc1647f1233"
-        "4009a89eecb09a8287abc8c2afd1ddd9a1b0641", 16),
+        "4009a89eecb09a8287abc8c2afd1ddd9a1b0641",
+        16,
+    ),
     dmp1=int(
         "a845366cd6f9df1f34861bef7594ed025aa83a12759e245f58adaa9bdff9c3befb760"
         "75d3701e90038e888eec9bf092df63400152cb25fc07effc6c74c45f0654ccbde15cd"
-        "90dd5504298a946fa5cf22a956072da27a6602e6c6e5c97f2db9c1", 16),
+        "90dd5504298a946fa5cf22a956072da27a6602e6c6e5c97f2db9c1",
+        16,
+    ),
     dmq1=int(
         "28b0c1e78cdac03310717992d321a3888830ec6829978c048156152d805b4f8919c61"
         "70b5dd204e5ddf3c6c53bc6aff15d0bd09faff7f351b94abb9db980b31f150a6d7573"
-        "08eb66938f89a5225cb4dd817a824c89e7a0293b58fc2eefb7e259", 16),
+        "08eb66938f89a5225cb4dd817a824c89e7a0293b58fc2eefb7e259",
+        16,
+    ),
     iqmp=int(
         "6c1536c0e16e42a094b6caaf50231ba81916871497d73dcbbbd4bdeb9e60cae0413b3"
         "8143b5d680275b29ed7769fe5577e4f9b3647ddb064941120914526d64d80016d2eb7"
-        "dc362da7c569623157f3d7cff8347f11494bf5c048d77e28d3f515", 16),
+        "dc362da7c569623157f3d7cff8347f11494bf5c048d77e28d3f515",
+        16,
+    ),
     public_numbers=RSAPublicNumbers(
         e=65537,
         n=int(
@@ -477,8 +644,10 @@
             "c248ceef4050160705c188043c8559bf6dbfb6c4bb382eda4e9547575a8227d5b"
             "3c0a7088391364cf9f018d8bea053b226ec65e8cdbeaf48a071d0074860a734b1"
             "cb7d2146d43014b20776dea42f7853a54690e6cbbf3331a9f43763cfe2a51c329"
-            "3bea3b2eebec0d8e43eb317a443afe541107d886e5243c096091543ae65", 16),
-    )
+            "3bea3b2eebec0d8e43eb317a443afe541107d886e5243c096091543ae65",
+            16,
+        ),
+    ),
 )
 
 RSA_KEY_2048 = RSAPrivateNumbers(
@@ -486,12 +655,16 @@
         "e14202e58c5f7446648d75e5dc465781f661f6b73000c080368afcfb21377f4ef19da"
         "845d4ef9bc6b151f6d9f34629103f2e57615f9ba0a3a2fbb035069e1d63b4bb0e78ad"
         "dad1ec3c6f87e25c877a1c4c1972098e09158ef7b9bc163852a18d44a70b7b31a03dc"
-        "2614fd9ab7bf002cba79054544af3bfbdb6aed06c7b24e6ab", 16),
+        "2614fd9ab7bf002cba79054544af3bfbdb6aed06c7b24e6ab",
+        16,
+    ),
     q=int(
         "dbe2bea1ff92599bd19f9d045d6ce62250c05cfeac5117f3cf3e626cb696e3d886379"
         "557d5a57b7476f9cf886accfd40508a805fe3b45a78e1a8a125e516cda91640ee6398"
         "ec5a39d3e6b177ef12ab00d07907a17640e4ca454fd8487da3c4ffa0d5c2a5edb1221"
-        "1c8e33c7ee9fa6753771fd111ec04b8317f86693eb2928c89", 16),
+        "1c8e33c7ee9fa6753771fd111ec04b8317f86693eb2928c89",
+        16,
+    ),
     d=int(
         "aef17f80f2653bc30539f26dd4c82ed6abc1d1b53bc0abcdbee47e9a8ab433abde865"
         "9fcfae1244d22de6ad333c95aee7d47f30b6815065ac3322744d3ea75058002cd1b29"
@@ -500,22 +673,30 @@
         "c8263ce2802a769a090e993fd49abc50c3d3c78c29bee2de0c98055d2f102f1c5684b"
         "8dddee611d5205392d8e8dd61a15bf44680972a87f040a611a149271eeb2573f8bf6f"
         "627dfa70e77def2ee6584914fa0290e041349ea0999cdff3e493365885b906cbcf195"
-        "843345809a85098cca90fea014a21", 16),
+        "843345809a85098cca90fea014a21",
+        16,
+    ),
     dmp1=int(
         "9ba56522ffcfa5244eae805c87cc0303461f82be29691b9a7c15a5a050df6c143c575"
         "7c288d3d7ab7f32c782e9d9fcddc10a604e6425c0e5d0e46069035d95a923646d276d"
         "d9d95b8696fa29ab0de18e53f6f119310f8dd9efca62f0679291166fed8cbd5f18fe1"
-        "3a5f1ead1d71d8c90f40382818c18c8d069be793dbc094f69", 16),
+        "3a5f1ead1d71d8c90f40382818c18c8d069be793dbc094f69",
+        16,
+    ),
     dmq1=int(
         "a8d4a0aaa2212ccc875796a81353da1fdf00d46676c88d2b96a4bfcdd924622d8e607"
         "f3ac1c01dda7ebfb0a97dd7875c2a7b2db6728fb827b89c519f5716fb3228f4121647"
         "04b30253c17de2289e9cce3343baa82eb404f789e094a094577a9b0c5314f1725fdf5"
-        "8e87611ad20da331bd30b8aebc7dc97d0e9a9ba8579772c9", 16),
+        "8e87611ad20da331bd30b8aebc7dc97d0e9a9ba8579772c9",
+        16,
+    ),
     iqmp=int(
         "17bd5ef638c49440d1853acb3fa63a5aca28cb7f94ed350db7001c8445da8943866a7"
         "0936e1ee2716c98b484e357cc054d82fbbd98d42f880695d38a1dd4eb096f629b9417"
         "aca47e6de5da9f34e60e8a0ffd7e35be74deeef67298d94b3e0db73fc4b7a4cb360c8"
-        "9d2117a0bfd9434d37dc7c027d6b01e5295c875015510917d", 16),
+        "9d2117a0bfd9434d37dc7c027d6b01e5295c875015510917d",
+        16,
+    ),
     public_numbers=RSAPublicNumbers(
         e=65537,
         n=int(
@@ -526,8 +707,10 @@
             "c29e53635e24c87a5b2c4215968063cdeb68a972babbc1e3cff00fb9a80e372a4"
             "d0c2c920d1e8cee333ce470dc2e8145adb05bf29aee1d24f141e8cc784989c587"
             "fc6fbacd979f3f2163c1d7299b365bc72ffe2848e967aed1e48dcc515b3a50ed4"
-            "de04fd053846ca10a223b10cc841cc80fdebee44f3114c13e886af583", 16),
-    )
+            "de04fd053846ca10a223b10cc841cc80fdebee44f3114c13e886af583",
+            16,
+        ),
+    ),
 )
 
 RSA_KEY_2048_ALT = RSAPrivateNumbers(
@@ -598,6 +781,36 @@
             "715070507278514207864914944621214574162116786377990456375"
             "964817771730371110612100247262908550409785456157505694419"
             "00451152778245269283276012328748538414051025541"
-        )
-    )
+        ),
+    ),
 )
+
+RSA_KEY_CORRUPTED = b"""
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAuYE4k09MAsi1yjMrXekMe6sT9bEt3ko47dnmN8YBgO8DiiCc
+226TnQPvuX3FGxU+Y1zTJpcvVL3L37UOvh4CSb9zKyrFK9/x/UcCfK3Eq8JdS98P
+CVeGpkp5E+vwIKY72rc1RSSSCs0PtFdYbSn4trwf5BjPxIqXwIOS3R7zC7cLPHY4
+YdsM4gLGVOP17uXJr/MPoAtWTBVm5zx4bHm6Xclzgf86sbPdL3LxNs0fz4HqJZgA
+6EUtyl6Qypq2LjXbdmm2i3vC+MxW6nEPItPqgComhq0zBmVonsiEO87rEtD548Yq
+DKvxwHhlcODcVkAYebJ+W5L6PPJBNYA3t5wYyQIDAQABAoIBAAbHkg5msftpGt5Z
+Vb3yUuepem7hWTF5YFlIRw5l2wNcURNpbswEhOVNJbuG+KCple7Dw4TuDmhHs/zr
+BRqpDhXldhrUtb2uc3ihqWiVFJbieqE4jUbGvMJusvtXXeDwU6wGWzV/V4qndCrk
+u4PGypk4Cbbq6ZP2oufPryQ3D4Ff1TA06RSWdP3Cg673VqwLtkXwsRDhymAviiqU
+hxQg8bRNiD7mYoUKyLVeV7YRDLTBugfiFmy54yC99NJclLkYmzCgRt1EuoW0Hixx
+EIQFEOLftgpc+sKpbbiOileMsc/stytHXXqfgozhBxDNeSzdNYfwEpkLJpLZSUNV
+EhS4X1cCgYEAz+7DkXksWw9zLqYniMIcvcBnHQcy3Anqbcu8Zbw+I9wOwzNt44Bo
+f88i2idvWvMsRq/LX4WD4jjPB4Z3wAzGBCq+2cy0GrWByMu+VbpwCrntRBkS5huY
+IIf1nr1+BuySNt8TL6nZNKz0D8+5c8wT+VbVdPH//4MzfDrK81PPnesCgYEA5GMy
+ji4l+8zO33LFMlWQGYgfSMd4jGMQD0VCvfhlosK0Py0AfZj/GKEGHduo/37KVVvb
+6XdJqYgB7OxPmdEqbMGeYPKv7pKkG1jXRuEtmXXJ9hS1t0oIvXJLHJnQrOOoRRAR
++xJZbI7WjemY+ZCMOAPT1tm97pxjs81WgSJ6ExsCgYEAze5ADfEeNskkYAz6lnz4
+jgzhkmQwwK+pVzgxy9g8brNkg3qJ2Iix9fKlJ71qkX7IWPF9z4qhxQhSMbfBHZkI
++9OB1J7huJoOgVkXliwIbvcYvxq+Fts5XO6KGb699AmT/XgMvmXO0lbAGLC3kLGL
+DqQrH3kU+m9sLBrmKPrWYiUCgYEA3/8etW4zmMvd1jAFkoFyzGfCbyocZGxAcwm2
+FQYMAN8/03p6sbSd9XTwv9YR4Uxke+WURkjVuW2IneuDgtQv6QCFKob74Jx4Uc4H
+jiAKDioFg9H6C6OUAOKZIpsFnJvIDLxfNkVf6WYKrrL+cz6/F61BVsbGTsGZ094/
+ynWbDyMCgYEAh44C/wkebe0zz/llG+KTRGENsw1c7+pm0/l3wPYAlH02ewbyRjFf
+OKPfyyBtBkoD5rG3IbLyPxsbd3wWwyUzSYq02qRJq43XqyMZhRnNlYhEnNu/Gr5H
+sN1f13zqkKoRxxbIjyh4RDYlAv4Sehk27z2Q3gBe9bI5xKkoQ/VfF2w=
+-----END RSA PRIVATE KEY-----
+"""
diff --git a/tests/hazmat/primitives/test_3des.py b/tests/hazmat/primitives/test_3des.py
index f281ba2..d14dcad 100644
--- a/tests/hazmat/primitives/test_3des.py
+++ b/tests/hazmat/primitives/test_3des.py
@@ -28,7 +28,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestTripleDESModeCBC(object):
-    test_KAT = generate_encrypt_test(
+    test_kat = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "3DES", "CBC"),
         [
@@ -42,14 +42,10 @@
         lambda iv, **kwargs: modes.CBC(binascii.unhexlify(iv)),
     )
 
-    test_MMT = generate_encrypt_test(
+    test_mmt = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "3DES", "CBC"),
-        [
-            "TCBCMMT1.rsp",
-            "TCBCMMT2.rsp",
-            "TCBCMMT3.rsp",
-        ],
+        ["TCBCMMT1.rsp", "TCBCMMT2.rsp", "TCBCMMT3.rsp"],
         lambda key1, key2, key3, **kwargs: algorithms.TripleDES(
             binascii.unhexlify(key1 + key2 + key3)
         ),
@@ -65,7 +61,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestTripleDESModeOFB(object):
-    test_KAT = generate_encrypt_test(
+    test_kat = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "3DES", "OFB"),
         [
@@ -79,14 +75,10 @@
         lambda iv, **kwargs: modes.OFB(binascii.unhexlify(iv)),
     )
 
-    test_MMT = generate_encrypt_test(
+    test_mmt = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "3DES", "OFB"),
-        [
-            "TOFBMMT1.rsp",
-            "TOFBMMT2.rsp",
-            "TOFBMMT3.rsp",
-        ],
+        ["TOFBMMT1.rsp", "TOFBMMT2.rsp", "TOFBMMT3.rsp"],
         lambda key1, key2, key3, **kwargs: algorithms.TripleDES(
             binascii.unhexlify(key1 + key2 + key3)
         ),
@@ -102,7 +94,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestTripleDESModeCFB(object):
-    test_KAT = generate_encrypt_test(
+    test_kat = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "3DES", "CFB"),
         [
@@ -116,14 +108,10 @@
         lambda iv, **kwargs: modes.CFB(binascii.unhexlify(iv)),
     )
 
-    test_MMT = generate_encrypt_test(
+    test_mmt = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "3DES", "CFB"),
-        [
-            "TCFB64MMT1.rsp",
-            "TCFB64MMT2.rsp",
-            "TCFB64MMT3.rsp",
-        ],
+        ["TCFB64MMT1.rsp", "TCFB64MMT2.rsp", "TCFB64MMT3.rsp"],
         lambda key1, key2, key3, **kwargs: algorithms.TripleDES(
             binascii.unhexlify(key1 + key2 + key3)
         ),
@@ -139,7 +127,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestTripleDESModeCFB8(object):
-    test_KAT = generate_encrypt_test(
+    test_kat = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "3DES", "CFB"),
         [
@@ -153,14 +141,10 @@
         lambda iv, **kwargs: modes.CFB8(binascii.unhexlify(iv)),
     )
 
-    test_MMT = generate_encrypt_test(
+    test_mmt = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "3DES", "CFB"),
-        [
-            "TCFB8MMT1.rsp",
-            "TCFB8MMT2.rsp",
-            "TCFB8MMT3.rsp",
-        ],
+        ["TCFB8MMT1.rsp", "TCFB8MMT2.rsp", "TCFB8MMT3.rsp"],
         lambda key1, key2, key3, **kwargs: algorithms.TripleDES(
             binascii.unhexlify(key1 + key2 + key3)
         ),
@@ -176,7 +160,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestTripleDESModeECB(object):
-    test_KAT = generate_encrypt_test(
+    test_kat = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "3DES", "ECB"),
         [
@@ -190,14 +174,10 @@
         lambda **kwargs: modes.ECB(),
     )
 
-    test_MMT = generate_encrypt_test(
+    test_mmt = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "3DES", "ECB"),
-        [
-            "TECBMMT1.rsp",
-            "TECBMMT2.rsp",
-            "TECBMMT3.rsp",
-        ],
+        ["TECBMMT1.rsp", "TECBMMT2.rsp", "TECBMMT3.rsp"],
         lambda key1, key2, key3, **kwargs: algorithms.TripleDES(
             binascii.unhexlify(key1 + key2 + key3)
         ),
diff --git a/tests/hazmat/primitives/test_aead.py b/tests/hazmat/primitives/test_aead.py
index e1a17a9..2706931 100644
--- a/tests/hazmat/primitives/test_aead.py
+++ b/tests/hazmat/primitives/test_aead.py
@@ -12,13 +12,17 @@
 from cryptography.exceptions import InvalidTag, UnsupportedAlgorithm, _Reasons
 from cryptography.hazmat.backends.interfaces import CipherBackend
 from cryptography.hazmat.primitives.ciphers.aead import (
-    AESCCM, AESGCM, ChaCha20Poly1305
+    AESCCM,
+    AESGCM,
+    ChaCha20Poly1305,
 )
 
 from .utils import _load_all_params
 from ...utils import (
-    load_nist_ccm_vectors, load_nist_vectors, load_vectors_from_file,
-    raises_unsupported_algorithm
+    load_nist_ccm_vectors,
+    load_nist_vectors,
+    load_vectors_from_file,
+    raises_unsupported_algorithm,
 )
 
 
@@ -37,7 +41,7 @@
 
 @pytest.mark.skipif(
     _aead_supported(ChaCha20Poly1305),
-    reason="Requires OpenSSL without ChaCha20Poly1305 support"
+    reason="Requires OpenSSL without ChaCha20Poly1305 support",
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 def test_chacha20poly1305_unsupported_on_older_openssl(backend):
@@ -47,7 +51,7 @@
 
 @pytest.mark.skipif(
     not _aead_supported(ChaCha20Poly1305),
-    reason="Does not support ChaCha20Poly1305"
+    reason="Does not support ChaCha20Poly1305",
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestChaCha20Poly1305(object):
@@ -78,11 +82,12 @@
         [
             [object(), b"data", b""],
             [b"0" * 12, object(), b""],
-            [b"0" * 12, b"data", object()]
-        ]
+            [b"0" * 12, b"data", object()],
+        ],
     )
-    def test_params_not_bytes_encrypt(self, nonce, data, associated_data,
-                                      backend):
+    def test_params_not_bytes_encrypt(
+        self, nonce, data, associated_data, backend
+    ):
         key = ChaCha20Poly1305.generate_key()
         chacha = ChaCha20Poly1305(key)
         with pytest.raises(TypeError):
@@ -121,8 +126,8 @@
         "vector",
         load_vectors_from_file(
             os.path.join("ciphers", "ChaCha20Poly1305", "openssl.txt"),
-            load_nist_vectors
-        )
+            load_nist_vectors,
+        ),
     )
     def test_openssl_vectors(self, vector, backend):
         key = binascii.unhexlify(vector["key"])
@@ -145,8 +150,8 @@
         "vector",
         load_vectors_from_file(
             os.path.join("ciphers", "ChaCha20Poly1305", "boringssl.txt"),
-            load_nist_vectors
-        )
+            load_nist_vectors,
+        ),
     )
     def test_boringssl_vectors(self, vector, backend):
         key = binascii.unhexlify(vector["key"])
@@ -183,20 +188,6 @@
         assert computed_pt2 == pt
 
 
-@pytest.mark.skipif(
-    _aead_supported(AESCCM),
-    reason="Requires OpenSSL without AES-CCM support"
-)
-@pytest.mark.requires_backend_interface(interface=CipherBackend)
-def test_aesccm_unsupported_on_older_openssl(backend):
-    with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER):
-        AESCCM(AESCCM.generate_key(128))
-
-
-@pytest.mark.skipif(
-    not _aead_supported(AESCCM),
-    reason="Does not support AESCCM"
-)
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestAESCCM(object):
     def test_data_too_large(self):
@@ -245,22 +236,30 @@
         _load_all_params(
             os.path.join("ciphers", "AES", "CCM"),
             [
-                "DVPT128.rsp", "DVPT192.rsp", "DVPT256.rsp",
-                "VADT128.rsp", "VADT192.rsp", "VADT256.rsp",
-                "VNT128.rsp", "VNT192.rsp", "VNT256.rsp",
-                "VPT128.rsp", "VPT192.rsp", "VPT256.rsp",
+                "DVPT128.rsp",
+                "DVPT192.rsp",
+                "DVPT256.rsp",
+                "VADT128.rsp",
+                "VADT192.rsp",
+                "VADT256.rsp",
+                "VNT128.rsp",
+                "VNT192.rsp",
+                "VNT256.rsp",
+                "VPT128.rsp",
+                "VPT192.rsp",
+                "VPT256.rsp",
             ],
-            load_nist_ccm_vectors
-        )
+            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"]]
+        adata = binascii.unhexlify(vector["adata"])[: vector["alen"]]
         ct = binascii.unhexlify(vector["ct"])
-        pt = binascii.unhexlify(vector["payload"])[:vector["plen"]]
+        pt = binascii.unhexlify(vector["payload"])[: vector["plen"]]
         aesccm = AESCCM(key, vector["tlen"])
-        if vector.get('fail'):
+        if vector.get("fail"):
             with pytest.raises(InvalidTag):
                 aesccm.decrypt(nonce, ct, adata)
         else:
@@ -293,7 +292,7 @@
             [object(), b"data", b""],
             [b"0" * 12, object(), b""],
             [b"0" * 12, b"data", object()],
-        ]
+        ],
     )
     def test_params_not_bytes(self, nonce, data, associated_data, backend):
         key = AESCCM.generate_key(128)
@@ -359,7 +358,7 @@
             "gcmEncryptExtIV192.rsp",
             "gcmEncryptExtIV256.rsp",
         ],
-        load_nist_vectors
+        load_nist_vectors,
     )
     return [x for x in vectors if len(x["tag"]) == 32]
 
@@ -378,9 +377,18 @@
             aesgcm.encrypt(nonce, b"", FakeData())
 
     @pytest.mark.parametrize("vector", _load_gcm_vectors())
-    def test_vectors(self, vector):
-        key = binascii.unhexlify(vector["key"])
+    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""))
@@ -401,8 +409,8 @@
         [
             [object(), b"data", b""],
             [b"0" * 12, object(), b""],
-            [b"0" * 12, b"data", object()]
-        ]
+            [b"0" * 12, b"data", object()],
+        ],
     )
     def test_params_not_bytes(self, nonce, data, associated_data, backend):
         key = AESGCM.generate_key(128)
@@ -413,11 +421,17 @@
         with pytest.raises(TypeError):
             aesgcm.decrypt(nonce, data, associated_data)
 
-    def test_invalid_nonce_length(self, backend):
+    @pytest.mark.parametrize("length", [7, 129])
+    def test_invalid_nonce_length(self, length, backend):
+        if backend._fips_enabled:
+            # 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 = AESGCM.generate_key(128)
         aesgcm = AESGCM(key)
         with pytest.raises(ValueError):
-            aesgcm.encrypt(b"", b"hi", None)
+            aesgcm.encrypt(b"\x00" * length, b"hi", None)
 
     def test_bad_key(self, backend):
         with pytest.raises(TypeError):
diff --git a/tests/hazmat/primitives/test_aes.py b/tests/hazmat/primitives/test_aes.py
index 90a6b3b..f98ba6f 100644
--- a/tests/hazmat/primitives/test_aes.py
+++ b/tests/hazmat/primitives/test_aes.py
@@ -12,7 +12,8 @@
 from cryptography.hazmat.backends.interfaces import CipherBackend
 from cryptography.hazmat.primitives.ciphers import algorithms, base, modes
 
-from .utils import _load_all_params, generate_aead_test, generate_encrypt_test
+from .utils import _load_all_params, generate_encrypt_test
+from ...doubles import DummyMode
 from ...utils import load_nist_vectors
 
 
@@ -30,11 +31,15 @@
         # 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.
-        [x for x in _load_all_params(
-            os.path.join("ciphers", "AES", "XTS", "tweak-128hexstr"),
-            ["XTSGenAES128.rsp", "XTSGenAES256.rsp"],
-            load_nist_vectors
-        ) if int(x["dataunitlen"]) / 8.0 == int(x["dataunitlen"]) // 8]
+        [
+            x
+            for x in _load_all_params(
+                os.path.join("ciphers", "AES", "XTS", "tweak-128hexstr"),
+                ["XTSGenAES128.rsp", "XTSGenAES256.rsp"],
+                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"])
@@ -58,7 +63,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestAESModeCBC(object):
-    test_CBC = generate_encrypt_test(
+    test_cbc = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "AES", "CBC"),
         [
@@ -91,7 +96,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestAESModeECB(object):
-    test_ECB = generate_encrypt_test(
+    test_ecb = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "AES", "ECB"),
         [
@@ -124,7 +129,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestAESModeOFB(object):
-    test_OFB = generate_encrypt_test(
+    test_ofb = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "AES", "OFB"),
         [
@@ -157,7 +162,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestAESModeCFB(object):
-    test_CFB = generate_encrypt_test(
+    test_cfb = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "AES", "CFB"),
         [
@@ -190,7 +195,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestAESModeCFB8(object):
-    test_CFB8 = generate_encrypt_test(
+    test_cfb8 = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "AES", "CFB"),
         [
@@ -223,7 +228,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestAESModeCTR(object):
-    test_CTR = generate_encrypt_test(
+    test_ctr = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "AES", "CTR"),
         ["aes-128-ctr.txt", "aes-192-ctr.txt", "aes-256-ctr.txt"],
@@ -232,249 +237,6 @@
     )
 
 
-@pytest.mark.supported(
-    only_if=lambda backend: backend.cipher_supported(
-        algorithms.AES(b"\x00" * 16), modes.GCM(b"\x00" * 12)
-    ),
-    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,
-        os.path.join("ciphers", "AES", "GCM"),
-        [
-            "gcmDecrypt128.rsp",
-            "gcmDecrypt192.rsp",
-            "gcmDecrypt256.rsp",
-            "gcmEncryptExtIV128.rsp",
-            "gcmEncryptExtIV192.rsp",
-            "gcmEncryptExtIV256.rsp",
-        ],
-        algorithms.AES,
-        modes.GCM,
-    )
-
-    def test_gcm_tag_with_only_aad(self, backend):
-        key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3")
-        iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d")
-        aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193")
-        tag = binascii.unhexlify(b"0f247e7f9c2505de374006738018493b")
-
-        cipher = base.Cipher(
-            algorithms.AES(key),
-            modes.GCM(iv),
-            backend=backend
-        )
-        encryptor = cipher.encryptor()
-        encryptor.authenticate_additional_data(aad)
-        encryptor.finalize()
-        assert encryptor.tag == tag
-
-    def test_gcm_ciphertext_with_no_aad(self, backend):
-        key = binascii.unhexlify(b"e98b72a9881a84ca6b76e0f43e68647a")
-        iv = binascii.unhexlify(b"8b23299fde174053f3d652ba")
-        ct = binascii.unhexlify(b"5a3c1cf1985dbb8bed818036fdd5ab42")
-        tag = binascii.unhexlify(b"23c7ab0f952b7091cd324835043b5eb5")
-        pt = binascii.unhexlify(b"28286a321293253c3e0aa2704a278032")
-
-        cipher = base.Cipher(
-            algorithms.AES(key),
-            modes.GCM(iv),
-            backend=backend
-        )
-        encryptor = cipher.encryptor()
-        computed_ct = encryptor.update(pt) + encryptor.finalize()
-        assert computed_ct == ct
-        assert encryptor.tag == tag
-
-    def test_gcm_ciphertext_limit(self, backend):
-        encryptor = base.Cipher(
-            algorithms.AES(b"\x00" * 16),
-            modes.GCM(b"\x01" * 16),
-            backend=backend
-        ).encryptor()
-        encryptor._bytes_processed = modes.GCM._MAX_ENCRYPTED_BYTES - 16
-        encryptor.update(b"0" * 16)
-        assert (
-            encryptor._bytes_processed == modes.GCM._MAX_ENCRYPTED_BYTES
-        )
-        with pytest.raises(ValueError):
-            encryptor.update(b"0")
-
-    def test_gcm_aad_limit(self, backend):
-        encryptor = base.Cipher(
-            algorithms.AES(b"\x00" * 16),
-            modes.GCM(b"\x01" * 16),
-            backend=backend
-        ).encryptor()
-        encryptor._aad_bytes_processed = modes.GCM._MAX_AAD_BYTES - 16
-        encryptor.authenticate_additional_data(b"0" * 16)
-        assert encryptor._aad_bytes_processed == modes.GCM._MAX_AAD_BYTES
-        with pytest.raises(ValueError):
-            encryptor.authenticate_additional_data(b"0")
-
-    def test_gcm_ciphertext_increments(self, backend):
-        encryptor = base.Cipher(
-            algorithms.AES(b"\x00" * 16),
-            modes.GCM(b"\x01" * 16),
-            backend=backend
-        ).encryptor()
-        encryptor.update(b"0" * 8)
-        assert encryptor._bytes_processed == 8
-        encryptor.update(b"0" * 7)
-        assert encryptor._bytes_processed == 15
-        encryptor.update(b"0" * 18)
-        assert encryptor._bytes_processed == 33
-
-    def test_gcm_aad_increments(self, backend):
-        encryptor = base.Cipher(
-            algorithms.AES(b"\x00" * 16),
-            modes.GCM(b"\x01" * 16),
-            backend=backend
-        ).encryptor()
-        encryptor.authenticate_additional_data(b"0" * 8)
-        assert encryptor._aad_bytes_processed == 8
-        encryptor.authenticate_additional_data(b"0" * 18)
-        assert encryptor._aad_bytes_processed == 26
-
-    def test_gcm_tag_decrypt_none(self, backend):
-        key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3")
-        iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d")
-        aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193")
-
-        encryptor = base.Cipher(
-            algorithms.AES(key),
-            modes.GCM(iv),
-            backend=backend
-        ).encryptor()
-        encryptor.authenticate_additional_data(aad)
-        encryptor.finalize()
-
-        if (
-            backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and
-            not backend._lib.CRYPTOGRAPHY_IS_LIBRESSL
-        ):
-            with pytest.raises(NotImplementedError):
-                decryptor = base.Cipher(
-                    algorithms.AES(key),
-                    modes.GCM(iv),
-                    backend=backend
-                ).decryptor()
-        else:
-            decryptor = base.Cipher(
-                algorithms.AES(key),
-                modes.GCM(iv),
-                backend=backend
-            ).decryptor()
-            decryptor.authenticate_additional_data(aad)
-            with pytest.raises(ValueError):
-                decryptor.finalize()
-
-    def test_gcm_tag_decrypt_mode(self, backend):
-        key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3")
-        iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d")
-        aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193")
-
-        encryptor = base.Cipher(
-            algorithms.AES(key),
-            modes.GCM(iv),
-            backend=backend
-        ).encryptor()
-        encryptor.authenticate_additional_data(aad)
-        encryptor.finalize()
-        tag = encryptor.tag
-
-        decryptor = base.Cipher(
-            algorithms.AES(key),
-            modes.GCM(iv, tag),
-            backend=backend
-        ).decryptor()
-        decryptor.authenticate_additional_data(aad)
-        decryptor.finalize()
-
-    def test_gcm_tag_decrypt_finalize(self, backend):
-        key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3")
-        iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d")
-        aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193")
-
-        encryptor = base.Cipher(
-            algorithms.AES(key),
-            modes.GCM(iv),
-            backend=backend
-        ).encryptor()
-        encryptor.authenticate_additional_data(aad)
-        encryptor.finalize()
-        tag = encryptor.tag
-
-        if (
-            backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and
-            not backend._lib.CRYPTOGRAPHY_IS_LIBRESSL
-        ):
-            with pytest.raises(NotImplementedError):
-                decryptor = base.Cipher(
-                    algorithms.AES(key),
-                    modes.GCM(iv),
-                    backend=backend
-                ).decryptor()
-            decryptor = base.Cipher(
-                algorithms.AES(key),
-                modes.GCM(iv, tag=encryptor.tag),
-                backend=backend
-            ).decryptor()
-        else:
-            decryptor = base.Cipher(
-                algorithms.AES(key),
-                modes.GCM(iv),
-                backend=backend
-            ).decryptor()
-        decryptor.authenticate_additional_data(aad)
-
-        if (
-            backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and
-            not backend._lib.CRYPTOGRAPHY_IS_LIBRESSL
-        ):
-            with pytest.raises(NotImplementedError):
-                decryptor.finalize_with_tag(tag)
-            decryptor.finalize()
-        else:
-            decryptor.finalize_with_tag(tag)
-
-    @pytest.mark.supported(
-        only_if=lambda backend: (
-            not backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 or
-            backend._lib.CRYPTOGRAPHY_IS_LIBRESSL
-        ),
-        skip_message="Not supported on OpenSSL 1.0.1",
-    )
-    def test_gcm_tag_decrypt_finalize_tag_length(self, 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")
-
-    def test_buffer_protocol(self, backend):
-        data = bytearray(b"helloworld")
-        enc = base.Cipher(
-            algorithms.AES(bytearray(b"\x00" * 16)),
-            modes.GCM(bytearray(b"\x00" * 12)),
-            backend
-        ).encryptor()
-        enc.authenticate_additional_data(bytearray(b"foo"))
-        ct = enc.update(data) + enc.finalize()
-        dec = base.Cipher(
-            algorithms.AES(bytearray(b"\x00" * 16)),
-            modes.GCM(bytearray(b"\x00" * 12), enc.tag),
-            backend
-        ).decryptor()
-        dec.authenticate_additional_data(bytearray(b"foo"))
-        pt = dec.update(ct) + dec.finalize()
-        assert pt == data
-
-
 @pytest.mark.parametrize(
     "mode",
     [
@@ -484,14 +246,17 @@
         modes.CFB(bytearray(b"\x00" * 16)),
         modes.CFB8(bytearray(b"\x00" * 16)),
         modes.XTS(bytearray(b"\x00" * 16)),
-    ]
+        # Add a dummy mode for coverage of the cipher_supported check.
+        DummyMode(),
+    ],
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 def test_buffer_protocol_alternate_modes(mode, backend):
     data = bytearray(b"sixteen_byte_msg")
-    cipher = base.Cipher(
-        algorithms.AES(bytearray(b"\x00" * 32)), mode, backend
-    )
+    key = algorithms.AES(bytearray(os.urandom(32)))
+    if not backend.cipher_supported(key, mode):
+        pytest.skip("AES in {} mode not supported".format(mode.name))
+    cipher = base.Cipher(key, mode, backend)
     enc = cipher.encryptor()
     ct = enc.update(data) + enc.finalize()
     dec = cipher.decryptor()
diff --git a/tests/hazmat/primitives/test_aes_gcm.py b/tests/hazmat/primitives/test_aes_gcm.py
new file mode 100644
index 0000000..8b71d12
--- /dev/null
+++ b/tests/hazmat/primitives/test_aes_gcm.py
@@ -0,0 +1,219 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+import os
+
+import pytest
+
+from cryptography.hazmat.backends.interfaces import CipherBackend
+from cryptography.hazmat.primitives.ciphers import algorithms, base, modes
+
+from .utils import generate_aead_test
+from ...utils import load_nist_vectors
+
+
+@pytest.mark.supported(
+    only_if=lambda backend: backend.cipher_supported(
+        algorithms.AES(b"\x00" * 16), modes.GCM(b"\x00" * 12)
+    ),
+    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,
+        os.path.join("ciphers", "AES", "GCM"),
+        [
+            "gcmDecrypt128.rsp",
+            "gcmDecrypt192.rsp",
+            "gcmDecrypt256.rsp",
+            "gcmEncryptExtIV128.rsp",
+            "gcmEncryptExtIV192.rsp",
+            "gcmEncryptExtIV256.rsp",
+        ],
+        algorithms.AES,
+        modes.GCM,
+    )
+
+    def test_gcm_tag_with_only_aad(self, backend):
+        key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3")
+        iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d")
+        aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193")
+        tag = binascii.unhexlify(b"0f247e7f9c2505de374006738018493b")
+
+        cipher = base.Cipher(
+            algorithms.AES(key), modes.GCM(iv), backend=backend
+        )
+        encryptor = cipher.encryptor()
+        encryptor.authenticate_additional_data(aad)
+        encryptor.finalize()
+        assert encryptor.tag == tag
+
+    def test_gcm_ciphertext_with_no_aad(self, backend):
+        key = binascii.unhexlify(b"e98b72a9881a84ca6b76e0f43e68647a")
+        iv = binascii.unhexlify(b"8b23299fde174053f3d652ba")
+        ct = binascii.unhexlify(b"5a3c1cf1985dbb8bed818036fdd5ab42")
+        tag = binascii.unhexlify(b"23c7ab0f952b7091cd324835043b5eb5")
+        pt = binascii.unhexlify(b"28286a321293253c3e0aa2704a278032")
+
+        cipher = base.Cipher(
+            algorithms.AES(key), modes.GCM(iv), backend=backend
+        )
+        encryptor = cipher.encryptor()
+        computed_ct = encryptor.update(pt) + encryptor.finalize()
+        assert computed_ct == ct
+        assert encryptor.tag == tag
+
+    def test_gcm_ciphertext_limit(self, backend):
+        encryptor = base.Cipher(
+            algorithms.AES(b"\x00" * 16),
+            modes.GCM(b"\x01" * 16),
+            backend=backend,
+        ).encryptor()
+        encryptor._bytes_processed = modes.GCM._MAX_ENCRYPTED_BYTES - 16
+        encryptor.update(b"0" * 16)
+        assert encryptor._bytes_processed == modes.GCM._MAX_ENCRYPTED_BYTES
+        with pytest.raises(ValueError):
+            encryptor.update(b"0")
+
+    def test_gcm_aad_limit(self, backend):
+        encryptor = base.Cipher(
+            algorithms.AES(b"\x00" * 16),
+            modes.GCM(b"\x01" * 16),
+            backend=backend,
+        ).encryptor()
+        encryptor._aad_bytes_processed = modes.GCM._MAX_AAD_BYTES - 16
+        encryptor.authenticate_additional_data(b"0" * 16)
+        assert encryptor._aad_bytes_processed == modes.GCM._MAX_AAD_BYTES
+        with pytest.raises(ValueError):
+            encryptor.authenticate_additional_data(b"0")
+
+    def test_gcm_ciphertext_increments(self, backend):
+        encryptor = base.Cipher(
+            algorithms.AES(b"\x00" * 16),
+            modes.GCM(b"\x01" * 16),
+            backend=backend,
+        ).encryptor()
+        encryptor.update(b"0" * 8)
+        assert encryptor._bytes_processed == 8
+        encryptor.update(b"0" * 7)
+        assert encryptor._bytes_processed == 15
+        encryptor.update(b"0" * 18)
+        assert encryptor._bytes_processed == 33
+
+    def test_gcm_aad_increments(self, backend):
+        encryptor = base.Cipher(
+            algorithms.AES(b"\x00" * 16),
+            modes.GCM(b"\x01" * 16),
+            backend=backend,
+        ).encryptor()
+        encryptor.authenticate_additional_data(b"0" * 8)
+        assert encryptor._aad_bytes_processed == 8
+        encryptor.authenticate_additional_data(b"0" * 18)
+        assert encryptor._aad_bytes_processed == 26
+
+    def test_gcm_tag_decrypt_none(self, backend):
+        key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3")
+        iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d")
+        aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193")
+
+        encryptor = base.Cipher(
+            algorithms.AES(key), modes.GCM(iv), backend=backend
+        ).encryptor()
+        encryptor.authenticate_additional_data(aad)
+        encryptor.finalize()
+
+        decryptor = base.Cipher(
+            algorithms.AES(key), modes.GCM(iv), backend=backend
+        ).decryptor()
+        decryptor.authenticate_additional_data(aad)
+        with pytest.raises(ValueError):
+            decryptor.finalize()
+
+    def test_gcm_tag_decrypt_mode(self, backend):
+        key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3")
+        iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d")
+        aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193")
+
+        encryptor = base.Cipher(
+            algorithms.AES(key), modes.GCM(iv), backend=backend
+        ).encryptor()
+        encryptor.authenticate_additional_data(aad)
+        encryptor.finalize()
+        tag = encryptor.tag
+
+        decryptor = base.Cipher(
+            algorithms.AES(key), modes.GCM(iv, tag), backend=backend
+        ).decryptor()
+        decryptor.authenticate_additional_data(aad)
+        decryptor.finalize()
+
+    def test_gcm_tag_decrypt_finalize(self, backend):
+        key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3")
+        iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d")
+        aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193")
+
+        encryptor = base.Cipher(
+            algorithms.AES(key), modes.GCM(iv), backend=backend
+        ).encryptor()
+        encryptor.authenticate_additional_data(aad)
+        encryptor.finalize()
+        tag = encryptor.tag
+
+        decryptor = base.Cipher(
+            algorithms.AES(key), modes.GCM(iv), backend=backend
+        ).decryptor()
+        decryptor.authenticate_additional_data(aad)
+
+        decryptor.finalize_with_tag(tag)
+
+    def test_gcm_tag_decrypt_finalize_tag_length(self, 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")
+
+    def test_buffer_protocol(self, backend):
+        data = bytearray(b"helloworld")
+        enc = base.Cipher(
+            algorithms.AES(bytearray(b"\x00" * 16)),
+            modes.GCM(bytearray(b"\x00" * 12)),
+            backend,
+        ).encryptor()
+        enc.authenticate_additional_data(bytearray(b"foo"))
+        ct = enc.update(data) + enc.finalize()
+        dec = base.Cipher(
+            algorithms.AES(bytearray(b"\x00" * 16)),
+            modes.GCM(bytearray(b"\x00" * 12), enc.tag),
+            backend,
+        ).decryptor()
+        dec.authenticate_additional_data(bytearray(b"foo"))
+        pt = dec.update(ct) + dec.finalize()
+        assert pt == data
+
+    @pytest.mark.parametrize("size", [8, 128])
+    def test_gcm_min_max_iv(self, size, backend):
+        if backend._fips_enabled:
+            # 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 = os.urandom(16)
+        iv = b"\x00" * size
+
+        payload = b"data"
+        encryptor = base.Cipher(algorithms.AES(key), modes.GCM(iv)).encryptor()
+        ct = encryptor.update(payload)
+        encryptor.finalize()
+        tag = encryptor.tag
+
+        decryptor = base.Cipher(algorithms.AES(key), modes.GCM(iv)).decryptor()
+        pt = decryptor.update(ct)
+
+        decryptor.finalize_with_tag(tag)
+        assert pt == payload
diff --git a/tests/hazmat/primitives/test_arc4.py b/tests/hazmat/primitives/test_arc4.py
index 1a17344..de20b70 100644
--- a/tests/hazmat/primitives/test_arc4.py
+++ b/tests/hazmat/primitives/test_arc4.py
@@ -35,7 +35,7 @@
             "rfc-6229-128.txt",
             "rfc-6229-192.txt",
             "rfc-6229-256.txt",
-            "arc4.txt"
+            "arc4.txt",
         ],
         lambda key, **kwargs: algorithms.ARC4(binascii.unhexlify(key)),
     )
diff --git a/tests/hazmat/primitives/test_asym_utils.py b/tests/hazmat/primitives/test_asym_utils.py
index fc9e9fd..70bff01 100644
--- a/tests/hazmat/primitives/test_asym_utils.py
+++ b/tests/hazmat/primitives/test_asym_utils.py
@@ -7,19 +7,10 @@
 import pytest
 
 from cryptography.hazmat.primitives.asymmetric.utils import (
-    Prehashed, decode_dss_signature, decode_rfc6979_signature,
-    encode_dss_signature, encode_rfc6979_signature,
+    Prehashed,
+    decode_dss_signature,
+    encode_dss_signature,
 )
-from cryptography.utils import CryptographyDeprecationWarning
-
-
-def test_deprecated_rfc6979_signature():
-    with pytest.warns(CryptographyDeprecationWarning):
-        sig = encode_rfc6979_signature(1, 1)
-    assert sig == b"0\x06\x02\x01\x01\x02\x01\x01"
-    with pytest.warns(CryptographyDeprecationWarning):
-        decoded = decode_rfc6979_signature(sig)
-    assert decoded == (1, 1)
 
 
 def test_dss_signature():
@@ -29,11 +20,11 @@
 
     r_s1 = (
         1037234182290683143945502320610861668562885151617,
-        559776156650501990899426031439030258256861634312
+        559776156650501990899426031439030258256861634312,
     )
     sig2 = encode_dss_signature(*r_s1)
     assert sig2 == (
-        b'0-\x02\x15\x00\xb5\xaf0xg\xfb\x8bT9\x00\x13\xccg\x02\r\xdf\x1f,\x0b'
+        b"0-\x02\x15\x00\xb5\xaf0xg\xfb\x8bT9\x00\x13\xccg\x02\r\xdf\x1f,\x0b"
         b'\x81\x02\x14b\r;"\xabP1D\x0c>5\xea\xb6\xf4\x81)\x8f\x9e\x9f\x08'
     )
     assert decode_dss_signature(sig2) == r_s1
@@ -42,10 +33,6 @@
     assert sig3 == b"0\x06\x02\x01\x00\x02\x01\x00"
     assert decode_dss_signature(sig3) == (0, 0)
 
-    sig4 = encode_dss_signature(-1, 0)
-    assert sig4 == b"0\x06\x02\x01\xFF\x02\x01\x00"
-    assert decode_dss_signature(sig4) == (-1, 0)
-
 
 def test_encode_dss_non_integer():
     with pytest.raises(ValueError):
@@ -64,6 +51,11 @@
         encode_dss_signature("hello", "world")
 
 
+def test_encode_dss_negative():
+    with pytest.raises(ValueError):
+        encode_dss_signature(-1, 0)
+
+
 def test_decode_dss_trailing_bytes():
     with pytest.raises(ValueError):
         decode_dss_signature(b"0\x06\x02\x01\x01\x02\x01\x01\x00\x00\x00")
diff --git a/tests/hazmat/primitives/test_block.py b/tests/hazmat/primitives/test_block.py
index 37158f1..5931993 100644
--- a/tests/hazmat/primitives/test_block.py
+++ b/tests/hazmat/primitives/test_block.py
@@ -8,16 +8,18 @@
 
 import pytest
 
-from cryptography.exceptions import (
-    AlreadyFinalized, _Reasons
-)
+from cryptography.exceptions import AlreadyFinalized, _Reasons
 from cryptography.hazmat.backends.interfaces import CipherBackend
 from cryptography.hazmat.primitives.ciphers import (
-    Cipher, algorithms, base, modes
+    Cipher,
+    algorithms,
+    base,
+    modes,
 )
 
 from .utils import (
-    generate_aead_exception_test, generate_aead_tag_exception_test
+    generate_aead_exception_test,
+    generate_aead_tag_exception_test,
 )
 from ...doubles import DummyCipherAlgorithm, DummyMode
 from ...utils import raises_unsupported_algorithm
@@ -29,7 +31,7 @@
         cipher = Cipher(
             algorithms.AES(binascii.unhexlify(b"0" * 32)),
             modes.CBC(binascii.unhexlify(b"0" * 32)),
-            backend
+            backend,
         )
         assert isinstance(cipher.encryptor(), base.CipherContext)
 
@@ -37,7 +39,7 @@
         cipher = Cipher(
             algorithms.AES(binascii.unhexlify(b"0" * 32)),
             modes.CBC(binascii.unhexlify(b"0" * 32)),
-            backend
+            backend,
         )
         assert isinstance(cipher.decryptor(), base.CipherContext)
 
@@ -53,7 +55,7 @@
         cipher = Cipher(
             algorithms.AES(binascii.unhexlify(b"0" * 32)),
             modes.CBC(binascii.unhexlify(b"0" * 32)),
-            backend
+            backend,
         )
         encryptor = cipher.encryptor()
         encryptor.update(b"a" * 16)
@@ -74,7 +76,7 @@
         cipher = Cipher(
             algorithms.AES(binascii.unhexlify(b"0" * 32)),
             modes.CBC(binascii.unhexlify(b"0" * 32)),
-            backend
+            backend,
         )
         encryptor = cipher.encryptor()
         encryptor.update(b"a" * 16)
@@ -85,9 +87,7 @@
 
     def test_unaligned_block_encryption(self, backend):
         cipher = Cipher(
-            algorithms.AES(binascii.unhexlify(b"0" * 32)),
-            modes.ECB(),
-            backend
+            algorithms.AES(binascii.unhexlify(b"0" * 32)), modes.ECB(), backend
         )
         encryptor = cipher.encryptor()
         ct = encryptor.update(b"a" * 15)
@@ -105,9 +105,7 @@
 
     @pytest.mark.parametrize("mode", [DummyMode(), None])
     def test_nonexistent_cipher(self, backend, mode):
-        cipher = Cipher(
-            DummyCipherAlgorithm(), mode, backend
-        )
+        cipher = Cipher(DummyCipherAlgorithm(), mode, backend)
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER):
             cipher.encryptor()
 
@@ -116,9 +114,7 @@
 
     def test_incorrectly_padded(self, backend):
         cipher = Cipher(
-            algorithms.AES(b"\x00" * 16),
-            modes.CBC(b"\x00" * 16),
-            backend
+            algorithms.AES(b"\x00" * 16), modes.CBC(b"\x00" * 16), backend
         )
         encryptor = cipher.encryptor()
         encryptor.update(b"1")
diff --git a/tests/hazmat/primitives/test_blowfish.py b/tests/hazmat/primitives/test_blowfish.py
index 0c38b98..5f7480e 100644
--- a/tests/hazmat/primitives/test_blowfish.py
+++ b/tests/hazmat/primitives/test_blowfish.py
@@ -24,7 +24,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestBlowfishModeECB(object):
-    test_ECB = generate_encrypt_test(
+    test_ecb = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "Blowfish"),
         ["bf-ecb.txt"],
@@ -41,7 +41,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestBlowfishModeCBC(object):
-    test_CBC = generate_encrypt_test(
+    test_cbc = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "Blowfish"),
         ["bf-cbc.txt"],
@@ -58,7 +58,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestBlowfishModeOFB(object):
-    test_OFB = generate_encrypt_test(
+    test_ofb = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "Blowfish"),
         ["bf-ofb.txt"],
@@ -75,7 +75,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestBlowfishModeCFB(object):
-    test_CFB = generate_encrypt_test(
+    test_cfb = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "Blowfish"),
         ["bf-cfb.txt"],
diff --git a/tests/hazmat/primitives/test_camellia.py b/tests/hazmat/primitives/test_camellia.py
index 87fcfe3..b752345 100644
--- a/tests/hazmat/primitives/test_camellia.py
+++ b/tests/hazmat/primitives/test_camellia.py
@@ -13,9 +13,7 @@
 from cryptography.hazmat.primitives.ciphers import algorithms, modes
 
 from .utils import generate_encrypt_test
-from ...utils import (
-    load_cryptrec_vectors, load_nist_vectors
-)
+from ...utils import load_cryptrec_vectors, load_nist_vectors
 
 
 @pytest.mark.supported(
@@ -26,13 +24,13 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestCamelliaModeECB(object):
-    test_ECB = generate_encrypt_test(
+    test_ecb = generate_encrypt_test(
         load_cryptrec_vectors,
         os.path.join("ciphers", "Camellia"),
         [
             "camellia-128-ecb.txt",
             "camellia-192-ecb.txt",
-            "camellia-256-ecb.txt"
+            "camellia-256-ecb.txt",
         ],
         lambda key, **kwargs: algorithms.Camellia(binascii.unhexlify(key)),
         lambda **kwargs: modes.ECB(),
@@ -47,7 +45,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestCamelliaModeCBC(object):
-    test_CBC = generate_encrypt_test(
+    test_cbc = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "Camellia"),
         ["camellia-cbc.txt"],
@@ -64,7 +62,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestCamelliaModeOFB(object):
-    test_OFB = generate_encrypt_test(
+    test_ofb = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "Camellia"),
         ["camellia-ofb.txt"],
@@ -81,7 +79,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestCamelliaModeCFB(object):
-    test_CFB = generate_encrypt_test(
+    test_cfb = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "Camellia"),
         ["camellia-cfb.txt"],
diff --git a/tests/hazmat/primitives/test_cast5.py b/tests/hazmat/primitives/test_cast5.py
index ec51659..eff5d25 100644
--- a/tests/hazmat/primitives/test_cast5.py
+++ b/tests/hazmat/primitives/test_cast5.py
@@ -24,7 +24,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestCAST5ModeECB(object):
-    test_ECB = generate_encrypt_test(
+    test_ecb = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "CAST5"),
         ["cast5-ecb.txt"],
@@ -41,12 +41,12 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestCAST5ModeCBC(object):
-    test_CBC = generate_encrypt_test(
+    test_cbc = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "CAST5"),
         ["cast5-cbc.txt"],
         lambda key, **kwargs: algorithms.CAST5(binascii.unhexlify((key))),
-        lambda iv, **kwargs: modes.CBC(binascii.unhexlify(iv))
+        lambda iv, **kwargs: modes.CBC(binascii.unhexlify(iv)),
     )
 
 
@@ -58,12 +58,12 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestCAST5ModeOFB(object):
-    test_OFB = generate_encrypt_test(
+    test_ofb = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "CAST5"),
         ["cast5-ofb.txt"],
         lambda key, **kwargs: algorithms.CAST5(binascii.unhexlify((key))),
-        lambda iv, **kwargs: modes.OFB(binascii.unhexlify(iv))
+        lambda iv, **kwargs: modes.OFB(binascii.unhexlify(iv)),
     )
 
 
@@ -75,10 +75,10 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestCAST5ModeCFB(object):
-    test_CFB = generate_encrypt_test(
+    test_cfb = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "CAST5"),
         ["cast5-cfb.txt"],
         lambda key, **kwargs: algorithms.CAST5(binascii.unhexlify((key))),
-        lambda iv, **kwargs: modes.CFB(binascii.unhexlify(iv))
+        lambda iv, **kwargs: modes.CFB(binascii.unhexlify(iv)),
     )
diff --git a/tests/hazmat/primitives/test_chacha20.py b/tests/hazmat/primitives/test_chacha20.py
index 7c475c0..cb12d3c 100644
--- a/tests/hazmat/primitives/test_chacha20.py
+++ b/tests/hazmat/primitives/test_chacha20.py
@@ -30,8 +30,8 @@
         _load_all_params(
             os.path.join("ciphers", "ChaCha20"),
             ["rfc7539.txt"],
-            load_nist_vectors
-        )
+            load_nist_vectors,
+        ),
     )
     def test_vectors(self, vector, backend):
         key = binascii.unhexlify(vector["key"])
@@ -47,9 +47,7 @@
     def test_buffer_protocol(self, backend):
         key = bytearray(os.urandom(32))
         nonce = bytearray(os.urandom(16))
-        cipher = Cipher(
-            algorithms.ChaCha20(key, nonce), None, backend
-        )
+        cipher = Cipher(algorithms.ChaCha20(key, nonce), None, backend)
         enc = cipher.encryptor()
         ct = enc.update(bytearray(b"hello")) + enc.finalize()
         dec = cipher.decryptor()
diff --git a/tests/hazmat/primitives/test_ciphers.py b/tests/hazmat/primitives/test_ciphers.py
index f29ba9a..a9219fe 100644
--- a/tests/hazmat/primitives/test_ciphers.py
+++ b/tests/hazmat/primitives/test_ciphers.py
@@ -14,20 +14,28 @@
 from cryptography.hazmat.primitives import ciphers
 from cryptography.hazmat.primitives.ciphers import modes
 from cryptography.hazmat.primitives.ciphers.algorithms import (
-    AES, ARC4, Blowfish, CAST5, Camellia, IDEA, SEED, TripleDES
+    AES,
+    ARC4,
+    Blowfish,
+    CAST5,
+    Camellia,
+    IDEA,
+    SEED,
+    TripleDES,
 )
 
 from ...utils import (
-    load_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm
+    load_nist_vectors,
+    load_vectors_from_file,
+    raises_unsupported_algorithm,
 )
 
 
 class TestAES(object):
-    @pytest.mark.parametrize(("key", "keysize"), [
-        (b"0" * 32, 128),
-        (b"0" * 48, 192),
-        (b"0" * 64, 256),
-    ])
+    @pytest.mark.parametrize(
+        ("key", "keysize"),
+        [(b"0" * 32, 128), (b"0" * 48, 192), (b"0" * 64, 256)],
+    )
     def test_key_size(self, key, keysize):
         cipher = AES(binascii.unhexlify(key))
         assert cipher.key_size == keysize
@@ -44,8 +52,7 @@
 class TestAESXTS(object):
     @pytest.mark.requires_backend_interface(interface=CipherBackend)
     @pytest.mark.parametrize(
-        "mode",
-        (modes.CBC, modes.CTR, modes.CFB, modes.CFB8, modes.OFB)
+        "mode", (modes.CBC, modes.CTR, modes.CFB, modes.CFB8, modes.OFB)
     )
     def test_invalid_key_size_with_mode(self, mode, backend):
         with pytest.raises(ValueError):
@@ -65,12 +72,18 @@
             ciphers.Cipher(AES(b"0" * 16), modes.XTS(b"0" * 16), backend)
 
 
+class TestGCM(object):
+    @pytest.mark.parametrize("size", [7, 129])
+    def test_gcm_min_max(self, size):
+        with pytest.raises(ValueError):
+            modes.GCM(b"0" * size)
+
+
 class TestCamellia(object):
-    @pytest.mark.parametrize(("key", "keysize"), [
-        (b"0" * 32, 128),
-        (b"0" * 48, 192),
-        (b"0" * 64, 256),
-    ])
+    @pytest.mark.parametrize(
+        ("key", "keysize"),
+        [(b"0" * 32, 128), (b"0" * 48, 192), (b"0" * 64, 256)],
+    )
     def test_key_size(self, key, keysize):
         cipher = Camellia(binascii.unhexlify(key))
         assert cipher.key_size == keysize
@@ -85,11 +98,7 @@
 
 
 class TestTripleDES(object):
-    @pytest.mark.parametrize("key", [
-        b"0" * 16,
-        b"0" * 32,
-        b"0" * 48,
-    ])
+    @pytest.mark.parametrize("key", [b"0" * 16, b"0" * 32, b"0" * 48])
     def test_key_size(self, key):
         cipher = TripleDES(binascii.unhexlify(key))
         assert cipher.key_size == 192
@@ -104,9 +113,10 @@
 
 
 class TestBlowfish(object):
-    @pytest.mark.parametrize(("key", "keysize"), [
-        (b"0" * (keysize // 4), keysize) for keysize in range(32, 449, 8)
-    ])
+    @pytest.mark.parametrize(
+        ("key", "keysize"),
+        [(b"0" * (keysize // 4), keysize) for keysize in range(32, 449, 8)],
+    )
     def test_key_size(self, key, keysize):
         cipher = Blowfish(binascii.unhexlify(key))
         assert cipher.key_size == keysize
@@ -121,9 +131,10 @@
 
 
 class TestCAST5(object):
-    @pytest.mark.parametrize(("key", "keysize"), [
-        (b"0" * (keysize // 4), keysize) for keysize in range(40, 129, 8)
-    ])
+    @pytest.mark.parametrize(
+        ("key", "keysize"),
+        [(b"0" * (keysize // 4), keysize) for keysize in range(40, 129, 8)],
+    )
     def test_key_size(self, key, keysize):
         cipher = CAST5(binascii.unhexlify(key))
         assert cipher.key_size == keysize
@@ -138,15 +149,18 @@
 
 
 class TestARC4(object):
-    @pytest.mark.parametrize(("key", "keysize"), [
-        (b"0" * 10, 40),
-        (b"0" * 14, 56),
-        (b"0" * 16, 64),
-        (b"0" * 20, 80),
-        (b"0" * 32, 128),
-        (b"0" * 48, 192),
-        (b"0" * 64, 256),
-    ])
+    @pytest.mark.parametrize(
+        ("key", "keysize"),
+        [
+            (b"0" * 10, 40),
+            (b"0" * 14, 56),
+            (b"0" * 16, 64),
+            (b"0" * 20, 80),
+            (b"0" * 32, 128),
+            (b"0" * 48, 192),
+            (b"0" * 64, 256),
+        ],
+    )
     def test_key_size(self, key, keysize):
         cipher = ARC4(binascii.unhexlify(key))
         assert cipher.key_size == keysize
@@ -207,8 +221,8 @@
         "params",
         load_vectors_from_file(
             os.path.join("ciphers", "AES", "ECB", "ECBGFSbox128.rsp"),
-            load_nist_vectors
-        )
+            load_nist_vectors,
+        ),
     )
     def test_update_into(self, params, backend):
         key = binascii.unhexlify(params["key"])
@@ -272,8 +286,8 @@
         "params",
         load_vectors_from_file(
             os.path.join("ciphers", "AES", "ECB", "ECBGFSbox128.rsp"),
-            load_nist_vectors
-        )
+            load_nist_vectors,
+        ),
     )
     def test_update_into_multiple_calls(self, params, backend):
         key = binascii.unhexlify(params["key"])
@@ -309,3 +323,29 @@
         buf = bytearray(5)
         with pytest.raises(ValueError):
             encryptor.update_into(b"testing", buf)
+
+    def test_update_into_auto_chunking(self, backend, monkeypatch):
+        key = b"\x00" * 16
+        c = ciphers.Cipher(AES(key), modes.ECB(), backend)
+        encryptor = c.encryptor()
+        # Lower max chunk size so we can test chunking
+        monkeypatch.setattr(encryptor._ctx, "_MAX_CHUNK_SIZE", 40)
+        buf = bytearray(527)
+        pt = b"abcdefghijklmnopqrstuvwxyz012345" * 16  # 512 bytes
+        processed = encryptor.update_into(pt, buf)
+        assert processed == 512
+        decryptor = c.decryptor()
+        # Change max chunk size to verify alternate boundaries don't matter
+        monkeypatch.setattr(decryptor._ctx, "_MAX_CHUNK_SIZE", 73)
+        decbuf = bytearray(527)
+        decprocessed = decryptor.update_into(buf[:processed], decbuf)
+        assert decbuf[:decprocessed] == pt
+
+    def test_max_chunk_size_fits_in_int32(self, backend):
+        # max chunk must fit in signed int32 or else a call large enough to
+        # cause chunking will result in the very OverflowError we want to
+        # avoid with chunking.
+        key = b"\x00" * 16
+        c = ciphers.Cipher(AES(key), modes.ECB(), backend)
+        encryptor = c.encryptor()
+        backend._ffi.new("int *", encryptor._ctx._MAX_CHUNK_SIZE)
diff --git a/tests/hazmat/primitives/test_cmac.py b/tests/hazmat/primitives/test_cmac.py
index e319396..e4a35df 100644
--- a/tests/hazmat/primitives/test_cmac.py
+++ b/tests/hazmat/primitives/test_cmac.py
@@ -9,32 +9,42 @@
 import pytest
 
 from cryptography.exceptions import (
-    AlreadyFinalized, InvalidSignature, _Reasons
+    AlreadyFinalized,
+    InvalidSignature,
+    _Reasons,
 )
 from cryptography.hazmat.backends.interfaces import CMACBackend
 from cryptography.hazmat.primitives.ciphers.algorithms import (
-    AES, ARC4, TripleDES
+    AES,
+    ARC4,
+    TripleDES,
 )
 from cryptography.hazmat.primitives.cmac import CMAC
 
 from ...utils import (
-    load_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm
+    load_nist_vectors,
+    load_vectors_from_file,
+    raises_unsupported_algorithm,
 )
 
 
 vectors_aes128 = load_vectors_from_file(
-    "CMAC/nist-800-38b-aes128.txt", load_nist_vectors)
+    "CMAC/nist-800-38b-aes128.txt", load_nist_vectors
+)
 
 vectors_aes192 = load_vectors_from_file(
-    "CMAC/nist-800-38b-aes192.txt", load_nist_vectors)
+    "CMAC/nist-800-38b-aes192.txt", load_nist_vectors
+)
 
 vectors_aes256 = load_vectors_from_file(
-    "CMAC/nist-800-38b-aes256.txt", load_nist_vectors)
+    "CMAC/nist-800-38b-aes256.txt", load_nist_vectors
+)
 
 vectors_aes = vectors_aes128 + vectors_aes192 + vectors_aes256
 
 vectors_3des = load_vectors_from_file(
-    "CMAC/nist-800-38b-3des.txt", load_nist_vectors)
+    "CMAC/nist-800-38b-3des.txt", load_nist_vectors
+)
 
 fake_key = b"\x00" * 16
 
@@ -43,8 +53,9 @@
 class TestCMAC(object):
     @pytest.mark.supported(
         only_if=lambda backend: backend.cmac_algorithm_supported(
-            AES(fake_key)),
-        skip_message="Does not support CMAC."
+            AES(fake_key)
+        ),
+        skip_message="Does not support CMAC.",
     )
     @pytest.mark.parametrize("params", vectors_aes)
     def test_aes_generate(self, backend, params):
@@ -58,8 +69,9 @@
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.cmac_algorithm_supported(
-            AES(fake_key)),
-        skip_message="Does not support CMAC."
+            AES(fake_key)
+        ),
+        skip_message="Does not support CMAC.",
     )
     @pytest.mark.parametrize("params", vectors_aes)
     def test_aes_verify(self, backend, params):
@@ -73,8 +85,9 @@
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.cmac_algorithm_supported(
-            TripleDES(fake_key)),
-        skip_message="Does not support CMAC."
+            TripleDES(fake_key)
+        ),
+        skip_message="Does not support CMAC.",
     )
     @pytest.mark.parametrize("params", vectors_3des)
     def test_3des_generate(self, backend, params):
@@ -93,8 +106,9 @@
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.cmac_algorithm_supported(
-            TripleDES(fake_key)),
-        skip_message="Does not support CMAC."
+            TripleDES(fake_key)
+        ),
+        skip_message="Does not support CMAC.",
     )
     @pytest.mark.parametrize("params", vectors_3des)
     def test_3des_verify(self, backend, params):
@@ -113,8 +127,9 @@
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.cmac_algorithm_supported(
-            AES(fake_key)),
-        skip_message="Does not support CMAC."
+            AES(fake_key)
+        ),
+        skip_message="Does not support CMAC.",
     )
     def test_invalid_verify(self, backend):
         key = b"2b7e151628aed2a6abf7158809cf4f3c"
@@ -125,9 +140,8 @@
             cmac.verify(b"foobar")
 
     @pytest.mark.supported(
-        only_if=lambda backend: backend.cipher_supported(
-            ARC4(fake_key), None),
-        skip_message="Does not support CMAC."
+        only_if=lambda backend: backend.cipher_supported(ARC4(fake_key), None),
+        skip_message="Does not support CMAC.",
     )
     def test_invalid_algorithm(self, backend):
         key = b"0102030405"
@@ -136,8 +150,9 @@
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.cmac_algorithm_supported(
-            AES(fake_key)),
-        skip_message="Does not support CMAC."
+            AES(fake_key)
+        ),
+        skip_message="Does not support CMAC.",
     )
     def test_raises_after_finalize(self, backend):
         key = b"2b7e151628aed2a6abf7158809cf4f3c"
@@ -158,23 +173,25 @@
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.cmac_algorithm_supported(
-            AES(fake_key)),
-        skip_message="Does not support CMAC."
+            AES(fake_key)
+        ),
+        skip_message="Does not support CMAC.",
     )
     def test_verify_reject_unicode(self, backend):
         key = b"2b7e151628aed2a6abf7158809cf4f3c"
         cmac = CMAC(AES(key), backend)
 
         with pytest.raises(TypeError):
-            cmac.update(u'')
+            cmac.update(u"")
 
         with pytest.raises(TypeError):
-            cmac.verify(u'')
+            cmac.verify(u"")
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.cmac_algorithm_supported(
-            AES(fake_key)),
-        skip_message="Does not support CMAC."
+            AES(fake_key)
+        ),
+        skip_message="Does not support CMAC.",
     )
     def test_copy_with_backend(self, backend):
         key = b"2b7e151628aed2a6abf7158809cf4f3c"
@@ -185,8 +202,9 @@
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.cmac_algorithm_supported(
-            AES(fake_key)),
-        skip_message="Does not support CMAC."
+            AES(fake_key)
+        ),
+        skip_message="Does not support CMAC.",
     )
     def test_buffer_protocol(self, backend):
         key = bytearray(b"2b7e151628aed2a6abf7158809cf4f3c")
diff --git a/tests/hazmat/primitives/test_concatkdf.py b/tests/hazmat/primitives/test_concatkdf.py
index 6731509..271e011 100644
--- a/tests/hazmat/primitives/test_concatkdf.py
+++ b/tests/hazmat/primitives/test_concatkdf.py
@@ -8,9 +8,7 @@
 
 import pytest
 
-from cryptography.exceptions import (
-    AlreadyFinalized, InvalidKey, _Reasons
-)
+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
@@ -102,38 +100,26 @@
     def test_unicode_typeerror(self, backend):
         with pytest.raises(TypeError):
             ConcatKDFHash(
-                hashes.SHA256(),
-                16,
-                otherinfo=u"foo",
-                backend=backend
+                hashes.SHA256(), 16, otherinfo=u"foo", backend=backend
             )
 
         with pytest.raises(TypeError):
             ckdf = ConcatKDFHash(
-                hashes.SHA256(),
-                16,
-                otherinfo=None,
-                backend=backend
+                hashes.SHA256(), 16, otherinfo=None, backend=backend
             )
 
             ckdf.derive(u"foo")
 
         with pytest.raises(TypeError):
             ckdf = ConcatKDFHash(
-                hashes.SHA256(),
-                16,
-                otherinfo=None,
-                backend=backend
+                hashes.SHA256(), 16, otherinfo=None, backend=backend
             )
 
             ckdf.verify(u"foo", b"bar")
 
         with pytest.raises(TypeError):
             ckdf = ConcatKDFHash(
-                hashes.SHA256(),
-                16,
-                otherinfo=None,
-                backend=backend
+                hashes.SHA256(), 16, otherinfo=None, backend=backend
             )
 
             ckdf.verify(b"foo", u"bar")
@@ -162,8 +148,10 @@
             b"8f0af7fce1d045edbc5790931e8d5ca79c73"
         )
 
-        okm = binascii.unhexlify(b"64ce901db10d558661f10b6836a122a7"
-                                 b"605323ce2f39bf27eaaac8b34cf89f2f")
+        okm = binascii.unhexlify(
+            b"64ce901db10d558661f10b6836a122a7"
+            b"605323ce2f39bf27eaaac8b34cf89f2f"
+        )
 
         oinfo = binascii.unhexlify(
             b"a1b2c3d4e55e600be5f367e0e8a465f4bf2704db00c9325c"
@@ -181,8 +169,10 @@
             b"8f0af7fce1d045edbc5790931e8d5ca79c73"
         )
 
-        okm = binascii.unhexlify(b"64ce901db10d558661f10b6836a122a7"
-                                 b"605323ce2f39bf27eaaac8b34cf89f2f")
+        okm = binascii.unhexlify(
+            b"64ce901db10d558661f10b6836a122a7"
+            b"605323ce2f39bf27eaaac8b34cf89f2f"
+        )
 
         oinfo = binascii.unhexlify(
             b"a1b2c3d4e55e600be5f367e0e8a465f4bf2704db00c9325c"
@@ -200,8 +190,10 @@
             b"8f0af7fce1d045edbc5790931e8d5ca79c73"
         )
 
-        okm = binascii.unhexlify(b"64ce901db10d558661f10b6836a122a7"
-                                 b"605323ce2f39bf27eaaac8b34cf89f2f")
+        okm = binascii.unhexlify(
+            b"64ce901db10d558661f10b6836a122a7"
+            b"605323ce2f39bf27eaaac8b34cf89f2f"
+        )
 
         oinfo = binascii.unhexlify(
             b"a1b2c3d4e55e600be5f367e0e8a465f4bf2704db00c9325c"
@@ -221,8 +213,10 @@
             b"8f0af7fce1d045edbc5790931e8d5ca79c73"
         )
 
-        okm = binascii.unhexlify(b"64ce901db10d558661f10b6836a122a7"
-                                 b"605323ce2f39bf27eaaac8b34cf89f2f")
+        okm = binascii.unhexlify(
+            b"64ce901db10d558661f10b6836a122a7"
+            b"605323ce2f39bf27eaaac8b34cf89f2f"
+        )
 
         oinfo = binascii.unhexlify(
             b"a1b2c3d4e55e600be5f367e0e8a465f4bf2704db00c9325c"
@@ -254,45 +248,38 @@
         with pytest.raises(TypeError):
             ConcatKDFHMAC(
                 hashes.SHA256(),
-                16, salt=u"foo",
+                16,
+                salt=u"foo",
                 otherinfo=None,
-                backend=backend
+                backend=backend,
             )
 
         with pytest.raises(TypeError):
             ConcatKDFHMAC(
                 hashes.SHA256(),
-                16, salt=None,
+                16,
+                salt=None,
                 otherinfo=u"foo",
-                backend=backend
+                backend=backend,
             )
 
         with pytest.raises(TypeError):
             ckdf = ConcatKDFHMAC(
-                hashes.SHA256(),
-                16, salt=None,
-                otherinfo=None,
-                backend=backend
+                hashes.SHA256(), 16, salt=None, otherinfo=None, backend=backend
             )
 
             ckdf.derive(u"foo")
 
         with pytest.raises(TypeError):
             ckdf = ConcatKDFHMAC(
-                hashes.SHA256(),
-                16, salt=None,
-                otherinfo=None,
-                backend=backend
+                hashes.SHA256(), 16, salt=None, otherinfo=None, backend=backend
             )
 
             ckdf.verify(u"foo", b"bar")
 
         with pytest.raises(TypeError):
             ckdf = ConcatKDFHMAC(
-                hashes.SHA256(),
-                16, salt=None,
-                otherinfo=None,
-                backend=backend
+                hashes.SHA256(), 16, salt=None, otherinfo=None, backend=backend
             )
 
             ckdf.verify(b"foo", u"bar")
diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py
index c667cd1..bc5ed8f 100644
--- a/tests/hazmat/primitives/test_dh.py
+++ b/tests/hazmat/primitives/test_dh.py
@@ -11,119 +11,114 @@
 import pytest
 
 from cryptography.hazmat.backends.interfaces import (
-    DERSerializationBackend, DHBackend, PEMSerializationBackend)
+    DERSerializationBackend,
+    DHBackend,
+    PEMSerializationBackend,
+)
 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
 from ...utils import load_nist_vectors, load_vectors_from_file
 
+# RFC 3526
+P_1536 = int(
+    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
+    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
+    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
+    "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+    "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF",
+    16,
+)
+
 
 def _skip_dhx_unsupported(backend, is_dhx):
     if not is_dhx:
         return
     if not backend.dh_x942_serialization_supported():
-        pytest.skip(
-            "DH x9.42 serialization is not supported"
-        )
+        pytest.skip("DH x9.42 serialization is not supported")
 
 
 def test_dh_parameternumbers():
-    params = dh.DHParameterNumbers(
-        65537, 2
-    )
+    params = dh.DHParameterNumbers(P_1536, 2)
 
-    assert params.p == 65537
+    assert params.p == P_1536
     assert params.g == 2
 
     with pytest.raises(TypeError):
-        dh.DHParameterNumbers(
-            None, 2
-        )
+        dh.DHParameterNumbers(None, 2)
 
     with pytest.raises(TypeError):
-        dh.DHParameterNumbers(
-            65537, None
-        )
+        dh.DHParameterNumbers(P_1536, None)
 
     with pytest.raises(TypeError):
-        dh.DHParameterNumbers(
-            None, None
-        )
+        dh.DHParameterNumbers(None, None)
 
     with pytest.raises(ValueError):
-        dh.DHParameterNumbers(
-            65537, 1
-        )
+        dh.DHParameterNumbers(P_1536, 1)
 
-    params = dh.DHParameterNumbers(
-        65537, 7, 1245
-    )
+    # p too small
+    with pytest.raises(ValueError):
+        dh.DHParameterNumbers(65537, 2)
 
-    assert params.p == 65537
+    params = dh.DHParameterNumbers(P_1536, 7, 1245)
+
+    assert params.p == P_1536
     assert params.g == 7
     assert params.q == 1245
 
     with pytest.raises(TypeError):
-        dh.DHParameterNumbers(
-            65537, 2, "hello"
-        )
+        dh.DHParameterNumbers(P_1536, 2, "hello")
 
 
 def test_dh_numbers():
-    params = dh.DHParameterNumbers(
-        65537, 2
-    )
+    params = dh.DHParameterNumbers(P_1536, 2)
 
-    public = dh.DHPublicNumbers(
-        1, params
-    )
+    public = dh.DHPublicNumbers(1, params)
 
     assert public.parameter_numbers is params
     assert public.y == 1
 
     with pytest.raises(TypeError):
-        dh.DHPublicNumbers(
-            1, None
-        )
+        dh.DHPublicNumbers(1, None)
 
     with pytest.raises(TypeError):
-        dh.DHPublicNumbers(
-            None, params
-        )
+        dh.DHPublicNumbers(None, params)
 
-    private = dh.DHPrivateNumbers(
-        1, public
-    )
+    private = dh.DHPrivateNumbers(1, public)
 
     assert private.public_numbers is public
     assert private.x == 1
 
     with pytest.raises(TypeError):
-        dh.DHPrivateNumbers(
-            1, None
-        )
+        dh.DHPrivateNumbers(1, None)
 
     with pytest.raises(TypeError):
-        dh.DHPrivateNumbers(
-            None, public
-        )
+        dh.DHPrivateNumbers(None, public)
 
 
 def test_dh_parameter_numbers_equality():
-    assert dh.DHParameterNumbers(65537, 2) == dh.DHParameterNumbers(65537, 2)
-    assert dh.DHParameterNumbers(65537, 7, 12345) == dh.DHParameterNumbers(
-        65537, 7, 12345)
-    assert dh.DHParameterNumbers(6, 2) != dh.DHParameterNumbers(65537, 2)
-    assert dh.DHParameterNumbers(65537, 2, 123) != dh.DHParameterNumbers(
-        65537, 2, 456)
-    assert dh.DHParameterNumbers(65537, 5) != dh.DHParameterNumbers(65537, 2)
-    assert dh.DHParameterNumbers(65537, 2) != object()
+    assert dh.DHParameterNumbers(P_1536, 2) == dh.DHParameterNumbers(P_1536, 2)
+    assert dh.DHParameterNumbers(P_1536, 7, 12345) == dh.DHParameterNumbers(
+        P_1536, 7, 12345
+    )
+    assert dh.DHParameterNumbers(P_1536 + 2, 2) != dh.DHParameterNumbers(
+        P_1536, 2
+    )
+    assert dh.DHParameterNumbers(P_1536, 2, 123) != dh.DHParameterNumbers(
+        P_1536, 2, 456
+    )
+    assert dh.DHParameterNumbers(P_1536, 5) != dh.DHParameterNumbers(P_1536, 2)
+    assert dh.DHParameterNumbers(P_1536, 2) != object()
 
 
 def test_dh_private_numbers_equality():
-    params = dh.DHParameterNumbers(65537, 2)
+    params = dh.DHParameterNumbers(P_1536, 2)
     public = dh.DHPublicNumbers(1, params)
     private = dh.DHPrivateNumbers(2, public)
 
@@ -131,18 +126,18 @@
     assert private != dh.DHPrivateNumbers(0, public)
     assert private != dh.DHPrivateNumbers(2, dh.DHPublicNumbers(0, params))
     assert private != dh.DHPrivateNumbers(
-        2, dh.DHPublicNumbers(1, dh.DHParameterNumbers(65537, 5))
+        2, dh.DHPublicNumbers(1, dh.DHParameterNumbers(P_1536, 5))
     )
     assert private != object()
 
 
 def test_dh_public_numbers_equality():
-    params = dh.DHParameterNumbers(65537, 2)
+    params = dh.DHParameterNumbers(P_1536, 2)
     public = dh.DHPublicNumbers(1, params)
 
     assert public == dh.DHPublicNumbers(1, params)
     assert public != dh.DHPublicNumbers(0, params)
-    assert public != dh.DHPublicNumbers(1, dh.DHParameterNumbers(65537, 5))
+    assert public != dh.DHPublicNumbers(1, dh.DHParameterNumbers(P_1536, 5))
     assert public != object()
 
 
@@ -156,19 +151,33 @@
         with pytest.raises(ValueError):
             dh.generate_parameters(7, 512, backend)
 
+    @pytest.mark.skip_fips(reason="non-FIPS parameters")
     def test_dh_parameters_supported(self, backend):
-        assert backend.dh_parameters_supported(23, 5)
-        assert not backend.dh_parameters_supported(23, 18)
+        valid_p = int(
+            b"907c7211ae61aaaba1825ff53b6cb71ac6df9f1a424c033f4a0a41ac42fad3a9"
+            b"bcfc7f938a269710ed69e330523e4039029b7900977c740990d46efed79b9bbe"
+            b"73505ae878808944ce4d9c6c52daecc0a87dc889c53499be93db8551ee685f30"
+            b"349bf1b443d4ebaee0d5e8b441a40d4e8178f8f612f657a5eb91e0a8e"
+            b"107755f",
+            16,
+        )
+        assert backend.dh_parameters_supported(valid_p, 5)
+        assert not backend.dh_parameters_supported(23, 22)
 
     @pytest.mark.parametrize(
         "vector",
         load_vectors_from_file(
-            os.path.join("asymmetric", "DH", "rfc3526.txt"),
-            load_nist_vectors
-        )
+            os.path.join("asymmetric", "DH", "rfc3526.txt"), load_nist_vectors
+        ),
     )
     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
+        ):
+            pytest.skip("modulus too small for FIPS mode")
+
         params = dh.DHParameterNumbers(p, int(vector["g"]))
         param = params.parameters(backend)
         key = param.generate_private_key()
@@ -178,22 +187,26 @@
         roundtripped_key = key.private_numbers().private_key(backend)
         assert key.private_numbers() == roundtripped_key.private_numbers()
 
+    @pytest.mark.skip_fips(reason="non-FIPS parameters")
     @pytest.mark.parametrize(
         "vector",
         load_vectors_from_file(
-            os.path.join("asymmetric", "DH", "RFC5114.txt"),
-            load_nist_vectors))
+            os.path.join("asymmetric", "DH", "RFC5114.txt"), load_nist_vectors
+        ),
+    )
     def test_dh_parameters_supported_with_q(self, backend, vector):
-        assert backend.dh_parameters_supported(int(vector["p"], 16),
-                                               int(vector["g"], 16),
-                                               int(vector["q"], 16))
+        assert backend.dh_parameters_supported(
+            int(vector["p"], 16), int(vector["g"], 16), int(vector["q"], 16)
+        )
 
+    @pytest.mark.skip_fips(reason="modulus too small for FIPS")
     @pytest.mark.parametrize("with_q", [False, True])
     def test_convert_to_numbers(self, backend, with_q):
         if with_q:
             vector = load_vectors_from_file(
                 os.path.join("asymmetric", "DH", "RFC5114.txt"),
-                load_nist_vectors)[0]
+                load_nist_vectors,
+            )[0]
             p = int(vector["p"], 16)
             g = int(vector["g"], 16)
             q = int(vector["q"], 16)
@@ -214,32 +227,35 @@
         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.DHParametersWithSerialization
+        )
+        assert isinstance(deserialized_public, dh.DHPublicKeyWithSerialization)
+        assert isinstance(
+            deserialized_private, dh.DHPrivateKeyWithSerialization
+        )
 
+    @pytest.mark.skip_fips(reason="FIPS requires specific parameters")
     def test_numbers_unsupported_parameters(self, backend):
-        # p is set to 21 because when calling private_key we want it to
-        # fail the DH_check call OpenSSL does. Originally this was 23, but
-        # we are allowing p % 24 to == 23 with this PR (see #3768 for more)
-        # By setting it to 21 it fails later in DH_check in a primality check
-        # which triggers the code path we want to test
-        params = dh.DHParameterNumbers(21, 2)
+        # p is set to P_1536 + 1 because when calling private_key we want it to
+        # fail the DH_check call OpenSSL does, but we specifically want it to
+        # fail such that we don't get a DH_NOT_SUITABLE_GENERATOR. We can cause
+        # this by making sure p is not prime.
+        params = dh.DHParameterNumbers(P_1536 + 1, 2)
         public = dh.DHPublicNumbers(1, params)
         private = dh.DHPrivateNumbers(2, public)
 
         with pytest.raises(ValueError):
             private.private_key(backend)
 
+    @pytest.mark.skip_fips(reason="FIPS requires key size >= 2048")
     @pytest.mark.parametrize("with_q", [False, True])
     def test_generate_dh(self, backend, with_q):
         if with_q:
             vector = load_vectors_from_file(
                 os.path.join("asymmetric", "DH", "RFC5114.txt"),
-                load_nist_vectors)[0]
+                load_nist_vectors,
+            )[0]
             p = int(vector["p"], 16)
             g = int(vector["g"], 16)
             q = int(vector["q"], 16)
@@ -274,7 +290,7 @@
         assert isinstance(key.parameters(), dh.DHParameters)
 
     def test_exchange(self, backend):
-        parameters = dh.generate_parameters(2, 512, backend)
+        parameters = FFDH3072_P.parameters(backend)
         assert isinstance(parameters, dh.DHParameters)
 
         key1 = parameters.generate_private_key()
@@ -282,65 +298,82 @@
 
         symkey1 = key1.exchange(key2.public_key())
         assert symkey1
-        assert len(symkey1) == 512 // 8
+        assert len(symkey1) == 3072 // 8
 
         symkey2 = key2.exchange(key1.public_key())
         assert symkey1 == symkey2
 
     def test_exchange_algorithm(self, backend):
-        parameters = dh.generate_parameters(2, 512, backend)
-
+        parameters = FFDH3072_P.parameters(backend)
         key1 = parameters.generate_private_key()
         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,
-                            key2.private_numbers().x,
-                            parameters.parameter_numbers().p)
+        symkey_manual = pow(
+            key1.public_key().public_numbers().y,
+            key2.private_numbers().x,
+            parameters.parameter_numbers().p,
+        )
 
         assert symkey == symkey_manual
 
+    @pytest.mark.skip_fips(reason="key_size too small for FIPS")
     def test_symmetric_key_padding(self, backend):
         """
         This test has specific parameters that produce a symmetric key
         In length 63 bytes instead 64. We make sure here that we add
         padding to the key.
         """
-        p = int("11859949538425015739337467917303613431031019140213666"
-                "129025407300654026585086345323066284800963463204246390"
-                "256567934582260424238844463330887962689642467123")
+        p = int(
+            "11859949538425015739337467917303613431031019140213666"
+            "129025407300654026585086345323066284800963463204246390"
+            "256567934582260424238844463330887962689642467123"
+        )
         g = 2
-        y = int("32155788395534640648739966373159697798396966919821525"
-                "72238852825117261342483718574508213761865276905503199"
-                "969908098203345481366464874759377454476688391248")
-        x = int("409364065449673443397833358558926598469347813468816037"
-                "268451847116982490733450463194921405069999008617231539"
-                "7147035896687401350877308899732826446337707128")
+        y = int(
+            "32155788395534640648739966373159697798396966919821525"
+            "72238852825117261342483718574508213761865276905503199"
+            "969908098203345481366464874759377454476688391248"
+        )
+        x = int(
+            "409364065449673443397833358558926598469347813468816037"
+            "268451847116982490733450463194921405069999008617231539"
+            "7147035896687401350877308899732826446337707128"
+        )
         parameters = dh.DHParameterNumbers(p, g)
         public = dh.DHPublicNumbers(y, parameters)
         private = dh.DHPrivateNumbers(x, public)
         key = private.private_key(backend)
         symkey = key.exchange(public.public_key(backend))
         assert len(symkey) == 512 // 8
-        assert symkey[:1] == b'\x00'
+        assert symkey[:1] == b"\x00"
 
     @pytest.mark.parametrize(
         "vector",
         load_vectors_from_file(
             os.path.join("asymmetric", "DH", "bad_exchange.txt"),
-            load_nist_vectors))
+            load_nist_vectors,
+        ),
+    )
     def test_bad_exchange(self, backend, vector):
-        parameters1 = dh.DHParameterNumbers(int(vector["p1"]),
-                                            int(vector["g"]))
+        if (
+            backend._fips_enabled
+            and int(vector["p1"]) < backend._fips_dh_min_modulus
+        ):
+            pytest.skip("modulus too small for FIPS mode")
+        parameters1 = dh.DHParameterNumbers(
+            int(vector["p1"]), int(vector["g"])
+        )
         public1 = dh.DHPublicNumbers(int(vector["y1"]), parameters1)
         private1 = dh.DHPrivateNumbers(int(vector["x1"]), public1)
         key1 = private1.private_key(backend)
         pub_key1 = key1.public_key()
 
-        parameters2 = dh.DHParameterNumbers(int(vector["p2"]),
-                                            int(vector["g"]))
+        parameters2 = dh.DHParameterNumbers(
+            int(vector["p2"]), int(vector["g"])
+        )
         public2 = dh.DHPublicNumbers(int(vector["y2"]), parameters2)
         private2 = dh.DHPrivateNumbers(int(vector["x2"]), public2)
         key2 = private2.private_key(backend)
@@ -357,30 +390,51 @@
 
             assert symkey1 != symkey2
 
+    @pytest.mark.skip_fips(reason="key_size too small for FIPS")
+    def test_load_256bit_key_from_pkcs8(self, backend):
+        data = load_vectors_from_file(
+            os.path.join("asymmetric", "DH", "dh_key_256.pem"),
+            lambda pemfile: pemfile.read(),
+            mode="rb",
+        )
+        key = serialization.load_pem_private_key(data, None, backend)
+        assert key.key_size == 256
+
     @pytest.mark.parametrize(
         "vector",
         load_vectors_from_file(
-            os.path.join("asymmetric", "DH", "vec.txt"),
-            load_nist_vectors))
+            os.path.join("asymmetric", "DH", "vec.txt"), load_nist_vectors
+        ),
+    )
     def test_dh_vectors(self, backend, vector):
-        parameters = dh.DHParameterNumbers(int(vector["p"]),
-                                           int(vector["g"]))
+        if (
+            backend._fips_enabled
+            and int(vector["p"]) < backend._fips_dh_min_modulus
+        ):
+            pytest.skip("modulus too small for FIPS mode")
+
+        if int(vector["p"]).bit_length() < 512:
+            pytest.skip("DH keys less than 512 bits are unsupported")
+
+        parameters = dh.DHParameterNumbers(int(vector["p"]), int(vector["g"]))
         public = dh.DHPublicNumbers(int(vector["y"]), parameters)
         private = dh.DHPrivateNumbers(int(vector["x"]), public)
         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(
         "vector",
         load_vectors_from_file(
-            os.path.join("asymmetric", "DH", "RFC5114.txt"),
-            load_nist_vectors))
+            os.path.join("asymmetric", "DH", "RFC5114.txt"), load_nist_vectors
+        ),
+    )
     def test_dh_vectors_with_q(self, backend, vector):
-        parameters = dh.DHParameterNumbers(int(vector["p"], 16),
-                                           int(vector["g"], 16),
-                                           int(vector["q"], 16))
+        parameters = dh.DHParameterNumbers(
+            int(vector["p"], 16), int(vector["g"], 16), int(vector["q"], 16)
+        )
         public1 = dh.DHPublicNumbers(int(vector["ystatcavs"], 16), parameters)
         private1 = dh.DHPrivateNumbers(int(vector["xstatcavs"], 16), public1)
         public2 = dh.DHPublicNumbers(int(vector["ystatiut"], 16), parameters)
@@ -390,35 +444,28 @@
         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)
 @pytest.mark.requires_backend_interface(interface=PEMSerializationBackend)
 @pytest.mark.requires_backend_interface(interface=DERSerializationBackend)
 class TestDHPrivateKeySerialization(object):
-
     @pytest.mark.parametrize(
         ("encoding", "loader_func"),
         [
-            [
-                serialization.Encoding.PEM,
-                serialization.load_pem_private_key
-            ],
-            [
-                serialization.Encoding.DER,
-                serialization.load_der_private_key
-            ],
-        ]
+            [serialization.Encoding.PEM, serialization.load_pem_private_key],
+            [serialization.Encoding.DER, serialization.load_der_private_key],
+        ],
     )
-    def test_private_bytes_unencrypted(self, backend, encoding,
-                                       loader_func):
-        parameters = dh.generate_parameters(2, 512, backend)
+    def test_private_bytes_unencrypted(self, backend, encoding, loader_func):
+        parameters = FFDH3072_P.parameters(backend)
         key = parameters.generate_private_key()
         serialized = key.private_bytes(
-            encoding, serialization.PrivateFormat.PKCS8,
-            serialization.NoEncryption()
+            encoding,
+            serialization.PrivateFormat.PKCS8,
+            serialization.NoEncryption(),
         )
         loaded_key = loader_func(serialized, None, backend)
         loaded_priv_num = loaded_key.private_numbers()
@@ -432,14 +479,15 @@
             (serialization.Encoding.DER, serialization.PrivateFormat.Raw),
             (serialization.Encoding.Raw, serialization.PrivateFormat.Raw),
             (serialization.Encoding.X962, serialization.PrivateFormat.PKCS8),
-        ]
+        ],
     )
     def test_private_bytes_rejects_invalid(self, encoding, fmt, backend):
-        parameters = dh.generate_parameters(2, 512, backend)
+        parameters = FFDH3072_P.parameters(backend)
         key = parameters.generate_private_key()
         with pytest.raises(ValueError):
             key.private_bytes(encoding, fmt, serialization.NoEncryption())
 
+    @pytest.mark.skip_fips(reason="non-FIPS parameters")
     @pytest.mark.parametrize(
         ("key_path", "loader_func", "encoding", "is_dhx"),
         [
@@ -448,38 +496,43 @@
                 serialization.load_pem_private_key,
                 serialization.Encoding.PEM,
                 False,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "DH", "dhkey.der"),
                 serialization.load_der_private_key,
                 serialization.Encoding.DER,
                 False,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.pem"),
                 serialization.load_pem_private_key,
                 serialization.Encoding.PEM,
                 True,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.der"),
                 serialization.load_der_private_key,
                 serialization.Encoding.DER,
                 True,
-            )
-        ]
+            ),
+        ],
     )
-    def test_private_bytes_match(self, key_path, loader_func,
-                                 encoding, is_dhx, backend):
+    def test_private_bytes_match(
+        self, key_path, loader_func, encoding, is_dhx, backend
+    ):
         _skip_dhx_unsupported(backend, is_dhx)
         key_bytes = load_vectors_from_file(
-            key_path,
-            lambda pemfile: pemfile.read(), mode="rb"
+            key_path, lambda pemfile: pemfile.read(), mode="rb"
         )
         key = loader_func(key_bytes, None, backend)
         serialized = key.private_bytes(
-            encoding, serialization.PrivateFormat.PKCS8,
-            serialization.NoEncryption()
+            encoding,
+            serialization.PrivateFormat.PKCS8,
+            serialization.NoEncryption(),
         )
         assert serialized == key_bytes
 
+    @pytest.mark.skip_fips(reason="non-FIPS parameters")
     @pytest.mark.parametrize(
         ("key_path", "loader_func", "vec_path", "is_dhx"),
         [
@@ -488,30 +541,33 @@
                 serialization.load_pem_private_key,
                 os.path.join("asymmetric", "DH", "dhkey.txt"),
                 False,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "DH", "dhkey.der"),
                 serialization.load_der_private_key,
                 os.path.join("asymmetric", "DH", "dhkey.txt"),
                 False,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.pem"),
                 serialization.load_pem_private_key,
                 os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.txt"),
                 True,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.der"),
                 serialization.load_der_private_key,
                 os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.txt"),
                 True,
-            )
-        ]
+            ),
+        ],
     )
-    def test_private_bytes_values(self, key_path, loader_func,
-                                  vec_path, is_dhx, backend):
+    def test_private_bytes_values(
+        self, key_path, loader_func, vec_path, is_dhx, backend
+    ):
         _skip_dhx_unsupported(backend, is_dhx)
         key_bytes = load_vectors_from_file(
-            key_path,
-            lambda pemfile: pemfile.read(), mode="rb"
+            key_path, lambda pemfile: pemfile.read(), mode="rb"
         )
         vec = load_vectors_from_file(vec_path, load_nist_vectors)[0]
         key = loader_func(key_bytes, None, backend)
@@ -519,63 +575,66 @@
         assert private_numbers.x == int(vec["x"], 16)
         assert private_numbers.public_numbers.y == int(vec["y"], 16)
         assert private_numbers.public_numbers.parameter_numbers.g == int(
-            vec["g"], 16)
+            vec["g"], 16
+        )
         assert private_numbers.public_numbers.parameter_numbers.p == int(
-            vec["p"], 16)
+            vec["p"], 16
+        )
         if "q" in vec:
             assert private_numbers.public_numbers.parameter_numbers.q == int(
-                vec["q"], 16)
+                vec["q"], 16
+            )
         else:
             assert private_numbers.public_numbers.parameter_numbers.q is None
 
     def test_private_bytes_traditional_openssl_invalid(self, backend):
-        parameters = dh.generate_parameters(2, 512, backend)
+        parameters = FFDH3072_P.parameters(backend)
         key = parameters.generate_private_key()
         with pytest.raises(ValueError):
             key.private_bytes(
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.TraditionalOpenSSL,
-                serialization.NoEncryption()
+                serialization.NoEncryption(),
             )
 
     def test_private_bytes_invalid_encoding(self, backend):
-        parameters = dh.generate_parameters(2, 512, backend)
+        parameters = FFDH3072_P.parameters(backend)
         key = parameters.generate_private_key()
         with pytest.raises(TypeError):
             key.private_bytes(
                 "notencoding",
                 serialization.PrivateFormat.PKCS8,
-                serialization.NoEncryption()
+                serialization.NoEncryption(),
             )
 
     def test_private_bytes_invalid_format(self, backend):
-        parameters = dh.generate_parameters(2, 512, backend)
+        parameters = FFDH3072_P.parameters(backend)
         key = parameters.generate_private_key()
         with pytest.raises(ValueError):
             key.private_bytes(
                 serialization.Encoding.PEM,
                 "invalidformat",
-                serialization.NoEncryption()
+                serialization.NoEncryption(),
             )
 
     def test_private_bytes_invalid_encryption_algorithm(self, backend):
-        parameters = dh.generate_parameters(2, 512, backend)
+        parameters = FFDH3072_P.parameters(backend)
         key = parameters.generate_private_key()
         with pytest.raises(TypeError):
             key.private_bytes(
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.PKCS8,
-                "notanencalg"
+                "notanencalg",
             )
 
     def test_private_bytes_unsupported_encryption_type(self, backend):
-        parameters = dh.generate_parameters(2, 512, backend)
+        parameters = FFDH3072_P.parameters(backend)
         key = parameters.generate_private_key()
         with pytest.raises(ValueError):
             key.private_bytes(
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.PKCS8,
-                DummyKeySerializationEncryption()
+                DummyKeySerializationEncryption(),
             )
 
 
@@ -583,23 +642,15 @@
 @pytest.mark.requires_backend_interface(interface=PEMSerializationBackend)
 @pytest.mark.requires_backend_interface(interface=DERSerializationBackend)
 class TestDHPublicKeySerialization(object):
-
     @pytest.mark.parametrize(
         ("encoding", "loader_func"),
         [
-            [
-                serialization.Encoding.PEM,
-                serialization.load_pem_public_key
-            ],
-            [
-                serialization.Encoding.DER,
-                serialization.load_der_public_key
-            ],
-        ]
+            [serialization.Encoding.PEM, serialization.load_pem_public_key],
+            [serialization.Encoding.DER, serialization.load_der_public_key],
+        ],
     )
-    def test_public_bytes(self, backend, encoding,
-                          loader_func):
-        parameters = dh.generate_parameters(2, 512, backend)
+    def test_public_bytes(self, backend, encoding, loader_func):
+        parameters = FFDH3072_P.parameters(backend)
         key = parameters.generate_private_key().public_key()
         serialized = key.public_bytes(
             encoding, serialization.PublicFormat.SubjectPublicKeyInfo
@@ -617,30 +668,33 @@
                 serialization.load_pem_public_key,
                 serialization.Encoding.PEM,
                 False,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "DH", "dhpub.der"),
                 serialization.load_der_public_key,
                 serialization.Encoding.DER,
                 False,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "DH", "dhpub_rfc5114_2.pem"),
                 serialization.load_pem_public_key,
                 serialization.Encoding.PEM,
                 True,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "DH", "dhpub_rfc5114_2.der"),
                 serialization.load_der_public_key,
                 serialization.Encoding.DER,
                 True,
-            )
-        ]
+            ),
+        ],
     )
-    def test_public_bytes_match(self, key_path, loader_func,
-                                encoding, is_dhx, backend):
+    def test_public_bytes_match(
+        self, key_path, loader_func, encoding, is_dhx, backend
+    ):
         _skip_dhx_unsupported(backend, is_dhx)
         key_bytes = load_vectors_from_file(
-            key_path,
-            lambda pemfile: pemfile.read(), mode="rb"
+            key_path, lambda pemfile: pemfile.read(), mode="rb"
         )
         pub_key = loader_func(key_bytes, backend)
         serialized = pub_key.public_bytes(
@@ -657,30 +711,33 @@
                 serialization.load_pem_public_key,
                 os.path.join("asymmetric", "DH", "dhkey.txt"),
                 False,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "DH", "dhpub.der"),
                 serialization.load_der_public_key,
                 os.path.join("asymmetric", "DH", "dhkey.txt"),
                 False,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "DH", "dhpub_rfc5114_2.pem"),
                 serialization.load_pem_public_key,
                 os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.txt"),
                 True,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "DH", "dhpub_rfc5114_2.der"),
                 serialization.load_der_public_key,
                 os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.txt"),
                 True,
-            )
-        ]
+            ),
+        ],
     )
-    def test_public_bytes_values(self, key_path, loader_func,
-                                 vec_path, is_dhx, backend):
+    def test_public_bytes_values(
+        self, key_path, loader_func, vec_path, is_dhx, backend
+    ):
         _skip_dhx_unsupported(backend, is_dhx)
         key_bytes = load_vectors_from_file(
-            key_path,
-            lambda pemfile: pemfile.read(), mode="rb"
+            key_path, lambda pemfile: pemfile.read(), mode="rb"
         )
         vec = load_vectors_from_file(vec_path, load_nist_vectors)[0]
         pub_key = loader_func(key_bytes, backend)
@@ -694,16 +751,15 @@
             assert public_numbers.parameter_numbers.q is None
 
     def test_public_bytes_invalid_encoding(self, backend):
-        parameters = dh.generate_parameters(2, 512, backend)
+        parameters = FFDH3072_P.parameters(backend)
         key = parameters.generate_private_key().public_key()
         with pytest.raises(TypeError):
             key.public_bytes(
-                "notencoding",
-                serialization.PublicFormat.SubjectPublicKeyInfo
+                "notencoding", serialization.PublicFormat.SubjectPublicKeyInfo
             )
 
     def test_public_bytes_pkcs1_unsupported(self, backend):
-        parameters = dh.generate_parameters(2, 512, backend)
+        parameters = FFDH3072_P.parameters(backend)
         key = parameters.generate_private_key().public_key()
         with pytest.raises(ValueError):
             key.public_bytes(
@@ -715,23 +771,15 @@
 @pytest.mark.requires_backend_interface(interface=PEMSerializationBackend)
 @pytest.mark.requires_backend_interface(interface=DERSerializationBackend)
 class TestDHParameterSerialization(object):
-
     @pytest.mark.parametrize(
         ("encoding", "loader_func"),
         [
-            [
-                serialization.Encoding.PEM,
-                serialization.load_pem_parameters
-            ],
-            [
-                serialization.Encoding.DER,
-                serialization.load_der_parameters
-            ],
-        ]
+            [serialization.Encoding.PEM, serialization.load_pem_parameters],
+            [serialization.Encoding.DER, serialization.load_der_parameters],
+        ],
     )
-    def test_parameter_bytes(self, backend, encoding,
-                             loader_func):
-        parameters = dh.generate_parameters(2, 512, backend)
+    def test_parameter_bytes(self, backend, encoding, loader_func):
+        parameters = FFDH3072_P.parameters(backend)
         serialized = parameters.parameter_bytes(
             encoding, serialization.ParameterFormat.PKCS3
         )
@@ -747,30 +795,33 @@
                 serialization.load_pem_parameters,
                 serialization.Encoding.PEM,
                 False,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "DH", "dhp.der"),
                 serialization.load_der_parameters,
                 serialization.Encoding.DER,
                 False,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "DH", "dhp_rfc5114_2.pem"),
                 serialization.load_pem_parameters,
                 serialization.Encoding.PEM,
                 True,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "DH", "dhp_rfc5114_2.der"),
                 serialization.load_der_parameters,
                 serialization.Encoding.DER,
                 True,
-            )
-        ]
+            ),
+        ],
     )
-    def test_parameter_bytes_match(self, param_path, loader_func,
-                                   encoding, backend, is_dhx):
+    def test_parameter_bytes_match(
+        self, param_path, loader_func, encoding, backend, is_dhx
+    ):
         _skip_dhx_unsupported(backend, is_dhx)
         param_bytes = load_vectors_from_file(
-            param_path,
-            lambda pemfile: pemfile.read(), mode="rb"
+            param_path, lambda pemfile: pemfile.read(), mode="rb"
         )
         parameters = loader_func(param_bytes, backend)
         serialized = parameters.parameter_bytes(
@@ -787,30 +838,33 @@
                 serialization.load_pem_parameters,
                 os.path.join("asymmetric", "DH", "dhkey.txt"),
                 False,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "DH", "dhp.der"),
                 serialization.load_der_parameters,
                 os.path.join("asymmetric", "DH", "dhkey.txt"),
                 False,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "DH", "dhp_rfc5114_2.pem"),
                 serialization.load_pem_parameters,
                 os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.txt"),
                 True,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "DH", "dhp_rfc5114_2.der"),
                 serialization.load_der_parameters,
                 os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.txt"),
                 True,
-            )
-        ]
+            ),
+        ],
     )
-    def test_public_bytes_values(self, param_path, loader_func,
-                                 vec_path, backend, is_dhx):
+    def test_public_bytes_values(
+        self, param_path, loader_func, vec_path, backend, is_dhx
+    ):
         _skip_dhx_unsupported(backend, is_dhx)
         key_bytes = load_vectors_from_file(
-            param_path,
-            lambda pemfile: pemfile.read(), mode="rb"
+            param_path, lambda pemfile: pemfile.read(), mode="rb"
         )
         vec = load_vectors_from_file(vec_path, load_nist_vectors)[0]
         parameters = loader_func(key_bytes, backend)
@@ -827,49 +881,48 @@
         [
             (
                 serialization.Encoding.Raw,
-                serialization.PublicFormat.SubjectPublicKeyInfo
+                serialization.PublicFormat.SubjectPublicKeyInfo,
             ),
             (serialization.Encoding.Raw, serialization.PublicFormat.PKCS1),
-        ] + list(itertools.product(
-            [
-                serialization.Encoding.Raw,
-                serialization.Encoding.X962,
-                serialization.Encoding.PEM,
-                serialization.Encoding.DER
-            ],
-            [
-                serialization.PublicFormat.Raw,
-                serialization.PublicFormat.UncompressedPoint,
-                serialization.PublicFormat.CompressedPoint
-            ]
-        ))
+        ]
+        + list(
+            itertools.product(
+                [
+                    serialization.Encoding.Raw,
+                    serialization.Encoding.X962,
+                    serialization.Encoding.PEM,
+                    serialization.Encoding.DER,
+                ],
+                [
+                    serialization.PublicFormat.Raw,
+                    serialization.PublicFormat.UncompressedPoint,
+                    serialization.PublicFormat.CompressedPoint,
+                ],
+            )
+        ),
     )
     def test_public_bytes_rejects_invalid(self, encoding, fmt, backend):
-        parameters = dh.generate_parameters(2, 512, backend)
+        parameters = FFDH3072_P.parameters(backend)
         key = parameters.generate_private_key().public_key()
         with pytest.raises(ValueError):
             key.public_bytes(encoding, fmt)
 
     def test_parameter_bytes_invalid_encoding(self, backend):
-        parameters = dh.generate_parameters(2, 512, backend)
+        parameters = FFDH3072_P.parameters(backend)
         with pytest.raises(TypeError):
             parameters.parameter_bytes(
-                "notencoding",
-                serialization.ParameterFormat.PKCS3
+                "notencoding", serialization.ParameterFormat.PKCS3
             )
 
     def test_parameter_bytes_invalid_format(self, backend):
-        parameters = dh.generate_parameters(2, 512, backend)
+        parameters = FFDH3072_P.parameters(backend)
         with pytest.raises(ValueError):
-            parameters.parameter_bytes(
-                serialization.Encoding.PEM,
-                "notformat"
-            )
+            parameters.parameter_bytes(serialization.Encoding.PEM, "notformat")
 
     def test_parameter_bytes_openssh_unsupported(self, backend):
-        parameters = dh.generate_parameters(2, 512, backend)
+        parameters = FFDH3072_P.parameters(backend)
         with pytest.raises(TypeError):
             parameters.parameter_bytes(
                 serialization.Encoding.OpenSSH,
-                serialization.ParameterFormat.PKCS3
+                serialization.ParameterFormat.PKCS3,
             )
diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py
index efd2239..bda2750 100644
--- a/tests/hazmat/primitives/test_dsa.py
+++ b/tests/hazmat/primitives/test_dsa.py
@@ -11,32 +11,33 @@
 
 from cryptography.exceptions import AlreadyFinalized, InvalidSignature
 from cryptography.hazmat.backends.interfaces import (
-    DSABackend, PEMSerializationBackend
+    DSABackend,
+    PEMSerializationBackend,
 )
 from cryptography.hazmat.primitives import hashes, serialization
 from cryptography.hazmat.primitives.asymmetric import dsa
 from cryptography.hazmat.primitives.asymmetric.utils import (
-    Prehashed, encode_dss_signature
+    Prehashed,
+    encode_dss_signature,
 )
 from cryptography.utils import CryptographyDeprecationWarning
 
-from .fixtures_dsa import (
-    DSA_KEY_1024, DSA_KEY_2048, DSA_KEY_3072
-)
+from .fixtures_dsa import DSA_KEY_1024, DSA_KEY_2048, DSA_KEY_3072
+from .utils import skip_fips_traditional_openssl
 from ...doubles import DummyHashAlgorithm, DummyKeySerializationEncryption
 from ...utils import (
-    load_fips_dsa_key_pair_vectors, load_fips_dsa_sig_vectors,
+    load_fips_dsa_key_pair_vectors,
+    load_fips_dsa_sig_vectors,
     load_vectors_from_file,
 )
 
 
 def _skip_if_dsa_not_supported(backend, algorithm, p, q, g):
-    if (
-        not backend.dsa_parameters_supported(p, q, g) or
-        not backend.dsa_hash_supported(algorithm)
-    ):
+    if not backend.dsa_parameters_supported(
+        p, q, g
+    ) or not backend.dsa_hash_supported(algorithm):
         pytest.skip(
-            "{0} does not support the provided parameters".format(backend)
+            "{} does not support the provided parameters".format(backend)
         )
 
 
@@ -49,7 +50,7 @@
 @pytest.mark.requires_backend_interface(interface=DSABackend)
 class TestDSA(object):
     def test_generate_dsa_parameters(self, backend):
-        parameters = dsa.generate_parameters(1024, backend)
+        parameters = dsa.generate_parameters(2048, backend)
         assert isinstance(parameters, dsa.DSAParameters)
 
     def test_generate_invalid_dsa_parameters(self, backend):
@@ -59,16 +60,18 @@
     @pytest.mark.parametrize(
         "vector",
         load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "DSA", "FIPS_186-3", "KeyPair.rsp"),
-            load_fips_dsa_key_pair_vectors
-        )
+            os.path.join("asymmetric", "DSA", "FIPS_186-3", "KeyPair.rsp"),
+            load_fips_dsa_key_pair_vectors,
+        ),
     )
     def test_generate_dsa_keys(self, vector, backend):
+        if (
+            backend._fips_enabled
+            and vector["p"] < backend._fips_dsa_min_modulus
+        ):
+            pytest.skip("Small modulus blocked in FIPS mode")
         parameters = dsa.DSAParameterNumbers(
-            p=vector['p'],
-            q=vector['q'],
-            g=vector['g']
+            p=vector["p"], q=vector["q"], g=vector["g"]
         ).parameters(backend)
         skey = parameters.generate_private_key()
         numbers = skey.private_numbers()
@@ -79,10 +82,10 @@
         assert parameter_numbers.p == skey_parameters.p
         assert parameter_numbers.q == skey_parameters.q
         assert parameter_numbers.g == skey_parameters.g
-        assert skey_parameters.p == vector['p']
-        assert skey_parameters.q == vector['q']
-        assert skey_parameters.g == vector['g']
-        assert skey.key_size == vector['p'].bit_length()
+        assert skey_parameters.p == vector["p"]
+        assert skey_parameters.q == vector["q"]
+        assert skey_parameters.g == vector["g"]
+        assert skey.key_size == vector["p"].bit_length()
         assert pkey.key_size == skey.key_size
         public_numbers = pkey.public_numbers()
         assert numbers.public_numbers.y == public_numbers.y
@@ -91,7 +94,7 @@
         )
 
     def test_generate_dsa_private_key_and_parameters(self, backend):
-        skey = dsa.generate_private_key(1024, backend)
+        skey = dsa.generate_private_key(2048, backend)
         assert skey
         numbers = skey.private_numbers()
         skey_parameters = numbers.public_numbers.parameter_numbers
@@ -130,7 +133,7 @@
             (
                 DSA_KEY_2048.public_numbers.parameter_numbers.p,
                 2 ** 250,
-                DSA_KEY_2048.public_numbers.parameter_numbers.g
+                DSA_KEY_2048.public_numbers.parameter_numbers.g,
             ),
             (
                 DSA_KEY_3072.public_numbers.parameter_numbers.p,
@@ -140,19 +143,19 @@
             (
                 DSA_KEY_1024.public_numbers.parameter_numbers.p,
                 DSA_KEY_1024.public_numbers.parameter_numbers.q,
-                0
+                0,
             ),
             (
                 DSA_KEY_1024.public_numbers.parameter_numbers.p,
                 DSA_KEY_1024.public_numbers.parameter_numbers.q,
-                1
+                1,
             ),
             (
                 DSA_KEY_1024.public_numbers.parameter_numbers.p,
                 DSA_KEY_1024.public_numbers.parameter_numbers.q,
-                2 ** 1200
+                2 ** 1200,
             ),
-        ]
+        ],
     )
     def test_invalid_parameters_values(self, p, q, g, backend):
         with pytest.raises(ValueError):
@@ -264,17 +267,18 @@
                 DSA_KEY_1024.public_numbers.parameter_numbers.q,
                 DSA_KEY_1024.public_numbers.parameter_numbers.g,
                 2 ** 100,
-                DSA_KEY_1024.x
+                DSA_KEY_1024.x,
             ),
-        ]
+        ],
     )
     def test_invalid_dsa_private_key_arguments(self, p, q, g, y, x, backend):
         with pytest.raises(ValueError):
             dsa.DSAPrivateNumbers(
                 public_numbers=dsa.DSAPublicNumbers(
                     parameter_numbers=dsa.DSAParameterNumbers(p=p, q=q, g=g),
-                    y=y
-                ), x=x
+                    y=y,
+                ),
+                x=x,
             ).private_key(backend)
 
     @pytest.mark.parametrize(
@@ -340,72 +344,95 @@
                 2 ** 1200,
                 DSA_KEY_1024.public_numbers.y,
             ),
-        ]
+        ],
     )
     def test_invalid_dsa_public_key_arguments(self, p, q, g, y, backend):
         with pytest.raises(ValueError):
             dsa.DSAPublicNumbers(
-                parameter_numbers=dsa.DSAParameterNumbers(p=p, q=q, g=g),
-                y=y
+                parameter_numbers=dsa.DSAParameterNumbers(p=p, q=q, g=g), y=y
             ).public_key(backend)
 
+    def test_large_p(self, backend):
+        key = load_vectors_from_file(
+            os.path.join("asymmetric", "PEM_Serialization", "dsa_4096.pem"),
+            lambda pemfile: serialization.load_pem_private_key(
+                pemfile.read(), None, backend
+            ),
+            mode="rb",
+        )
+        pn = key.private_numbers()
+        assert pn.public_numbers.parameter_numbers.p.bit_length() == 4096
+        # Turn it back into a key to confirm that values this large pass
+        # verification
+        dsa.DSAPrivateNumbers(
+            public_numbers=dsa.DSAPublicNumbers(
+                parameter_numbers=dsa.DSAParameterNumbers(
+                    p=pn.public_numbers.parameter_numbers.p,
+                    q=pn.public_numbers.parameter_numbers.q,
+                    g=pn.public_numbers.parameter_numbers.g,
+                ),
+                y=pn.public_numbers.y,
+            ),
+            x=pn.x,
+        ).private_key(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
+        "SHA1": hashes.SHA1,
+        "SHA224": hashes.SHA224,
+        "SHA256": hashes.SHA256,
+        "SHA384": hashes.SHA384,
+        "SHA512": hashes.SHA512,
     }
 
     @pytest.mark.parametrize(
         "vector",
         load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "DSA", "FIPS_186-3", "SigVer.rsp"),
-            load_fips_dsa_sig_vectors
-        )
+            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("-", "")
+        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']
+            backend, algorithm, vector["p"], vector["q"], vector["g"]
         )
 
         public_key = dsa.DSAPublicNumbers(
             parameter_numbers=dsa.DSAParameterNumbers(
-                vector['p'], vector['q'], vector['g']
+                vector["p"], vector["q"], vector["g"]
             ),
-            y=vector['y']
+            y=vector["y"],
         ).public_key(backend)
-        sig = encode_dss_signature(vector['r'], vector['s'])
+        sig = encode_dss_signature(vector["r"], vector["s"])
 
-        if vector['result'] == "F":
+        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)
         with pytest.raises(InvalidSignature):
-            public_key.verify(b'fakesig', b'fakemsg', hashes.SHA1())
+            public_key.verify(b"fakesig", b"fakemsg", hashes.SHA1())
 
     def test_signature_not_bytes(self, backend):
         public_key = DSA_KEY_1024.public_numbers.public_key(backend)
-        with pytest.raises(TypeError), \
-                pytest.warns(CryptographyDeprecationWarning):
+        with pytest.raises(TypeError), pytest.warns(
+            CryptographyDeprecationWarning
+        ):
             public_key.verifier(1234, hashes.SHA1())
 
     def test_use_after_finalize(self, backend):
         public_key = DSA_KEY_1024.public_numbers.public_key(backend)
         with pytest.warns(CryptographyDeprecationWarning):
-            verifier = public_key.verifier(b'fakesig', hashes.SHA1())
-        verifier.update(b'irrelevant')
+            verifier = public_key.verifier(b"fakesig", hashes.SHA1())
+        verifier.update(b"irrelevant")
         with pytest.raises(InvalidSignature):
             verifier.verify()
         with pytest.raises(AlreadyFinalized):
@@ -445,57 +472,57 @@
 
     def test_prehashed_unsupported_in_signer_ctx(self, backend):
         private_key = DSA_KEY_1024.private_key(backend)
-        with pytest.raises(TypeError), \
-                pytest.warns(CryptographyDeprecationWarning):
+        with pytest.raises(TypeError), pytest.warns(
+            CryptographyDeprecationWarning
+        ):
             private_key.signer(Prehashed(hashes.SHA1()))
 
     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())
-            )
+        with pytest.raises(TypeError), pytest.warns(
+            CryptographyDeprecationWarning
+        ):
+            public_key.verifier(b"0" * 64, Prehashed(hashes.SHA1()))
 
 
 @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}
+        "SHA1": hashes.SHA1,
+        "SHA224": hashes.SHA224,
+        "SHA256": hashes.SHA256,
+        "SHA384": hashes.SHA384,
+        "SHA512": hashes.SHA512,
+    }
 
     @pytest.mark.parametrize(
         "vector",
         load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "DSA", "FIPS_186-3", "SigGen.txt"),
-            load_fips_dsa_sig_vectors
-        )
+            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("-", "")
+        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']
+            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']
+                    vector["p"], vector["q"], vector["g"]
                 ),
-                y=vector['y']
+                y=vector["y"],
             ),
-            x=vector['x']
+            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())
+        private_key.public_key().verify(signature, vector["msg"], algorithm())
 
     def test_use_after_finalize(self, backend):
         private_key = DSA_KEY_1024.private_key(backend)
@@ -558,8 +585,7 @@
     def test_dsa_public_numbers(self):
         parameter_numbers = dsa.DSAParameterNumbers(p=1, q=2, g=3)
         public_numbers = dsa.DSAPublicNumbers(
-            y=4,
-            parameter_numbers=parameter_numbers
+            y=4, parameter_numbers=parameter_numbers
         )
         assert public_numbers.y == 4
         assert public_numbers.parameter_numbers == parameter_numbers
@@ -575,12 +601,10 @@
     def test_dsa_private_numbers(self):
         parameter_numbers = dsa.DSAParameterNumbers(p=1, q=2, g=3)
         public_numbers = dsa.DSAPublicNumbers(
-            y=4,
-            parameter_numbers=parameter_numbers
+            y=4, parameter_numbers=parameter_numbers
         )
         private_numbers = dsa.DSAPrivateNumbers(
-            x=5,
-            public_numbers=public_numbers
+            x=5, public_numbers=public_numbers
         )
         assert private_numbers.x == 5
         assert private_numbers.public_numbers == public_numbers
@@ -588,8 +612,7 @@
     def test_dsa_private_numbers_invalid_types(self):
         parameter_numbers = dsa.DSAParameterNumbers(p=1, q=2, g=3)
         public_numbers = dsa.DSAPublicNumbers(
-            y=4,
-            parameter_numbers=parameter_numbers
+            y=4, parameter_numbers=parameter_numbers
         )
         with pytest.raises(TypeError):
             dsa.DSAPrivateNumbers(x=4, public_numbers=None)
@@ -604,8 +627,7 @@
         )
 
         public_numbers = dsa.DSAPublicNumbers(
-            y=4,
-            parameter_numbers=parameter_numbers
+            y=4, parameter_numbers=parameter_numbers
         )
         assert repr(public_numbers) == (
             "<DSAPublicNumbers(y=4, parameter_numbers=<DSAParameterNumbers(p=1"
@@ -641,38 +663,26 @@
         pub = dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3))
         priv = dsa.DSAPrivateNumbers(1, pub)
         assert priv == dsa.DSAPrivateNumbers(
-            1, dsa.DSAPublicNumbers(
-                1, dsa.DSAParameterNumbers(1, 2, 3)
-            )
+            1, dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3))
         )
 
     def test_private_numbers_ne(self):
         pub = dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3))
         priv = dsa.DSAPrivateNumbers(1, pub)
         assert priv != dsa.DSAPrivateNumbers(
-            2, dsa.DSAPublicNumbers(
-                1, dsa.DSAParameterNumbers(1, 2, 3)
-            )
+            2, dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3))
         )
         assert priv != dsa.DSAPrivateNumbers(
-            1, dsa.DSAPublicNumbers(
-                2, dsa.DSAParameterNumbers(1, 2, 3)
-            )
+            1, dsa.DSAPublicNumbers(2, dsa.DSAParameterNumbers(1, 2, 3))
         )
         assert priv != dsa.DSAPrivateNumbers(
-            1, dsa.DSAPublicNumbers(
-                1, dsa.DSAParameterNumbers(2, 2, 3)
-            )
+            1, dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(2, 2, 3))
         )
         assert priv != dsa.DSAPrivateNumbers(
-            1, dsa.DSAPublicNumbers(
-                1, dsa.DSAParameterNumbers(1, 3, 3)
-            )
+            1, dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 3, 3))
         )
         assert priv != dsa.DSAPrivateNumbers(
-            1, dsa.DSAPublicNumbers(
-                1, dsa.DSAParameterNumbers(1, 2, 4)
-            )
+            1, dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 4))
         )
         assert priv != object()
 
@@ -685,26 +695,27 @@
         itertools.product(
             [
                 serialization.PrivateFormat.TraditionalOpenSSL,
-                serialization.PrivateFormat.PKCS8
+                serialization.PrivateFormat.PKCS8,
             ],
             [
                 b"s",
                 b"longerpassword",
                 b"!*$&(@#$*&($T@%_somesymbols",
                 b"\x01" * 1000,
-            ]
-        )
+            ],
+        ),
     )
     def test_private_bytes_encrypted_pem(self, backend, fmt, password):
+        skip_fips_traditional_openssl(backend, fmt)
         key_bytes = load_vectors_from_file(
             os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"),
-            lambda pemfile: pemfile.read().encode()
+            lambda pemfile: pemfile.read().encode(),
         )
         key = serialization.load_pem_private_key(key_bytes, None, backend)
         serialized = key.private_bytes(
             serialization.Encoding.PEM,
             fmt,
-            serialization.BestAvailableEncryption(password)
+            serialization.BestAvailableEncryption(password),
         )
         loaded_key = serialization.load_pem_private_key(
             serialized, password, backend
@@ -720,7 +731,7 @@
             (serialization.Encoding.DER, serialization.PrivateFormat.Raw),
             (serialization.Encoding.Raw, serialization.PrivateFormat.Raw),
             (serialization.Encoding.X962, serialization.PrivateFormat.PKCS8),
-        ]
+        ],
     )
     def test_private_bytes_rejects_invalid(self, encoding, fmt, backend):
         key = DSA_KEY_1024.private_key(backend)
@@ -733,19 +744,19 @@
             [serialization.PrivateFormat.PKCS8, b"s"],
             [serialization.PrivateFormat.PKCS8, b"longerpassword"],
             [serialization.PrivateFormat.PKCS8, b"!*$&(@#$*&($T@%_somesymbol"],
-            [serialization.PrivateFormat.PKCS8, b"\x01" * 1000]
-        ]
+            [serialization.PrivateFormat.PKCS8, b"\x01" * 1000],
+        ],
     )
     def test_private_bytes_encrypted_der(self, backend, fmt, password):
         key_bytes = load_vectors_from_file(
             os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"),
-            lambda pemfile: pemfile.read().encode()
+            lambda pemfile: pemfile.read().encode(),
         )
         key = serialization.load_pem_private_key(key_bytes, None, backend)
         serialized = key.private_bytes(
             serialization.Encoding.DER,
             fmt,
-            serialization.BestAvailableEncryption(password)
+            serialization.BestAvailableEncryption(password),
         )
         loaded_key = serialization.load_der_private_key(
             serialized, password, backend
@@ -760,27 +771,28 @@
             [
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.TraditionalOpenSSL,
-                serialization.load_pem_private_key
+                serialization.load_pem_private_key,
             ],
             [
                 serialization.Encoding.DER,
                 serialization.PrivateFormat.TraditionalOpenSSL,
-                serialization.load_der_private_key
+                serialization.load_der_private_key,
             ],
             [
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.PKCS8,
-                serialization.load_pem_private_key
+                serialization.load_pem_private_key,
             ],
             [
                 serialization.Encoding.DER,
                 serialization.PrivateFormat.PKCS8,
-                serialization.load_der_private_key
+                serialization.load_der_private_key,
             ],
-        ]
+        ],
     )
-    def test_private_bytes_unencrypted(self, backend, encoding, fmt,
-                                       loader_func):
+    def test_private_bytes_unencrypted(
+        self, backend, encoding, fmt, loader_func
+    ):
         key = DSA_KEY_1024.private_key(backend)
         serialized = key.private_bytes(
             encoding, fmt, serialization.NoEncryption()
@@ -790,6 +802,9 @@
         priv_num = key.private_numbers()
         assert loaded_priv_num == priv_num
 
+    @pytest.mark.skip_fips(
+        reason="Traditional OpenSSL key format is not supported in FIPS mode."
+    )
     @pytest.mark.parametrize(
         ("key_path", "encoding", "loader_func"),
         [
@@ -797,19 +812,19 @@
                 os.path.join(
                     "asymmetric",
                     "Traditional_OpenSSL_Serialization",
-                    "dsa.1024.pem"
+                    "dsa.1024.pem",
                 ),
                 serialization.Encoding.PEM,
-                serialization.load_pem_private_key
+                serialization.load_pem_private_key,
             ],
             [
                 os.path.join(
                     "asymmetric", "DER_Serialization", "dsa.1024.der"
                 ),
                 serialization.Encoding.DER,
-                serialization.load_der_private_key
+                serialization.load_der_private_key,
             ],
-        ]
+        ],
     )
     def test_private_bytes_traditional_openssl_unencrypted(
         self, backend, key_path, encoding, loader_func
@@ -821,7 +836,7 @@
         serialized = key.private_bytes(
             encoding,
             serialization.PrivateFormat.TraditionalOpenSSL,
-            serialization.NoEncryption()
+            serialization.NoEncryption(),
         )
         assert serialized == key_bytes
 
@@ -831,7 +846,7 @@
             key.private_bytes(
                 serialization.Encoding.DER,
                 serialization.PrivateFormat.TraditionalOpenSSL,
-                serialization.BestAvailableEncryption(b"password")
+                serialization.BestAvailableEncryption(b"password"),
             )
 
     def test_private_bytes_invalid_encoding(self, backend):
@@ -839,13 +854,13 @@
             os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"),
             lambda pemfile: serialization.load_pem_private_key(
                 pemfile.read().encode(), None, backend
-            )
+            ),
         )
         with pytest.raises(TypeError):
             key.private_bytes(
                 "notencoding",
                 serialization.PrivateFormat.PKCS8,
-                serialization.NoEncryption()
+                serialization.NoEncryption(),
             )
 
     def test_private_bytes_invalid_format(self, backend):
@@ -853,13 +868,13 @@
             os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"),
             lambda pemfile: serialization.load_pem_private_key(
                 pemfile.read().encode(), None, backend
-            )
+            ),
         )
         with pytest.raises(TypeError):
             key.private_bytes(
                 serialization.Encoding.PEM,
                 "invalidformat",
-                serialization.NoEncryption()
+                serialization.NoEncryption(),
             )
 
     def test_private_bytes_invalid_encryption_algorithm(self, backend):
@@ -867,13 +882,13 @@
             os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"),
             lambda pemfile: serialization.load_pem_private_key(
                 pemfile.read().encode(), None, backend
-            )
+            ),
         )
         with pytest.raises(TypeError):
             key.private_bytes(
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.TraditionalOpenSSL,
-                "notanencalg"
+                "notanencalg",
             )
 
     def test_private_bytes_unsupported_encryption_type(self, backend):
@@ -881,13 +896,13 @@
             os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"),
             lambda pemfile: serialization.load_pem_private_key(
                 pemfile.read().encode(), None, backend
-            )
+            ),
         )
         with pytest.raises(ValueError):
             key.private_bytes(
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.TraditionalOpenSSL,
-                DummyKeySerializationEncryption()
+                DummyKeySerializationEncryption(),
             )
 
 
@@ -901,32 +916,36 @@
                 os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pub.pem"),
                 serialization.load_pem_public_key,
                 serialization.Encoding.PEM,
-            ), (
+            ),
+            (
                 os.path.join(
                     "asymmetric",
                     "DER_Serialization",
-                    "unenc-dsa-pkcs8.pub.der"
+                    "unenc-dsa-pkcs8.pub.der",
                 ),
                 serialization.load_der_public_key,
                 serialization.Encoding.DER,
-            )
-        ]
+            ),
+        ],
     )
-    def test_public_bytes_match(self, key_path, loader_func, encoding,
-                                backend):
+    def test_public_bytes_match(
+        self, key_path, loader_func, encoding, backend
+    ):
         key_bytes = load_vectors_from_file(
             key_path, lambda pemfile: pemfile.read(), mode="rb"
         )
         key = loader_func(key_bytes, backend)
         serialized = key.public_bytes(
-            encoding, serialization.PublicFormat.SubjectPublicKeyInfo,
+            encoding,
+            serialization.PublicFormat.SubjectPublicKeyInfo,
         )
         assert serialized == key_bytes
 
     def test_public_bytes_openssh(self, backend):
         key_bytes = load_vectors_from_file(
             os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pub.pem"),
-            lambda pemfile: pemfile.read(), mode="rb"
+            lambda pemfile: pemfile.read(),
+            mode="rb",
         )
         key = serialization.load_pem_public_key(key_bytes, backend)
 
@@ -950,8 +969,7 @@
         key = DSA_KEY_2048.private_key(backend).public_key()
         with pytest.raises(TypeError):
             key.public_bytes(
-                "notencoding",
-                serialization.PublicFormat.SubjectPublicKeyInfo
+                "notencoding", serialization.PublicFormat.SubjectPublicKeyInfo
             )
 
     def test_public_bytes_invalid_format(self, backend):
@@ -971,22 +989,25 @@
         [
             (
                 serialization.Encoding.Raw,
-                serialization.PublicFormat.SubjectPublicKeyInfo
+                serialization.PublicFormat.SubjectPublicKeyInfo,
             ),
             (serialization.Encoding.Raw, serialization.PublicFormat.PKCS1),
-        ] + list(itertools.product(
-            [
-                serialization.Encoding.Raw,
-                serialization.Encoding.X962,
-                serialization.Encoding.PEM,
-                serialization.Encoding.DER
-            ],
-            [
-                serialization.PublicFormat.Raw,
-                serialization.PublicFormat.UncompressedPoint,
-                serialization.PublicFormat.CompressedPoint
-            ]
-        ))
+        ]
+        + list(
+            itertools.product(
+                [
+                    serialization.Encoding.Raw,
+                    serialization.Encoding.X962,
+                    serialization.Encoding.PEM,
+                    serialization.Encoding.DER,
+                ],
+                [
+                    serialization.PublicFormat.Raw,
+                    serialization.PublicFormat.UncompressedPoint,
+                    serialization.PublicFormat.CompressedPoint,
+                ],
+            )
+        ),
     )
     def test_public_bytes_rejects_invalid(self, encoding, fmt, backend):
         key = DSA_KEY_2048.private_key(backend).public_key()
diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py
index 7a6d6af..8361306 100644
--- a/tests/hazmat/primitives/test_ec.py
+++ b/tests/hazmat/primitives/test_ec.py
@@ -11,23 +11,29 @@
 
 import pytest
 
-from cryptography import exceptions, utils
+from cryptography import exceptions, utils, x509
 from cryptography.hazmat.backends.interfaces import (
-    EllipticCurveBackend, PEMSerializationBackend
+    EllipticCurveBackend,
+    PEMSerializationBackend,
 )
 from cryptography.hazmat.primitives import hashes, serialization
 from cryptography.hazmat.primitives.asymmetric import ec
 from cryptography.hazmat.primitives.asymmetric.utils import (
-    Prehashed, encode_dss_signature
+    Prehashed,
+    encode_dss_signature,
 )
 from cryptography.utils import CryptographyDeprecationWarning
 
 from .fixtures_ec import EC_KEY_SECP384R1
+from .utils import skip_fips_traditional_openssl
 from ...doubles import DummyKeySerializationEncryption
 from ...utils import (
-    load_fips_ecdsa_key_pair_vectors, load_fips_ecdsa_signing_vectors,
-    load_kasvs_ecdh_vectors, load_nist_vectors, load_vectors_from_file,
-    raises_unsupported_algorithm
+    load_fips_ecdsa_key_pair_vectors,
+    load_fips_ecdsa_signing_vectors,
+    load_kasvs_ecdh_vectors,
+    load_nist_vectors,
+    load_vectors_from_file,
+    raises_unsupported_algorithm,
 )
 
 _HASH_TYPES = {
@@ -41,11 +47,10 @@
 
 def _skip_ecdsa_vector(backend, curve_type, hash_type):
     if not backend.elliptic_curve_signature_algorithm_supported(
-        ec.ECDSA(hash_type()),
-        curve_type()
+        ec.ECDSA(hash_type()), curve_type()
     ):
         pytest.skip(
-            "ECDSA not supported with this hash {0} and curve {1}".format(
+            "ECDSA not supported with this hash {} and curve {}.".format(
                 hash_type().name, curve_type().name
             )
         )
@@ -54,7 +59,7 @@
 def _skip_curve_unsupported(backend, curve):
     if not backend.elliptic_curve_supported(curve):
         pytest.skip(
-            "Curve {0} is not supported by this backend {1}".format(
+            "Curve {} is not supported by this backend {}".format(
                 curve.name, backend
             )
         )
@@ -65,12 +70,18 @@
         algorithm, curve
     ):
         pytest.skip(
-            "Exchange with {0} curve is not supported by {1}".format(
+            "Exchange with {} curve is not supported by {}".format(
                 curve.name, backend
             )
         )
 
 
+def test_get_curve_for_oid():
+    assert ec.get_curve_for_oid(ec.EllipticCurveOID.SECP256R1) == ec.SECP256R1
+    with pytest.raises(LookupError):
+        ec.get_curve_for_oid(x509.ObjectIdentifier("1.1.1.1"))
+
+
 @utils.register_interface(ec.EllipticCurve)
 class DummyCurve(object):
     name = "dummy-curve"
@@ -120,10 +131,10 @@
     _skip_curve_unsupported(backend, curve)
 
     with pytest.raises(TypeError):
-        ec.derive_private_key('one', curve, backend)
+        ec.derive_private_key("one", curve, backend)
 
     with pytest.raises(TypeError):
-        ec.derive_private_key(10, 'five', backend)
+        ec.derive_private_key(10, "five", backend)
 
     with pytest.raises(ValueError):
         ec.derive_private_key(-7, curve, backend)
@@ -131,10 +142,7 @@
 
 def test_ec_numbers():
     numbers = ec.EllipticCurvePrivateNumbers(
-        1,
-        ec.EllipticCurvePublicNumbers(
-            2, 3, DummyCurve()
-        )
+        1, ec.EllipticCurvePublicNumbers(2, 3, DummyCurve())
     )
 
     assert numbers.private_value == 1
@@ -150,7 +158,7 @@
         (1, None, 3, DummyCurve()),
         (1, 2, None, DummyCurve()),
         (1, 2, 3, None),
-    ]
+    ],
 )
 def test_invalid_ec_numbers_args(private_value, x, y, curve):
     with pytest.raises(TypeError):
@@ -167,15 +175,13 @@
 def test_encode_point():
     # secp256r1 point
     x = int(
-        '233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22aec',
-        16
+        "233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22aec", 16
     )
     y = int(
-        '3ea2c10a84153862be4ec82940f0543f9ba866af9751a6ee79d38460b35f442e',
-        16
+        "3ea2c10a84153862be4ec82940f0543f9ba866af9751a6ee79d38460b35f442e", 16
     )
     pn = ec.EllipticCurvePublicNumbers(x, y, ec.SECP256R1())
-    with pytest.warns(utils.DeprecatedIn25):
+    with pytest.warns(utils.PersistentlyDeprecated2019):
         data = pn.encode_point()
     assert data == binascii.unhexlify(
         "04233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22ae"
@@ -194,12 +200,10 @@
             ec.SECP256R1(), data
         )
     assert pn.x == int(
-        '233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22aec',
-        16
+        "233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22aec", 16
     )
     assert pn.y == int(
-        '3ea2c10a84153862be4ec82940f0543f9ba866af9751a6ee79d38460b35f442e',
-        16
+        "3ea2c10a84153862be4ec82940f0543f9ba866af9751a6ee79d38460b35f442e", 16
     )
 
 
@@ -277,34 +281,35 @@
 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
-            ),
-            _HASH_TYPES.values()
-        ))
+        list(
+            itertools.product(
+                load_vectors_from_file(
+                    os.path.join(
+                        "asymmetric", "ECDSA", "FIPS_186-3", "KeyPair.rsp"
+                    ),
+                    load_fips_ecdsa_key_pair_vectors,
+                ),
+                _HASH_TYPES.values(),
+            )
+        ),
     )
     def test_with_numbers(self, backend, vector, hash_type):
-        curve_type = ec._CURVE_TYPES[vector['curve']]
+        curve_type = ec._CURVE_TYPES[vector["curve"]]
 
         _skip_ecdsa_vector(backend, curve_type, hash_type)
 
         key = ec.EllipticCurvePrivateNumbers(
-            vector['d'],
+            vector["d"],
             ec.EllipticCurvePublicNumbers(
-                vector['x'],
-                vector['y'],
-                curve_type()
-            )
+                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 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
 
 
@@ -312,27 +317,28 @@
 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
-            ),
-            _HASH_TYPES.values()
-        ))
+        list(
+            itertools.product(
+                load_vectors_from_file(
+                    os.path.join(
+                        "asymmetric", "ECDSA", "FIPS_186-3", "KeyPair.rsp"
+                    ),
+                    load_fips_ecdsa_key_pair_vectors,
+                ),
+                _HASH_TYPES.values(),
+            )
+        ),
     )
     def test_signing_with_example_keys(self, backend, vector, hash_type):
-        curve_type = ec._CURVE_TYPES[vector['curve']]
+        curve_type = ec._CURVE_TYPES[vector["curve"]]
 
         _skip_ecdsa_vector(backend, curve_type, hash_type)
 
         key = ec.EllipticCurvePrivateNumbers(
-            vector['d'],
+            vector["d"],
             ec.EllipticCurvePublicNumbers(
-                vector['x'],
-                vector['y'],
-                curve_type()
-            )
+                vector["x"], vector["y"], curve_type()
+            ),
         ).private_key(backend)
         assert key
 
@@ -349,9 +355,7 @@
         verifier.update(b"YELLOW SUBMARINE")
         verifier.verify()
 
-    @pytest.mark.parametrize(
-        "curve", ec._CURVE_TYPES.values()
-    )
+    @pytest.mark.parametrize("curve", ec._CURVE_TYPES.values())
     def test_generate_vector_curves(self, backend, curve):
         _skip_curve_unsupported(backend, curve())
 
@@ -371,10 +375,12 @@
         ):
             ec.generate_private_key(DummyCurve(), backend)
 
-        assert backend.elliptic_curve_signature_algorithm_supported(
-            ec.ECDSA(hashes.SHA256()),
-            DummyCurve()
-        ) is False
+        assert (
+            backend.elliptic_curve_signature_algorithm_supported(
+                ec.ECDSA(hashes.SHA256()), DummyCurve()
+            )
+            is False
+        )
 
     def test_unknown_signature_algoritm(self, backend):
         _skip_curve_unsupported(backend, ec.SECP192R1())
@@ -403,10 +409,12 @@
                 b"signature", b"data", DummySignatureAlgorithm()
             )
 
-        assert backend.elliptic_curve_signature_algorithm_supported(
-            DummySignatureAlgorithm(),
-            ec.SECP192R1()
-        ) is False
+        assert (
+            backend.elliptic_curve_signature_algorithm_supported(
+                DummySignatureAlgorithm(), ec.SECP192R1()
+            )
+            is False
+        )
 
     def test_load_invalid_ec_key_from_numbers(self, backend):
         _skip_curve_unsupported(backend, ec.SECP256R1())
@@ -417,7 +425,7 @@
                 47250808410327023131573602008345894927686381772325561185532964,
                 1120253292479243545483756778742719537373113335231773536789915,
                 ec.SECP256R1(),
-            )
+            ),
         )
         with pytest.raises(ValueError):
             numbers.private_key(backend)
@@ -428,7 +436,7 @@
                 -4725080841032702313157360200834589492768638177232556118553296,
                 1120253292479243545483756778742719537373113335231773536789915,
                 ec.SECP256R1(),
-            )
+            ),
         )
         with pytest.raises(ValueError):
             numbers.private_key(backend)
@@ -439,7 +447,7 @@
                 47250808410327023131573602008345894927686381772325561185532964,
                 -1120253292479243545483756778742719537373113335231773536789915,
                 ec.SECP256R1(),
-            )
+            ),
         )
         with pytest.raises(ValueError):
             numbers.private_key(backend)
@@ -449,26 +457,38 @@
 
         # Bad X coordinate
         numbers = ec.EllipticCurvePublicNumbers(
-            int("000003647356b91f8ace114c7247ecf4f4a622553fc025e04a178f179ef27"
+            int(
+                "000003647356b91f8ace114c7247ecf4f4a622553fc025e04a178f179ef27"
                 "9090c184af678a4c78f635483bdd8aa544851c6ef291c1f0d6a241ebfd145"
-                "77d1d30d9903ce", 16),
-            int("000001499bc7e079322ea0fcfbd6b40103fa6a1536c2257b182db0df4b369"
+                "77d1d30d9903ce",
+                16,
+            ),
+            int(
+                "000001499bc7e079322ea0fcfbd6b40103fa6a1536c2257b182db0df4b369"
                 "6ec643adf100eb4f2025d1b873f82e5a475d6e4400ba777090eeb4563a115"
-                "09e4c87319dc26", 16),
-            ec.SECP521R1()
+                "09e4c87319dc26",
+                16,
+            ),
+            ec.SECP521R1(),
         )
         with pytest.raises(ValueError):
             numbers.public_key(backend)
 
         # Bad Y coordinate
         numbers = ec.EllipticCurvePublicNumbers(
-            int("0000019aadc221cc0525118ab6d5aa1f64720603de0be128cbfea0b381ad8"
+            int(
+                "0000019aadc221cc0525118ab6d5aa1f64720603de0be128cbfea0b381ad8"
                 "02a2facc6370bb58cf88b3f0c692bc654ee19d6cad198f10d4b681b396f20"
-                "d2e40603fa945b", 16),
-            int("0000025da392803a320717a08d4cb3dea932039badff363b71bdb8064e726"
+                "d2e40603fa945b",
+                16,
+            ),
+            int(
+                "0000025da392803a320717a08d4cb3dea932039badff363b71bdb8064e726"
                 "6c7f4f4b748d4d425347fc33e3885d34b750fa7fcd5691f4d90c89522ce33"
-                "feff5db10088a5", 16),
-            ec.SECP521R1()
+                "feff5db10088a5",
+                16,
+            ),
+            ec.SECP521R1(),
         )
         with pytest.raises(ValueError):
             numbers.public_key(backend)
@@ -478,71 +498,54 @@
         itertools.chain(
             load_vectors_from_file(
                 os.path.join(
-                    "asymmetric", "ECDSA", "FIPS_186-3", "SigGen.txt"),
-                load_fips_ecdsa_signing_vectors
+                    "asymmetric", "ECDSA", "FIPS_186-3", "SigGen.txt"
+                ),
+                load_fips_ecdsa_signing_vectors,
             ),
             load_vectors_from_file(
-                os.path.join(
-                    "asymmetric", "ECDSA", "SECP256K1", "SigGen.txt"),
-                load_fips_ecdsa_signing_vectors
+                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']]
+        hash_type = _HASH_TYPES[vector["digest_algorithm"]]
+        curve_type = ec._CURVE_TYPES[vector["curve"]]
 
         _skip_ecdsa_vector(backend, curve_type, hash_type)
 
         key = ec.EllipticCurvePublicNumbers(
-            vector['x'],
-            vector['y'],
-            curve_type()
+            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(
-            os.path.join(
-                "asymmetric", "ECDSA", "FIPS_186-3", "SigVer.rsp"),
-            load_fips_ecdsa_signing_vectors
-        )
+            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']]
+        hash_type = _HASH_TYPES[vector["digest_algorithm"]]
+        curve_type = ec._CURVE_TYPES[vector["curve"]]
 
         _skip_ecdsa_vector(backend, curve_type, hash_type)
 
         key = ec.EllipticCurvePublicNumbers(
-            vector['x'],
-            vector['y'],
-            curve_type()
+            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())
-                )
+                key.verify(signature, vector["message"], ec.ECDSA(hash_type()))
         else:
-            key.verify(
-                signature,
-                vector['message'],
-                ec.ECDSA(hash_type())
-            )
+            key.verify(signature, vector["message"], ec.ECDSA(hash_type()))
 
     def test_sign(self, backend):
         _skip_curve_unsupported(backend, ec.SECP256R1())
@@ -595,9 +598,7 @@
         h.update(message)
         data = h.finalize()
         public_key = private_key.public_key()
-        public_key.verify(
-            signature, data, ec.ECDSA(Prehashed(hashes.SHA1()))
-        )
+        public_key.verify(signature, data, ec.ECDSA(Prehashed(hashes.SHA1())))
 
     def test_verify_prehashed_digest_mismatch(self, backend):
         _skip_curve_unsupported(backend, ec.SECP256R1())
@@ -615,20 +616,19 @@
     def test_prehashed_unsupported_in_signer_ctx(self, backend):
         _skip_curve_unsupported(backend, ec.SECP256R1())
         private_key = ec.generate_private_key(ec.SECP256R1(), backend)
-        with pytest.raises(TypeError), \
-                pytest.warns(CryptographyDeprecationWarning):
+        with pytest.raises(TypeError), pytest.warns(
+            CryptographyDeprecationWarning
+        ):
             private_key.signer(ec.ECDSA(Prehashed(hashes.SHA1())))
 
     def test_prehashed_unsupported_in_verifier_ctx(self, backend):
         _skip_curve_unsupported(backend, ec.SECP256R1())
         private_key = ec.generate_private_key(ec.SECP256R1(), backend)
         public_key = private_key.public_key()
-        with pytest.raises(TypeError), \
-                pytest.warns(CryptographyDeprecationWarning):
-            public_key.verifier(
-                b"0" * 64,
-                ec.ECDSA(Prehashed(hashes.SHA1()))
-            )
+        with pytest.raises(TypeError), pytest.warns(
+            CryptographyDeprecationWarning
+        ):
+            public_key.verifier(b"0" * 64, ec.ECDSA(Prehashed(hashes.SHA1())))
 
 
 class TestECNumbersEquality(object):
@@ -676,28 +676,28 @@
         itertools.product(
             [
                 serialization.PrivateFormat.TraditionalOpenSSL,
-                serialization.PrivateFormat.PKCS8
+                serialization.PrivateFormat.PKCS8,
             ],
             [
                 b"s",
                 b"longerpassword",
                 b"!*$&(@#$*&($T@%_somesymbols",
                 b"\x01" * 1000,
-            ]
-        )
+            ],
+        ),
     )
     def test_private_bytes_encrypted_pem(self, backend, fmt, password):
+        skip_fips_traditional_openssl(backend, fmt)
         _skip_curve_unsupported(backend, ec.SECP256R1())
         key_bytes = load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "PKCS8", "ec_private_key.pem"),
-            lambda pemfile: pemfile.read().encode()
+            os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
+            lambda pemfile: pemfile.read().encode(),
         )
         key = serialization.load_pem_private_key(key_bytes, None, backend)
         serialized = key.private_bytes(
             serialization.Encoding.PEM,
             fmt,
-            serialization.BestAvailableEncryption(password)
+            serialization.BestAvailableEncryption(password),
         )
         loaded_key = serialization.load_pem_private_key(
             serialized, password, backend
@@ -713,7 +713,7 @@
             (serialization.Encoding.DER, serialization.PrivateFormat.Raw),
             (serialization.Encoding.Raw, serialization.PrivateFormat.Raw),
             (serialization.Encoding.X962, serialization.PrivateFormat.PKCS8),
-        ]
+        ],
     )
     def test_private_bytes_rejects_invalid(self, encoding, fmt, backend):
         _skip_curve_unsupported(backend, ec.SECP256R1())
@@ -727,21 +727,20 @@
             [serialization.PrivateFormat.PKCS8, b"s"],
             [serialization.PrivateFormat.PKCS8, b"longerpassword"],
             [serialization.PrivateFormat.PKCS8, b"!*$&(@#$*&($T@%_somesymbol"],
-            [serialization.PrivateFormat.PKCS8, b"\x01" * 1000]
-        ]
+            [serialization.PrivateFormat.PKCS8, b"\x01" * 1000],
+        ],
     )
     def test_private_bytes_encrypted_der(self, backend, fmt, password):
         _skip_curve_unsupported(backend, ec.SECP256R1())
         key_bytes = load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "PKCS8", "ec_private_key.pem"),
-            lambda pemfile: pemfile.read().encode()
+            os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
+            lambda pemfile: pemfile.read().encode(),
         )
         key = serialization.load_pem_private_key(key_bytes, None, backend)
         serialized = key.private_bytes(
             serialization.Encoding.DER,
             fmt,
-            serialization.BestAvailableEncryption(password)
+            serialization.BestAvailableEncryption(password),
         )
         loaded_key = serialization.load_der_private_key(
             serialized, password, backend
@@ -756,32 +755,32 @@
             [
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.TraditionalOpenSSL,
-                serialization.load_pem_private_key
+                serialization.load_pem_private_key,
             ],
             [
                 serialization.Encoding.DER,
                 serialization.PrivateFormat.TraditionalOpenSSL,
-                serialization.load_der_private_key
+                serialization.load_der_private_key,
             ],
             [
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.PKCS8,
-                serialization.load_pem_private_key
+                serialization.load_pem_private_key,
             ],
             [
                 serialization.Encoding.DER,
                 serialization.PrivateFormat.PKCS8,
-                serialization.load_der_private_key
+                serialization.load_der_private_key,
             ],
-        ]
+        ],
     )
-    def test_private_bytes_unencrypted(self, backend, encoding, fmt,
-                                       loader_func):
+    def test_private_bytes_unencrypted(
+        self, backend, encoding, fmt, loader_func
+    ):
         _skip_curve_unsupported(backend, ec.SECP256R1())
         key_bytes = load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "PKCS8", "ec_private_key.pem"),
-            lambda pemfile: pemfile.read().encode()
+            os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
+            lambda pemfile: pemfile.read().encode(),
         )
         key = serialization.load_pem_private_key(key_bytes, None, backend)
         serialized = key.private_bytes(
@@ -792,6 +791,9 @@
         priv_num = key.private_numbers()
         assert loaded_priv_num == priv_num
 
+    @pytest.mark.skip_fips(
+        reason="Traditional OpenSSL key format is not supported in FIPS mode."
+    )
     @pytest.mark.parametrize(
         ("key_path", "encoding", "loader_func"),
         [
@@ -800,16 +802,16 @@
                     "asymmetric", "PEM_Serialization", "ec_private_key.pem"
                 ),
                 serialization.Encoding.PEM,
-                serialization.load_pem_private_key
+                serialization.load_pem_private_key,
             ],
             [
                 os.path.join(
                     "asymmetric", "DER_Serialization", "ec_private_key.der"
                 ),
                 serialization.Encoding.DER,
-                serialization.load_der_private_key
+                serialization.load_der_private_key,
             ],
-        ]
+        ],
     )
     def test_private_bytes_traditional_openssl_unencrypted(
         self, backend, key_path, encoding, loader_func
@@ -822,103 +824,97 @@
         serialized = key.private_bytes(
             encoding,
             serialization.PrivateFormat.TraditionalOpenSSL,
-            serialization.NoEncryption()
+            serialization.NoEncryption(),
         )
         assert serialized == key_bytes
 
     def test_private_bytes_traditional_der_encrypted_invalid(self, backend):
         _skip_curve_unsupported(backend, ec.SECP256R1())
         key = load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "PKCS8", "ec_private_key.pem"),
+            os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
             lambda pemfile: serialization.load_pem_private_key(
                 pemfile.read().encode(), None, backend
-            )
+            ),
         )
         with pytest.raises(ValueError):
             key.private_bytes(
                 serialization.Encoding.DER,
                 serialization.PrivateFormat.TraditionalOpenSSL,
-                serialization.BestAvailableEncryption(b"password")
+                serialization.BestAvailableEncryption(b"password"),
             )
 
     def test_private_bytes_invalid_encoding(self, backend):
         _skip_curve_unsupported(backend, ec.SECP256R1())
         key = load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "PKCS8", "ec_private_key.pem"),
+            os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
             lambda pemfile: serialization.load_pem_private_key(
                 pemfile.read().encode(), None, backend
-            )
+            ),
         )
         with pytest.raises(TypeError):
             key.private_bytes(
                 "notencoding",
                 serialization.PrivateFormat.PKCS8,
-                serialization.NoEncryption()
+                serialization.NoEncryption(),
             )
 
     def test_private_bytes_invalid_format(self, backend):
         _skip_curve_unsupported(backend, ec.SECP256R1())
         key = load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "PKCS8", "ec_private_key.pem"),
+            os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
             lambda pemfile: serialization.load_pem_private_key(
                 pemfile.read().encode(), None, backend
-            )
+            ),
         )
         with pytest.raises(TypeError):
             key.private_bytes(
                 serialization.Encoding.PEM,
                 "invalidformat",
-                serialization.NoEncryption()
+                serialization.NoEncryption(),
             )
 
     def test_private_bytes_invalid_encryption_algorithm(self, backend):
         _skip_curve_unsupported(backend, ec.SECP256R1())
         key = load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "PKCS8", "ec_private_key.pem"),
+            os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
             lambda pemfile: serialization.load_pem_private_key(
                 pemfile.read().encode(), None, backend
-            )
+            ),
         )
         with pytest.raises(TypeError):
             key.private_bytes(
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.TraditionalOpenSSL,
-                "notanencalg"
+                "notanencalg",
             )
 
     def test_private_bytes_unsupported_encryption_type(self, backend):
         _skip_curve_unsupported(backend, ec.SECP256R1())
         key = load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "PKCS8", "ec_private_key.pem"),
+            os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
             lambda pemfile: serialization.load_pem_private_key(
                 pemfile.read().encode(), None, backend
-            )
+            ),
         )
         with pytest.raises(ValueError):
             key.private_bytes(
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.TraditionalOpenSSL,
-                DummyKeySerializationEncryption()
+                DummyKeySerializationEncryption(),
             )
 
     def test_public_bytes_from_derived_public_key(self, backend):
         _skip_curve_unsupported(backend, ec.SECP256R1())
         key = load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "PKCS8", "ec_private_key.pem"),
+            os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
             lambda pemfile: serialization.load_pem_private_key(
                 pemfile.read().encode(), None, backend
-            )
+            ),
         )
         public = key.public_key()
         pem = public.public_bytes(
             serialization.Encoding.PEM,
-            serialization.PublicFormat.SubjectPublicKeyInfo
+            serialization.PublicFormat.SubjectPublicKeyInfo,
         )
         parsed_public = serialization.load_pem_public_key(pem, backend)
         assert parsed_public
@@ -936,24 +932,27 @@
                 ),
                 serialization.load_pem_public_key,
                 serialization.Encoding.PEM,
-            ), (
+            ),
+            (
                 os.path.join(
                     "asymmetric", "DER_Serialization", "ec_public_key.der"
                 ),
                 serialization.load_der_public_key,
                 serialization.Encoding.DER,
-            )
-        ]
+            ),
+        ],
     )
-    def test_public_bytes_match(self, key_path, loader_func, encoding,
-                                backend):
+    def test_public_bytes_match(
+        self, key_path, loader_func, encoding, backend
+    ):
         _skip_curve_unsupported(backend, ec.SECP256R1())
         key_bytes = load_vectors_from_file(
             key_path, lambda pemfile: pemfile.read(), mode="rb"
         )
         key = loader_func(key_bytes, backend)
         serialized = key.public_bytes(
-            encoding, serialization.PublicFormat.SubjectPublicKeyInfo,
+            encoding,
+            serialization.PublicFormat.SubjectPublicKeyInfo,
         )
         assert serialized == key_bytes
 
@@ -965,7 +964,8 @@
             os.path.join(
                 "asymmetric", "PEM_Serialization", "ec_public_key.pem"
             ),
-            lambda pemfile: pemfile.read(), mode="rb"
+            lambda pemfile: pemfile.read(),
+            mode="rb",
         )
         key = serialization.load_pem_public_key(key_bytes, backend)
 
@@ -982,7 +982,7 @@
         with pytest.raises(ValueError):
             key.public_bytes(
                 serialization.Encoding.OpenSSH,
-                serialization.PublicFormat.OpenSSH
+                serialization.PublicFormat.OpenSSH,
             )
 
     def test_public_bytes_invalid_encoding(self, backend):
@@ -993,35 +993,37 @@
             ),
             lambda pemfile: serialization.load_pem_public_key(
                 pemfile.read().encode(), backend
-            )
+            ),
         )
         with pytest.raises(TypeError):
             key.public_bytes(
-                "notencoding",
-                serialization.PublicFormat.SubjectPublicKeyInfo
+                "notencoding", serialization.PublicFormat.SubjectPublicKeyInfo
             )
 
     @pytest.mark.parametrize(
         ("encoding", "fmt"),
-        list(itertools.product(
-            [
-                serialization.Encoding.Raw,
-                serialization.Encoding.X962,
-                serialization.Encoding.PEM,
-                serialization.Encoding.DER
-            ],
-            [
-                serialization.PublicFormat.Raw,
-            ]
-        )) + list(itertools.product(
-            [serialization.Encoding.Raw],
-            [
-                serialization.PublicFormat.SubjectPublicKeyInfo,
-                serialization.PublicFormat.PKCS1,
-                serialization.PublicFormat.UncompressedPoint,
-                serialization.PublicFormat.CompressedPoint,
-            ]
-        ))
+        list(
+            itertools.product(
+                [
+                    serialization.Encoding.Raw,
+                    serialization.Encoding.X962,
+                    serialization.Encoding.PEM,
+                    serialization.Encoding.DER,
+                ],
+                [serialization.PublicFormat.Raw],
+            )
+        )
+        + list(
+            itertools.product(
+                [serialization.Encoding.Raw],
+                [
+                    serialization.PublicFormat.SubjectPublicKeyInfo,
+                    serialization.PublicFormat.PKCS1,
+                    serialization.PublicFormat.UncompressedPoint,
+                    serialization.PublicFormat.CompressedPoint,
+                ],
+            )
+        ),
     )
     def test_public_bytes_rejects_invalid(self, encoding, fmt, backend):
         _skip_curve_unsupported(backend, ec.SECP256R1())
@@ -1037,7 +1039,7 @@
             ),
             lambda pemfile: serialization.load_pem_public_key(
                 pemfile.read().encode(), backend
-            )
+            ),
         )
         with pytest.raises(TypeError):
             key.public_bytes(serialization.Encoding.PEM, "invalidformat")
@@ -1050,7 +1052,7 @@
             ),
             lambda pemfile: serialization.load_pem_public_key(
                 pemfile.read().encode(), backend
-            )
+            ),
         )
         with pytest.raises(ValueError):
             key.public_bytes(
@@ -1061,14 +1063,14 @@
         "vector",
         load_vectors_from_file(
             os.path.join("asymmetric", "EC", "compressed_points.txt"),
-            load_nist_vectors
-        )
+            load_nist_vectors,
+        ),
     )
-    def test_from_encoded_point_compressed(self, vector):
-        curve = {
-            b"SECP256R1": ec.SECP256R1(),
-            b"SECP256K1": ec.SECP256K1(),
-        }[vector["curve"]]
+    def test_from_encoded_point_compressed(self, vector, backend):
+        curve = {b"SECP256R1": ec.SECP256R1(), b"SECP256K1": ec.SECP256K1()}[
+            vector["curve"]
+        ]
+        _skip_curve_unsupported(backend, curve)
         point = binascii.unhexlify(vector["point"])
         pn = ec.EllipticCurvePublicKey.from_encoded_point(curve, point)
         public_num = pn.public_numbers()
@@ -1096,12 +1098,12 @@
             ec.SECP256R1(), uncompressed_point
         )
         assert pn.public_numbers().x == int(
-            '7399336a9edf2197c2f8eb3d39aed9c34a66e45d918a07dc7684c42c9b37ac68',
-            16
+            "7399336a9edf2197c2f8eb3d39aed9c34a66e45d918a07dc7684c42c9b37ac68",
+            16,
         )
         assert pn.public_numbers().y == int(
-            '6699ececc4f5f0d756d3c450708a0694eb0a07a68b805070b40b058d27271f6d',
-            16
+            "6699ececc4f5f0d756d3c450708a0694eb0a07a68b805070b40b058d27271f6d",
+            16,
         )
 
     def test_from_encoded_point_invalid_length(self):
@@ -1117,9 +1119,7 @@
 
     def test_from_encoded_point_empty_byte_string(self):
         with pytest.raises(ValueError):
-            ec.EllipticCurvePublicKey.from_encoded_point(
-                ec.SECP384R1(), b""
-            )
+            ec.EllipticCurvePublicKey.from_encoded_point(ec.SECP384R1(), b"")
 
     def test_from_encoded_point_not_a_curve(self):
         with pytest.raises(TypeError):
@@ -1141,31 +1141,37 @@
         "vector",
         load_vectors_from_file(
             os.path.join("asymmetric", "EC", "compressed_points.txt"),
-            load_nist_vectors
-        )
+            load_nist_vectors,
+        ),
     )
     def test_serialize_point(self, vector, backend):
-        curve = {
-            b"SECP256R1": ec.SECP256R1(),
-            b"SECP256K1": ec.SECP256K1(),
-        }[vector["curve"]]
+        curve = {b"SECP256R1": ec.SECP256R1(), b"SECP256K1": ec.SECP256K1()}[
+            vector["curve"]
+        ]
+        _skip_curve_unsupported(backend, curve)
         point = binascii.unhexlify(vector["point"])
         key = ec.EllipticCurvePublicKey.from_encoded_point(curve, point)
         key2 = ec.EllipticCurvePublicKey.from_encoded_point(
             curve,
             key.public_bytes(
                 serialization.Encoding.X962,
-                serialization.PublicFormat.UncompressedPoint
-            )
+                serialization.PublicFormat.UncompressedPoint,
+            ),
         )
-        assert key.public_bytes(
-            serialization.Encoding.X962,
-            serialization.PublicFormat.CompressedPoint
-        ) == point
-        assert key2.public_bytes(
-            serialization.Encoding.X962,
-            serialization.PublicFormat.CompressedPoint
-        ) == point
+        assert (
+            key.public_bytes(
+                serialization.Encoding.X962,
+                serialization.PublicFormat.CompressedPoint,
+            )
+            == point
+        )
+        assert (
+            key2.public_bytes(
+                serialization.Encoding.X962,
+                serialization.PublicFormat.CompressedPoint,
+            )
+            == point
+        )
 
 
 @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
@@ -1174,8 +1180,9 @@
         _skip_curve_unsupported(backend, ec.SECP256R1())
         key = ec.generate_private_key(ec.SECP256R1(), backend)
         public_key = key.public_key()
-        with pytest.raises(TypeError), \
-                pytest.warns(CryptographyDeprecationWarning):
+        with pytest.raises(TypeError), pytest.warns(
+            CryptographyDeprecationWarning
+        ):
             public_key.verifier(1234, ec.ECDSA(hashes.SHA256()))
 
 
@@ -1185,43 +1192,45 @@
         "vector",
         load_vectors_from_file(
             os.path.join(
-                "asymmetric", "ECDH",
-                "KASValidityTest_ECCStaticUnified_NOKC_ZZOnly_init.fax"),
-            load_kasvs_ecdh_vectors
-        )
+                "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']]
+            backend, ec.ECDH(), ec._CURVE_TYPES[vector["curve"]]
         )
 
-        key_numbers = vector['IUT']
+        key_numbers = vector["IUT"]
         private_numbers = ec.EllipticCurvePrivateNumbers(
-            key_numbers['d'],
+            key_numbers["d"],
             ec.EllipticCurvePublicNumbers(
-                key_numbers['x'],
-                key_numbers['y'],
-                ec._CURVE_TYPES[vector['curve']]()
-            )
+                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]:
+        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']
+        peer_numbers = vector["CAVS"]
         public_numbers = ec.EllipticCurvePublicNumbers(
-            peer_numbers['x'],
-            peer_numbers['y'],
-            ec._CURVE_TYPES[vector['curve']]()
+            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]:
+        if vector["fail"] and vector["errno"] in [1, 2]:
             with pytest.raises(ValueError):
                 public_numbers.public_key(backend)
             return
@@ -1229,37 +1238,37 @@
             peer_pubkey = public_numbers.public_key(backend)
 
         z = private_key.exchange(ec.ECDH(), peer_pubkey)
-        z = int(hexlify(z).decode('ascii'), 16)
+        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']:
+        if vector["fail"]:
             # Errno 8 indicates Z should be changed.
-            assert vector['errno'] == 8
-            assert z != vector['Z']
+            assert vector["errno"] == 8
+            assert z != vector["Z"]
         else:
-            assert z == vector['Z']
+            assert z == vector["Z"]
 
     @pytest.mark.parametrize(
         "vector",
         load_vectors_from_file(
             os.path.join("asymmetric", "ECDH", "brainpool.txt"),
-            load_nist_vectors
-        )
+            load_nist_vectors,
+        ),
     )
     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),
+            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),
+            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())
         assert shared_secret == binascii.unhexlify(vector["x_z"])
@@ -1270,11 +1279,10 @@
         _skip_curve_unsupported(backend, ec.SECP256R1())
 
         key = load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "PKCS8", "ec_private_key.pem"),
+            os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
             lambda pemfile: serialization.load_pem_private_key(
                 pemfile.read().encode(), None, backend
-            )
+            ),
         )
 
         with raises_unsupported_algorithm(
@@ -1287,11 +1295,10 @@
         _skip_curve_unsupported(backend, ec.SECP384R1())
 
         key = load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "PKCS8", "ec_private_key.pem"),
+            os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
             lambda pemfile: serialization.load_pem_private_key(
                 pemfile.read().encode(), None, backend
-            )
+            ),
         )
         public_key = EC_KEY_SECP384R1.public_numbers.public_key(backend)
 
diff --git a/tests/hazmat/primitives/test_ed25519.py b/tests/hazmat/primitives/test_ed25519.py
new file mode 100644
index 0000000..5b003d1
--- /dev/null
+++ b/tests/hazmat/primitives/test_ed25519.py
@@ -0,0 +1,232 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+import os
+
+import pytest
+
+from cryptography.exceptions import InvalidSignature, _Reasons
+from cryptography.hazmat.primitives import serialization
+from cryptography.hazmat.primitives.asymmetric.ed25519 import (
+    Ed25519PrivateKey,
+    Ed25519PublicKey,
+)
+
+from ...utils import load_vectors_from_file, raises_unsupported_algorithm
+
+
+def load_ed25519_vectors(vector_data):
+    """
+    djb's ed25519 vectors are structured as a colon delimited array:
+        0: secret key (32 bytes) + public key (32 bytes)
+        1: public key (32 bytes)
+        2: message (0+ bytes)
+        3: signature + message (64+ bytes)
+    """
+    data = []
+    for line in vector_data:
+        secret_key, public_key, message, signature, _ = line.split(":")
+        secret_key = secret_key[0:64]
+        signature = signature[0:128]
+        data.append(
+            {
+                "secret_key": secret_key,
+                "public_key": public_key,
+                "message": message,
+                "signature": signature,
+            }
+        )
+    return data
+
+
+@pytest.mark.supported(
+    only_if=lambda backend: not backend.ed25519_supported(),
+    skip_message="Requires OpenSSL without Ed25519 support",
+)
+def test_ed25519_unsupported(backend):
+    with raises_unsupported_algorithm(
+        _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
+    ):
+        Ed25519PublicKey.from_public_bytes(b"0" * 32)
+
+    with raises_unsupported_algorithm(
+        _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
+    ):
+        Ed25519PrivateKey.from_private_bytes(b"0" * 32)
+
+    with raises_unsupported_algorithm(
+        _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
+    ):
+        Ed25519PrivateKey.generate()
+
+
+@pytest.mark.supported(
+    only_if=lambda backend: backend.ed25519_supported(),
+    skip_message="Requires OpenSSL with Ed25519 support",
+)
+class TestEd25519Signing(object):
+    @pytest.mark.parametrize(
+        "vector",
+        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)
+
+    def test_invalid_signature(self, backend):
+        key = Ed25519PrivateKey.generate()
+        signature = key.sign(b"test data")
+        with pytest.raises(InvalidSignature):
+            key.public_key().verify(signature, b"wrong data")
+
+        with pytest.raises(InvalidSignature):
+            key.public_key().verify(b"0" * 64, b"test data")
+
+    def test_generate(self, backend):
+        key = Ed25519PrivateKey.generate()
+        assert key
+        assert key.public_key()
+
+    def test_load_public_bytes(self, backend):
+        public_key = Ed25519PrivateKey.generate().public_key()
+        public_bytes = public_key.public_bytes(
+            serialization.Encoding.Raw, serialization.PublicFormat.Raw
+        )
+        public_key2 = Ed25519PublicKey.from_public_bytes(public_bytes)
+        assert public_bytes == public_key2.public_bytes(
+            serialization.Encoding.Raw, serialization.PublicFormat.Raw
+        )
+
+    def test_invalid_type_public_bytes(self, backend):
+        with pytest.raises(TypeError):
+            Ed25519PublicKey.from_public_bytes(object())
+
+    def test_invalid_type_private_bytes(self, backend):
+        with pytest.raises(TypeError):
+            Ed25519PrivateKey.from_private_bytes(object())
+
+    def test_invalid_length_from_public_bytes(self, backend):
+        with pytest.raises(ValueError):
+            Ed25519PublicKey.from_public_bytes(b"a" * 31)
+        with pytest.raises(ValueError):
+            Ed25519PublicKey.from_public_bytes(b"a" * 33)
+
+    def test_invalid_length_from_private_bytes(self, backend):
+        with pytest.raises(ValueError):
+            Ed25519PrivateKey.from_private_bytes(b"a" * 31)
+        with pytest.raises(ValueError):
+            Ed25519PrivateKey.from_private_bytes(b"a" * 33)
+
+    def test_invalid_private_bytes(self, backend):
+        key = Ed25519PrivateKey.generate()
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                serialization.Encoding.Raw,
+                serialization.PrivateFormat.Raw,
+                None,
+            )
+
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                serialization.Encoding.Raw,
+                serialization.PrivateFormat.PKCS8,
+                None,
+            )
+
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                serialization.Encoding.PEM,
+                serialization.PrivateFormat.Raw,
+                serialization.NoEncryption(),
+            )
+
+    def test_invalid_public_bytes(self, backend):
+        key = Ed25519PrivateKey.generate().public_key()
+        with pytest.raises(ValueError):
+            key.public_bytes(
+                serialization.Encoding.Raw,
+                serialization.PublicFormat.SubjectPublicKeyInfo,
+            )
+
+        with pytest.raises(ValueError):
+            key.public_bytes(
+                serialization.Encoding.PEM, serialization.PublicFormat.PKCS1
+            )
+
+        with pytest.raises(ValueError):
+            key.public_bytes(
+                serialization.Encoding.PEM, serialization.PublicFormat.Raw
+            )
+
+    @pytest.mark.parametrize(
+        ("encoding", "fmt", "encryption", "passwd", "load_func"),
+        [
+            (
+                serialization.Encoding.PEM,
+                serialization.PrivateFormat.PKCS8,
+                serialization.BestAvailableEncryption(b"password"),
+                b"password",
+                serialization.load_pem_private_key,
+            ),
+            (
+                serialization.Encoding.DER,
+                serialization.PrivateFormat.PKCS8,
+                serialization.BestAvailableEncryption(b"password"),
+                b"password",
+                serialization.load_der_private_key,
+            ),
+            (
+                serialization.Encoding.PEM,
+                serialization.PrivateFormat.PKCS8,
+                serialization.NoEncryption(),
+                None,
+                serialization.load_pem_private_key,
+            ),
+            (
+                serialization.Encoding.DER,
+                serialization.PrivateFormat.PKCS8,
+                serialization.NoEncryption(),
+                None,
+                serialization.load_der_private_key,
+            ),
+        ],
+    )
+    def test_round_trip_private_serialization(
+        self, encoding, fmt, encryption, passwd, load_func, backend
+    ):
+        key = Ed25519PrivateKey.generate()
+        serialized = key.private_bytes(encoding, fmt, encryption)
+        loaded_key = load_func(serialized, passwd, backend)
+        assert isinstance(loaded_key, Ed25519PrivateKey)
+
+    def test_buffer_protocol(self, backend):
+        private_bytes = os.urandom(32)
+        key = Ed25519PrivateKey.from_private_bytes(bytearray(private_bytes))
+        assert (
+            key.private_bytes(
+                serialization.Encoding.Raw,
+                serialization.PrivateFormat.Raw,
+                serialization.NoEncryption(),
+            )
+            == private_bytes
+        )
diff --git a/tests/hazmat/primitives/test_ed448.py b/tests/hazmat/primitives/test_ed448.py
new file mode 100644
index 0000000..9a1f905
--- /dev/null
+++ b/tests/hazmat/primitives/test_ed448.py
@@ -0,0 +1,256 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+import os
+
+import pytest
+
+from cryptography.exceptions import InvalidSignature, _Reasons
+from cryptography.hazmat.primitives import serialization
+from cryptography.hazmat.primitives.asymmetric.ed448 import (
+    Ed448PrivateKey,
+    Ed448PublicKey,
+)
+
+from ...utils import (
+    load_nist_vectors,
+    load_vectors_from_file,
+    raises_unsupported_algorithm,
+)
+
+
+@pytest.mark.supported(
+    only_if=lambda backend: not backend.ed448_supported(),
+    skip_message="Requires OpenSSL without Ed448 support",
+)
+def test_ed448_unsupported(backend):
+    with raises_unsupported_algorithm(
+        _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
+    ):
+        Ed448PublicKey.from_public_bytes(b"0" * 57)
+
+    with raises_unsupported_algorithm(
+        _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
+    ):
+        Ed448PrivateKey.from_private_bytes(b"0" * 57)
+
+    with raises_unsupported_algorithm(
+        _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
+    ):
+        Ed448PrivateKey.generate()
+
+
+@pytest.mark.supported(
+    only_if=lambda backend: backend.ed448_supported(),
+    skip_message="Requires OpenSSL with Ed448 support",
+)
+class TestEd448Signing(object):
+    @pytest.mark.parametrize(
+        "vector",
+        load_vectors_from_file(
+            os.path.join("asymmetric", "Ed448", "rfc8032.txt"),
+            load_nist_vectors,
+        ),
+    )
+    def test_sign_input(self, vector, backend):
+        if vector.get("context") is not None:
+            pytest.skip("ed448 contexts are not currently supported")
+
+        sk = binascii.unhexlify(vector["secret"])
+        pk = binascii.unhexlify(vector["public"])
+        message = binascii.unhexlify(vector["message"])
+        signature = binascii.unhexlify(vector["signature"])
+        private_key = Ed448PrivateKey.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 = Ed448PrivateKey.generate()
+        signature = key.sign(b"test data")
+        with pytest.raises(InvalidSignature):
+            key.public_key().verify(signature, b"wrong data")
+
+        with pytest.raises(InvalidSignature):
+            key.public_key().verify(b"0" * 64, b"test data")
+
+    def test_generate(self, backend):
+        key = Ed448PrivateKey.generate()
+        assert key
+        assert key.public_key()
+
+    @pytest.mark.parametrize(
+        "vector",
+        load_vectors_from_file(
+            os.path.join("asymmetric", "Ed448", "rfc8032.txt"),
+            load_nist_vectors,
+        ),
+    )
+    def test_pub_priv_bytes_raw(self, vector, backend):
+        sk = binascii.unhexlify(vector["secret"])
+        pk = binascii.unhexlify(vector["public"])
+        private_key = Ed448PrivateKey.from_private_bytes(sk)
+        assert (
+            private_key.private_bytes(
+                serialization.Encoding.Raw,
+                serialization.PrivateFormat.Raw,
+                serialization.NoEncryption(),
+            )
+            == sk
+        )
+        assert (
+            private_key.public_key().public_bytes(
+                serialization.Encoding.Raw, serialization.PublicFormat.Raw
+            )
+            == pk
+        )
+        public_key = Ed448PublicKey.from_public_bytes(pk)
+        assert (
+            public_key.public_bytes(
+                serialization.Encoding.Raw, serialization.PublicFormat.Raw
+            )
+            == pk
+        )
+
+    @pytest.mark.parametrize(
+        ("encoding", "fmt", "encryption", "passwd", "load_func"),
+        [
+            (
+                serialization.Encoding.PEM,
+                serialization.PrivateFormat.PKCS8,
+                serialization.BestAvailableEncryption(b"password"),
+                b"password",
+                serialization.load_pem_private_key,
+            ),
+            (
+                serialization.Encoding.DER,
+                serialization.PrivateFormat.PKCS8,
+                serialization.BestAvailableEncryption(b"password"),
+                b"password",
+                serialization.load_der_private_key,
+            ),
+            (
+                serialization.Encoding.PEM,
+                serialization.PrivateFormat.PKCS8,
+                serialization.NoEncryption(),
+                None,
+                serialization.load_pem_private_key,
+            ),
+            (
+                serialization.Encoding.DER,
+                serialization.PrivateFormat.PKCS8,
+                serialization.NoEncryption(),
+                None,
+                serialization.load_der_private_key,
+            ),
+        ],
+    )
+    def test_round_trip_private_serialization(
+        self, encoding, fmt, encryption, passwd, load_func, backend
+    ):
+        key = Ed448PrivateKey.generate()
+        serialized = key.private_bytes(encoding, fmt, encryption)
+        loaded_key = load_func(serialized, passwd, backend)
+        assert isinstance(loaded_key, Ed448PrivateKey)
+
+    def test_invalid_type_public_bytes(self, backend):
+        with pytest.raises(TypeError):
+            Ed448PublicKey.from_public_bytes(object())
+
+    def test_invalid_type_private_bytes(self, backend):
+        with pytest.raises(TypeError):
+            Ed448PrivateKey.from_private_bytes(object())
+
+    def test_invalid_length_from_public_bytes(self, backend):
+        with pytest.raises(ValueError):
+            Ed448PublicKey.from_public_bytes(b"a" * 56)
+        with pytest.raises(ValueError):
+            Ed448PublicKey.from_public_bytes(b"a" * 58)
+
+    def test_invalid_length_from_private_bytes(self, backend):
+        with pytest.raises(ValueError):
+            Ed448PrivateKey.from_private_bytes(b"a" * 56)
+        with pytest.raises(ValueError):
+            Ed448PrivateKey.from_private_bytes(b"a" * 58)
+
+    def test_invalid_private_bytes(self, backend):
+        key = Ed448PrivateKey.generate()
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                serialization.Encoding.Raw,
+                serialization.PrivateFormat.Raw,
+                None,
+            )
+
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                serialization.Encoding.Raw,
+                serialization.PrivateFormat.PKCS8,
+                None,
+            )
+
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                serialization.Encoding.PEM,
+                serialization.PrivateFormat.Raw,
+                serialization.NoEncryption(),
+            )
+
+    def test_invalid_public_bytes(self, backend):
+        key = Ed448PrivateKey.generate().public_key()
+        with pytest.raises(ValueError):
+            key.public_bytes(
+                serialization.Encoding.Raw,
+                serialization.PublicFormat.SubjectPublicKeyInfo,
+            )
+
+        with pytest.raises(ValueError):
+            key.public_bytes(
+                serialization.Encoding.PEM, serialization.PublicFormat.PKCS1
+            )
+
+        with pytest.raises(ValueError):
+            key.public_bytes(
+                serialization.Encoding.PEM, serialization.PublicFormat.Raw
+            )
+
+    def test_buffer_protocol(self, backend):
+        private_bytes = os.urandom(57)
+        key = Ed448PrivateKey.from_private_bytes(bytearray(private_bytes))
+        assert (
+            key.private_bytes(
+                serialization.Encoding.Raw,
+                serialization.PrivateFormat.Raw,
+                serialization.NoEncryption(),
+            )
+            == private_bytes
+        )
+
+    def test_malleability(self, backend):
+        # This is a signature where r > the group order. It should be
+        # rejected to prevent signature malleability issues. This test can
+        # be removed when wycheproof grows ed448 vectors
+        public_bytes = binascii.unhexlify(
+            "fedb02a658d74990244d9d10cf338e977565cbbda6b24c716829ed6ee1e4f28cf"
+            "2620c052db8d878f6243bffc22242816c1aaa67d2f3603600"
+        )
+        signature = binascii.unhexlify(
+            "0cc16ba24d69277f927c1554b0f08a2a711bbdd20b058ccc660d00ca13542a3ce"
+            "f9e5c44c54ab23a2eb14f947e167b990b080863e28b399380f30db6e54d5d1406"
+            "d23378ffde11b1fb81b2b438a3b8e8aa7f7f4e1befcc905023fab5a5465053844"
+            "f04cf0c1b51d84760f869588687f57500"
+        )
+        key = Ed448PublicKey.from_public_bytes(public_bytes)
+        with pytest.raises(InvalidSignature):
+            key.verify(signature, b"8")
diff --git a/tests/hazmat/primitives/test_hash_vectors.py b/tests/hazmat/primitives/test_hash_vectors.py
index 5225a00..9301b62 100644
--- a/tests/hazmat/primitives/test_hash_vectors.py
+++ b/tests/hazmat/primitives/test_hash_vectors.py
@@ -22,13 +22,10 @@
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestSHA1(object):
-    test_SHA1 = generate_hash_test(
+    test_sha1 = generate_hash_test(
         load_hash_vectors,
         os.path.join("hashes", "SHA1"),
-        [
-            "SHA1LongMsg.rsp",
-            "SHA1ShortMsg.rsp",
-        ],
+        ["SHA1LongMsg.rsp", "SHA1ShortMsg.rsp"],
         hashes.SHA1(),
     )
 
@@ -39,13 +36,10 @@
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestSHA224(object):
-    test_SHA224 = generate_hash_test(
+    test_sha224 = generate_hash_test(
         load_hash_vectors,
         os.path.join("hashes", "SHA2"),
-        [
-            "SHA224LongMsg.rsp",
-            "SHA224ShortMsg.rsp",
-        ],
+        ["SHA224LongMsg.rsp", "SHA224ShortMsg.rsp"],
         hashes.SHA224(),
     )
 
@@ -56,13 +50,10 @@
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestSHA256(object):
-    test_SHA256 = generate_hash_test(
+    test_sha256 = generate_hash_test(
         load_hash_vectors,
         os.path.join("hashes", "SHA2"),
-        [
-            "SHA256LongMsg.rsp",
-            "SHA256ShortMsg.rsp",
-        ],
+        ["SHA256LongMsg.rsp", "SHA256ShortMsg.rsp"],
         hashes.SHA256(),
     )
 
@@ -73,13 +64,10 @@
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestSHA384(object):
-    test_SHA384 = generate_hash_test(
+    test_sha384 = generate_hash_test(
         load_hash_vectors,
         os.path.join("hashes", "SHA2"),
-        [
-            "SHA384LongMsg.rsp",
-            "SHA384ShortMsg.rsp",
-        ],
+        ["SHA384LongMsg.rsp", "SHA384ShortMsg.rsp"],
         hashes.SHA384(),
     )
 
@@ -90,13 +78,10 @@
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestSHA512(object):
-    test_SHA512 = generate_hash_test(
+    test_sha512 = generate_hash_test(
         load_hash_vectors,
         os.path.join("hashes", "SHA2"),
-        [
-            "SHA512LongMsg.rsp",
-            "SHA512ShortMsg.rsp",
-        ],
+        ["SHA512LongMsg.rsp", "SHA512ShortMsg.rsp"],
         hashes.SHA512(),
     )
 
@@ -107,13 +92,10 @@
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestSHA512224(object):
-    test_SHA512_224 = generate_hash_test(
+    test_sha512_224 = generate_hash_test(
         load_hash_vectors,
         os.path.join("hashes", "SHA2"),
-        [
-            "SHA512_224LongMsg.rsp",
-            "SHA512_224ShortMsg.rsp",
-        ],
+        ["SHA512_224LongMsg.rsp", "SHA512_224ShortMsg.rsp"],
         hashes.SHA512_224(),
     )
 
@@ -124,13 +106,10 @@
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestSHA512256(object):
-    test_SHA512_256 = generate_hash_test(
+    test_sha512_256 = generate_hash_test(
         load_hash_vectors,
         os.path.join("hashes", "SHA2"),
-        [
-            "SHA512_256LongMsg.rsp",
-            "SHA512_256ShortMsg.rsp",
-        ],
+        ["SHA512_256LongMsg.rsp", "SHA512_256ShortMsg.rsp"],
         hashes.SHA512_256(),
     )
 
@@ -144,16 +123,15 @@
     test_md5 = generate_hash_test(
         load_hash_vectors,
         os.path.join("hashes", "MD5"),
-        [
-            "rfc-1321.txt",
-        ],
+        ["rfc-1321.txt"],
         hashes.MD5(),
     )
 
 
 @pytest.mark.supported(
     only_if=lambda backend: backend.hash_supported(
-        hashes.BLAKE2b(digest_size=64)),
+        hashes.BLAKE2b(digest_size=64)
+    ),
     skip_message="Does not support BLAKE2b",
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
@@ -161,16 +139,15 @@
     test_b2b = generate_hash_test(
         load_hash_vectors,
         os.path.join("hashes", "blake2"),
-        [
-            "blake2b.txt",
-        ],
+        ["blake2b.txt"],
         hashes.BLAKE2b(digest_size=64),
     )
 
 
 @pytest.mark.supported(
     only_if=lambda backend: backend.hash_supported(
-        hashes.BLAKE2s(digest_size=32)),
+        hashes.BLAKE2s(digest_size=32)
+    ),
     skip_message="Does not support BLAKE2s",
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
@@ -178,9 +155,7 @@
     test_b2s = generate_hash_test(
         load_hash_vectors,
         os.path.join("hashes", "blake2"),
-        [
-            "blake2s.txt",
-        ],
+        ["blake2s.txt"],
         hashes.BLAKE2s(digest_size=32),
     )
 
@@ -191,13 +166,10 @@
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestSHA3224(object):
-    test_SHA3_224 = generate_hash_test(
+    test_sha3_224 = generate_hash_test(
         load_hash_vectors,
         os.path.join("hashes", "SHA3"),
-        [
-            "SHA3_224LongMsg.rsp",
-            "SHA3_224ShortMsg.rsp",
-        ],
+        ["SHA3_224LongMsg.rsp", "SHA3_224ShortMsg.rsp"],
         hashes.SHA3_224(),
     )
 
@@ -208,13 +180,10 @@
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestSHA3256(object):
-    test_SHA3_256 = generate_hash_test(
+    test_sha3_256 = generate_hash_test(
         load_hash_vectors,
         os.path.join("hashes", "SHA3"),
-        [
-            "SHA3_256LongMsg.rsp",
-            "SHA3_256ShortMsg.rsp",
-        ],
+        ["SHA3_256LongMsg.rsp", "SHA3_256ShortMsg.rsp"],
         hashes.SHA3_256(),
     )
 
@@ -225,13 +194,10 @@
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestSHA3384(object):
-    test_SHA3_384 = generate_hash_test(
+    test_sha3_384 = generate_hash_test(
         load_hash_vectors,
         os.path.join("hashes", "SHA3"),
-        [
-            "SHA3_384LongMsg.rsp",
-            "SHA3_384ShortMsg.rsp",
-        ],
+        ["SHA3_384LongMsg.rsp", "SHA3_384ShortMsg.rsp"],
         hashes.SHA3_384(),
     )
 
@@ -242,20 +208,18 @@
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestSHA3512(object):
-    test_SHA3_512 = generate_hash_test(
+    test_sha3_512 = generate_hash_test(
         load_hash_vectors,
         os.path.join("hashes", "SHA3"),
-        [
-            "SHA3_512LongMsg.rsp",
-            "SHA3_512ShortMsg.rsp",
-        ],
+        ["SHA3_512LongMsg.rsp", "SHA3_512ShortMsg.rsp"],
         hashes.SHA3_512(),
     )
 
 
 @pytest.mark.supported(
     only_if=lambda backend: backend.hash_supported(
-        hashes.SHAKE128(digest_size=16)),
+        hashes.SHAKE128(digest_size=16)
+    ),
     skip_message="Does not support SHAKE128",
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
@@ -263,10 +227,7 @@
     test_shake128 = generate_hash_test(
         load_hash_vectors,
         os.path.join("hashes", "SHAKE"),
-        [
-            "SHAKE128LongMsg.rsp",
-            "SHAKE128ShortMsg.rsp",
-        ],
+        ["SHAKE128LongMsg.rsp", "SHAKE128ShortMsg.rsp"],
         hashes.SHAKE128(digest_size=16),
     )
 
@@ -274,24 +235,23 @@
         "vector",
         _load_all_params(
             os.path.join("hashes", "SHAKE"),
-            [
-                "SHAKE128VariableOut.rsp",
-            ],
+            ["SHAKE128VariableOut.rsp"],
             load_nist_vectors,
-        )
+        ),
     )
     def test_shake128_variable(self, vector, backend):
-        output_length = int(vector['outputlen']) // 8
-        msg = binascii.unhexlify(vector['msg'])
+        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'])
+        assert m.finalize() == binascii.unhexlify(vector["output"])
 
 
 @pytest.mark.supported(
     only_if=lambda backend: backend.hash_supported(
-        hashes.SHAKE256(digest_size=32)),
+        hashes.SHAKE256(digest_size=32)
+    ),
     skip_message="Does not support SHAKE256",
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
@@ -299,10 +259,7 @@
     test_shake256 = generate_hash_test(
         load_hash_vectors,
         os.path.join("hashes", "SHAKE"),
-        [
-            "SHAKE256LongMsg.rsp",
-            "SHAKE256ShortMsg.rsp",
-        ],
+        ["SHAKE256LongMsg.rsp", "SHAKE256ShortMsg.rsp"],
         hashes.SHAKE256(digest_size=32),
     )
 
@@ -310,16 +267,14 @@
         "vector",
         _load_all_params(
             os.path.join("hashes", "SHAKE"),
-            [
-                "SHAKE256VariableOut.rsp",
-            ],
+            ["SHAKE256VariableOut.rsp"],
             load_nist_vectors,
-        )
+        ),
     )
     def test_shake256_variable(self, vector, backend):
-        output_length = int(vector['outputlen']) // 8
-        msg = binascii.unhexlify(vector['msg'])
+        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'])
+        assert m.finalize() == binascii.unhexlify(vector["output"])
diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py
index b10fadc..eadd0fe 100644
--- a/tests/hazmat/primitives/test_hashes.py
+++ b/tests/hazmat/primitives/test_hashes.py
@@ -52,7 +52,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestSHA1(object):
-    test_SHA1 = generate_base_hash_test(
+    test_sha1 = generate_base_hash_test(
         hashes.SHA1(),
         digest_size=20,
     )
@@ -64,7 +64,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestSHA224(object):
-    test_SHA224 = generate_base_hash_test(
+    test_sha224 = generate_base_hash_test(
         hashes.SHA224(),
         digest_size=28,
     )
@@ -76,7 +76,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestSHA256(object):
-    test_SHA256 = generate_base_hash_test(
+    test_sha256 = generate_base_hash_test(
         hashes.SHA256(),
         digest_size=32,
     )
@@ -88,7 +88,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestSHA384(object):
-    test_SHA384 = generate_base_hash_test(
+    test_sha384 = generate_base_hash_test(
         hashes.SHA384(),
         digest_size=48,
     )
@@ -100,7 +100,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestSHA512(object):
-    test_SHA512 = generate_base_hash_test(
+    test_sha512 = generate_base_hash_test(
         hashes.SHA512(),
         digest_size=64,
     )
@@ -112,7 +112,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestMD5(object):
-    test_MD5 = generate_base_hash_test(
+    test_md5 = generate_base_hash_test(
         hashes.MD5(),
         digest_size=16,
     )
@@ -120,12 +120,13 @@
 
 @pytest.mark.supported(
     only_if=lambda backend: backend.hash_supported(
-        hashes.BLAKE2b(digest_size=64)),
+        hashes.BLAKE2b(digest_size=64)
+    ),
     skip_message="Does not support BLAKE2b",
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestBLAKE2b(object):
-    test_BLAKE2b = generate_base_hash_test(
+    test_blake2b = generate_base_hash_test(
         hashes.BLAKE2b(digest_size=64),
         digest_size=64,
     )
@@ -143,12 +144,13 @@
 
 @pytest.mark.supported(
     only_if=lambda backend: backend.hash_supported(
-        hashes.BLAKE2s(digest_size=32)),
+        hashes.BLAKE2s(digest_size=32)
+    ),
     skip_message="Does not support BLAKE2s",
 )
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestBLAKE2s(object):
-    test_BLAKE2s = generate_base_hash_test(
+    test_blake2s = generate_base_hash_test(
         hashes.BLAKE2s(digest_size=32),
         digest_size=32,
     )
@@ -182,18 +184,12 @@
 
 
 class TestSHAKE(object):
-    @pytest.mark.parametrize(
-        "xof",
-        [hashes.SHAKE128, hashes.SHAKE256]
-    )
+    @pytest.mark.parametrize("xof", [hashes.SHAKE128, hashes.SHAKE256])
     def test_invalid_digest_type(self, xof):
         with pytest.raises(TypeError):
             xof(digest_size=object())
 
-    @pytest.mark.parametrize(
-        "xof",
-        [hashes.SHAKE128, hashes.SHAKE256]
-    )
+    @pytest.mark.parametrize("xof", [hashes.SHAKE128, hashes.SHAKE256])
     def test_invalid_digest_size(self, xof):
         with pytest.raises(ValueError):
             xof(digest_size=-5)
diff --git a/tests/hazmat/primitives/test_hkdf.py b/tests/hazmat/primitives/test_hkdf.py
index 195bfb3..1d7de6c 100644
--- a/tests/hazmat/primitives/test_hkdf.py
+++ b/tests/hazmat/primitives/test_hkdf.py
@@ -9,15 +9,15 @@
 
 import pytest
 
-from cryptography.exceptions import (
-    AlreadyFinalized, InvalidKey, _Reasons
-)
+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
 
 from ...utils import (
-    load_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm
+    load_nist_vectors,
+    load_vectors_from_file,
+    raises_unsupported_algorithm,
 )
 
 
@@ -32,127 +32,67 @@
                 big_length,
                 salt=None,
                 info=None,
-                backend=backend
+                backend=backend,
             )
 
     def test_already_finalized(self, backend):
-        hkdf = HKDF(
-            hashes.SHA256(),
-            16,
-            salt=None,
-            info=None,
-            backend=backend
-        )
+        hkdf = HKDF(hashes.SHA256(), 16, salt=None, info=None, backend=backend)
 
         hkdf.derive(b"\x01" * 16)
 
         with pytest.raises(AlreadyFinalized):
             hkdf.derive(b"\x02" * 16)
 
-        hkdf = HKDF(
-            hashes.SHA256(),
-            16,
-            salt=None,
-            info=None,
-            backend=backend
-        )
+        hkdf = HKDF(hashes.SHA256(), 16, salt=None, info=None, backend=backend)
 
         hkdf.verify(b"\x01" * 16, b"gJ\xfb{\xb1Oi\xc5sMC\xb7\xe4@\xf7u")
 
         with pytest.raises(AlreadyFinalized):
             hkdf.verify(b"\x02" * 16, b"gJ\xfb{\xb1Oi\xc5sMC\xb7\xe4@\xf7u")
 
-        hkdf = HKDF(
-            hashes.SHA256(),
-            16,
-            salt=None,
-            info=None,
-            backend=backend
-        )
+        hkdf = HKDF(hashes.SHA256(), 16, salt=None, info=None, backend=backend)
 
     def test_verify(self, backend):
-        hkdf = HKDF(
-            hashes.SHA256(),
-            16,
-            salt=None,
-            info=None,
-            backend=backend
-        )
+        hkdf = HKDF(hashes.SHA256(), 16, salt=None, info=None, backend=backend)
 
         hkdf.verify(b"\x01" * 16, b"gJ\xfb{\xb1Oi\xc5sMC\xb7\xe4@\xf7u")
 
     def test_verify_invalid(self, backend):
-        hkdf = HKDF(
-            hashes.SHA256(),
-            16,
-            salt=None,
-            info=None,
-            backend=backend
-        )
+        hkdf = HKDF(hashes.SHA256(), 16, salt=None, info=None, backend=backend)
 
         with pytest.raises(InvalidKey):
             hkdf.verify(b"\x02" * 16, b"gJ\xfb{\xb1Oi\xc5sMC\xb7\xe4@\xf7u")
 
     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=u"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=u"foo", backend=backend)
 
         with pytest.raises(TypeError):
             hkdf = HKDF(
-                hashes.SHA256(),
-                16,
-                salt=None,
-                info=None,
-                backend=backend
+                hashes.SHA256(), 16, salt=None, info=None, backend=backend
             )
 
             hkdf.derive(u"foo")
 
         with pytest.raises(TypeError):
             hkdf = HKDF(
-                hashes.SHA256(),
-                16,
-                salt=None,
-                info=None,
-                backend=backend
+                hashes.SHA256(), 16, salt=None, info=None, backend=backend
             )
 
             hkdf.verify(u"foo", b"bar")
 
         with pytest.raises(TypeError):
             hkdf = HKDF(
-                hashes.SHA256(),
-                16,
-                salt=None,
-                info=None,
-                backend=backend
+                hashes.SHA256(), 16, salt=None, info=None, backend=backend
             )
 
             hkdf.verify(b"foo", u"bar")
 
     def test_derive_short_output(self, backend):
-        hkdf = HKDF(
-            hashes.SHA256(),
-            4,
-            salt=None,
-            info=None,
-            backend=backend
-        )
+        hkdf = HKDF(hashes.SHA256(), 4, salt=None, info=None, backend=backend)
 
         assert hkdf.derive(b"\x01" * 16) == b"gJ\xfb{"
 
@@ -165,7 +105,7 @@
             int(vector["l"]),
             salt=vector["salt"],
             info=vector["info"],
-            backend=backend
+            backend=backend,
         )
         ikm = binascii.unhexlify(vector["ikm"])
 
@@ -180,7 +120,7 @@
             int(vector["l"]),
             salt=vector["salt"],
             info=vector["info"],
-            backend=backend
+            backend=backend,
         )
         ikm = bytearray(binascii.unhexlify(vector["ikm"]))
 
@@ -194,8 +134,10 @@
             b"077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5"
         )
 
-        okm = (b"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c"
-               b"5bf34007208d5b887185865")
+        okm = (
+            b"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c"
+            b"5bf34007208d5b887185865"
+        )
 
         info = binascii.unhexlify(b"f0f1f2f3f4f5f6f7f8f9")
         hkdf = HKDFExpand(hashes.SHA256(), 42, info, backend)
@@ -203,12 +145,17 @@
         assert binascii.hexlify(hkdf.derive(prk)) == okm
 
     def test_buffer_protocol(self, backend):
-        prk = bytearray(binascii.unhexlify(
-            b"077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5"
-        ))
+        prk = bytearray(
+            binascii.unhexlify(
+                b"077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2"
+                b"b3e5"
+            )
+        )
 
-        okm = (b"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c"
-               b"5bf34007208d5b887185865")
+        okm = (
+            b"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c"
+            b"5bf34007208d5b887185865"
+        )
 
         info = binascii.unhexlify(b"f0f1f2f3f4f5f6f7f8f9")
         hkdf = HKDFExpand(hashes.SHA256(), 42, info, backend)
@@ -220,8 +167,10 @@
             b"077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5"
         )
 
-        okm = (b"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c"
-               b"5bf34007208d5b887185865")
+        okm = (
+            b"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c"
+            b"5bf34007208d5b887185865"
+        )
 
         info = binascii.unhexlify(b"f0f1f2f3f4f5f6f7f8f9")
         hkdf = HKDFExpand(hashes.SHA256(), 42, info, backend)
diff --git a/tests/hazmat/primitives/test_hkdf_vectors.py b/tests/hazmat/primitives/test_hkdf_vectors.py
index 74bf929..97385e2 100644
--- a/tests/hazmat/primitives/test_hkdf_vectors.py
+++ b/tests/hazmat/primitives/test_hkdf_vectors.py
@@ -17,27 +17,27 @@
 
 @pytest.mark.supported(
     only_if=lambda backend: backend.hmac_supported(hashes.SHA1()),
-    skip_message="Does not support SHA1."
+    skip_message="Does not support SHA1.",
 )
 @pytest.mark.requires_backend_interface(interface=HMACBackend)
 class TestHKDFSHA1(object):
-    test_HKDFSHA1 = generate_hkdf_test(
+    test_hkdfsha1 = generate_hkdf_test(
         load_nist_vectors,
         os.path.join("KDF"),
         ["rfc-5869-HKDF-SHA1.txt"],
-        hashes.SHA1()
+        hashes.SHA1(),
     )
 
 
 @pytest.mark.supported(
     only_if=lambda backend: backend.hmac_supported(hashes.SHA256()),
-    skip_message="Does not support SHA256."
+    skip_message="Does not support SHA256.",
 )
 @pytest.mark.requires_backend_interface(interface=HMACBackend)
 class TestHKDFSHA256(object):
-    test_HKDFSHA1 = generate_hkdf_test(
+    test_hkdfsha256 = generate_hkdf_test(
         load_nist_vectors,
         os.path.join("KDF"),
         ["rfc-5869-HKDF-SHA256.txt"],
-        hashes.SHA256()
+        hashes.SHA256(),
     )
diff --git a/tests/hazmat/primitives/test_hmac.py b/tests/hazmat/primitives/test_hmac.py
index 0e2fe68..7ea931a 100644
--- a/tests/hazmat/primitives/test_hmac.py
+++ b/tests/hazmat/primitives/test_hmac.py
@@ -9,7 +9,9 @@
 import pytest
 
 from cryptography.exceptions import (
-    AlreadyFinalized, InvalidSignature, _Reasons
+    AlreadyFinalized,
+    InvalidSignature,
+    _Reasons,
 )
 from cryptography.hazmat.backends.interfaces import HMACBackend
 from cryptography.hazmat.primitives import hashes, hmac
@@ -55,27 +57,27 @@
             h.finalize()
 
     def test_verify(self, backend):
-        h = hmac.HMAC(b'', hashes.SHA1(), backend=backend)
+        h = hmac.HMAC(b"", hashes.SHA1(), backend=backend)
         digest = h.finalize()
 
-        h = hmac.HMAC(b'', hashes.SHA1(), backend=backend)
+        h = hmac.HMAC(b"", hashes.SHA1(), backend=backend)
         h.verify(digest)
 
         with pytest.raises(AlreadyFinalized):
-            h.verify(b'')
+            h.verify(b"")
 
     def test_invalid_verify(self, backend):
-        h = hmac.HMAC(b'', hashes.SHA1(), backend=backend)
+        h = hmac.HMAC(b"", hashes.SHA1(), backend=backend)
         with pytest.raises(InvalidSignature):
-            h.verify(b'')
+            h.verify(b"")
 
         with pytest.raises(AlreadyFinalized):
-            h.verify(b'')
+            h.verify(b"")
 
     def test_verify_reject_unicode(self, backend):
-        h = hmac.HMAC(b'', hashes.SHA1(), backend=backend)
+        h = hmac.HMAC(b"", hashes.SHA1(), backend=backend)
         with pytest.raises(TypeError):
-            h.verify(u'')
+            h.verify(u"")
 
     def test_unsupported_hash(self, backend):
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_HASH):
diff --git a/tests/hazmat/primitives/test_hmac_vectors.py b/tests/hazmat/primitives/test_hmac_vectors.py
index 6ff71fe..b39df1a 100644
--- a/tests/hazmat/primitives/test_hmac_vectors.py
+++ b/tests/hazmat/primitives/test_hmac_vectors.py
@@ -24,9 +24,7 @@
     test_hmac_md5 = generate_hmac_test(
         load_hash_vectors,
         "HMAC",
-        [
-            "rfc-2202-md5.txt",
-        ],
+        ["rfc-2202-md5.txt"],
         hashes.MD5(),
     )
 
@@ -40,9 +38,7 @@
     test_hmac_sha1 = generate_hmac_test(
         load_hash_vectors,
         "HMAC",
-        [
-            "rfc-2202-sha1.txt",
-        ],
+        ["rfc-2202-sha1.txt"],
         hashes.SHA1(),
     )
 
@@ -56,9 +52,7 @@
     test_hmac_sha224 = generate_hmac_test(
         load_hash_vectors,
         "HMAC",
-        [
-            "rfc-4231-sha224.txt",
-        ],
+        ["rfc-4231-sha224.txt"],
         hashes.SHA224(),
     )
 
@@ -72,9 +66,7 @@
     test_hmac_sha256 = generate_hmac_test(
         load_hash_vectors,
         "HMAC",
-        [
-            "rfc-4231-sha256.txt",
-        ],
+        ["rfc-4231-sha256.txt"],
         hashes.SHA256(),
     )
 
@@ -88,9 +80,7 @@
     test_hmac_sha384 = generate_hmac_test(
         load_hash_vectors,
         "HMAC",
-        [
-            "rfc-4231-sha384.txt",
-        ],
+        ["rfc-4231-sha384.txt"],
         hashes.SHA384(),
     )
 
@@ -104,17 +94,15 @@
     test_hmac_sha512 = generate_hmac_test(
         load_hash_vectors,
         "HMAC",
-        [
-            "rfc-4231-sha512.txt",
-        ],
+        ["rfc-4231-sha512.txt"],
         hashes.SHA512(),
     )
 
 
 @pytest.mark.supported(
-    only_if=lambda backend: backend.hmac_supported(hashes.BLAKE2b(
-        digest_size=64
-    )),
+    only_if=lambda backend: backend.hmac_supported(
+        hashes.BLAKE2b(digest_size=64)
+    ),
     skip_message="Does not support BLAKE2",
 )
 @pytest.mark.requires_backend_interface(interface=HMACBackend)
diff --git a/tests/hazmat/primitives/test_idea.py b/tests/hazmat/primitives/test_idea.py
index 75116dc..1f766de 100644
--- a/tests/hazmat/primitives/test_idea.py
+++ b/tests/hazmat/primitives/test_idea.py
@@ -24,7 +24,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestIDEAModeECB(object):
-    test_ECB = generate_encrypt_test(
+    test_ecb = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "IDEA"),
         ["idea-ecb.txt"],
@@ -41,12 +41,12 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestIDEAModeCBC(object):
-    test_CBC = generate_encrypt_test(
+    test_cbc = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "IDEA"),
         ["idea-cbc.txt"],
         lambda key, **kwargs: algorithms.IDEA(binascii.unhexlify((key))),
-        lambda iv, **kwargs: modes.CBC(binascii.unhexlify(iv))
+        lambda iv, **kwargs: modes.CBC(binascii.unhexlify(iv)),
     )
 
 
@@ -58,12 +58,12 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestIDEAModeOFB(object):
-    test_OFB = generate_encrypt_test(
+    test_ofb = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "IDEA"),
         ["idea-ofb.txt"],
         lambda key, **kwargs: algorithms.IDEA(binascii.unhexlify((key))),
-        lambda iv, **kwargs: modes.OFB(binascii.unhexlify(iv))
+        lambda iv, **kwargs: modes.OFB(binascii.unhexlify(iv)),
     )
 
 
@@ -75,10 +75,10 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestIDEAModeCFB(object):
-    test_CFB = generate_encrypt_test(
+    test_cfb = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "IDEA"),
         ["idea-cfb.txt"],
         lambda key, **kwargs: algorithms.IDEA(binascii.unhexlify((key))),
-        lambda iv, **kwargs: modes.CFB(binascii.unhexlify(iv))
+        lambda iv, **kwargs: modes.CFB(binascii.unhexlify(iv)),
     )
diff --git a/tests/hazmat/primitives/test_kbkdf.py b/tests/hazmat/primitives/test_kbkdf.py
index a16f176..5ff5d74 100644
--- a/tests/hazmat/primitives/test_kbkdf.py
+++ b/tests/hazmat/primitives/test_kbkdf.py
@@ -6,13 +6,13 @@
 
 import pytest
 
-from cryptography.exceptions import (
-    AlreadyFinalized, InvalidKey, _Reasons
-)
+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, KBKDFHMAC, Mode
+    CounterLocation,
+    KBKDFHMAC,
+    Mode,
 )
 
 from ...doubles import DummyHashAlgorithm
@@ -22,137 +22,316 @@
 @pytest.mark.requires_backend_interface(interface=HMACBackend)
 class TestKBKDFHMAC(object):
     def test_invalid_key(self, backend):
-        kdf = KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
-                        CounterLocation.BeforeFixed, b'label', b'context',
-                        None, backend=backend)
+        kdf = KBKDFHMAC(
+            hashes.SHA256(),
+            Mode.CounterMode,
+            32,
+            4,
+            4,
+            CounterLocation.BeforeFixed,
+            b"label",
+            b"context",
+            None,
+            backend=backend,
+        )
 
         key = kdf.derive(b"material")
 
-        kdf = KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
-                        CounterLocation.BeforeFixed, b'label', b'context',
-                        None, backend=backend)
+        kdf = KBKDFHMAC(
+            hashes.SHA256(),
+            Mode.CounterMode,
+            32,
+            4,
+            4,
+            CounterLocation.BeforeFixed,
+            b"label",
+            b"context",
+            None,
+            backend=backend,
+        )
 
         with pytest.raises(InvalidKey):
             kdf.verify(b"material2", key)
 
     def test_already_finalized(self, backend):
-        kdf = KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
-                        CounterLocation.BeforeFixed, b'label', b'context',
-                        None, backend=backend)
+        kdf = KBKDFHMAC(
+            hashes.SHA256(),
+            Mode.CounterMode,
+            32,
+            4,
+            4,
+            CounterLocation.BeforeFixed,
+            b"label",
+            b"context",
+            None,
+            backend=backend,
+        )
 
-        kdf.derive(b'material')
+        kdf.derive(b"material")
 
         with pytest.raises(AlreadyFinalized):
-            kdf.derive(b'material2')
+            kdf.derive(b"material2")
 
-        kdf = KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
-                        CounterLocation.BeforeFixed, b'label', b'context',
-                        None, backend=backend)
+        kdf = KBKDFHMAC(
+            hashes.SHA256(),
+            Mode.CounterMode,
+            32,
+            4,
+            4,
+            CounterLocation.BeforeFixed,
+            b"label",
+            b"context",
+            None,
+            backend=backend,
+        )
 
-        key = kdf.derive(b'material')
+        key = kdf.derive(b"material")
 
         with pytest.raises(AlreadyFinalized):
-            kdf.verify(b'material', key)
+            kdf.verify(b"material", key)
 
-        kdf = KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
-                        CounterLocation.BeforeFixed, b'label', b'context',
-                        None, backend=backend)
-        kdf.verify(b'material', key)
+        kdf = KBKDFHMAC(
+            hashes.SHA256(),
+            Mode.CounterMode,
+            32,
+            4,
+            4,
+            CounterLocation.BeforeFixed,
+            b"label",
+            b"context",
+            None,
+            backend=backend,
+        )
+        kdf.verify(b"material", key)
 
         with pytest.raises(AlreadyFinalized):
             kdf.verify(b"material", key)
 
     def test_key_length(self, backend):
-        kdf = KBKDFHMAC(hashes.SHA1(), Mode.CounterMode, 85899345920, 4, 4,
-                        CounterLocation.BeforeFixed, b'label', b'context',
-                        None, backend=backend)
+        kdf = KBKDFHMAC(
+            hashes.SHA1(),
+            Mode.CounterMode,
+            85899345920,
+            4,
+            4,
+            CounterLocation.BeforeFixed,
+            b"label",
+            b"context",
+            None,
+            backend=backend,
+        )
 
         with pytest.raises(ValueError):
-            kdf.derive(b'material')
+            kdf.derive(b"material")
 
     def test_rlen(self, backend):
         with pytest.raises(ValueError):
-            KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 5, 4,
-                      CounterLocation.BeforeFixed, b'label', b'context',
-                      None, backend=backend)
+            KBKDFHMAC(
+                hashes.SHA256(),
+                Mode.CounterMode,
+                32,
+                5,
+                4,
+                CounterLocation.BeforeFixed,
+                b"label",
+                b"context",
+                None,
+                backend=backend,
+            )
 
     def test_r_type(self, backend):
         with pytest.raises(TypeError):
-            KBKDFHMAC(hashes.SHA1(), Mode.CounterMode, 32, b'r', 4,
-                      CounterLocation.BeforeFixed, b'label', b'context',
-                      None, backend=backend)
+            KBKDFHMAC(
+                hashes.SHA1(),
+                Mode.CounterMode,
+                32,
+                b"r",
+                4,
+                CounterLocation.BeforeFixed,
+                b"label",
+                b"context",
+                None,
+                backend=backend,
+            )
 
     def test_l_type(self, backend):
         with pytest.raises(TypeError):
-            KBKDFHMAC(hashes.SHA1(), Mode.CounterMode, 32, 4, b'l',
-                      CounterLocation.BeforeFixed, b'label', b'context',
-                      None, backend=backend)
+            KBKDFHMAC(
+                hashes.SHA1(),
+                Mode.CounterMode,
+                32,
+                4,
+                b"l",
+                CounterLocation.BeforeFixed,
+                b"label",
+                b"context",
+                None,
+                backend=backend,
+            )
 
     def test_l(self, backend):
         with pytest.raises(ValueError):
-            KBKDFHMAC(hashes.SHA1(), Mode.CounterMode, 32, 4, None,
-                      CounterLocation.BeforeFixed, b'label', b'context',
-                      None, backend=backend)
+            KBKDFHMAC(
+                hashes.SHA1(),
+                Mode.CounterMode,
+                32,
+                4,
+                None,
+                CounterLocation.BeforeFixed,
+                b"label",
+                b"context",
+                None,
+                backend=backend,
+            )
 
     def test_unsupported_mode(self, backend):
         with pytest.raises(TypeError):
-            KBKDFHMAC(hashes.SHA256(), None, 32, 4, 4,
-                      CounterLocation.BeforeFixed, b'label', b'context',
-                      None, backend=backend)
+            KBKDFHMAC(
+                hashes.SHA256(),
+                None,
+                32,
+                4,
+                4,
+                CounterLocation.BeforeFixed,
+                b"label",
+                b"context",
+                None,
+                backend=backend,
+            )
 
     def test_unsupported_location(self, backend):
         with pytest.raises(TypeError):
-            KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
-                      None, b'label', b'context', None,
-                      backend=backend)
+            KBKDFHMAC(
+                hashes.SHA256(),
+                Mode.CounterMode,
+                32,
+                4,
+                4,
+                None,
+                b"label",
+                b"context",
+                None,
+                backend=backend,
+            )
 
     def test_unsupported_parameters(self, backend):
         with pytest.raises(ValueError):
-            KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
-                      CounterLocation.BeforeFixed, b'label', b'context',
-                      b'fixed', backend=backend)
+            KBKDFHMAC(
+                hashes.SHA256(),
+                Mode.CounterMode,
+                32,
+                4,
+                4,
+                CounterLocation.BeforeFixed,
+                b"label",
+                b"context",
+                b"fixed",
+                backend=backend,
+            )
 
     def test_unsupported_hash(self, backend):
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_HASH):
-            KBKDFHMAC(object(), Mode.CounterMode, 32, 4, 4,
-                      CounterLocation.BeforeFixed, b'label', b'context',
-                      None, backend=backend)
+            KBKDFHMAC(
+                object(),
+                Mode.CounterMode,
+                32,
+                4,
+                4,
+                CounterLocation.BeforeFixed,
+                b"label",
+                b"context",
+                None,
+                backend=backend,
+            )
 
     def test_unsupported_algorithm(self, backend):
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_HASH):
-            KBKDFHMAC(DummyHashAlgorithm(), Mode.CounterMode, 32, 4, 4,
-                      CounterLocation.BeforeFixed, b'label', b'context',
-                      None, backend=backend)
+            KBKDFHMAC(
+                DummyHashAlgorithm(),
+                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):
-            KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
-                      CounterLocation.BeforeFixed, b'label', b'context',
-                      None, backend=object())
+            KBKDFHMAC(
+                hashes.SHA256(),
+                Mode.CounterMode,
+                32,
+                4,
+                4,
+                CounterLocation.BeforeFixed,
+                b"label",
+                b"context",
+                None,
+                backend=object(),
+            )
 
     def test_unicode_error_label(self, backend):
         with pytest.raises(TypeError):
-            KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
-                      CounterLocation.BeforeFixed, u'label', b'context',
-                      backend=backend)
+            KBKDFHMAC(
+                hashes.SHA256(),
+                Mode.CounterMode,
+                32,
+                4,
+                4,
+                CounterLocation.BeforeFixed,
+                u"label",
+                b"context",
+                backend=backend,
+            )
 
     def test_unicode_error_context(self, backend):
         with pytest.raises(TypeError):
-            KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
-                      CounterLocation.BeforeFixed, b'label', u'context',
-                      None, backend=backend)
+            KBKDFHMAC(
+                hashes.SHA256(),
+                Mode.CounterMode,
+                32,
+                4,
+                4,
+                CounterLocation.BeforeFixed,
+                b"label",
+                u"context",
+                None,
+                backend=backend,
+            )
 
     def test_unicode_error_key_material(self, backend):
         with pytest.raises(TypeError):
-            kdf = KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
-                            CounterLocation.BeforeFixed, b'label',
-                            b'context', None, backend=backend)
-            kdf.derive(u'material')
+            kdf = KBKDFHMAC(
+                hashes.SHA256(),
+                Mode.CounterMode,
+                32,
+                4,
+                4,
+                CounterLocation.BeforeFixed,
+                b"label",
+                b"context",
+                None,
+                backend=backend,
+            )
+            kdf.derive(u"material")
 
     def test_buffer_protocol(self, backend):
-        kdf = KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 10, 4, 4,
-                        CounterLocation.BeforeFixed, b'label', b'context',
-                        None, backend=backend)
+        kdf = KBKDFHMAC(
+            hashes.SHA256(),
+            Mode.CounterMode,
+            10,
+            4,
+            4,
+            CounterLocation.BeforeFixed,
+            b"label",
+            b"context",
+            None,
+            backend=backend,
+        )
 
         key = kdf.derive(bytearray(b"material"))
-        assert key == b'\xb7\x01\x05\x98\xf5\x1a\x12L\xc7.'
+        assert key == b"\xb7\x01\x05\x98\xf5\x1a\x12L\xc7."
diff --git a/tests/hazmat/primitives/test_kbkdf_vectors.py b/tests/hazmat/primitives/test_kbkdf_vectors.py
index c8263e2..462e04e 100644
--- a/tests/hazmat/primitives/test_kbkdf_vectors.py
+++ b/tests/hazmat/primitives/test_kbkdf_vectors.py
@@ -16,8 +16,8 @@
 
 @pytest.mark.requires_backend_interface(interface=HMACBackend)
 class TestCounterKDFCounterMode(object):
-    test_HKDFSHA1 = generate_kbkdf_counter_mode_test(
+    test_kbkdfctr = generate_kbkdf_counter_mode_test(
         load_nist_kbkdf_vectors,
         os.path.join("KDF"),
-        ["nist-800-108-KBKDF-CTR.txt"]
+        ["nist-800-108-KBKDF-CTR.txt"],
     )
diff --git a/tests/hazmat/primitives/test_keywrap.py b/tests/hazmat/primitives/test_keywrap.py
index c74b144..9b91ccf 100644
--- a/tests/hazmat/primitives/test_keywrap.py
+++ b/tests/hazmat/primitives/test_keywrap.py
@@ -24,15 +24,15 @@
         _load_all_params(
             os.path.join("keywrap", "kwtestvectors"),
             ["KW_AE_128.txt", "KW_AE_192.txt", "KW_AE_256.txt"],
-            load_nist_vectors
-        )
+            load_nist_vectors,
+        ),
     )
     @pytest.mark.supported(
         only_if=lambda backend: backend.cipher_supported(
             algorithms.AES(b"\x00" * 16), modes.ECB()
         ),
         skip_message="Does not support AES key wrap (RFC 3394) because AES-ECB"
-                     " is unsupported",
+        " is unsupported",
     )
     def test_wrap(self, backend, params):
         wrapping_key = binascii.unhexlify(params["k"])
@@ -45,15 +45,15 @@
         _load_all_params(
             os.path.join("keywrap", "kwtestvectors"),
             ["KW_AD_128.txt", "KW_AD_192.txt", "KW_AD_256.txt"],
-            load_nist_vectors
-        )
+            load_nist_vectors,
+        ),
     )
     @pytest.mark.supported(
         only_if=lambda backend: backend.cipher_supported(
             algorithms.AES(b"\x00" * 16), modes.ECB()
         ),
         skip_message="Does not support AES key wrap (RFC 3394) because AES-ECB"
-                     " is unsupported",
+        " is unsupported",
     )
     def test_unwrap(self, backend, params):
         wrapping_key = binascii.unhexlify(params["k"])
@@ -72,7 +72,7 @@
             algorithms.AES(b"\x00" * 16), modes.ECB()
         ),
         skip_message="Does not support AES key wrap (RFC 3394) because AES-ECB"
-                     " is unsupported",
+        " is unsupported",
     )
     def test_wrap_invalid_key_length(self, backend):
         # The wrapping key must be of length [16, 24, 32]
@@ -84,7 +84,7 @@
             algorithms.AES(b"\x00" * 16), modes.ECB()
         ),
         skip_message="Does not support AES key wrap (RFC 3394) because AES-ECB"
-                     " is unsupported",
+        " is unsupported",
     )
     def test_unwrap_invalid_key_length(self, backend):
         with pytest.raises(ValueError):
@@ -95,7 +95,7 @@
             algorithms.AES(b"\x00" * 16), modes.ECB()
         ),
         skip_message="Does not support AES key wrap (RFC 3394) because AES-ECB"
-                     " is unsupported",
+        " is unsupported",
     )
     def test_wrap_invalid_key_to_wrap_length(self, backend):
         # Keys to wrap must be at least 16 bytes long
@@ -121,7 +121,7 @@
         algorithms.AES(b"\x00" * 16), modes.ECB()
     ),
     skip_message="Does not support AES key wrap (RFC 5649) because AES-ECB"
-                 " is unsupported",
+    " is unsupported",
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestAESKeyWrapWithPadding(object):
@@ -130,8 +130,8 @@
         _load_all_params(
             os.path.join("keywrap", "kwtestvectors"),
             ["KWP_AE_128.txt", "KWP_AE_192.txt", "KWP_AE_256.txt"],
-            load_nist_vectors
-        )
+            load_nist_vectors,
+        ),
     )
     def test_wrap(self, backend, params):
         wrapping_key = binascii.unhexlify(params["k"])
@@ -143,7 +143,7 @@
 
     @pytest.mark.parametrize(
         "params",
-        _load_all_params("keywrap", ["kwp_botan.txt"], load_nist_vectors)
+        _load_all_params("keywrap", ["kwp_botan.txt"], load_nist_vectors),
     )
     def test_wrap_additional_vectors(self, backend, params):
         wrapping_key = binascii.unhexlify(params["key"])
@@ -158,8 +158,8 @@
         _load_all_params(
             os.path.join("keywrap", "kwtestvectors"),
             ["KWP_AD_128.txt", "KWP_AD_192.txt", "KWP_AD_256.txt"],
-            load_nist_vectors
-        )
+            load_nist_vectors,
+        ),
     )
     def test_unwrap(self, backend, params):
         wrapping_key = binascii.unhexlify(params["k"])
@@ -177,7 +177,7 @@
 
     @pytest.mark.parametrize(
         "params",
-        _load_all_params("keywrap", ["kwp_botan.txt"], load_nist_vectors)
+        _load_all_params("keywrap", ["kwp_botan.txt"], load_nist_vectors),
     )
     def test_unwrap_additional_vectors(self, backend, params):
         wrapping_key = binascii.unhexlify(params["key"])
@@ -190,18 +190,18 @@
     def test_unwrap_invalid_wrapped_key_length(self, backend):
         # Keys to unwrap must be at least 16 bytes
         with pytest.raises(
-            keywrap.InvalidUnwrap, match='Must be at least 16 bytes'
+            keywrap.InvalidUnwrap, match="Must be at least 16 bytes"
         ):
             keywrap.aes_key_unwrap_with_padding(
                 b"sixteen_byte_key", b"\x00" * 15, backend
             )
 
     def test_wrap_invalid_key_length(self, backend):
-        with pytest.raises(ValueError, match='must be a valid AES key length'):
+        with pytest.raises(ValueError, match="must be a valid AES key length"):
             keywrap.aes_key_wrap_with_padding(b"badkey", b"\x00", backend)
 
     def test_unwrap_invalid_key_length(self, backend):
-        with pytest.raises(ValueError, match='must be a valid AES key length'):
+        with pytest.raises(ValueError, match="must be a valid AES key length"):
             keywrap.aes_key_unwrap_with_padding(
                 b"badkey", b"\x00" * 16, backend
             )
diff --git a/tests/hazmat/primitives/test_padding.py b/tests/hazmat/primitives/test_padding.py
index fb72a79..b15eb37 100644
--- a/tests/hazmat/primitives/test_padding.py
+++ b/tests/hazmat/primitives/test_padding.py
@@ -18,14 +18,17 @@
         with pytest.raises(ValueError):
             padding.PKCS7(size)
 
-    @pytest.mark.parametrize(("size", "padded"), [
-        (128, b"1111"),
-        (128, b"1111111111111111"),
-        (128, b"111111111111111\x06"),
-        (128, b""),
-        (128, b"\x06" * 6),
-        (128, b"\x00" * 16),
-    ])
+    @pytest.mark.parametrize(
+        ("size", "padded"),
+        [
+            (128, b"1111"),
+            (128, b"1111111111111111"),
+            (128, b"111111111111111\x06"),
+            (128, b""),
+            (128, b"\x06" * 6),
+            (128, b"\x00" * 16),
+        ],
+    )
     def test_invalid_padding(self, size, padded):
         unpadder = padding.PKCS7(size).unpadder()
         with pytest.raises(ValueError):
@@ -40,46 +43,48 @@
         with pytest.raises(TypeError):
             unpadder.update(u"abc")
 
-    @pytest.mark.parametrize(("size", "unpadded", "padded"), [
-        (
-            128,
-            b"1111111111",
-            b"1111111111\x06\x06\x06\x06\x06\x06",
-        ),
-        (
-            128,
-            b"111111111111111122222222222222",
-            b"111111111111111122222222222222\x02\x02",
-        ),
-        (
-            128,
-            b"1" * 16,
-            b"1" * 16 + b"\x10" * 16,
-        ),
-        (
-            128,
-            b"1" * 17,
-            b"1" * 17 + b"\x0F" * 15,
-        )
-    ])
+    def test_zany_py2_bytes_subclass(self):
+        class mybytes(bytes):  # noqa: N801
+            def __str__(self):
+                return "broken"
+
+        str(mybytes())
+        padder = padding.PKCS7(128).padder()
+        padder.update(mybytes(b"abc"))
+        unpadder = padding.PKCS7(128).unpadder()
+        unpadder.update(mybytes(padder.finalize()))
+        assert unpadder.finalize() == b"abc"
+
+    @pytest.mark.parametrize(
+        ("size", "unpadded", "padded"),
+        [
+            (128, b"1111111111", b"1111111111\x06\x06\x06\x06\x06\x06"),
+            (
+                128,
+                b"111111111111111122222222222222",
+                b"111111111111111122222222222222\x02\x02",
+            ),
+            (128, b"1" * 16, b"1" * 16 + b"\x10" * 16),
+            (128, b"1" * 17, b"1" * 17 + b"\x0F" * 15),
+        ],
+    )
     def test_pad(self, size, unpadded, padded):
         padder = padding.PKCS7(size).padder()
         result = padder.update(unpadded)
         result += padder.finalize()
         assert result == padded
 
-    @pytest.mark.parametrize(("size", "unpadded", "padded"), [
-        (
-            128,
-            b"1111111111",
-            b"1111111111\x06\x06\x06\x06\x06\x06",
-        ),
-        (
-            128,
-            b"111111111111111122222222222222",
-            b"111111111111111122222222222222\x02\x02",
-        ),
-    ])
+    @pytest.mark.parametrize(
+        ("size", "unpadded", "padded"),
+        [
+            (128, b"1111111111", b"1111111111\x06\x06\x06\x06\x06\x06"),
+            (
+                128,
+                b"111111111111111122222222222222",
+                b"111111111111111122222222222222\x02\x02",
+            ),
+        ],
+    )
     def test_unpad(self, size, unpadded, padded):
         unpadder = padding.PKCS7(size).unpadder()
         result = unpadder.update(padded)
@@ -116,6 +121,18 @@
 
         assert data == b""
 
+    def test_bytearray(self):
+        padder = padding.PKCS7(128).padder()
+        unpadded = bytearray(b"t" * 38)
+        padded = (
+            padder.update(unpadded)
+            + padder.update(unpadded)
+            + padder.finalize()
+        )
+        unpadder = padding.PKCS7(128).unpadder()
+        final = unpadder.update(padded) + unpadder.finalize()
+        assert final == unpadded + unpadded
+
 
 class TestANSIX923(object):
     @pytest.mark.parametrize("size", [127, 4096, -2])
@@ -123,15 +140,18 @@
         with pytest.raises(ValueError):
             padding.ANSIX923(size)
 
-    @pytest.mark.parametrize(("size", "padded"), [
-        (128, b"1111"),
-        (128, b"1111111111111111"),
-        (128, b"111111111111111\x06"),
-        (128, b"1111111111\x06\x06\x06\x06\x06\x06"),
-        (128, b""),
-        (128, b"\x06" * 6),
-        (128, b"\x00" * 16),
-    ])
+    @pytest.mark.parametrize(
+        ("size", "padded"),
+        [
+            (128, b"1111"),
+            (128, b"1111111111111111"),
+            (128, b"111111111111111\x06"),
+            (128, b"1111111111\x06\x06\x06\x06\x06\x06"),
+            (128, b""),
+            (128, b"\x06" * 6),
+            (128, b"\x00" * 16),
+        ],
+    )
     def test_invalid_padding(self, size, padded):
         unpadder = padding.ANSIX923(size).unpadder()
         with pytest.raises(ValueError):
@@ -146,46 +166,48 @@
         with pytest.raises(TypeError):
             unpadder.update(u"abc")
 
-    @pytest.mark.parametrize(("size", "unpadded", "padded"), [
-        (
-            128,
-            b"1111111111",
-            b"1111111111\x00\x00\x00\x00\x00\x06",
-        ),
-        (
-            128,
-            b"111111111111111122222222222222",
-            b"111111111111111122222222222222\x00\x02",
-        ),
-        (
-            128,
-            b"1" * 16,
-            b"1" * 16 + b"\x00" * 15 + b"\x10",
-        ),
-        (
-            128,
-            b"1" * 17,
-            b"1" * 17 + b"\x00" * 14 + b"\x0F",
-        )
-    ])
+    def test_zany_py2_bytes_subclass(self):
+        class mybytes(bytes):  # noqa: N801
+            def __str__(self):
+                return "broken"
+
+        str(mybytes())
+        padder = padding.ANSIX923(128).padder()
+        padder.update(mybytes(b"abc"))
+        unpadder = padding.ANSIX923(128).unpadder()
+        unpadder.update(mybytes(padder.finalize()))
+        assert unpadder.finalize() == b"abc"
+
+    @pytest.mark.parametrize(
+        ("size", "unpadded", "padded"),
+        [
+            (128, b"1111111111", b"1111111111\x00\x00\x00\x00\x00\x06"),
+            (
+                128,
+                b"111111111111111122222222222222",
+                b"111111111111111122222222222222\x00\x02",
+            ),
+            (128, b"1" * 16, b"1" * 16 + b"\x00" * 15 + b"\x10"),
+            (128, b"1" * 17, b"1" * 17 + b"\x00" * 14 + b"\x0F"),
+        ],
+    )
     def test_pad(self, size, unpadded, padded):
         padder = padding.ANSIX923(size).padder()
         result = padder.update(unpadded)
         result += padder.finalize()
         assert result == padded
 
-    @pytest.mark.parametrize(("size", "unpadded", "padded"), [
-        (
-            128,
-            b"1111111111",
-            b"1111111111\x00\x00\x00\x00\x00\x06",
-        ),
-        (
-            128,
-            b"111111111111111122222222222222",
-            b"111111111111111122222222222222\x00\x02",
-        ),
-    ])
+    @pytest.mark.parametrize(
+        ("size", "unpadded", "padded"),
+        [
+            (128, b"1111111111", b"1111111111\x00\x00\x00\x00\x00\x06"),
+            (
+                128,
+                b"111111111111111122222222222222",
+                b"111111111111111122222222222222\x00\x02",
+            ),
+        ],
+    )
     def test_unpad(self, size, unpadded, padded):
         unpadder = padding.ANSIX923(size).unpadder()
         result = unpadder.update(padded)
@@ -207,3 +229,15 @@
             unpadder.update(b"")
         with pytest.raises(AlreadyFinalized):
             unpadder.finalize()
+
+    def test_bytearray(self):
+        padder = padding.ANSIX923(128).padder()
+        unpadded = bytearray(b"t" * 38)
+        padded = (
+            padder.update(unpadded)
+            + padder.update(unpadded)
+            + padder.finalize()
+        )
+        unpadder = padding.ANSIX923(128).unpadder()
+        final = unpadder.update(padded) + unpadder.finalize()
+        assert final == unpadded + unpadded
diff --git a/tests/hazmat/primitives/test_pbkdf2hmac.py b/tests/hazmat/primitives/test_pbkdf2hmac.py
index 0254b21..34fd25c 100644
--- a/tests/hazmat/primitives/test_pbkdf2hmac.py
+++ b/tests/hazmat/primitives/test_pbkdf2hmac.py
@@ -6,10 +6,7 @@
 
 import pytest
 
-from cryptography.exceptions import (
-    AlreadyFinalized, InvalidKey, _Reasons
-)
-from cryptography.hazmat.backends import default_backend
+from cryptography.exceptions import AlreadyFinalized, InvalidKey, _Reasons
 from cryptography.hazmat.primitives import hashes
 from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
 
@@ -18,47 +15,45 @@
 
 
 class TestPBKDF2HMAC(object):
-    def test_already_finalized(self):
-        kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, default_backend())
+    def test_already_finalized(self, backend):
+        kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, backend)
         kdf.derive(b"password")
         with pytest.raises(AlreadyFinalized):
             kdf.derive(b"password2")
 
-        kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, default_backend())
+        kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, backend)
         key = kdf.derive(b"password")
         with pytest.raises(AlreadyFinalized):
             kdf.verify(b"password", key)
 
-        kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, default_backend())
+        kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, backend)
         kdf.verify(b"password", key)
         with pytest.raises(AlreadyFinalized):
             kdf.verify(b"password", key)
 
-    def test_unsupported_algorithm(self):
+    def test_unsupported_algorithm(self, backend):
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_HASH):
-            PBKDF2HMAC(
-                DummyHashAlgorithm(), 20, b"salt", 10, default_backend()
-            )
+            PBKDF2HMAC(DummyHashAlgorithm(), 20, b"salt", 10, backend)
 
-    def test_invalid_key(self):
-        kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, default_backend())
+    def test_invalid_key(self, backend):
+        kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, backend)
         key = kdf.derive(b"password")
 
-        kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, default_backend())
+        kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, backend)
         with pytest.raises(InvalidKey):
             kdf.verify(b"password2", key)
 
-    def test_unicode_error_with_salt(self):
+    def test_unicode_error_with_salt(self, backend):
         with pytest.raises(TypeError):
-            PBKDF2HMAC(hashes.SHA1(), 20, u"salt", 10, default_backend())
+            PBKDF2HMAC(hashes.SHA1(), 20, u"salt", 10, backend)
 
-    def test_unicode_error_with_key_material(self):
-        kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, default_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")
 
     def test_buffer_protocol(self, backend):
-        kdf = PBKDF2HMAC(hashes.SHA1(), 10, b"salt", 10, default_backend())
+        kdf = PBKDF2HMAC(hashes.SHA1(), 10, b"salt", 10, backend)
         data = bytearray(b"data")
         assert kdf.derive(data) == b"\xe9n\xaa\x81\xbbt\xa4\xf6\x08\xce"
 
diff --git a/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py b/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py
index fe51f54..4b97b0d 100644
--- a/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py
+++ b/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py
@@ -22,8 +22,6 @@
     test_pbkdf2_sha1 = generate_pbkdf2_test(
         load_nist_vectors,
         "KDF",
-        [
-            "rfc-6070-PBKDF2-SHA1.txt",
-        ],
+        ["rfc-6070-PBKDF2-SHA1.txt"],
         hashes.SHA1(),
     )
diff --git a/tests/hazmat/primitives/test_pkcs12.py b/tests/hazmat/primitives/test_pkcs12.py
index f084d57..297483e 100644
--- a/tests/hazmat/primitives/test_pkcs12.py
+++ b/tests/hazmat/primitives/test_pkcs12.py
@@ -10,61 +10,85 @@
 
 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.serialization import load_pem_private_key
 from cryptography.hazmat.primitives.serialization.pkcs12 import (
-    load_key_and_certificates
+    load_key_and_certificates,
+    serialize_key_and_certificates,
 )
 
 from .utils import load_vectors_from_file
+from ...doubles import DummyKeySerializationEncryption
 
 
 @pytest.mark.requires_backend_interface(interface=DERSerializationBackend)
-class TestPKCS12(object):
-    @pytest.mark.parametrize(
-        ("filename", "password"),
-        [
-            ("cert-key-aes256cbc.p12", b"cryptography"),
-            ("cert-none-key-none.p12", b"cryptography"),
-            ("cert-rc2-key-3des.p12", b"cryptography"),
-            ("no-password.p12", None),
-        ]
-    )
-    def test_load_pkcs12_ec_keys(self, filename, password, backend):
+class TestPKCS12Loading(object):
+    def _test_load_pkcs12_ec_keys(self, filename, password, backend):
         cert = load_vectors_from_file(
             os.path.join("x509", "custom", "ca", "ca.pem"),
             lambda pemfile: x509.load_pem_x509_certificate(
                 pemfile.read(), backend
-            ), mode="rb"
+            ),
+            mode="rb",
         )
         key = load_vectors_from_file(
             os.path.join("x509", "custom", "ca", "ca_key.pem"),
             lambda pemfile: load_pem_private_key(
                 pemfile.read(), None, backend
-            ), mode="rb"
+            ),
+            mode="rb",
         )
         parsed_key, parsed_cert, parsed_more_certs = load_vectors_from_file(
             os.path.join("pkcs12", filename),
             lambda derfile: load_key_and_certificates(
                 derfile.read(), password, backend
-            ), mode="rb"
+            ),
+            mode="rb",
         )
         assert parsed_cert == cert
         assert parsed_key.private_numbers() == key.private_numbers()
         assert parsed_more_certs == []
 
+    @pytest.mark.parametrize(
+        ("filename", "password"),
+        [
+            ("cert-key-aes256cbc.p12", b"cryptography"),
+            ("cert-none-key-none.p12", b"cryptography"),
+        ],
+    )
+    def test_load_pkcs12_ec_keys(self, filename, password, backend):
+        self._test_load_pkcs12_ec_keys(filename, password, backend)
+
+    @pytest.mark.parametrize(
+        ("filename", "password"),
+        [
+            ("cert-rc2-key-3des.p12", b"cryptography"),
+            ("no-password.p12", None),
+        ],
+    )
+    @pytest.mark.supported(
+        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)
+
     def test_load_pkcs12_cert_only(self, backend):
         cert = load_vectors_from_file(
             os.path.join("x509", "custom", "ca", "ca.pem"),
             lambda pemfile: x509.load_pem_x509_certificate(
                 pemfile.read(), backend
-            ), mode="rb"
+            ),
+            mode="rb",
         )
         parsed_key, parsed_cert, parsed_more_certs = load_vectors_from_file(
             os.path.join("pkcs12", "cert-aes256cbc-no-key.p12"),
             lambda data: load_key_and_certificates(
                 data.read(), b"cryptography", backend
             ),
-            mode="rb"
+            mode="rb",
         )
         assert parsed_cert is None
         assert parsed_key is None
@@ -75,14 +99,15 @@
             os.path.join("x509", "custom", "ca", "ca_key.pem"),
             lambda pemfile: load_pem_private_key(
                 pemfile.read(), None, backend
-            ), mode="rb"
+            ),
+            mode="rb",
         )
         parsed_key, parsed_cert, parsed_more_certs = load_vectors_from_file(
             os.path.join("pkcs12", "no-cert-key-aes256cbc.p12"),
             lambda data: load_key_and_certificates(
                 data.read(), b"cryptography", backend
             ),
-            mode="rb"
+            mode="rb",
         )
         assert parsed_key.private_numbers() == key.private_numbers()
         assert parsed_cert is None
@@ -90,15 +115,11 @@
 
     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)
 
     def test_not_a_pkcs12(self, backend):
         with pytest.raises(ValueError):
-            load_key_and_certificates(
-                b"invalid", b"pass", backend
-            )
+            load_key_and_certificates(b"invalid", b"pass", backend)
 
     def test_invalid_password(self, backend):
         with pytest.raises(ValueError):
@@ -106,13 +127,15 @@
                 os.path.join("pkcs12", "cert-key-aes256cbc.p12"),
                 lambda derfile: load_key_and_certificates(
                     derfile.read(), b"invalid", backend
-                ), mode="rb"
+                ),
+                mode="rb",
             )
 
     def test_buffer_protocol(self, backend):
         p12 = load_vectors_from_file(
             os.path.join("pkcs12", "cert-key-aes256cbc.p12"),
-            lambda derfile: derfile.read(), mode="rb"
+            lambda derfile: derfile.read(),
+            mode="rb",
         )
         p12buffer = bytearray(p12)
         parsed_key, parsed_cert, parsed_more_certs = load_key_and_certificates(
@@ -121,3 +144,128 @@
         assert parsed_key is not None
         assert parsed_cert is not None
         assert parsed_more_certs == []
+
+
+def _load_cert(backend, path):
+    return load_vectors_from_file(
+        path,
+        lambda pemfile: x509.load_pem_x509_certificate(
+            pemfile.read(), backend
+        ),
+        mode="rb",
+    )
+
+
+def _load_ca(backend):
+    cert = _load_cert(backend, os.path.join("x509", "custom", "ca", "ca.pem"))
+    key = load_vectors_from_file(
+        os.path.join("x509", "custom", "ca", "ca_key.pem"),
+        lambda pemfile: load_pem_private_key(pemfile.read(), None, backend),
+        mode="rb",
+    )
+    return cert, key
+
+
+class TestPKCS12Creation(object):
+    @pytest.mark.parametrize("name", [None, b"name"])
+    @pytest.mark.parametrize(
+        ("encryption_algorithm", "password"),
+        [
+            (serialization.BestAvailableEncryption(b"password"), b"password"),
+            (serialization.NoEncryption(), None),
+        ],
+    )
+    def test_generate(self, backend, name, encryption_algorithm, password):
+        cert, key = _load_ca(backend)
+        p12 = serialize_key_and_certificates(
+            name, key, cert, None, encryption_algorithm
+        )
+
+        parsed_key, parsed_cert, parsed_more_certs = load_key_and_certificates(
+            p12, password, backend
+        )
+        assert parsed_cert == cert
+        assert parsed_key.private_numbers() == key.private_numbers()
+        assert parsed_more_certs == []
+
+    def test_generate_with_cert_key_ca(self, backend):
+        cert, key = _load_ca(backend)
+        cert2 = _load_cert(
+            backend, os.path.join("x509", "custom", "dsa_selfsigned_ca.pem")
+        )
+        cert3 = _load_cert(backend, os.path.join("x509", "letsencryptx3.pem"))
+        encryption = serialization.NoEncryption()
+        p12 = serialize_key_and_certificates(
+            None, key, cert, [cert2, cert3], encryption
+        )
+
+        parsed_key, parsed_cert, parsed_more_certs = load_key_and_certificates(
+            p12, None, backend
+        )
+        assert parsed_cert == cert
+        assert parsed_key.private_numbers() == key.private_numbers()
+        assert parsed_more_certs == [cert2, cert3]
+
+    def test_generate_wrong_types(self, backend):
+        cert, key = _load_ca(backend)
+        cert2 = _load_cert(backend, os.path.join("x509", "letsencryptx3.pem"))
+        encryption = serialization.NoEncryption()
+        with pytest.raises(TypeError) as exc:
+            serialize_key_and_certificates(
+                b"name", cert, cert, None, encryption
+            )
+        assert (
+            str(exc.value)
+            == "Key must be RSA, DSA, or EllipticCurve private key."
+        )
+
+        with pytest.raises(TypeError) as exc:
+            serialize_key_and_certificates(b"name", key, key, None, encryption)
+        assert str(exc.value) == "cert must be a certificate"
+
+        with pytest.raises(TypeError) as exc:
+            serialize_key_and_certificates(b"name", key, cert, None, key)
+        assert str(exc.value) == (
+            "Key encryption algorithm must be a "
+            "KeySerializationEncryption instance"
+        )
+
+        with pytest.raises(TypeError) as exc:
+            serialize_key_and_certificates(None, key, cert, cert2, encryption)
+
+        with pytest.raises(TypeError) as exc:
+            serialize_key_and_certificates(None, key, cert, [key], encryption)
+        assert str(exc.value) == "all values in cas must be certificates"
+
+    def test_generate_no_cert(self, backend):
+        _, key = _load_ca(backend)
+        p12 = serialize_key_and_certificates(
+            None, key, None, None, serialization.NoEncryption()
+        )
+        parsed_key, parsed_cert, parsed_more_certs = load_key_and_certificates(
+            p12, None, backend
+        )
+        assert parsed_cert is None
+        assert parsed_key.private_numbers() == key.private_numbers()
+        assert parsed_more_certs == []
+
+    def test_must_supply_something(self):
+        with pytest.raises(ValueError) as exc:
+            serialize_key_and_certificates(
+                None, None, None, None, serialization.NoEncryption()
+            )
+        assert str(exc.value) == (
+            "You must supply at least one of key, cert, or cas"
+        )
+
+    def test_generate_unsupported_encryption_type(self, backend):
+        cert, key = _load_ca(backend)
+        with pytest.raises(ValueError) as exc:
+            serialize_key_and_certificates(
+                None,
+                key,
+                cert,
+                None,
+                DummyKeySerializationEncryption(),
+            )
+        assert str(exc.value) == "Unsupported key encryption type"
diff --git a/tests/hazmat/primitives/test_pkcs7.py b/tests/hazmat/primitives/test_pkcs7.py
new file mode 100644
index 0000000..8b93cb6
--- /dev/null
+++ b/tests/hazmat/primitives/test_pkcs7.py
@@ -0,0 +1,675 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import os
+
+import pytest
+
+from cryptography import x509
+from cryptography.exceptions import _Reasons
+from cryptography.hazmat.primitives import hashes, serialization
+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
+
+
+class TestPKCS7Loading(object):
+    def test_load_invalid_der_pkcs7(self):
+        with pytest.raises(ValueError):
+            pkcs7.load_der_pkcs7_certificates(b"nonsense")
+
+    def test_load_invalid_pem_pkcs7(self):
+        with pytest.raises(ValueError):
+            pkcs7.load_pem_pkcs7_certificates(b"nonsense")
+
+    def test_not_bytes_der(self):
+        with pytest.raises(TypeError):
+            pkcs7.load_der_pkcs7_certificates(38)
+
+    def test_not_bytes_pem(self):
+        with pytest.raises(TypeError):
+            pkcs7.load_pem_pkcs7_certificates(38)
+
+    def test_load_pkcs7_pem(self):
+        certs = load_vectors_from_file(
+            os.path.join("pkcs7", "isrg.pem"),
+            lambda pemfile: pkcs7.load_pem_pkcs7_certificates(pemfile.read()),
+            mode="rb",
+        )
+        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")
+        ]
+
+    def test_load_pkcs7_der(self):
+        certs = load_vectors_from_file(
+            os.path.join("pkcs7", "amazon-roots.p7b"),
+            lambda derfile: pkcs7.load_der_pkcs7_certificates(derfile.read()),
+            mode="rb",
+        )
+        assert len(certs) == 2
+        assert certs[0].subject.get_attributes_for_oid(
+            x509.oid.NameOID.COMMON_NAME
+        ) == [
+            x509.NameAttribute(
+                x509.oid.NameOID.COMMON_NAME, u"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"
+            )
+        ]
+
+    def test_load_pkcs7_unsupported_type(self):
+        with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION):
+            load_vectors_from_file(
+                os.path.join("pkcs7", "enveloped.pem"),
+                lambda pemfile: pkcs7.load_pem_pkcs7_certificates(
+                    pemfile.read()
+                ),
+                mode="rb",
+            )
+
+
+# We have no public verification API and won't be adding one until we get
+# some requirements from users so this function exists to give us basic
+# verification for the signing tests.
+def _pkcs7_verify(encoding, sig, msg, certs, options, backend):
+    sig_bio = backend._bytes_to_bio(sig)
+    if encoding is serialization.Encoding.DER:
+        p7 = backend._lib.d2i_PKCS7_bio(sig_bio.bio, backend._ffi.NULL)
+    elif encoding is serialization.Encoding.PEM:
+        p7 = backend._lib.PEM_read_bio_PKCS7(
+            sig_bio.bio,
+            backend._ffi.NULL,
+            backend._ffi.NULL,
+            backend._ffi.NULL,
+        )
+    else:
+        p7 = backend._lib.SMIME_read_PKCS7(sig_bio.bio, backend._ffi.NULL)
+    backend.openssl_assert(p7 != backend._ffi.NULL)
+    p7 = backend._ffi.gc(p7, backend._lib.PKCS7_free)
+    flags = 0
+    for option in options:
+        if option is pkcs7.PKCS7Options.Text:
+            flags |= backend._lib.PKCS7_TEXT
+    store = backend._lib.X509_STORE_new()
+    backend.openssl_assert(store != backend._ffi.NULL)
+    store = backend._ffi.gc(store, backend._lib.X509_STORE_free)
+    for cert in certs:
+        res = backend._lib.X509_STORE_add_cert(store, cert._x509)
+        backend.openssl_assert(res == 1)
+    if msg is None:
+        res = backend._lib.PKCS7_verify(
+            p7,
+            backend._ffi.NULL,
+            store,
+            backend._ffi.NULL,
+            backend._ffi.NULL,
+            flags,
+        )
+    else:
+        msg_bio = backend._bytes_to_bio(msg)
+        res = backend._lib.PKCS7_verify(
+            p7, backend._ffi.NULL, store, msg_bio.bio, backend._ffi.NULL, flags
+        )
+    backend.openssl_assert(res == 1)
+
+
+def _load_cert_key():
+    key = load_vectors_from_file(
+        os.path.join("x509", "custom", "ca", "ca_key.pem"),
+        lambda pemfile: serialization.load_pem_private_key(
+            pemfile.read(), None
+        ),
+        mode="rb",
+    )
+    cert = load_vectors_from_file(
+        os.path.join("x509", "custom", "ca", "ca.pem"),
+        loader=lambda pemfile: x509.load_pem_x509_certificate(pemfile.read()),
+        mode="rb",
+    )
+    return cert, key
+
+
+class TestPKCS7Builder(object):
+    def test_invalid_data(self):
+        builder = pkcs7.PKCS7SignatureBuilder()
+        with pytest.raises(TypeError):
+            builder.set_data(u"not bytes")
+
+    def test_set_data_twice(self):
+        builder = pkcs7.PKCS7SignatureBuilder().set_data(b"test")
+        with pytest.raises(ValueError):
+            builder.set_data(b"test")
+
+    def test_sign_no_signer(self):
+        builder = pkcs7.PKCS7SignatureBuilder().set_data(b"test")
+        with pytest.raises(ValueError):
+            builder.sign(serialization.Encoding.SMIME, [])
+
+    def test_sign_no_data(self):
+        cert, key = _load_cert_key()
+        builder = pkcs7.PKCS7SignatureBuilder().add_signer(
+            cert, key, hashes.SHA256()
+        )
+        with pytest.raises(ValueError):
+            builder.sign(serialization.Encoding.SMIME, [])
+
+    def test_unsupported_hash_alg(self):
+        cert, key = _load_cert_key()
+        with pytest.raises(TypeError):
+            pkcs7.PKCS7SignatureBuilder().add_signer(
+                cert, key, hashes.SHA512_256()
+            )
+
+    def test_not_a_cert(self):
+        cert, key = _load_cert_key()
+        with pytest.raises(TypeError):
+            pkcs7.PKCS7SignatureBuilder().add_signer(
+                b"notacert", key, hashes.SHA256()
+            )
+
+    @pytest.mark.supported(
+        only_if=lambda backend: backend.ed25519_supported(),
+        skip_message="Does not support ed25519.",
+    )
+    def test_unsupported_key_type(self, backend):
+        cert, _ = _load_cert_key()
+        key = ed25519.Ed25519PrivateKey.generate()
+        with pytest.raises(TypeError):
+            pkcs7.PKCS7SignatureBuilder().add_signer(
+                cert, key, hashes.SHA256()
+            )
+
+    def test_sign_invalid_options(self):
+        cert, key = _load_cert_key()
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(b"test")
+            .add_signer(cert, key, hashes.SHA256())
+        )
+        with pytest.raises(ValueError):
+            builder.sign(serialization.Encoding.SMIME, [b"invalid"])
+
+    def test_sign_invalid_encoding(self):
+        cert, key = _load_cert_key()
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(b"test")
+            .add_signer(cert, key, hashes.SHA256())
+        )
+        with pytest.raises(ValueError):
+            builder.sign(serialization.Encoding.Raw, [])
+
+    def test_sign_invalid_options_text_no_detached(self):
+        cert, key = _load_cert_key()
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(b"test")
+            .add_signer(cert, key, hashes.SHA256())
+        )
+        options = [pkcs7.PKCS7Options.Text]
+        with pytest.raises(ValueError):
+            builder.sign(serialization.Encoding.SMIME, options)
+
+    def test_sign_invalid_options_text_der_encoding(self):
+        cert, key = _load_cert_key()
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(b"test")
+            .add_signer(cert, key, hashes.SHA256())
+        )
+        options = [
+            pkcs7.PKCS7Options.Text,
+            pkcs7.PKCS7Options.DetachedSignature,
+        ]
+        with pytest.raises(ValueError):
+            builder.sign(serialization.Encoding.DER, options)
+
+    def test_sign_invalid_options_no_attrs_and_no_caps(self):
+        cert, key = _load_cert_key()
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(b"test")
+            .add_signer(cert, key, hashes.SHA256())
+        )
+        options = [
+            pkcs7.PKCS7Options.NoAttributes,
+            pkcs7.PKCS7Options.NoCapabilities,
+        ]
+        with pytest.raises(ValueError):
+            builder.sign(serialization.Encoding.SMIME, options)
+
+    def test_smime_sign_detached(self, backend):
+        data = b"hello world"
+        cert, key = _load_cert_key()
+        options = [pkcs7.PKCS7Options.DetachedSignature]
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(data)
+            .add_signer(cert, key, hashes.SHA256())
+        )
+
+        sig = builder.sign(serialization.Encoding.SMIME, options)
+        sig_binary = builder.sign(serialization.Encoding.DER, options)
+        # We don't have a generic ASN.1 parser available to us so we instead
+        # will assert on specific byte sequences being present based on the
+        # parameters chosen above.
+        assert b"sha-256" in sig
+        # Detached signature means that the signed data is *not* embedded into
+        # the PKCS7 structure itself, but is present in the SMIME serialization
+        # as a separate section before the PKCS7 data. So we should expect to
+        # have data in sig but not in sig_binary
+        assert data in sig
+        _pkcs7_verify(
+            serialization.Encoding.SMIME, sig, data, [cert], options, backend
+        )
+        assert data not in sig_binary
+        _pkcs7_verify(
+            serialization.Encoding.DER,
+            sig_binary,
+            data,
+            [cert],
+            options,
+            backend,
+        )
+
+    def test_sign_byteslike(self):
+        data = bytearray(b"hello world")
+        cert, key = _load_cert_key()
+        options = [pkcs7.PKCS7Options.DetachedSignature]
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(data)
+            .add_signer(cert, key, hashes.SHA256())
+        )
+
+        sig = builder.sign(serialization.Encoding.SMIME, options)
+        assert bytes(data) in sig
+
+    def test_sign_pem(self, backend):
+        data = b"hello world"
+        cert, key = _load_cert_key()
+        options = []
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(data)
+            .add_signer(cert, key, hashes.SHA256())
+        )
+
+        sig = builder.sign(serialization.Encoding.PEM, options)
+        _pkcs7_verify(
+            serialization.Encoding.PEM,
+            sig,
+            None,
+            [cert],
+            options,
+            backend,
+        )
+
+    @pytest.mark.parametrize(
+        ("hash_alg", "expected_value"),
+        [
+            (hashes.SHA1(), b"\x06\x05+\x0e\x03\x02\x1a"),
+            (hashes.SHA256(), b"\x06\t`\x86H\x01e\x03\x04\x02\x01"),
+            (hashes.SHA384(), b"\x06\t`\x86H\x01e\x03\x04\x02\x02"),
+            (hashes.SHA512(), b"\x06\t`\x86H\x01e\x03\x04\x02\x03"),
+        ],
+    )
+    def test_sign_alternate_digests_der(
+        self, hash_alg, expected_value, backend
+    ):
+        data = b"hello world"
+        cert, key = _load_cert_key()
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(data)
+            .add_signer(cert, key, hash_alg)
+        )
+        options = []
+        sig = builder.sign(serialization.Encoding.DER, options)
+        assert expected_value in sig
+        _pkcs7_verify(
+            serialization.Encoding.DER, sig, None, [cert], options, backend
+        )
+
+    @pytest.mark.parametrize(
+        ("hash_alg", "expected_value"),
+        [
+            (hashes.SHA1(), b"sha1"),
+            (hashes.SHA256(), b"sha-256"),
+            (hashes.SHA384(), b"sha-384"),
+            (hashes.SHA512(), b"sha-512"),
+        ],
+    )
+    def test_sign_alternate_digests_detached(self, hash_alg, expected_value):
+        data = b"hello world"
+        cert, key = _load_cert_key()
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(data)
+            .add_signer(cert, key, hash_alg)
+        )
+        options = [pkcs7.PKCS7Options.DetachedSignature]
+        sig = builder.sign(serialization.Encoding.SMIME, options)
+        # When in detached signature mode the hash algorithm is stored as a
+        # byte string like "sha-384".
+        assert expected_value in sig
+
+    def test_sign_attached(self, backend):
+        data = b"hello world"
+        cert, key = _load_cert_key()
+        options = []
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(data)
+            .add_signer(cert, key, hashes.SHA256())
+        )
+
+        sig_binary = builder.sign(serialization.Encoding.DER, options)
+        # When not passing detached signature the signed data is embedded into
+        # the PKCS7 structure itself
+        assert data in sig_binary
+        _pkcs7_verify(
+            serialization.Encoding.DER,
+            sig_binary,
+            None,
+            [cert],
+            options,
+            backend,
+        )
+
+    def test_sign_binary(self, backend):
+        data = b"hello\nworld"
+        cert, key = _load_cert_key()
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(data)
+            .add_signer(cert, key, hashes.SHA256())
+        )
+        options = []
+        sig_no_binary = builder.sign(serialization.Encoding.DER, options)
+        sig_binary = builder.sign(
+            serialization.Encoding.DER, [pkcs7.PKCS7Options.Binary]
+        )
+        # Binary prevents translation of LF to CR+LF (SMIME canonical form)
+        # so data should not be present in sig_no_binary, but should be present
+        # in sig_binary
+        assert data not in sig_no_binary
+        _pkcs7_verify(
+            serialization.Encoding.DER,
+            sig_no_binary,
+            None,
+            [cert],
+            options,
+            backend,
+        )
+        assert data in sig_binary
+        _pkcs7_verify(
+            serialization.Encoding.DER,
+            sig_binary,
+            None,
+            [cert],
+            options,
+            backend,
+        )
+
+    def test_sign_smime_canonicalization(self, backend):
+        data = b"hello\nworld"
+        cert, key = _load_cert_key()
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(data)
+            .add_signer(cert, key, hashes.SHA256())
+        )
+
+        options = []
+        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
+        assert data not in sig_binary
+        assert b"hello\r\nworld" in sig_binary
+        _pkcs7_verify(
+            serialization.Encoding.DER,
+            sig_binary,
+            None,
+            [cert],
+            options,
+            backend,
+        )
+
+    def test_sign_text(self, backend):
+        data = b"hello world"
+        cert, key = _load_cert_key()
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(data)
+            .add_signer(cert, key, hashes.SHA256())
+        )
+
+        options = [
+            pkcs7.PKCS7Options.Text,
+            pkcs7.PKCS7Options.DetachedSignature,
+        ]
+        sig_pem = builder.sign(serialization.Encoding.SMIME, options)
+        # The text option adds text/plain headers to the S/MIME message
+        # These headers are only relevant in SMIME mode, not binary, which is
+        # just the PKCS7 structure itself.
+        assert b"text/plain" in sig_pem
+        # When passing the Text option the header is prepended so the actual
+        # signed data is this.
+        signed_data = b"Content-Type: text/plain\r\n\r\nhello world"
+        _pkcs7_verify(
+            serialization.Encoding.SMIME,
+            sig_pem,
+            signed_data,
+            [cert],
+            options,
+            backend,
+        )
+
+    def test_sign_no_capabilities(self, backend):
+        data = b"hello world"
+        cert, key = _load_cert_key()
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(data)
+            .add_signer(cert, key, hashes.SHA256())
+        )
+
+        options = [pkcs7.PKCS7Options.NoCapabilities]
+        sig_binary = builder.sign(serialization.Encoding.DER, options)
+        # NoCapabilities removes the SMIMECapabilities attribute from the
+        # PKCS7 structure. This is an ASN.1 sequence with the
+        # OID 1.2.840.113549.1.9.15. It does NOT remove all authenticated
+        # attributes, so we verify that by looking for the signingTime OID.
+
+        # 1.2.840.113549.1.9.15 SMIMECapabilities as an ASN.1 DER encoded OID
+        assert b"\x06\t*\x86H\x86\xf7\r\x01\t\x0f" not in sig_binary
+        # 1.2.840.113549.1.9.5 signingTime as an ASN.1 DER encoded OID
+        assert b"\x06\t*\x86H\x86\xf7\r\x01\t\x05" in sig_binary
+        _pkcs7_verify(
+            serialization.Encoding.DER,
+            sig_binary,
+            None,
+            [cert],
+            options,
+            backend,
+        )
+
+    def test_sign_no_attributes(self, backend):
+        data = b"hello world"
+        cert, key = _load_cert_key()
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(data)
+            .add_signer(cert, key, hashes.SHA256())
+        )
+
+        options = [pkcs7.PKCS7Options.NoAttributes]
+        sig_binary = builder.sign(serialization.Encoding.DER, options)
+        # NoAttributes removes all authenticated attributes, so we shouldn't
+        # find SMIMECapabilities or signingTime.
+
+        # 1.2.840.113549.1.9.15 SMIMECapabilities as an ASN.1 DER encoded OID
+        assert b"\x06\t*\x86H\x86\xf7\r\x01\t\x0f" not in sig_binary
+        # 1.2.840.113549.1.9.5 signingTime as an ASN.1 DER encoded OID
+        assert b"\x06\t*\x86H\x86\xf7\r\x01\t\x05" not in sig_binary
+        _pkcs7_verify(
+            serialization.Encoding.DER,
+            sig_binary,
+            None,
+            [cert],
+            options,
+            backend,
+        )
+
+    def test_sign_no_certs(self, backend):
+        data = b"hello world"
+        cert, key = _load_cert_key()
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(data)
+            .add_signer(cert, key, hashes.SHA256())
+        )
+
+        options = []
+        sig = builder.sign(serialization.Encoding.DER, options)
+        assert sig.count(cert.public_bytes(serialization.Encoding.DER)) == 1
+
+        options = [pkcs7.PKCS7Options.NoCerts]
+        sig_no = builder.sign(serialization.Encoding.DER, options)
+        assert sig_no.count(cert.public_bytes(serialization.Encoding.DER)) == 0
+
+    def test_multiple_signers(self, backend):
+        data = b"hello world"
+        cert, key = _load_cert_key()
+        rsa_key = load_vectors_from_file(
+            os.path.join("x509", "custom", "ca", "rsa_key.pem"),
+            lambda pemfile: serialization.load_pem_private_key(
+                pemfile.read(), None
+            ),
+            mode="rb",
+        )
+        rsa_cert = load_vectors_from_file(
+            os.path.join("x509", "custom", "ca", "rsa_ca.pem"),
+            loader=lambda pemfile: x509.load_pem_x509_certificate(
+                pemfile.read()
+            ),
+            mode="rb",
+        )
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(data)
+            .add_signer(cert, key, hashes.SHA512())
+            .add_signer(rsa_cert, rsa_key, hashes.SHA512())
+        )
+        options = []
+        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
+        _pkcs7_verify(
+            serialization.Encoding.DER,
+            sig,
+            None,
+            [cert, rsa_cert],
+            options,
+            backend,
+        )
+
+    def test_multiple_signers_different_hash_algs(self, backend):
+        data = b"hello world"
+        cert, key = _load_cert_key()
+        rsa_key = load_vectors_from_file(
+            os.path.join("x509", "custom", "ca", "rsa_key.pem"),
+            lambda pemfile: serialization.load_pem_private_key(
+                pemfile.read(), None
+            ),
+            mode="rb",
+        )
+        rsa_cert = load_vectors_from_file(
+            os.path.join("x509", "custom", "ca", "rsa_ca.pem"),
+            loader=lambda pemfile: x509.load_pem_x509_certificate(
+                pemfile.read()
+            ),
+            mode="rb",
+        )
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(data)
+            .add_signer(cert, key, hashes.SHA384())
+            .add_signer(rsa_cert, rsa_key, hashes.SHA512())
+        )
+        options = []
+        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
+        assert sig.count(b"\x06\t`\x86H\x01e\x03\x04\x02\x03") == 2
+        _pkcs7_verify(
+            serialization.Encoding.DER,
+            sig,
+            None,
+            [cert, rsa_cert],
+            options,
+            backend,
+        )
+
+    def test_add_additional_cert_not_a_cert(self, backend):
+        with pytest.raises(TypeError):
+            pkcs7.PKCS7SignatureBuilder().add_certificate(b"notacert")
+
+    def test_add_additional_cert(self, backend):
+        data = b"hello world"
+        cert, key = _load_cert_key()
+        rsa_cert = load_vectors_from_file(
+            os.path.join("x509", "custom", "ca", "rsa_ca.pem"),
+            loader=lambda pemfile: x509.load_pem_x509_certificate(
+                pemfile.read()
+            ),
+            mode="rb",
+        )
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(data)
+            .add_signer(cert, key, hashes.SHA384())
+            .add_certificate(rsa_cert)
+        )
+        options = []
+        sig = builder.sign(serialization.Encoding.DER, options)
+        assert (
+            sig.count(rsa_cert.public_bytes(serialization.Encoding.DER)) == 1
+        )
+
+    def test_add_multiple_additional_certs(self, backend):
+        data = b"hello world"
+        cert, key = _load_cert_key()
+        rsa_cert = load_vectors_from_file(
+            os.path.join("x509", "custom", "ca", "rsa_ca.pem"),
+            loader=lambda pemfile: x509.load_pem_x509_certificate(
+                pemfile.read()
+            ),
+            mode="rb",
+        )
+        builder = (
+            pkcs7.PKCS7SignatureBuilder()
+            .set_data(data)
+            .add_signer(cert, key, hashes.SHA384())
+            .add_certificate(rsa_cert)
+            .add_certificate(rsa_cert)
+        )
+        options = []
+        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_poly1305.py b/tests/hazmat/primitives/test_poly1305.py
new file mode 100644
index 0000000..8779484
--- /dev/null
+++ b/tests/hazmat/primitives/test_poly1305.py
@@ -0,0 +1,156 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+import os
+
+import pytest
+
+from cryptography.exceptions import (
+    AlreadyFinalized,
+    InvalidSignature,
+    _Reasons,
+)
+from cryptography.hazmat.primitives.poly1305 import Poly1305
+
+from ...utils import (
+    load_nist_vectors,
+    load_vectors_from_file,
+    raises_unsupported_algorithm,
+)
+
+
+@pytest.mark.supported(
+    only_if=lambda backend: not backend.poly1305_supported(),
+    skip_message="Requires OpenSSL without poly1305 support",
+)
+def test_poly1305_unsupported(backend):
+    with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_MAC):
+        Poly1305(b"0" * 32)
+
+
+@pytest.mark.supported(
+    only_if=lambda backend: backend.poly1305_supported(),
+    skip_message="Requires OpenSSL with poly1305 support",
+)
+class TestPoly1305(object):
+    @pytest.mark.parametrize(
+        "vector",
+        load_vectors_from_file(
+            os.path.join("poly1305", "rfc7539.txt"), load_nist_vectors
+        ),
+    )
+    def test_vectors(self, vector, backend):
+        key = binascii.unhexlify(vector["key"])
+        msg = binascii.unhexlify(vector["msg"])
+        tag = binascii.unhexlify(vector["tag"])
+        poly = Poly1305(key)
+        poly.update(msg)
+        assert poly.finalize() == tag
+
+        assert Poly1305.generate_tag(key, msg) == tag
+        Poly1305.verify_tag(key, msg, tag)
+
+    def test_key_with_no_additional_references(self, backend):
+        poly = Poly1305(os.urandom(32))
+        assert len(poly.finalize()) == 16
+
+    def test_raises_after_finalize(self, backend):
+        poly = Poly1305(b"0" * 32)
+        poly.finalize()
+
+        with pytest.raises(AlreadyFinalized):
+            poly.update(b"foo")
+
+        with pytest.raises(AlreadyFinalized):
+            poly.finalize()
+
+    def test_reject_unicode(self, backend):
+        poly = Poly1305(b"0" * 32)
+        with pytest.raises(TypeError):
+            poly.update(u"")
+
+        with pytest.raises(TypeError):
+            Poly1305.generate_tag(b"0" * 32, u"")
+
+    def test_verify(self, backend):
+        poly = Poly1305(b"0" * 32)
+        poly.update(b"msg")
+        tag = poly.finalize()
+
+        with pytest.raises(AlreadyFinalized):
+            poly.verify(b"")
+
+        poly2 = Poly1305(b"0" * 32)
+        poly2.update(b"msg")
+        poly2.verify(tag)
+
+        Poly1305.verify_tag(b"0" * 32, b"msg", tag)
+
+    def test_invalid_verify(self, backend):
+        poly = Poly1305(b"0" * 32)
+        poly.update(b"msg")
+        with pytest.raises(InvalidSignature):
+            poly.verify(b"")
+
+        p2 = Poly1305(b"0" * 32)
+        p2.update(b"msg")
+        with pytest.raises(InvalidSignature):
+            p2.verify(b"\x00" * 16)
+
+        with pytest.raises(InvalidSignature):
+            Poly1305.verify_tag(b"0" * 32, b"msg", b"\x00" * 16)
+
+    def test_verify_reject_unicode(self, backend):
+        poly = Poly1305(b"0" * 32)
+        with pytest.raises(TypeError):
+            poly.verify(u"")
+
+        with pytest.raises(TypeError):
+            Poly1305.verify_tag(b"0" * 32, b"msg", u"")
+
+    def test_invalid_key_type(self, backend):
+        with pytest.raises(TypeError):
+            Poly1305(object())
+
+        with pytest.raises(TypeError):
+            Poly1305.generate_tag(object(), b"msg")
+
+    def test_invalid_key_length(self, backend):
+        with pytest.raises(ValueError):
+            Poly1305(b"0" * 31)
+
+        with pytest.raises(ValueError):
+            Poly1305.generate_tag(b"0" * 31, b"msg")
+
+        with pytest.raises(ValueError):
+            Poly1305(b"0" * 33)
+
+        with pytest.raises(ValueError):
+            Poly1305.generate_tag(b"0" * 33, b"msg")
+
+    def test_buffer_protocol(self, backend):
+        key = binascii.unhexlify(
+            b"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cb"
+            b"c207075c0"
+        )
+        msg = binascii.unhexlify(
+            b"2754776173206272696c6c69672c20616e642074686520736c69746"
+            b"87920746f7665730a446964206779726520616e642067696d626c65"
+            b"20696e2074686520776162653a0a416c6c206d696d7379207765726"
+            b"52074686520626f726f676f7665732c0a416e6420746865206d6f6d"
+            b"65207261746873206f757467726162652e"
+        )
+        key = bytearray(key)
+        poly = Poly1305(key)
+        poly.update(bytearray(msg))
+        assert poly.finalize() == binascii.unhexlify(
+            b"4541669a7eaaee61e708dc7cbcc5eb62"
+        )
+
+        assert Poly1305.generate_tag(key, msg) == binascii.unhexlify(
+            b"4541669a7eaaee61e708dc7cbcc5eb62"
+        )
diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py
index 65d88f5..61c4815 100644
--- a/tests/hazmat/primitives/test_rsa.py
+++ b/tests/hazmat/primitives/test_rsa.py
@@ -6,41 +6,67 @@
 
 import binascii
 import itertools
-import math
 import os
 
 import pytest
 
 from cryptography.exceptions import (
-    AlreadyFinalized, InvalidSignature, _Reasons
+    AlreadyFinalized,
+    InvalidSignature,
+    _Reasons,
 )
 from cryptography.hazmat.backends.interfaces import (
-    PEMSerializationBackend, RSABackend
+    PEMSerializationBackend,
+    RSABackend,
 )
 from cryptography.hazmat.primitives import hashes, serialization
 from cryptography.hazmat.primitives.asymmetric import (
-    padding, rsa, utils as asym_utils
+    padding,
+    rsa,
+    utils as asym_utils,
 )
 from cryptography.hazmat.primitives.asymmetric.rsa import (
-    RSAPrivateNumbers, RSAPublicNumbers
+    RSAPrivateNumbers,
+    RSAPublicNumbers,
 )
 from cryptography.utils import CryptographyDeprecationWarning
 
 from .fixtures_rsa import (
-    RSA_KEY_1024, RSA_KEY_1025, RSA_KEY_1026, RSA_KEY_1027, RSA_KEY_1028,
-    RSA_KEY_1029, RSA_KEY_1030, RSA_KEY_1031, RSA_KEY_1536, 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_1024,
+    RSA_KEY_1025,
+    RSA_KEY_1026,
+    RSA_KEY_1027,
+    RSA_KEY_1028,
+    RSA_KEY_1029,
+    RSA_KEY_1030,
+    RSA_KEY_1031,
+    RSA_KEY_1536,
+    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 (
-    _check_rsa_private_numbers, generate_rsa_verification_test
+    _check_rsa_private_numbers,
+    generate_rsa_verification_test,
+    skip_fips_traditional_openssl,
 )
 from ...doubles import (
-    DummyAsymmetricPadding, DummyHashAlgorithm, DummyKeySerializationEncryption
+    DummyAsymmetricPadding,
+    DummyHashAlgorithm,
+    DummyKeySerializationEncryption,
 )
 from ...utils import (
-    load_nist_vectors, load_pkcs1_vectors, load_rsa_nist_vectors,
-    load_vectors_from_file, raises_unsupported_algorithm
+    load_nist_vectors,
+    load_pkcs1_vectors,
+    load_rsa_nist_vectors,
+    load_vectors_from_file,
+    raises_unsupported_algorithm,
 )
 
 
@@ -89,11 +115,9 @@
             load_vectors_from_file(
                 os.path.join(
                     base_path,
-                    "oaep-{0}-{1}.txt".format(
-                        mgf1alg.name, oaepalg.name
-                    )
+                    "oaep-{}-{}.txt".format(mgf1alg.name, oaepalg.name),
                 ),
-                load_pkcs1_vectors
+                load_pkcs1_vectors,
             )
         )
         # We've loaded the files, but the loaders don't give us any information
@@ -107,12 +131,11 @@
 def _skip_pss_hash_algorithm_unsupported(backend, hash_alg):
     if not backend.rsa_padding_supported(
         padding.PSS(
-            mgf=padding.MGF1(hash_alg),
-            salt_length=padding.PSS.MAX_LENGTH
+            mgf=padding.MGF1(hash_alg), salt_length=padding.PSS.MAX_LENGTH
         )
     ):
         pytest.skip(
-            "Does not support {0} in MGF1 using PSS.".format(hash_alg.name)
+            "Does not support {} in MGF1 using PSS.".format(hash_alg.name)
         )
 
 
@@ -127,19 +150,22 @@
         "d1f9f6c09fd3d38987f7970247b85a6da84907753d42ec52bc23b745093f4fff5cff3"
         "617ce43d00121a9accc0051f519c76e08cf02fc18acfe4c9e6aea18da470a2b611d2e"
         "56a7b35caa2c0239bc041a53cc5875ca0b668ae6377d4b23e932d8c995fd1e58ecfd8"
-        "c4b73259c0d8a54d691cca3f6fb85c8a5c1baf588e898d481", 16
+        "c4b73259c0d8a54d691cca3f6fb85c8a5c1baf588e898d481",
+        16,
     )
     q = int(
         "d1519255eb8f678c86cfd06802d1fbef8b664441ac46b73d33d13a8404580a33a8e74"
         "cb2ea2e2963125b3d454d7a922cef24dd13e55f989cbabf64255a736671f4629a47b5"
         "b2347cfcd669133088d1c159518531025297c2d67c9da856a12e80222cd03b4c6ec0f"
-        "86c957cb7bb8de7a127b645ec9e820aa94581e4762e209f01", 16
+        "86c957cb7bb8de7a127b645ec9e820aa94581e4762e209f01",
+        16,
     )
     assert rsa._modinv(q, p) == int(
         "0275e06afa722999315f8f322275483e15e2fb46d827b17800f99110b269a6732748f"
         "624a382fa2ed1ec68c99f7fc56fb60e76eea51614881f497ba7034c17dde955f92f15"
         "772f8b2b41f3e56d88b1e096cdd293eba4eae1e82db815e0fadea0c4ec971bc6fd875"
-        "c20e67e48c31a611e98d32c6213ae4c4d7b53023b2f80c538", 16
+        "c20e67e48c31a611e98d32c6213ae4c4d7b53023b2f80c538",
+        16,
     )
 
 
@@ -148,11 +174,18 @@
     @pytest.mark.parametrize(
         ("public_exponent", "key_size"),
         itertools.product(
-            (3, 5, 65537),
-            (1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1536, 2048)
-        )
+            (3, 65537),
+            (1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1536, 2048),
+        ),
     )
     def test_generate_rsa_keys(self, backend, public_exponent, key_size):
+        if backend._fips_enabled:
+            if key_size < backend._fips_rsa_min_key_size:
+                pytest.skip("Key size not FIPS compliant: {}".format(key_size))
+            if public_exponent < backend._fips_rsa_min_public_exponent:
+                pytest.skip(
+                    "Exponent not FIPS compliant: {}".format(public_exponent)
+                )
         skey = rsa.generate_private_key(public_exponent, key_size, backend)
         assert skey.key_size == key_size
 
@@ -162,33 +195,39 @@
 
     def test_generate_bad_public_exponent(self, backend):
         with pytest.raises(ValueError):
-            rsa.generate_private_key(public_exponent=1,
-                                     key_size=2048,
-                                     backend=backend)
+            rsa.generate_private_key(
+                public_exponent=1, key_size=2048, backend=backend
+            )
 
         with pytest.raises(ValueError):
-            rsa.generate_private_key(public_exponent=4,
-                                     key_size=2048,
-                                     backend=backend)
+            rsa.generate_private_key(
+                public_exponent=4, key_size=2048, backend=backend
+            )
+
+        with pytest.raises(ValueError):
+            rsa.generate_private_key(
+                public_exponent=65535, key_size=2048, backend=backend
+            )
 
     def test_cant_generate_insecure_tiny_key(self, backend):
         with pytest.raises(ValueError):
-            rsa.generate_private_key(public_exponent=65537,
-                                     key_size=511,
-                                     backend=backend)
+            rsa.generate_private_key(
+                public_exponent=65537, key_size=511, backend=backend
+            )
 
         with pytest.raises(ValueError):
-            rsa.generate_private_key(public_exponent=65537,
-                                     key_size=256,
-                                     backend=backend)
+            rsa.generate_private_key(
+                public_exponent=65537, key_size=256, backend=backend
+            )
 
     @pytest.mark.parametrize(
         "pkcs1_example",
         load_vectors_from_file(
             os.path.join(
-                "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "pss-vect.txt"),
-            load_pkcs1_vectors
-        )
+                "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "pss-vect.txt"
+            ),
+            load_pkcs1_vectors,
+        ),
     )
     def test_load_pss_vect_example_keys(self, pkcs1_example):
         secret, public = pkcs1_example
@@ -201,15 +240,13 @@
             dmq1=secret["dmq1"],
             iqmp=secret["iqmp"],
             public_numbers=rsa.RSAPublicNumbers(
-                e=secret["public_exponent"],
-                n=secret["modulus"]
-            )
+                e=secret["public_exponent"], n=secret["modulus"]
+            ),
         )
         _check_rsa_private_numbers(private_num)
 
         public_num = rsa.RSAPublicNumbers(
-            e=public["public_exponent"],
-            n=public["modulus"]
+            e=public["public_exponent"], n=public["modulus"]
         )
         assert public_num
 
@@ -223,17 +260,18 @@
         "vector",
         load_vectors_from_file(
             os.path.join("asymmetric", "RSA", "oaep-label.txt"),
-            load_nist_vectors)
+            load_nist_vectors,
+        ),
     )
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.OAEP(
                 mgf=padding.MGF1(algorithm=hashes.SHA256()),
                 algorithm=hashes.SHA256(),
-                label=b"label"
+                label=b"label",
             )
         ),
-        skip_message="Does not support RSA OAEP labels"
+        skip_message="Does not support RSA OAEP labels",
     )
     def test_oaep_label_decrypt(self, vector, backend):
         private_key = serialization.load_der_private_key(
@@ -245,8 +283,8 @@
             padding.OAEP(
                 mgf=padding.MGF1(algorithm=hashes.SHA512()),
                 algorithm=hashes.SHA512(),
-                label=binascii.unhexlify(vector["oaeplabel"])
-            )
+                label=binascii.unhexlify(vector["oaeplabel"]),
+            ),
         )
         assert vector["output"][1:-1] == decrypted
 
@@ -255,17 +293,17 @@
         [
             (b"amazing encrypted msg", b"some label"),
             (b"amazing encrypted msg", b""),
-        ]
+        ],
     )
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.OAEP(
                 mgf=padding.MGF1(algorithm=hashes.SHA256()),
                 algorithm=hashes.SHA256(),
-                label=b"label"
+                label=b"label",
             )
         ),
-        skip_message="Does not support RSA OAEP labels"
+        skip_message="Does not support RSA OAEP labels",
     )
     def test_oaep_label_roundtrip(self, msg, label, backend):
         private_key = RSA_KEY_2048.private_key(backend)
@@ -274,54 +312,52 @@
             padding.OAEP(
                 mgf=padding.MGF1(algorithm=hashes.SHA256()),
                 algorithm=hashes.SHA256(),
-                label=label
-            )
+                label=label,
+            ),
         )
         pt = private_key.decrypt(
             ct,
             padding.OAEP(
                 mgf=padding.MGF1(algorithm=hashes.SHA256()),
                 algorithm=hashes.SHA256(),
-                label=label
-            )
+                label=label,
+            ),
         )
         assert pt == msg
 
     @pytest.mark.parametrize(
         ("enclabel", "declabel"),
-        [
-            (b"label1", b"label2"),
-            (b"label3", b""),
-            (b"", b"label4"),
-        ]
+        [(b"label1", b"label2"), (b"label3", b""), (b"", b"label4")],
     )
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.OAEP(
                 mgf=padding.MGF1(algorithm=hashes.SHA256()),
                 algorithm=hashes.SHA256(),
-                label=b"label"
+                label=b"label",
             )
         ),
-        skip_message="Does not support RSA OAEP labels"
+        skip_message="Does not support RSA OAEP labels",
     )
     def test_oaep_wrong_label(self, enclabel, declabel, backend):
         private_key = RSA_KEY_2048.private_key(backend)
         msg = b"test"
         ct = private_key.public_key().encrypt(
-            msg, padding.OAEP(
+            msg,
+            padding.OAEP(
                 mgf=padding.MGF1(algorithm=hashes.SHA256()),
                 algorithm=hashes.SHA256(),
-                label=enclabel
-            )
+                label=enclabel,
+            ),
         )
         with pytest.raises(ValueError):
             private_key.decrypt(
-                ct, padding.OAEP(
+                ct,
+                padding.OAEP(
                     mgf=padding.MGF1(algorithm=hashes.SHA256()),
                     algorithm=hashes.SHA256(),
-                    label=declabel
-                )
+                    label=declabel,
+                ),
             )
 
     @pytest.mark.supported(
@@ -329,10 +365,10 @@
             padding.OAEP(
                 mgf=padding.MGF1(algorithm=hashes.SHA256()),
                 algorithm=hashes.SHA256(),
-                label=b"label"
+                label=b"label",
             )
         ),
-        skip_message="Requires backend without RSA OAEP label support"
+        skip_message="Requires backend without RSA OAEP label support",
     )
     def test_unsupported_oaep_label_decrypt(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
@@ -342,8 +378,8 @@
                 padding.OAEP(
                     mgf=padding.MGF1(algorithm=hashes.SHA1()),
                     algorithm=hashes.SHA1(),
-                    label=b"label"
-                )
+                    label=b"label",
+                ),
             )
 
 
@@ -360,15 +396,16 @@
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PKCS1v15()
         ),
-        skip_message="Does not support PKCS1v1.5."
+        skip_message="Does not support PKCS1v1.5.",
     )
     @pytest.mark.parametrize(
         "pkcs1_example",
-        _flatten_pkcs1_examples(load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "RSA", "pkcs1v15sign-vectors.txt"),
-            load_pkcs1_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
@@ -380,14 +417,13 @@
             dmq1=private["dmq1"],
             iqmp=private["iqmp"],
             public_numbers=rsa.RSAPublicNumbers(
-                e=private["public_exponent"],
-                n=private["modulus"]
-            )
+                e=private["public_exponent"], n=private["modulus"]
+            ),
         ).private_key(backend)
         signature = private_key.sign(
             binascii.unhexlify(example["message"]),
             padding.PKCS1v15(),
-            hashes.SHA1()
+            hashes.SHA1(),
         )
         assert binascii.hexlify(signature) == example["signature"]
 
@@ -395,18 +431,21 @@
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PSS(
                 mgf=padding.MGF1(hashes.SHA1()),
-                salt_length=padding.PSS.MAX_LENGTH
+                salt_length=padding.PSS.MAX_LENGTH,
             )
         ),
-        skip_message="Does not support PSS."
+        skip_message="Does not support PSS.",
     )
     @pytest.mark.parametrize(
         "pkcs1_example",
-        _flatten_pkcs1_examples(load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "pss-vect.txt"),
-            load_pkcs1_vectors
-        ))
+        _flatten_pkcs1_examples(
+            load_vectors_from_file(
+                os.path.join(
+                    "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "pss-vect.txt"
+                ),
+                load_pkcs1_vectors,
+            )
+        ),
     )
     def test_pss_signing(self, pkcs1_example, backend):
         private, public, example = pkcs1_example
@@ -418,23 +457,21 @@
             dmq1=private["dmq1"],
             iqmp=private["iqmp"],
             public_numbers=rsa.RSAPublicNumbers(
-                e=private["public_exponent"],
-                n=private["modulus"]
-            )
+                e=private["public_exponent"], n=private["modulus"]
+            ),
         ).private_key(backend)
         public_key = rsa.RSAPublicNumbers(
-            e=public["public_exponent"],
-            n=public["modulus"]
+            e=public["public_exponent"], n=public["modulus"]
         ).public_key(backend)
         signature = private_key.sign(
             binascii.unhexlify(example["message"]),
             padding.PSS(
                 mgf=padding.MGF1(algorithm=hashes.SHA1()),
-                salt_length=padding.PSS.MAX_LENGTH
+                salt_length=padding.PSS.MAX_LENGTH,
             ),
-            hashes.SHA1()
+            hashes.SHA1(),
         )
-        assert len(signature) == math.ceil(private_key.key_size / 8.0)
+        assert len(signature) == (private_key.key_size + 7) // 8
         # PSS signatures contain randomness so we can't do an exact
         # signature check. Instead we'll verify that the signature created
         # successfully verifies.
@@ -443,22 +480,21 @@
             binascii.unhexlify(example["message"]),
             padding.PSS(
                 mgf=padding.MGF1(algorithm=hashes.SHA1()),
-                salt_length=padding.PSS.MAX_LENGTH
+                salt_length=padding.PSS.MAX_LENGTH,
             ),
             hashes.SHA1(),
         )
 
     @pytest.mark.parametrize(
         "hash_alg",
-        [hashes.SHA224(), hashes.SHA256(), hashes.SHA384(), hashes.SHA512()]
+        [hashes.SHA224(), hashes.SHA256(), hashes.SHA384(), hashes.SHA512()],
     )
     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)
         public_key = private_key.public_key()
         pss = padding.PSS(
-            mgf=padding.MGF1(hash_alg),
-            salt_length=padding.PSS.MAX_LENGTH
+            mgf=padding.MGF1(hash_alg), salt_length=padding.PSS.MAX_LENGTH
         )
         msg = b"testing signature"
         signature = private_key.sign(msg, pss, hash_alg)
@@ -466,15 +502,15 @@
 
     @pytest.mark.supported(
         only_if=lambda backend: (
-            backend.hash_supported(hashes.SHA512()) and
-            backend.rsa_padding_supported(
+            backend.hash_supported(hashes.SHA512())
+            and backend.rsa_padding_supported(
                 padding.PSS(
                     mgf=padding.MGF1(hashes.SHA1()),
-                    salt_length=padding.PSS.MAX_LENGTH
+                    salt_length=padding.PSS.MAX_LENGTH,
                 )
             )
         ),
-        skip_message="Does not support SHA512."
+        skip_message="Does not support SHA512.",
     )
     def test_pss_minimum_key_size_for_digest(self, backend):
         private_key = RSA_KEY_522.private_key(backend)
@@ -482,23 +518,23 @@
             b"no failure",
             padding.PSS(
                 mgf=padding.MGF1(hashes.SHA1()),
-                salt_length=padding.PSS.MAX_LENGTH
+                salt_length=padding.PSS.MAX_LENGTH,
             ),
-            hashes.SHA512()
+            hashes.SHA512(),
         )
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PSS(
                 mgf=padding.MGF1(hashes.SHA1()),
-                salt_length=padding.PSS.MAX_LENGTH
+                salt_length=padding.PSS.MAX_LENGTH,
             )
         ),
-        skip_message="Does not support PSS."
+        skip_message="Does not support PSS.",
     )
     @pytest.mark.supported(
         only_if=lambda backend: backend.hash_supported(hashes.SHA512()),
-        skip_message="Does not support SHA512."
+        skip_message="Does not support SHA512.",
     )
     def test_pss_signing_digest_too_large_for_key_size(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
@@ -507,19 +543,19 @@
                 b"msg",
                 padding.PSS(
                     mgf=padding.MGF1(hashes.SHA1()),
-                    salt_length=padding.PSS.MAX_LENGTH
+                    salt_length=padding.PSS.MAX_LENGTH,
                 ),
-                hashes.SHA512()
+                hashes.SHA512(),
             )
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PSS(
                 mgf=padding.MGF1(hashes.SHA1()),
-                salt_length=padding.PSS.MAX_LENGTH
+                salt_length=padding.PSS.MAX_LENGTH,
             )
         ),
-        skip_message="Does not support PSS."
+        skip_message="Does not support PSS.",
     )
     def test_pss_signing_salt_length_too_long(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
@@ -527,17 +563,16 @@
             private_key.sign(
                 b"failure coming",
                 padding.PSS(
-                    mgf=padding.MGF1(hashes.SHA1()),
-                    salt_length=1000000
+                    mgf=padding.MGF1(hashes.SHA1()), salt_length=1000000
                 ),
-                hashes.SHA1()
+                hashes.SHA1(),
             )
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PKCS1v15()
         ),
-        skip_message="Does not support PKCS1v1.5."
+        skip_message="Does not support PKCS1v1.5.",
     )
     def test_use_after_finalize(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
@@ -564,7 +599,7 @@
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=0)
         ),
-        skip_message="Does not support PSS."
+        skip_message="Does not support PSS.",
     )
     def test_unsupported_pss_mgf(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
@@ -572,40 +607,33 @@
             private_key.sign(
                 b"msg",
                 padding.PSS(
-                    mgf=DummyMGF(),
-                    salt_length=padding.PSS.MAX_LENGTH
+                    mgf=DummyMGF(), salt_length=padding.PSS.MAX_LENGTH
                 ),
-                hashes.SHA1()
+                hashes.SHA1(),
             )
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PKCS1v15()
         ),
-        skip_message="Does not support PKCS1v1.5."
+        skip_message="Does not support PKCS1v1.5.",
     )
     def test_pkcs1_digest_too_large_for_key_size(self, backend):
         private_key = RSA_KEY_599.private_key(backend)
         with pytest.raises(ValueError):
             private_key.sign(
-                b"failure coming",
-                padding.PKCS1v15(),
-                hashes.SHA512()
+                b"failure coming", padding.PKCS1v15(), hashes.SHA512()
             )
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PKCS1v15()
         ),
-        skip_message="Does not support PKCS1v1.5."
+        skip_message="Does not support PKCS1v1.5.",
     )
     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()
-        )
+        private_key.sign(b"no failure", padding.PKCS1v15(), hashes.SHA512())
 
     def test_sign(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
@@ -620,7 +648,7 @@
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=0)
         ),
-        skip_message="Does not support PSS."
+        skip_message="Does not support PSS.",
     )
     def test_prehashed_sign(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
@@ -636,14 +664,15 @@
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.hash_supported(
-            hashes.BLAKE2s(digest_size=32)),
+            hashes.BLAKE2s(digest_size=32)
+        ),
         skip_message="Does not support BLAKE2s",
     )
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=0)
         ),
-        skip_message="Does not support PSS."
+        skip_message="Does not support PSS.",
     )
     def test_unsupported_hash(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
@@ -656,7 +685,7 @@
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=0)
         ),
-        skip_message="Does not support PSS."
+        skip_message="Does not support PSS.",
     )
     def test_prehashed_digest_mismatch(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
@@ -673,31 +702,50 @@
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PKCS1v15()
         ),
-        skip_message="Does not support PKCS1v1.5."
+        skip_message="Does not support PKCS1v1.5.",
     )
     def test_prehashed_unsupported_in_signer_ctx(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
-        with pytest.raises(TypeError), \
-                pytest.warns(CryptographyDeprecationWarning):
+        with pytest.raises(TypeError), pytest.warns(
+            CryptographyDeprecationWarning
+        ):
             private_key.signer(
-                padding.PKCS1v15(),
-                asym_utils.Prehashed(hashes.SHA1())
+                padding.PKCS1v15(), asym_utils.Prehashed(hashes.SHA1())
             )
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PKCS1v15()
         ),
-        skip_message="Does not support PKCS1v1.5."
+        skip_message="Does not support PKCS1v1.5.",
     )
     def test_prehashed_unsupported_in_verifier_ctx(self, backend):
         public_key = RSA_KEY_512.private_key(backend).public_key()
-        with pytest.raises(TypeError), \
-                pytest.warns(CryptographyDeprecationWarning):
+        with pytest.raises(TypeError), pytest.warns(
+            CryptographyDeprecationWarning
+        ):
             public_key.verifier(
                 b"0" * 64,
                 padding.PKCS1v15(),
-                asym_utils.Prehashed(hashes.SHA1())
+                asym_utils.Prehashed(hashes.SHA1()),
+            )
+
+    def test_prehashed_unsupported_in_signature_recover(self, backend):
+        private_key = RSA_KEY_512.private_key(backend)
+        public_key = private_key.public_key()
+        signature = private_key.sign(
+            b"sign me", padding.PKCS1v15(), hashes.SHA1()
+        )
+        prehashed_alg = asym_utils.Prehashed(hashes.SHA1())
+        with pytest.raises(TypeError):
+            public_key.recover_data_from_signature(
+                signature, padding.PKCS1v15(), prehashed_alg
+            )
+
+    def test_corrupted_private_key(self, backend):
+        with pytest.raises(ValueError):
+            serialization.load_pem_private_key(
+                RSA_KEY_CORRUPTED, password=None, backend=backend
             )
 
 
@@ -707,34 +755,49 @@
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PKCS1v15()
         ),
-        skip_message="Does not support PKCS1v1.5."
+        skip_message="Does not support PKCS1v1.5.",
     )
     @pytest.mark.parametrize(
         "pkcs1_example",
-        _flatten_pkcs1_examples(load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "RSA", "pkcs1v15sign-vectors.txt"),
-            load_pkcs1_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"]
+            e=public["public_exponent"], n=public["modulus"]
         ).public_key(backend)
+        signature = binascii.unhexlify(example["signature"])
+        message = binascii.unhexlify(example["message"])
         public_key.verify(
-            binascii.unhexlify(example["signature"]),
-            binascii.unhexlify(example["message"]),
-            padding.PKCS1v15(),
-            hashes.SHA1()
+            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 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(
             padding.PKCS1v15()
         ),
-        skip_message="Does not support PKCS1v1.5."
+        skip_message="Does not support PKCS1v1.5.",
     )
     def test_invalid_pkcs1v15_signature_wrong_data(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
@@ -744,10 +807,18 @@
         )
         with pytest.raises(InvalidSignature):
             public_key.verify(
-                signature,
-                b"incorrect data",
-                padding.PKCS1v15(),
-                hashes.SHA1()
+                signature, b"incorrect data", padding.PKCS1v15(), hashes.SHA1()
+            )
+
+    def test_invalid_pkcs1v15_signature_recover_wrong_hash_alg(self, backend):
+        private_key = RSA_KEY_512.private_key(backend)
+        public_key = private_key.public_key()
+        signature = private_key.sign(
+            b"sign me", padding.PKCS1v15(), hashes.SHA1()
+        )
+        with pytest.raises(InvalidSignature):
+            public_key.recover_data_from_signature(
+                signature, padding.PKCS1v15(), hashes.SHA256()
             )
 
     def test_invalid_signature_sequence_removed(self, backend):
@@ -782,14 +853,14 @@
                 sig,
                 binascii.unhexlify(b"313233343030"),
                 padding.PKCS1v15(),
-                hashes.SHA256()
+                hashes.SHA256(),
             )
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PKCS1v15()
         ),
-        skip_message="Does not support PKCS1v1.5."
+        skip_message="Does not support PKCS1v1.5.",
     )
     def test_invalid_pkcs1v15_signature_wrong_key(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
@@ -804,54 +875,53 @@
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
-            padding.PSS(
-                mgf=padding.MGF1(hashes.SHA1()),
-                salt_length=20
-            )
+            padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=20)
         ),
-        skip_message="Does not support PSS."
+        skip_message="Does not support PSS.",
     )
     @pytest.mark.parametrize(
         "pkcs1_example",
-        _flatten_pkcs1_examples(load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "pss-vect.txt"),
-            load_pkcs1_vectors
-        ))
+        _flatten_pkcs1_examples(
+            load_vectors_from_file(
+                os.path.join(
+                    "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "pss-vect.txt"
+                ),
+                load_pkcs1_vectors,
+            )
+        ),
     )
     def test_pss_verification(self, pkcs1_example, backend):
         private, public, example = pkcs1_example
         public_key = rsa.RSAPublicNumbers(
-            e=public["public_exponent"],
-            n=public["modulus"]
+            e=public["public_exponent"], n=public["modulus"]
         ).public_key(backend)
         public_key.verify(
             binascii.unhexlify(example["signature"]),
             binascii.unhexlify(example["message"]),
             padding.PSS(
-                mgf=padding.MGF1(algorithm=hashes.SHA1()),
-                salt_length=20
+                mgf=padding.MGF1(algorithm=hashes.SHA1()), salt_length=20
             ),
-            hashes.SHA1()
+            hashes.SHA1(),
         )
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PSS(
                 mgf=padding.MGF1(hashes.SHA1()),
-                salt_length=padding.PSS.MAX_LENGTH
+                salt_length=padding.PSS.MAX_LENGTH,
             )
         ),
-        skip_message="Does not support PSS."
+        skip_message="Does not support PSS.",
     )
     def test_invalid_pss_signature_wrong_data(self, backend):
         public_key = rsa.RSAPublicNumbers(
             n=int(
                 b"dffc2137d5e810cde9e4b4612f5796447218bab913b3fa98bdf7982e4fa6"
                 b"ec4d6653ef2b29fb1642b095befcbea6decc178fb4bed243d3c3592c6854"
-                b"6af2d3f3", 16
+                b"6af2d3f3",
+                16,
             ),
-            e=65537
+            e=65537,
         ).public_key(backend)
         signature = binascii.unhexlify(
             b"0e68c3649df91c5bc3665f96e157efa75b71934aaa514d91e94ca8418d100f45"
@@ -863,19 +933,19 @@
                 b"incorrect data",
                 padding.PSS(
                     mgf=padding.MGF1(algorithm=hashes.SHA1()),
-                    salt_length=padding.PSS.MAX_LENGTH
+                    salt_length=padding.PSS.MAX_LENGTH,
                 ),
-                hashes.SHA1()
+                hashes.SHA1(),
             )
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PSS(
                 mgf=padding.MGF1(hashes.SHA1()),
-                salt_length=padding.PSS.MAX_LENGTH
+                salt_length=padding.PSS.MAX_LENGTH,
             )
         ),
-        skip_message="Does not support PSS."
+        skip_message="Does not support PSS.",
     )
     def test_invalid_pss_signature_wrong_key(self, backend):
         signature = binascii.unhexlify(
@@ -888,9 +958,10 @@
                 b"5a95441be90866a14c4d2e139cd16db540ec6c7abab13ffff91443fd46a8"
                 b"960cbb7658ded26a5c95c86f6e40384e1c1239c63e541ba221191c4dd303"
                 b"231b42e33c6dbddf5ec9a746f09bf0c25d0f8d27f93ee0ae5c0d723348f4"
-                b"030d3581e13522e1", 16
+                b"030d3581e13522e1",
+                16,
             ),
-            e=65537
+            e=65537,
         ).public_key(backend)
         with pytest.raises(InvalidSignature):
             public_key.verify(
@@ -898,51 +969,71 @@
                 b"sign me",
                 padding.PSS(
                     mgf=padding.MGF1(algorithm=hashes.SHA1()),
-                    salt_length=padding.PSS.MAX_LENGTH
+                    salt_length=padding.PSS.MAX_LENGTH,
                 ),
-                hashes.SHA1()
+                hashes.SHA1(),
             )
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PSS(
                 mgf=padding.MGF1(hashes.SHA1()),
-                salt_length=padding.PSS.MAX_LENGTH
+                salt_length=padding.PSS.MAX_LENGTH,
             )
         ),
-        skip_message="Does not support PSS."
+        skip_message="Does not support PSS.",
     )
     def test_invalid_pss_signature_data_too_large_for_modulus(self, backend):
+        # 2048 bit PSS signature
         signature = binascii.unhexlify(
-            b"cb43bde4f7ab89eb4a79c6e8dd67e0d1af60715da64429d90c716a490b799c29"
-            b"194cf8046509c6ed851052367a74e2e92d9b38947ed74332acb115a03fcc0222"
+            b"58750fc3d2f560d1f3e37c8e28bc8da6d3e93f5d58f8becd25b1c931eea30fea"
+            b"54cb17d44b90104a0aacb7fe9ffa2a59c5788435911d63de78178d21eb875ccd"
+            b"0b07121b641ed4fe6bcb1ca5060322765507b4f24bdba8a698a8e4e07e6bf2c4"
+            b"7a736abe5a912e85cd32f648f3e043b4385e8b612dcce342c5fddf18c524deb5"
+            b"6295b95f6dfa759b2896b793628a90f133e74c1ff7d3af43e3f7ee792df2e5b6"
+            b"a19e996ac3676884354899a437b3ae4e3ac91976c336c332a3b1db0d172b19cb"
+            b"40ad3d871296cfffb3c889ce74a179a3e290852c35d59525afe4b39dc907fad2"
+            b"ac462c50a488dca486031a3dc8c4cdbbc53e9f71d64732e1533a5d1249b833ce"
         )
-        public_key = rsa.RSAPublicNumbers(
-            n=int(
-                b"381201f4905d67dfeb3dec131a0fbea773489227ec7a1448c3109189ac68"
-                b"5a95441be90866a14c4d2e139cd16db540ec6c7abab13ffff91443fd46a8"
-                b"960cbb7658ded26a5c95c86f6e40384e1c1239c63e541ba221191c4dd303"
-                b"231b42e33c6dbddf5ec9a746f09bf0c25d0f8d27f93ee0ae5c0d723348f4"
-                b"030d3581e13522", 16
-            ),
-            e=65537
-        ).public_key(backend)
+        # 1024 bit key
+        public_key = RSA_KEY_1024.private_key(backend).public_key()
         with pytest.raises(InvalidSignature):
             public_key.verify(
                 signature,
                 b"sign me",
                 padding.PSS(
                     mgf=padding.MGF1(algorithm=hashes.SHA1()),
-                    salt_length=padding.PSS.MAX_LENGTH
+                    salt_length=padding.PSS.MAX_LENGTH,
                 ),
-                hashes.SHA1()
+                hashes.SHA1(),
+            )
+
+    def test_invalid_pss_signature_recover(self, backend):
+        private_key = RSA_KEY_1024.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())
+
+        # Hash algorithm can not be absent for PSS padding
+        with pytest.raises(TypeError):
+            public_key.recover_data_from_signature(
+                signature, pss_padding, None
+            )
+
+        # 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()
             )
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PKCS1v15()
         ),
-        skip_message="Does not support PKCS1v1.5."
+        skip_message="Does not support PKCS1v1.5.",
     )
     def test_use_after_finalize(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
@@ -953,9 +1044,7 @@
 
         with pytest.warns(CryptographyDeprecationWarning):
             verifier = public_key.verifier(
-                signature,
-                padding.PKCS1v15(),
-                hashes.SHA1()
+                signature, padding.PKCS1v15(), hashes.SHA1()
             )
         verifier.update(b"sign me")
         verifier.verify()
@@ -976,19 +1065,16 @@
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PKCS1v15()
         ),
-        skip_message="Does not support PKCS1v1.5."
+        skip_message="Does not support PKCS1v1.5.",
     )
     def test_signature_not_bytes(self, backend):
         public_key = RSA_KEY_512.public_numbers.public_key(backend)
         signature = 1234
 
-        with pytest.raises(TypeError), \
-                pytest.warns(CryptographyDeprecationWarning):
-            public_key.verifier(
-                signature,
-                padding.PKCS1v15(),
-                hashes.SHA1()
-            )
+        with pytest.raises(TypeError), pytest.warns(
+            CryptographyDeprecationWarning
+        ):
+            public_key.verifier(signature, padding.PKCS1v15(), hashes.SHA1())
 
     def test_padding_incorrect_type(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
@@ -1000,7 +1086,7 @@
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=0)
         ),
-        skip_message="Does not support PSS."
+        skip_message="Does not support PSS.",
     )
     def test_unsupported_pss_mgf(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
@@ -1010,24 +1096,23 @@
                 b"sig",
                 b"msg",
                 padding.PSS(
-                    mgf=DummyMGF(),
-                    salt_length=padding.PSS.MAX_LENGTH
+                    mgf=DummyMGF(), salt_length=padding.PSS.MAX_LENGTH
                 ),
-                hashes.SHA1()
+                hashes.SHA1(),
             )
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PSS(
                 mgf=padding.MGF1(hashes.SHA1()),
-                salt_length=padding.PSS.MAX_LENGTH
+                salt_length=padding.PSS.MAX_LENGTH,
             )
         ),
-        skip_message="Does not support PSS."
+        skip_message="Does not support PSS.",
     )
     @pytest.mark.supported(
         only_if=lambda backend: backend.hash_supported(hashes.SHA512()),
-        skip_message="Does not support SHA512."
+        skip_message="Does not support SHA512.",
     )
     def test_pss_verify_digest_too_large_for_key_size(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
@@ -1042,19 +1127,19 @@
                 b"msg doesn't matter",
                 padding.PSS(
                     mgf=padding.MGF1(algorithm=hashes.SHA1()),
-                    salt_length=padding.PSS.MAX_LENGTH
+                    salt_length=padding.PSS.MAX_LENGTH,
                 ),
-                hashes.SHA512()
+                hashes.SHA512(),
             )
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PSS(
                 mgf=padding.MGF1(hashes.SHA1()),
-                salt_length=padding.PSS.MAX_LENGTH
+                salt_length=padding.PSS.MAX_LENGTH,
             )
         ),
-        skip_message="Does not support PSS."
+        skip_message="Does not support PSS.",
     )
     def test_pss_verify_salt_length_too_long(self, backend):
         signature = binascii.unhexlify(
@@ -1065,9 +1150,10 @@
             n=int(
                 b"d309e4612809437548b747d7f9eb9cd3340f54fe42bb3f84a36933b0839c"
                 b"11b0c8b7f67e11f7252370161e31159c49c784d4bc41c42a78ce0f0b40a3"
-                b"ca8ffb91", 16
+                b"ca8ffb91",
+                16,
             ),
-            e=65537
+            e=65537,
         ).public_key(backend)
         with pytest.raises(InvalidSignature):
             public_key.verify(
@@ -1077,9 +1163,9 @@
                     mgf=padding.MGF1(
                         algorithm=hashes.SHA1(),
                     ),
-                    salt_length=1000000
+                    salt_length=1000000,
                 ),
-                hashes.SHA1()
+                hashes.SHA1(),
             )
 
     def test_verify(self, backend):
@@ -1121,219 +1207,239 @@
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PSS(
                 mgf=padding.MGF1(hashes.SHA1()),
-                salt_length=padding.PSS.MAX_LENGTH
+                salt_length=padding.PSS.MAX_LENGTH,
             )
         ),
-        skip_message="Does not support PSS using MGF1 with SHA1."
-    )(generate_rsa_verification_test(
-        load_rsa_nist_vectors,
-        os.path.join("asymmetric", "RSA", "FIPS_186-2"),
-        [
-            "SigGenPSS_186-2.rsp",
-            "SigGenPSS_186-3.rsp",
-            "SigVerPSS_186-3.rsp",
-        ],
-        hashes.SHA1(),
-        lambda params, hash_alg: padding.PSS(
-            mgf=padding.MGF1(
-                algorithm=hash_alg,
+        skip_message="Does not support PSS using MGF1 with SHA1.",
+    )(
+        generate_rsa_verification_test(
+            load_rsa_nist_vectors,
+            os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+            [
+                "SigGenPSS_186-2.rsp",
+                "SigGenPSS_186-3.rsp",
+                "SigVerPSS_186-3.rsp",
+            ],
+            hashes.SHA1(),
+            lambda params, hash_alg: padding.PSS(
+                mgf=padding.MGF1(
+                    algorithm=hash_alg,
+                ),
+                salt_length=params["salt_length"],
             ),
-            salt_length=params["salt_length"]
         )
-    ))
+    )
 
     test_rsa_pss_mgf1_sha224 = pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PSS(
                 mgf=padding.MGF1(hashes.SHA224()),
-                salt_length=padding.PSS.MAX_LENGTH
+                salt_length=padding.PSS.MAX_LENGTH,
             )
         ),
-        skip_message="Does not support PSS using MGF1 with SHA224."
-    )(generate_rsa_verification_test(
-        load_rsa_nist_vectors,
-        os.path.join("asymmetric", "RSA", "FIPS_186-2"),
-        [
-            "SigGenPSS_186-2.rsp",
-            "SigGenPSS_186-3.rsp",
-            "SigVerPSS_186-3.rsp",
-        ],
-        hashes.SHA224(),
-        lambda params, hash_alg: padding.PSS(
-            mgf=padding.MGF1(
-                algorithm=hash_alg,
+        skip_message="Does not support PSS using MGF1 with SHA224.",
+    )(
+        generate_rsa_verification_test(
+            load_rsa_nist_vectors,
+            os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+            [
+                "SigGenPSS_186-2.rsp",
+                "SigGenPSS_186-3.rsp",
+                "SigVerPSS_186-3.rsp",
+            ],
+            hashes.SHA224(),
+            lambda params, hash_alg: padding.PSS(
+                mgf=padding.MGF1(
+                    algorithm=hash_alg,
+                ),
+                salt_length=params["salt_length"],
             ),
-            salt_length=params["salt_length"]
         )
-    ))
+    )
 
     test_rsa_pss_mgf1_sha256 = pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PSS(
                 mgf=padding.MGF1(hashes.SHA256()),
-                salt_length=padding.PSS.MAX_LENGTH
+                salt_length=padding.PSS.MAX_LENGTH,
             )
         ),
-        skip_message="Does not support PSS using MGF1 with SHA256."
-    )(generate_rsa_verification_test(
-        load_rsa_nist_vectors,
-        os.path.join("asymmetric", "RSA", "FIPS_186-2"),
-        [
-            "SigGenPSS_186-2.rsp",
-            "SigGenPSS_186-3.rsp",
-            "SigVerPSS_186-3.rsp",
-        ],
-        hashes.SHA256(),
-        lambda params, hash_alg: padding.PSS(
-            mgf=padding.MGF1(
-                algorithm=hash_alg,
+        skip_message="Does not support PSS using MGF1 with SHA256.",
+    )(
+        generate_rsa_verification_test(
+            load_rsa_nist_vectors,
+            os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+            [
+                "SigGenPSS_186-2.rsp",
+                "SigGenPSS_186-3.rsp",
+                "SigVerPSS_186-3.rsp",
+            ],
+            hashes.SHA256(),
+            lambda params, hash_alg: padding.PSS(
+                mgf=padding.MGF1(
+                    algorithm=hash_alg,
+                ),
+                salt_length=params["salt_length"],
             ),
-            salt_length=params["salt_length"]
         )
-    ))
+    )
 
     test_rsa_pss_mgf1_sha384 = pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PSS(
                 mgf=padding.MGF1(hashes.SHA384()),
-                salt_length=padding.PSS.MAX_LENGTH
+                salt_length=padding.PSS.MAX_LENGTH,
             )
         ),
-        skip_message="Does not support PSS using MGF1 with SHA384."
-    )(generate_rsa_verification_test(
-        load_rsa_nist_vectors,
-        os.path.join("asymmetric", "RSA", "FIPS_186-2"),
-        [
-            "SigGenPSS_186-2.rsp",
-            "SigGenPSS_186-3.rsp",
-            "SigVerPSS_186-3.rsp",
-        ],
-        hashes.SHA384(),
-        lambda params, hash_alg: padding.PSS(
-            mgf=padding.MGF1(
-                algorithm=hash_alg,
+        skip_message="Does not support PSS using MGF1 with SHA384.",
+    )(
+        generate_rsa_verification_test(
+            load_rsa_nist_vectors,
+            os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+            [
+                "SigGenPSS_186-2.rsp",
+                "SigGenPSS_186-3.rsp",
+                "SigVerPSS_186-3.rsp",
+            ],
+            hashes.SHA384(),
+            lambda params, hash_alg: padding.PSS(
+                mgf=padding.MGF1(
+                    algorithm=hash_alg,
+                ),
+                salt_length=params["salt_length"],
             ),
-            salt_length=params["salt_length"]
         )
-    ))
+    )
 
     test_rsa_pss_mgf1_sha512 = pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PSS(
                 mgf=padding.MGF1(hashes.SHA512()),
-                salt_length=padding.PSS.MAX_LENGTH
+                salt_length=padding.PSS.MAX_LENGTH,
             )
         ),
-        skip_message="Does not support PSS using MGF1 with SHA512."
-    )(generate_rsa_verification_test(
-        load_rsa_nist_vectors,
-        os.path.join("asymmetric", "RSA", "FIPS_186-2"),
-        [
-            "SigGenPSS_186-2.rsp",
-            "SigGenPSS_186-3.rsp",
-            "SigVerPSS_186-3.rsp",
-        ],
-        hashes.SHA512(),
-        lambda params, hash_alg: padding.PSS(
-            mgf=padding.MGF1(
-                algorithm=hash_alg,
+        skip_message="Does not support PSS using MGF1 with SHA512.",
+    )(
+        generate_rsa_verification_test(
+            load_rsa_nist_vectors,
+            os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+            [
+                "SigGenPSS_186-2.rsp",
+                "SigGenPSS_186-3.rsp",
+                "SigVerPSS_186-3.rsp",
+            ],
+            hashes.SHA512(),
+            lambda params, hash_alg: padding.PSS(
+                mgf=padding.MGF1(
+                    algorithm=hash_alg,
+                ),
+                salt_length=params["salt_length"],
             ),
-            salt_length=params["salt_length"]
         )
-    ))
+    )
 
 
 @pytest.mark.requires_backend_interface(interface=RSABackend)
 class TestRSAPKCS1Verification(object):
     test_rsa_pkcs1v15_verify_sha1 = pytest.mark.supported(
         only_if=lambda backend: (
-            backend.hash_supported(hashes.SHA1()) and
-            backend.rsa_padding_supported(padding.PKCS1v15())
+            backend.hash_supported(hashes.SHA1())
+            and backend.rsa_padding_supported(padding.PKCS1v15())
         ),
-        skip_message="Does not support SHA1 and PKCS1v1.5."
-    )(generate_rsa_verification_test(
-        load_rsa_nist_vectors,
-        os.path.join("asymmetric", "RSA", "FIPS_186-2"),
-        [
-            "SigGen15_186-2.rsp",
-            "SigGen15_186-3.rsp",
-            "SigVer15_186-3.rsp",
-        ],
-        hashes.SHA1(),
-        lambda params, hash_alg: padding.PKCS1v15()
-    ))
+        skip_message="Does not support SHA1 and PKCS1v1.5.",
+    )(
+        generate_rsa_verification_test(
+            load_rsa_nist_vectors,
+            os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+            [
+                "SigGen15_186-2.rsp",
+                "SigGen15_186-3.rsp",
+                "SigVer15_186-3.rsp",
+            ],
+            hashes.SHA1(),
+            lambda params, hash_alg: padding.PKCS1v15(),
+        )
+    )
 
     test_rsa_pkcs1v15_verify_sha224 = pytest.mark.supported(
         only_if=lambda backend: (
-            backend.hash_supported(hashes.SHA224()) and
-            backend.rsa_padding_supported(padding.PKCS1v15())
+            backend.hash_supported(hashes.SHA224())
+            and backend.rsa_padding_supported(padding.PKCS1v15())
         ),
-        skip_message="Does not support SHA224 and PKCS1v1.5."
-    )(generate_rsa_verification_test(
-        load_rsa_nist_vectors,
-        os.path.join("asymmetric", "RSA", "FIPS_186-2"),
-        [
-            "SigGen15_186-2.rsp",
-            "SigGen15_186-3.rsp",
-            "SigVer15_186-3.rsp",
-        ],
-        hashes.SHA224(),
-        lambda params, hash_alg: padding.PKCS1v15()
-    ))
+        skip_message="Does not support SHA224 and PKCS1v1.5.",
+    )(
+        generate_rsa_verification_test(
+            load_rsa_nist_vectors,
+            os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+            [
+                "SigGen15_186-2.rsp",
+                "SigGen15_186-3.rsp",
+                "SigVer15_186-3.rsp",
+            ],
+            hashes.SHA224(),
+            lambda params, hash_alg: padding.PKCS1v15(),
+        )
+    )
 
     test_rsa_pkcs1v15_verify_sha256 = pytest.mark.supported(
         only_if=lambda backend: (
-            backend.hash_supported(hashes.SHA256()) and
-            backend.rsa_padding_supported(padding.PKCS1v15())
+            backend.hash_supported(hashes.SHA256())
+            and backend.rsa_padding_supported(padding.PKCS1v15())
         ),
-        skip_message="Does not support SHA256 and PKCS1v1.5."
-    )(generate_rsa_verification_test(
-        load_rsa_nist_vectors,
-        os.path.join("asymmetric", "RSA", "FIPS_186-2"),
-        [
-            "SigGen15_186-2.rsp",
-            "SigGen15_186-3.rsp",
-            "SigVer15_186-3.rsp",
-        ],
-        hashes.SHA256(),
-        lambda params, hash_alg: padding.PKCS1v15()
-    ))
+        skip_message="Does not support SHA256 and PKCS1v1.5.",
+    )(
+        generate_rsa_verification_test(
+            load_rsa_nist_vectors,
+            os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+            [
+                "SigGen15_186-2.rsp",
+                "SigGen15_186-3.rsp",
+                "SigVer15_186-3.rsp",
+            ],
+            hashes.SHA256(),
+            lambda params, hash_alg: padding.PKCS1v15(),
+        )
+    )
 
     test_rsa_pkcs1v15_verify_sha384 = pytest.mark.supported(
         only_if=lambda backend: (
-            backend.hash_supported(hashes.SHA384()) and
-            backend.rsa_padding_supported(padding.PKCS1v15())
+            backend.hash_supported(hashes.SHA384())
+            and backend.rsa_padding_supported(padding.PKCS1v15())
         ),
-        skip_message="Does not support SHA384 and PKCS1v1.5."
-    )(generate_rsa_verification_test(
-        load_rsa_nist_vectors,
-        os.path.join("asymmetric", "RSA", "FIPS_186-2"),
-        [
-            "SigGen15_186-2.rsp",
-            "SigGen15_186-3.rsp",
-            "SigVer15_186-3.rsp",
-        ],
-        hashes.SHA384(),
-        lambda params, hash_alg: padding.PKCS1v15()
-    ))
+        skip_message="Does not support SHA384 and PKCS1v1.5.",
+    )(
+        generate_rsa_verification_test(
+            load_rsa_nist_vectors,
+            os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+            [
+                "SigGen15_186-2.rsp",
+                "SigGen15_186-3.rsp",
+                "SigVer15_186-3.rsp",
+            ],
+            hashes.SHA384(),
+            lambda params, hash_alg: padding.PKCS1v15(),
+        )
+    )
 
     test_rsa_pkcs1v15_verify_sha512 = pytest.mark.supported(
         only_if=lambda backend: (
-            backend.hash_supported(hashes.SHA512()) and
-            backend.rsa_padding_supported(padding.PKCS1v15())
+            backend.hash_supported(hashes.SHA512())
+            and backend.rsa_padding_supported(padding.PKCS1v15())
         ),
-        skip_message="Does not support SHA512 and PKCS1v1.5."
-    )(generate_rsa_verification_test(
-        load_rsa_nist_vectors,
-        os.path.join("asymmetric", "RSA", "FIPS_186-2"),
-        [
-            "SigGen15_186-2.rsp",
-            "SigGen15_186-3.rsp",
-            "SigVer15_186-3.rsp",
-        ],
-        hashes.SHA512(),
-        lambda params, hash_alg: padding.PKCS1v15()
-    ))
+        skip_message="Does not support SHA512 and PKCS1v1.5.",
+    )(
+        generate_rsa_verification_test(
+            load_rsa_nist_vectors,
+            os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+            [
+                "SigGen15_186-2.rsp",
+                "SigGen15_186-3.rsp",
+                "SigVer15_186-3.rsp",
+            ],
+            hashes.SHA512(),
+            lambda params, hash_alg: padding.PKCS1v15(),
+        )
+    )
 
 
 class TestPSS(object):
@@ -1344,20 +1450,12 @@
     def test_invalid_salt_length_not_integer(self):
         with pytest.raises(TypeError):
             padding.PSS(
-                mgf=padding.MGF1(
-                    hashes.SHA1()
-                ),
-                salt_length=b"not_a_length"
+                mgf=padding.MGF1(hashes.SHA1()), salt_length=b"not_a_length"
             )
 
     def test_invalid_salt_length_negative_integer(self):
         with pytest.raises(ValueError):
-            padding.PSS(
-                mgf=padding.MGF1(
-                    hashes.SHA1()
-                ),
-                salt_length=-1
-            )
+            padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=-1)
 
     def test_valid_pss_parameters(self):
         algorithm = hashes.SHA1()
@@ -1390,11 +1488,7 @@
     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)
 
 
 @pytest.mark.requires_backend_interface(interface=RSABackend)
@@ -1403,15 +1497,16 @@
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PKCS1v15()
         ),
-        skip_message="Does not support PKCS1v1.5."
+        skip_message="Does not support PKCS1v1.5.",
     )
     @pytest.mark.parametrize(
         "vector",
-        _flatten_pkcs1_examples(load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "RSA", "pkcs1v15crypt-vectors.txt"),
-            load_pkcs1_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
@@ -1423,12 +1518,11 @@
             dmq1=private["dmq1"],
             iqmp=private["iqmp"],
             public_numbers=rsa.RSAPublicNumbers(
-                e=private["public_exponent"],
-                n=private["modulus"]
-            )
+                e=private["public_exponent"], n=private["modulus"]
+            ),
         ).private_key(backend)
         ciphertext = binascii.unhexlify(example["encryption"])
-        assert len(ciphertext) == math.ceil(skey.key_size / 8.0)
+        assert len(ciphertext) == (skey.key_size + 7) // 8
         message = skey.decrypt(ciphertext, padding.PKCS1v15())
         assert message == binascii.unhexlify(example["message"])
 
@@ -1441,35 +1535,29 @@
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PKCS1v15()
         ),
-        skip_message="Does not support PKCS1v1.5."
+        skip_message="Does not support PKCS1v1.5.",
     )
     def test_decrypt_invalid_decrypt(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
         with pytest.raises(ValueError):
-            private_key.decrypt(
-                b"\x00" * 64,
-                padding.PKCS1v15()
-            )
+            private_key.decrypt(b"\x00" * 64, padding.PKCS1v15())
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PKCS1v15()
         ),
-        skip_message="Does not support PKCS1v1.5."
+        skip_message="Does not support PKCS1v1.5.",
     )
     def test_decrypt_ciphertext_too_large(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
         with pytest.raises(ValueError):
-            private_key.decrypt(
-                b"\x00" * 65,
-                padding.PKCS1v15()
-            )
+            private_key.decrypt(b"\x00" * 65, padding.PKCS1v15())
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PKCS1v15()
         ),
-        skip_message="Does not support PKCS1v1.5."
+        skip_message="Does not support PKCS1v1.5.",
     )
     def test_decrypt_ciphertext_too_small(self, backend):
         private_key = RSA_KEY_512.private_key(backend)
@@ -1478,28 +1566,28 @@
             b"69d210f2b9bdfb48b12f9ea05009c77da257cc600ccefe3a6283789d8ea0"
         )
         with pytest.raises(ValueError):
-            private_key.decrypt(
-                ct,
-                padding.PKCS1v15()
-            )
+            private_key.decrypt(ct, padding.PKCS1v15())
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.OAEP(
                 mgf=padding.MGF1(algorithm=hashes.SHA1()),
                 algorithm=hashes.SHA1(),
-                label=None
+                label=None,
             )
         ),
-        skip_message="Does not support OAEP."
+        skip_message="Does not support OAEP.",
     )
     @pytest.mark.parametrize(
         "vector",
-        _flatten_pkcs1_examples(load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "oaep-vect.txt"),
-            load_pkcs1_vectors
-        ))
+        _flatten_pkcs1_examples(
+            load_vectors_from_file(
+                os.path.join(
+                    "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "oaep-vect.txt"
+                ),
+                load_pkcs1_vectors,
+            )
+        ),
     )
     def test_decrypt_oaep_vectors(self, vector, backend):
         private, public, example = vector
@@ -1511,17 +1599,16 @@
             dmq1=private["dmq1"],
             iqmp=private["iqmp"],
             public_numbers=rsa.RSAPublicNumbers(
-                e=private["public_exponent"],
-                n=private["modulus"]
-            )
+                e=private["public_exponent"], n=private["modulus"]
+            ),
         ).private_key(backend)
         message = skey.decrypt(
             binascii.unhexlify(example["encryption"]),
             padding.OAEP(
                 mgf=padding.MGF1(algorithm=hashes.SHA1()),
                 algorithm=hashes.SHA1(),
-                label=None
-            )
+                label=None,
+            ),
         )
         assert message == binascii.unhexlify(example["message"])
 
@@ -1530,15 +1617,14 @@
             padding.OAEP(
                 mgf=padding.MGF1(algorithm=hashes.SHA224()),
                 algorithm=hashes.SHA224(),
-                label=None
+                label=None,
             )
         ),
-        skip_message="Does not support OAEP using SHA224 MGF1 and SHA224 hash."
+        skip_message=(
+            "Does not support OAEP using SHA224 MGF1 and SHA224 hash."
+        ),
     )
-    @pytest.mark.parametrize(
-        "vector",
-        _build_oaep_sha2_vectors()
-    )
+    @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(
@@ -1549,17 +1635,16 @@
             dmq1=private["dmq1"],
             iqmp=private["iqmp"],
             public_numbers=rsa.RSAPublicNumbers(
-                e=private["public_exponent"],
-                n=private["modulus"]
-            )
+                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
-            )
+                label=None,
+            ),
         )
         assert message == binascii.unhexlify(example["message"])
 
@@ -1568,24 +1653,24 @@
             padding.OAEP(
                 mgf=padding.MGF1(algorithm=hashes.SHA1()),
                 algorithm=hashes.SHA1(),
-                label=None
+                label=None,
             )
         ),
-        skip_message="Does not support OAEP."
+        skip_message="Does not support OAEP.",
     )
     def test_invalid_oaep_decryption(self, backend):
-        # More recent versions of OpenSSL may raise RSA_R_OAEP_DECODING_ERROR
-        # This test triggers it and confirms that we properly handle it. Other
-        # backends should also return the proper ValueError.
+        # 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)
 
         ciphertext = private_key.public_key().encrypt(
-            b'secure data',
+            b"secure data",
             padding.OAEP(
                 mgf=padding.MGF1(algorithm=hashes.SHA1()),
                 algorithm=hashes.SHA1(),
-                label=None
-            )
+                label=None,
+            ),
         )
 
         private_key_alt = RSA_KEY_512_ALT.private_key(backend)
@@ -1596,8 +1681,8 @@
                 padding.OAEP(
                     mgf=padding.MGF1(algorithm=hashes.SHA1()),
                     algorithm=hashes.SHA1(),
-                    label=None
-                )
+                    label=None,
+                ),
             )
 
     @pytest.mark.supported(
@@ -1605,27 +1690,27 @@
             padding.OAEP(
                 mgf=padding.MGF1(algorithm=hashes.SHA1()),
                 algorithm=hashes.SHA1(),
-                label=None
+                label=None,
             )
         ),
-        skip_message="Does not support OAEP."
+        skip_message="Does not support OAEP.",
     )
     def test_invalid_oaep_decryption_data_to_large_for_modulus(self, backend):
         key = RSA_KEY_2048_ALT.private_key(backend)
 
         ciphertext = (
-            b'\xb1ph\xc0\x0b\x1a|\xe6\xda\xea\xb5\xd7%\x94\x07\xf96\xfb\x96'
-            b'\x11\x9b\xdc4\xea.-\x91\x80\x13S\x94\x04m\xe9\xc5/F\x1b\x9b:\\'
-            b'\x1d\x04\x16ML\xae\xb32J\x01yuA\xbb\x83\x1c\x8f\xf6\xa5\xdbp\xcd'
-            b'\nx\xc7\xf6\x15\xb2/\xdcH\xae\xe7\x13\x13by\r4t\x99\x0fc\x1f\xc1'
-            b'\x1c\xb1\xdd\xc5\x08\xd1\xee\xa1XQ\xb8H@L5v\xc3\xaf\xf2\r\x97'
-            b'\xed\xaa\xe7\xf1\xd4xai\xd3\x83\xd9\xaa9\xbfx\xe1\x87F \x01\xff'
-            b'L\xccv}ae\xb3\xfa\xf2B\xb8\xf9\x04H\x94\x85\xcb\x86\xbb\\ghx!W31'
-            b'\xc7;t\na_E\xc2\x16\xb0;\xa1\x18\t\x1b\xe1\xdb\x80>)\x15\xc6\x12'
-            b'\xcb\xeeg`\x8b\x9b\x1b\x05y4\xb0\x84M6\xcd\xa1\x827o\xfd\x96\xba'
-            b'Z#\x8d\xae\x01\xc9\xf2\xb6\xde\x89{8&eQ\x1e8\x03\x01#?\xb66\\'
-            b'\xad.\xe9\xfa!\x95 c{\xcaz\xe0*\tP\r\x91\x9a)B\xb5\xadN\xf4$\x83'
-            b'\t\xb5u\xab\x19\x99'
+            b"\xb1ph\xc0\x0b\x1a|\xe6\xda\xea\xb5\xd7%\x94\x07\xf96\xfb\x96"
+            b"\x11\x9b\xdc4\xea.-\x91\x80\x13S\x94\x04m\xe9\xc5/F\x1b\x9b:\\"
+            b"\x1d\x04\x16ML\xae\xb32J\x01yuA\xbb\x83\x1c\x8f\xf6\xa5\xdbp\xcd"
+            b"\nx\xc7\xf6\x15\xb2/\xdcH\xae\xe7\x13\x13by\r4t\x99\x0fc\x1f\xc1"
+            b"\x1c\xb1\xdd\xc5\x08\xd1\xee\xa1XQ\xb8H@L5v\xc3\xaf\xf2\r\x97"
+            b"\xed\xaa\xe7\xf1\xd4xai\xd3\x83\xd9\xaa9\xbfx\xe1\x87F \x01\xff"
+            b"L\xccv}ae\xb3\xfa\xf2B\xb8\xf9\x04H\x94\x85\xcb\x86\xbb\\ghx!W31"
+            b"\xc7;t\na_E\xc2\x16\xb0;\xa1\x18\t\x1b\xe1\xdb\x80>)\x15\xc6\x12"
+            b"\xcb\xeeg`\x8b\x9b\x1b\x05y4\xb0\x84M6\xcd\xa1\x827o\xfd\x96\xba"
+            b"Z#\x8d\xae\x01\xc9\xf2\xb6\xde\x89{8&eQ\x1e8\x03\x01#?\xb66\\"
+            b"\xad.\xe9\xfa!\x95 c{\xcaz\xe0*\tP\r\x91\x9a)B\xb5\xadN\xf4$\x83"
+            b"\t\xb5u\xab\x19\x99"
         )
 
         with pytest.raises(ValueError):
@@ -1634,8 +1719,8 @@
                 padding.OAEP(
                     algorithm=hashes.SHA1(),
                     mgf=padding.MGF1(hashes.SHA1()),
-                    label=None
-                )
+                    label=None,
+                ),
             )
 
     def test_unsupported_oaep_mgf(self, backend):
@@ -1644,10 +1729,8 @@
             private_key.decrypt(
                 b"0" * 64,
                 padding.OAEP(
-                    mgf=DummyMGF(),
-                    algorithm=hashes.SHA1(),
-                    label=None
-                )
+                    mgf=DummyMGF(), algorithm=hashes.SHA1(), label=None
+                ),
             )
 
 
@@ -1658,25 +1741,34 @@
             padding.OAEP(
                 mgf=padding.MGF1(algorithm=hashes.SHA1()),
                 algorithm=hashes.SHA1(),
-                label=None
+                label=None,
             )
         ),
-        skip_message="Does not support OAEP."
+        skip_message="Does not support OAEP.",
     )
     @pytest.mark.parametrize(
         ("key_data", "pad"),
         itertools.product(
-            (RSA_KEY_1024, RSA_KEY_1025, RSA_KEY_1026, RSA_KEY_1027,
-             RSA_KEY_1028, RSA_KEY_1029, RSA_KEY_1030, RSA_KEY_1031,
-             RSA_KEY_1536, RSA_KEY_2048),
+            (
+                RSA_KEY_1024,
+                RSA_KEY_1025,
+                RSA_KEY_1026,
+                RSA_KEY_1027,
+                RSA_KEY_1028,
+                RSA_KEY_1029,
+                RSA_KEY_1030,
+                RSA_KEY_1031,
+                RSA_KEY_1536,
+                RSA_KEY_2048,
+            ),
             [
                 padding.OAEP(
                     mgf=padding.MGF1(algorithm=hashes.SHA1()),
                     algorithm=hashes.SHA1(),
-                    label=None
+                    label=None,
                 )
-            ]
-        )
+            ],
+        ),
     )
     def test_rsa_encrypt_oaep(self, key_data, pad, backend):
         private_key = key_data.private_key(backend)
@@ -1684,7 +1776,7 @@
         public_key = private_key.public_key()
         ct = public_key.encrypt(pt, pad)
         assert ct != pt
-        assert len(ct) == math.ceil(public_key.key_size / 8.0)
+        assert len(ct) == (public_key.key_size + 7) // 8
         recovered_pt = private_key.decrypt(ct, pad)
         assert recovered_pt == pt
 
@@ -1693,39 +1785,44 @@
             padding.OAEP(
                 mgf=padding.MGF1(algorithm=hashes.SHA256()),
                 algorithm=hashes.SHA512(),
-                label=None
+                label=None,
             )
         ),
-        skip_message="Does not support OAEP using SHA256 MGF1 and SHA512 hash."
+        skip_message=(
+            "Does not support OAEP using SHA256 MGF1 and SHA512 hash."
+        ),
     )
     @pytest.mark.parametrize(
         ("mgf1hash", "oaephash"),
-        itertools.product([
-            hashes.SHA1(),
-            hashes.SHA224(),
-            hashes.SHA256(),
-            hashes.SHA384(),
-            hashes.SHA512(),
-        ], [
-            hashes.SHA1(),
-            hashes.SHA224(),
-            hashes.SHA256(),
-            hashes.SHA384(),
-            hashes.SHA512(),
-        ])
+        itertools.product(
+            [
+                hashes.SHA1(),
+                hashes.SHA224(),
+                hashes.SHA256(),
+                hashes.SHA384(),
+                hashes.SHA512(),
+            ],
+            [
+                hashes.SHA1(),
+                hashes.SHA224(),
+                hashes.SHA256(),
+                hashes.SHA384(),
+                hashes.SHA512(),
+            ],
+        ),
     )
     def test_rsa_encrypt_oaep_sha2(self, mgf1hash, oaephash, backend):
         pad = padding.OAEP(
             mgf=padding.MGF1(algorithm=mgf1hash),
             algorithm=oaephash,
-            label=None
+            label=None,
         )
         private_key = RSA_KEY_2048.private_key(backend)
         pt = b"encrypt me using sha2 hashes!"
         public_key = private_key.public_key()
         ct = public_key.encrypt(pt, pad)
         assert ct != pt
-        assert len(ct) == math.ceil(public_key.key_size / 8.0)
+        assert len(ct) == (public_key.key_size + 7) // 8
         recovered_pt = private_key.decrypt(ct, pad)
         assert recovered_pt == pt
 
@@ -1733,16 +1830,25 @@
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PKCS1v15()
         ),
-        skip_message="Does not support PKCS1v1.5."
+        skip_message="Does not support PKCS1v1.5.",
     )
     @pytest.mark.parametrize(
         ("key_data", "pad"),
         itertools.product(
-            (RSA_KEY_1024, RSA_KEY_1025, RSA_KEY_1026, RSA_KEY_1027,
-             RSA_KEY_1028, RSA_KEY_1029, RSA_KEY_1030, RSA_KEY_1031,
-             RSA_KEY_1536, RSA_KEY_2048),
-            [padding.PKCS1v15()]
-        )
+            (
+                RSA_KEY_1024,
+                RSA_KEY_1025,
+                RSA_KEY_1026,
+                RSA_KEY_1027,
+                RSA_KEY_1028,
+                RSA_KEY_1029,
+                RSA_KEY_1030,
+                RSA_KEY_1031,
+                RSA_KEY_1536,
+                RSA_KEY_2048,
+            ),
+            [padding.PKCS1v15()],
+        ),
     )
     def test_rsa_encrypt_pkcs1v15(self, key_data, pad, backend):
         private_key = key_data.private_key(backend)
@@ -1750,42 +1856,45 @@
         public_key = private_key.public_key()
         ct = public_key.encrypt(pt, pad)
         assert ct != pt
-        assert len(ct) == math.ceil(public_key.key_size / 8.0)
+        assert len(ct) == (public_key.key_size + 7) // 8
         recovered_pt = private_key.decrypt(ct, pad)
         assert recovered_pt == pt
 
     @pytest.mark.parametrize(
         ("key_data", "pad"),
         itertools.product(
-            (RSA_KEY_1024, RSA_KEY_1025, RSA_KEY_1026, RSA_KEY_1027,
-             RSA_KEY_1028, RSA_KEY_1029, RSA_KEY_1030, RSA_KEY_1031,
-             RSA_KEY_1536, RSA_KEY_2048),
+            (
+                RSA_KEY_1024,
+                RSA_KEY_1025,
+                RSA_KEY_1026,
+                RSA_KEY_1027,
+                RSA_KEY_1028,
+                RSA_KEY_1029,
+                RSA_KEY_1030,
+                RSA_KEY_1031,
+                RSA_KEY_1536,
+                RSA_KEY_2048,
+            ),
             (
                 padding.OAEP(
                     mgf=padding.MGF1(algorithm=hashes.SHA1()),
                     algorithm=hashes.SHA1(),
-                    label=None
+                    label=None,
                 ),
-                padding.PKCS1v15()
-            )
-        )
+                padding.PKCS1v15(),
+            ),
+        ),
     )
     def test_rsa_encrypt_key_too_small(self, key_data, pad, backend):
         private_key = key_data.private_key(backend)
         public_key = private_key.public_key()
         # Slightly smaller than the key size but not enough for padding.
         with pytest.raises(ValueError):
-            public_key.encrypt(
-                b"\x00" * (private_key.key_size // 8 - 1),
-                pad
-            )
+            public_key.encrypt(b"\x00" * (private_key.key_size // 8 - 1), pad)
 
         # Larger than the key size.
         with pytest.raises(ValueError):
-            public_key.encrypt(
-                b"\x00" * (private_key.key_size // 8 + 5),
-                pad
-            )
+            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)
@@ -1804,10 +1913,8 @@
             public_key.encrypt(
                 b"ciphertext",
                 padding.OAEP(
-                    mgf=DummyMGF(),
-                    algorithm=hashes.SHA1(),
-                    label=None
-                )
+                    mgf=DummyMGF(), algorithm=hashes.SHA1(), label=None
+                ),
             )
 
 
@@ -1827,7 +1934,7 @@
             dmp1=1,
             dmq1=1,
             iqmp=2,
-            public_numbers=public_numbers
+            public_numbers=public_numbers,
         )
 
         assert private_numbers.p == 3
@@ -1846,6 +1953,9 @@
         public_key = RSA_KEY_1024.public_numbers.public_key(backend)
         assert public_key
 
+        public_key = rsa.RSAPublicNumbers(n=10, e=3).public_key(backend)
+        assert public_key
+
     def test_public_numbers_invalid_types(self):
         with pytest.raises(TypeError):
             rsa.RSAPublicNumbers(e=None, n=15)
@@ -1863,18 +1973,20 @@
             (3, 5, 1, 1, None, 2, rsa.RSAPublicNumbers(e=1, n=15)),
             (3, 5, 1, 1, 1, None, rsa.RSAPublicNumbers(e=1, n=15)),
             (3, 5, 1, 1, 1, 2, None),
-        ]
+        ],
     )
-    def test_private_numbers_invalid_types(self, p, q, d, dmp1, dmq1, iqmp,
-                                           public_numbers):
+    def test_private_numbers_invalid_types(
+        self, p, q, d, dmp1, dmq1, iqmp, public_numbers
+    ):
         with pytest.raises(TypeError):
             rsa.RSAPrivateNumbers(
-                p=p, q=q,
+                p=p,
+                q=q,
                 d=d,
                 dmp1=dmp1,
                 dmq1=dmq1,
                 iqmp=iqmp,
-                public_numbers=public_numbers
+                public_numbers=public_numbers,
             )
 
     @pytest.mark.parametrize(
@@ -1884,7 +1996,7 @@
             (1, 15),  # public_exponent < 3
             (17, 15),  # public_exponent > modulus
             (14, 15),  # public_exponent not odd
-        ]
+        ],
     )
     def test_invalid_public_numbers_argument_values(self, e, n, backend):
         # Start with public_exponent=7, modulus=15. Then change one value at a
@@ -1909,10 +2021,11 @@
             (3, 11, 3, 1, 3, 2, 6, 33),  # public_exponent is not odd
             (3, 11, 3, 2, 3, 2, 7, 33),  # dmp1 is not odd
             (3, 11, 3, 1, 4, 2, 7, 33),  # dmq1 is not odd
-        ]
+        ],
     )
-    def test_invalid_private_numbers_argument_values(self, p, q, d, dmp1, dmq1,
-                                                     iqmp, e, n, backend):
+    def test_invalid_private_numbers_argument_values(
+        self, p, q, d, dmp1, dmq1, iqmp, e, n, backend
+    ):
         # Start with p=3, q=11, private_exponent=3, public_exponent=7,
         # modulus=33, dmp1=1, dmq1=3, iqmp=2. Then change one value at
         # a time to test the bounds.
@@ -1925,10 +2038,7 @@
                 dmp1=dmp1,
                 dmq1=dmq1,
                 iqmp=iqmp,
-                public_numbers=rsa.RSAPublicNumbers(
-                    e=e,
-                    n=n
-                )
+                public_numbers=rsa.RSAPublicNumbers(e=e, n=n),
             ).private_key(backend)
 
     def test_public_number_repr(self):
@@ -2004,18 +2114,19 @@
 class TestRSAPrimeFactorRecovery(object):
     @pytest.mark.parametrize(
         "vector",
-        _flatten_pkcs1_examples(load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "RSA", "pkcs1v15crypt-vectors.txt"),
-            load_pkcs1_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"]
+            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
@@ -2037,22 +2148,23 @@
         itertools.product(
             [
                 serialization.PrivateFormat.TraditionalOpenSSL,
-                serialization.PrivateFormat.PKCS8
+                serialization.PrivateFormat.PKCS8,
             ],
             [
                 b"s",
                 b"longerpassword",
                 b"!*$&(@#$*&($T@%_somesymbols",
                 b"\x01" * 1000,
-            ]
-        )
+            ],
+        ),
     )
     def test_private_bytes_encrypted_pem(self, backend, fmt, password):
+        skip_fips_traditional_openssl(backend, fmt)
         key = RSA_KEY_2048.private_key(backend)
         serialized = key.private_bytes(
             serialization.Encoding.PEM,
             fmt,
-            serialization.BestAvailableEncryption(password)
+            serialization.BestAvailableEncryption(password),
         )
         loaded_key = serialization.load_pem_private_key(
             serialized, password, backend
@@ -2068,7 +2180,7 @@
             (serialization.Encoding.DER, serialization.PrivateFormat.Raw),
             (serialization.Encoding.Raw, serialization.PrivateFormat.Raw),
             (serialization.Encoding.X962, serialization.PrivateFormat.PKCS8),
-        ]
+        ],
     )
     def test_private_bytes_rejects_invalid(self, encoding, fmt, backend):
         key = RSA_KEY_2048.private_key(backend)
@@ -2081,15 +2193,15 @@
             [serialization.PrivateFormat.PKCS8, b"s"],
             [serialization.PrivateFormat.PKCS8, b"longerpassword"],
             [serialization.PrivateFormat.PKCS8, b"!*$&(@#$*&($T@%_somesymbol"],
-            [serialization.PrivateFormat.PKCS8, b"\x01" * 1000]
-        ]
+            [serialization.PrivateFormat.PKCS8, b"\x01" * 1000],
+        ],
     )
     def test_private_bytes_encrypted_der(self, backend, fmt, password):
         key = RSA_KEY_2048.private_key(backend)
         serialized = key.private_bytes(
             serialization.Encoding.DER,
             fmt,
-            serialization.BestAvailableEncryption(password)
+            serialization.BestAvailableEncryption(password),
         )
         loaded_key = serialization.load_der_private_key(
             serialized, password, backend
@@ -2104,27 +2216,28 @@
             [
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.TraditionalOpenSSL,
-                serialization.load_pem_private_key
+                serialization.load_pem_private_key,
             ],
             [
                 serialization.Encoding.DER,
                 serialization.PrivateFormat.TraditionalOpenSSL,
-                serialization.load_der_private_key
+                serialization.load_der_private_key,
             ],
             [
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.PKCS8,
-                serialization.load_pem_private_key
+                serialization.load_pem_private_key,
             ],
             [
                 serialization.Encoding.DER,
                 serialization.PrivateFormat.PKCS8,
-                serialization.load_der_private_key
+                serialization.load_der_private_key,
             ],
-        ]
+        ],
     )
-    def test_private_bytes_unencrypted(self, backend, encoding, fmt,
-                                       loader_func):
+    def test_private_bytes_unencrypted(
+        self, backend, encoding, fmt, loader_func
+    ):
         key = RSA_KEY_2048.private_key(backend)
         serialized = key.private_bytes(
             encoding, fmt, serialization.NoEncryption()
@@ -2134,6 +2247,9 @@
         priv_num = key.private_numbers()
         assert loaded_priv_num == priv_num
 
+    @pytest.mark.skip_fips(
+        reason="Traditional OpenSSL key format is not supported in FIPS mode."
+    )
     @pytest.mark.parametrize(
         ("key_path", "encoding", "loader_func"),
         [
@@ -2141,17 +2257,17 @@
                 os.path.join(
                     "asymmetric",
                     "Traditional_OpenSSL_Serialization",
-                    "testrsa.pem"
+                    "testrsa.pem",
                 ),
                 serialization.Encoding.PEM,
-                serialization.load_pem_private_key
+                serialization.load_pem_private_key,
             ],
             [
                 os.path.join("asymmetric", "DER_Serialization", "testrsa.der"),
                 serialization.Encoding.DER,
-                serialization.load_der_private_key
+                serialization.load_der_private_key,
             ],
-        ]
+        ],
     )
     def test_private_bytes_traditional_openssl_unencrypted(
         self, backend, key_path, encoding, loader_func
@@ -2163,7 +2279,7 @@
         serialized = key.private_bytes(
             encoding,
             serialization.PrivateFormat.TraditionalOpenSSL,
-            serialization.NoEncryption()
+            serialization.NoEncryption(),
         )
         assert serialized == key_bytes
 
@@ -2173,7 +2289,7 @@
             key.private_bytes(
                 serialization.Encoding.DER,
                 serialization.PrivateFormat.TraditionalOpenSSL,
-                serialization.BestAvailableEncryption(b"password")
+                serialization.BestAvailableEncryption(b"password"),
             )
 
     def test_private_bytes_invalid_encoding(self, backend):
@@ -2182,7 +2298,7 @@
             key.private_bytes(
                 "notencoding",
                 serialization.PrivateFormat.PKCS8,
-                serialization.NoEncryption()
+                serialization.NoEncryption(),
             )
 
     def test_private_bytes_invalid_format(self, backend):
@@ -2191,7 +2307,7 @@
             key.private_bytes(
                 serialization.Encoding.PEM,
                 "invalidformat",
-                serialization.NoEncryption()
+                serialization.NoEncryption(),
             )
 
     def test_private_bytes_invalid_encryption_algorithm(self, backend):
@@ -2200,7 +2316,7 @@
             key.private_bytes(
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.TraditionalOpenSSL,
-                "notanencalg"
+                "notanencalg",
             )
 
     def test_private_bytes_unsupported_encryption_type(self, backend):
@@ -2209,7 +2325,7 @@
             key.private_bytes(
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.TraditionalOpenSSL,
-                DummyKeySerializationEncryption()
+                DummyKeySerializationEncryption(),
             )
 
 
@@ -2224,30 +2340,34 @@
                 serialization.load_pem_public_key,
                 serialization.Encoding.PEM,
                 serialization.PublicFormat.PKCS1,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "public", "PKCS1", "rsa.pub.der"),
                 serialization.load_der_public_key,
                 serialization.Encoding.DER,
                 serialization.PublicFormat.PKCS1,
-            ), (
+            ),
+            (
                 os.path.join("asymmetric", "PKCS8", "unenc-rsa-pkcs8.pub.pem"),
                 serialization.load_pem_public_key,
                 serialization.Encoding.PEM,
                 serialization.PublicFormat.SubjectPublicKeyInfo,
-            ), (
+            ),
+            (
                 os.path.join(
                     "asymmetric",
                     "DER_Serialization",
-                    "unenc-rsa-pkcs8.pub.der"
+                    "unenc-rsa-pkcs8.pub.der",
                 ),
                 serialization.load_der_public_key,
                 serialization.Encoding.DER,
                 serialization.PublicFormat.SubjectPublicKeyInfo,
-            )
-        ]
+            ),
+        ],
     )
-    def test_public_bytes_match(self, key_path, loader_func, encoding, format,
-                                backend):
+    def test_public_bytes_match(
+        self, key_path, loader_func, encoding, format, backend
+    ):
         key_bytes = load_vectors_from_file(
             key_path, lambda pemfile: pemfile.read(), mode="rb"
         )
@@ -2258,7 +2378,8 @@
     def test_public_bytes_openssh(self, backend):
         key_bytes = load_vectors_from_file(
             os.path.join("asymmetric", "public", "PKCS1", "rsa.pub.pem"),
-            lambda pemfile: pemfile.read(), mode="rb"
+            lambda pemfile: pemfile.read(),
+            mode="rb",
         )
         key = serialization.load_pem_public_key(key_bytes, backend)
 
@@ -2306,22 +2427,25 @@
         [
             (
                 serialization.Encoding.Raw,
-                serialization.PublicFormat.SubjectPublicKeyInfo
+                serialization.PublicFormat.SubjectPublicKeyInfo,
             ),
             (serialization.Encoding.Raw, serialization.PublicFormat.PKCS1),
-        ] + list(itertools.product(
-            [
-                serialization.Encoding.Raw,
-                serialization.Encoding.X962,
-                serialization.Encoding.PEM,
-                serialization.Encoding.DER
-            ],
-            [
-                serialization.PublicFormat.Raw,
-                serialization.PublicFormat.UncompressedPoint,
-                serialization.PublicFormat.CompressedPoint
-            ]
-        ))
+        ]
+        + list(
+            itertools.product(
+                [
+                    serialization.Encoding.Raw,
+                    serialization.Encoding.X962,
+                    serialization.Encoding.PEM,
+                    serialization.Encoding.DER,
+                ],
+                [
+                    serialization.PublicFormat.Raw,
+                    serialization.PublicFormat.UncompressedPoint,
+                    serialization.PublicFormat.CompressedPoint,
+                ],
+            )
+        ),
     )
     def test_public_bytes_rejects_invalid(self, encoding, fmt, backend):
         key = RSA_KEY_2048.private_key(backend).public_key()
diff --git a/tests/hazmat/primitives/test_scrypt.py b/tests/hazmat/primitives/test_scrypt.py
index 8f3a14e..52e7e15 100644
--- a/tests/hazmat/primitives/test_scrypt.py
+++ b/tests/hazmat/primitives/test_scrypt.py
@@ -10,7 +10,9 @@
 import pytest
 
 from cryptography.exceptions import (
-    AlreadyFinalized, InvalidKey, UnsupportedAlgorithm
+    AlreadyFinalized,
+    InvalidKey,
+    UnsupportedAlgorithm,
 )
 from cryptography.hazmat.backends.interfaces import ScryptBackend
 from cryptography.hazmat.primitives.kdf.scrypt import Scrypt, _MEM_LIMIT
@@ -18,7 +20,8 @@
 from tests.utils import load_nist_vectors, load_vectors_from_file
 
 vectors = load_vectors_from_file(
-    os.path.join("KDF", "scrypt.txt"), load_nist_vectors)
+    os.path.join("KDF", "scrypt.txt"), load_nist_vectors
+)
 
 
 def _skip_if_memory_limited(memory_limit, params):
@@ -29,8 +32,10 @@
     vlen = 32 * int(params["r"]) * (int(params["n"]) + 2) * 4
     memory_required = blen + vlen
     if memory_limit < memory_required:
-        pytest.skip("Test exceeds Scrypt memory limit. "
-                    "This is likely a 32-bit platform.")
+        pytest.skip(
+            "Test exceeds Scrypt memory limit. "
+            "This is likely a 32-bit platform."
+        )
 
 
 def test_memory_limit_skip():
@@ -53,8 +58,14 @@
         salt = params["salt"]
         derived_key = params["derived_key"]
 
-        scrypt = Scrypt(salt, length, work_factor, block_size,
-                        parallelization_factor, backend)
+        scrypt = Scrypt(
+            salt,
+            length,
+            work_factor,
+            block_size,
+            parallelization_factor,
+            backend,
+        )
         assert binascii.hexlify(scrypt.derive(password)) == derived_key
 
     def test_unsupported_backend(self):
@@ -66,8 +77,14 @@
         backend = object()
 
         with pytest.raises(UnsupportedAlgorithm):
-            Scrypt(salt, length, work_factor, block_size,
-                   parallelization_factor, backend)
+            Scrypt(
+                salt,
+                length,
+                work_factor,
+                block_size,
+                parallelization_factor,
+                backend,
+            )
 
     def test_salt_not_bytes(self, backend):
         work_factor = 1024
@@ -77,8 +94,14 @@
         salt = 1
 
         with pytest.raises(TypeError):
-            Scrypt(salt, length, work_factor, block_size,
-                   parallelization_factor, backend)
+            Scrypt(
+                salt,
+                length,
+                work_factor,
+                block_size,
+                parallelization_factor,
+                backend,
+            )
 
     def test_scrypt_malloc_failure(self, backend):
         password = b"NaCl"
@@ -88,8 +111,14 @@
         length = 64
         salt = b"NaCl"
 
-        scrypt = Scrypt(salt, length, work_factor, block_size,
-                        parallelization_factor, backend)
+        scrypt = Scrypt(
+            salt,
+            length,
+            work_factor,
+            block_size,
+            parallelization_factor,
+            backend,
+        )
 
         with pytest.raises(MemoryError):
             scrypt.derive(password)
@@ -102,8 +131,14 @@
         length = 64
         salt = b"NaCl"
 
-        scrypt = Scrypt(salt, length, work_factor, block_size,
-                        parallelization_factor, backend)
+        scrypt = Scrypt(
+            salt,
+            length,
+            work_factor,
+            block_size,
+            parallelization_factor,
+            backend,
+        )
 
         with pytest.raises(TypeError):
             scrypt.derive(password)
@@ -116,10 +151,16 @@
         length = 10
         salt = b"NaCl"
 
-        scrypt = Scrypt(salt, length, work_factor, block_size,
-                        parallelization_factor, backend)
+        scrypt = Scrypt(
+            salt,
+            length,
+            work_factor,
+            block_size,
+            parallelization_factor,
+            backend,
+        )
 
-        assert scrypt.derive(password) == b'\xf4\x92\x86\xb2\x06\x0c\x848W\x87'
+        assert scrypt.derive(password) == b"\xf4\x92\x86\xb2\x06\x0c\x848W\x87"
 
     @pytest.mark.parametrize("params", vectors)
     def test_verify(self, backend, params):
@@ -132,8 +173,14 @@
         salt = params["salt"]
         derived_key = params["derived_key"]
 
-        scrypt = Scrypt(salt, length, work_factor, block_size,
-                        parallelization_factor, backend)
+        scrypt = Scrypt(
+            salt,
+            length,
+            work_factor,
+            block_size,
+            parallelization_factor,
+            backend,
+        )
         assert scrypt.verify(password, binascii.unhexlify(derived_key)) is None
 
     def test_invalid_verify(self, backend):
@@ -145,8 +192,14 @@
         salt = b"NaCl"
         derived_key = b"fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e773"
 
-        scrypt = Scrypt(salt, length, work_factor, block_size,
-                        parallelization_factor, backend)
+        scrypt = Scrypt(
+            salt,
+            length,
+            work_factor,
+            block_size,
+            parallelization_factor,
+            backend,
+        )
 
         with pytest.raises(InvalidKey):
             scrypt.verify(password, binascii.unhexlify(derived_key))
@@ -159,8 +212,14 @@
         length = 64
         salt = b"NaCl"
 
-        scrypt = Scrypt(salt, length, work_factor, block_size,
-                        parallelization_factor, backend)
+        scrypt = Scrypt(
+            salt,
+            length,
+            work_factor,
+            block_size,
+            parallelization_factor,
+            backend,
+        )
         scrypt.derive(password)
         with pytest.raises(AlreadyFinalized):
             scrypt.derive(password)
diff --git a/tests/hazmat/primitives/test_seed.py b/tests/hazmat/primitives/test_seed.py
index 29cae4f..66da978 100644
--- a/tests/hazmat/primitives/test_seed.py
+++ b/tests/hazmat/primitives/test_seed.py
@@ -24,7 +24,7 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestSEEDModeECB(object):
-    test_ECB = generate_encrypt_test(
+    test_ecb = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "SEED"),
         ["rfc-4269.txt"],
@@ -41,12 +41,12 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestSEEDModeCBC(object):
-    test_CBC = generate_encrypt_test(
+    test_cbc = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "SEED"),
         ["rfc-4196.txt"],
         lambda key, **kwargs: algorithms.SEED(binascii.unhexlify((key))),
-        lambda iv, **kwargs: modes.CBC(binascii.unhexlify(iv))
+        lambda iv, **kwargs: modes.CBC(binascii.unhexlify(iv)),
     )
 
 
@@ -58,12 +58,12 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestSEEDModeOFB(object):
-    test_OFB = generate_encrypt_test(
+    test_ofb = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "SEED"),
         ["seed-ofb.txt"],
         lambda key, **kwargs: algorithms.SEED(binascii.unhexlify((key))),
-        lambda iv, **kwargs: modes.OFB(binascii.unhexlify(iv))
+        lambda iv, **kwargs: modes.OFB(binascii.unhexlify(iv)),
     )
 
 
@@ -75,10 +75,10 @@
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 class TestSEEDModeCFB(object):
-    test_CFB = generate_encrypt_test(
+    test_cfb = generate_encrypt_test(
         load_nist_vectors,
         os.path.join("ciphers", "SEED"),
         ["seed-cfb.txt"],
         lambda key, **kwargs: algorithms.SEED(binascii.unhexlify((key))),
-        lambda iv, **kwargs: modes.CFB(binascii.unhexlify(iv))
+        lambda iv, **kwargs: modes.CFB(binascii.unhexlify(iv)),
     )
diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py
index 5dd7248..32debd4 100644
--- a/tests/hazmat/primitives/test_serialization.py
+++ b/tests/hazmat/primitives/test_serialization.py
@@ -11,27 +11,58 @@
 
 import pytest
 
-from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
+import six
+
+from cryptography.exceptions import UnsupportedAlgorithm
 from cryptography.hazmat.backends.interfaces import (
-    DERSerializationBackend, DSABackend, EllipticCurveBackend,
-    PEMSerializationBackend, RSABackend
+    DERSerializationBackend,
+    DSABackend,
+    EllipticCurveBackend,
+    PEMSerializationBackend,
+    RSABackend,
 )
-from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
+from cryptography.hazmat.primitives.asymmetric import (
+    dsa,
+    ec,
+    ed25519,
+    ed448,
+    rsa,
+    x25519,
+    x448,
+)
 from cryptography.hazmat.primitives.serialization import (
-    BestAvailableEncryption, Encoding, NoEncryption,
-    PrivateFormat, PublicFormat,
-    load_der_parameters, load_der_private_key,
-    load_der_public_key, load_pem_parameters, load_pem_private_key,
-    load_pem_public_key, load_ssh_public_key
+    BestAvailableEncryption,
+    Encoding,
+    NoEncryption,
+    PrivateFormat,
+    PublicFormat,
+    load_der_parameters,
+    load_der_private_key,
+    load_der_public_key,
+    load_pem_parameters,
+    load_pem_private_key,
+    load_pem_public_key,
+    load_ssh_private_key,
+    load_ssh_public_key,
+    ssh,
 )
 
 
 from .test_ec import _skip_curve_unsupported
 from .utils import (
-    _check_dsa_private_numbers, _check_rsa_private_numbers,
-    load_vectors_from_file
+    _check_dsa_private_numbers,
+    _check_rsa_private_numbers,
+    load_vectors_from_file,
 )
-from ...utils import raises_unsupported_algorithm
+from ...doubles import DummyKeySerializationEncryption
+
+
+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")
 
 
 class TestBufferProtocolSerialization(object):
@@ -43,12 +74,13 @@
             (["DER_Serialization", "enc2-rsa-pkcs8.der"], bytearray(b"baz")),
             (["DER_Serialization", "unenc-rsa-pkcs8.der"], None),
             (["DER_Serialization", "testrsa.der"], None),
-        ]
+        ],
     )
     def test_load_der_rsa_private_key(self, key_path, password, backend):
         data = load_vectors_from_file(
             os.path.join("asymmetric", *key_path),
-            lambda derfile: derfile.read(), mode="rb"
+            lambda derfile: derfile.read(),
+            mode="rb",
         )
         key = load_der_private_key(bytearray(data), password, backend)
         assert key
@@ -61,21 +93,23 @@
         [
             (
                 ["PEM_Serialization", "rsa_private_key.pem"],
-                bytearray(b"123456")
+                bytearray(b"123456"),
             ),
             (["PKCS8", "unenc-rsa-pkcs8.pem"], None),
             (["PKCS8", "enc-rsa-pkcs8.pem"], bytearray(b"foobar")),
             (["PKCS8", "enc2-rsa-pkcs8.pem"], bytearray(b"baz")),
             (
                 ["Traditional_OpenSSL_Serialization", "key1.pem"],
-                bytearray(b"123456")
+                bytearray(b"123456"),
             ),
-        ]
+        ],
     )
     def test_load_pem_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 pemfile: pemfile.read(), mode="rb"
+            lambda pemfile: pemfile.read(),
+            mode="rb",
         )
         key = load_pem_private_key(bytearray(data), password, backend)
         assert key
@@ -93,7 +127,7 @@
             (["DER_Serialization", "enc2-rsa-pkcs8.der"], b"baz"),
             (["DER_Serialization", "unenc-rsa-pkcs8.der"], None),
             (["DER_Serialization", "testrsa.der"], None),
-        ]
+        ],
     )
     def test_load_der_rsa_private_key(self, key_path, password, backend):
         key = load_vectors_from_file(
@@ -101,7 +135,7 @@
             lambda derfile: load_der_private_key(
                 derfile.read(), password, backend
             ),
-            mode="rb"
+            mode="rb",
         )
         assert key
         assert isinstance(key, rsa.RSAPrivateKey)
@@ -115,7 +149,7 @@
             (["DER_Serialization", "dsa.1024.der"], None),
             (["DER_Serialization", "dsa.2048.der"], None),
             (["DER_Serialization", "dsa.3072.der"], None),
-        ]
+        ],
     )
     def test_load_der_dsa_private_key(self, key_path, password, backend):
         key = load_vectors_from_file(
@@ -123,17 +157,14 @@
             lambda derfile: load_der_private_key(
                 derfile.read(), password, backend
             ),
-            mode="rb"
+            mode="rb",
         )
         assert key
         assert isinstance(key, dsa.DSAPrivateKey)
         _check_dsa_private_numbers(key.private_numbers())
 
     @pytest.mark.parametrize(
-        "key_path",
-        [
-            ["DER_Serialization", "enc-rsa-pkcs8.der"],
-        ]
+        "key_path", [["DER_Serialization", "enc-rsa-pkcs8.der"]]
     )
     @pytest.mark.requires_backend_interface(interface=RSABackend)
     def test_password_not_bytes(self, key_path, backend):
@@ -146,7 +177,7 @@
                 lambda derfile: load_der_private_key(
                     derfile.read(), password, backend
                 ),
-                mode="rb"
+                mode="rb",
             )
 
     @pytest.mark.parametrize(
@@ -154,7 +185,7 @@
         [
             (["DER_Serialization", "ec_private_key.der"], None),
             (["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):
@@ -164,7 +195,7 @@
             lambda derfile: load_der_private_key(
                 derfile.read(), password, backend
             ),
-            mode="rb"
+            mode="rb",
         )
 
         assert key
@@ -173,10 +204,7 @@
         assert key.curve.key_size == 256
 
     @pytest.mark.parametrize(
-        "key_path",
-        [
-            ["DER_Serialization", "enc-rsa-pkcs8.der"],
-        ]
+        "key_path", [["DER_Serialization", "enc-rsa-pkcs8.der"]]
     )
     @pytest.mark.requires_backend_interface(interface=RSABackend)
     def test_wrong_password(self, key_path, backend):
@@ -189,14 +217,11 @@
                 lambda derfile: load_der_private_key(
                     derfile.read(), password, backend
                 ),
-                mode="rb"
+                mode="rb",
             )
 
     @pytest.mark.parametrize(
-        "key_path",
-        [
-            ["DER_Serialization", "unenc-rsa-pkcs8.der"]
-        ]
+        "key_path", [["DER_Serialization", "unenc-rsa-pkcs8.der"]]
     )
     @pytest.mark.requires_backend_interface(interface=RSABackend)
     def test_unused_password(self, key_path, backend):
@@ -209,17 +234,14 @@
                 lambda derfile: load_der_private_key(
                     derfile.read(), password, backend
                 ),
-                mode="rb"
+                mode="rb",
             )
 
     @pytest.mark.parametrize(
         ("key_path", "password"),
         itertools.product(
-            [
-                ["DER_Serialization", "enc-rsa-pkcs8.der"],
-            ],
-            [b"", None]
-        )
+            [["DER_Serialization", "enc-rsa-pkcs8.der"]], [b"", None]
+        ),
     )
     @pytest.mark.requires_backend_interface(interface=RSABackend)
     def test_missing_password(self, key_path, password, backend):
@@ -231,16 +253,14 @@
                 lambda derfile: load_der_private_key(
                     derfile.read(), password, backend
                 ),
-                mode="rb"
+                mode="rb",
             )
 
     def test_wrong_format(self, backend):
         key_data = b"---- NOT A KEY ----\n"
 
         with pytest.raises(ValueError):
-            load_der_private_key(
-                key_data, None, backend
-            )
+            load_der_private_key(key_data, None, backend)
 
         with pytest.raises(ValueError):
             load_der_private_key(
@@ -249,7 +269,8 @@
 
     def test_corrupt_der_pkcs8(self, backend):
         # unenc-rsa-pkcs8 with a bunch of data missing.
-        key_data = textwrap.dedent("""\
+        key_data = textwrap.dedent(
+            """\
         MIICdQIBADALBgkqhkiG9w0BAQEEggJhMIICXQIBAAKBgQC7JHoJfg6yNzLMOWet
         8Z49a4KD0dCspMAYvo2YAMB7/wdEycocujbhJ2n/seONi+5XqTqqFkM5VBl8rmkk
         FPZk/7x0xmdsTPECSWnHK+HhoaNDFPR3j8jQhVo1laxiqcEhAHegi5cwtFosuJAv
@@ -263,13 +284,12 @@
         z+KOpdpPRR5TQmbEMEspjsFpFymMiuYPgmihQbO2cJl1qScY5OkCQQCJ6m5tcN8l
         Xxg/SNpjEIv+qAyUD96XVlOJlOIeLHQ8kYE0C6ZA+MsqYIzgAreJk88Yn0lU/X0/
         mu/UpE/BRZmR
-        """).encode()
+        """
+        ).encode()
         bad_der = base64.b64decode(b"".join(key_data.splitlines()))
 
         with pytest.raises(ValueError):
-            load_der_private_key(
-                bad_der, None, backend
-            )
+            load_der_private_key(bad_der, None, backend)
 
         with pytest.raises(ValueError):
             load_der_private_key(
@@ -278,14 +298,16 @@
 
     def test_corrupt_traditional_format_der(self, backend):
         # privkey with a bunch of data missing.
-        key_data = textwrap.dedent("""\
+        key_data = textwrap.dedent(
+            """\
         MIIBPAIBAAJBAKrbeqkuRk8VcRmWFmtP+LviMB3+6dizWW3DwaffznyHGAFwUJ/I
         Tv0XtbsCyl3QoyKGhrOAy3RvPK5M38iuXT0CAwEAAQJAZ3cnzaHXM/bxGaR5CR1R
         rD1qFBAVfoQFiOH9uPJgMaoAuoQEisPHVcZDKcOv4wEg6/TInAIXBnEigtqvRzuy
         mvcpHZwQJdmdHHkGKAs37Dfxi67HbkUCIQCeZGliHXFa071Fp06ZeWlR2ADonTZz
         rJBhdTe0v5pCeQIhAIZfkiGgGBX4cIuuckzEm43g9WMUjxP/0GlK39vIyihxAiEA
         mymehFRT0MvqW5xAKAx7Pgkt8HVKwVhc2LwGKHE0DZM=
-        """).encode()
+        """
+        ).encode()
         bad_der = base64.b64decode(b"".join(key_data.splitlines()))
 
         with pytest.raises(ValueError):
@@ -300,20 +322,20 @@
         "key_file",
         [
             os.path.join(
-                "asymmetric", "DER_Serialization", "unenc-rsa-pkcs8.pub.der"),
+                "asymmetric", "DER_Serialization", "unenc-rsa-pkcs8.pub.der"
+            ),
             os.path.join(
-                "asymmetric", "DER_Serialization", "rsa_public_key.der"),
+                "asymmetric", "DER_Serialization", "rsa_public_key.der"
+            ),
             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,
-            lambda derfile: load_der_public_key(
-                derfile.read(), backend
-            ),
-            mode="rb"
+            lambda derfile: load_der_public_key(derfile.read(), backend),
+            mode="rb",
         )
         assert key
         assert isinstance(key, rsa.RSAPublicKey)
@@ -328,19 +350,19 @@
         "key_file",
         [
             os.path.join(
-                "asymmetric", "DER_Serialization", "unenc-dsa-pkcs8.pub.der"),
+                "asymmetric", "DER_Serialization", "unenc-dsa-pkcs8.pub.der"
+            ),
             os.path.join(
-                "asymmetric", "DER_Serialization", "dsa_public_key.der"),
-        ]
+                "asymmetric", "DER_Serialization", "dsa_public_key.der"
+            ),
+        ],
     )
     @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,
-            lambda derfile: load_der_public_key(
-                derfile.read(), backend
-            ),
-            mode="rb"
+            lambda derfile: load_der_public_key(derfile.read(), backend),
+            mode="rb",
         )
         assert key
         assert isinstance(key, dsa.DSAPublicKey)
@@ -350,12 +372,10 @@
         _skip_curve_unsupported(backend, ec.SECP256R1())
         key = load_vectors_from_file(
             os.path.join(
-                "asymmetric", "DER_Serialization",
-                "ec_public_key.der"),
-            lambda derfile: load_der_public_key(
-                derfile.read(), backend
+                "asymmetric", "DER_Serialization", "ec_public_key.der"
             ),
-            mode="rb"
+            lambda derfile: load_der_public_key(derfile.read(), backend),
+            mode="rb",
         )
         assert key
         assert isinstance(key, ec.EllipticCurvePublicKey)
@@ -366,9 +386,7 @@
         param_data = b"---- NOT A KEY ----\n"
 
         with pytest.raises(ValueError):
-            load_der_parameters(
-                param_data, backend
-            )
+            load_der_parameters(param_data, backend)
 
 
 @pytest.mark.requires_backend_interface(interface=PEMSerializationBackend)
@@ -393,16 +411,19 @@
             (["Traditional_OpenSSL_Serialization", "key1.pem"], b"123456"),
             (["Traditional_OpenSSL_Serialization", "key2.pem"], b"a123456"),
             (["Traditional_OpenSSL_Serialization", "testrsa.pem"], None),
-            (["Traditional_OpenSSL_Serialization", "testrsa-encrypted.pem"],
-             b"password"),
-        ]
+            (
+                ["Traditional_OpenSSL_Serialization", "testrsa-encrypted.pem"],
+                b"password",
+            ),
+        ],
     )
     def test_load_pem_rsa_private_key(self, key_file, password, backend):
+        _skip_fips_format(key_file, password, backend)
         key = load_vectors_from_file(
             os.path.join("asymmetric", *key_file),
             lambda pemfile: load_pem_private_key(
                 pemfile.read().encode(), password, backend
-            )
+            ),
         )
 
         assert key
@@ -417,14 +438,15 @@
             (["Traditional_OpenSSL_Serialization", "dsa.3072.pem"], None),
             (["PKCS8", "unenc-dsa-pkcs8.pem"], None),
             (["PEM_Serialization", "dsa_private_key.pem"], b"123456"),
-        ]
+        ],
     )
     def test_load_dsa_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 pemfile: load_pem_private_key(
                 pemfile.read().encode(), password, backend
-            )
+            ),
         )
         assert key
         assert isinstance(key, dsa.DSAPrivateKey)
@@ -437,16 +459,17 @@
             (["PKCS8", "ec_private_key_encrypted.pem"], b"123456"),
             (["PEM_Serialization", "ec_private_key.pem"], None),
             (["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)
         key = load_vectors_from_file(
             os.path.join("asymmetric", *key_path),
             lambda pemfile: load_pem_private_key(
                 pemfile.read().encode(), password, backend
-            )
+            ),
         )
 
         assert key
@@ -459,16 +482,17 @@
         [
             os.path.join("asymmetric", "PKCS8", "unenc-rsa-pkcs8.pub.pem"),
             os.path.join(
-                "asymmetric", "PEM_Serialization", "rsa_public_key.pem"),
+                "asymmetric", "PEM_Serialization", "rsa_public_key.pem"
+            ),
             os.path.join("asymmetric", "public", "PKCS1", "rsa.pub.pem"),
-        ]
+        ],
     )
     def test_load_pem_rsa_public_key(self, key_file, backend):
         key = load_vectors_from_file(
             key_file,
             lambda pemfile: load_pem_public_key(
                 pemfile.read().encode(), backend
-            )
+            ),
         )
         assert key
         assert isinstance(key, rsa.RSAPublicKey)
@@ -480,16 +504,16 @@
         [
             os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pub.pem"),
             os.path.join(
-                "asymmetric", "PEM_Serialization",
-                "dsa_public_key.pem"),
-        ]
+                "asymmetric", "PEM_Serialization", "dsa_public_key.pem"
+            ),
+        ],
     )
     def test_load_pem_dsa_public_key(self, key_file, backend):
         key = load_vectors_from_file(
             key_file,
             lambda pemfile: load_pem_public_key(
                 pemfile.read().encode(), backend
-            )
+            ),
         )
         assert key
         assert isinstance(key, dsa.DSAPublicKey)
@@ -499,66 +523,70 @@
         _skip_curve_unsupported(backend, ec.SECP256R1())
         key = load_vectors_from_file(
             os.path.join(
-                "asymmetric", "PEM_Serialization",
-                "ec_public_key.pem"),
+                "asymmetric", "PEM_Serialization", "ec_public_key.pem"
+            ),
             lambda pemfile: load_pem_public_key(
                 pemfile.read().encode(), backend
-            )
+            ),
         )
         assert key
         assert isinstance(key, ec.EllipticCurvePublicKey)
         assert key.curve.name == "secp256r1"
         assert key.curve.key_size == 256
 
+    @pytest.mark.skip_fips(
+        reason="Traditional OpenSSL format blocked in FIPS mode"
+    )
     def test_rsa_traditional_encrypted_values(self, backend):
         pkey = load_vectors_from_file(
             os.path.join(
-                "asymmetric", "Traditional_OpenSSL_Serialization", "key1.pem"),
+                "asymmetric", "Traditional_OpenSSL_Serialization", "key1.pem"
+            ),
             lambda pemfile: load_pem_private_key(
                 pemfile.read().encode(), b"123456", backend
-            )
+            ),
         )
         assert pkey
 
         numbers = pkey.private_numbers()
         assert numbers.p == int(
             "fb7d316fc51531b36d93adaefaf52db6ad5beb793d37c4cf9dfc1ddd17cfbafb",
-            16
+            16,
         )
         assert numbers.q == int(
             "df98264e646de9a0fbeab094e31caad5bc7adceaaae3c800ca0275dd4bb307f5",
-            16
+            16,
         )
         assert numbers.d == int(
             "db4848c36f478dd5d38f35ae519643b6b810d404bcb76c00e44015e56ca1cab0"
             "7bb7ae91f6b4b43fcfc82a47d7ed55b8c575152116994c2ce5325ec24313b911",
-            16
+            16,
         )
         assert numbers.dmp1 == int(
             "ce997f967192c2bcc3853186f1559fd355c190c58ddc15cbf5de9b6df954c727",
-            16
+            16,
         )
         assert numbers.dmq1 == int(
             "b018a57ab20ffaa3862435445d863369b852cf70a67c55058213e3fe10e3848d",
-            16
+            16,
         )
         assert numbers.iqmp == int(
             "6a8d830616924f5cf2d1bc1973f97fde6b63e052222ac7be06aa2532d10bac76",
-            16
+            16,
         )
         assert numbers.public_numbers.e == 65537
         assert numbers.public_numbers.n == int(
             "dba786074f2f0350ce1d99f5aed5b520cfe0deb5429ec8f2a88563763f566e77"
             "9814b7c310e5326edae31198eed439b845dd2db99eaa60f5c16a43f4be6bcf37",
-            16
+            16,
         )
 
     @pytest.mark.parametrize(
         "key_path",
         [
             ["Traditional_OpenSSL_Serialization", "testrsa.pem"],
-            ["PKCS8", "unenc-rsa-pkcs8.pem"]
-        ]
+            ["PKCS8", "unenc-rsa-pkcs8.pem"],
+        ],
     )
     def test_unused_password(self, key_path, backend):
         key_file = os.path.join("asymmetric", *key_path)
@@ -569,15 +597,33 @@
                 key_file,
                 lambda pemfile: load_pem_private_key(
                     pemfile.read().encode(), password, backend
-                )
+                ),
             )
 
+    def test_invalid_encoding_with_traditional(self, backend):
+        key_file = os.path.join(
+            "asymmetric", "Traditional_OpenSSL_Serialization", "testrsa.pem"
+        )
+        key = load_vectors_from_file(
+            key_file,
+            lambda pemfile: load_pem_private_key(
+                pemfile.read(), None, backend
+            ),
+            mode="rb",
+        )
+
+        for enc in (Encoding.OpenSSH, Encoding.Raw, Encoding.X962):
+            with pytest.raises(ValueError):
+                key.private_bytes(
+                    enc, PrivateFormat.TraditionalOpenSSL, NoEncryption()
+                )
+
     @pytest.mark.parametrize(
         "key_path",
         [
             ["Traditional_OpenSSL_Serialization", "testrsa-encrypted.pem"],
-            ["PKCS8", "enc-rsa-pkcs8.pem"]
-        ]
+            ["PKCS8", "enc-rsa-pkcs8.pem"],
+        ],
     )
     def test_password_not_bytes(self, key_path, backend):
         key_file = os.path.join("asymmetric", *key_path)
@@ -588,15 +634,15 @@
                 key_file,
                 lambda pemfile: load_pem_private_key(
                     pemfile.read().encode(), password, backend
-                )
+                ),
             )
 
     @pytest.mark.parametrize(
         "key_path",
         [
             ["Traditional_OpenSSL_Serialization", "testrsa-encrypted.pem"],
-            ["PKCS8", "enc-rsa-pkcs8.pem"]
-        ]
+            ["PKCS8", "enc-rsa-pkcs8.pem"],
+        ],
     )
     def test_wrong_password(self, key_path, backend):
         key_file = os.path.join("asymmetric", *key_path)
@@ -607,19 +653,18 @@
                 key_file,
                 lambda pemfile: load_pem_private_key(
                     pemfile.read().encode(), password, backend
-                )
+                ),
             )
 
     @pytest.mark.parametrize(
         ("key_path", "password"),
         itertools.product(
             [
-                ["Traditional_OpenSSL_Serialization",
-                 "testrsa-encrypted.pem"],
+                ["Traditional_OpenSSL_Serialization", "testrsa-encrypted.pem"],
                 ["PKCS8", "enc-rsa-pkcs8.pem"],
             ],
-            [b"", None]
-        )
+            [b"", None],
+        ),
     )
     def test_missing_password(self, key_path, password, backend):
         key_file = os.path.join("asymmetric", *key_path)
@@ -629,16 +674,14 @@
                 key_file,
                 lambda pemfile: load_pem_private_key(
                     pemfile.read().encode(), password, backend
-                )
+                ),
             )
 
     def test_wrong_private_format(self, backend):
         key_data = b"---- NOT A KEY ----\n"
 
         with pytest.raises(ValueError):
-            load_pem_private_key(
-                key_data, None, backend
-            )
+            load_pem_private_key(key_data, None, backend)
 
         with pytest.raises(ValueError):
             load_pem_private_key(
@@ -659,7 +702,8 @@
 
     def test_corrupt_traditional_format(self, backend):
         # privkey.pem with a bunch of data missing.
-        key_data = textwrap.dedent("""\
+        key_data = textwrap.dedent(
+            """\
         -----BEGIN RSA PRIVATE KEY-----
         MIIBPAIBAAJBAKrbeqkuRk8VcRmWFmtP+LviMB3+6dizWW3DwaffznyHGAFwUJ/I
         Tv0XtbsCyl3QoyKGhrOAy3RvPK5M38iuXT0CAwEAAQJAZ3cnzaHXM/bxGaR5CR1R
@@ -668,12 +712,11 @@
         rJBhdTe0v5pCeQIhAIZfkiGgGBX4cIuuckzEm43g9WMUjxP/0GlK39vIyihxAiEA
         mymehFRT0MvqW5xAKAx7Pgkt8HVKwVhc2LwGKHE0DZM=
         -----END RSA PRIVATE KEY-----
-        """).encode()
+        """
+        ).encode()
 
         with pytest.raises(ValueError):
-            load_pem_private_key(
-                key_data, None, backend
-            )
+            load_pem_private_key(key_data, None, backend)
 
         with pytest.raises(ValueError):
             load_pem_private_key(
@@ -682,7 +725,8 @@
 
     def test_traditional_encrypted_corrupt_format(self, backend):
         # privkey.pem with a single bit flipped
-        key_data = textwrap.dedent("""\
+        key_data = textwrap.dedent(
+            """\
         -----BEGIN RSA PRIVATE KEY-----
         Proc-Type: <,ENCRYPTED
         DEK-Info: AES-128-CBC,5E22A2BD85A653FB7A3ED20DE84F54CD
@@ -695,22 +739,20 @@
         5A295jD9BQp9CY0nNFSsy+qiXWToq2xT3y5zVNEStmN0SCGNaIlUnJzL9IHW+oMI
         kPmXZMnAYBWeeCF1gf3J3aE5lZInegHNfEI0+J0LazC2aNU5Dg/BNqrmRqKWEIo/
         -----END RSA PRIVATE KEY-----
-        """).encode()
+        """
+        ).encode()
 
         password = b"this password is wrong"
 
         with pytest.raises(ValueError):
-            load_pem_private_key(
-                key_data, None, backend
-            )
+            load_pem_private_key(key_data, None, backend)
 
         with pytest.raises(ValueError):
-            load_pem_private_key(
-                key_data, password, backend
-            )
+            load_pem_private_key(key_data, password, backend)
 
     def test_unsupported_key_encryption(self, backend):
-        key_data = textwrap.dedent("""\
+        key_data = textwrap.dedent(
+            """\
         -----BEGIN RSA PRIVATE KEY-----
         Proc-Type: 4,ENCRYPTED
         DEK-Info: FAKE-123,5E22A2BD85A653FB7A3ED20DE84F54CD
@@ -723,18 +765,18 @@
         5A295jD9BQp9CY0nNFSsy+qiXWToq2xT3y5zVNEStmN0SCGNaIlUnJzL9IHW+oMI
         kPmXZMnAYBWeeCF1gf3J3aE5lZInegHNfEI0+J0LazC2aNU5Dg/BNqrmRqKWEIo/
         -----END RSA PRIVATE KEY-----
-        """).encode()
+        """
+        ).encode()
 
         password = b"password"
 
-        with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER):
-            load_pem_private_key(
-                key_data, password, backend
-            )
+        with pytest.raises(ValueError):
+            load_pem_private_key(key_data, password, backend)
 
     def test_corrupt_pkcs8_format(self, backend):
         # unenc-rsa-pkcs8.pem with a bunch of data missing.
-        key_data = textwrap.dedent("""\
+        key_data = textwrap.dedent(
+            """\
         -----BEGIN PRIVATE KEY-----
         MIICdQIBADALBgkqhkiG9w0BAQEEggJhMIICXQIBAAKBgQC7JHoJfg6yNzLMOWet
         8Z49a4KD0dCspMAYvo2YAMB7/wdEycocujbhJ2n/seONi+5XqTqqFkM5VBl8rmkk
@@ -750,12 +792,11 @@
         Xxg/SNpjEIv+qAyUD96XVlOJlOIeLHQ8kYE0C6ZA+MsqYIzgAreJk88Yn0lU/X0/
         mu/UpE/BRZmR
         -----END PRIVATE KEY-----
-        """).encode()
+        """
+        ).encode()
 
         with pytest.raises(ValueError):
-            load_pem_private_key(
-                key_data, None, backend
-            )
+            load_pem_private_key(key_data, None, backend)
 
         with pytest.raises(ValueError):
             load_pem_private_key(
@@ -764,7 +805,8 @@
 
     def test_pks8_encrypted_corrupt_format(self, backend):
         # enc-rsa-pkcs8.pem with some bits flipped.
-        key_data = textwrap.dedent("""\
+        key_data = textwrap.dedent(
+            """\
         -----BEGIN ENCRYPTED PRIVATE KEY-----
         MIICojAcBgoqhkiG9w0BDAEDMA4ECHK0M0+QuEL9AgIBIcSCAoDRq+KRY+0XP0tO
         lwBTzViiXSXoyNnKAZKt5r5K/fGNntv22g/1s/ZNCetrqsJDC5eMUPPacz06jFq/
@@ -782,27 +824,23 @@
         6JLgl8FrvdfjHwIvmSOO1YMNmILBq000Q8WDqyErBDs4hsvtO6VQ4LeqJj6gClX3
         qeJNaJFu
         -----END ENCRYPTED PRIVATE KEY-----
-        """).encode()
+        """
+        ).encode()
 
         password = b"this password is wrong"
 
         with pytest.raises(ValueError):
-            load_pem_private_key(
-                key_data, None, backend
-            )
+            load_pem_private_key(key_data, None, backend)
 
         with pytest.raises(ValueError):
-            load_pem_private_key(
-                key_data, password, backend
-            )
+            load_pem_private_key(key_data, password, backend)
 
     def test_rsa_pkcs8_encrypted_values(self, backend):
         pkey = load_vectors_from_file(
-            os.path.join(
-                "asymmetric", "PKCS8", "enc-rsa-pkcs8.pem"),
+            os.path.join("asymmetric", "PKCS8", "enc-rsa-pkcs8.pem"),
             lambda pemfile: load_pem_private_key(
                 pemfile.read().encode(), b"foobar", backend
-            )
+            ),
         )
         assert pkey
 
@@ -813,7 +851,8 @@
             "376a7fe5b19f95b35ca358ea5c8abd7ae051d49cd2f1e45969a1ae945460"
             "3c14b278664a0e414ebc8913acb6203626985525e17a600611b028542dd0"
             "562aad787fb4f1650aa318cdcff751e1b187cbf6785fbe164e9809491b95"
-            "dd68480567c99b1a57", 16
+            "dd68480567c99b1a57",
+            16,
         )
 
         assert numbers.public_numbers.e == 65537
@@ -823,37 +862,43 @@
             "f3d9785c3a2c09e4c8090909fb3721e19a3009ec21221523a729265707a5"
             "8f13063671c42a4096cad378ef2510cb59e23071489d8893ac4934dd149f"
             "34f2d094bea57f1c8027c3a77248ac9b91218737d0c3c3dfa7d7829e6977"
-            "cf7d995688c86c81", 16
+            "cf7d995688c86c81",
+            16,
         )
 
         assert numbers.p == int(
             "00db122ac857b2c0437d7616daa98e597bb75ca9ad3a47a70bec10c10036"
             "03328794b225c8e3eee6ffd3fd6d2253d28e071fe27d629ab072faa14377"
-            "ce6118cb67", 16
+            "ce6118cb67",
+            16,
         )
 
         assert numbers.q == int(
             "00df1b8aa8506fcbbbb9d00257f2975e38b33d2698fd0f37e82d7ef38c56"
             "f21b6ced63c825383782a7115cfcc093300987dbd2853b518d1c8f26382a"
-            "2d2586d391", 16
+            "2d2586d391",
+            16,
         )
 
         assert numbers.dmp1 == int(
             "00be18aca13e60712fdf5daa85421eb10d86d654b269e1255656194fb0c4"
             "2dd01a1070ea12c19f5c39e09587af02f7b1a1030d016a9ffabf3b36d699"
-            "ceaf38d9bf", 16
+            "ceaf38d9bf",
+            16,
         )
 
         assert numbers.dmq1 == int(
             "71aa8978f90a0c050744b77cf1263725b203ac9f730606d8ae1d289dce4a"
             "28b8d534e9ea347aeb808c73107e583eb80c546d2bddadcdb3c82693a4c1"
-            "3d863451", 16
+            "3d863451",
+            16,
         )
 
         assert numbers.iqmp == int(
             "136b7b1afac6e6279f71b24217b7083485a5e827d156024609dae39d48a6"
             "bdb55af2f062cc4a3b077434e6fffad5faa29a2b5dba2bed3e4621e478c0"
-            "97ccfe7f", 16
+            "97ccfe7f",
+            16,
         )
 
     def test_load_pem_dsa_private_key(self, backend):
@@ -861,7 +906,7 @@
             os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"),
             lambda pemfile: load_pem_private_key(
                 pemfile.read().encode(), None, backend
-            )
+            ),
         )
         assert key
         assert isinstance(key, dsa.DSAPrivateKey)
@@ -872,15 +917,14 @@
         num = key.private_numbers()
         pub = num.public_numbers
         parameter_numbers = pub.parameter_numbers
-        assert num.x == int("00a535a8e1d0d91beafc8bee1d9b2a3a8de3311203",
-                            16)
+        assert num.x == int("00a535a8e1d0d91beafc8bee1d9b2a3a8de3311203", 16)
         assert pub.y == int(
             "2b260ea97dc6a12ae932c640e7df3d8ff04a8a05a0324f8d5f1b23f15fa1"
             "70ff3f42061124eff2586cb11b49a82dcdc1b90fc6a84fb10109cb67db5d"
             "2da971aeaf17be5e37284563e4c64d9e5fc8480258b319f0de29d54d8350"
             "70d9e287914d77df81491f4423b62da984eb3f45eb2a29fcea5dae525ac6"
             "ab6bcce04bfdf5b6",
-            16
+            16,
         )
 
         assert parameter_numbers.p == int(
@@ -889,11 +933,12 @@
             "071d4dceb2782794ad393cc08a4d4ada7f68d6e839a5fcd34b4e402d82cb"
             "8a8cb40fec31911bf9bd360b034caacb4c5e947992573c9e90099c1b0f05"
             "940cabe5d2de49a167",
-            16
+            16,
         )
 
         assert parameter_numbers.q == int(
-            "00adc0e869b36f0ac013a681fdf4d4899d69820451", 16)
+            "00adc0e869b36f0ac013a681fdf4d4899d69820451", 16
+        )
 
         assert parameter_numbers.g == int(
             "008c6b4589afa53a4d1048bfc346d1f386ca75521ccf72ddaa251286880e"
@@ -901,69 +946,61 @@
             "e71141ba324f5b93131929182c88a9fa4062836066cebe74b5c6690c7d10"
             "1106c240ab7ebd54e4e3301fd086ce6adac922fb2713a2b0887cba13b9bc"
             "68ce5cfff241cd3246",
-            16
+            16,
         )
 
     @pytest.mark.parametrize(
-        ("key_file", "password"),
-        [
-            ("bad-oid-dsa-key.pem", None),
-        ]
+        ("key_file", "password"), [("bad-oid-dsa-key.pem", None)]
     )
     def test_load_bad_oid_key(self, key_file, password, backend):
         with pytest.raises(ValueError):
             load_vectors_from_file(
-                os.path.join(
-                    "asymmetric", "PKCS8", key_file),
+                os.path.join("asymmetric", "PKCS8", key_file),
                 lambda pemfile: load_pem_private_key(
                     pemfile.read().encode(), password, backend
-                )
+                ),
             )
 
     @pytest.mark.parametrize(
-        ("key_file", "password"),
-        [
-            ("bad-encryption-oid.pem", b"password"),
-        ]
+        ("key_file", "password"), [("bad-encryption-oid.pem", b"password")]
     )
     def test_load_bad_encryption_oid_key(self, key_file, password, backend):
-        with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER):
+        with pytest.raises(ValueError):
             load_vectors_from_file(
-                os.path.join(
-                    "asymmetric", "PKCS8", key_file),
+                os.path.join("asymmetric", "PKCS8", key_file),
                 lambda pemfile: load_pem_private_key(
                     pemfile.read().encode(), 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='
+        ssh_key = b"ecdsa-sha2-junk AAAAE2VjZHNhLXNoYTItbmlzdHAyNTY="
 
         with pytest.raises(UnsupportedAlgorithm):
             load_ssh_public_key(ssh_key, backend)
 
     def test_load_ssh_public_key_bad_format(self, backend):
-        ssh_key = b'ssh-rsa not-a-real-key'
+        ssh_key = b"ssh-rsa not-a-real-key"
 
         with pytest.raises(ValueError):
             load_ssh_public_key(ssh_key, backend)
 
     def test_load_ssh_public_key_rsa_too_short(self, backend):
-        ssh_key = b'ssh-rsa'
+        ssh_key = b"ssh-rsa"
 
         with pytest.raises(ValueError):
             load_ssh_public_key(ssh_key, backend)
 
     def test_load_ssh_public_key_truncated_int(self, backend):
-        ssh_key = b'ssh-rsa AAAAB3NzaC1yc2EAAAA='
+        ssh_key = b"ssh-rsa AAAAB3NzaC1yc2EAAAA="
 
         with pytest.raises(ValueError):
             load_ssh_public_key(ssh_key, backend)
 
-        ssh_key = b'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAACKr+IHXo'
+        ssh_key = b"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAACKr+IHXo"
 
         with pytest.raises(ValueError):
             load_ssh_public_key(ssh_key, backend)
@@ -1032,16 +1069,18 @@
 
         expected_e = 0x10001
         expected_n = int(
-            '00C3BBF5D13F59322BA0A0B77EA0B6CF570241628AE24B5BA454D'
-            '23DCA295652B3523B67752653DFFD69587FAD9578DD6406F23691'
-            'EA491C3F8B2D391D0312D9653C303B651067ADF887A5241843CEF'
-            '8019680A088E092FEC305FB04EA070340BB9BD0F1635B2AD84142'
-            '61B4E2D010ABD8FC6D2FB768912F78EE6B05A60857532B75B75EF'
-            'C007601A4EF58BA947B7E75E38F3443CDD87E7C138A1DAD9D9FB3'
-            '19FF69DA43A9F6F6B0CD243F042CD1A5AFAEB286BD46AEB2D922B'
-            'D01385D6892167074A0907F94A2BF08A54ABB2FFFFC89920861D0'
-            '46F8706AB88DDADBD9E8204D48B87789081E074024C8996783B31'
-            '7076A98ABF0A2D8550EAF2097D8CCC7BE76EF', 16)
+            "00C3BBF5D13F59322BA0A0B77EA0B6CF570241628AE24B5BA454D"
+            "23DCA295652B3523B67752653DFFD69587FAD9578DD6406F23691"
+            "EA491C3F8B2D391D0312D9653C303B651067ADF887A5241843CEF"
+            "8019680A088E092FEC305FB04EA070340BB9BD0F1635B2AD84142"
+            "61B4E2D010ABD8FC6D2FB768912F78EE6B05A60857532B75B75EF"
+            "C007601A4EF58BA947B7E75E38F3443CDD87E7C138A1DAD9D9FB3"
+            "19FF69DA43A9F6F6B0CD243F042CD1A5AFAEB286BD46AEB2D922B"
+            "D01385D6892167074A0907F94A2BF08A54ABB2FFFFC89920861D0"
+            "46F8706AB88DDADBD9E8204D48B87789081E074024C8996783B31"
+            "7076A98ABF0A2D8550EAF2097D8CCC7BE76EF",
+            16,
+        )
 
         expected = rsa.RSAPublicNumbers(expected_e, expected_n)
 
@@ -1051,7 +1090,7 @@
 @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'
+        ssh_key = b"ssh-dss"
 
         with pytest.raises(ValueError):
             load_ssh_public_key(ssh_key, backend)
@@ -1134,14 +1173,16 @@
             "96a7032c01cdd8485b5cbfb73a46bb04708f98a18bc88d4c7812b284da8f900"
             "6e473e89897f9bc9125c69bbfd8ef691c0e76c1c34e6c843b8fe240e6e5aeb3"
             "13486e5fa917ab1288ff1a6ebcf9dcdeed3c5fc88474e30476f53a5ec816ef6"
-            "9f4", 16
+            "9f4",
+            16,
         )
         expected_p = int(
             "b9b052d7f07630148d4d838b17790ef4f43437238ebebd5032ea483fd7b7902"
             "5ec3dc65ebd563ab586a633b4344f6acd10af31353bcf29111fa5e3b8d5c1e8"
             "7befe3c65f9b8be69c740716698c8366c8ef925b9cec1dcd69e73d926b554e2"
             "b4b6ddd1453eab39ba0f846e1555adcc33c5a8637128c9ed61104a45505a748"
-            "f6db", 16
+            "f6db",
+            16,
         )
         expected_q = 1230879958723280233885494314531920096931919647917
         expected_g = int(
@@ -1149,11 +1190,12 @@
             "7bc249b6cf8f5f5c5022afefd4df5bf9d13bbdf182df5af2a5c5d1dc7604185"
             "7d5b0e4b22b856c300f850a3b00bac394b728755b8b7a56522eefc491573967"
             "debb5982fc94d6a8c291f758feae63ad769a5621947221522a2dc31d18ede6f"
-            "b656", 16
+            "b656",
+            16,
         )
         expected = dsa.DSAPublicNumbers(
             expected_y,
-            dsa.DSAParameterNumbers(expected_p, expected_q, expected_g)
+            dsa.DSAParameterNumbers(expected_p, expected_q, expected_g),
         )
 
         assert numbers == expected
@@ -1174,17 +1216,32 @@
 
         expected_x = int(
             "44196257377740326295529888716212621920056478823906609851236662550"
-            "785814128027", 10
+            "785814128027",
+            10,
         )
         expected_y = int(
             "12257763433170736656417248739355923610241609728032203358057767672"
-            "925775019611", 10
+            "925775019611",
+            10,
         )
 
         assert key.public_numbers() == ec.EllipticCurvePublicNumbers(
             expected_x, expected_y, ec.SECP256R1()
         )
 
+    def test_load_ssh_public_key_byteslike(self, backend):
+        _skip_curve_unsupported(backend, ec.SECP256R1())
+
+        ssh_key = (
+            b"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAy"
+            b"NTYAAABBBGG2MfkHXp0UkxUyllDzWNBAImsvt5t7pFtTXegZK2WbGxml8zMrgWi5"
+            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)
+
     def test_load_ssh_public_key_ecdsa_nist_p384(self, backend):
         _skip_curve_unsupported(backend, ec.SECP384R1())
         ssh_key = (
@@ -1197,11 +1254,13 @@
 
         expected_x = int(
             "31541830871345183397582554827482786756220448716666815789487537666"
-            "592636882822352575507883817901562613492450642523901", 10
+            "592636882822352575507883817901562613492450642523901",
+            10,
         )
         expected_y = int(
             "15111413269431823234030344298767984698884955023183354737123929430"
-            "995703524272335782455051101616329050844273733614670", 10
+            "995703524272335782455051101616329050844273733614670",
+            10,
         )
 
         assert key.public_numbers() == ec.EllipticCurvePublicNumbers(
@@ -1222,12 +1281,14 @@
         expected_x = int(
             "54124123120178189598842622575230904027376313369742467279346415219"
             "77809037378785192537810367028427387173980786968395921877911964629"
-            "142163122798974160187785455", 10
+            "142163122798974160187785455",
+            10,
         )
         expected_y = int(
             "16111775122845033200938694062381820957441843014849125660011303579"
             "15284560361402515564433711416776946492019498546572162801954089916"
-            "006665939539407104638103918", 10
+            "006665939539407104638103918",
+            10,
         )
 
         assert key.public_numbers() == ec.EllipticCurvePublicNumbers(
@@ -1274,6 +1335,51 @@
             load_ssh_public_key(ssh_key, backend)
 
 
+@pytest.mark.supported(
+    only_if=lambda backend: backend.ed25519_supported(),
+    skip_message="Requires OpenSSL with Ed25519 support",
+)
+class TestEd25519SSHSerialization(object):
+    def test_load_ssh_public_key(self, backend):
+        ssh_key = (
+            b"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG2fgpmpYO61qeAxGd0wgRaN/E4"
+            b"GR+xWvBmvxjxrB1vG user@chiron.local"
+        )
+        key = load_ssh_public_key(ssh_key, backend)
+        assert isinstance(key, ed25519.Ed25519PublicKey)
+        assert key.public_bytes(Encoding.Raw, PublicFormat.Raw) == (
+            b"m\x9f\x82\x99\xa9`\xee\xb5\xa9\xe01\x19\xdd0\x81\x16\x8d\xfc"
+            b"N\x06G\xecV\xbc\x19\xaf\xc6<k\x07[\xc6"
+        )
+
+    def test_public_bytes_openssh(self, backend):
+        ssh_key = (
+            b"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG2fgpmpYO61qeAxGd0wgRaN/E4"
+            b"GR+xWvBmvxjxrB1vG"
+        )
+        key = load_ssh_public_key(ssh_key, backend)
+        assert isinstance(key, ed25519.Ed25519PublicKey)
+        assert (
+            key.public_bytes(Encoding.OpenSSH, PublicFormat.OpenSSH) == ssh_key
+        )
+
+    def test_load_ssh_public_key_not_32_bytes(self, backend):
+        ssh_key = (
+            b"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI22fgpmpYO61qeAxGd0wgRaN/E4"
+            b"GR+xWvBmvxjxrB1vGaGVs user@chiron.local"
+        )
+        with pytest.raises(ValueError):
+            load_ssh_public_key(ssh_key, backend)
+
+    def test_load_ssh_public_key_trailing_data(self, backend):
+        ssh_key = (
+            b"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG2fgpmpYO61qeAxGd0wgRa"
+            b"N/E4GR+xWvBmvxjxrB1vGdHJhaWxpbmdkYXRh user@chiron.local"
+        )
+        with pytest.raises(ValueError):
+            load_ssh_public_key(ssh_key, backend)
+
+
 class TestKeySerializationEncryptionTypes(object):
     def test_non_bytes_password(self):
         with pytest.raises(ValueError):
@@ -1285,128 +1391,959 @@
 
 
 @pytest.mark.supported(
+    only_if=lambda backend: backend.ed25519_supported(),
+    skip_message="Requires OpenSSL with Ed25519 support",
+)
+class TestEd25519Serialization(object):
+    def test_load_der_private_key(self, backend):
+        data = load_vectors_from_file(
+            os.path.join("asymmetric", "Ed25519", "ed25519-pkcs8-enc.der"),
+            lambda derfile: derfile.read(),
+            mode="rb",
+        )
+        unencrypted = load_vectors_from_file(
+            os.path.join("asymmetric", "Ed25519", "ed25519-pkcs8.der"),
+            lambda derfile: derfile.read(),
+            mode="rb",
+        )
+        key = load_der_private_key(data, b"password", backend)
+        assert (
+            key.private_bytes(
+                Encoding.DER, PrivateFormat.PKCS8, NoEncryption()
+            )
+            == unencrypted
+        )
+
+    def test_load_pem_private_key(self, backend):
+        data = load_vectors_from_file(
+            os.path.join("asymmetric", "Ed25519", "ed25519-pkcs8-enc.pem"),
+            lambda pemfile: pemfile.read(),
+            mode="rb",
+        )
+        unencrypted = load_vectors_from_file(
+            os.path.join("asymmetric", "Ed25519", "ed25519-pkcs8.pem"),
+            lambda pemfile: pemfile.read(),
+            mode="rb",
+        )
+        key = load_pem_private_key(data, b"password", backend)
+        assert (
+            key.private_bytes(
+                Encoding.PEM, PrivateFormat.PKCS8, NoEncryption()
+            )
+            == unencrypted
+        )
+
+    @pytest.mark.parametrize(
+        ("key_path", "encoding", "loader"),
+        [
+            (
+                ["Ed25519", "ed25519-pub.pem"],
+                Encoding.PEM,
+                load_pem_public_key,
+            ),
+            (
+                ["Ed25519", "ed25519-pub.der"],
+                Encoding.DER,
+                load_der_public_key,
+            ),
+        ],
+    )
+    def test_load_public_key(self, key_path, encoding, loader, backend):
+        data = load_vectors_from_file(
+            os.path.join("asymmetric", *key_path),
+            lambda pemfile: pemfile.read(),
+            mode="rb",
+        )
+        public_key = loader(data, backend)
+        assert (
+            public_key.public_bytes(
+                encoding, PublicFormat.SubjectPublicKeyInfo
+            )
+            == data
+        )
+
+    def test_openssl_serialization_unsupported(self, backend):
+        key = ed25519.Ed25519PrivateKey.generate()
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                Encoding.PEM,
+                PrivateFormat.TraditionalOpenSSL,
+                NoEncryption(),
+            )
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                Encoding.DER,
+                PrivateFormat.TraditionalOpenSSL,
+                NoEncryption(),
+            )
+
+
+@pytest.mark.supported(
     only_if=lambda backend: backend.x448_supported(),
-    skip_message="Requires OpenSSL with X448 support"
+    skip_message="Requires OpenSSL with X448 support",
 )
 class TestX448Serialization(object):
     def test_load_der_private_key(self, backend):
         data = load_vectors_from_file(
             os.path.join("asymmetric", "X448", "x448-pkcs8-enc.der"),
             lambda derfile: derfile.read(),
-            mode="rb"
+            mode="rb",
         )
         unencrypted = load_vectors_from_file(
             os.path.join("asymmetric", "X448", "x448-pkcs8.der"),
             lambda derfile: derfile.read(),
-            mode="rb"
+            mode="rb",
         )
         key = load_der_private_key(data, b"password", backend)
-        assert key.private_bytes(
-            Encoding.DER, PrivateFormat.PKCS8, NoEncryption()
-        ) == unencrypted
+        assert (
+            key.private_bytes(
+                Encoding.DER, PrivateFormat.PKCS8, NoEncryption()
+            )
+            == unencrypted
+        )
 
     def test_load_pem_private_key(self, backend):
         data = load_vectors_from_file(
             os.path.join("asymmetric", "X448", "x448-pkcs8-enc.pem"),
             lambda pemfile: pemfile.read(),
-            mode="rb"
+            mode="rb",
         )
         unencrypted = load_vectors_from_file(
             os.path.join("asymmetric", "X448", "x448-pkcs8.pem"),
             lambda pemfile: pemfile.read(),
-            mode="rb"
+            mode="rb",
         )
         key = load_pem_private_key(data, b"password", backend)
-        assert key.private_bytes(
-            Encoding.PEM, PrivateFormat.PKCS8, NoEncryption()
-        ) == unencrypted
+        assert (
+            key.private_bytes(
+                Encoding.PEM, PrivateFormat.PKCS8, NoEncryption()
+            )
+            == unencrypted
+        )
 
     @pytest.mark.parametrize(
         ("key_path", "encoding", "loader"),
         [
-            (
-                ["X448", "x448-pub.pem"],
-                Encoding.PEM,
-                load_pem_public_key
-            ),
-            (
-                ["X448", "x448-pub.der"],
-                Encoding.DER,
-                load_der_public_key
-            ),
-        ]
+            (["X448", "x448-pub.pem"], Encoding.PEM, load_pem_public_key),
+            (["X448", "x448-pub.der"], Encoding.DER, load_der_public_key),
+        ],
     )
     def test_load_public_key(self, key_path, encoding, loader, backend):
         data = load_vectors_from_file(
             os.path.join("asymmetric", *key_path),
             lambda pemfile: pemfile.read(),
-            mode="rb"
+            mode="rb",
         )
         public_key = loader(data, backend)
-        assert public_key.public_bytes(
-            encoding, PublicFormat.SubjectPublicKeyInfo
-        ) == data
+        assert (
+            public_key.public_bytes(
+                encoding, PublicFormat.SubjectPublicKeyInfo
+            )
+            == data
+        )
+
+    def test_openssl_serialization_unsupported(self, backend):
+        key = x448.X448PrivateKey.generate()
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                Encoding.PEM,
+                PrivateFormat.TraditionalOpenSSL,
+                NoEncryption(),
+            )
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                Encoding.DER,
+                PrivateFormat.TraditionalOpenSSL,
+                NoEncryption(),
+            )
+
+    def test_openssh_serialization_unsupported(self, backend):
+        key = x448.X448PrivateKey.generate()
+        with pytest.raises(ValueError):
+            key.public_key().public_bytes(
+                Encoding.OpenSSH, PublicFormat.OpenSSH
+            )
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                Encoding.PEM, PrivateFormat.OpenSSH, NoEncryption()
+            )
 
 
 @pytest.mark.supported(
     only_if=lambda backend: backend.x25519_supported(),
-    skip_message="Requires OpenSSL with X25519 support"
+    skip_message="Requires OpenSSL with X25519 support",
 )
 class TestX25519Serialization(object):
     def test_load_der_private_key(self, backend):
         data = load_vectors_from_file(
             os.path.join("asymmetric", "X25519", "x25519-pkcs8-enc.der"),
             lambda derfile: derfile.read(),
-            mode="rb"
+            mode="rb",
         )
         unencrypted = load_vectors_from_file(
             os.path.join("asymmetric", "X25519", "x25519-pkcs8.der"),
             lambda derfile: derfile.read(),
-            mode="rb"
+            mode="rb",
         )
         key = load_der_private_key(data, b"password", backend)
-        assert key.private_bytes(
-            Encoding.DER, PrivateFormat.PKCS8, NoEncryption()
-        ) == unencrypted
+        assert (
+            key.private_bytes(
+                Encoding.DER, PrivateFormat.PKCS8, NoEncryption()
+            )
+            == unencrypted
+        )
 
     def test_load_pem_private_key(self, backend):
         data = load_vectors_from_file(
             os.path.join("asymmetric", "X25519", "x25519-pkcs8-enc.pem"),
             lambda pemfile: pemfile.read(),
-            mode="rb"
+            mode="rb",
         )
         unencrypted = load_vectors_from_file(
             os.path.join("asymmetric", "X25519", "x25519-pkcs8.pem"),
             lambda pemfile: pemfile.read(),
-            mode="rb"
+            mode="rb",
         )
         key = load_pem_private_key(data, b"password", backend)
-        assert key.private_bytes(
-            Encoding.PEM, PrivateFormat.PKCS8, NoEncryption()
-        ) == unencrypted
+        assert (
+            key.private_bytes(
+                Encoding.PEM, PrivateFormat.PKCS8, NoEncryption()
+            )
+            == unencrypted
+        )
 
     @pytest.mark.parametrize(
         ("key_path", "encoding", "loader"),
         [
-            (
-                ["X25519", "x25519-pub.pem"],
-                Encoding.PEM,
-                load_pem_public_key
-            ),
-            (
-                ["X25519", "x25519-pub.der"],
-                Encoding.DER,
-                load_der_public_key
-            ),
-        ]
+            (["X25519", "x25519-pub.pem"], Encoding.PEM, load_pem_public_key),
+            (["X25519", "x25519-pub.der"], Encoding.DER, load_der_public_key),
+        ],
     )
     def test_load_public_key(self, key_path, encoding, loader, backend):
         data = load_vectors_from_file(
             os.path.join("asymmetric", *key_path),
             lambda pemfile: pemfile.read(),
-            mode="rb"
+            mode="rb",
         )
         public_key = loader(data, backend)
-        assert public_key.public_bytes(
-            encoding, PublicFormat.SubjectPublicKeyInfo
-        ) == data
+        assert (
+            public_key.public_bytes(
+                encoding, PublicFormat.SubjectPublicKeyInfo
+            )
+            == data
+        )
+
+    def test_openssl_serialization_unsupported(self, backend):
+        key = x25519.X25519PrivateKey.generate()
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                Encoding.PEM,
+                PrivateFormat.TraditionalOpenSSL,
+                NoEncryption(),
+            )
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                Encoding.DER,
+                PrivateFormat.TraditionalOpenSSL,
+                NoEncryption(),
+            )
+
+    def test_openssh_serialization_unsupported(self, backend):
+        key = x25519.X25519PrivateKey.generate()
+        with pytest.raises(ValueError):
+            key.public_key().public_bytes(
+                Encoding.OpenSSH, PublicFormat.OpenSSH
+            )
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                Encoding.PEM, PrivateFormat.OpenSSH, NoEncryption()
+            )
+
+
+@pytest.mark.supported(
+    only_if=lambda backend: backend.ed448_supported(),
+    skip_message="Requires OpenSSL with Ed448 support",
+)
+class TestEd448Serialization(object):
+    def test_load_der_private_key(self, backend):
+        data = load_vectors_from_file(
+            os.path.join("asymmetric", "Ed448", "ed448-pkcs8-enc.der"),
+            lambda derfile: derfile.read(),
+            mode="rb",
+        )
+        unencrypted = load_vectors_from_file(
+            os.path.join("asymmetric", "Ed448", "ed448-pkcs8.der"),
+            lambda derfile: derfile.read(),
+            mode="rb",
+        )
+        key = load_der_private_key(data, b"password", backend)
+        assert (
+            key.private_bytes(
+                Encoding.DER, PrivateFormat.PKCS8, NoEncryption()
+            )
+            == unencrypted
+        )
+
+    def test_load_pem_private_key(self, backend):
+        data = load_vectors_from_file(
+            os.path.join("asymmetric", "Ed448", "ed448-pkcs8-enc.pem"),
+            lambda pemfile: pemfile.read(),
+            mode="rb",
+        )
+        unencrypted = load_vectors_from_file(
+            os.path.join("asymmetric", "Ed448", "ed448-pkcs8.pem"),
+            lambda pemfile: pemfile.read(),
+            mode="rb",
+        )
+        key = load_pem_private_key(data, b"password", backend)
+        assert (
+            key.private_bytes(
+                Encoding.PEM, PrivateFormat.PKCS8, NoEncryption()
+            )
+            == unencrypted
+        )
+
+    @pytest.mark.parametrize(
+        ("key_path", "encoding", "loader"),
+        [
+            (["Ed448", "ed448-pub.pem"], Encoding.PEM, load_pem_public_key),
+            (["Ed448", "ed448-pub.der"], Encoding.DER, load_der_public_key),
+        ],
+    )
+    def test_load_public_key(self, key_path, encoding, loader, backend):
+        data = load_vectors_from_file(
+            os.path.join("asymmetric", *key_path),
+            lambda pemfile: pemfile.read(),
+            mode="rb",
+        )
+        public_key = loader(data, backend)
+        assert (
+            public_key.public_bytes(
+                encoding, PublicFormat.SubjectPublicKeyInfo
+            )
+            == data
+        )
+
+    def test_openssl_serialization_unsupported(self, backend):
+        key = ed448.Ed448PrivateKey.generate()
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                Encoding.PEM,
+                PrivateFormat.TraditionalOpenSSL,
+                NoEncryption(),
+            )
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                Encoding.DER,
+                PrivateFormat.TraditionalOpenSSL,
+                NoEncryption(),
+            )
+
+    def test_openssh_serialization_unsupported(self, backend):
+        key = ed448.Ed448PrivateKey.generate()
+        with pytest.raises(ValueError):
+            key.public_key().public_bytes(
+                Encoding.OpenSSH,
+                PublicFormat.OpenSSH,
+            )
+        with pytest.raises(ValueError):
+            key.private_bytes(
+                Encoding.PEM,
+                PrivateFormat.OpenSSH,
+                NoEncryption(),
+            )
+
+
+class TestDHSerialization(object):
+    """Test all options with least-supported key type."""
+
+    @pytest.mark.skip_fips(reason="non-FIPS parameters")
+    def test_dh_public_key(self, backend):
+        data = load_vectors_from_file(
+            os.path.join("asymmetric", "DH", "dhkey.pem"),
+            lambda pemfile: pemfile.read(),
+            mode="rb",
+        )
+        public_key = load_pem_private_key(data, None, backend).public_key()
+        for enc in (
+            Encoding.PEM,
+            Encoding.DER,
+            Encoding.OpenSSH,
+            Encoding.Raw,
+            Encoding.X962,
+        ):
+            for fmt in (
+                PublicFormat.SubjectPublicKeyInfo,
+                PublicFormat.PKCS1,
+                PublicFormat.OpenSSH,
+                PublicFormat.Raw,
+                PublicFormat.CompressedPoint,
+                PublicFormat.UncompressedPoint,
+            ):
+                if (
+                    enc in (Encoding.PEM, Encoding.DER)
+                    and fmt == PublicFormat.SubjectPublicKeyInfo
+                ):
+                    # tested elsewhere
+                    continue
+                with pytest.raises(ValueError):
+                    public_key.public_bytes(enc, fmt)
+
+    @pytest.mark.skip_fips(reason="non-FIPS parameters")
+    def test_dh_private_key(self, backend):
+        data = load_vectors_from_file(
+            os.path.join("asymmetric", "DH", "dhkey.pem"),
+            lambda pemfile: pemfile.read(),
+            mode="rb",
+        )
+        private_key = load_pem_private_key(data, None, backend)
+        for enc in (
+            Encoding.PEM,
+            Encoding.DER,
+            Encoding.OpenSSH,
+            Encoding.Raw,
+            Encoding.X962,
+        ):
+            for fmt in (
+                PrivateFormat.PKCS8,
+                PrivateFormat.TraditionalOpenSSL,
+                PrivateFormat.Raw,
+            ):
+                if (
+                    enc in (Encoding.PEM, Encoding.DER)
+                    and fmt is PrivateFormat.PKCS8
+                ):
+                    # tested elsewhere
+                    continue
+                with pytest.raises(ValueError):
+                    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"),
+        [
+            ("rsa-psw.key.pub", None),
+            ("rsa-nopsw.key.pub", "rsa-nopsw.key-cert.pub"),
+            ("dsa-psw.key.pub", None),
+            ("dsa-nopsw.key.pub", "dsa-nopsw.key-cert.pub"),
+            ("ecdsa-psw.key.pub", None),
+            ("ecdsa-nopsw.key.pub", "ecdsa-nopsw.key-cert.pub"),
+            ("ed25519-psw.key.pub", None),
+            ("ed25519-nopsw.key.pub", "ed25519-nopsw.key-cert.pub"),
+        ],
+    )
+    def test_load_ssh_public_key(self, key_file, cert_file, backend):
+        if "ed25519" in key_file and not backend.ed25519_supported():
+            pytest.skip("Requires OpenSSL with Ed25519 support")
+
+        # normal public key
+        pub_data = load_vectors_from_file(
+            os.path.join("asymmetric", "OpenSSH", key_file),
+            lambda f: f.read(),
+            mode="rb",
+        )
+        public_key = load_ssh_public_key(pub_data, backend)
+        nocomment_data = b" ".join(pub_data.split()[:2])
+        assert (
+            public_key.public_bytes(Encoding.OpenSSH, PublicFormat.OpenSSH)
+            == nocomment_data
+        )
+
+        self.run_partial_pubkey(pub_data, backend)
+
+        # parse public key with ssh certificate
+        if cert_file:
+            cert_data = load_vectors_from_file(
+                os.path.join("asymmetric", "OpenSSH", cert_file),
+                lambda f: f.read(),
+                mode="rb",
+            )
+            cert_key = load_ssh_public_key(cert_data, backend)
+            assert (
+                cert_key.public_bytes(Encoding.OpenSSH, PublicFormat.OpenSSH)
+                == nocomment_data
+            )
+
+            # try with more spaces
+            cert_data = b" \t ".join(cert_data.split())
+            cert_key = load_ssh_public_key(cert_data, backend)
+            assert (
+                cert_key.public_bytes(Encoding.OpenSSH, PublicFormat.OpenSSH)
+                == nocomment_data
+            )
+
+            self.run_partial_pubkey(cert_data, backend)
+
+    def run_partial_pubkey(self, pubdata, backend):
+        parts = pubdata.split()
+        raw = base64.b64decode(parts[1])
+        for i in range(1, len(raw)):
+            frag = base64.b64encode(raw[:i])
+            new_pub = b" ".join([parts[0], frag])
+            with pytest.raises(ValueError):
+                load_ssh_public_key(new_pub, backend)
+
+    @pytest.mark.parametrize(
+        ("key_file",),
+        [
+            ("rsa-nopsw.key",),
+            ("rsa-psw.key",),
+            ("dsa-nopsw.key",),
+            ("dsa-psw.key",),
+            ("ecdsa-nopsw.key",),
+            ("ecdsa-psw.key",),
+            ("ed25519-nopsw.key",),
+            ("ed25519-psw.key",),
+        ],
+    )
+    def test_load_ssh_private_key(self, key_file, backend):
+        if "ed25519" in key_file and not backend.ed25519_supported():
+            pytest.skip("Requires OpenSSL with Ed25519 support")
+        if "-psw" in key_file and not ssh._bcrypt_supported:
+            pytest.skip("Requires bcrypt module")
+
+        # read public and private key from ssh-keygen
+        priv_data = load_vectors_from_file(
+            os.path.join("asymmetric", "OpenSSH", key_file),
+            lambda f: f.read(),
+            mode="rb",
+        )
+        pub_data = load_vectors_from_file(
+            os.path.join("asymmetric", "OpenSSH", key_file + ".pub"),
+            lambda f: f.read(),
+            mode="rb",
+        )
+        nocomment_data = b" ".join(pub_data.split()[:2])
+
+        # load and compare
+        password = None
+        if "-psw" in key_file:
+            password = b"password"
+        private_key = load_ssh_private_key(priv_data, password, backend)
+        assert (
+            private_key.public_key().public_bytes(
+                Encoding.OpenSSH, PublicFormat.OpenSSH
+            )
+            == nocomment_data
+        )
+
+        # bytearray
+        private_key = load_ssh_private_key(
+            bytearray(priv_data), password, backend
+        )
+        assert (
+            private_key.public_key().public_bytes(
+                Encoding.OpenSSH, PublicFormat.OpenSSH
+            )
+            == 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(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()
+        if password:
+            encryption = BestAvailableEncryption(password)
+        priv_data2 = private_key.private_bytes(
+            Encoding.PEM,
+            PrivateFormat.OpenSSH,
+            encryption,
+        )
+        private_key2 = load_ssh_private_key(priv_data2, password, backend)
+        assert (
+            private_key2.public_key().public_bytes(
+                Encoding.OpenSSH, PublicFormat.OpenSSH
+            )
+            == nocomment_data
+        )
+
+        # make sure multi-line base64 is used
+        maxline = max(map(len, priv_data2.split(b"\n")))
+        assert maxline < 80
+
+    @pytest.mark.supported(
+        only_if=lambda backend: ssh._bcrypt_supported,
+        skip_message="Requires that bcrypt exists",
+    )
+    def test_bcrypt_encryption(self, backend):
+        private_key = ec.generate_private_key(ec.SECP256R1(), backend)
+        pub1 = private_key.public_key().public_bytes(
+            Encoding.OpenSSH, PublicFormat.OpenSSH
+        )
+
+        for psw in (
+            b"1",
+            b"1234",
+            b"1234" * 4,
+            b"x" * 72,
+        ):
+            # BestAvailableEncryption does not handle bytes-like?
+            best = BestAvailableEncryption(psw)
+            encdata = private_key.private_bytes(
+                Encoding.PEM, PrivateFormat.OpenSSH, best
+            )
+            decoded_key = load_ssh_private_key(encdata, psw, backend)
+            pub2 = decoded_key.public_key().public_bytes(
+                Encoding.OpenSSH, PublicFormat.OpenSSH
+            )
+            assert pub1 == pub2
+
+            # bytearray
+            decoded_key2 = load_ssh_private_key(
+                bytearray(encdata), psw, backend
+            )
+            pub2 = decoded_key2.public_key().public_bytes(
+                Encoding.OpenSSH, PublicFormat.OpenSSH
+            )
+            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(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)
+            with pytest.raises(ValueError):
+                decoded_key = load_ssh_private_key(encdata, b"wrong", backend)
+
+    @pytest.mark.supported(
+        only_if=lambda backend: not ssh._bcrypt_supported,
+        skip_message="Requires that bcrypt is missing",
+    )
+    def test_missing_bcrypt(self, backend):
+        priv_data = load_vectors_from_file(
+            os.path.join("asymmetric", "OpenSSH", "ecdsa-psw.key"),
+            lambda f: f.read(),
+            mode="rb",
+        )
+        with pytest.raises(UnsupportedAlgorithm):
+            load_ssh_private_key(priv_data, b"password", backend)
+
+        private_key = ec.generate_private_key(ec.SECP256R1(), backend)
+        with pytest.raises(UnsupportedAlgorithm):
+            private_key.private_bytes(
+                Encoding.PEM,
+                PrivateFormat.OpenSSH,
+                BestAvailableEncryption(b"x"),
+            )
+
+    def test_fraglist_corners(self):
+        f = ssh._FragList()
+        with pytest.raises(ValueError):
+            f.put_mpint(-1)
+        f.put_mpint(0)
+        f.put_mpint(0x80)
+        assert f.tobytes() == b"\0\0\0\0" + b"\0\0\0\x02" + b"\0\x80"
+
+    def make_file(
+        self,
+        magic=b"openssh-key-v1\0",
+        ciphername=b"none",
+        kdfname=b"none",
+        kdfoptions=b"",
+        nkeys=1,
+        pub_type=b"ecdsa-sha2-nistp256",
+        pub_fields=(
+            b"nistp256",
+            b"\x04" * 65,
+        ),
+        priv_type=None,
+        priv_fields=(b"nistp256", b"\x04" * 65, b"\x7F" * 32),
+        comment=b"comment",
+        checkval1=b"1234",
+        checkval2=b"1234",
+        pad=None,
+        header=b"-----BEGIN OPENSSH PRIVATE KEY-----\n",
+        footer=b"-----END OPENSSH PRIVATE KEY-----\n",
+        cut=8192,
+    ):
+        """Create private key file"""
+        if not priv_type:
+            priv_type = pub_type
+
+        pub = ssh._FragList()
+        for elem in (pub_type,) + pub_fields:
+            pub.put_sshstr(elem)
+
+        secret = ssh._FragList([checkval1, checkval2])
+        for i in range(nkeys):
+            for elem in (priv_type,) + priv_fields + (comment,):
+                secret.put_sshstr(elem)
+
+        if pad is None:
+            pad_len = 8 - (secret.size() % 8)
+            pad = bytearray(range(1, 1 + pad_len))
+        secret.put_raw(pad)
+
+        main = ssh._FragList([magic])
+        main.put_sshstr(ciphername)
+        main.put_sshstr(kdfname)
+        main.put_sshstr(kdfoptions)
+        main.put_u32(nkeys)
+        for i in range(nkeys):
+            main.put_sshstr(pub)
+        main.put_sshstr(secret)
+
+        res = main.tobytes()
+        return ssh._ssh_pem_encode(res[:cut], header, footer)
+
+    def test_ssh_make_file(self, backend):
+        # check if works by default
+        data = self.make_file()
+        key = load_ssh_private_key(data, None, backend)
+        assert isinstance(key, ec.EllipticCurvePrivateKey)
+
+    def test_load_ssh_private_key_errors(self, backend):
+        # bad kdf
+        data = self.make_file(kdfname=b"unknown", ciphername=b"aes256-ctr")
+        with pytest.raises(UnsupportedAlgorithm):
+            load_ssh_private_key(data, None, backend)
+
+        # bad cipher
+        data = self.make_file(ciphername=b"unknown", kdfname=b"bcrypt")
+        with pytest.raises(UnsupportedAlgorithm):
+            load_ssh_private_key(data, None, backend)
+
+        # bad magic
+        data = self.make_file(magic=b"unknown")
+        with pytest.raises(ValueError):
+            load_ssh_private_key(data, None, backend)
+
+        # too few keys
+        data = self.make_file(nkeys=0)
+        with pytest.raises(ValueError):
+            load_ssh_private_key(data, None, backend)
+
+        # too many keys
+        data = self.make_file(nkeys=2)
+        with pytest.raises(ValueError):
+            load_ssh_private_key(data, None, backend)
+
+    def test_ssh_errors_bad_values(self, backend):
+        # bad curve
+        data = self.make_file(pub_type=b"ecdsa-sha2-nistp444")
+        with pytest.raises(UnsupportedAlgorithm):
+            load_ssh_private_key(data, None, backend)
+
+        # curve mismatch
+        data = self.make_file(priv_type=b"ecdsa-sha2-nistp384")
+        with pytest.raises(ValueError):
+            load_ssh_private_key(data, None, backend)
+
+        # invalid bigint
+        data = self.make_file(
+            priv_fields=(b"nistp256", b"\x04" * 65, b"\x80" * 32)
+        )
+        with pytest.raises(ValueError):
+            load_ssh_private_key(data, None, backend)
+
+    def test_ssh_errors_pubpriv_mismatch(self, backend):
+        # ecdsa public-private mismatch
+        data = self.make_file(
+            pub_fields=(
+                b"nistp256",
+                b"\x04" + b"\x05" * 64,
+            )
+        )
+        with pytest.raises(ValueError):
+            load_ssh_private_key(data, None, backend)
+
+        # rsa public-private mismatch
+        data = self.make_file(
+            pub_type=b"ssh-rsa",
+            pub_fields=(b"x" * 32,) * 2,
+            priv_fields=(b"z" * 32,) * 6,
+        )
+        with pytest.raises(ValueError):
+            load_ssh_private_key(data, None, backend)
+
+        # dsa public-private mismatch
+        data = self.make_file(
+            pub_type=b"ssh-dss",
+            pub_fields=(b"x" * 32,) * 4,
+            priv_fields=(b"z" * 32,) * 5,
+        )
+        with pytest.raises(ValueError):
+            load_ssh_private_key(data, None, backend)
+
+        # ed25519 public-private mismatch
+        sk = b"x" * 32
+        pk1 = b"y" * 32
+        pk2 = b"z" * 32
+        data = self.make_file(
+            pub_type=b"ssh-ed25519",
+            pub_fields=(pk1,),
+            priv_fields=(
+                pk1,
+                sk + pk2,
+            ),
+        )
+        with pytest.raises(ValueError):
+            load_ssh_private_key(data, None, backend)
+        data = self.make_file(
+            pub_type=b"ssh-ed25519",
+            pub_fields=(pk1,),
+            priv_fields=(
+                pk2,
+                sk + pk1,
+            ),
+        )
+        with pytest.raises(ValueError):
+            load_ssh_private_key(data, None, backend)
+
+    def test_ssh_errors_bad_wrapper(self, backend):
+        # wrong header
+        data = self.make_file(header=b"-----BEGIN RSA PRIVATE KEY-----\n")
+        with pytest.raises(ValueError):
+            load_ssh_private_key(data, None, backend)
+
+        # wring footer
+        data = self.make_file(footer=b"-----END RSA PRIVATE KEY-----\n")
+        with pytest.raises(ValueError):
+            load_ssh_private_key(data, None, backend)
+
+    def test_ssh_no_padding(self, backend):
+        # no padding must work, if data is on block boundary
+        data = self.make_file(pad=b"", comment=b"")
+        key = load_ssh_private_key(data, None, backend)
+        assert isinstance(key, ec.EllipticCurvePrivateKey)
+
+        # no padding with right last byte
+        data = self.make_file(pad=b"", comment=b"\x08" * 8)
+        key = load_ssh_private_key(data, None, backend)
+        assert isinstance(key, ec.EllipticCurvePrivateKey)
+
+        # avoid unexpected padding removal
+        data = self.make_file(pad=b"", comment=b"1234\x01\x02\x03\x04")
+        key = load_ssh_private_key(data, None, backend)
+        assert isinstance(key, ec.EllipticCurvePrivateKey)
+
+        # bad padding with right size
+        data = self.make_file(pad=b"\x08" * 8, comment=b"")
+        with pytest.raises(ValueError):
+            load_ssh_private_key(data, None, backend)
+
+    def test_ssh_errors_bad_secrets(self, backend):
+        # checkval mismatch
+        data = self.make_file(checkval2=b"4321")
+        with pytest.raises(ValueError):
+            load_ssh_private_key(data, None, backend)
+
+        # bad padding, correct=1
+        data = self.make_file(pad=b"\x01\x02")
+        with pytest.raises(ValueError):
+            load_ssh_private_key(data, None, backend)
+        data = self.make_file(pad=b"")
+        with pytest.raises(ValueError):
+            load_ssh_private_key(data, None, backend)
+
+    @pytest.mark.supported(
+        only_if=lambda backend: backend.elliptic_curve_supported(
+            ec.SECP192R1()
+        ),
+        skip_message="Requires backend support for ec.SECP192R1",
+    )
+    def test_serialize_ssh_private_key_errors_bad_curve(self, backend):
+        private_key = ec.generate_private_key(ec.SECP192R1(), backend)
+        with pytest.raises(ValueError):
+            private_key.private_bytes(
+                Encoding.PEM, PrivateFormat.OpenSSH, NoEncryption()
+            )
+
+    def test_serialize_ssh_private_key_errors(self, backend):
+        # bad encoding
+        private_key = ec.generate_private_key(ec.SECP256R1(), backend)
+        with pytest.raises(ValueError):
+            private_key.private_bytes(
+                Encoding.DER, PrivateFormat.OpenSSH, NoEncryption()
+            )
+
+        # bad object type
+        with pytest.raises(ValueError):
+            ssh.serialize_ssh_private_key(object(), None)
+
+        private_key = ec.generate_private_key(ec.SECP256R1(), backend)
+
+        # too long password
+        with pytest.raises(ValueError):
+            private_key.private_bytes(
+                Encoding.PEM,
+                PrivateFormat.OpenSSH,
+                BestAvailableEncryption(b"p" * 73),
+            )
+
+        # unknown encryption class
+        with pytest.raises(ValueError):
+            private_key.private_bytes(
+                Encoding.PEM,
+                PrivateFormat.OpenSSH,
+                DummyKeySerializationEncryption(),
+            )
+
+    @pytest.mark.parametrize(
+        ("key_path", "supported"),
+        [
+            (["Traditional_OpenSSL_Serialization", "dsa.1024.pem"], True),
+            (["Traditional_OpenSSL_Serialization", "dsa.2048.pem"], False),
+            (["Traditional_OpenSSL_Serialization", "dsa.3072.pem"], False),
+        ],
+    )
+    def test_dsa_private_key_sizes(self, key_path, supported, backend):
+        key = load_vectors_from_file(
+            os.path.join("asymmetric", *key_path),
+            lambda pemfile: load_pem_private_key(
+                pemfile.read(), None, backend
+            ),
+            mode="rb",
+        )
+        assert isinstance(key, dsa.DSAPrivateKey)
+        if supported:
+            res = key.private_bytes(
+                Encoding.PEM, PrivateFormat.OpenSSH, NoEncryption()
+            )
+            assert isinstance(res, bytes)
+        else:
+            with pytest.raises(ValueError):
+                key.private_bytes(
+                    Encoding.PEM, PrivateFormat.OpenSSH, NoEncryption()
+                )
diff --git a/tests/hazmat/primitives/test_x25519.py b/tests/hazmat/primitives/test_x25519.py
index 17a9115..fd1137d 100644
--- a/tests/hazmat/primitives/test_x25519.py
+++ b/tests/hazmat/primitives/test_x25519.py
@@ -9,24 +9,24 @@
 
 import pytest
 
-from cryptography import utils
 from cryptography.exceptions import _Reasons
-from cryptography.hazmat.backends.interfaces import DHBackend
 from cryptography.hazmat.primitives import serialization
 from cryptography.hazmat.primitives.asymmetric.x25519 import (
-    X25519PrivateKey, X25519PublicKey
+    X25519PrivateKey,
+    X25519PublicKey,
 )
 
 from ...utils import (
-    load_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm
+    load_nist_vectors,
+    load_vectors_from_file,
+    raises_unsupported_algorithm,
 )
 
 
 @pytest.mark.supported(
     only_if=lambda backend: not backend.x25519_supported(),
-    skip_message="Requires OpenSSL without X25519 support"
+    skip_message="Requires OpenSSL without X25519 support",
 )
-@pytest.mark.requires_backend_interface(interface=DHBackend)
 def test_x25519_unsupported(backend):
     with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM):
         X25519PublicKey.from_public_bytes(b"0" * 32)
@@ -40,16 +40,15 @@
 
 @pytest.mark.supported(
     only_if=lambda backend: backend.x25519_supported(),
-    skip_message="Requires OpenSSL with X25519 support"
+    skip_message="Requires OpenSSL with X25519 support",
 )
-@pytest.mark.requires_backend_interface(interface=DHBackend)
 class TestX25519Exchange(object):
     @pytest.mark.parametrize(
         "vector",
         load_vectors_from_file(
             os.path.join("asymmetric", "X25519", "rfc7748.txt"),
-            load_nist_vectors
-        )
+            load_nist_vectors,
+        ),
     )
     def test_rfc7748(self, vector, backend):
         private = binascii.unhexlify(vector["input_scalar"])
@@ -91,23 +90,16 @@
         private = binascii.unhexlify(
             "78f1e8edf14481b389448dac8f59c70b038e7cf92ef2c7eff57a72466e115296"
         )
-        private_key = X25519PrivateKey.from_private_bytes(
-            private
-        )
+        private_key = X25519PrivateKey.from_private_bytes(private)
         public_key = X25519PublicKey.from_public_bytes(public)
         with pytest.raises(ValueError):
             private_key.exchange(public_key)
 
-    def test_deprecated_public_bytes(self, backend):
-        key = X25519PrivateKey.generate().public_key()
-        with pytest.warns(utils.DeprecatedIn25):
-            key.public_bytes()
-
     def test_public_bytes_bad_args(self, backend):
         key = X25519PrivateKey.generate().public_key()
         with pytest.raises(ValueError):
             key.public_bytes(None, serialization.PublicFormat.Raw)
-        with pytest.raises(ValueError):
+        with pytest.raises(TypeError):
             key.public_bytes(serialization.Encoding.Raw)
 
     # These vectors are also from RFC 7748
@@ -123,7 +115,7 @@
                 binascii.unhexlify(
                     b"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98"
                     b"eaa9b4e6a"
-                )
+                ),
             ),
             (
                 binascii.unhexlify(
@@ -133,24 +125,33 @@
                 binascii.unhexlify(
                     b"de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e1"
                     b"46f882b4f"
-                )
-            )
-        ]
+                ),
+            ),
+        ],
     )
     def test_pub_priv_bytes_raw(self, private_bytes, public_bytes, backend):
         private_key = X25519PrivateKey.from_private_bytes(private_bytes)
-        assert private_key.private_bytes(
-            serialization.Encoding.Raw,
-            serialization.PrivateFormat.Raw,
-            serialization.NoEncryption()
-        ) == private_bytes
-        assert private_key.public_key().public_bytes(
-            serialization.Encoding.Raw, serialization.PublicFormat.Raw
-        ) == public_bytes
+        assert (
+            private_key.private_bytes(
+                serialization.Encoding.Raw,
+                serialization.PrivateFormat.Raw,
+                serialization.NoEncryption(),
+            )
+            == private_bytes
+        )
+        assert (
+            private_key.public_key().public_bytes(
+                serialization.Encoding.Raw, serialization.PublicFormat.Raw
+            )
+            == public_bytes
+        )
         public_key = X25519PublicKey.from_public_bytes(public_bytes)
-        assert public_key.public_bytes(
-            serialization.Encoding.Raw, serialization.PublicFormat.Raw
-        ) == public_bytes
+        assert (
+            public_key.public_bytes(
+                serialization.Encoding.Raw, serialization.PublicFormat.Raw
+            )
+            == public_bytes
+        )
 
     def test_generate(self, backend):
         key = X25519PrivateKey.generate()
@@ -182,21 +183,21 @@
             key.private_bytes(
                 serialization.Encoding.Raw,
                 serialization.PrivateFormat.Raw,
-                None
+                None,
             )
 
         with pytest.raises(ValueError):
             key.private_bytes(
                 serialization.Encoding.Raw,
                 serialization.PrivateFormat.PKCS8,
-                None
+                None,
             )
 
         with pytest.raises(ValueError):
             key.private_bytes(
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.Raw,
-                serialization.NoEncryption()
+                serialization.NoEncryption(),
             )
 
     def test_invalid_public_bytes(self, backend):
@@ -204,19 +205,17 @@
         with pytest.raises(ValueError):
             key.public_bytes(
                 serialization.Encoding.Raw,
-                serialization.PublicFormat.SubjectPublicKeyInfo
+                serialization.PublicFormat.SubjectPublicKeyInfo,
             )
 
         with pytest.raises(ValueError):
             key.public_bytes(
-                serialization.Encoding.PEM,
-                serialization.PublicFormat.PKCS1
+                serialization.Encoding.PEM, serialization.PublicFormat.PKCS1
             )
 
         with pytest.raises(ValueError):
             key.public_bytes(
-                serialization.Encoding.PEM,
-                serialization.PublicFormat.Raw
+                serialization.Encoding.PEM, serialization.PublicFormat.Raw
             )
 
     @pytest.mark.parametrize(
@@ -227,33 +226,34 @@
                 serialization.PrivateFormat.PKCS8,
                 serialization.BestAvailableEncryption(b"password"),
                 b"password",
-                serialization.load_pem_private_key
+                serialization.load_pem_private_key,
             ),
             (
                 serialization.Encoding.DER,
                 serialization.PrivateFormat.PKCS8,
                 serialization.BestAvailableEncryption(b"password"),
                 b"password",
-                serialization.load_der_private_key
+                serialization.load_der_private_key,
             ),
             (
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.PKCS8,
                 serialization.NoEncryption(),
                 None,
-                serialization.load_pem_private_key
+                serialization.load_pem_private_key,
             ),
             (
                 serialization.Encoding.DER,
                 serialization.PrivateFormat.PKCS8,
                 serialization.NoEncryption(),
                 None,
-                serialization.load_der_private_key
+                serialization.load_der_private_key,
             ),
-        ]
+        ],
     )
-    def test_round_trip_private_serialization(self, encoding, fmt, encryption,
-                                              passwd, load_func, backend):
+    def test_round_trip_private_serialization(
+        self, encoding, fmt, encryption, passwd, load_func, backend
+    ):
         key = X25519PrivateKey.generate()
         serialized = key.private_bytes(encoding, fmt, encryption)
         loaded_key = load_func(serialized, passwd, backend)
@@ -262,8 +262,11 @@
     def test_buffer_protocol(self, backend):
         private_bytes = bytearray(os.urandom(32))
         key = X25519PrivateKey.from_private_bytes(private_bytes)
-        assert key.private_bytes(
-            serialization.Encoding.Raw,
-            serialization.PrivateFormat.Raw,
-            serialization.NoEncryption()
-        ) == private_bytes
+        assert (
+            key.private_bytes(
+                serialization.Encoding.Raw,
+                serialization.PrivateFormat.Raw,
+                serialization.NoEncryption(),
+            )
+            == private_bytes
+        )
diff --git a/tests/hazmat/primitives/test_x448.py b/tests/hazmat/primitives/test_x448.py
index 817de76..7b19b65 100644
--- a/tests/hazmat/primitives/test_x448.py
+++ b/tests/hazmat/primitives/test_x448.py
@@ -10,22 +10,23 @@
 import pytest
 
 from cryptography.exceptions import _Reasons
-from cryptography.hazmat.backends.interfaces import DHBackend
 from cryptography.hazmat.primitives import serialization
 from cryptography.hazmat.primitives.asymmetric.x448 import (
-    X448PrivateKey, X448PublicKey
+    X448PrivateKey,
+    X448PublicKey,
 )
 
 from ...utils import (
-    load_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm
+    load_nist_vectors,
+    load_vectors_from_file,
+    raises_unsupported_algorithm,
 )
 
 
 @pytest.mark.supported(
     only_if=lambda backend: not backend.x448_supported(),
-    skip_message="Requires OpenSSL without X448 support"
+    skip_message="Requires OpenSSL without X448 support",
 )
-@pytest.mark.requires_backend_interface(interface=DHBackend)
 def test_x448_unsupported(backend):
     with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM):
         X448PublicKey.from_public_bytes(b"0" * 56)
@@ -39,16 +40,15 @@
 
 @pytest.mark.supported(
     only_if=lambda backend: backend.x448_supported(),
-    skip_message="Requires OpenSSL with X448 support"
+    skip_message="Requires OpenSSL with X448 support",
 )
-@pytest.mark.requires_backend_interface(interface=DHBackend)
 class TestX448Exchange(object):
     @pytest.mark.parametrize(
         "vector",
         load_vectors_from_file(
             os.path.join("asymmetric", "X448", "rfc7748.txt"),
-            load_nist_vectors
-        )
+            load_nist_vectors,
+        ),
     )
     def test_rfc7748(self, vector, backend):
         private = binascii.unhexlify(vector["input_scalar"])
@@ -93,7 +93,7 @@
                 binascii.unhexlify(
                     b"9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c"
                     b"22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0"
-                )
+                ),
             ),
             (
                 binascii.unhexlify(
@@ -103,24 +103,33 @@
                 binascii.unhexlify(
                     b"3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b430"
                     b"27d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609"
-                )
-            )
-        ]
+                ),
+            ),
+        ],
     )
     def test_pub_priv_bytes_raw(self, private_bytes, public_bytes, backend):
         private_key = X448PrivateKey.from_private_bytes(private_bytes)
-        assert private_key.private_bytes(
-            serialization.Encoding.Raw,
-            serialization.PrivateFormat.Raw,
-            serialization.NoEncryption()
-        ) == private_bytes
-        assert private_key.public_key().public_bytes(
-            serialization.Encoding.Raw, serialization.PublicFormat.Raw
-        ) == public_bytes
+        assert (
+            private_key.private_bytes(
+                serialization.Encoding.Raw,
+                serialization.PrivateFormat.Raw,
+                serialization.NoEncryption(),
+            )
+            == private_bytes
+        )
+        assert (
+            private_key.public_key().public_bytes(
+                serialization.Encoding.Raw, serialization.PublicFormat.Raw
+            )
+            == public_bytes
+        )
         public_key = X448PublicKey.from_public_bytes(public_bytes)
-        assert public_key.public_bytes(
-            serialization.Encoding.Raw, serialization.PublicFormat.Raw
-        ) == public_bytes
+        assert (
+            public_key.public_bytes(
+                serialization.Encoding.Raw, serialization.PublicFormat.Raw
+            )
+            == public_bytes
+        )
 
     @pytest.mark.parametrize(
         ("encoding", "fmt", "encryption", "passwd", "load_func"),
@@ -130,33 +139,34 @@
                 serialization.PrivateFormat.PKCS8,
                 serialization.BestAvailableEncryption(b"password"),
                 b"password",
-                serialization.load_pem_private_key
+                serialization.load_pem_private_key,
             ),
             (
                 serialization.Encoding.DER,
                 serialization.PrivateFormat.PKCS8,
                 serialization.BestAvailableEncryption(b"password"),
                 b"password",
-                serialization.load_der_private_key
+                serialization.load_der_private_key,
             ),
             (
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.PKCS8,
                 serialization.NoEncryption(),
                 None,
-                serialization.load_pem_private_key
+                serialization.load_pem_private_key,
             ),
             (
                 serialization.Encoding.DER,
                 serialization.PrivateFormat.PKCS8,
                 serialization.NoEncryption(),
                 None,
-                serialization.load_der_private_key
+                serialization.load_der_private_key,
             ),
-        ]
+        ],
     )
-    def test_round_trip_private_serialization(self, encoding, fmt, encryption,
-                                              passwd, load_func, backend):
+    def test_round_trip_private_serialization(
+        self, encoding, fmt, encryption, passwd, load_func, backend
+    ):
         key = X448PrivateKey.generate()
         serialized = key.private_bytes(encoding, fmt, encryption)
         loaded_key = load_func(serialized, passwd, backend)
@@ -192,21 +202,21 @@
             key.private_bytes(
                 serialization.Encoding.Raw,
                 serialization.PrivateFormat.Raw,
-                None
+                None,
             )
 
         with pytest.raises(ValueError):
             key.private_bytes(
                 serialization.Encoding.Raw,
                 serialization.PrivateFormat.PKCS8,
-                None
+                None,
             )
 
         with pytest.raises(ValueError):
             key.private_bytes(
                 serialization.Encoding.PEM,
                 serialization.PrivateFormat.Raw,
-                serialization.NoEncryption()
+                serialization.NoEncryption(),
             )
 
     def test_invalid_public_bytes(self, backend):
@@ -214,19 +224,17 @@
         with pytest.raises(ValueError):
             key.public_bytes(
                 serialization.Encoding.Raw,
-                serialization.PublicFormat.SubjectPublicKeyInfo
+                serialization.PublicFormat.SubjectPublicKeyInfo,
             )
 
         with pytest.raises(ValueError):
             key.public_bytes(
-                serialization.Encoding.PEM,
-                serialization.PublicFormat.PKCS1
+                serialization.Encoding.PEM, serialization.PublicFormat.PKCS1
             )
 
         with pytest.raises(ValueError):
             key.public_bytes(
-                serialization.Encoding.PEM,
-                serialization.PublicFormat.Raw
+                serialization.Encoding.PEM, serialization.PublicFormat.Raw
             )
 
     def test_buffer_protocol(self, backend):
@@ -235,8 +243,11 @@
             b"d9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b"
         )
         key = X448PrivateKey.from_private_bytes(bytearray(private_bytes))
-        assert key.private_bytes(
-            serialization.Encoding.Raw,
-            serialization.PrivateFormat.Raw,
-            serialization.NoEncryption()
-        ) == private_bytes
+        assert (
+            key.private_bytes(
+                serialization.Encoding.Raw,
+                serialization.PrivateFormat.Raw,
+                serialization.NoEncryption(),
+            )
+            == private_bytes
+        )
diff --git a/tests/hazmat/primitives/test_x963_vectors.py b/tests/hazmat/primitives/test_x963_vectors.py
index 4a945d4..e3b54fc 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 import default_backend
 from cryptography.hazmat.backends.interfaces import HashBackend
 from cryptography.hazmat.primitives import hashes
 from cryptography.hazmat.primitives.kdf.x963kdf import X963KDF
@@ -21,7 +20,7 @@
 def _skip_hashfn_unsupported(backend, hashfn):
     if not backend.hash_supported(hashfn):
         pytest.skip(
-            "Hash {0} is not supported by this backend {1}".format(
+            "Hash {} is not supported by this backend {}".format(
                 hashfn.name, backend
             )
         )
@@ -30,19 +29,18 @@
 @pytest.mark.requires_backend_interface(interface=HashBackend)
 class TestX963(object):
     _algorithms_dict = {
-        'SHA-1': hashes.SHA1,
-        'SHA-224': hashes.SHA224,
-        'SHA-256': hashes.SHA256,
-        'SHA-384': hashes.SHA384,
-        'SHA-512': hashes.SHA512
+        "SHA-1": hashes.SHA1,
+        "SHA-224": hashes.SHA224,
+        "SHA-256": hashes.SHA256,
+        "SHA-384": hashes.SHA384,
+        "SHA-512": hashes.SHA512,
     }
 
     @pytest.mark.parametrize(
         ("vector"),
         load_vectors_from_file(
-            os.path.join("KDF", "ansx963_2001.txt"),
-            load_x963_vectors
-        )
+            os.path.join("KDF", "ansx963_2001.txt"), load_x963_vectors
+        ),
     )
     def test_x963(self, backend, vector):
         hashfn = self._algorithms_dict[vector["hash"]]
@@ -55,10 +53,12 @@
         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=default_backend())
+        xkdf = X963KDF(
+            algorithm=hashfn(),
+            length=key_data_len,
+            sharedinfo=sharedinfo,
+            backend=backend,
+        )
         xkdf.verify(key, key_data)
 
     def test_unsupported_hash(self, backend):
diff --git a/tests/hazmat/primitives/test_x963kdf.py b/tests/hazmat/primitives/test_x963kdf.py
index c4dd892..5040ae4 100644
--- a/tests/hazmat/primitives/test_x963kdf.py
+++ b/tests/hazmat/primitives/test_x963kdf.py
@@ -8,9 +8,7 @@
 
 import pytest
 
-from cryptography.exceptions import (
-    AlreadyFinalized, InvalidKey, _Reasons
-)
+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
@@ -46,9 +44,11 @@
         assert xkdf.derive(key) == derivedkey
 
     def test_buffer_protocol(self, backend):
-        key = bytearray(binascii.unhexlify(
-            b"96c05619d56c328ab95fe84b18264b08725b85e33fd34f08"
-        ))
+        key = bytearray(
+            binascii.unhexlify(
+                b"96c05619d56c328ab95fe84b18264b08725b85e33fd34f08"
+            )
+        )
 
         derivedkey = binascii.unhexlify(b"443024c3dae66b95e6f5670601558f71")
 
@@ -86,39 +86,25 @@
 
     def test_unicode_typeerror(self, backend):
         with pytest.raises(TypeError):
-            X963KDF(
-                hashes.SHA256(),
-                16,
-                sharedinfo=u"foo",
-                backend=backend
-            )
+            X963KDF(hashes.SHA256(), 16, sharedinfo=u"foo", backend=backend)
 
         with pytest.raises(TypeError):
             xkdf = X963KDF(
-                hashes.SHA256(),
-                16,
-                sharedinfo=None,
-                backend=backend
+                hashes.SHA256(), 16, sharedinfo=None, backend=backend
             )
 
             xkdf.derive(u"foo")
 
         with pytest.raises(TypeError):
             xkdf = X963KDF(
-                hashes.SHA256(),
-                16,
-                sharedinfo=None,
-                backend=backend
+                hashes.SHA256(), 16, sharedinfo=None, backend=backend
             )
 
             xkdf.verify(u"foo", b"bar")
 
         with pytest.raises(TypeError):
             xkdf = X963KDF(
-                hashes.SHA256(),
-                16,
-                sharedinfo=None,
-                backend=backend
+                hashes.SHA256(), 16, sharedinfo=None, backend=backend
             )
 
             xkdf.verify(b"foo", u"bar")
diff --git a/tests/hazmat/primitives/twofactor/test_hotp.py b/tests/hazmat/primitives/twofactor/test_hotp.py
index 14cb08a..08bfd7e 100644
--- a/tests/hazmat/primitives/twofactor/test_hotp.py
+++ b/tests/hazmat/primitives/twofactor/test_hotp.py
@@ -16,16 +16,17 @@
 from cryptography.hazmat.primitives.twofactor.hotp import HOTP
 
 from ....utils import (
-    load_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm
+    load_nist_vectors,
+    load_vectors_from_file,
+    raises_unsupported_algorithm,
 )
 
-vectors = load_vectors_from_file(
-    "twofactor/rfc-4226.txt", load_nist_vectors)
+vectors = load_vectors_from_file("twofactor/rfc-4226.txt", load_nist_vectors)
 
 
 @pytest.mark.supported(
     only_if=lambda backend: backend.hmac_supported(hashes.SHA1()),
-    skip_message="Does not support HMAC-SHA1."
+    skip_message="Does not support HMAC-SHA1.",
 )
 @pytest.mark.requires_backend_interface(interface=HMACBackend)
 class TestHOTP(object):
@@ -102,12 +103,14 @@
 
         assert hotp.get_provisioning_uri("Alice Smith", 1, None) == (
             "otpauth://hotp/Alice%20Smith?digits=6&secret=GEZDGNBV"
-            "GY3TQOJQGEZDGNBVGY3TQOJQ&algorithm=SHA1&counter=1")
+            "GY3TQOJQGEZDGNBVGY3TQOJQ&algorithm=SHA1&counter=1"
+        )
 
-        assert hotp.get_provisioning_uri("Alice Smith", 1, 'Foo') == (
+        assert hotp.get_provisioning_uri("Alice Smith", 1, "Foo") == (
             "otpauth://hotp/Foo:Alice%20Smith?digits=6&secret=GEZD"
             "GNBVGY3TQOJQGEZDGNBVGY3TQOJQ&algorithm=SHA1&issuer=Foo"
-            "&counter=1")
+            "&counter=1"
+        )
 
     def test_buffer_protocol(self, backend):
         key = bytearray(b"a long key with lots of entropy goes here")
diff --git a/tests/hazmat/primitives/twofactor/test_totp.py b/tests/hazmat/primitives/twofactor/test_totp.py
index 59d875a..06d8600 100644
--- a/tests/hazmat/primitives/twofactor/test_totp.py
+++ b/tests/hazmat/primitives/twofactor/test_totp.py
@@ -13,21 +13,23 @@
 from cryptography.hazmat.primitives.twofactor.totp import TOTP
 
 from ....utils import (
-    load_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm
+    load_nist_vectors,
+    load_vectors_from_file,
+    raises_unsupported_algorithm,
 )
 
-vectors = load_vectors_from_file(
-    "twofactor/rfc-6238.txt", load_nist_vectors)
+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()),
-        skip_message="Does not support HMAC-SHA1."
+        skip_message="Does not support HMAC-SHA1.",
     )
     @pytest.mark.parametrize(
-        "params", [i for i in vectors if i["mode"] == b"SHA1"])
+        "params", [i for i in vectors if i["mode"] == b"SHA1"]
+    )
     def test_generate_sha1(self, backend, params):
         secret = params["secret"]
         time = int(params["time"])
@@ -38,10 +40,11 @@
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.hmac_supported(hashes.SHA256()),
-        skip_message="Does not support HMAC-SHA256."
+        skip_message="Does not support HMAC-SHA256.",
     )
     @pytest.mark.parametrize(
-        "params", [i for i in vectors if i["mode"] == b"SHA256"])
+        "params", [i for i in vectors if i["mode"] == b"SHA256"]
+    )
     def test_generate_sha256(self, backend, params):
         secret = params["secret"]
         time = int(params["time"])
@@ -52,10 +55,11 @@
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.hmac_supported(hashes.SHA512()),
-        skip_message="Does not support HMAC-SHA512."
+        skip_message="Does not support HMAC-SHA512.",
     )
     @pytest.mark.parametrize(
-        "params", [i for i in vectors if i["mode"] == b"SHA512"])
+        "params", [i for i in vectors if i["mode"] == b"SHA512"]
+    )
     def test_generate_sha512(self, backend, params):
         secret = params["secret"]
         time = int(params["time"])
@@ -66,10 +70,11 @@
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.hmac_supported(hashes.SHA1()),
-        skip_message="Does not support HMAC-SHA1."
+        skip_message="Does not support HMAC-SHA1.",
     )
     @pytest.mark.parametrize(
-        "params", [i for i in vectors if i["mode"] == b"SHA1"])
+        "params", [i for i in vectors if i["mode"] == b"SHA1"]
+    )
     def test_verify_sha1(self, backend, params):
         secret = params["secret"]
         time = int(params["time"])
@@ -81,10 +86,11 @@
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.hmac_supported(hashes.SHA256()),
-        skip_message="Does not support HMAC-SHA256."
+        skip_message="Does not support HMAC-SHA256.",
     )
     @pytest.mark.parametrize(
-        "params", [i for i in vectors if i["mode"] == b"SHA256"])
+        "params", [i for i in vectors if i["mode"] == b"SHA256"]
+    )
     def test_verify_sha256(self, backend, params):
         secret = params["secret"]
         time = int(params["time"])
@@ -96,10 +102,11 @@
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.hmac_supported(hashes.SHA512()),
-        skip_message="Does not support HMAC-SHA512."
+        skip_message="Does not support HMAC-SHA512.",
     )
     @pytest.mark.parametrize(
-        "params", [i for i in vectors if i["mode"] == b"SHA512"])
+        "params", [i for i in vectors if i["mode"] == b"SHA512"]
+    )
     def test_verify_sha512(self, backend, params):
         secret = params["secret"]
         time = int(params["time"])
@@ -132,12 +139,14 @@
 
         assert totp.get_provisioning_uri("Alice Smith", None) == (
             "otpauth://totp/Alice%20Smith?digits=6&secret=GEZDGNBVG"
-            "Y3TQOJQGEZDGNBVGY3TQOJQ&algorithm=SHA1&period=30")
+            "Y3TQOJQGEZDGNBVGY3TQOJQ&algorithm=SHA1&period=30"
+        )
 
-        assert totp.get_provisioning_uri("Alice Smith", 'World') == (
+        assert totp.get_provisioning_uri("Alice Smith", "World") == (
             "otpauth://totp/World:Alice%20Smith?digits=6&secret=GEZ"
             "DGNBVGY3TQOJQGEZDGNBVGY3TQOJQ&algorithm=SHA1&issuer=World"
-            "&period=30")
+            "&period=30"
+        )
 
     def test_buffer_protocol(self, backend):
         key = bytearray(b"a long key with lots of entropy goes here")
diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py
index 811dcf9..3f1eff6 100644
--- a/tests/hazmat/primitives/utils.py
+++ b/tests/hazmat/primitives/utils.py
@@ -11,15 +11,21 @@
 import pytest
 
 from cryptography.exceptions import (
-    AlreadyFinalized, AlreadyUpdated, InvalidSignature, InvalidTag,
-    NotYetFinalized
+    AlreadyFinalized,
+    AlreadyUpdated,
+    InvalidSignature,
+    InvalidTag,
+    NotYetFinalized,
 )
-from cryptography.hazmat.primitives import hashes, hmac
+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.modes import GCM
 from cryptography.hazmat.primitives.kdf.hkdf import HKDF, HKDFExpand
 from cryptography.hazmat.primitives.kdf.kbkdf import (
-    CounterLocation, KBKDFHMAC, Mode
+    CounterLocation,
+    KBKDFHMAC,
+    Mode,
 )
 from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
 
@@ -35,8 +41,9 @@
     return all_params
 
 
-def generate_encrypt_test(param_loader, path, file_names, cipher_factory,
-                          mode_factory):
+def generate_encrypt_test(
+    param_loader, path, file_names, cipher_factory, mode_factory
+):
     all_params = _load_all_params(path, file_names, param_loader)
 
     @pytest.mark.parametrize("params", all_params)
@@ -54,9 +61,7 @@
     plaintext = params["plaintext"]
     ciphertext = params["ciphertext"]
     cipher = Cipher(
-        cipher_factory(**params),
-        mode_factory(**params),
-        backend=backend
+        cipher_factory(**params), mode_factory(**params), backend=backend
     )
     encryptor = cipher.encryptor()
     actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
@@ -68,8 +73,9 @@
     assert actual_plaintext == binascii.unhexlify(plaintext)
 
 
-def generate_aead_test(param_loader, path, file_names, cipher_factory,
-                       mode_factory):
+def generate_aead_test(
+    param_loader, path, file_names, cipher_factory, mode_factory
+):
     all_params = _load_all_params(path, file_names, param_loader)
 
     @pytest.mark.parametrize("params", all_params)
@@ -80,6 +86,20 @@
 
 
 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
+        and len(params["iv"]) != 24
+    ):
+        # Red Hat disables non-96-bit IV support as part of its FIPS
+        # patches. The check is for a byte length of 24 because the value is
+        # hex encoded.
+        pytest.skip("Non-96-bit IVs unsupported in FIPS mode.")
+
     if params.get("pt") is not None:
         plaintext = params["pt"]
     ciphertext = params["ct"]
@@ -87,10 +107,12 @@
     if params.get("fail") is True:
         cipher = Cipher(
             cipher_factory(binascii.unhexlify(params["key"])),
-            mode_factory(binascii.unhexlify(params["iv"]),
-                         binascii.unhexlify(params["tag"]),
-                         len(binascii.unhexlify(params["tag"]))),
-            backend
+            mode_factory(
+                binascii.unhexlify(params["iv"]),
+                binascii.unhexlify(params["tag"]),
+                len(binascii.unhexlify(params["tag"])),
+            ),
+            backend,
         )
         decryptor = cipher.decryptor()
         decryptor.authenticate_additional_data(binascii.unhexlify(aad))
@@ -101,7 +123,7 @@
         cipher = Cipher(
             cipher_factory(binascii.unhexlify(params["key"])),
             mode_factory(binascii.unhexlify(params["iv"]), None),
-            backend
+            backend,
         )
         encryptor = cipher.encryptor()
         encryptor.authenticate_additional_data(binascii.unhexlify(aad))
@@ -111,10 +133,12 @@
         assert binascii.hexlify(encryptor.tag[:tag_len]) == params["tag"]
         cipher = Cipher(
             cipher_factory(binascii.unhexlify(params["key"])),
-            mode_factory(binascii.unhexlify(params["iv"]),
-                         binascii.unhexlify(params["tag"]),
-                         min_tag_length=tag_len),
-            backend
+            mode_factory(
+                binascii.unhexlify(params["iv"]),
+                binascii.unhexlify(params["tag"]),
+                min_tag_length=tag_len,
+            ),
+            backend,
         )
         decryptor = cipher.decryptor()
         decryptor.authenticate_additional_data(binascii.unhexlify(aad))
@@ -123,13 +147,15 @@
         assert actual_plaintext == binascii.unhexlify(plaintext)
 
 
-def generate_stream_encryption_test(param_loader, path, file_names,
-                                    cipher_factory):
+def generate_stream_encryption_test(
+    param_loader, path, file_names, cipher_factory
+):
     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)
+
     return test_stream_encryption
 
 
@@ -157,6 +183,7 @@
     @pytest.mark.parametrize("params", all_params)
     def test_hash(self, backend, params):
         hash_test(backend, hash_cls, params)
+
     return test_hash
 
 
@@ -171,6 +198,7 @@
 def generate_base_hash_test(algorithm, digest_size):
     def test_base_hash(self, backend):
         base_hash_test(backend, algorithm, digest_size)
+
     return test_base_hash
 
 
@@ -191,6 +219,7 @@
 def generate_base_hmac_test(hash_cls):
     def test_base_hmac(self, backend):
         base_hmac_test(backend, hash_cls)
+
     return test_base_hmac
 
 
@@ -208,6 +237,7 @@
     @pytest.mark.parametrize("params", all_params)
     def test_hmac(self, backend, params):
         hmac_test(backend, algorithm, params)
+
     return test_hmac
 
 
@@ -224,6 +254,7 @@
     @pytest.mark.parametrize("params", all_params)
     def test_pbkdf2(self, backend, params):
         pbkdf2_test(backend, algorithm, params)
+
     return test_pbkdf2
 
 
@@ -236,7 +267,7 @@
         int(params["length"]),
         params["salt"],
         int(params["iterations"]),
-        backend
+        backend,
     )
     derived_key = kdf.derive(params["password"])
     assert binascii.hexlify(derived_key) == params["derived_key"]
@@ -245,6 +276,7 @@
 def generate_aead_exception_test(cipher_factory, mode_factory):
     def test_aead_exception(self, backend):
         aead_exception_test(backend, cipher_factory, mode_factory)
+
     return test_aead_exception
 
 
@@ -252,7 +284,7 @@
     cipher = Cipher(
         cipher_factory(binascii.unhexlify(b"0" * 32)),
         mode_factory(binascii.unhexlify(b"0" * 24)),
-        backend
+        backend,
     )
     encryptor = cipher.encryptor()
     encryptor.update(b"a" * 16)
@@ -270,7 +302,7 @@
     cipher = Cipher(
         cipher_factory(binascii.unhexlify(b"0" * 32)),
         mode_factory(binascii.unhexlify(b"0" * 24), b"0" * 16),
-        backend
+        backend,
     )
     decryptor = cipher.decryptor()
     decryptor.update(b"a" * 16)
@@ -281,6 +313,7 @@
 def generate_aead_tag_exception_test(cipher_factory, mode_factory):
     def test_aead_tag_exception(self, backend):
         aead_tag_exception_test(backend, cipher_factory, mode_factory)
+
     return test_aead_tag_exception
 
 
@@ -288,7 +321,7 @@
     cipher = Cipher(
         cipher_factory(binascii.unhexlify(b"0" * 32)),
         mode_factory(binascii.unhexlify(b"0" * 24)),
-        backend
+        backend,
     )
 
     with pytest.raises(ValueError):
@@ -300,7 +333,7 @@
     cipher = Cipher(
         cipher_factory(binascii.unhexlify(b"0" * 32)),
         mode_factory(binascii.unhexlify(b"0" * 24), b"0" * 16),
-        backend
+        backend,
     )
     with pytest.raises(ValueError):
         cipher.encryptor()
@@ -312,7 +345,7 @@
         int(params["l"]),
         salt=binascii.unhexlify(params["salt"]) or None,
         info=binascii.unhexlify(params["info"]) or None,
-        backend=backend
+        backend=backend,
     )
 
     okm = hkdf.derive(binascii.unhexlify(params["ikm"]))
@@ -326,7 +359,7 @@
         int(params["l"]),
         salt=binascii.unhexlify(params["salt"]) or None,
         info=binascii.unhexlify(params["info"]) or None,
-        backend=backend
+        backend=backend,
     )
 
     prk = hkdf._extract(binascii.unhexlify(params["ikm"]))
@@ -339,7 +372,7 @@
         algorithm,
         int(params["l"]),
         info=binascii.unhexlify(params["info"]) or None,
-        backend=backend
+        backend=backend,
     )
 
     okm = hkdf.derive(binascii.unhexlify(params["prk"]))
@@ -353,8 +386,7 @@
     all_tests = [hkdf_extract_test, hkdf_expand_test, hkdf_derive_test]
 
     @pytest.mark.parametrize(
-        ("params", "hkdf_test"),
-        itertools.product(all_params, all_tests)
+        ("params", "hkdf_test"), itertools.product(all_params, all_tests)
     )
     def test_hkdf(self, backend, params, hkdf_test):
         hkdf_test(backend, algorithm, params)
@@ -368,16 +400,17 @@
     @pytest.mark.parametrize("params", all_params)
     def test_kbkdf(self, backend, params):
         kbkdf_counter_mode_test(backend, params)
+
     return test_kbkdf
 
 
 def kbkdf_counter_mode_test(backend, params):
     supported_algorithms = {
-        'hmac_sha1': hashes.SHA1,
-        'hmac_sha224': hashes.SHA224,
-        'hmac_sha256': hashes.SHA256,
-        'hmac_sha384': hashes.SHA384,
-        'hmac_sha512': hashes.SHA512,
+        "hmac_sha1": hashes.SHA1,
+        "hmac_sha224": hashes.SHA224,
+        "hmac_sha256": hashes.SHA256,
+        "hmac_sha384": hashes.SHA384,
+        "hmac_sha512": hashes.SHA512,
     }
 
     supported_counter_locations = {
@@ -385,39 +418,44 @@
         "after_fixed": CounterLocation.AfterFixed,
     }
 
-    algorithm = supported_algorithms.get(params.get('prf'))
+    algorithm = supported_algorithms.get(params.get("prf"))
     if algorithm is None or not backend.hmac_supported(algorithm()):
-        pytest.skip("KBKDF does not support algorithm: {0}".format(
-            params.get('prf')
-        ))
+        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: {0}".format(
-            params.get('ctrlocation')
-        ))
+        pytest.skip(
+            "Does not support counter location: {}".format(
+                params.get("ctrlocation")
+            )
+        )
 
     ctrkdf = KBKDFHMAC(
         algorithm(),
         Mode.CounterMode,
-        params['l'] // 8,
-        params['rlen'] // 8,
+        params["l"] // 8,
+        params["rlen"] // 8,
         None,
         ctr_loc,
         None,
         None,
-        binascii.unhexlify(params['fixedinputdata']),
-        backend=backend)
+        binascii.unhexlify(params["fixedinputdata"]),
+        backend=backend,
+    )
 
-    ko = ctrkdf.derive(binascii.unhexlify(params['ki']))
+    ko = ctrkdf.derive(binascii.unhexlify(params["ki"]))
     assert binascii.hexlify(ko) == params["ko"]
 
 
-def generate_rsa_verification_test(param_loader, path, file_names, hash_alg,
-                                   pad_factory):
+def generate_rsa_verification_test(
+    param_loader, path, file_names, hash_alg, pad_factory
+):
     all_params = _load_all_params(path, file_names, param_loader)
-    all_params = [i for i in all_params
-                  if i["algorithm"] == hash_alg.name.upper()]
+    all_params = [
+        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):
@@ -428,8 +466,7 @@
 
 def rsa_verification_test(backend, params, hash_alg, pad_factory):
     public_numbers = rsa.RSAPublicNumbers(
-        e=params["public_exponent"],
-        n=params["modulus"]
+        e=params["public_exponent"], n=params["modulus"]
     )
     public_key = public_numbers.public_key(backend)
     pad = pad_factory(params, hash_alg)
@@ -437,19 +474,9 @@
     msg = binascii.unhexlify(params["msg"])
     if params["fail"]:
         with pytest.raises(InvalidSignature):
-            public_key.verify(
-                signature,
-                msg,
-                pad,
-                hash_alg
-            )
+            public_key.verify(signature, msg, pad, hash_alg)
     else:
-        public_key.verify(
-            signature,
-            msg,
-            pad,
-            hash_alg
-        )
+        public_key.verify(signature, msg, pad, hash_alg)
 
 
 def _check_rsa_private_numbers(skey):
@@ -470,3 +497,13 @@
     pkey = skey.public_numbers
     params = pkey.parameter_numbers
     assert pow(params.g, skey.x, params.p) == pkey.y
+
+
+def skip_fips_traditional_openssl(backend, fmt):
+    if (
+        fmt is serialization.PrivateFormat.TraditionalOpenSSL
+        and backend._fips_enabled
+    ):
+        pytest.skip(
+            "Traditional OpenSSL key format is not supported in FIPS mode."
+        )
diff --git a/tests/hazmat/test_der.py b/tests/hazmat/test_der.py
new file mode 100644
index 0000000..ef2052f
--- /dev/null
+++ b/tests/hazmat/test_der.py
@@ -0,0 +1,232 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import 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.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")
diff --git a/tests/hazmat/test_oid.py b/tests/hazmat/test_oid.py
new file mode 100644
index 0000000..5589ed9
--- /dev/null
+++ b/tests/hazmat/test_oid.py
@@ -0,0 +1,39 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import pytest
+
+from cryptography.hazmat._oid import ObjectIdentifier
+
+
+def test_basic_oid():
+    assert ObjectIdentifier("1.2.3.4").dotted_string == "1.2.3.4"
+
+
+def test_oid_constraint():
+    # Too short
+    with pytest.raises(ValueError):
+        ObjectIdentifier("1")
+
+    # First node too big
+    with pytest.raises(ValueError):
+        ObjectIdentifier("3.2.1")
+
+    # Outside range
+    with pytest.raises(ValueError):
+        ObjectIdentifier("1.40")
+    with pytest.raises(ValueError):
+        ObjectIdentifier("0.42")
+
+    # non-decimal oid
+    with pytest.raises(ValueError):
+        ObjectIdentifier("1.2.foo.bar")
+    with pytest.raises(ValueError):
+        ObjectIdentifier("1.2.0xf00.0xba4")
+
+    # negative oid
+    with pytest.raises(ValueError):
+        ObjectIdentifier("1.2.-3.-4")
diff --git a/tests/test_cryptography_utils.py b/tests/test_cryptography_utils.py
index ddea760..0158ef3 100644
--- a/tests/test_cryptography_utils.py
+++ b/tests/test_cryptography_utils.py
@@ -58,8 +58,3 @@
         assert len(accesses) == 1
         assert t.t == 14
         assert len(accesses) == 1
-
-
-def test_bit_length():
-    assert utils.bit_length(1) == 1
-    assert utils.bit_length(11) == 4
diff --git a/tests/test_fernet.py b/tests/test_fernet.py
index 75ecc35..38409b0 100644
--- a/tests/test_fernet.py
+++ b/tests/test_fernet.py
@@ -6,7 +6,6 @@
 
 import base64
 import calendar
-import datetime
 import json
 import os
 import time
@@ -27,14 +26,13 @@
 
 def json_parametrize(keys, filename):
     vector_file = cryptography_vectors.open_vector_file(
-        os.path.join('fernet', filename), "r"
+        os.path.join("fernet", filename), "r"
     )
     with vector_file:
         data = json.load(vector_file)
-        return pytest.mark.parametrize(keys, [
-            tuple([entry[k] for k in keys])
-            for entry in data
-        ])
+        return pytest.mark.parametrize(
+            keys, [tuple([entry[k] for k in keys]) for entry in data]
+        )
 
 
 def test_default_backend():
@@ -52,24 +50,33 @@
 )
 class TestFernet(object):
     @json_parametrize(
-        ("secret", "now", "iv", "src", "token"), "generate.json",
+        ("secret", "now", "iv", "src", "token"),
+        "generate.json",
     )
     def test_generate(self, secret, now, iv, src, token, backend):
         f = Fernet(secret.encode("ascii"), backend=backend)
         actual_token = f._encrypt_from_parts(
             src.encode("ascii"),
             calendar.timegm(iso8601.parse_date(now).utctimetuple()),
-            b"".join(map(six.int2byte, iv))
+            b"".join(map(six.int2byte, iv)),
         )
         assert actual_token == token.encode("ascii")
 
     @json_parametrize(
-        ("secret", "now", "src", "ttl_sec", "token"), "verify.json",
+        ("secret", "now", "src", "ttl_sec", "token"),
+        "verify.json",
     )
-    def test_verify(self, secret, now, src, ttl_sec, token, backend,
-                    monkeypatch):
+    def test_verify(
+        self, secret, now, src, ttl_sec, token, backend, monkeypatch
+    ):
         f = Fernet(secret.encode("ascii"), backend=backend)
         current_time = calendar.timegm(iso8601.parse_date(now).utctimetuple())
+        payload = f.decrypt_at_time(
+            token.encode("ascii"),
+            ttl=ttl_sec,
+            current_time=current_time,
+        )
+        assert payload == src.encode("ascii")
         monkeypatch.setattr(time, "time", lambda: current_time)
         payload = f.decrypt(token.encode("ascii"), ttl=ttl_sec)
         assert payload == src.encode("ascii")
@@ -78,6 +85,12 @@
     def test_invalid(self, secret, token, now, ttl_sec, backend, monkeypatch):
         f = Fernet(secret.encode("ascii"), backend=backend)
         current_time = calendar.timegm(iso8601.parse_date(now).utctimetuple())
+        with pytest.raises(InvalidToken):
+            f.decrypt_at_time(
+                token.encode("ascii"),
+                ttl=ttl_sec,
+                current_time=current_time,
+            )
         monkeypatch.setattr(time, "time", lambda: current_time)
         with pytest.raises(InvalidToken):
             f.decrypt(token.encode("ascii"), ttl=ttl_sec)
@@ -113,6 +126,13 @@
         monkeypatch.setattr(time, "time", lambda: current_time)
         assert f.decrypt(token, ttl=None) == pt
 
+    def test_ttl_required_in_decrypt_at_time(self, monkeypatch, backend):
+        f = Fernet(base64.urlsafe_b64encode(b"\x00" * 32), backend=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()))
+
     @pytest.mark.parametrize("message", [b"", b"Abc!", b"\x00\xFF\x00\x80"])
     def test_roundtrips(self, message, backend):
         f = Fernet(Fernet.generate_key(), backend=backend)
@@ -125,8 +145,7 @@
     def test_extract_timestamp(self, monkeypatch, backend):
         f = Fernet(base64.urlsafe_b64encode(b"\x00" * 32), backend=backend)
         current_time = 1526138327
-        monkeypatch.setattr(time, "time", lambda: current_time)
-        token = f.encrypt(b'encrypt me')
+        token = f.encrypt_at_time(b"encrypt me", current_time)
         assert f.extract_timestamp(token) == current_time
         with pytest.raises(InvalidToken):
             f.extract_timestamp(b"nonsensetoken")
@@ -159,6 +178,17 @@
         with pytest.raises(InvalidToken):
             f.decrypt(b"\x00" * 16)
 
+    def test_decrypt_at_time(self, backend):
+        f1 = Fernet(base64.urlsafe_b64encode(b"\x00" * 32), backend=backend)
+        f = MultiFernet([f1])
+        pt = b"encrypt me"
+        token = f.encrypt_at_time(pt, current_time=100)
+        assert f.decrypt_at_time(token, ttl=1, current_time=100) == pt
+        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)
+
     def test_no_fernets(self, backend):
         with pytest.raises(ValueError):
             MultiFernet([])
@@ -195,18 +225,14 @@
         mf2 = MultiFernet([f2, f1])
 
         plaintext = b"abc"
-        mf1_ciphertext = mf1.encrypt(plaintext)
+        original_time = int(time.time()) - 5 * 60
+        mf1_ciphertext = mf1.encrypt_at_time(plaintext, original_time)
 
-        later = datetime.datetime.now() + datetime.timedelta(minutes=5)
-        later_time = time.mktime(later.timetuple())
-        monkeypatch.setattr(time, "time", lambda: later_time)
-
-        original_time, _ = Fernet._get_unverified_token_data(mf1_ciphertext)
         rotated_time, _ = Fernet._get_unverified_token_data(
             mf2.rotate(mf1_ciphertext)
         )
 
-        assert later_time != rotated_time
+        assert int(time.time()) != rotated_time
         assert original_time == rotated_time
 
     def test_rotate_decrypt_no_shared_keys(self, backend):
diff --git a/tests/test_interfaces.py b/tests/test_interfaces.py
index 97df45a..042245f 100644
--- a/tests/test_interfaces.py
+++ b/tests/test_interfaces.py
@@ -9,7 +9,9 @@
 import six
 
 from cryptography.utils import (
-    InterfaceNotImplemented, register_interface_if, verify_interface
+    InterfaceNotImplemented,
+    register_interface_if,
+    verify_interface,
 )
 
 
diff --git a/tests/test_utils.py b/tests/test_utils.py
index ecd257b..d6afa3b 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -18,13 +18,24 @@
 import cryptography_vectors
 
 from .utils import (
-    check_backend_support, load_cryptrec_vectors, load_ed25519_vectors,
-    load_fips_dsa_key_pair_vectors, load_fips_dsa_sig_vectors,
-    load_fips_ecdsa_key_pair_vectors, load_fips_ecdsa_signing_vectors,
-    load_hash_vectors, load_kasvs_dh_vectors,
-    load_kasvs_ecdh_vectors, load_nist_ccm_vectors, load_nist_kbkdf_vectors,
-    load_nist_vectors, load_pkcs1_vectors, load_rsa_nist_vectors,
-    load_vectors_from_file, load_x963_vectors, raises_unsupported_algorithm
+    check_backend_support,
+    load_cryptrec_vectors,
+    load_ed25519_vectors,
+    load_fips_dsa_key_pair_vectors,
+    load_fips_dsa_sig_vectors,
+    load_fips_ecdsa_key_pair_vectors,
+    load_fips_ecdsa_signing_vectors,
+    load_hash_vectors,
+    load_kasvs_dh_vectors,
+    load_kasvs_ecdh_vectors,
+    load_nist_ccm_vectors,
+    load_nist_kbkdf_vectors,
+    load_nist_vectors,
+    load_pkcs1_vectors,
+    load_rsa_nist_vectors,
+    load_vectors_from_file,
+    load_x963_vectors,
+    raises_unsupported_algorithm,
 )
 
 
@@ -49,7 +60,8 @@
 
 
 def test_load_nist_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     # CAVS 11.1
     # Config info for aes_values
     # AESVS GFSbox test data for CBC
@@ -84,7 +96,8 @@
     IV = 00000000000000000000000000000000
     CIPHERTEXT = a9a1631bf4996954ebc093957b234589
     PLAINTEXT = 9798c4640bad75c7c3227db910174e72
-    """).splitlines()
+    """
+    ).splitlines()
 
     assert load_nist_vectors(vector_data) == [
         {
@@ -115,21 +128,19 @@
 
 
 def test_load_nist_vectors_with_null_chars():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     COUNT = 0
     KEY = thing\\0withnulls
 
     COUNT = 1
     KEY = 00000000000000000000000000000000
-    """).splitlines()
+    """
+    ).splitlines()
 
     assert load_nist_vectors(vector_data) == [
-        {
-            "key": b"thing\x00withnulls",
-        },
-        {
-            "key": b"00000000000000000000000000000000",
-        },
+        {"key": b"thing\x00withnulls"},
+        {"key": b"00000000000000000000000000000000"},
     ]
 
 
@@ -172,7 +183,7 @@
                 "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e06522490"
                 "1555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e"
                 "7a100b"
-            )
+            ),
         },
         {
             "secret_key": (
@@ -188,7 +199,7 @@
                 "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb6"
                 "9da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612"
                 "bb0c00"
-            )
+            ),
         },
         {
             "secret_key": (
@@ -204,7 +215,7 @@
                 "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac"
                 "3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea"
                 "1ec40a"
-            )
+            ),
         },
         {
             "secret_key": (
@@ -220,13 +231,14 @@
                 "d9868d52c2bebce5f3fa5a79891970f309cb6591e3e1702a70276fa97c24b"
                 "3a8e58606c38c9758529da50ee31b8219cba45271c689afa60b0ea26c99db"
                 "19b00c"
-            )
+            ),
         },
     ]
 
 
 def test_load_cryptrec_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     # Vectors taken from https://info.isl.ntt.co.jp/crypt/eng/camellia/
     # Download is t_camelia.txt
 
@@ -244,7 +256,8 @@
 
     P No.001 : 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
     C No.001 : 07 92 3A 39 EB 0A 81 7D 1C 4D 87 BD B8 2D 1F 1C
-    """).splitlines()
+    """
+    ).splitlines()
 
     assert load_cryptrec_vectors(vector_data) == [
         {
@@ -266,21 +279,24 @@
 
 
 def test_load_cryptrec_vectors_invalid():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     # Vectors taken from https://info.isl.ntt.co.jp/crypt/eng/camellia/
     # Download is t_camelia.txt
 
     # Camellia with 128-bit key
 
     E No.001 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-    """).splitlines()
+    """
+    ).splitlines()
 
     with pytest.raises(ValueError):
         load_cryptrec_vectors(vector_data)
 
 
 def test_load_hash_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
 
         # https://tools.ietf.org/html/rfc1321
         [irrelevant]
@@ -300,7 +316,8 @@
         Len = 112
         Msg = 6d65737361676520646967657374
         MD = f96b697d7cb7938d525a2f31aaf161d0
-    """).splitlines()
+    """
+    ).splitlines()
     assert load_hash_vectors(vector_data) == [
         (b"", "d41d8cd98f00b204e9800998ecf8427e"),
         (b"61", "0cc175b9c0f1b6a831c399e269772661"),
@@ -310,29 +327,35 @@
 
 
 def test_load_hmac_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
 Len = 224
 # "Jefe"
 Key = 4a656665
 # "what do ya want for nothing?"
 Msg = 7768617420646f2079612077616e7420666f72206e6f7468696e673f
 MD = 750c783e6ab0b503eaa86e310a5db738
-    """).splitlines()
+    """
+    ).splitlines()
     assert load_hash_vectors(vector_data) == [
-        (b"7768617420646f2079612077616e7420666f72206e6f7468696e673f",
-         "750c783e6ab0b503eaa86e310a5db738",
-         b"4a656665"),
+        (
+            b"7768617420646f2079612077616e7420666f72206e6f7468696e673f",
+            "750c783e6ab0b503eaa86e310a5db738",
+            b"4a656665",
+        ),
     ]
 
 
 def test_load_hash_vectors_bad_data():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
         # https://tools.ietf.org/html/rfc1321
 
         Len = 0
         Msg = 00
         UNKNOWN=Hello World
-    """).splitlines()
+    """
+    ).splitlines()
     with pytest.raises(ValueError):
         load_hash_vectors(vector_data)
 
@@ -357,7 +380,8 @@
 
 
 def test_load_nist_gcm_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
         [Keylen = 128]
         [IVlen = 96]
         [PTlen = 0]
@@ -447,67 +471,87 @@
         AAD =
         Tag = eae841d4355feeb3f786bc86625f1e5b
         FAIL
-    """).splitlines()
+    """
+    ).splitlines()
     assert load_nist_vectors(vector_data) == [
-        {'aad': b'',
-         'pt': b'',
-         'iv': b'3c819d9a9bed087615030b65',
-         'tag': b'250327c674aaf477aef2675748cf6971',
-         'key': b'11754cd72aec309bf52f7687212e8957',
-         'ct': b''},
-        {'aad': b'',
-         'pt': b'',
-         'iv': b'794ec588176c703d3d2a7a07',
-         'tag': b'b6e6f197168f5049aeda32dafbdaeb',
-         'key': b'272f16edb81a7abbea887357a58c1917',
-         'ct': b''},
-        {'aad': b'',
-         'iv': b'907763b19b9b4ab6bd4f0281',
-         'tag': b'a2be08210d8c470a8df6e8fbd79ec5cf',
-         'key': b'a49a5e26a2f8cb63d05546c2a62f5343',
-         'ct': b'',
-         'fail': True},
-        {'aad': b'e98e9d9c618e46fef32660976f854ee3',
-         'pt': b'd1448fa852b84408e2dad8381f363de7',
-         'iv': b'9549e4ba69a61cad7856efc1',
-         'tag': b'd72da7f5c6cf0bca7242c71835809449',
-         'key': b'5c1155084cc0ede76b3bc22e9f7574ef',
-         'ct': b'f78b60ca125218493bea1c50a2e12ef4'},
-        {'aad': b'',
-         'pt': b'',
-         'iv': b'4e8df20faaf2c8eebe922902',
-         'tag': b'e39aeaebe86aa309a4d062d6274339',
-         'key': b'eac258e99c55e6ae8ef1da26640613d7',
-         'ct': b''},
-        {'aad': b'',
-         'iv': b'55fef82cde693ce76efcc193',
-         'tag': b'3d68111a81ed22d2ef5bccac4fc27f',
-         'key': b'3726cf02fcc6b8639a5497652c94350d',
-         'ct': b'',
-         'fail': True},
-        {'aad': b'',
-         'iv': b'eec51e7958c3f20a1bb71815',
-         'tag': b'a81886b3fb26e51fca87b267e1e157',
-         'key': b'f202299d5fd74f03b12d2119a6c4c038',
-         'ct': b'',
-         'fail': True},
-        {'aad': b'',
-         'pt': b'',
-         'iv': b'f5cf3227444afd905a5f6dba',
-         'tag': b'1665b0f1a0b456e1664cfd3de08ccd',
-         'key': b'fd52925f39546b4c55ffb6b20c59898c',
-         'ct': b''},
-        {'aad': b'',
-         'iv': b'3c',
-         'tag': b'eae841d4355feeb3f786bc86625f1e5b',
-         'key': b'58fab7632bcf10d2bcee58520bf37414',
-         'ct': b'15c4db4cbb451211179d57017f',
-         'fail': True},
+        {
+            "aad": b"",
+            "pt": b"",
+            "iv": b"3c819d9a9bed087615030b65",
+            "tag": b"250327c674aaf477aef2675748cf6971",
+            "key": b"11754cd72aec309bf52f7687212e8957",
+            "ct": b"",
+        },
+        {
+            "aad": b"",
+            "pt": b"",
+            "iv": b"794ec588176c703d3d2a7a07",
+            "tag": b"b6e6f197168f5049aeda32dafbdaeb",
+            "key": b"272f16edb81a7abbea887357a58c1917",
+            "ct": b"",
+        },
+        {
+            "aad": b"",
+            "iv": b"907763b19b9b4ab6bd4f0281",
+            "tag": b"a2be08210d8c470a8df6e8fbd79ec5cf",
+            "key": b"a49a5e26a2f8cb63d05546c2a62f5343",
+            "ct": b"",
+            "fail": True,
+        },
+        {
+            "aad": b"e98e9d9c618e46fef32660976f854ee3",
+            "pt": b"d1448fa852b84408e2dad8381f363de7",
+            "iv": b"9549e4ba69a61cad7856efc1",
+            "tag": b"d72da7f5c6cf0bca7242c71835809449",
+            "key": b"5c1155084cc0ede76b3bc22e9f7574ef",
+            "ct": b"f78b60ca125218493bea1c50a2e12ef4",
+        },
+        {
+            "aad": b"",
+            "pt": b"",
+            "iv": b"4e8df20faaf2c8eebe922902",
+            "tag": b"e39aeaebe86aa309a4d062d6274339",
+            "key": b"eac258e99c55e6ae8ef1da26640613d7",
+            "ct": b"",
+        },
+        {
+            "aad": b"",
+            "iv": b"55fef82cde693ce76efcc193",
+            "tag": b"3d68111a81ed22d2ef5bccac4fc27f",
+            "key": b"3726cf02fcc6b8639a5497652c94350d",
+            "ct": b"",
+            "fail": True,
+        },
+        {
+            "aad": b"",
+            "iv": b"eec51e7958c3f20a1bb71815",
+            "tag": b"a81886b3fb26e51fca87b267e1e157",
+            "key": b"f202299d5fd74f03b12d2119a6c4c038",
+            "ct": b"",
+            "fail": True,
+        },
+        {
+            "aad": b"",
+            "pt": b"",
+            "iv": b"f5cf3227444afd905a5f6dba",
+            "tag": b"1665b0f1a0b456e1664cfd3de08ccd",
+            "key": b"fd52925f39546b4c55ffb6b20c59898c",
+            "ct": b"",
+        },
+        {
+            "aad": b"",
+            "iv": b"3c",
+            "tag": b"eae841d4355feeb3f786bc86625f1e5b",
+            "key": b"58fab7632bcf10d2bcee58520bf37414",
+            "ct": b"15c4db4cbb451211179d57017f",
+            "fail": True,
+        },
     ]
 
 
 def test_load_pkcs1_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     Test vectors for RSA-PSS
     ========================
 
@@ -789,168 +833,201 @@
     # =============================================
 
     # <snip>
-    """).splitlines()
+    """
+    ).splitlines()
 
     vectors = tuple(load_pkcs1_vectors(vector_data))
     expected = (
         (
             {
-                'modulus': int(
-                    '495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f77'
-                    '8a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e58'
-                    '2de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218'
-                    'f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a'
-                    '2b8efab0561b0810344739ada0733f', 16),
-                'public_exponent': int('10001', 16),
-                'private_exponent': int(
-                    '6c66ffe98980c38fcdeab5159898836165f4b4b817c4f6a8d486ee4ea'
-                    '9130fe9b9092bd136d184f95f504a607eac565846d2fdd6597a8967c7'
-                    '396ef95a6eeebb4578a643966dca4d8ee3de842de63279c618159c1ab'
-                    '54a89437b6a6120e4930afb52a4ba6ced8a4947ac64b30a3497cbe701'
-                    'c2d6266d517219ad0ec6d347dbe9', 16),
-                'p': int(
-                    '8dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab7'
-                    '2619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c'
-                    '8060645a1d29edb', 16),
-                'q': int(
-                    '847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b'
-                    '97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca41'
-                    '74825b48f49706d', 16),
-                'dmp1': int(
-                    '05c2a83c124b3621a2aa57ea2c3efe035eff4560f33ddebb7adab81fc'
-                    'e69a0c8c2edc16520dda83d59a23be867963ac65f2cc710bbcfb96ee1'
-                    '03deb771d105fd85', 16),
-                'dmq1': int(
-                    '04cae8aa0d9faa165c87b682ec140b8ed3b50b24594b7a3b2c220b366'
-                    '9bb819f984f55310a1ae7823651d4a02e99447972595139363434e5e3'
-                    '0a7e7d241551e1b9', 16),
-                'iqmp': int(
-                    '07d3e47bf686600b11ac283ce88dbb3f6051e8efd04680e44c171ef53'
-                    '1b80b2b7c39fc766320e2cf15d8d99820e96ff30dc69691839c4b40d7'
-                    'b06e45307dc91f3f', 16),
-                'examples': [
+                "modulus": int(
+                    "495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f77"
+                    "8a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e58"
+                    "2de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218"
+                    "f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a"
+                    "2b8efab0561b0810344739ada0733f",
+                    16,
+                ),
+                "public_exponent": int("10001", 16),
+                "private_exponent": int(
+                    "6c66ffe98980c38fcdeab5159898836165f4b4b817c4f6a8d486ee4ea"
+                    "9130fe9b9092bd136d184f95f504a607eac565846d2fdd6597a8967c7"
+                    "396ef95a6eeebb4578a643966dca4d8ee3de842de63279c618159c1ab"
+                    "54a89437b6a6120e4930afb52a4ba6ced8a4947ac64b30a3497cbe701"
+                    "c2d6266d517219ad0ec6d347dbe9",
+                    16,
+                ),
+                "p": int(
+                    "8dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab7"
+                    "2619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c"
+                    "8060645a1d29edb",
+                    16,
+                ),
+                "q": int(
+                    "847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b"
+                    "97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca41"
+                    "74825b48f49706d",
+                    16,
+                ),
+                "dmp1": int(
+                    "05c2a83c124b3621a2aa57ea2c3efe035eff4560f33ddebb7adab81fc"
+                    "e69a0c8c2edc16520dda83d59a23be867963ac65f2cc710bbcfb96ee1"
+                    "03deb771d105fd85",
+                    16,
+                ),
+                "dmq1": int(
+                    "04cae8aa0d9faa165c87b682ec140b8ed3b50b24594b7a3b2c220b366"
+                    "9bb819f984f55310a1ae7823651d4a02e99447972595139363434e5e3"
+                    "0a7e7d241551e1b9",
+                    16,
+                ),
+                "iqmp": int(
+                    "07d3e47bf686600b11ac283ce88dbb3f6051e8efd04680e44c171ef53"
+                    "1b80b2b7c39fc766320e2cf15d8d99820e96ff30dc69691839c4b40d7"
+                    "b06e45307dc91f3f",
+                    16,
+                ),
+                "examples": [
                     {
-                        'message': b'81332f4be62948415ea1d899792eeacf6c6e1db1d'
-                                   b'a8be13b5cea41db2fed467092e1ff398914c71425'
-                                   b'9775f595f8547f735692a575e6923af78f22c6997'
-                                   b'ddb90fb6f72d7bb0dd5744a31decd3dc368584983'
-                                   b'6ed34aec596304ad11843c4f88489f209735f5fb7'
-                                   b'fdaf7cec8addc5818168f880acbf490d51005b7a8'
-                                   b'e84e43e54287977571dd99eea4b161eb2df1f5108'
-                                   b'f12a4142a83322edb05a75487a3435c9a78ce53ed'
-                                   b'93bc550857d7a9fb',
-                        'salt': b'1d65491d79c864b373009be6f6f2467bac4c78fa',
-                        'signature': b'0262ac254bfa77f3c1aca22c5179f8f040422b3'
-                                     b'c5bafd40a8f21cf0fa5a667ccd5993d42dbafb4'
-                                     b'09c520e25fce2b1ee1e716577f1efa17f3da280'
-                                     b'52f40f0419b23106d7845aaf01125b698e7a4df'
-                                     b'e92d3967bb00c4d0d35ba3552ab9a8b3eef07c7'
-                                     b'fecdbc5424ac4db1e20cb37d0b2744769940ea9'
-                                     b'07e17fbbca673b20522380c5'
-                    }, {
-                        'message': b'e2f96eaf0e05e7ba326ecca0ba7fd2f7c02356f3c'
-                                   b'ede9d0faabf4fcc8e60a973e5595fd9ea08',
-                        'salt': b'435c098aa9909eb2377f1248b091b68987ff1838',
-                        'signature': b'2707b9ad5115c58c94e932e8ec0a280f56339e4'
-                                     b'4a1b58d4ddcff2f312e5f34dcfe39e89c6a94dc'
-                                     b'ee86dbbdae5b79ba4e0819a9e7bfd9d982e7ee6'
-                                     b'c86ee68396e8b3a14c9c8f34b178eb741f9d3f1'
-                                     b'21109bf5c8172fada2e768f9ea1433032c004a8'
-                                     b'aa07eb990000a48dc94c8bac8aabe2b09b1aa46'
-                                     b'c0a2aa0e12f63fbba775ba7e'
-                    }
-                ]
+                        "message": b"81332f4be62948415ea1d899792eeacf6c6e1db1d"
+                        b"a8be13b5cea41db2fed467092e1ff398914c71425"
+                        b"9775f595f8547f735692a575e6923af78f22c6997"
+                        b"ddb90fb6f72d7bb0dd5744a31decd3dc368584983"
+                        b"6ed34aec596304ad11843c4f88489f209735f5fb7"
+                        b"fdaf7cec8addc5818168f880acbf490d51005b7a8"
+                        b"e84e43e54287977571dd99eea4b161eb2df1f5108"
+                        b"f12a4142a83322edb05a75487a3435c9a78ce53ed"
+                        b"93bc550857d7a9fb",
+                        "salt": b"1d65491d79c864b373009be6f6f2467bac4c78fa",
+                        "signature": b"0262ac254bfa77f3c1aca22c5179f8f040422b3"
+                        b"c5bafd40a8f21cf0fa5a667ccd5993d42dbafb4"
+                        b"09c520e25fce2b1ee1e716577f1efa17f3da280"
+                        b"52f40f0419b23106d7845aaf01125b698e7a4df"
+                        b"e92d3967bb00c4d0d35ba3552ab9a8b3eef07c7"
+                        b"fecdbc5424ac4db1e20cb37d0b2744769940ea9"
+                        b"07e17fbbca673b20522380c5",
+                    },
+                    {
+                        "message": b"e2f96eaf0e05e7ba326ecca0ba7fd2f7c02356f3c"
+                        b"ede9d0faabf4fcc8e60a973e5595fd9ea08",
+                        "salt": b"435c098aa9909eb2377f1248b091b68987ff1838",
+                        "signature": b"2707b9ad5115c58c94e932e8ec0a280f56339e4"
+                        b"4a1b58d4ddcff2f312e5f34dcfe39e89c6a94dc"
+                        b"ee86dbbdae5b79ba4e0819a9e7bfd9d982e7ee6"
+                        b"c86ee68396e8b3a14c9c8f34b178eb741f9d3f1"
+                        b"21109bf5c8172fada2e768f9ea1433032c004a8"
+                        b"aa07eb990000a48dc94c8bac8aabe2b09b1aa46"
+                        b"c0a2aa0e12f63fbba775ba7e",
+                    },
+                ],
             },
-
             {
-                'modulus': int(
-                    '495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f77'
-                    '8a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e58'
-                    '2de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218'
-                    'f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a'
-                    '2b8efab0561b0810344739ada0733f', 16),
-                'public_exponent': int('10001', 16)
-            }
+                "modulus": int(
+                    "495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f77"
+                    "8a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e58"
+                    "2de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218"
+                    "f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a"
+                    "2b8efab0561b0810344739ada0733f",
+                    16,
+                ),
+                "public_exponent": int("10001", 16),
+            },
         ),
         (
             {
-                'modulus': int(
-                    'e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd0'
-                    '6c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee31'
-                    '5ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b'
-                    '1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddb'
-                    'c2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8d'
-                    'e3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6f'
-                    'd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b', 16),
-                'public_exponent': int('10001', 16),
-                'private_exponent': int(
-                    '6a7fd84fb85fad073b34406db74f8d61a6abc12196a961dd79565e9da'
-                    '6e5187bce2d980250f7359575359270d91590bb0e427c71460b55d514'
-                    '10b191bcf309fea131a92c8e702738fa719f1e0041f52e40e91f229f4'
-                    'd96a1e6f172e15596b4510a6daec26105f2bebc53316b87bdf2131166'
-                    '6070e8dfee69d52c71a976caae79c72b68d28580dc686d9f5129d225f'
-                    '82b3d615513a882b3db91416b48ce08888213e37eeb9af800d81cab32'
-                    '8ce420689903c00c7b5fd31b75503a6d419684d629', 16),
-                'p': int(
-                    'f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac'
-                    '086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a'
-                    '82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f61'
-                    '54a762aed165d47dee367', 16),
-                'q': int(
-                    'ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f'
-                    '288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e472'
-                    '8cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b48'
-                    '9c176128092d629e49d3d', 16),
-                'dmp1': int(
-                    '2bb68bddfb0c4f56c8558bffaf892d8043037841e7fa81cfa61a38c5e'
-                    '39b901c8ee71122a5da2227bd6cdeeb481452c12ad3d61d5e4f776a0a'
-                    'b556591befe3e59e5a7fddb8345e1f2f35b9f4cee57c32414c086aec9'
-                    '93e9353e480d9eec6289f', 16),
-                'dmq1': int(
-                    '4ff897709fad079746494578e70fd8546130eeab5627c49b080f05ee4'
-                    'ad9f3e4b7cba9d6a5dff113a41c3409336833f190816d8a6bc42e9bec'
-                    '56b7567d0f3c9c696db619b245d901dd856db7c8092e77e9a1cccd56e'
-                    'e4dba42c5fdb61aec2669', 16),
-                'iqmp': int(
-                    '77b9d1137b50404a982729316efafc7dfe66d34e5a182600d5f30a0a8'
-                    '512051c560d081d4d0a1835ec3d25a60f4e4d6aa948b2bf3dbb5b124c'
-                    'bbc3489255a3a948372f6978496745f943e1db4f18382ceaa505dfc65'
-                    '757bb3f857a58dce52156', 16),
-                'examples': [
+                "modulus": int(
+                    "e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd0"
+                    "6c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee31"
+                    "5ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b"
+                    "1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddb"
+                    "c2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8d"
+                    "e3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6f"
+                    "d4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b",
+                    16,
+                ),
+                "public_exponent": int("10001", 16),
+                "private_exponent": int(
+                    "6a7fd84fb85fad073b34406db74f8d61a6abc12196a961dd79565e9da"
+                    "6e5187bce2d980250f7359575359270d91590bb0e427c71460b55d514"
+                    "10b191bcf309fea131a92c8e702738fa719f1e0041f52e40e91f229f4"
+                    "d96a1e6f172e15596b4510a6daec26105f2bebc53316b87bdf2131166"
+                    "6070e8dfee69d52c71a976caae79c72b68d28580dc686d9f5129d225f"
+                    "82b3d615513a882b3db91416b48ce08888213e37eeb9af800d81cab32"
+                    "8ce420689903c00c7b5fd31b75503a6d419684d629",
+                    16,
+                ),
+                "p": int(
+                    "f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac"
+                    "086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a"
+                    "82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f61"
+                    "54a762aed165d47dee367",
+                    16,
+                ),
+                "q": int(
+                    "ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f"
+                    "288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e472"
+                    "8cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b48"
+                    "9c176128092d629e49d3d",
+                    16,
+                ),
+                "dmp1": int(
+                    "2bb68bddfb0c4f56c8558bffaf892d8043037841e7fa81cfa61a38c5e"
+                    "39b901c8ee71122a5da2227bd6cdeeb481452c12ad3d61d5e4f776a0a"
+                    "b556591befe3e59e5a7fddb8345e1f2f35b9f4cee57c32414c086aec9"
+                    "93e9353e480d9eec6289f",
+                    16,
+                ),
+                "dmq1": int(
+                    "4ff897709fad079746494578e70fd8546130eeab5627c49b080f05ee4"
+                    "ad9f3e4b7cba9d6a5dff113a41c3409336833f190816d8a6bc42e9bec"
+                    "56b7567d0f3c9c696db619b245d901dd856db7c8092e77e9a1cccd56e"
+                    "e4dba42c5fdb61aec2669",
+                    16,
+                ),
+                "iqmp": int(
+                    "77b9d1137b50404a982729316efafc7dfe66d34e5a182600d5f30a0a8"
+                    "512051c560d081d4d0a1835ec3d25a60f4e4d6aa948b2bf3dbb5b124c"
+                    "bbc3489255a3a948372f6978496745f943e1db4f18382ceaa505dfc65"
+                    "757bb3f857a58dce52156",
+                    16,
+                ),
+                "examples": [
                     {
-                        'message': b'06add75ab689de067744e69a2ebd4b90fa9383003'
-                                   b'cd05ff536cbf294cd215f0923b7fc9004f0aa1852'
-                                   b'71a1d0061fd0e9777ad1ec0c71591f578bf7b8e5a'
-                                   b'1',
-                        'signature': b'4514210e541d5bad7dd60ae549b943acc44f213'
-                                     b'90df5b61318455a17610df5b74d84aed232f17e'
-                                     b'59d91dd2659922f812dbd49681690384b954e9a'
-                                     b'dfb9b1a968c0cbff763eceed62750c59164b5e0'
-                                     b'80a8fef3d55bfe2acfad2752a6a8459fa1fab49'
-                                     b'ad378c6964b23ee97fd1034610c5cc14c61e0eb'
-                                     b'fb1711f8ade96fe6557b38'
+                        "message": b"06add75ab689de067744e69a2ebd4b90fa9383003"
+                        b"cd05ff536cbf294cd215f0923b7fc9004f0aa1852"
+                        b"71a1d0061fd0e9777ad1ec0c71591f578bf7b8e5a"
+                        b"1",
+                        "signature": b"4514210e541d5bad7dd60ae549b943acc44f213"
+                        b"90df5b61318455a17610df5b74d84aed232f17e"
+                        b"59d91dd2659922f812dbd49681690384b954e9a"
+                        b"dfb9b1a968c0cbff763eceed62750c59164b5e0"
+                        b"80a8fef3d55bfe2acfad2752a6a8459fa1fab49"
+                        b"ad378c6964b23ee97fd1034610c5cc14c61e0eb"
+                        b"fb1711f8ade96fe6557b38",
                     }
-                ]
+                ],
             },
-
             {
-                'modulus': int(
-                    'e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd0'
-                    '6c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee31'
-                    '5ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b'
-                    '1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddb'
-                    'c2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8d'
-                    'e3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6f'
-                    'd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b', 16),
-                'public_exponent': int('10001', 16)
-            }
-        )
+                "modulus": int(
+                    "e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd0"
+                    "6c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee31"
+                    "5ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b"
+                    "1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddb"
+                    "c2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8d"
+                    "e3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6f"
+                    "d4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b",
+                    16,
+                ),
+                "public_exponent": int("10001", 16),
+            },
+        ),
     )
     assert vectors == expected
 
 
 def test_load_pkcs1_oaep_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     Test vectors for RSA-OAEP
     =========================
 
@@ -1083,88 +1160,106 @@
     15 91 2d f6 96 ff e0 70 29 32 94 6d 71 49 2b 44
 
     # =============================================
-    """).splitlines()
+    """
+    ).splitlines()
 
     vectors = load_pkcs1_vectors(vector_data)
     expected = [
         (
             {
-                'modulus': int(
-                    'a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae481'
-                    '1a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6'
-                    'c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb'
-                    '662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616'
-                    'd4f5ba10d4cfd226de88d39f16fb', 16),
-                'public_exponent': int('10001', 16),
-                'private_exponent': int(
-                    '53339cfdb79fc8466a655c7316aca85c55fd8f6dd898fdaf119517ef4'
-                    'f52e8fd8e258df93fee180fa0e4ab29693cd83b152a553d4ac4d1812b'
-                    '8b9fa5af0e7f55fe7304df41570926f3311f15c4d65a732c483116ee3'
-                    'd3d2d0af3549ad9bf7cbfb78ad884f84d5beb04724dc7369b31def37d'
-                    '0cf539e9cfcdd3de653729ead5d1', 16),
-                'p': int(
-                    'd32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9'
-                    'cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dc'
-                    'ad212eac7ca39d', 16),
-                'q': int(
-                    'cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3'
-                    'd5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030'
-                    'e860b0288b5d77', 16),
-                'dmp1': int(
-                    '0e12bf1718e9cef5599ba1c3882fe8046a90874eefce8f2ccc20e4f27'
-                    '41fb0a33a3848aec9c9305fbecbd2d76819967d4671acc6431e403796'
-                    '8db37878e695c1', 16),
-                'dmq1': int(
-                    '95297b0f95a2fa67d00707d609dfd4fc05c89dafc2ef6d6ea55bec771'
-                    'ea333734d9251e79082ecda866efef13c459e1a631386b7e354c899f5'
-                    'f112ca85d71583', 16),
-                'iqmp': int(
-                    '4f456c502493bdc0ed2ab756a3a6ed4d67352a697d4216e93212b127a'
-                    '63d5411ce6fa98d5dbefd73263e3728142743818166ed7dd63687dd2a'
-                    '8ca1d2f4fbd8e1', 16),
-                'examples': [
+                "modulus": int(
+                    "a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae481"
+                    "1a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6"
+                    "c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb"
+                    "662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616"
+                    "d4f5ba10d4cfd226de88d39f16fb",
+                    16,
+                ),
+                "public_exponent": int("10001", 16),
+                "private_exponent": int(
+                    "53339cfdb79fc8466a655c7316aca85c55fd8f6dd898fdaf119517ef4"
+                    "f52e8fd8e258df93fee180fa0e4ab29693cd83b152a553d4ac4d1812b"
+                    "8b9fa5af0e7f55fe7304df41570926f3311f15c4d65a732c483116ee3"
+                    "d3d2d0af3549ad9bf7cbfb78ad884f84d5beb04724dc7369b31def37d"
+                    "0cf539e9cfcdd3de653729ead5d1",
+                    16,
+                ),
+                "p": int(
+                    "d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9"
+                    "cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dc"
+                    "ad212eac7ca39d",
+                    16,
+                ),
+                "q": int(
+                    "cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3"
+                    "d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030"
+                    "e860b0288b5d77",
+                    16,
+                ),
+                "dmp1": int(
+                    "0e12bf1718e9cef5599ba1c3882fe8046a90874eefce8f2ccc20e4f27"
+                    "41fb0a33a3848aec9c9305fbecbd2d76819967d4671acc6431e403796"
+                    "8db37878e695c1",
+                    16,
+                ),
+                "dmq1": int(
+                    "95297b0f95a2fa67d00707d609dfd4fc05c89dafc2ef6d6ea55bec771"
+                    "ea333734d9251e79082ecda866efef13c459e1a631386b7e354c899f5"
+                    "f112ca85d71583",
+                    16,
+                ),
+                "iqmp": int(
+                    "4f456c502493bdc0ed2ab756a3a6ed4d67352a697d4216e93212b127a"
+                    "63d5411ce6fa98d5dbefd73263e3728142743818166ed7dd63687dd2a"
+                    "8ca1d2f4fbd8e1",
+                    16,
+                ),
+                "examples": [
                     {
-                        'message': b'6628194e12073db03ba94cda9ef9532397d50dba7'
-                                   b'9b987004afefe34',
-                        'seed': b'18b776ea21069d69776a33e96bad48e1dda0a5ef',
-                        'encryption': b'354fe67b4a126d5d35fe36c777791a3f7ba13d'
-                                      b'ef484e2d3908aff722fad468fb21696de95d0b'
-                                      b'e911c2d3174f8afcc201035f7b6d8e69402de5'
-                                      b'451618c21a535fa9d7bfc5b8dd9fc243f8cf92'
-                                      b'7db31322d6e881eaa91a996170e657a05a2664'
-                                      b'26d98c88003f8477c1227094a0d9fa1e8c4024'
-                                      b'309ce1ecccb5210035d47ac72e8a'
-                    }, {
-                        'message': b'750c4047f547e8e41411856523298ac9bae245efa'
-                                   b'f1397fbe56f9dd5',
-                        'seed': b'0cc742ce4a9b7f32f951bcb251efd925fe4fe35f',
-                        'encryption': b'640db1acc58e0568fe5407e5f9b701dff8c3c9'
-                                      b'1e716c536fc7fcec6cb5b71c1165988d4a279e'
-                                      b'1577d730fc7a29932e3f00c81515236d8d8e31'
-                                      b'017a7a09df4352d904cdeb79aa583adcc31ea6'
-                                      b'98a4c05283daba9089be5491f67c1a4ee48dc7'
-                                      b'4bbbe6643aef846679b4cb395a352d5ed11591'
-                                      b'2df696ffe0702932946d71492b44'
-                    }
-                ]
+                        "message": b"6628194e12073db03ba94cda9ef9532397d50dba7"
+                        b"9b987004afefe34",
+                        "seed": b"18b776ea21069d69776a33e96bad48e1dda0a5ef",
+                        "encryption": b"354fe67b4a126d5d35fe36c777791a3f7ba13d"
+                        b"ef484e2d3908aff722fad468fb21696de95d0b"
+                        b"e911c2d3174f8afcc201035f7b6d8e69402de5"
+                        b"451618c21a535fa9d7bfc5b8dd9fc243f8cf92"
+                        b"7db31322d6e881eaa91a996170e657a05a2664"
+                        b"26d98c88003f8477c1227094a0d9fa1e8c4024"
+                        b"309ce1ecccb5210035d47ac72e8a",
+                    },
+                    {
+                        "message": b"750c4047f547e8e41411856523298ac9bae245efa"
+                        b"f1397fbe56f9dd5",
+                        "seed": b"0cc742ce4a9b7f32f951bcb251efd925fe4fe35f",
+                        "encryption": b"640db1acc58e0568fe5407e5f9b701dff8c3c9"
+                        b"1e716c536fc7fcec6cb5b71c1165988d4a279e"
+                        b"1577d730fc7a29932e3f00c81515236d8d8e31"
+                        b"017a7a09df4352d904cdeb79aa583adcc31ea6"
+                        b"98a4c05283daba9089be5491f67c1a4ee48dc7"
+                        b"4bbbe6643aef846679b4cb395a352d5ed11591"
+                        b"2df696ffe0702932946d71492b44",
+                    },
+                ],
             },
-
             {
-                'modulus': int(
-                    'a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae481'
-                    '1a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6'
-                    'c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb'
-                    '662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616'
-                    'd4f5ba10d4cfd226de88d39f16fb', 16),
-                'public_exponent': int('10001', 16),
-            }
+                "modulus": int(
+                    "a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae481"
+                    "1a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6"
+                    "c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb"
+                    "662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616"
+                    "d4f5ba10d4cfd226de88d39f16fb",
+                    16,
+                ),
+                "public_exponent": int("10001", 16),
+            },
         )
     ]
     assert vectors == expected
 
 
 def test_load_hotp_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     # HOTP Test Vectors
     # RFC 4226 Appendix D
 
@@ -1197,7 +1292,8 @@
     TRUNCATED = 66ef7655
     HOTP = 969429
     SECRET = 12345678901234567890
-    """).splitlines()
+    """
+    ).splitlines()
 
     assert load_nist_vectors(vector_data) == [
         {
@@ -1232,7 +1328,8 @@
 
 
 def test_load_totp_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     # TOTP Test Vectors
     # RFC 6238 Appendix B
 
@@ -1253,7 +1350,8 @@
     TOTP = 90693936
     MODE = SHA512
     SECRET = 12345678901234567890
-    """).splitlines()
+    """
+    ).splitlines()
 
     assert load_nist_vectors(vector_data) == [
         {
@@ -1278,7 +1376,8 @@
 
 
 def test_load_rsa_nist_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     # CAVS 11.4
     # "SigGen PKCS#1 RSASSA-PSS" information
     # Mod sizes selected: 1024 1536 2048 3072 4096
@@ -1307,33 +1406,40 @@
     SHAAlg = SHA512
     Msg = 3456781293fab829
     S = deadbeef0000
-    """).splitlines()
+    """
+    ).splitlines()
 
     vectors = load_rsa_nist_vectors(vector_data)
     assert vectors == [
         {
-            "modulus": int("bcb47b2e0dafcba81ff2a2b5cb115ca7e757184c9d72bcdcda"
-                           "707a146b3b4e29989d", 16),
+            "modulus": int(
+                "bcb47b2e0dafcba81ff2a2b5cb115ca7e757184c9d72bcdcda"
+                "707a146b3b4e29989d",
+                16,
+            ),
             "public_exponent": 65537,
             "algorithm": "SHA1",
             "salt_length": 20,
             "msg": b"1248f62a4389f42f7b4bb131053d6c88a994db2075b912ccbe3ea7dc6"
-                   b"11714f14e",
+            b"11714f14e",
             "s": b"682cf53c1145d22a50caa9eb1a9ba70670c5915e0fdfde6457a765de2a8"
-                 b"fe12de97",
-            "fail": False
+            b"fe12de97",
+            "fail": False,
         },
         {
-            "modulus": int("bcb47b2e0dafcba81ff2a2b5cb115ca7e757184c9d72bcdcda"
-                           "707a146b3b4e29989d", 16),
+            "modulus": int(
+                "bcb47b2e0dafcba81ff2a2b5cb115ca7e757184c9d72bcdcda"
+                "707a146b3b4e29989d",
+                16,
+            ),
             "public_exponent": 65537,
             "algorithm": "SHA384",
             "salt_length": 20,
             "msg": b"e511903c2f1bfba245467295ac95413ac4746c984c3750a728c388aa6"
-                   b"28b0ebf",
+            b"28b0ebf",
             "s": b"9c748702bbcc1f9468864cd360c8c39d007b2d8aaee833606c70f7593cf"
-                 b"0d1519",
-            "fail": False
+            b"0d1519",
+            "fail": False,
         },
         {
             "modulus": 78187493520,
@@ -1342,13 +1448,14 @@
             "salt_length": 20,
             "msg": b"3456781293fab829",
             "s": b"deadbeef0000",
-            "fail": False
+            "fail": False,
         },
     ]
 
 
 def test_load_rsa_nist_pkcs1v15_verification_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     # CAVS 11.0
     # "SigVer PKCS#1 Ver 1.5" information
     # Mod sizes selected: 1024 1536 2048 3072 4096
@@ -1377,50 +1484,73 @@
     S = 2b91c6ae2b3c46ff18d5b7abe239634cb752d0acb53eea0ccd8ea8483036a50e8faf
     SaltVal = 11223344555432167890
     Result = P
-    """).splitlines()
+    """
+    ).splitlines()
 
     vectors = load_rsa_nist_vectors(vector_data)
     assert vectors == [
         {
-            "modulus": int("be499b5e7f06c83fa0293e31465c8eb6b58af920bae52a7b5b"
-                           "9bfeb7aa72db126411", 16),
-            "p": int("e7a80c5d211c06acb900939495f26d365fc2b4825b75e356f89003ea"
-                     "a5931e6be5c3", 16),
-            "q": int("d248aa248000f720258742da67b711940c8f76e1ecd52b67a6ffe1e4"
-                     "9354d66ff84f", 16),
+            "modulus": int(
+                "be499b5e7f06c83fa0293e31465c8eb6b58af920bae52a7b5b"
+                "9bfeb7aa72db126411",
+                16,
+            ),
+            "p": int(
+                "e7a80c5d211c06acb900939495f26d365fc2b4825b75e356f89003ea"
+                "a5931e6be5c3",
+                16,
+            ),
+            "q": int(
+                "d248aa248000f720258742da67b711940c8f76e1ecd52b67a6ffe1e4"
+                "9354d66ff84f",
+                16,
+            ),
             "public_exponent": 17,
             "algorithm": "SHA1",
-            "private_exponent": int("0d0f17362bdad181db4e1fe03e8de1a3208989914"
-                                    "e14bf269558826bfa20faf4b68d", 16),
+            "private_exponent": int(
+                "0d0f17362bdad181db4e1fe03e8de1a3208989914"
+                "e14bf269558826bfa20faf4b68d",
+                16,
+            ),
             "msg": b"6b9cfac0ba1c7890b13e381ce752195cc1375237db2afcf6a9dcd1f95"
-                   b"ec733a80c",
+            b"ec733a80c",
             "s": b"562d87b5781c01d166fef3972669a0495c145b898a17df4743fbefb0a15"
-                 b"82bd6ba9d",
+            b"82bd6ba9d",
             "saltval": b"11223344555432167890",
-            "fail": True
+            "fail": True,
         },
         {
-            "modulus": int("be499b5e7f06c83fa0293e31465c8eb6b58af920bae52a7b5b"
-                           "9bfeb7aa72db126411", 16),
-            "p": int("e7a80c5d211c06acb900939495f26d365fc2b4825b75e356f89003ea"
-                     "a5931e6be5c3", 16),
-            "q": int("d248aa248000f720258742da67b711940c8f76e1ecd52b67a6ffe1e4"
-                     "9354d66ff84f", 16),
+            "modulus": int(
+                "be499b5e7f06c83fa0293e31465c8eb6b58af920bae52a7b5b"
+                "9bfeb7aa72db126411",
+                16,
+            ),
+            "p": int(
+                "e7a80c5d211c06acb900939495f26d365fc2b4825b75e356f89003ea"
+                "a5931e6be5c3",
+                16,
+            ),
+            "q": int(
+                "d248aa248000f720258742da67b711940c8f76e1ecd52b67a6ffe1e4"
+                "9354d66ff84f",
+                16,
+            ),
             "public_exponent": 3,
             "algorithm": "SHA1",
             "private_exponent": int("bfa20faf4b68d", 16),
             "msg": b"2a67c70ff14f9b34ddb42e6f89d5971057a0da980fc9ae70c81a84da0"
-                   b"c0ac42737",
+            b"c0ac42737",
             "s": b"2b91c6ae2b3c46ff18d5b7abe239634cb752d0acb53eea0ccd8ea848303"
-                 b"6a50e8faf",
+            b"6a50e8faf",
             "saltval": b"11223344555432167890",
-            "fail": False
+            "fail": False,
         },
     ]
 
 
 def test_load_rsa_nist_pss_verification_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     # CAVS 11.0
     # "SigVer PKCS#1 RSASSA-PSS" information
     # Mod sizes selected: 1024 1536 2048 3072 4096
@@ -1450,7 +1580,8 @@
     S = 2b91c6ae2b3c46ff18d5b7abe239634cb7
     SaltVal = 11223344555432167890
     Result = P
-    """).splitlines()
+    """
+    ).splitlines()
 
     vectors = load_rsa_nist_vectors(vector_data)
     assert vectors == [
@@ -1465,7 +1596,7 @@
             "s": b"562d87b5781c01d166fef3972669a0495c",
             "saltval": b"11223344555432167890",
             "salt_length": 10,
-            "fail": True
+            "fail": True,
         },
         {
             "modulus": int("be499b5e7f06c83fa0293e31465c8eb6b5", 16),
@@ -1478,13 +1609,14 @@
             "s": b"2b91c6ae2b3c46ff18d5b7abe239634cb7",
             "saltval": b"11223344555432167890",
             "salt_length": 10,
-            "fail": False
+            "fail": False,
         },
     ]
 
 
 def test_load_fips_dsa_key_pair_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     #  CAVS 11.1
     #  "KeyPair" information
     #  Mod sizes selected: L=1024, N=160:: L=2048, N=224 :: L=2048, N=256 :: L
@@ -1599,213 +1731,303 @@
 623399b473ce712a2184cf2da1861706c41466806aefe41b497db82aca6c31c8f4aa68c17d1d9e\
 380b57998917655783ec96e5234a131f7299398d36f1f5f84297a55ff292f1f060958c358fed34\
 6db2de45127ca728a9417b2c54203e33e53b9a061d924395b09afab8daf3e8dd7eedcec3ac
-    """).splitlines()
+    """
+    ).splitlines()
 
     expected = [
-        {'g': int('06b7861abbd35cc89e79c52f68d20875389b127361ca66822138ce499'
-                  '1d2b862259d6b4548a6495b195aa0e0b6137ca37eb23b94074d3c3d3000'
-                  '42bdf15762812b6333ef7b07ceba78607610fcc9ee68491dbc1e34cd12'
-                  '615474e52b18bc934fb00c61d39e7da8902291c4434a4e2224c3f'
-                  '4fd9f93cd6f4f17fc076341a7e7d9', 16),
-         'p': int('d38311e2cd388c3ed698e82fdf88eb92b5a9a483dc88005d4b725e'
-                  'f341eabb47cf8a7a8a41e792a156b7ce97206c4f9c5ce6fc5ae791210'
-                  '2b6b502e59050b5b21ce263dddb2044b652236f4d42ab4b5d6aa73189c'
-                  'ef1ace778d7845a5c1c1c7147123188f8dc551054ee162b634d60f097f7'
-                  '19076640e20980a0093113a8bd73', 16),
-         'q': int('96c5390a8b612c0e422bb2b0ea194a3ec935a281', 16),
-         'x': int('8185fee9cc7c0e91fd85503274f1cd5a3fd15a49', 16),
-         'y': int('6f26d98d41de7d871b6381851c9d91fa03942092ab6097e76422'
-                  '070edb71db44ff568280fdb1709f8fc3feab39f1f824adaeb2a29808815'
-                  '6ac31af1aa04bf54f475bdcfdcf2f8a2dd973e922d83e76f01655861760'
-                  '3129b21c70bf7d0e5dc9e68fe332e295b65876eb9a12fe6fca9f1a1ce80'
-                  '204646bf99b5771d249a6fea627', 16)},
-        {'g': int('06b7861abbd35cc89e79c52f68d20875389b127361ca66822138ce4991d'
-                  '2b862259d6b4548a6495b195aa0e0b6137ca37eb23b94074d3c3d30004'
-                  '2bdf15762812b6333ef7b07ceba78607610fcc9ee68491dbc1e34cd126'
-                  '15474e52b18bc934fb00c61d39e7da8902291c4434a4e2224c3f4fd9'
-                  'f93cd6f4f17fc076341a7e7d9', 16),
-         'p': int('d38311e2cd388c3ed698e82fdf88eb92b5a9a483dc88005d4b725ef341e'
-                  'abb47cf8a7a8a41e792a156b7ce97206c4f9c5ce6fc5ae7912102b6b50'
-                  '2e59050b5b21ce263dddb2044b652236f4d42ab4b5d6aa73189cef1a'
-                  'ce778d7845a5c1c1c7147123188f8dc551054ee162b634d6'
-                  '0f097f719076640e20980a0093113a8bd73', 16),
-         'q': int('96c5390a8b612c0e422bb2b0ea194a3ec935a281', 16),
-         'x': int('85322d6ea73083064376099ca2f65f56e8522d9b', 16),
-         'y': int('21f8690f717c9f4dcb8f4b6971de2f15b9231fcf41b7eeb997d781f240'
-                  'bfdddfd2090d22083c26cca39bf37c9caf1ec89518ea64845a50d747b49'
-                  '131ffff6a2fd11ea7bacbb93c7d05137383a06365af82225dd3713c'
-                  'a5a45006316f53bd12b0e260d5f79795e5a4c9f353f12867a1d3'
-                  '202394673ada8563b71555e53f415254', 16)},
-
-        {'g': int('e4c4eca88415b23ecf811c96e48cd24200fe916631a68a684e6ccb6b191'
-                  '3413d344d1d8d84a333839d88eee431521f6e357c16e6a93be111a9807'
-                  '6739cd401bab3b9d565bf4fb99e9d185b1e14d61c93700133f908bae0'
-                  '3e28764d107dcd2ea7674217622074bb19efff482f5f5c1a86d5551b2'
-                  'fc68d1c6e9d8011958ef4b9c2a3a55d0d3c882e6ad7f9f0f3c61568f78'
-                  'd0706b10a26f23b4f197c322b825002284a0aca91807bba98ece912'
-                  'b80e10cdf180cf99a35f210c1655fbfdd74f13b1b5046591f8403873d'
-                  '12239834dd6c4eceb42bf7482e1794a1601357b629ddfa971f2ed273b1'
-                  '46ec1ca06d0adf55dd91d65c37297bda78c6d210c0bc26e558302', 16),
-         'p': int('ea1fb1af22881558ef93be8a5f8653c5a559434c49c8c2c12ace'
-                  '5e9c41434c9cf0a8e9498acb0f4663c08b4484eace845f6fb17d'
-                  'ac62c98e706af0fc74e4da1c6c2b3fbf5a1d58ff82fc1a66f3e8b122'
-                  '52c40278fff9dd7f102eed2cb5b7323ebf1908c234d935414dded7f8d2'
-                  '44e54561b0dca39b301de8c49da9fb23df33c6182e3f983208c560fb5'
-                  '119fbf78ebe3e6564ee235c6a15cbb9ac247baba5a423bc6582a1a9d8a'
-                  '2b4f0e9e3d9dbac122f750dd754325135257488b1f6ecabf21bff2947'
-                  'fe0d3b2cb7ffe67f4e7fcdf1214f6053e72a5bb0dd20a0e9fe6db2df0a'
-                  '908c36e95e60bf49ca4368b8b892b9c79f61ef91c47567c40e1f80ac'
-                  '5aa66ef7', 16),
-         'q': int('8ec73f3761caf5fdfe6e4e82098bf10f898740dcb808204bf6b1'
-                  '8f507192c19d', 16),
-         'x': int('405772da6e90d809e77d5de796562a2dd4dfd10ef00a83a3aba6'
-                  'bd818a0348a1', 16),
-         'y': int('6b32e31ab9031dc4dd0b5039a78d07826687ab087ae6de4736f5'
-                  'b0434e1253092e8a0b231f9c87f3fc8a4cb5634eb194bf1b638'
-                  'b7a7889620ce6711567e36aa36cda4604cfaa601a45918371d'
-                  '4ccf68d8b10a50a0460eb1dc0fff62ef5e6ee4d473e18ea4a6'
-                  '6c196fb7e677a49b48241a0b4a97128eff30fa437050501a584'
-                  'f8771e7280d26d5af30784039159c11ebfea10b692fd0a58215ee'
-                  'b18bff117e13f08db792ed4151a218e4bed8dddfb0793225bd1e97'
-                  '73505166f4bd8cedbb286ea28232972da7bae836ba97329ba6b0a36508'
-                  'e50a52a7675e476d4d4137eae13f22a9d2fefde708ba8f34bf336c6e7'
-                  '6331761e4b0617633fe7ec3f23672fb19d27', 16)},
-        {'g': int('e4c4eca88415b23ecf811c96e48cd24200fe916631a68a684e6ccb6b191'
-                  '3413d344d1d8d84a333839d88eee431521f6e357c16e6a93be111a9807'
-                  '6739cd401bab3b9d565bf4fb99e9d185b1e14d61c93700133f908bae0'
-                  '3e28764d107dcd2ea7674217622074bb19efff482f5f5c1a86d5551b2'
-                  'fc68d1c6e9d8011958ef4b9c2a3a55d0d3c882e6ad7f9f0f3c61568f78'
-                  'd0706b10a26f23b4f197c322b825002284a0aca91807bba98ece912'
-                  'b80e10cdf180cf99a35f210c1655fbfdd74f13b1b5046591f8403873d'
-                  '12239834dd6c4eceb42bf7482e1794a1601357b629ddfa971f2ed273b1'
-                  '46ec1ca06d0adf55dd91d65c37297bda78c6d210c0bc26e558302', 16),
-         'p': int('ea1fb1af22881558ef93be8a5f8653c5a559434c49c8c2c12ace'
-                  '5e9c41434c9cf0a8e9498acb0f4663c08b4484eace845f6fb17d'
-                  'ac62c98e706af0fc74e4da1c6c2b3fbf5a1d58ff82fc1a66f3e8b122'
-                  '52c40278fff9dd7f102eed2cb5b7323ebf1908c234d935414dded7f8d2'
-                  '44e54561b0dca39b301de8c49da9fb23df33c6182e3f983208c560fb5'
-                  '119fbf78ebe3e6564ee235c6a15cbb9ac247baba5a423bc6582a1a9d8a'
-                  '2b4f0e9e3d9dbac122f750dd754325135257488b1f6ecabf21bff2947'
-                  'fe0d3b2cb7ffe67f4e7fcdf1214f6053e72a5bb0dd20a0e9fe6db2df0a'
-                  '908c36e95e60bf49ca4368b8b892b9c79f61ef91c47567c40e1f80ac'
-                  '5aa66ef7', 16),
-         'q': int('8ec73f3761caf5fdfe6e4e82098bf10f898740dcb808204bf6b1'
-                  '8f507192c19d', 16),
-         'x': int('0e0b95e31fda3f888059c46c3002ef8f2d6be112d0209aeb9e95'
-                  '45da67aeea80', 16),
-         'y': int('778082b77ddba6f56597cc74c3a612abf2ddbd85cc81430c99ab'
-                  '843c1f630b9db0139965f563978164f9bf3a8397256be714625'
-                  'cd41cd7fa0067d94ea66d7e073f7125af692ad01371d4a17f45'
-                  '50590378f2b074030c20e36911598a1018772f61be3b24de4be'
-                  '5a388ccc09e15a92819c31dec50de9fde105b49eaa097b9d13d'
-                  '9219eeb33b628facfd1c78a7159c8430d0647c506e7e3de74763c'
-                  'b351eada72c00bef3c9641881e6254870c1e6599f8ca2f1bbb74f'
-                  '39a905e3a34e4544168e6e50c9e3305fd09cab6ed4aff6fda6e0d'
-                  '5bf375c81ac9054406d9193b003c89272f1bd83d48250134b65c77'
-                  'c2b6332d38d34d9016f0e8975536ad6c348a1faedb0', 16)},
-
-        {'g': int('ce84b30ddf290a9f787a7c2f1ce92c1cbf4ef400e3cd7ce4978d'
-                  'b2104d7394b493c18332c64cec906a71c3778bd93341165dee8'
-                  'e6cd4ca6f13afff531191194ada55ecf01ff94d6cf7c4768b82'
-                  'dd29cd131aaf202aefd40e564375285c01f3220af4d70b96f1'
-                  '395420d778228f1461f5d0b8e47357e87b1fe3286223b553e3'
-                  'fc9928f16ae3067ded6721bedf1d1a01bfd22b9ae85fce77820d88cdf'
-                  '50a6bde20668ad77a707d1c60fcc5d51c9de488610d0285eb8ff721f'
-                  'f141f93a9fb23c1d1f7654c07c46e58836d1652828f71057b8aff0b077'
-                  '8ef2ca934ea9d0f37daddade2d823a4d8e362721082e279d003b575ee'
-                  '59fd050d105dfd71cd63154efe431a0869178d9811f4f231dc5dcf3b'
-                  '0ec0f2b0f9896c32ec6c7ee7d60aa97109e09224907328d4e6acd1011'
-                  '7e45774406c4c947da8020649c3168f690e0bd6e91ac67074d1d436b'
-                  '58ae374523deaf6c93c1e6920db4a080b744804bb073cecfe83fa939'
-                  '8cf150afa286dc7eb7949750cf5001ce104e9187f7e16859afa8fd0d'
-                  '775ae', 16),
-         'p': int('f335666dd1339165af8b9a5e3835adfe15c158e4c3c7bd53132e7d5828'
-                  'c352f593a9a787760ce34b789879941f2f01f02319f6ae0b756f1a842'
-                  'ba54c85612ed632ee2d79ef17f06b77c641b7b080aff52a03fc2462e8'
-                  '0abc64d223723c236deeb7d201078ec01ca1fbc1763139e25099a84ec'
-                  '389159c409792080736bd7caa816b92edf23f2c351f90074aa5ea2651'
-                  'b372f8b58a0a65554db2561d706a63685000ac576b7e4562e262a1428'
-                  '5a9c6370b290e4eb7757527d80b6c0fd5df831d36f3d1d35f12ab0605'
-                  '48de1605fd15f7c7aafed688b146a02c945156e284f5b71282045aba9'
-                  '844d48b5df2e9e7a5887121eae7d7b01db7cdf6ff917cd8eb50c6bf1d'
-                  '54f90cce1a491a9c74fea88f7e7230b047d16b5a6027881d6f154818f'
-                  '06e513faf40c8814630e4e254f17a47bfe9cb519b98289935bf17673a'
-                  'e4c8033504a20a898d0032ee402b72d5986322f3bdfb27400561f7476'
-                  'cd715eaabb7338b854e51fc2fa026a5a579b6dcea1b1c0559c13d3c11'
-                  '36f303f4b4d25ad5b692229957', 16),
-         'q': int('d3eba6521240694015ef94412e08bf3cf8d635a455a398d6f210'
-                  'f6169041653b', 16),
-         'x': int('b2764c46113983777d3e7e97589f1303806d14ad9f2f1ef03309'
-                  '7de954b17706', 16),
-         'y': int('814824e435e1e6f38daa239aad6dad21033afce6a3ebd35c1359348a0f2'
-                  '418871968c2babfc2baf47742148828f8612183178f126504da73566b6'
-                  'bab33ba1f124c15aa461555c2451d86c94ee21c3e3fc24c55527e'
-                  '01b1f03adcdd8ec5cb08082803a7b6a829c3e99eeb332a2cf5c035b0c'
-                  'e0078d3d414d31fa47e9726be2989b8d06da2e6cd363f5a7d1515e3f4'
-                  '925e0b32adeae3025cc5a996f6fd27494ea408763de48f3bb39f6a06'
-                  '514b019899b312ec570851637b8865cff3a52bf5d54ad5a19e6e400'
-                  'a2d33251055d0a440b50d53f4791391dc754ad02b9eab74c46b4903'
-                  'f9d76f824339914db108057af7cde657d41766a99991ac8787694f'
-                  '4185d6f91d7627048f827b405ec67bf2fe56141c4c581d8c317333'
-                  '624e073e5879a82437cb0c7b435c0ce434e15965db1315d648959'
-                  '91e6bbe7dac040c42052408bbc53423fd31098248a58f8a67da3a'
-                  '39895cd0cc927515d044c1e3cb6a3259c3d0da354cce89ea3552c'
-                  '59609db10ee989986527436af21d9485ddf25f90f7dff6d2bae', 16)},
-        {'g': int('ce84b30ddf290a9f787a7c2f1ce92c1cbf4ef400e3cd7ce4978d'
-                  'b2104d7394b493c18332c64cec906a71c3778bd93341165dee8'
-                  'e6cd4ca6f13afff531191194ada55ecf01ff94d6cf7c4768b82'
-                  'dd29cd131aaf202aefd40e564375285c01f3220af4d70b96f1'
-                  '395420d778228f1461f5d0b8e47357e87b1fe3286223b553e3'
-                  'fc9928f16ae3067ded6721bedf1d1a01bfd22b9ae85fce77820d88cdf'
-                  '50a6bde20668ad77a707d1c60fcc5d51c9de488610d0285eb8ff721f'
-                  'f141f93a9fb23c1d1f7654c07c46e58836d1652828f71057b8aff0b077'
-                  '8ef2ca934ea9d0f37daddade2d823a4d8e362721082e279d003b575ee'
-                  '59fd050d105dfd71cd63154efe431a0869178d9811f4f231dc5dcf3b'
-                  '0ec0f2b0f9896c32ec6c7ee7d60aa97109e09224907328d4e6acd1011'
-                  '7e45774406c4c947da8020649c3168f690e0bd6e91ac67074d1d436b'
-                  '58ae374523deaf6c93c1e6920db4a080b744804bb073cecfe83fa939'
-                  '8cf150afa286dc7eb7949750cf5001ce104e9187f7e16859afa8fd0d'
-                  '775ae', 16),
-         'p': int('f335666dd1339165af8b9a5e3835adfe15c158e4c3c7bd53132e7d5828'
-                  'c352f593a9a787760ce34b789879941f2f01f02319f6ae0b756f1a842'
-                  'ba54c85612ed632ee2d79ef17f06b77c641b7b080aff52a03fc2462e8'
-                  '0abc64d223723c236deeb7d201078ec01ca1fbc1763139e25099a84ec'
-                  '389159c409792080736bd7caa816b92edf23f2c351f90074aa5ea2651'
-                  'b372f8b58a0a65554db2561d706a63685000ac576b7e4562e262a1428'
-                  '5a9c6370b290e4eb7757527d80b6c0fd5df831d36f3d1d35f12ab0605'
-                  '48de1605fd15f7c7aafed688b146a02c945156e284f5b71282045aba9'
-                  '844d48b5df2e9e7a5887121eae7d7b01db7cdf6ff917cd8eb50c6bf1d'
-                  '54f90cce1a491a9c74fea88f7e7230b047d16b5a6027881d6f154818f'
-                  '06e513faf40c8814630e4e254f17a47bfe9cb519b98289935bf17673a'
-                  'e4c8033504a20a898d0032ee402b72d5986322f3bdfb27400561f7476'
-                  'cd715eaabb7338b854e51fc2fa026a5a579b6dcea1b1c0559c13d3c11'
-                  '36f303f4b4d25ad5b692229957', 16),
-         'q': int('d3eba6521240694015ef94412e08bf3cf8d635a455a398d6f210'
-                  'f6169041653b', 16),
-         'x': int('52e3e040efb30e1befd909a0bdbcfd140d005b1bff094af97186'
-                  '080262f1904d', 16),
-         'y': int('a5ae6e8f9b7a68ab0516dad4d7b7d002126f811d5a52e3d35c6d'
-                  '387fcb43fd19bf7792362f9c98f8348aa058bb62376685f3d0c3'
-                  '66c520d697fcd8416947151d4bbb6f32b53528a016479e99d2cd'
-                  '48d1fc679027c15f0042f207984efe05c1796bca8eba678dfdd0'
-                  '0b80418e3ea840557e73b09e003882f9a68edba3431d351d1ca0'
-                  '7a8150b018fdbdf6c2f1ab475792a3ccaa6594472a45f8dc777b'
-                  '60bf67de3e0f65c20d11b7d59faedf83fbce52617f500d9e5149'
-                  '47c455274c6e900464767fb56599b81344cf6d12c25cb2b7d038'
-                  'd7b166b6cf30534811c15d0e8ab880a2ac06786ae2ddde61329a'
-                  '78d526f65245380ce877e979c5b50de66c9c30d66382c8f25465'
-                  '3d25a1eb1d3a4897d7623399b473ce712a2184cf2da1861706c4'
-                  '1466806aefe41b497db82aca6c31c8f4aa68c17d1d9e380b5799'
-                  '8917655783ec96e5234a131f7299398d36f1f5f84297a55ff292'
-                  'f1f060958c358fed346db2de45127ca728a9417b2c54203e33e5'
-                  '3b9a061d924395b09afab8daf3e8dd7eedcec3ac', 16)}
+        {
+            "g": int(
+                "06b7861abbd35cc89e79c52f68d20875389b127361ca66822138ce499"
+                "1d2b862259d6b4548a6495b195aa0e0b6137ca37eb23b94074d3c3d3000"
+                "42bdf15762812b6333ef7b07ceba78607610fcc9ee68491dbc1e34cd12"
+                "615474e52b18bc934fb00c61d39e7da8902291c4434a4e2224c3f"
+                "4fd9f93cd6f4f17fc076341a7e7d9",
+                16,
+            ),
+            "p": int(
+                "d38311e2cd388c3ed698e82fdf88eb92b5a9a483dc88005d4b725e"
+                "f341eabb47cf8a7a8a41e792a156b7ce97206c4f9c5ce6fc5ae791210"
+                "2b6b502e59050b5b21ce263dddb2044b652236f4d42ab4b5d6aa73189c"
+                "ef1ace778d7845a5c1c1c7147123188f8dc551054ee162b634d60f097f7"
+                "19076640e20980a0093113a8bd73",
+                16,
+            ),
+            "q": int("96c5390a8b612c0e422bb2b0ea194a3ec935a281", 16),
+            "x": int("8185fee9cc7c0e91fd85503274f1cd5a3fd15a49", 16),
+            "y": int(
+                "6f26d98d41de7d871b6381851c9d91fa03942092ab6097e76422"
+                "070edb71db44ff568280fdb1709f8fc3feab39f1f824adaeb2a29808815"
+                "6ac31af1aa04bf54f475bdcfdcf2f8a2dd973e922d83e76f01655861760"
+                "3129b21c70bf7d0e5dc9e68fe332e295b65876eb9a12fe6fca9f1a1ce80"
+                "204646bf99b5771d249a6fea627",
+                16,
+            ),
+        },
+        {
+            "g": int(
+                "06b7861abbd35cc89e79c52f68d20875389b127361ca66822138ce4991d"
+                "2b862259d6b4548a6495b195aa0e0b6137ca37eb23b94074d3c3d30004"
+                "2bdf15762812b6333ef7b07ceba78607610fcc9ee68491dbc1e34cd126"
+                "15474e52b18bc934fb00c61d39e7da8902291c4434a4e2224c3f4fd9"
+                "f93cd6f4f17fc076341a7e7d9",
+                16,
+            ),
+            "p": int(
+                "d38311e2cd388c3ed698e82fdf88eb92b5a9a483dc88005d4b725ef341e"
+                "abb47cf8a7a8a41e792a156b7ce97206c4f9c5ce6fc5ae7912102b6b50"
+                "2e59050b5b21ce263dddb2044b652236f4d42ab4b5d6aa73189cef1a"
+                "ce778d7845a5c1c1c7147123188f8dc551054ee162b634d6"
+                "0f097f719076640e20980a0093113a8bd73",
+                16,
+            ),
+            "q": int("96c5390a8b612c0e422bb2b0ea194a3ec935a281", 16),
+            "x": int("85322d6ea73083064376099ca2f65f56e8522d9b", 16),
+            "y": int(
+                "21f8690f717c9f4dcb8f4b6971de2f15b9231fcf41b7eeb997d781f240"
+                "bfdddfd2090d22083c26cca39bf37c9caf1ec89518ea64845a50d747b49"
+                "131ffff6a2fd11ea7bacbb93c7d05137383a06365af82225dd3713c"
+                "a5a45006316f53bd12b0e260d5f79795e5a4c9f353f12867a1d3"
+                "202394673ada8563b71555e53f415254",
+                16,
+            ),
+        },
+        {
+            "g": int(
+                "e4c4eca88415b23ecf811c96e48cd24200fe916631a68a684e6ccb6b191"
+                "3413d344d1d8d84a333839d88eee431521f6e357c16e6a93be111a9807"
+                "6739cd401bab3b9d565bf4fb99e9d185b1e14d61c93700133f908bae0"
+                "3e28764d107dcd2ea7674217622074bb19efff482f5f5c1a86d5551b2"
+                "fc68d1c6e9d8011958ef4b9c2a3a55d0d3c882e6ad7f9f0f3c61568f78"
+                "d0706b10a26f23b4f197c322b825002284a0aca91807bba98ece912"
+                "b80e10cdf180cf99a35f210c1655fbfdd74f13b1b5046591f8403873d"
+                "12239834dd6c4eceb42bf7482e1794a1601357b629ddfa971f2ed273b1"
+                "46ec1ca06d0adf55dd91d65c37297bda78c6d210c0bc26e558302",
+                16,
+            ),
+            "p": int(
+                "ea1fb1af22881558ef93be8a5f8653c5a559434c49c8c2c12ace"
+                "5e9c41434c9cf0a8e9498acb0f4663c08b4484eace845f6fb17d"
+                "ac62c98e706af0fc74e4da1c6c2b3fbf5a1d58ff82fc1a66f3e8b122"
+                "52c40278fff9dd7f102eed2cb5b7323ebf1908c234d935414dded7f8d2"
+                "44e54561b0dca39b301de8c49da9fb23df33c6182e3f983208c560fb5"
+                "119fbf78ebe3e6564ee235c6a15cbb9ac247baba5a423bc6582a1a9d8a"
+                "2b4f0e9e3d9dbac122f750dd754325135257488b1f6ecabf21bff2947"
+                "fe0d3b2cb7ffe67f4e7fcdf1214f6053e72a5bb0dd20a0e9fe6db2df0a"
+                "908c36e95e60bf49ca4368b8b892b9c79f61ef91c47567c40e1f80ac"
+                "5aa66ef7",
+                16,
+            ),
+            "q": int(
+                "8ec73f3761caf5fdfe6e4e82098bf10f898740dcb808204bf6b1"
+                "8f507192c19d",
+                16,
+            ),
+            "x": int(
+                "405772da6e90d809e77d5de796562a2dd4dfd10ef00a83a3aba6"
+                "bd818a0348a1",
+                16,
+            ),
+            "y": int(
+                "6b32e31ab9031dc4dd0b5039a78d07826687ab087ae6de4736f5"
+                "b0434e1253092e8a0b231f9c87f3fc8a4cb5634eb194bf1b638"
+                "b7a7889620ce6711567e36aa36cda4604cfaa601a45918371d"
+                "4ccf68d8b10a50a0460eb1dc0fff62ef5e6ee4d473e18ea4a6"
+                "6c196fb7e677a49b48241a0b4a97128eff30fa437050501a584"
+                "f8771e7280d26d5af30784039159c11ebfea10b692fd0a58215ee"
+                "b18bff117e13f08db792ed4151a218e4bed8dddfb0793225bd1e97"
+                "73505166f4bd8cedbb286ea28232972da7bae836ba97329ba6b0a36508"
+                "e50a52a7675e476d4d4137eae13f22a9d2fefde708ba8f34bf336c6e7"
+                "6331761e4b0617633fe7ec3f23672fb19d27",
+                16,
+            ),
+        },
+        {
+            "g": int(
+                "e4c4eca88415b23ecf811c96e48cd24200fe916631a68a684e6ccb6b191"
+                "3413d344d1d8d84a333839d88eee431521f6e357c16e6a93be111a9807"
+                "6739cd401bab3b9d565bf4fb99e9d185b1e14d61c93700133f908bae0"
+                "3e28764d107dcd2ea7674217622074bb19efff482f5f5c1a86d5551b2"
+                "fc68d1c6e9d8011958ef4b9c2a3a55d0d3c882e6ad7f9f0f3c61568f78"
+                "d0706b10a26f23b4f197c322b825002284a0aca91807bba98ece912"
+                "b80e10cdf180cf99a35f210c1655fbfdd74f13b1b5046591f8403873d"
+                "12239834dd6c4eceb42bf7482e1794a1601357b629ddfa971f2ed273b1"
+                "46ec1ca06d0adf55dd91d65c37297bda78c6d210c0bc26e558302",
+                16,
+            ),
+            "p": int(
+                "ea1fb1af22881558ef93be8a5f8653c5a559434c49c8c2c12ace"
+                "5e9c41434c9cf0a8e9498acb0f4663c08b4484eace845f6fb17d"
+                "ac62c98e706af0fc74e4da1c6c2b3fbf5a1d58ff82fc1a66f3e8b122"
+                "52c40278fff9dd7f102eed2cb5b7323ebf1908c234d935414dded7f8d2"
+                "44e54561b0dca39b301de8c49da9fb23df33c6182e3f983208c560fb5"
+                "119fbf78ebe3e6564ee235c6a15cbb9ac247baba5a423bc6582a1a9d8a"
+                "2b4f0e9e3d9dbac122f750dd754325135257488b1f6ecabf21bff2947"
+                "fe0d3b2cb7ffe67f4e7fcdf1214f6053e72a5bb0dd20a0e9fe6db2df0a"
+                "908c36e95e60bf49ca4368b8b892b9c79f61ef91c47567c40e1f80ac"
+                "5aa66ef7",
+                16,
+            ),
+            "q": int(
+                "8ec73f3761caf5fdfe6e4e82098bf10f898740dcb808204bf6b1"
+                "8f507192c19d",
+                16,
+            ),
+            "x": int(
+                "0e0b95e31fda3f888059c46c3002ef8f2d6be112d0209aeb9e95"
+                "45da67aeea80",
+                16,
+            ),
+            "y": int(
+                "778082b77ddba6f56597cc74c3a612abf2ddbd85cc81430c99ab"
+                "843c1f630b9db0139965f563978164f9bf3a8397256be714625"
+                "cd41cd7fa0067d94ea66d7e073f7125af692ad01371d4a17f45"
+                "50590378f2b074030c20e36911598a1018772f61be3b24de4be"
+                "5a388ccc09e15a92819c31dec50de9fde105b49eaa097b9d13d"
+                "9219eeb33b628facfd1c78a7159c8430d0647c506e7e3de74763c"
+                "b351eada72c00bef3c9641881e6254870c1e6599f8ca2f1bbb74f"
+                "39a905e3a34e4544168e6e50c9e3305fd09cab6ed4aff6fda6e0d"
+                "5bf375c81ac9054406d9193b003c89272f1bd83d48250134b65c77"
+                "c2b6332d38d34d9016f0e8975536ad6c348a1faedb0",
+                16,
+            ),
+        },
+        {
+            "g": int(
+                "ce84b30ddf290a9f787a7c2f1ce92c1cbf4ef400e3cd7ce4978d"
+                "b2104d7394b493c18332c64cec906a71c3778bd93341165dee8"
+                "e6cd4ca6f13afff531191194ada55ecf01ff94d6cf7c4768b82"
+                "dd29cd131aaf202aefd40e564375285c01f3220af4d70b96f1"
+                "395420d778228f1461f5d0b8e47357e87b1fe3286223b553e3"
+                "fc9928f16ae3067ded6721bedf1d1a01bfd22b9ae85fce77820d88cdf"
+                "50a6bde20668ad77a707d1c60fcc5d51c9de488610d0285eb8ff721f"
+                "f141f93a9fb23c1d1f7654c07c46e58836d1652828f71057b8aff0b077"
+                "8ef2ca934ea9d0f37daddade2d823a4d8e362721082e279d003b575ee"
+                "59fd050d105dfd71cd63154efe431a0869178d9811f4f231dc5dcf3b"
+                "0ec0f2b0f9896c32ec6c7ee7d60aa97109e09224907328d4e6acd1011"
+                "7e45774406c4c947da8020649c3168f690e0bd6e91ac67074d1d436b"
+                "58ae374523deaf6c93c1e6920db4a080b744804bb073cecfe83fa939"
+                "8cf150afa286dc7eb7949750cf5001ce104e9187f7e16859afa8fd0d"
+                "775ae",
+                16,
+            ),
+            "p": int(
+                "f335666dd1339165af8b9a5e3835adfe15c158e4c3c7bd53132e7d5828"
+                "c352f593a9a787760ce34b789879941f2f01f02319f6ae0b756f1a842"
+                "ba54c85612ed632ee2d79ef17f06b77c641b7b080aff52a03fc2462e8"
+                "0abc64d223723c236deeb7d201078ec01ca1fbc1763139e25099a84ec"
+                "389159c409792080736bd7caa816b92edf23f2c351f90074aa5ea2651"
+                "b372f8b58a0a65554db2561d706a63685000ac576b7e4562e262a1428"
+                "5a9c6370b290e4eb7757527d80b6c0fd5df831d36f3d1d35f12ab0605"
+                "48de1605fd15f7c7aafed688b146a02c945156e284f5b71282045aba9"
+                "844d48b5df2e9e7a5887121eae7d7b01db7cdf6ff917cd8eb50c6bf1d"
+                "54f90cce1a491a9c74fea88f7e7230b047d16b5a6027881d6f154818f"
+                "06e513faf40c8814630e4e254f17a47bfe9cb519b98289935bf17673a"
+                "e4c8033504a20a898d0032ee402b72d5986322f3bdfb27400561f7476"
+                "cd715eaabb7338b854e51fc2fa026a5a579b6dcea1b1c0559c13d3c11"
+                "36f303f4b4d25ad5b692229957",
+                16,
+            ),
+            "q": int(
+                "d3eba6521240694015ef94412e08bf3cf8d635a455a398d6f210"
+                "f6169041653b",
+                16,
+            ),
+            "x": int(
+                "b2764c46113983777d3e7e97589f1303806d14ad9f2f1ef03309"
+                "7de954b17706",
+                16,
+            ),
+            "y": int(
+                "814824e435e1e6f38daa239aad6dad21033afce6a3ebd35c1359348a0f2"
+                "418871968c2babfc2baf47742148828f8612183178f126504da73566b6"
+                "bab33ba1f124c15aa461555c2451d86c94ee21c3e3fc24c55527e"
+                "01b1f03adcdd8ec5cb08082803a7b6a829c3e99eeb332a2cf5c035b0c"
+                "e0078d3d414d31fa47e9726be2989b8d06da2e6cd363f5a7d1515e3f4"
+                "925e0b32adeae3025cc5a996f6fd27494ea408763de48f3bb39f6a06"
+                "514b019899b312ec570851637b8865cff3a52bf5d54ad5a19e6e400"
+                "a2d33251055d0a440b50d53f4791391dc754ad02b9eab74c46b4903"
+                "f9d76f824339914db108057af7cde657d41766a99991ac8787694f"
+                "4185d6f91d7627048f827b405ec67bf2fe56141c4c581d8c317333"
+                "624e073e5879a82437cb0c7b435c0ce434e15965db1315d648959"
+                "91e6bbe7dac040c42052408bbc53423fd31098248a58f8a67da3a"
+                "39895cd0cc927515d044c1e3cb6a3259c3d0da354cce89ea3552c"
+                "59609db10ee989986527436af21d9485ddf25f90f7dff6d2bae",
+                16,
+            ),
+        },
+        {
+            "g": int(
+                "ce84b30ddf290a9f787a7c2f1ce92c1cbf4ef400e3cd7ce4978d"
+                "b2104d7394b493c18332c64cec906a71c3778bd93341165dee8"
+                "e6cd4ca6f13afff531191194ada55ecf01ff94d6cf7c4768b82"
+                "dd29cd131aaf202aefd40e564375285c01f3220af4d70b96f1"
+                "395420d778228f1461f5d0b8e47357e87b1fe3286223b553e3"
+                "fc9928f16ae3067ded6721bedf1d1a01bfd22b9ae85fce77820d88cdf"
+                "50a6bde20668ad77a707d1c60fcc5d51c9de488610d0285eb8ff721f"
+                "f141f93a9fb23c1d1f7654c07c46e58836d1652828f71057b8aff0b077"
+                "8ef2ca934ea9d0f37daddade2d823a4d8e362721082e279d003b575ee"
+                "59fd050d105dfd71cd63154efe431a0869178d9811f4f231dc5dcf3b"
+                "0ec0f2b0f9896c32ec6c7ee7d60aa97109e09224907328d4e6acd1011"
+                "7e45774406c4c947da8020649c3168f690e0bd6e91ac67074d1d436b"
+                "58ae374523deaf6c93c1e6920db4a080b744804bb073cecfe83fa939"
+                "8cf150afa286dc7eb7949750cf5001ce104e9187f7e16859afa8fd0d"
+                "775ae",
+                16,
+            ),
+            "p": int(
+                "f335666dd1339165af8b9a5e3835adfe15c158e4c3c7bd53132e7d5828"
+                "c352f593a9a787760ce34b789879941f2f01f02319f6ae0b756f1a842"
+                "ba54c85612ed632ee2d79ef17f06b77c641b7b080aff52a03fc2462e8"
+                "0abc64d223723c236deeb7d201078ec01ca1fbc1763139e25099a84ec"
+                "389159c409792080736bd7caa816b92edf23f2c351f90074aa5ea2651"
+                "b372f8b58a0a65554db2561d706a63685000ac576b7e4562e262a1428"
+                "5a9c6370b290e4eb7757527d80b6c0fd5df831d36f3d1d35f12ab0605"
+                "48de1605fd15f7c7aafed688b146a02c945156e284f5b71282045aba9"
+                "844d48b5df2e9e7a5887121eae7d7b01db7cdf6ff917cd8eb50c6bf1d"
+                "54f90cce1a491a9c74fea88f7e7230b047d16b5a6027881d6f154818f"
+                "06e513faf40c8814630e4e254f17a47bfe9cb519b98289935bf17673a"
+                "e4c8033504a20a898d0032ee402b72d5986322f3bdfb27400561f7476"
+                "cd715eaabb7338b854e51fc2fa026a5a579b6dcea1b1c0559c13d3c11"
+                "36f303f4b4d25ad5b692229957",
+                16,
+            ),
+            "q": int(
+                "d3eba6521240694015ef94412e08bf3cf8d635a455a398d6f210"
+                "f6169041653b",
+                16,
+            ),
+            "x": int(
+                "52e3e040efb30e1befd909a0bdbcfd140d005b1bff094af97186"
+                "080262f1904d",
+                16,
+            ),
+            "y": int(
+                "a5ae6e8f9b7a68ab0516dad4d7b7d002126f811d5a52e3d35c6d"
+                "387fcb43fd19bf7792362f9c98f8348aa058bb62376685f3d0c3"
+                "66c520d697fcd8416947151d4bbb6f32b53528a016479e99d2cd"
+                "48d1fc679027c15f0042f207984efe05c1796bca8eba678dfdd0"
+                "0b80418e3ea840557e73b09e003882f9a68edba3431d351d1ca0"
+                "7a8150b018fdbdf6c2f1ab475792a3ccaa6594472a45f8dc777b"
+                "60bf67de3e0f65c20d11b7d59faedf83fbce52617f500d9e5149"
+                "47c455274c6e900464767fb56599b81344cf6d12c25cb2b7d038"
+                "d7b166b6cf30534811c15d0e8ab880a2ac06786ae2ddde61329a"
+                "78d526f65245380ce877e979c5b50de66c9c30d66382c8f25465"
+                "3d25a1eb1d3a4897d7623399b473ce712a2184cf2da1861706c4"
+                "1466806aefe41b497db82aca6c31c8f4aa68c17d1d9e380b5799"
+                "8917655783ec96e5234a131f7299398d36f1f5f84297a55ff292"
+                "f1f060958c358fed346db2de45127ca728a9417b2c54203e33e5"
+                "3b9a061d924395b09afab8daf3e8dd7eedcec3ac",
+                16,
+            ),
+        },
     ]
 
     assert expected == load_fips_dsa_key_pair_vectors(vector_data)
 
 
 def test_load_fips_dsa_sig_ver_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     # CAVS 11.0
     # "SigVer" information
     # Mod sizes selected: SHA-1 L=1024, N=160,SHA-384 L=2048, N=256
@@ -1902,166 +2124,236 @@
     R = 343ea0a9e66277380f604d5880fca686bffab69ca97bfba015a102a7e23dce0e
     S = 6258488c770e0f5ad7b9da8bade5023fc0d17c6ec517bd08d53e6dc01ac5c2b3
     Result = P
-    """).splitlines()
+    """
+    ).splitlines()
 
     expected = [
         {
-            'p': int('dc5bf3a88b2d99e4c95cdd7a0501cc38630d425cf5c390af3429cff1'
-                     'f35147b795caea923f0d3577158f8a0c89dabd1962c2c453306b5d70'
-                     'cacfb01430aceb54e5a5fa6f9340d3bd2da612fceeb76b0ec1ebfae6'
-                     '35a56ab141b108e00dc76eefe2edd0c514c21c457457c39065dba9d0'
-                     'ecb7569c247172d8438ad2827b60435b', 16),
-            'q': int('e956602b83d195dbe945b3ac702fc61f81571f1d', 16),
-            'g': int('d7eb9ca20a3c7a079606bafc4c9261ccaba303a5dc9fe9953f197dfe'
-                     '548c234895baa77f441ee6a2d97b909cbbd26ff7b869d24cae51b5c6'
-                     'edb127a4b5d75cd8b46608bfa148249dffdb59807c5d7dde3fe3080c'
-                     'a3a2d28312142becb1fa8e24003e21c7287108174b95d5bc711e1c8d'
-                     '9b1076784f5dc37a964a5e51390da713', 16),
-            'digest_algorithm': 'SHA-1',
-            'msg': binascii.unhexlify(
-                b'0fe1bfee500bdb76026099b1d37553f6bdfe48c82094ef98cb309dd77733'
-                b'0bedfaa2f94c823ef74ef4074b50d8706041ac0e371c7c22dcf70263b8d6'
-                b'0e17a86c7c379cfda8f22469e0df9d49d59439fc99891873628fff25dda5'
-                b'fac5ac794e948babdde968143ba05f1128f34fdad5875edc4cd71c6c24ba'
-                b'2060ffbd439ce2b3'),
-            'x': int('1d93010c29ecfc432188942f46f19f44f0e1bb5d', 16),
-            'y': int('6240ea0647117c38fe705106d56db578f3e10130928452d4f3587881'
-                     'b8a2bc6873a8befc3237f20914e2a91c7f07a928ee22adeed23d74ab'
-                     '7f82ea11f70497e578f7a9b4cbd6f10226222b0b4da2ea1e49813d6b'
-                     'b9882fbf675c0846bb80cc891857b89b0ef1beb6cce3378a9aab5d66'
-                     'ad4cb9277cf447dfe1e64434749432fb', 16),
-            'r': int('b5af307867fb8b54390013cc67020ddf1f2c0b81', 16),
-            's': int('620d3b22ab5031440c3e35eab6f481298f9e9f08', 16),
-            'result': 'P'},
+            "p": int(
+                "dc5bf3a88b2d99e4c95cdd7a0501cc38630d425cf5c390af3429cff1"
+                "f35147b795caea923f0d3577158f8a0c89dabd1962c2c453306b5d70"
+                "cacfb01430aceb54e5a5fa6f9340d3bd2da612fceeb76b0ec1ebfae6"
+                "35a56ab141b108e00dc76eefe2edd0c514c21c457457c39065dba9d0"
+                "ecb7569c247172d8438ad2827b60435b",
+                16,
+            ),
+            "q": int("e956602b83d195dbe945b3ac702fc61f81571f1d", 16),
+            "g": int(
+                "d7eb9ca20a3c7a079606bafc4c9261ccaba303a5dc9fe9953f197dfe"
+                "548c234895baa77f441ee6a2d97b909cbbd26ff7b869d24cae51b5c6"
+                "edb127a4b5d75cd8b46608bfa148249dffdb59807c5d7dde3fe3080c"
+                "a3a2d28312142becb1fa8e24003e21c7287108174b95d5bc711e1c8d"
+                "9b1076784f5dc37a964a5e51390da713",
+                16,
+            ),
+            "digest_algorithm": "SHA-1",
+            "msg": binascii.unhexlify(
+                b"0fe1bfee500bdb76026099b1d37553f6bdfe48c82094ef98cb309dd77733"
+                b"0bedfaa2f94c823ef74ef4074b50d8706041ac0e371c7c22dcf70263b8d6"
+                b"0e17a86c7c379cfda8f22469e0df9d49d59439fc99891873628fff25dda5"
+                b"fac5ac794e948babdde968143ba05f1128f34fdad5875edc4cd71c6c24ba"
+                b"2060ffbd439ce2b3"
+            ),
+            "x": int("1d93010c29ecfc432188942f46f19f44f0e1bb5d", 16),
+            "y": int(
+                "6240ea0647117c38fe705106d56db578f3e10130928452d4f3587881"
+                "b8a2bc6873a8befc3237f20914e2a91c7f07a928ee22adeed23d74ab"
+                "7f82ea11f70497e578f7a9b4cbd6f10226222b0b4da2ea1e49813d6b"
+                "b9882fbf675c0846bb80cc891857b89b0ef1beb6cce3378a9aab5d66"
+                "ad4cb9277cf447dfe1e64434749432fb",
+                16,
+            ),
+            "r": int("b5af307867fb8b54390013cc67020ddf1f2c0b81", 16),
+            "s": int("620d3b22ab5031440c3e35eab6f481298f9e9f08", 16),
+            "result": "P",
+        },
         {
-            'p': int('dc5bf3a88b2d99e4c95cdd7a0501cc38630d425cf5c390af3429cff1'
-                     'f35147b795caea923f0d3577158f8a0c89dabd1962c2c453306b5d70'
-                     'cacfb01430aceb54e5a5fa6f9340d3bd2da612fceeb76b0ec1ebfae6'
-                     '35a56ab141b108e00dc76eefe2edd0c514c21c457457c39065dba9d0'
-                     'ecb7569c247172d8438ad2827b60435b', 16),
-            'q': int('e956602b83d195dbe945b3ac702fc61f81571f1d', 16),
-            'g': int('d7eb9ca20a3c7a079606bafc4c9261ccaba303a5dc9fe9953f197dfe'
-                     '548c234895baa77f441ee6a2d97b909cbbd26ff7b869d24cae51b5c6'
-                     'edb127a4b5d75cd8b46608bfa148249dffdb59807c5d7dde3fe3080c'
-                     'a3a2d28312142becb1fa8e24003e21c7287108174b95d5bc711e1c8d'
-                     '9b1076784f5dc37a964a5e51390da713', 16),
-            'digest_algorithm': 'SHA-1',
-            'msg': binascii.unhexlify(
-                b'97d50898025d2f9ba633866e968ca75e969d394edba6517204cb3dd537c2'
-                b'ba38778a2dc9dbc685a915e5676fcd43bc3726bc59ce3d7a9fae35565082'
-                b'a069c139fa37c90d922b126933db3fa6c5ef6b1edf00d174a51887bb7690'
-                b'9c6a94fe994ecc7b7fc8f26113b17f30f9d01693df99a125b4f17e184331'
-                b'c6b6e8ca00f54f3a'),
-            'x': int('350e13534692a7e0c4b7d58836046c436fbb2322', 16),
-            'y': int('69974de550fe6bd3099150faea1623ad3fb6d9bf23a07215093f3197'
-                     '25ad0877accffd291b6da18eb0cbe51676ceb0977504eb97c27c0b19'
-                     '1883f72fb2710a9fbd8bcf13be0bf854410b32f42b33ec89d3cc1cf8'
-                     '92bcd536c4195ca9ada302ad600c3408739935d77dc247529ca47f84'
-                     '4cc86f5016a2fe962c6e20ca7c4d4e8f', 16),
-            'r': int('b5d05faa7005764e8dae0327c5bf1972ff7681b9', 16),
-            's': int('18ea15bd9f00475b25204cbc23f8c23e01588015', 16),
-            'result': 'F'},
+            "p": int(
+                "dc5bf3a88b2d99e4c95cdd7a0501cc38630d425cf5c390af3429cff1"
+                "f35147b795caea923f0d3577158f8a0c89dabd1962c2c453306b5d70"
+                "cacfb01430aceb54e5a5fa6f9340d3bd2da612fceeb76b0ec1ebfae6"
+                "35a56ab141b108e00dc76eefe2edd0c514c21c457457c39065dba9d0"
+                "ecb7569c247172d8438ad2827b60435b",
+                16,
+            ),
+            "q": int("e956602b83d195dbe945b3ac702fc61f81571f1d", 16),
+            "g": int(
+                "d7eb9ca20a3c7a079606bafc4c9261ccaba303a5dc9fe9953f197dfe"
+                "548c234895baa77f441ee6a2d97b909cbbd26ff7b869d24cae51b5c6"
+                "edb127a4b5d75cd8b46608bfa148249dffdb59807c5d7dde3fe3080c"
+                "a3a2d28312142becb1fa8e24003e21c7287108174b95d5bc711e1c8d"
+                "9b1076784f5dc37a964a5e51390da713",
+                16,
+            ),
+            "digest_algorithm": "SHA-1",
+            "msg": binascii.unhexlify(
+                b"97d50898025d2f9ba633866e968ca75e969d394edba6517204cb3dd537c2"
+                b"ba38778a2dc9dbc685a915e5676fcd43bc3726bc59ce3d7a9fae35565082"
+                b"a069c139fa37c90d922b126933db3fa6c5ef6b1edf00d174a51887bb7690"
+                b"9c6a94fe994ecc7b7fc8f26113b17f30f9d01693df99a125b4f17e184331"
+                b"c6b6e8ca00f54f3a"
+            ),
+            "x": int("350e13534692a7e0c4b7d58836046c436fbb2322", 16),
+            "y": int(
+                "69974de550fe6bd3099150faea1623ad3fb6d9bf23a07215093f3197"
+                "25ad0877accffd291b6da18eb0cbe51676ceb0977504eb97c27c0b19"
+                "1883f72fb2710a9fbd8bcf13be0bf854410b32f42b33ec89d3cc1cf8"
+                "92bcd536c4195ca9ada302ad600c3408739935d77dc247529ca47f84"
+                "4cc86f5016a2fe962c6e20ca7c4d4e8f",
+                16,
+            ),
+            "r": int("b5d05faa7005764e8dae0327c5bf1972ff7681b9", 16),
+            "s": int("18ea15bd9f00475b25204cbc23f8c23e01588015", 16),
+            "result": "F",
+        },
         {
-            'p': int('e7c1c86125db9ef417da1ced7ea0861bdad629216a3f3c745df42a4'
-                     '6b989e59f4d98425ee3c932fa3c2b6f637bdb6545bec526faa037e1'
-                     '1f5578a4363b9fca5eba60d6a9cbaa2befd04141d989c7356285132'
-                     'c2eaf74f2d868521cdc0a17ae9a2546ef863027d3f8cc7949631fd0'
-                     'e2971417a912c8b8c5c989730db6ea6e8baee0e667850429038093c'
-                     '851ccb6fb173bb081e0efe0bd7450e0946888f89f75e443ab93ef2d'
-                     'a293a01622cf43c6dd79625d41ba8f9ef7e3086ab39134283d8e96c'
-                     '89249488120fd061e4a87d34af41069c0b4fd3934c31b589cbe85b6'
-                     '8b912718d5dab859fda7082511fad1d152044905005546e19b14aa9'
-                     '6585a55269bf2b831', 16),
-            'q': int('8e056ec9d4b7acb580087a6ed9ba3478711bb025d5b8d9c731ef9b3'
-                     '8bd43db2f', 16),
-            'g': int('dc2bfb9776786ad310c8b0cdcbba3062402613c67e6959a8d8d1b05'
-                     'aab636528b7b1fe9cd33765f853d6dbe13d09f2681f8c7b1ed7886a'
-                     'aed70c7bd76dbe858ffb8bd86235ddf759244678f428c6519af593d'
-                     'c94eeadbd9852ba2b3d61664e8d58c29d2039af3c3d6d16f90988f6'
-                     'a8c824569f3d48050e30896a9e17cd0232ef01ab8790008f6973b84'
-                     'c763a72f4ae8b485abfb7e8efeb86808fa2b281d3e5d65d28f5992a'
-                     '34c077c5aa8026cb2fbc34a45f7e9bd216b10e6f12ecb172e9a6eb8'
-                     'f2e91316905b6add1fd22e83bc2f089f1d5e6a6e6707c18ff55ddcb'
-                     '7954e8bceaf0efc4e8314910c03b0e51175f344faafee476a373ac9'
-                     '5743cec712b72cf2e', 16),
-            'digest_algorithm': 'SHA-384',
-            'msg': binascii.unhexlify(
-                b'6cd6ccfd66bcd832189c5f0c77994210e3bf2c43416f0fe77c4e92f31c5'
-                b'369538dc2c003f146c5ac79df43194ccf3c44d470d9f1083bd15b99b5bc'
-                b'f88c32d8a9021f09ea2288d7b3bf345a12aef3949c1e121b9fb371a67c2'
-                b'd1377364206ac839dd78483561426bda0303f285aa12e9c45d3cdfc6bea'
-                b'e3549703b187deeb3296'),
-            'x': int('56c897b5938ad5b3d437d7e4826da586a6b3be15e893fa1aaa946f2'
-                     '0a028b6b3', 16),
-            'y': int('38ad44489e1a5778b9689f4dcf40e2acf23840fb954e987d6e8cb62'
-                     '9106328ac64e1f3c3eba48b21176ad4afe3b733bead382ee1597e1b'
-                     '83e4b43424f2daaba04e5bd79e1436693ac2bddb79a298f026e57e2'
-                     '00a252efd1e848a4a2e90be6e78f5242b468b9c0c6d2615047a5a40'
-                     'b9ae7e57a519114db55bf3bed65e580f894b094630ca9c217f6accd'
-                     '091e72d2f22da620044ff372d7273f9445017fad492959e59600b74'
-                     '94dbe766a03e40125d4e6747c76f68a5b0cdc0e7d7cee12d08c6fb7'
-                     'd0fb049e420a33405075ed4463296345ca695fb7feab7c1b5333ae5'
-                     '19fcd4bb6a043f4555378969114743d4face96cad31c0e0089da4e3'
-                     'f61b6d7dabc088ab7', 16),
-            'r': int('3b85b17be240ed658beb3652c9d93e8e9eea160d35ee24596143058'
-                     '02963374e', 16),
-            's': int('726800a5174a53b56dce86064109c0273cd11fcfa3c92c5cd6aa910'
-                     '260c0e3c7', 16),
-            'result': 'F'},
+            "p": int(
+                "e7c1c86125db9ef417da1ced7ea0861bdad629216a3f3c745df42a4"
+                "6b989e59f4d98425ee3c932fa3c2b6f637bdb6545bec526faa037e1"
+                "1f5578a4363b9fca5eba60d6a9cbaa2befd04141d989c7356285132"
+                "c2eaf74f2d868521cdc0a17ae9a2546ef863027d3f8cc7949631fd0"
+                "e2971417a912c8b8c5c989730db6ea6e8baee0e667850429038093c"
+                "851ccb6fb173bb081e0efe0bd7450e0946888f89f75e443ab93ef2d"
+                "a293a01622cf43c6dd79625d41ba8f9ef7e3086ab39134283d8e96c"
+                "89249488120fd061e4a87d34af41069c0b4fd3934c31b589cbe85b6"
+                "8b912718d5dab859fda7082511fad1d152044905005546e19b14aa9"
+                "6585a55269bf2b831",
+                16,
+            ),
+            "q": int(
+                "8e056ec9d4b7acb580087a6ed9ba3478711bb025d5b8d9c731ef9b3"
+                "8bd43db2f",
+                16,
+            ),
+            "g": int(
+                "dc2bfb9776786ad310c8b0cdcbba3062402613c67e6959a8d8d1b05"
+                "aab636528b7b1fe9cd33765f853d6dbe13d09f2681f8c7b1ed7886a"
+                "aed70c7bd76dbe858ffb8bd86235ddf759244678f428c6519af593d"
+                "c94eeadbd9852ba2b3d61664e8d58c29d2039af3c3d6d16f90988f6"
+                "a8c824569f3d48050e30896a9e17cd0232ef01ab8790008f6973b84"
+                "c763a72f4ae8b485abfb7e8efeb86808fa2b281d3e5d65d28f5992a"
+                "34c077c5aa8026cb2fbc34a45f7e9bd216b10e6f12ecb172e9a6eb8"
+                "f2e91316905b6add1fd22e83bc2f089f1d5e6a6e6707c18ff55ddcb"
+                "7954e8bceaf0efc4e8314910c03b0e51175f344faafee476a373ac9"
+                "5743cec712b72cf2e",
+                16,
+            ),
+            "digest_algorithm": "SHA-384",
+            "msg": binascii.unhexlify(
+                b"6cd6ccfd66bcd832189c5f0c77994210e3bf2c43416f0fe77c4e92f31c5"
+                b"369538dc2c003f146c5ac79df43194ccf3c44d470d9f1083bd15b99b5bc"
+                b"f88c32d8a9021f09ea2288d7b3bf345a12aef3949c1e121b9fb371a67c2"
+                b"d1377364206ac839dd78483561426bda0303f285aa12e9c45d3cdfc6bea"
+                b"e3549703b187deeb3296"
+            ),
+            "x": int(
+                "56c897b5938ad5b3d437d7e4826da586a6b3be15e893fa1aaa946f2"
+                "0a028b6b3",
+                16,
+            ),
+            "y": int(
+                "38ad44489e1a5778b9689f4dcf40e2acf23840fb954e987d6e8cb62"
+                "9106328ac64e1f3c3eba48b21176ad4afe3b733bead382ee1597e1b"
+                "83e4b43424f2daaba04e5bd79e1436693ac2bddb79a298f026e57e2"
+                "00a252efd1e848a4a2e90be6e78f5242b468b9c0c6d2615047a5a40"
+                "b9ae7e57a519114db55bf3bed65e580f894b094630ca9c217f6accd"
+                "091e72d2f22da620044ff372d7273f9445017fad492959e59600b74"
+                "94dbe766a03e40125d4e6747c76f68a5b0cdc0e7d7cee12d08c6fb7"
+                "d0fb049e420a33405075ed4463296345ca695fb7feab7c1b5333ae5"
+                "19fcd4bb6a043f4555378969114743d4face96cad31c0e0089da4e3"
+                "f61b6d7dabc088ab7",
+                16,
+            ),
+            "r": int(
+                "3b85b17be240ed658beb3652c9d93e8e9eea160d35ee24596143058"
+                "02963374e",
+                16,
+            ),
+            "s": int(
+                "726800a5174a53b56dce86064109c0273cd11fcfa3c92c5cd6aa910"
+                "260c0e3c7",
+                16,
+            ),
+            "result": "F",
+        },
         {
-            'p': int('e7c1c86125db9ef417da1ced7ea0861bdad629216a3f3c745df42a4'
-                     '6b989e59f4d98425ee3c932fa3c2b6f637bdb6545bec526faa037e1'
-                     '1f5578a4363b9fca5eba60d6a9cbaa2befd04141d989c7356285132'
-                     'c2eaf74f2d868521cdc0a17ae9a2546ef863027d3f8cc7949631fd0'
-                     'e2971417a912c8b8c5c989730db6ea6e8baee0e667850429038093c'
-                     '851ccb6fb173bb081e0efe0bd7450e0946888f89f75e443ab93ef2d'
-                     'a293a01622cf43c6dd79625d41ba8f9ef7e3086ab39134283d8e96c'
-                     '89249488120fd061e4a87d34af41069c0b4fd3934c31b589cbe85b6'
-                     '8b912718d5dab859fda7082511fad1d152044905005546e19b14aa9'
-                     '6585a55269bf2b831', 16),
-            'q': int('8e056ec9d4b7acb580087a6ed9ba3478711bb025d5b8d9c731ef9b3'
-                     '8bd43db2f', 16),
-            'g': int('dc2bfb9776786ad310c8b0cdcbba3062402613c67e6959a8d8d1b05'
-                     'aab636528b7b1fe9cd33765f853d6dbe13d09f2681f8c7b1ed7886a'
-                     'aed70c7bd76dbe858ffb8bd86235ddf759244678f428c6519af593d'
-                     'c94eeadbd9852ba2b3d61664e8d58c29d2039af3c3d6d16f90988f6'
-                     'a8c824569f3d48050e30896a9e17cd0232ef01ab8790008f6973b84'
-                     'c763a72f4ae8b485abfb7e8efeb86808fa2b281d3e5d65d28f5992a'
-                     '34c077c5aa8026cb2fbc34a45f7e9bd216b10e6f12ecb172e9a6eb8'
-                     'f2e91316905b6add1fd22e83bc2f089f1d5e6a6e6707c18ff55ddcb'
-                     '7954e8bceaf0efc4e8314910c03b0e51175f344faafee476a373ac9'
-                     '5743cec712b72cf2e', 16),
-            'digest_algorithm': 'SHA-384',
-            'msg': binascii.unhexlify(
-                b'3ad6b0884f358dea09c31a9abc40c45a6000611fc2b907b30eac00413fd'
-                b'2819de7015488a411609d46c499b8f7afa1b78b352ac7f8535bd805b8ff'
-                b'2a5eae557098c668f7ccd73af886d6823a6d456c29931ee864ed46d7673'
-                b'82785728c2a83fcff5271007d2a67d06fa205fd7b9d1a42ea5d6dc76e5e'
-                b'18a9eb148cd1e8b262ae'),
-            'x': int('2faf566a9f057960f1b50c69508f483d9966d6e35743591f3a677a9'
-                     'dc40e1555', 16),
-            'y': int('926425d617babe87c442b03903e32ba5bbf0cd9d602b59c4df791a4d'
-                     '64a6d4333ca0c0d370552539197d327dcd1bbf8c454f24b03fc7805f'
-                     '862db34c7b066ddfddbb11dbd010b27123062d028fe041cb56a2e774'
-                     '88348ae0ab6705d87aac4d4e9e6600e9e706326d9979982cffa839be'
-                     'b9eacc3963bcca455a507e80c1c37ad4e765b2c9c0477a075e9bc584'
-                     'feacdf3a35a9391d4711f14e197c54022282bfed9a191213d64127f1'
-                     '7a9c5affec26e0c71f15d3a5b16098fec118c45bf8bb2f3b1560df09'
-                     '49254c1c0aeb0a16d5a95a40fab8521fbe8ea77c51169b587cc3360e'
-                     '5733e6a23b9fded8c40724ea1f9e93614b3a6c9b4f8dbbe915b79449'
-                     '7227ba62', 16),
-            'r': int('343ea0a9e66277380f604d5880fca686bffab69ca97bfba015a102a'
-                     '7e23dce0e', 16),
-            's': int('6258488c770e0f5ad7b9da8bade5023fc0d17c6ec517bd08d53e6dc'
-                     '01ac5c2b3', 16),
-            'result': 'P'}
+            "p": int(
+                "e7c1c86125db9ef417da1ced7ea0861bdad629216a3f3c745df42a4"
+                "6b989e59f4d98425ee3c932fa3c2b6f637bdb6545bec526faa037e1"
+                "1f5578a4363b9fca5eba60d6a9cbaa2befd04141d989c7356285132"
+                "c2eaf74f2d868521cdc0a17ae9a2546ef863027d3f8cc7949631fd0"
+                "e2971417a912c8b8c5c989730db6ea6e8baee0e667850429038093c"
+                "851ccb6fb173bb081e0efe0bd7450e0946888f89f75e443ab93ef2d"
+                "a293a01622cf43c6dd79625d41ba8f9ef7e3086ab39134283d8e96c"
+                "89249488120fd061e4a87d34af41069c0b4fd3934c31b589cbe85b6"
+                "8b912718d5dab859fda7082511fad1d152044905005546e19b14aa9"
+                "6585a55269bf2b831",
+                16,
+            ),
+            "q": int(
+                "8e056ec9d4b7acb580087a6ed9ba3478711bb025d5b8d9c731ef9b3"
+                "8bd43db2f",
+                16,
+            ),
+            "g": int(
+                "dc2bfb9776786ad310c8b0cdcbba3062402613c67e6959a8d8d1b05"
+                "aab636528b7b1fe9cd33765f853d6dbe13d09f2681f8c7b1ed7886a"
+                "aed70c7bd76dbe858ffb8bd86235ddf759244678f428c6519af593d"
+                "c94eeadbd9852ba2b3d61664e8d58c29d2039af3c3d6d16f90988f6"
+                "a8c824569f3d48050e30896a9e17cd0232ef01ab8790008f6973b84"
+                "c763a72f4ae8b485abfb7e8efeb86808fa2b281d3e5d65d28f5992a"
+                "34c077c5aa8026cb2fbc34a45f7e9bd216b10e6f12ecb172e9a6eb8"
+                "f2e91316905b6add1fd22e83bc2f089f1d5e6a6e6707c18ff55ddcb"
+                "7954e8bceaf0efc4e8314910c03b0e51175f344faafee476a373ac9"
+                "5743cec712b72cf2e",
+                16,
+            ),
+            "digest_algorithm": "SHA-384",
+            "msg": binascii.unhexlify(
+                b"3ad6b0884f358dea09c31a9abc40c45a6000611fc2b907b30eac00413fd"
+                b"2819de7015488a411609d46c499b8f7afa1b78b352ac7f8535bd805b8ff"
+                b"2a5eae557098c668f7ccd73af886d6823a6d456c29931ee864ed46d7673"
+                b"82785728c2a83fcff5271007d2a67d06fa205fd7b9d1a42ea5d6dc76e5e"
+                b"18a9eb148cd1e8b262ae"
+            ),
+            "x": int(
+                "2faf566a9f057960f1b50c69508f483d9966d6e35743591f3a677a9"
+                "dc40e1555",
+                16,
+            ),
+            "y": int(
+                "926425d617babe87c442b03903e32ba5bbf0cd9d602b59c4df791a4d"
+                "64a6d4333ca0c0d370552539197d327dcd1bbf8c454f24b03fc7805f"
+                "862db34c7b066ddfddbb11dbd010b27123062d028fe041cb56a2e774"
+                "88348ae0ab6705d87aac4d4e9e6600e9e706326d9979982cffa839be"
+                "b9eacc3963bcca455a507e80c1c37ad4e765b2c9c0477a075e9bc584"
+                "feacdf3a35a9391d4711f14e197c54022282bfed9a191213d64127f1"
+                "7a9c5affec26e0c71f15d3a5b16098fec118c45bf8bb2f3b1560df09"
+                "49254c1c0aeb0a16d5a95a40fab8521fbe8ea77c51169b587cc3360e"
+                "5733e6a23b9fded8c40724ea1f9e93614b3a6c9b4f8dbbe915b79449"
+                "7227ba62",
+                16,
+            ),
+            "r": int(
+                "343ea0a9e66277380f604d5880fca686bffab69ca97bfba015a102a"
+                "7e23dce0e",
+                16,
+            ),
+            "s": int(
+                "6258488c770e0f5ad7b9da8bade5023fc0d17c6ec517bd08d53e6dc"
+                "01ac5c2b3",
+                16,
+            ),
+            "result": "P",
+        },
     ]
 
     assert expected == load_fips_dsa_sig_vectors(vector_data)
 
 
 def test_load_fips_dsa_sig_gen_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     # CAVS 11.2
     # "SigGen" information for "dsa2_values"
     # Mod sizes selected: SHA-1 L=1024, N=160, SHA-256 L=2048, N=256
@@ -2145,155 +2437,219 @@
 60bc1dc46f78ceaaa2c02f5375dd82e708744aa40b15799eb81d7e5b1a
     R = bcd490568c0a89ba311bef88ea4f4b03d273e793722722327095a378dd6f3522
     S = 74498fc43091fcdd2d1ef0775f8286945a01cd72b805256b0451f9cbd943cf82
-    """).splitlines()
+    """
+    ).splitlines()
 
     expected = [
         {
-            'p': int('a8f9cd201e5e35d892f85f80e4db2599a5676a3b1d4f190330ed325'
-                     '6b26d0e80a0e49a8fffaaad2a24f472d2573241d4d6d6c7480c80b4'
-                     'c67bb4479c15ada7ea8424d2502fa01472e760241713dab025ae1b0'
-                     '2e1703a1435f62ddf4ee4c1b664066eb22f2e3bf28bb70a2a76e4fd'
-                     '5ebe2d1229681b5b06439ac9c7e9d8bde283', 16),
-            'q': int('f85f0f83ac4df7ea0cdf8f469bfeeaea14156495', 16),
-            'g': int('2b3152ff6c62f14622b8f48e59f8af46883b38e79b8c74deeae9df1'
-                     '31f8b856e3ad6c8455dab87cc0da8ac973417ce4f7878557d6cdf40'
-                     'b35b4a0ca3eb310c6a95d68ce284ad4e25ea28591611ee08b8444bd'
-                     '64b25f3f7c572410ddfb39cc728b9c936f85f419129869929cdb909'
-                     'a6a3a99bbe089216368171bd0ba81de4fe33', 16),
-            'digest_algorithm': 'SHA-1',
-            'msg': binascii.unhexlify(
-                b'3b46736d559bd4e0c2c1b2553a33ad3c6cf23cac998d3d0c0e8fa4b19bc'
-                b'a06f2f386db2dcff9dca4f40ad8f561ffc308b46c5f31a7735b5fa7e0f9'
-                b'e6cb512e63d7eea05538d66a75cd0d4234b5ccf6c1715ccaaf9cdc0a222'
-                b'8135f716ee9bdee7fc13ec27a03a6d11c5c5b3685f51900b1337153bc6c'
-                b'4e8f52920c33fa37f4e7'),
-            'y': int('313fd9ebca91574e1c2eebe1517c57e0c21b0209872140c5328761b'
-                     'bb2450b33f1b18b409ce9ab7c4cd8fda3391e8e34868357c199e16a'
-                     '6b2eba06d6749def791d79e95d3a4d09b24c392ad89dbf100995ae1'
-                     '9c01062056bb14bce005e8731efde175f95b975089bdcdaea562b32'
-                     '786d96f5a31aedf75364008ad4fffebb970b', 16),
-            'r': int('50ed0e810e3f1c7cb6ac62332058448bd8b284c0', 16),
-            's': int('c6aded17216b46b7e4b6f2a97c1ad7cc3da83fde', 16)},
+            "p": int(
+                "a8f9cd201e5e35d892f85f80e4db2599a5676a3b1d4f190330ed325"
+                "6b26d0e80a0e49a8fffaaad2a24f472d2573241d4d6d6c7480c80b4"
+                "c67bb4479c15ada7ea8424d2502fa01472e760241713dab025ae1b0"
+                "2e1703a1435f62ddf4ee4c1b664066eb22f2e3bf28bb70a2a76e4fd"
+                "5ebe2d1229681b5b06439ac9c7e9d8bde283",
+                16,
+            ),
+            "q": int("f85f0f83ac4df7ea0cdf8f469bfeeaea14156495", 16),
+            "g": int(
+                "2b3152ff6c62f14622b8f48e59f8af46883b38e79b8c74deeae9df1"
+                "31f8b856e3ad6c8455dab87cc0da8ac973417ce4f7878557d6cdf40"
+                "b35b4a0ca3eb310c6a95d68ce284ad4e25ea28591611ee08b8444bd"
+                "64b25f3f7c572410ddfb39cc728b9c936f85f419129869929cdb909"
+                "a6a3a99bbe089216368171bd0ba81de4fe33",
+                16,
+            ),
+            "digest_algorithm": "SHA-1",
+            "msg": binascii.unhexlify(
+                b"3b46736d559bd4e0c2c1b2553a33ad3c6cf23cac998d3d0c0e8fa4b19bc"
+                b"a06f2f386db2dcff9dca4f40ad8f561ffc308b46c5f31a7735b5fa7e0f9"
+                b"e6cb512e63d7eea05538d66a75cd0d4234b5ccf6c1715ccaaf9cdc0a222"
+                b"8135f716ee9bdee7fc13ec27a03a6d11c5c5b3685f51900b1337153bc6c"
+                b"4e8f52920c33fa37f4e7"
+            ),
+            "y": int(
+                "313fd9ebca91574e1c2eebe1517c57e0c21b0209872140c5328761b"
+                "bb2450b33f1b18b409ce9ab7c4cd8fda3391e8e34868357c199e16a"
+                "6b2eba06d6749def791d79e95d3a4d09b24c392ad89dbf100995ae1"
+                "9c01062056bb14bce005e8731efde175f95b975089bdcdaea562b32"
+                "786d96f5a31aedf75364008ad4fffebb970b",
+                16,
+            ),
+            "r": int("50ed0e810e3f1c7cb6ac62332058448bd8b284c0", 16),
+            "s": int("c6aded17216b46b7e4b6f2a97c1ad7cc3da83fde", 16),
+        },
         {
-            'p': int('a8f9cd201e5e35d892f85f80e4db2599a5676a3b1d4f190330ed325'
-                     '6b26d0e80a0e49a8fffaaad2a24f472d2573241d4d6d6c7480c80b4'
-                     'c67bb4479c15ada7ea8424d2502fa01472e760241713dab025ae1b0'
-                     '2e1703a1435f62ddf4ee4c1b664066eb22f2e3bf28bb70a2a76e4fd'
-                     '5ebe2d1229681b5b06439ac9c7e9d8bde283', 16),
-            'q': int('f85f0f83ac4df7ea0cdf8f469bfeeaea14156495', 16),
-            'g': int('2b3152ff6c62f14622b8f48e59f8af46883b38e79b8c74deeae9df1'
-                     '31f8b856e3ad6c8455dab87cc0da8ac973417ce4f7878557d6cdf40'
-                     'b35b4a0ca3eb310c6a95d68ce284ad4e25ea28591611ee08b8444bd'
-                     '64b25f3f7c572410ddfb39cc728b9c936f85f419129869929cdb909'
-                     'a6a3a99bbe089216368171bd0ba81de4fe33', 16),
-            'digest_algorithm': 'SHA-1',
-            'msg': binascii.unhexlify(
-                b'd2bcb53b044b3e2e4b61ba2f91c0995fb83a6a97525e66441a3b489d959'
-                b'4238bc740bdeea0f718a769c977e2de003877b5d7dc25b182ae533db33e'
-                b'78f2c3ff0645f2137abc137d4e7d93ccf24f60b18a820bc07c7b4b5fe08'
-                b'b4f9e7d21b256c18f3b9d49acc4f93e2ce6f3754c7807757d2e11760426'
-                b'12cb32fc3f4f70700e25'),
-            'y': int('29bdd759aaa62d4bf16b4861c81cf42eac2e1637b9ecba512bdbc13'
-                     'ac12a80ae8de2526b899ae5e4a231aef884197c944c732693a634d7'
-                     '659abc6975a773f8d3cd5a361fe2492386a3c09aaef12e4a7e73ad7'
-                     'dfc3637f7b093f2c40d6223a195c136adf2ea3fbf8704a675aa7817'
-                     'aa7ec7f9adfb2854d4e05c3ce7f76560313b', 16),
-            'r': int('a26c00b5750a2d27fe7435b93476b35438b4d8ab', 16),
-            's': int('61c9bfcb2938755afa7dad1d1e07c6288617bf70', 16)},
+            "p": int(
+                "a8f9cd201e5e35d892f85f80e4db2599a5676a3b1d4f190330ed325"
+                "6b26d0e80a0e49a8fffaaad2a24f472d2573241d4d6d6c7480c80b4"
+                "c67bb4479c15ada7ea8424d2502fa01472e760241713dab025ae1b0"
+                "2e1703a1435f62ddf4ee4c1b664066eb22f2e3bf28bb70a2a76e4fd"
+                "5ebe2d1229681b5b06439ac9c7e9d8bde283",
+                16,
+            ),
+            "q": int("f85f0f83ac4df7ea0cdf8f469bfeeaea14156495", 16),
+            "g": int(
+                "2b3152ff6c62f14622b8f48e59f8af46883b38e79b8c74deeae9df1"
+                "31f8b856e3ad6c8455dab87cc0da8ac973417ce4f7878557d6cdf40"
+                "b35b4a0ca3eb310c6a95d68ce284ad4e25ea28591611ee08b8444bd"
+                "64b25f3f7c572410ddfb39cc728b9c936f85f419129869929cdb909"
+                "a6a3a99bbe089216368171bd0ba81de4fe33",
+                16,
+            ),
+            "digest_algorithm": "SHA-1",
+            "msg": binascii.unhexlify(
+                b"d2bcb53b044b3e2e4b61ba2f91c0995fb83a6a97525e66441a3b489d959"
+                b"4238bc740bdeea0f718a769c977e2de003877b5d7dc25b182ae533db33e"
+                b"78f2c3ff0645f2137abc137d4e7d93ccf24f60b18a820bc07c7b4b5fe08"
+                b"b4f9e7d21b256c18f3b9d49acc4f93e2ce6f3754c7807757d2e11760426"
+                b"12cb32fc3f4f70700e25"
+            ),
+            "y": int(
+                "29bdd759aaa62d4bf16b4861c81cf42eac2e1637b9ecba512bdbc13"
+                "ac12a80ae8de2526b899ae5e4a231aef884197c944c732693a634d7"
+                "659abc6975a773f8d3cd5a361fe2492386a3c09aaef12e4a7e73ad7"
+                "dfc3637f7b093f2c40d6223a195c136adf2ea3fbf8704a675aa7817"
+                "aa7ec7f9adfb2854d4e05c3ce7f76560313b",
+                16,
+            ),
+            "r": int("a26c00b5750a2d27fe7435b93476b35438b4d8ab", 16),
+            "s": int("61c9bfcb2938755afa7dad1d1e07c6288617bf70", 16),
+        },
         {
-            'p': int('a8adb6c0b4cf9588012e5deff1a871d383e0e2a85b5e8e03d814fe1'
-                     '3a059705e663230a377bf7323a8fa117100200bfd5adf857393b0bb'
-                     'd67906c081e585410e38480ead51684dac3a38f7b64c9eb109f1973'
-                     '9a4517cd7d5d6291e8af20a3fbf17336c7bf80ee718ee087e322ee4'
-                     '1047dabefbcc34d10b66b644ddb3160a28c0639563d71993a26543e'
-                     'adb7718f317bf5d9577a6156561b082a10029cd44012b18de684450'
-                     '9fe058ba87980792285f2750969fe89c2cd6498db3545638d5379d1'
-                     '25dccf64e06c1af33a6190841d223da1513333a7c9d78462abaab31'
-                     'b9f96d5f34445ceb6309f2f6d2c8dde06441e87980d303ef9a1ff00'
-                     '7e8be2f0be06cc15f', 16),
-            'q': int('e71f8567447f42e75f5ef85ca20fe557ab0343d37ed09edc3f6e686'
-                     '04d6b9dfb', 16),
-            'g': int('5ba24de9607b8998e66ce6c4f812a314c6935842f7ab54cd82b19fa'
-                     '104abfb5d84579a623b2574b37d22ccae9b3e415e48f5c0f9bcbdff'
-                     '8071d63b9bb956e547af3a8df99e5d3061979652ff96b765cb3ee49'
-                     '3643544c75dbe5bb39834531952a0fb4b0378b3fcbb4c8b5800a533'
-                     '0392a2a04e700bb6ed7e0b85795ea38b1b962741b3f33b9dde2f4ec'
-                     '1354f09e2eb78e95f037a5804b6171659f88715ce1a9b0cc90c27f3'
-                     '5ef2f10ff0c7c7a2bb0154d9b8ebe76a3d764aa879af372f4240de8'
-                     '347937e5a90cec9f41ff2f26b8da9a94a225d1a913717d73f10397d'
-                     '2183f1ba3b7b45a68f1ff1893caf69a827802f7b6a48d51da6fbefb'
-                     '64fd9a6c5b75c4561', 16),
-            'digest_algorithm': 'SHA-256',
-            'msg': binascii.unhexlify(
-                b'4e3a28bcf90d1d2e75f075d9fbe55b36c5529b17bc3a9ccaba6935c9e20'
-                b'548255b3dfae0f91db030c12f2c344b3a29c4151c5b209f5e319fdf1c23'
-                b'b190f64f1fe5b330cb7c8fa952f9d90f13aff1cb11d63181da9efc6f7e1'
-                b'5bfed4862d1a62c7dcf3ba8bf1ff304b102b1ec3f1497dddf09712cf323'
-                b'f5610a9d10c3d9132659'),
-            'y': int('5a55dceddd1134ee5f11ed85deb4d634a3643f5f36dc3a706892564'
-                     '69a0b651ad22880f14ab85719434f9c0e407e60ea420e2a0cd29422'
-                     'c4899c416359dbb1e592456f2b3cce233259c117542fd05f31ea25b'
-                     '015d9121c890b90e0bad033be1368d229985aac7226d1c8c2eab325'
-                     'ef3b2cd59d3b9f7de7dbc94af1a9339eb430ca36c26c46ecfa6c548'
-                     '1711496f624e188ad7540ef5df26f8efacb820bd17a1f618acb50c9'
-                     'bc197d4cb7ccac45d824a3bf795c234b556b06aeb92917345325208'
-                     '4003f69fe98045fe74002ba658f93475622f76791d9b2623d1b5fff'
-                     '2cc16844746efd2d30a6a8134bfc4c8cc80a46107901fb973c28fc5'
-                     '53130f3286c1489da', 16),
-            'r': int('633055e055f237c38999d81c397848c38cce80a55b649d9e7905c29'
-                     '8e2a51447', 16),
-            's': int('2bbf68317660ec1e4b154915027b0bc00ee19cfc0bf75d01930504f'
-                     '2ce10a8b0', 16)},
+            "p": int(
+                "a8adb6c0b4cf9588012e5deff1a871d383e0e2a85b5e8e03d814fe1"
+                "3a059705e663230a377bf7323a8fa117100200bfd5adf857393b0bb"
+                "d67906c081e585410e38480ead51684dac3a38f7b64c9eb109f1973"
+                "9a4517cd7d5d6291e8af20a3fbf17336c7bf80ee718ee087e322ee4"
+                "1047dabefbcc34d10b66b644ddb3160a28c0639563d71993a26543e"
+                "adb7718f317bf5d9577a6156561b082a10029cd44012b18de684450"
+                "9fe058ba87980792285f2750969fe89c2cd6498db3545638d5379d1"
+                "25dccf64e06c1af33a6190841d223da1513333a7c9d78462abaab31"
+                "b9f96d5f34445ceb6309f2f6d2c8dde06441e87980d303ef9a1ff00"
+                "7e8be2f0be06cc15f",
+                16,
+            ),
+            "q": int(
+                "e71f8567447f42e75f5ef85ca20fe557ab0343d37ed09edc3f6e686"
+                "04d6b9dfb",
+                16,
+            ),
+            "g": int(
+                "5ba24de9607b8998e66ce6c4f812a314c6935842f7ab54cd82b19fa"
+                "104abfb5d84579a623b2574b37d22ccae9b3e415e48f5c0f9bcbdff"
+                "8071d63b9bb956e547af3a8df99e5d3061979652ff96b765cb3ee49"
+                "3643544c75dbe5bb39834531952a0fb4b0378b3fcbb4c8b5800a533"
+                "0392a2a04e700bb6ed7e0b85795ea38b1b962741b3f33b9dde2f4ec"
+                "1354f09e2eb78e95f037a5804b6171659f88715ce1a9b0cc90c27f3"
+                "5ef2f10ff0c7c7a2bb0154d9b8ebe76a3d764aa879af372f4240de8"
+                "347937e5a90cec9f41ff2f26b8da9a94a225d1a913717d73f10397d"
+                "2183f1ba3b7b45a68f1ff1893caf69a827802f7b6a48d51da6fbefb"
+                "64fd9a6c5b75c4561",
+                16,
+            ),
+            "digest_algorithm": "SHA-256",
+            "msg": binascii.unhexlify(
+                b"4e3a28bcf90d1d2e75f075d9fbe55b36c5529b17bc3a9ccaba6935c9e20"
+                b"548255b3dfae0f91db030c12f2c344b3a29c4151c5b209f5e319fdf1c23"
+                b"b190f64f1fe5b330cb7c8fa952f9d90f13aff1cb11d63181da9efc6f7e1"
+                b"5bfed4862d1a62c7dcf3ba8bf1ff304b102b1ec3f1497dddf09712cf323"
+                b"f5610a9d10c3d9132659"
+            ),
+            "y": int(
+                "5a55dceddd1134ee5f11ed85deb4d634a3643f5f36dc3a706892564"
+                "69a0b651ad22880f14ab85719434f9c0e407e60ea420e2a0cd29422"
+                "c4899c416359dbb1e592456f2b3cce233259c117542fd05f31ea25b"
+                "015d9121c890b90e0bad033be1368d229985aac7226d1c8c2eab325"
+                "ef3b2cd59d3b9f7de7dbc94af1a9339eb430ca36c26c46ecfa6c548"
+                "1711496f624e188ad7540ef5df26f8efacb820bd17a1f618acb50c9"
+                "bc197d4cb7ccac45d824a3bf795c234b556b06aeb92917345325208"
+                "4003f69fe98045fe74002ba658f93475622f76791d9b2623d1b5fff"
+                "2cc16844746efd2d30a6a8134bfc4c8cc80a46107901fb973c28fc5"
+                "53130f3286c1489da",
+                16,
+            ),
+            "r": int(
+                "633055e055f237c38999d81c397848c38cce80a55b649d9e7905c29"
+                "8e2a51447",
+                16,
+            ),
+            "s": int(
+                "2bbf68317660ec1e4b154915027b0bc00ee19cfc0bf75d01930504f"
+                "2ce10a8b0",
+                16,
+            ),
+        },
         {
-            'p': int('a8adb6c0b4cf9588012e5deff1a871d383e0e2a85b5e8e03d814fe1'
-                     '3a059705e663230a377bf7323a8fa117100200bfd5adf857393b0bb'
-                     'd67906c081e585410e38480ead51684dac3a38f7b64c9eb109f1973'
-                     '9a4517cd7d5d6291e8af20a3fbf17336c7bf80ee718ee087e322ee4'
-                     '1047dabefbcc34d10b66b644ddb3160a28c0639563d71993a26543e'
-                     'adb7718f317bf5d9577a6156561b082a10029cd44012b18de684450'
-                     '9fe058ba87980792285f2750969fe89c2cd6498db3545638d5379d1'
-                     '25dccf64e06c1af33a6190841d223da1513333a7c9d78462abaab31'
-                     'b9f96d5f34445ceb6309f2f6d2c8dde06441e87980d303ef9a1ff00'
-                     '7e8be2f0be06cc15f', 16),
-            'q': int('e71f8567447f42e75f5ef85ca20fe557ab0343d37ed09edc3f6e686'
-                     '04d6b9dfb', 16),
-            'g': int('5ba24de9607b8998e66ce6c4f812a314c6935842f7ab54cd82b19fa'
-                     '104abfb5d84579a623b2574b37d22ccae9b3e415e48f5c0f9bcbdff'
-                     '8071d63b9bb956e547af3a8df99e5d3061979652ff96b765cb3ee49'
-                     '3643544c75dbe5bb39834531952a0fb4b0378b3fcbb4c8b5800a533'
-                     '0392a2a04e700bb6ed7e0b85795ea38b1b962741b3f33b9dde2f4ec'
-                     '1354f09e2eb78e95f037a5804b6171659f88715ce1a9b0cc90c27f3'
-                     '5ef2f10ff0c7c7a2bb0154d9b8ebe76a3d764aa879af372f4240de8'
-                     '347937e5a90cec9f41ff2f26b8da9a94a225d1a913717d73f10397d'
-                     '2183f1ba3b7b45a68f1ff1893caf69a827802f7b6a48d51da6fbefb'
-                     '64fd9a6c5b75c4561', 16),
-            'digest_algorithm': 'SHA-256',
-            'msg': binascii.unhexlify(
-                b'a733b3f588d5ac9b9d4fe2f804df8c256403a9f8eef6f191fc48e1267fb'
-                b'5b4d546ba11e77b667844e489bf0d5f72990aeb061d01ccd7949a23def7'
-                b'4a803b7d92d51abfadeb4885ffd8ffd58ab87548a15c087a39b8993b2fa'
-                b'64c9d31a594eeb7512da16955834336a234435c5a9d0dd9b15a94e11615'
-                b'4dea63fdc8dd7a512181'),
-            'y': int('356ed47537fbf02cb30a8cee0537f300dff1d0c467399ce70b87a87'
-                     '58d5ec9dd256246fccaeb9dfe109f2a984f2ddaa87aad54ce0d31f9'
-                     '07e504521baf4207d7073b0a4a9fc67d8ddda99f87aed6e0367cec2'
-                     '7f9c608af743bf1ee6e11d55a182d43b024ace534029b866f642282'
-                     '8bb81a39aae9601ee81c7f81dd358e69f4e2edfa4654d8a65bc6431'
-                     '1dc86aac4abc1fc7a3f65159661a0d8e288eb8d665cb0adf5ac3d6b'
-                     'a8e9453facf7542393ae24fd50451d3828086558f7ec528e284935a'
-                     '53f67a1aa8e25d8ad5c4ad55d83aef883a4d9eeb6297e6a53f65049'
-                     'ba9e2c6b7953a760bc1dc46f78ceaaa2c02f5375dd82e708744aa40'
-                     'b15799eb81d7e5b1a', 16),
-            'r': int('bcd490568c0a89ba311bef88ea4f4b03d273e793722722327095a37'
-                     '8dd6f3522', 16),
-            's': int('74498fc43091fcdd2d1ef0775f8286945a01cd72b805256b0451f9c'
-                     'bd943cf82', 16)}
+            "p": int(
+                "a8adb6c0b4cf9588012e5deff1a871d383e0e2a85b5e8e03d814fe1"
+                "3a059705e663230a377bf7323a8fa117100200bfd5adf857393b0bb"
+                "d67906c081e585410e38480ead51684dac3a38f7b64c9eb109f1973"
+                "9a4517cd7d5d6291e8af20a3fbf17336c7bf80ee718ee087e322ee4"
+                "1047dabefbcc34d10b66b644ddb3160a28c0639563d71993a26543e"
+                "adb7718f317bf5d9577a6156561b082a10029cd44012b18de684450"
+                "9fe058ba87980792285f2750969fe89c2cd6498db3545638d5379d1"
+                "25dccf64e06c1af33a6190841d223da1513333a7c9d78462abaab31"
+                "b9f96d5f34445ceb6309f2f6d2c8dde06441e87980d303ef9a1ff00"
+                "7e8be2f0be06cc15f",
+                16,
+            ),
+            "q": int(
+                "e71f8567447f42e75f5ef85ca20fe557ab0343d37ed09edc3f6e686"
+                "04d6b9dfb",
+                16,
+            ),
+            "g": int(
+                "5ba24de9607b8998e66ce6c4f812a314c6935842f7ab54cd82b19fa"
+                "104abfb5d84579a623b2574b37d22ccae9b3e415e48f5c0f9bcbdff"
+                "8071d63b9bb956e547af3a8df99e5d3061979652ff96b765cb3ee49"
+                "3643544c75dbe5bb39834531952a0fb4b0378b3fcbb4c8b5800a533"
+                "0392a2a04e700bb6ed7e0b85795ea38b1b962741b3f33b9dde2f4ec"
+                "1354f09e2eb78e95f037a5804b6171659f88715ce1a9b0cc90c27f3"
+                "5ef2f10ff0c7c7a2bb0154d9b8ebe76a3d764aa879af372f4240de8"
+                "347937e5a90cec9f41ff2f26b8da9a94a225d1a913717d73f10397d"
+                "2183f1ba3b7b45a68f1ff1893caf69a827802f7b6a48d51da6fbefb"
+                "64fd9a6c5b75c4561",
+                16,
+            ),
+            "digest_algorithm": "SHA-256",
+            "msg": binascii.unhexlify(
+                b"a733b3f588d5ac9b9d4fe2f804df8c256403a9f8eef6f191fc48e1267fb"
+                b"5b4d546ba11e77b667844e489bf0d5f72990aeb061d01ccd7949a23def7"
+                b"4a803b7d92d51abfadeb4885ffd8ffd58ab87548a15c087a39b8993b2fa"
+                b"64c9d31a594eeb7512da16955834336a234435c5a9d0dd9b15a94e11615"
+                b"4dea63fdc8dd7a512181"
+            ),
+            "y": int(
+                "356ed47537fbf02cb30a8cee0537f300dff1d0c467399ce70b87a87"
+                "58d5ec9dd256246fccaeb9dfe109f2a984f2ddaa87aad54ce0d31f9"
+                "07e504521baf4207d7073b0a4a9fc67d8ddda99f87aed6e0367cec2"
+                "7f9c608af743bf1ee6e11d55a182d43b024ace534029b866f642282"
+                "8bb81a39aae9601ee81c7f81dd358e69f4e2edfa4654d8a65bc6431"
+                "1dc86aac4abc1fc7a3f65159661a0d8e288eb8d665cb0adf5ac3d6b"
+                "a8e9453facf7542393ae24fd50451d3828086558f7ec528e284935a"
+                "53f67a1aa8e25d8ad5c4ad55d83aef883a4d9eeb6297e6a53f65049"
+                "ba9e2c6b7953a760bc1dc46f78ceaaa2c02f5375dd82e708744aa40"
+                "b15799eb81d7e5b1a",
+                16,
+            ),
+            "r": int(
+                "bcd490568c0a89ba311bef88ea4f4b03d273e793722722327095a37"
+                "8dd6f3522",
+                16,
+            ),
+            "s": int(
+                "74498fc43091fcdd2d1ef0775f8286945a01cd72b805256b0451f9c"
+                "bd943cf82",
+                16,
+            ),
+        },
     ]
     assert expected == load_fips_dsa_sig_vectors(vector_data)
 
 
 def test_load_fips_ecdsa_key_pair_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     #  CAVS 11.0
     #  "Key Pair" information
     #  Curves selected: P-192 K-233 B-571
@@ -2346,67 +2702,97 @@
 7d6289980819292a719eb247195529ea60ad62862de0a26c72bfc49ecc81c2f9ed704e3168f
     Qy = 0721496cf16f988b1aabef3368450441df8439a0ca794170f270ead56203d675b57f5\
 a4090a3a2f602a77ff3bac1417f7e25a683f667b3b91f105016a47afad46a0367b18e2bdf0c
-    """).splitlines()
+    """
+    ).splitlines()
 
     expected = [
         {
             "curve": "secp192r1",
             "d": int("e5ce89a34adddf25ff3bf1ffe6803f57d0220de3118798ea", 16),
             "x": int("8abf7b3ceb2b02438af19543d3e5b1d573fa9ac60085840f", 16),
-            "y": int("a87f80182dcd56a6a061f81f7da393e7cffd5e0738c6b245", 16)
+            "y": int("a87f80182dcd56a6a061f81f7da393e7cffd5e0738c6b245", 16),
         },
-
         {
             "curve": "secp192r1",
             "d": int("7d14435714ad13ff23341cb567cc91198ff8617cc39751b2", 16),
             "x": int("39dc723b19527daa1e80425209c56463481b9b47c51f8cbd", 16),
             "y": int("432a3e84f2a16418834fabaf6b7d2341669512951f1672ad", 16),
         },
-
         {
             "curve": "sect233k1",
-            "d": int("1da7422b50e3ff051f2aaaed10acea6cbf6110c517da2f4e"
-                     "aca8b5b87", 16),
-            "x": int("1c7475da9a161e4b3f7d6b086494063543a979e34b8d7ac4"
-                     "4204d47bf9f", 16),
-            "y": int("131cbd433f112871cc175943991b6a1350bf0cdd57ed8c83"
-                     "1a2a7710c92", 16),
+            "d": int(
+                "1da7422b50e3ff051f2aaaed10acea6cbf6110c517da2f4e" "aca8b5b87",
+                16,
+            ),
+            "x": int(
+                "1c7475da9a161e4b3f7d6b086494063543a979e34b8d7ac4"
+                "4204d47bf9f",
+                16,
+            ),
+            "y": int(
+                "131cbd433f112871cc175943991b6a1350bf0cdd57ed8c83"
+                "1a2a7710c92",
+                16,
+            ),
         },
-
         {
             "curve": "sect233k1",
-            "d": int("530951158f7b1586978c196603c12d25607d2cb0557efadb"
-                     "23cd0ce8", 16),
-            "x": int("d37500a0391d98d3070d493e2b392a2c79dc736c097ed24b"
-                     "7dd5ddec44", 16),
-            "y": int("1d996cc79f37d8dba143d4a8ad9a8a60ed7ea760aae1ddba"
-                     "34d883f65d9", 16),
+            "d": int(
+                "530951158f7b1586978c196603c12d25607d2cb0557efadb" "23cd0ce8",
+                16,
+            ),
+            "x": int(
+                "d37500a0391d98d3070d493e2b392a2c79dc736c097ed24b"
+                "7dd5ddec44",
+                16,
+            ),
+            "y": int(
+                "1d996cc79f37d8dba143d4a8ad9a8a60ed7ea760aae1ddba"
+                "34d883f65d9",
+                16,
+            ),
         },
-
         {
             "curve": "sect571r1",
-            "d": int("1443e93c7ef6802655f641ecbe95e75f1f15b02d2e172f49"
-                     "a32e22047d5c00ebe1b3ff0456374461360667dbf07bc67f"
-                     "7d6135ee0d1d46a226a530fefe8ebf3b926e9fbad8d57a6", 16),
-            "x": int("53e3710d8e7d4138db0a369c97e5332c1be38a20a4a84c36"
-                     "f5e55ea9fd6f34545b864ea64f319e74b5ee9e4e1fa1b7c5"
-                     "b2db0e52467518f8c45b658824871d5d4025a6320ca06f8", 16),
-            "y": int("3a22cfd370c4a449b936ae97ab97aab11c57686cca99d14e"
-                     "f184f9417fad8bedae4df8357e3710bcda1833b30e297d4b"
-                     "f637938b995d231e557d13f062e81e830af5ab052208ead", 16),
+            "d": int(
+                "1443e93c7ef6802655f641ecbe95e75f1f15b02d2e172f49"
+                "a32e22047d5c00ebe1b3ff0456374461360667dbf07bc67f"
+                "7d6135ee0d1d46a226a530fefe8ebf3b926e9fbad8d57a6",
+                16,
+            ),
+            "x": int(
+                "53e3710d8e7d4138db0a369c97e5332c1be38a20a4a84c36"
+                "f5e55ea9fd6f34545b864ea64f319e74b5ee9e4e1fa1b7c5"
+                "b2db0e52467518f8c45b658824871d5d4025a6320ca06f8",
+                16,
+            ),
+            "y": int(
+                "3a22cfd370c4a449b936ae97ab97aab11c57686cca99d14e"
+                "f184f9417fad8bedae4df8357e3710bcda1833b30e297d4b"
+                "f637938b995d231e557d13f062e81e830af5ab052208ead",
+                16,
+            ),
         },
-
         {
             "curve": "sect571r1",
-            "d": int("3d2bd44ca9eeee8c860a4873ed55a54bdfdf5dab4060df72"
-                     "92877960b85d1fd496aa33c587347213d7f6bf208a6ab4b4"
-                     "30546e7b6ffbc3135bd12f44a28517867ca3c83a821d6f8", 16),
-            "x": int("7a7af10f6617090bade18b2e092d0dfdc87cd616db7f2db1"
-                     "33477a82bfe3ea421ebb7d6289980819292a719eb2471955"
-                     "29ea60ad62862de0a26c72bfc49ecc81c2f9ed704e3168f", 16),
-            "y": int("721496cf16f988b1aabef3368450441df8439a0ca794170f"
-                     "270ead56203d675b57f5a4090a3a2f602a77ff3bac1417f7"
-                     "e25a683f667b3b91f105016a47afad46a0367b18e2bdf0c", 16),
+            "d": int(
+                "3d2bd44ca9eeee8c860a4873ed55a54bdfdf5dab4060df72"
+                "92877960b85d1fd496aa33c587347213d7f6bf208a6ab4b4"
+                "30546e7b6ffbc3135bd12f44a28517867ca3c83a821d6f8",
+                16,
+            ),
+            "x": int(
+                "7a7af10f6617090bade18b2e092d0dfdc87cd616db7f2db1"
+                "33477a82bfe3ea421ebb7d6289980819292a719eb2471955"
+                "29ea60ad62862de0a26c72bfc49ecc81c2f9ed704e3168f",
+                16,
+            ),
+            "y": int(
+                "721496cf16f988b1aabef3368450441df8439a0ca794170f"
+                "270ead56203d675b57f5a4090a3a2f602a77ff3bac1417f7"
+                "e25a683f667b3b91f105016a47afad46a0367b18e2bdf0c",
+                16,
+            ),
         },
     ]
 
@@ -2414,7 +2800,8 @@
 
 
 def test_load_fips_ecdsa_signing_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     #  CAVS 11.2
     #  "SigVer" information for "ecdsa_values"
     #  Curves/SHAs selected: P-192, B-571,SHA-512
@@ -2481,7 +2868,8 @@
 bdcf3035f6829ede041b745955d219dc5d30ddd8b37f6ba0f6d2857504cdc68a1ed812a10
     S = 34db9998dc53527114518a7ce3783d674ca8cced823fa05e2942e7a0a20b3cc583dcd9\
 30c43f9b93079c5ee18a1f5a66e7c3527c18610f9b47a4da7e245ef803e0662e4d2ad721c
-    """).splitlines()
+    """
+    ).splitlines()
 
     expected = [
         {
@@ -2499,7 +2887,7 @@
             "y": int("76fab681d00b414ea636ba215de26d98c41bd7f2e4d65477", 16),
             "r": int("6994d962bdd0d793ffddf855ec5bf2f91a9698b46258a63e", 16),
             "s": int("02ba6465a234903744ab02bc8521405b73cf5fc00e1a9f41", 16),
-            "fail": True
+            "fail": True,
         },
         {
             "curve": "secp192r1",
@@ -2527,22 +2915,37 @@
                 b"d74e38983b24c0748618e2f92ef7cac257ff4bd1f41113f2891eb13c4793"
                 b"0e69ddbe91f270fb"
             ),
-            "d": int("3e1b03ffca4399d5b439fac8f87a5cb06930f00d304193d7daf83d59"
-                     "47d0c1e293f74aef8e56849f16147133c37a6b3d1b1883e5d61d6b87"
-                     "1ea036c5291d9a74541f28878cb986", 16),
-            "x": int("3b236fc135d849d50140fdaae1045e6ae35ef61091e98f5059b30eb1"
-                     "6acdd0deb2bc0d3544bc3a666e0014e50030134fe5466a9e4d3911ed"
-                     "580e28851f3747c0010888e819d3d1f", 16),
-            "y": int("3a8b6627a587d289032bd76374d16771188d7ff281c39542c8977f68"
-                     "72fa932e5daa14e13792dea9ffe8e9f68d6b525ec99b81a5a60cfb05"
-                     "90cc6f297cfff8d7ba1a8bb81fe2e16", 16),
-            "r": int("2eb1c5c1fc93cf3c8babed12c031cf1504e094174fd335104cbe4a2a"
-                     "bd210b5a14b1c3a455579f1ed0517c31822340e4dd3c1f967e1b4b9d"
-                     "071a1072afc1a199f8c548cd449a634", 16),
-            "s": int("22f97bb48641235826cf4e597fa8de849402d6bd6114ad2d7fbcf53a"
-                     "08247e5ee921f1bd5994dffee36eedff5592bb93b8bb148214da3b7b"
-                     "aebffbd96b4f86c55b3f6bbac142442", 16),
-            "fail": False
+            "d": int(
+                "3e1b03ffca4399d5b439fac8f87a5cb06930f00d304193d7daf83d59"
+                "47d0c1e293f74aef8e56849f16147133c37a6b3d1b1883e5d61d6b87"
+                "1ea036c5291d9a74541f28878cb986",
+                16,
+            ),
+            "x": int(
+                "3b236fc135d849d50140fdaae1045e6ae35ef61091e98f5059b30eb1"
+                "6acdd0deb2bc0d3544bc3a666e0014e50030134fe5466a9e4d3911ed"
+                "580e28851f3747c0010888e819d3d1f",
+                16,
+            ),
+            "y": int(
+                "3a8b6627a587d289032bd76374d16771188d7ff281c39542c8977f68"
+                "72fa932e5daa14e13792dea9ffe8e9f68d6b525ec99b81a5a60cfb05"
+                "90cc6f297cfff8d7ba1a8bb81fe2e16",
+                16,
+            ),
+            "r": int(
+                "2eb1c5c1fc93cf3c8babed12c031cf1504e094174fd335104cbe4a2a"
+                "bd210b5a14b1c3a455579f1ed0517c31822340e4dd3c1f967e1b4b9d"
+                "071a1072afc1a199f8c548cd449a634",
+                16,
+            ),
+            "s": int(
+                "22f97bb48641235826cf4e597fa8de849402d6bd6114ad2d7fbcf53a"
+                "08247e5ee921f1bd5994dffee36eedff5592bb93b8bb148214da3b7b"
+                "aebffbd96b4f86c55b3f6bbac142442",
+                16,
+            ),
+            "fail": False,
         },
         {
             "curve": "sect571r1",
@@ -2554,28 +2957,44 @@
                 b"0f10bc31c249b7b46edd2462a55f85560d99bde9d5b06b97817d1dbe0a67"
                 b"c701d6e6e7878272"
             ),
-            "d": int("2e09ffd8b434bb7f67d1d3ccf482164f1653c6e4ec64dec2517aa21b"
-                     "7a93b2b21ea1eebb54734882f29303e489f02e3b741a87287e2dcdf3"
-                     "858eb6d2ec668f8b5b26f442ce513a2", 16),
-            "x": int("36f1be8738dd7dae4486b86a08fe90424f3673e76b10e739442e15f3"
-                     "bfafaf841842ac98e490521b7e7bb94c127529f6ec6a42cc6f06fc80"
-                     "606f1210fe020ff508148f93301c9d3", 16),
-            "y": int("4d39666ebe99fe214336ad440d776c88eb916f2f4a3433548b87d2ae"
-                     "bed840b424d15c8341b4a0a657bf6a234d4fe78631c8e07ac1f4dc74"
-                     "74cd6b4545d536b7b17c160db4562d9", 16),
-            "r": int("3d8105f87fe3166046c08e80a28acc98a80b8b7a729623053c2a9e80"
-                     "afd06756edfe09bdcf3035f6829ede041b745955d219dc5d30ddd8b3"
-                     "7f6ba0f6d2857504cdc68a1ed812a10", 16),
-            "s": int("34db9998dc53527114518a7ce3783d674ca8cced823fa05e2942e7a0"
-                     "a20b3cc583dcd930c43f9b93079c5ee18a1f5a66e7c3527c18610f9b"
-                     "47a4da7e245ef803e0662e4d2ad721c", 16)
-        }
+            "d": int(
+                "2e09ffd8b434bb7f67d1d3ccf482164f1653c6e4ec64dec2517aa21b"
+                "7a93b2b21ea1eebb54734882f29303e489f02e3b741a87287e2dcdf3"
+                "858eb6d2ec668f8b5b26f442ce513a2",
+                16,
+            ),
+            "x": int(
+                "36f1be8738dd7dae4486b86a08fe90424f3673e76b10e739442e15f3"
+                "bfafaf841842ac98e490521b7e7bb94c127529f6ec6a42cc6f06fc80"
+                "606f1210fe020ff508148f93301c9d3",
+                16,
+            ),
+            "y": int(
+                "4d39666ebe99fe214336ad440d776c88eb916f2f4a3433548b87d2ae"
+                "bed840b424d15c8341b4a0a657bf6a234d4fe78631c8e07ac1f4dc74"
+                "74cd6b4545d536b7b17c160db4562d9",
+                16,
+            ),
+            "r": int(
+                "3d8105f87fe3166046c08e80a28acc98a80b8b7a729623053c2a9e80"
+                "afd06756edfe09bdcf3035f6829ede041b745955d219dc5d30ddd8b3"
+                "7f6ba0f6d2857504cdc68a1ed812a10",
+                16,
+            ),
+            "s": int(
+                "34db9998dc53527114518a7ce3783d674ca8cced823fa05e2942e7a0"
+                "a20b3cc583dcd930c43f9b93079c5ee18a1f5a66e7c3527c18610f9b"
+                "47a4da7e245ef803e0662e4d2ad721c",
+                16,
+            ),
+        },
     ]
     assert expected == load_fips_ecdsa_signing_vectors(vector_data)
 
 
 def test_load_kasvs_dh_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     [SHA(s) supported (Used for hashing Z): SHA256 ]
     #  Generated on Thu Mar 17 20:44:26 2011
 
@@ -2745,70 +3164,83 @@
 d518475576730ed528779366568e46b7dd4ed787cb72d0733c93
     CAVSHashZZ = 17dbbaa7a20c1390cd8cb3d31ee947bf9dde87739e067b9861ffeea9
     Result = P (0 - Correct)
-    """).splitlines()
+    """
+    ).splitlines()
 
     expected = [
         {
-            'fail_agree': False,
-            'fail_z': False,
-            'g': int(
+            "fail_agree": False,
+            "fail_z": False,
+            "g": int(
                 "a51883e9ac0539859df3d25c716437008bb4bd8ec4786eb4bc643299daef5"
                 "e3e5af5863a6ac40a597b83a27583f6a658d408825105b16d31b6ed088fc6"
                 "23f648fd6d95e9cefcb0745763cddf564c87bcf4ba7928e74fd6a3080481f"
                 "588d535e4c026b58a21e1e5ec412ff241b436043e29173f1dc6cb943c0974"
-                "2de989547288", 16),
-            'p': int(
+                "2de989547288",
+                16,
+            ),
+            "p": int(
                 "da3a8085d372437805de95b88b675122f575df976610c6a844de99f1df82a"
                 "06848bf7a42f18895c97402e81118e01a00d0855d51922f434c022350861d"
                 "58ddf60d65bc6941fc6064b147071a4c30426d82fc90d888f94990267c64b"
                 "eef8c304a4b2b26fb93724d6a9472fa16bc50c5b9b8b59afb62cfe9ea3ba0"
-                "42c73a6ade35", 16),
-            'q': 1386090807861091316803998193774751098153687863463,
-            'x1': 381229709512864262422021151581620734547375903702,
-            'x2': 479735944608461101114916716909067001453470352916,
-            'y1': int(
+                "42c73a6ade35",
+                16,
+            ),
+            "q": 1386090807861091316803998193774751098153687863463,
+            "x1": 381229709512864262422021151581620734547375903702,
+            "x2": 479735944608461101114916716909067001453470352916,
+            "y1": int(
                 "5a7890f6d20ee9c7162cd84222cb0c7cb5b4f29244a58fc95327fc41045f4"
                 "76fb3da42fca76a1dd59222a7a7c3872d5af7d8dc254e003eccdb38f29161"
                 "9c51911df2b6ed67d0b459f4bc25819c0078777b9a1a24c72e7c037a3720a"
                 "1edad5863ef5ac75ce816869c820859558d5721089ddbe331f55bef741396"
-                "a3bbf85c6c1a", 16),
-            'y2': int(
+                "a3bbf85c6c1a",
+                16,
+            ),
+            "y2": int(
                 "b92af0468b841ea5de4ca91d895b5e922245421de57ed7a88d2de41610b20"
                 "8e8e233705f17b2e9eb91914bad2fa87f0a58519a7da2980bc06e7411c925"
                 "a6050526bd86e621505e6f610b63fdcd9afcfaa96bd087afca44d9197cc35"
                 "b559f731357a5b979250c0f3a254bb8165f5072156e3fd6f9a6e69bcf4b45"
-                "78f78b3bde7", 16),
-            'z': binascii.unhexlify(
+                "78f78b3bde7",
+                16,
+            ),
+            "z": binascii.unhexlify(
                 b"8d8f4175e16e15a42eb9099b11528af88741cc206a088971d3064bb291ed"
                 b"a608d1600bff829624db258fd15e95d96d3e74c6be3232afe5c855b9c596"
                 b"81ce13b7aea9ff2b16707e4c02f0e82bf6dadf2149ac62630f6c62dea0e5"
                 b"05e3279404da5ffd5a088e8474ae0c8726b8189cb3d2f04baffe700be849"
                 b"df9f91567fc2ebb8"
-            )
+            ),
         },
         {
-            'fail_agree': False,
-            'fail_z': False,
-            'g': int(
+            "fail_agree": False,
+            "fail_z": False,
+            "g": int(
                 "a51883e9ac0539859df3d25c716437008bb4bd8ec4786eb4bc643299daef5"
                 "e3e5af5863a6ac40a597b83a27583f6a658d408825105b16d31b6ed088fc6"
                 "23f648fd6d95e9cefcb0745763cddf564c87bcf4ba7928e74fd6a3080481f"
                 "588d535e4c026b58a21e1e5ec412ff241b436043e29173f1dc6cb943c0974"
-                "2de989547288", 16),
-            'p': int(
+                "2de989547288",
+                16,
+            ),
+            "p": int(
                 "da3a8085d372437805de95b88b675122f575df976610c6a844de99f1df82a"
                 "06848bf7a42f18895c97402e81118e01a00d0855d51922f434c022350861d"
                 "58ddf60d65bc6941fc6064b147071a4c30426d82fc90d888f94990267c64b"
                 "eef8c304a4b2b26fb93724d6a9472fa16bc50c5b9b8b59afb62cfe9ea3ba0"
-                "42c73a6ade35", 16),
-            'q': 1386090807861091316803998193774751098153687863463,
-            'x1': int(
-                "32e642683d745a23dccf4f12f989d8dfd1fd9894c422930950cb4c71",
-                16),
-            'x2': int(
-                "7d8ae93df3bc09d399a4157ec562126acf51092c3269ab27f60a3a2b",
-                16),
-            'y1': int(
+                "42c73a6ade35",
+                16,
+            ),
+            "q": 1386090807861091316803998193774751098153687863463,
+            "x1": int(
+                "32e642683d745a23dccf4f12f989d8dfd1fd9894c422930950cb4c71", 16
+            ),
+            "x2": int(
+                "7d8ae93df3bc09d399a4157ec562126acf51092c3269ab27f60a3a2b", 16
+            ),
+            "y1": int(
                 "8cd371363b32fcc2e936e345f2278b77001f2efdf78512c3ee75c12f88507"
                 "e2d5c0e5cdded3bb78435506c8028a3f4d6f028c0f49a0d61f1285795197e"
                 "56deac80279e723f2b3746e213ac8ec60f1cefc2308ff17a7e9e2efab537e"
@@ -2817,8 +3249,10 @@
                 "3e1c450c5798dc05f8265ad9e35095ff112af9e889f00315fa337a76a4506"
                 "70866eca12cc6ad0778576962eb9cdc12721d3c15e4d87b67488a145d4002"
                 "40670eb26695a42879cd3940a55087f6527667277e1212a202dbe455c45c6"
-                "4b9be4a38153557bbb8fd755", 16),
-            'y2': int(
+                "4b9be4a38153557bbb8fd755",
+                16,
+            ),
+            "y2": int(
                 "22127e9728e906ea4b1512c8b1e80474b58446210c23ccfc800f83c2c15da"
                 "8159940e494b235266f6a9d5f80529067794f1a9edd566755d23d0a3060fe"
                 "074c5a10122df3e472973bba39ea3a988e8387f5f0491e590b6b5edc299b4"
@@ -2827,8 +3261,10 @@
                 "6c3d75d9bcf83f4b8d1ed39408bd8d973b4ea81e8e832eac361dcd5307133"
                 "88a60971ea9f8b1e69c1e99df1cca12bdaf293dacfa1419c5692ceffa9198"
                 "8aef3321ac8cbc2efae6c4337c8808310fb5a240395a98e6004fe613c39e8"
-                "4f4177341746d9e388dcb2e8", 16),
-            'z': binascii.unhexlify(
+                "4f4177341746d9e388dcb2e8",
+                16,
+            ),
+            "z": binascii.unhexlify(
                 b"0efeaa399a182e0a603baf0dd95aa0fae5289ebd47d5f0f60c86bc936839"
                 b"c31c9f7f37bf04f76ab02f4094a8ab10ed907ec7291585cc085c3e8981df"
                 b"2bd46a01c19ec9a2f66709df1d4fefbeb48c8263554e46890f59eb642bf9"
@@ -2838,31 +3274,35 @@
                 b"ce2a585eb9e8f308b48cf4e29593b6f7a02e8625e1e8bff1ea1405f8c8c3"
                 b"4b8339a9a99c7c9de4eb9895df7719ccda9394f53080eff1226f6b9c7ae0"
                 b"a38941e18b1a137aabbb62308eb35ba2"
-            )
+            ),
         },
         {
-            'fail_agree': False,
-            'fail_z': True,
-            'g': int(
+            "fail_agree": False,
+            "fail_z": True,
+            "g": int(
                 "a51883e9ac0539859df3d25c716437008bb4bd8ec4786eb4bc643299daef5"
                 "e3e5af5863a6ac40a597b83a27583f6a658d408825105b16d31b6ed088fc6"
                 "23f648fd6d95e9cefcb0745763cddf564c87bcf4ba7928e74fd6a3080481f"
                 "588d535e4c026b58a21e1e5ec412ff241b436043e29173f1dc6cb943c0974"
-                "2de989547288", 16),
-            'p': int(
+                "2de989547288",
+                16,
+            ),
+            "p": int(
                 "da3a8085d372437805de95b88b675122f575df976610c6a844de99f1df82a"
                 "06848bf7a42f18895c97402e81118e01a00d0855d51922f434c022350861d"
                 "58ddf60d65bc6941fc6064b147071a4c30426d82fc90d888f94990267c64b"
                 "eef8c304a4b2b26fb93724d6a9472fa16bc50c5b9b8b59afb62cfe9ea3ba0"
-                "42c73a6ade35", 16),
-            'q': 1386090807861091316803998193774751098153687863463,
-            'x1': int(
-                "66502429aba271e2f2ee2197a2b336e5f0467f192aa28b60dcbf1194",
-                16),
-            'x2': int(
-                "106b358be4f068348ac240ecbb454e5c39ca80b078cb0fafd856e9c5",
-                16),
-            'y1': int(
+                "42c73a6ade35",
+                16,
+            ),
+            "q": 1386090807861091316803998193774751098153687863463,
+            "x1": int(
+                "66502429aba271e2f2ee2197a2b336e5f0467f192aa28b60dcbf1194", 16
+            ),
+            "x2": int(
+                "106b358be4f068348ac240ecbb454e5c39ca80b078cb0fafd856e9c5", 16
+            ),
+            "y1": int(
                 "dfb001294215423d7146a2453cdb8598ccef01e1d931a913c3e4ed4a3cf38"
                 "a912066c28e4eaf77dd80ff07183a6160bd95932f513402f864dcf7a70cbe"
                 "dc9b60bbfbc67f72a83d5f6463a2b5a4fc906d3e921f5e1069126113265b4"
@@ -2871,8 +3311,10 @@
                 "51043d351bb74a952e6a694e6e7456f714c47d7c8eeeb4fd83ad93c86b784"
                 "45f9393fdfd65c7dbd7fd6eba9794ddf183901b1d213321fd0ab3f7588ab0"
                 "f6b3692f365a87131eda0e062505861988f6ce63150207545ecf9678e0971"
-                "330253dfb7cfd546c5346fec", 16),
-            'y2': int(
+                "330253dfb7cfd546c5346fec",
+                16,
+            ),
+            "y2": int(
                 "715d0781975b7b03162f4401c1eda343fd9bf1140006034573b31828a618c"
                 "356163554cd27da956f7179a69e860fb6efeaa2e2aa9f1261506a8344c492"
                 "9953621381b13d6426e152c0f2f94bfcd2b758eca24923596d427ed8f957e"
@@ -2881,8 +3323,10 @@
                 "ad5c5bd490ea600e04379232fb1077fbf394f4579accdbe352714e25b8891"
                 "6dca8d8f7e0c4ed9594f7693f656a235a2e88ebda48b0d557e32da9f12d2a"
                 "4c3180f05b16b4fba9bec79278a3971b77f9223b5ab78b857e0376c500821"
-                "1592c8c72d521373ee3b22b8", 16),
-            'z': binascii.unhexlify(
+                "1592c8c72d521373ee3b22b8",
+                16,
+            ),
+            "z": binascii.unhexlify(
                 b"cf879ebd107bb877457809c3fc410218b7acba3c5967495a8f1c3370d57f"
                 b"038a48dd69f9f69b9f4dd855e7c58a1e4ec32646a978266eb314db468ea1"
                 b"dfcee8a85a1644a5732498c4fbcdf85098c6ed0ce12e431e99142fd23353"
@@ -2892,12 +3336,12 @@
                 b"665095490056287e4fc49e6cb3181cb2bf06444fd0040150271c9ce1f61c"
                 b"13ecd5dd022194a2dbf3e1c7fbc6bd19497c7b888b4da613d28fa6f378a4"
                 b"3369cb8795a1c823f7d6cf4d84bba578"
-            )
+            ),
         },
         {
-            'fail_agree': True,
-            'fail_z': False,
-            'g': int(
+            "fail_agree": True,
+            "fail_z": False,
+            "g": int(
                 "35513ec441402b78353ab1bba550b21c76c89973885a627170262ef52497d"
                 "5d137b8927a212aaab2f051198c90bb81dffd9eb10b36b7ca3b63565b4c10"
                 "25aea3b5e9c4a348c9cfa17f3907a1e4469701c0dedb8a4b9e96c5965b1fb"
@@ -2906,8 +3350,10 @@
                 "65bb4e1e9474993fe382fd23480dc875861be152997a621fdb7aef977ea5b"
                 "4d3d74486b162dc28f95a64cf65587a919a57eef92934fc9410df7f09fa82"
                 "f975328ed82ff29cc3e15a971f56f4ac2dcb289252575e02a6cdb7fcc6cdd"
-                "d7b0dca9c422e63eb2b8f05", 16),
-            'p': int(
+                "d7b0dca9c422e63eb2b8f05",
+                16,
+            ),
+            "p": int(
                 "f3722b9b911c6aede9eaeeaa406283de66a097f39a7225df6c3c916e57920"
                 "d356e50478d307dbfd146bfb91b6f68ecbbcf54b3d19c33a4b17293fea3e3"
                 "d6bff8ac4cca93a805386f062a8a27ae906ef5da94d279fd7b3d7289e0095"
@@ -2916,17 +3362,19 @@
                 "3c3dfda8de8429e087c5be97fc5c9db9526031ad3a218bd9916fb4a3c2796"
                 "6d208b1e360014c01e95530c148fb3cd27e6a7250d3c3b81dcd220ca14548"
                 "dbccf99ebb9e334db6bcd14e632c98dd3f9860af7ae450f1b7809b45f0ec1"
-                "0e6f27672beebc9963befc73", 16),
-            'q': int(
-                "a9a17de95a29091bf8e07dab53ea1aba9403be3c61027c6c8f48bac5",
-                16),
-            'x1': int(
-                "1610eaa4e0ccc8857e2b53149e008492b1fbd9025a6e8d95aaee9c0f",
-                16),
-            'x2': int(
-                "c4c83d75b27864b052cadc556e500e25aabf0c9d1bc01f0e1fe3862",
-                16),
-            'y1': int(
+                "0e6f27672beebc9963befc73",
+                16,
+            ),
+            "q": int(
+                "a9a17de95a29091bf8e07dab53ea1aba9403be3c61027c6c8f48bac5", 16
+            ),
+            "x1": int(
+                "1610eaa4e0ccc8857e2b53149e008492b1fbd9025a6e8d95aaee9c0f", 16
+            ),
+            "x2": int(
+                "c4c83d75b27864b052cadc556e500e25aabf0c9d1bc01f0e1fe3862", 16
+            ),
+            "y1": int(
                 "51ee21cd9f97015180f258fad5c94ff5a458806b1412087236bf77fe87aae"
                 "1a36735816ed6e2160a731159814b6ae1f3f52c478dd9207094adfb62f766"
                 "7d5c366327e66d23096395e938504db330953a708015f861fe9d948761109"
@@ -2935,8 +3383,10 @@
                 "a6f14ccdb29db02f64911bd83bfdcdfc843dd14a4cab9acb0bda8b293d2f5"
                 "f7050768e57533cbc415a29e6f31cc365e107f91ae3722484e2c7329a85af"
                 "69055a5a104da37e810878896d1b247b02b75234ecff82b1958f42d7b0316"
-                "22e9394c98b5229112f7f620", 16),
-            'y2': int(
+                "22e9394c98b5229112f7f620",
+                16,
+            ),
+            "y2": int(
                 "467a857337a82472a1307a64dccc8e9994c5c63ec4312936885d17be41905"
                 "1a5f037fbb052d7010ebe01634d9e8b8b522d9ab4749fdc274f465369b89e"
                 "360df8f70b7865a3c71d2dbcd2df19e9293dab1153d3d63fcb7deb559b684"
@@ -2945,8 +3395,10 @@
                 "c193f460dcd0be7e6e06e546da7653770dc5859df87029e722dbe81361030"
                 "569148d1636988926bf0dcfe47c9d8a54698c08b3b5c70afe86b5c6f64346"
                 "3f8f34889d27d6cfd2d478c2d7b3d008a985c7380f0b43f10024b59c35438"
-                "80883c42d0e7e0a07326ba3a", 16),
-            'z': binascii.unhexlify(
+                "80883c42d0e7e0a07326ba3a",
+                16,
+            ),
+            "z": binascii.unhexlify(
                 b"10a30bacab82e652415376baffdbc008c7eb2e5a3aa68bc10ce486ca8498"
                 b"3fd89b1b027bb40e75333406361005f5e756526a95fe01202df9217d81b1"
                 b"713d5187c368fdd4c9c2433d9e6c18844769479b725c4140c92a304ee1bc"
@@ -2956,41 +3408,47 @@
                 b"68c90178974a0602436cd186748bcc63a629edc3a0db59415cccd37a6513"
                 b"0ea477c89da92d41371f5972891cf41f9c7f0e75ccbff9893225384db30d"
                 b"aa5e310f08e3e0fad98bcdf8ecf35fe5"
-            )
+            ),
         },
         {
-            'fail_agree': False,
-            'fail_z': False,
-            'g': int("35513ec441402b78353ab1bba550b21c76c89973885a627170262ef5"
-                     "2497d5d137b8927a212aaab2f051198c90bb81dffd9eb10b36b7ca3b"
-                     "63565b4c1025aea3b5e9c4a348c9cfa17f3907a1e4469701c0dedb8a"
-                     "4b9e96c5965b1fb8c229b0c34baac774bf9dda4fc5ee8764358b3c84"
-                     "812878aab7464bc09e97aecab7d7e3fbb4870e2a3b89667a4158bf1e"
-                     "d1a90dfaf47019fbb52b1b96365bb4e1e9474993fe382fd23480dc87"
-                     "5861be152997a621fdb7aef977ea5b4d3d74486b162dc28f95a64cf6"
-                     "5587a919a57eef92934fc9410df7f09fa82f975328ed82ff29cc3e15"
-                     "a971f56f4ac2dcb289252575e02a6cdb7fcc6cddd7b0dca9c422e63e"
-                     "b2b8f05", 16),
-            'p': int("f3722b9b911c6aede9eaeeaa406283de66a097f39a7225df6c3c916e"
-                     "57920d356e50478d307dbfd146bfb91b6f68ecbbcf54b3d19c33a4b1"
-                     "7293fea3e3d6bff8ac4cca93a805386f062a8a27ae906ef5da94d279"
-                     "fd7b3d7289e00956f76bae9c0d2b8d11742ca5809630632aae58f9c6"
-                     "dce00c7380581deffde2187b022f83c6ceaeaadb0844a17fcbb04039"
-                     "ca6843c91f0c9058b22434b263c3dfda8de8429e087c5be97fc5c9db"
-                     "9526031ad3a218bd9916fb4a3c27966d208b1e360014c01e95530c14"
-                     "8fb3cd27e6a7250d3c3b81dcd220ca14548dbccf99ebb9e334db6bcd"
-                     "14e632c98dd3f9860af7ae450f1b7809b45f0ec10e6f27672beebc99"
-                     "63befc73", 16),
-            'q': int(
-                "a9a17de95a29091bf8e07dab53ea1aba9403be3c61027c6c8f48bac5",
-                16),
-            'x1': int(
-                "9ee22ac51664e40e0a24dbb94142dba40605e2b6eeaaa0268a0f6847",
-                16),
-            'x2': int(
-                "438093a468236658821bf64eb08456139963d4fb27121c3ed6c55876",
-                16),
-            'y1': int(
+            "fail_agree": False,
+            "fail_z": False,
+            "g": int(
+                "35513ec441402b78353ab1bba550b21c76c89973885a627170262ef5"
+                "2497d5d137b8927a212aaab2f051198c90bb81dffd9eb10b36b7ca3b"
+                "63565b4c1025aea3b5e9c4a348c9cfa17f3907a1e4469701c0dedb8a"
+                "4b9e96c5965b1fb8c229b0c34baac774bf9dda4fc5ee8764358b3c84"
+                "812878aab7464bc09e97aecab7d7e3fbb4870e2a3b89667a4158bf1e"
+                "d1a90dfaf47019fbb52b1b96365bb4e1e9474993fe382fd23480dc87"
+                "5861be152997a621fdb7aef977ea5b4d3d74486b162dc28f95a64cf6"
+                "5587a919a57eef92934fc9410df7f09fa82f975328ed82ff29cc3e15"
+                "a971f56f4ac2dcb289252575e02a6cdb7fcc6cddd7b0dca9c422e63e"
+                "b2b8f05",
+                16,
+            ),
+            "p": int(
+                "f3722b9b911c6aede9eaeeaa406283de66a097f39a7225df6c3c916e"
+                "57920d356e50478d307dbfd146bfb91b6f68ecbbcf54b3d19c33a4b1"
+                "7293fea3e3d6bff8ac4cca93a805386f062a8a27ae906ef5da94d279"
+                "fd7b3d7289e00956f76bae9c0d2b8d11742ca5809630632aae58f9c6"
+                "dce00c7380581deffde2187b022f83c6ceaeaadb0844a17fcbb04039"
+                "ca6843c91f0c9058b22434b263c3dfda8de8429e087c5be97fc5c9db"
+                "9526031ad3a218bd9916fb4a3c27966d208b1e360014c01e95530c14"
+                "8fb3cd27e6a7250d3c3b81dcd220ca14548dbccf99ebb9e334db6bcd"
+                "14e632c98dd3f9860af7ae450f1b7809b45f0ec10e6f27672beebc99"
+                "63befc73",
+                16,
+            ),
+            "q": int(
+                "a9a17de95a29091bf8e07dab53ea1aba9403be3c61027c6c8f48bac5", 16
+            ),
+            "x1": int(
+                "9ee22ac51664e40e0a24dbb94142dba40605e2b6eeaaa0268a0f6847", 16
+            ),
+            "x2": int(
+                "438093a468236658821bf64eb08456139963d4fb27121c3ed6c55876", 16
+            ),
+            "y1": int(
                 "c2630c9d38ed5c825d1c6a3eba7143f3fc8a049c8bcd1efc212d2af64eca9"
                 "94308208691d330aa8f27fc4a1e55de4e512113996d21375a667f8c26d76d"
                 "ee2f6809b15432a33fb735aca5c2263940f58712bded08f55443dee300b94"
@@ -2999,8 +3457,10 @@
                 "d43c4ffc9a605addbdcce0cb3790c6db846156bb857a7b3df40dc6ed04d19"
                 "cc9eaebb6bbc034e77c3d882a1a62317cce25b6130f0803e3bc49b5e36768"
                 "260073a617034872be0b50bed32740224beaf582d67fbcfef3b3ecc18f9c7"
-                "1c782e9a68495ef31dc7986e", 16),
-            'y2': int(
+                "1c782e9a68495ef31dc7986e",
+                16,
+            ),
+            "y2": int(
                 "e192da8e1244e27221c1765344a5bb379dce741d427a734b4bdb6c4d16b24"
                 "90bd37564d745008e63ae46ef332331d79887ac63298ce143e125f8b320c0"
                 "f859b7f5f2c1e0053e4a7a16997e6143ff702300c9863ae7caef5c1dfca0e"
@@ -3009,8 +3469,10 @@
                 "a56431cd48579bf53c903bbe066dd78b23c0996ef3a880f0d91315104366a"
                 "82f01abdecce96fd371f94e8420f8bc5b896c801df573554f749b03d0d28b"
                 "1e1a990bc61c7e9659342ac7e268e9c0b7c40fdaab394f29cf0a54f780022"
-                "f9a03b0bd28eb7db8b0b1b47", 16),
-            'z': binascii.unhexlify(
+                "f9a03b0bd28eb7db8b0b1b47",
+                16,
+            ),
+            "z": binascii.unhexlify(
                 b"56f8f40fa4b8f3580f9014b30d60a42933a53a62182a690142f458dc275c"
                 b"3b2f0e721bc5ee6e890b14516419110f5252ff1cceea8e274b2987aa78e3"
                 b"bae90c1935b276b7a1f1c944f79d4774b7a85b3355bdf25cb02bddfbda4e"
@@ -3020,8 +3482,8 @@
                 b"b75d049d4c82097af8a5ce353e14416b3eeb31ba9bc4f6f3dbd846c5299f"
                 b"b5c0043a1b95b9149b39d14df9e6a69547abf8a4d518475576730ed52877"
                 b"9366568e46b7dd4ed787cb72d0733c93"
-            )
-        }
+            ),
+        },
     ]
 
     assert expected == load_kasvs_dh_vectors(vector_data)
@@ -3032,7 +3494,8 @@
 
 
 def test_load_kasvs_ecdh_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     #  CAVS 11.0
     #  Parameter set(s) supported: EA EB EC ED EE
     #  CAVSid: CAVSid (in hex: 434156536964)
@@ -3183,148 +3646,291 @@
 
 
 
-    """).splitlines()
+    """
+    ).splitlines()
 
     expected = [
-        {'errno': 0,
-         'fail': False,
-         'COUNT': 0,
-         'CAVS': {
-             'd': int("f70c297a683d6b7ef82b5af7349606c4447c8b4fc6fa5e80", 16),
-             'x': int("f7b5061fb557e516c50abf541d97dbfd76ca7172b22cf590", 16),
-             'y': int("135e15e21f9e85c76205fd148a92ac19f9e6243ddab322d1", 16)},
-         'IUT': {
-             'd': int("a5b4bbad57f101ca48021cb7440cd681a9d40cd51b99d917", 16),
-             'x': int("79a77fcb18a32cdb59ed5d87740f29e8565d649dbf01ce86", 16),
-             'y': int("f7187efaa0b1573f1fb00905d46810b880bf738b4c720bb7", 16)},
-         'Z': int("26382468d721761e14a87dc3bee67340095c6455962d1ba3", 16),
-         'curve': 'secp192r1'},
-
-        {'errno': 8,
-         'fail': True,
-         'COUNT': 2,
-         'CAVS': {
-             'd': int("5f909dcb0ccce58c82fada748c47297579e6a981b5518a96", 16),
-             'x': int("537f1ecfda0e366de393a9bc8188fcc280311bffefe21ecf", 16),
-             'y': int("a1fa1f98498d65f2754caff4e5303a4066a5ff89fde95381", 16)},
-         'IUT': {
-             'd': int("3357aa7f47f3e09421602cc12cdce4434c68e330d44de05e", 16),
-             'x': int("6a33d43d9c72173eabc7a771a5687748c4774c62762e96ec", 16),
-             'y': int("8033f238b3abc69470aad4be8dbe4f60a2fd50207626c56a", 16)},
-         'Z': int("3153034f6617326f19c35be8c99a0585431adf09d2f8e0fd", 16),
-         'curve': 'secp192r1'},
-
-        {'errno': 13,
-         'fail': False,
-         'COUNT': 8,
-         'CAVS': {
-             'd': int("8fcfaf0524cc868fad20e50410a2205319f1327308d98dc8", 16),
-             'x': int("9b0243d80a9e328738080fb4d46bc450243d0efb7ead0c92", 16),
-             'y': int("ad5bebad7f03849693071537f60ef858cad214123beee7c7", 16)},
-         'IUT': {
-             'd': int("bba95dac90289cb68ca2b006f9757219b70579c299ad7a7d", 16),
-             'x': int("7733dc0cb365cd6312724196b9b4eb491fd4d2e31b9afdb1", 16),
-             'y': int("92ffa3722acc5b94d772258ba2d471b06c0f53f56fcd8662", 16)},
-         'Z': int("0f3c6e4a29a08296ae730f56a1ebf819ea2edfa6f0434e40", 16),
-         'curve': 'secp192r1'},
-
-        {'errno': 0,
-         'fail': False,
-         'COUNT': 0,
-         'CAVS': {
-             'd': int("e53a88af7cf8ce6bf13c8b9ad191494e37a6acc1368c71f4"
-                      "306e39e5", 16),
-             'x': int("3a24217c4b957fea922eec9d9ac52d5cb4b3fcd95efde1e4"
-                      "fa0dd6e2", 16),
-             'y': int("775b94025a808eb6f4af14ea4b57dca576c35373c6dc198b"
-                      "15b981df", 16)},
-         'IUT': {
-             'd': int("09f51e302c6a0fe6ff48f34c208c6af91e70f65f88102e6f"
-                      "cab9af4a", 16),
-             'x': int("c5d5706ccd7424c74fd616e699865af96e56f39adea6aa05"
-                      "9e5092b5", 16),
-             'y': int("f0729077bb602404d56d2f7e2ba5bb2f383df4a542556788"
-                      "1ff0165d", 16)},
-         'Z': int("b1259ceedfb663d9515089cf727e7024fb3d86cbcec611b4"
-                  "ba0b4ab6", 16),
-         'curve': 'secp224r1'},
-
-        {'errno': 2,
-         'fail': True,
-         'COUNT': 0,
-         'CAVS': {
-             'd': int("305dfb4a8850cc59280891147baf457bfe5e2bae98457163"
-                      "4a77dc8d3472fa9b", 16),
-             'x': int("202cb5a224e6c2a84e624094486edf04116c8d68ec1f4a0e"
-                      "0ed9ee090e1a900b", 16),
-             'y': int("cacf3a5789bb33954be600425d62d9eae5371f90f8816725"
-                      "8814213e4a4f4b1a", 16)},
-         'IUT': {
-             'd': int("72cc52808f294b64b6f7233c3d2f5d96cc1d29287320e39e"
-                      "1c151deef0bc14eb", 16),
-             'x': int("49a768c9a4ca56e374f685dd76a461b1016c59dcded2c8d8"
-                      "cbd9f23ca453831f", 16),
-             'y': int("b1e3bb9b5f12a3b5ae788535d4554bd8c46e0e6130075e4e"
-                      "437d3854cf8f1c34", 16)},
-         'Z': int("c0147c3c2691b450b5edc08b51aea224d9f4359ff67aab6d"
-                  "a3146f396dbceaea", 16),
-         'curve': 'secp256r1'},
-
-        {'errno': 0,
-         'fail': False,
-         'COUNT': 0,
-         'CAVS': {
-             'd': int("0e5c98ff2d2a3aab14ad0067b60dbe64e4f541ab5bed11c5"
-                      "a0c55ae1e60b51ff5faaf377837977d80cbfdc33c2ff542b", 16),
-             'x': int("d1bf2ac21637d66d6398aac01dcd56ac6f065fb45d1f6f16"
-                      "747bab9e9b01b4630b59b20927aea147355bf41838acb482", 16),
-             'y': int("4c9e23f1c5a41647d094086bf4ed31708651f21d996c4778"
-                      "0688ac10f77deee2e43b5241b6caecd2fd5444bc50472e0e", 16)},
-         'IUT': {
-             'd': int("f865418473e5bf7d2e1bbcd9bd5a9270c003a9dd35e77813"
-                      "3ca59fcab4bb64fe24d6800e7047bdd033abc8bfa8db35b5", 16),
-             'x': int("32b72ab9b558249dcbc6cbade234f58e4f7aa5d3f6420ea9"
-                      "9a5f997e8c2a91fb7fd83779d0d2169428683771c745fd1a", 16),
-             'y': int("c749e02a3719bb56bf1dfc4ba3820309c01ab6e84cb29db7"
-                      "cdd80f127233f5295687f8178f3a8704c1063b84c2ee472f", 16)},
-         'Z': int("a781430e6078a179df3f9ee27cd8fdc6188f161b6c4ccc40"
-                  "53ef6c6ca6fc222946883a53c06db08f0a020023ced055aa", 16),
-         'curve': 'secp384r1'},
-
-        {'errno': 7,
-         'fail': True,
-         'COUNT': 0,
-         'CAVS': {
-             'd': int("0000002fef62381162942889a6094a6bb9ac1f4ddf66d9cd"
-                      "a9f618232d31b90c50d7da78a47ed91d40cae946898571db"
-                      "972dc294b109815f38feee9eaac0d5f7c3250728", 16),
-             'x': int("0000004b05ffa025113390797f2736174aa1c784f4dd34e7"
-                      "64ee40d40e4d2442677ebea3498086c9473e5c92789cbdb0"
-                      "2bb327bbd61d58690f6a83d9ca73bccbde37dec4", 16),
-             'y': int("0000004da67cffc98070b82af61feba78787efefb13bd810"
-                      "d80ff92304788e49a4e5b634b3565474a8ecb1615d7b1b77"
-                      "a7a27875adb73a8a5d8f3f84e5e8b744cda250b0", 16)},
-         'IUT': {
-             'd': int("00000311a5e520e238141527671a38cb6f776d96a9f82ef7"
-                      "0dffa11dc0895f4060f1abbb9ad6fd259e4a7beaf5f7266e"
-                      "a1bb45bcbfebfda2705e5c551e710fb1d745f57e", 16),
-             'x': int("0000010ba3778cb2cc965834c0a9593adc6a222692656d65"
-                      "7fb0d15293edf0ab33762384a96a16fddea7540b7ccbcca4"
-                      "6ec4ac9bcf95fdb5aa18e158aab4d91981bd733e", 16),
-             'y': int("0000018522df93ddd636e5bc94daecdc600fa241686ec186"
-                      "34fd30b7cbdfdc9ffba1166ac08df34a31896f6fad191414"
-                      "929261ebd7187afb72919f8a0c926be37f99c1e5", 16)},
-         'Z': int("01a5e4b31be4b1346e53906b6767b1fe94ec1a8a5abc28fb"
-                  "6f01518c056959af3bc9335dddab178b52318cc551255993"
-                  "1b8dc18de0ce810c2c7f15769d7ce70e719c", 16),
-         'curve': 'secp521r1'}
+        {
+            "errno": 0,
+            "fail": False,
+            "COUNT": 0,
+            "CAVS": {
+                "d": int(
+                    "f70c297a683d6b7ef82b5af7349606c4447c8b4fc6fa5e80", 16
+                ),
+                "x": int(
+                    "f7b5061fb557e516c50abf541d97dbfd76ca7172b22cf590", 16
+                ),
+                "y": int(
+                    "135e15e21f9e85c76205fd148a92ac19f9e6243ddab322d1", 16
+                ),
+            },
+            "IUT": {
+                "d": int(
+                    "a5b4bbad57f101ca48021cb7440cd681a9d40cd51b99d917", 16
+                ),
+                "x": int(
+                    "79a77fcb18a32cdb59ed5d87740f29e8565d649dbf01ce86", 16
+                ),
+                "y": int(
+                    "f7187efaa0b1573f1fb00905d46810b880bf738b4c720bb7", 16
+                ),
+            },
+            "Z": int("26382468d721761e14a87dc3bee67340095c6455962d1ba3", 16),
+            "curve": "secp192r1",
+        },
+        {
+            "errno": 8,
+            "fail": True,
+            "COUNT": 2,
+            "CAVS": {
+                "d": int(
+                    "5f909dcb0ccce58c82fada748c47297579e6a981b5518a96", 16
+                ),
+                "x": int(
+                    "537f1ecfda0e366de393a9bc8188fcc280311bffefe21ecf", 16
+                ),
+                "y": int(
+                    "a1fa1f98498d65f2754caff4e5303a4066a5ff89fde95381", 16
+                ),
+            },
+            "IUT": {
+                "d": int(
+                    "3357aa7f47f3e09421602cc12cdce4434c68e330d44de05e", 16
+                ),
+                "x": int(
+                    "6a33d43d9c72173eabc7a771a5687748c4774c62762e96ec", 16
+                ),
+                "y": int(
+                    "8033f238b3abc69470aad4be8dbe4f60a2fd50207626c56a", 16
+                ),
+            },
+            "Z": int("3153034f6617326f19c35be8c99a0585431adf09d2f8e0fd", 16),
+            "curve": "secp192r1",
+        },
+        {
+            "errno": 13,
+            "fail": False,
+            "COUNT": 8,
+            "CAVS": {
+                "d": int(
+                    "8fcfaf0524cc868fad20e50410a2205319f1327308d98dc8", 16
+                ),
+                "x": int(
+                    "9b0243d80a9e328738080fb4d46bc450243d0efb7ead0c92", 16
+                ),
+                "y": int(
+                    "ad5bebad7f03849693071537f60ef858cad214123beee7c7", 16
+                ),
+            },
+            "IUT": {
+                "d": int(
+                    "bba95dac90289cb68ca2b006f9757219b70579c299ad7a7d", 16
+                ),
+                "x": int(
+                    "7733dc0cb365cd6312724196b9b4eb491fd4d2e31b9afdb1", 16
+                ),
+                "y": int(
+                    "92ffa3722acc5b94d772258ba2d471b06c0f53f56fcd8662", 16
+                ),
+            },
+            "Z": int("0f3c6e4a29a08296ae730f56a1ebf819ea2edfa6f0434e40", 16),
+            "curve": "secp192r1",
+        },
+        {
+            "errno": 0,
+            "fail": False,
+            "COUNT": 0,
+            "CAVS": {
+                "d": int(
+                    "e53a88af7cf8ce6bf13c8b9ad191494e37a6acc1368c71f4"
+                    "306e39e5",
+                    16,
+                ),
+                "x": int(
+                    "3a24217c4b957fea922eec9d9ac52d5cb4b3fcd95efde1e4"
+                    "fa0dd6e2",
+                    16,
+                ),
+                "y": int(
+                    "775b94025a808eb6f4af14ea4b57dca576c35373c6dc198b"
+                    "15b981df",
+                    16,
+                ),
+            },
+            "IUT": {
+                "d": int(
+                    "09f51e302c6a0fe6ff48f34c208c6af91e70f65f88102e6f"
+                    "cab9af4a",
+                    16,
+                ),
+                "x": int(
+                    "c5d5706ccd7424c74fd616e699865af96e56f39adea6aa05"
+                    "9e5092b5",
+                    16,
+                ),
+                "y": int(
+                    "f0729077bb602404d56d2f7e2ba5bb2f383df4a542556788"
+                    "1ff0165d",
+                    16,
+                ),
+            },
+            "Z": int(
+                "b1259ceedfb663d9515089cf727e7024fb3d86cbcec611b4" "ba0b4ab6",
+                16,
+            ),
+            "curve": "secp224r1",
+        },
+        {
+            "errno": 2,
+            "fail": True,
+            "COUNT": 0,
+            "CAVS": {
+                "d": int(
+                    "305dfb4a8850cc59280891147baf457bfe5e2bae98457163"
+                    "4a77dc8d3472fa9b",
+                    16,
+                ),
+                "x": int(
+                    "202cb5a224e6c2a84e624094486edf04116c8d68ec1f4a0e"
+                    "0ed9ee090e1a900b",
+                    16,
+                ),
+                "y": int(
+                    "cacf3a5789bb33954be600425d62d9eae5371f90f8816725"
+                    "8814213e4a4f4b1a",
+                    16,
+                ),
+            },
+            "IUT": {
+                "d": int(
+                    "72cc52808f294b64b6f7233c3d2f5d96cc1d29287320e39e"
+                    "1c151deef0bc14eb",
+                    16,
+                ),
+                "x": int(
+                    "49a768c9a4ca56e374f685dd76a461b1016c59dcded2c8d8"
+                    "cbd9f23ca453831f",
+                    16,
+                ),
+                "y": int(
+                    "b1e3bb9b5f12a3b5ae788535d4554bd8c46e0e6130075e4e"
+                    "437d3854cf8f1c34",
+                    16,
+                ),
+            },
+            "Z": int(
+                "c0147c3c2691b450b5edc08b51aea224d9f4359ff67aab6d"
+                "a3146f396dbceaea",
+                16,
+            ),
+            "curve": "secp256r1",
+        },
+        {
+            "errno": 0,
+            "fail": False,
+            "COUNT": 0,
+            "CAVS": {
+                "d": int(
+                    "0e5c98ff2d2a3aab14ad0067b60dbe64e4f541ab5bed11c5"
+                    "a0c55ae1e60b51ff5faaf377837977d80cbfdc33c2ff542b",
+                    16,
+                ),
+                "x": int(
+                    "d1bf2ac21637d66d6398aac01dcd56ac6f065fb45d1f6f16"
+                    "747bab9e9b01b4630b59b20927aea147355bf41838acb482",
+                    16,
+                ),
+                "y": int(
+                    "4c9e23f1c5a41647d094086bf4ed31708651f21d996c4778"
+                    "0688ac10f77deee2e43b5241b6caecd2fd5444bc50472e0e",
+                    16,
+                ),
+            },
+            "IUT": {
+                "d": int(
+                    "f865418473e5bf7d2e1bbcd9bd5a9270c003a9dd35e77813"
+                    "3ca59fcab4bb64fe24d6800e7047bdd033abc8bfa8db35b5",
+                    16,
+                ),
+                "x": int(
+                    "32b72ab9b558249dcbc6cbade234f58e4f7aa5d3f6420ea9"
+                    "9a5f997e8c2a91fb7fd83779d0d2169428683771c745fd1a",
+                    16,
+                ),
+                "y": int(
+                    "c749e02a3719bb56bf1dfc4ba3820309c01ab6e84cb29db7"
+                    "cdd80f127233f5295687f8178f3a8704c1063b84c2ee472f",
+                    16,
+                ),
+            },
+            "Z": int(
+                "a781430e6078a179df3f9ee27cd8fdc6188f161b6c4ccc40"
+                "53ef6c6ca6fc222946883a53c06db08f0a020023ced055aa",
+                16,
+            ),
+            "curve": "secp384r1",
+        },
+        {
+            "errno": 7,
+            "fail": True,
+            "COUNT": 0,
+            "CAVS": {
+                "d": int(
+                    "0000002fef62381162942889a6094a6bb9ac1f4ddf66d9cd"
+                    "a9f618232d31b90c50d7da78a47ed91d40cae946898571db"
+                    "972dc294b109815f38feee9eaac0d5f7c3250728",
+                    16,
+                ),
+                "x": int(
+                    "0000004b05ffa025113390797f2736174aa1c784f4dd34e7"
+                    "64ee40d40e4d2442677ebea3498086c9473e5c92789cbdb0"
+                    "2bb327bbd61d58690f6a83d9ca73bccbde37dec4",
+                    16,
+                ),
+                "y": int(
+                    "0000004da67cffc98070b82af61feba78787efefb13bd810"
+                    "d80ff92304788e49a4e5b634b3565474a8ecb1615d7b1b77"
+                    "a7a27875adb73a8a5d8f3f84e5e8b744cda250b0",
+                    16,
+                ),
+            },
+            "IUT": {
+                "d": int(
+                    "00000311a5e520e238141527671a38cb6f776d96a9f82ef7"
+                    "0dffa11dc0895f4060f1abbb9ad6fd259e4a7beaf5f7266e"
+                    "a1bb45bcbfebfda2705e5c551e710fb1d745f57e",
+                    16,
+                ),
+                "x": int(
+                    "0000010ba3778cb2cc965834c0a9593adc6a222692656d65"
+                    "7fb0d15293edf0ab33762384a96a16fddea7540b7ccbcca4"
+                    "6ec4ac9bcf95fdb5aa18e158aab4d91981bd733e",
+                    16,
+                ),
+                "y": int(
+                    "0000018522df93ddd636e5bc94daecdc600fa241686ec186"
+                    "34fd30b7cbdfdc9ffba1166ac08df34a31896f6fad191414"
+                    "929261ebd7187afb72919f8a0c926be37f99c1e5",
+                    16,
+                ),
+            },
+            "Z": int(
+                "01a5e4b31be4b1346e53906b6767b1fe94ec1a8a5abc28fb"
+                "6f01518c056959af3bc9335dddab178b52318cc551255993"
+                "1b8dc18de0ce810c2c7f15769d7ce70e719c",
+                16,
+            ),
+            "curve": "secp521r1",
+        },
     ]
 
     assert expected == load_kasvs_ecdh_vectors(vector_data)
 
 
 def test_load_kasvs_ecdh_kdf_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     #  Parameter set(s) supported: EB EC ED EE
     #  CAVSid: CAVSid (in hex: 434156536964)
     #  IUTid: In hex: a1b2c3d4e5
@@ -3361,39 +3967,68 @@
 ffdfa60dd7
     DKM = ad65fa2d12541c3a21f3cd223efb
     Result = F (12 - Tag changed )
-    """).splitlines()
+    """
+    ).splitlines()
 
     expected = [
-        {'errno': 12,
-         'fail': True,
-         'COUNT': 50,
-         'CAVS': {
-             'd': int("540904b67b3716823dd621ed72ad3dbc615887b4f56f910b"
-                      "78a57199", 16),
-             'x': int("28e5f3a72d8f6b8499dd1bcdfceafcecec68a0d715789bcf"
-                      "4b55fe15", 16),
-             'y': int("8c8006a7da7c1a19f5328d7e865522b0c0dfb9a29b2c46dc"
-                      "96590d2a", 16)},
-         'IUT': {
-             'd': int("5e717ae889fc8d67be11c2ebe1a7d3550051448d68a040b2"
-                      "dee8e327", 16),
-             'x': int("ae7f3db340b647d61713f5374c019f1be2b28573cb6219bb"
-                      "7b747223", 16),
-             'y': int("800e6bffcf97c15864ec6e5673fb83359b45f89b8a26a27f"
-                      "6f3dfbff", 16)},
-         'OI': int("a1b2c3d4e5bb7f1b40d14ebd70443393990b574341565369"
-                   "645b1582daab9cc6c30d61fdcf1cdfc7e9a304651e0fdb", 16),
-         'Z': int("43f23b2c760d686fc99cc008b63aea92f866e224265af60d"
-                  "2d8ae540", 16),
-         'DKM': int("ad65fa2d12541c3a21f3cd223efb", 16),
-         'curve': 'secp224r1'}
+        {
+            "errno": 12,
+            "fail": True,
+            "COUNT": 50,
+            "CAVS": {
+                "d": int(
+                    "540904b67b3716823dd621ed72ad3dbc615887b4f56f910b"
+                    "78a57199",
+                    16,
+                ),
+                "x": int(
+                    "28e5f3a72d8f6b8499dd1bcdfceafcecec68a0d715789bcf"
+                    "4b55fe15",
+                    16,
+                ),
+                "y": int(
+                    "8c8006a7da7c1a19f5328d7e865522b0c0dfb9a29b2c46dc"
+                    "96590d2a",
+                    16,
+                ),
+            },
+            "IUT": {
+                "d": int(
+                    "5e717ae889fc8d67be11c2ebe1a7d3550051448d68a040b2"
+                    "dee8e327",
+                    16,
+                ),
+                "x": int(
+                    "ae7f3db340b647d61713f5374c019f1be2b28573cb6219bb"
+                    "7b747223",
+                    16,
+                ),
+                "y": int(
+                    "800e6bffcf97c15864ec6e5673fb83359b45f89b8a26a27f"
+                    "6f3dfbff",
+                    16,
+                ),
+            },
+            "OI": int(
+                "a1b2c3d4e5bb7f1b40d14ebd70443393990b574341565369"
+                "645b1582daab9cc6c30d61fdcf1cdfc7e9a304651e0fdb",
+                16,
+            ),
+            "Z": int(
+                "43f23b2c760d686fc99cc008b63aea92f866e224265af60d" "2d8ae540",
+                16,
+            ),
+            "DKM": int("ad65fa2d12541c3a21f3cd223efb", 16),
+            "curve": "secp224r1",
+        }
     ]
 
     assert expected == load_kasvs_ecdh_vectors(vector_data)
 
 
 def test_load_x963_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     # CAVS 12.0
     # 'ANS X9.63-2001' information for sample
 
@@ -3443,37 +4078,48 @@
 d6e4dd2a599acceb3ea54a6217ce0b50eef4f6b40a5c30250a5a8eeee208002267089dbf351f3f\
 5022aa9638bf1ee419dea9c4ff745a25ac27bda33ca08bd56dd1a59b4106cf2dbbc0ab2aa8e2ef\
 a7b17902d34276951ceccab87f9661c3e8816
-    """).splitlines()
+    """
+    ).splitlines()
 
     assert load_x963_vectors(vector_data) == [
-        {"hash": "SHA-1", "count": 0,
-         "shared_secret_length": 192,
-         "Z": "1c7d7b5f0597b03d06a018466ed1a93e30ed4b04dc64ccdd",
-         "sharedinfo_length": 0,
-         "key_data_length": 128,
-         "key_data": "bf71dffd8f4d99223936beb46fee8ccc"},
-        {"hash": "SHA-1", "count": 1,
-         "shared_secret_length": 192,
-         "Z": "5ed096510e3fcf782ceea98e9737993e2b21370f6cda2ab1",
-         "sharedinfo_length": 0,
-         "key_data_length": 128,
-         "key_data": "ec3e224446bfd7b3be1df404104af953"},
-        {"hash": "SHA-512", "count": 0,
-         "shared_secret_length": 521,
-         "Z": "00aa5bb79b33e389fa58ceadc047197f14e73712f452caa9fc4c9adb369348b\
+        {
+            "hash": "SHA-1",
+            "count": 0,
+            "shared_secret_length": 192,
+            "Z": "1c7d7b5f0597b03d06a018466ed1a93e30ed4b04dc64ccdd",
+            "sharedinfo_length": 0,
+            "key_data_length": 128,
+            "key_data": "bf71dffd8f4d99223936beb46fee8ccc",
+        },
+        {
+            "hash": "SHA-1",
+            "count": 1,
+            "shared_secret_length": 192,
+            "Z": "5ed096510e3fcf782ceea98e9737993e2b21370f6cda2ab1",
+            "sharedinfo_length": 0,
+            "key_data_length": 128,
+            "key_data": "ec3e224446bfd7b3be1df404104af953",
+        },
+        {
+            "hash": "SHA-512",
+            "count": 0,
+            "shared_secret_length": 521,
+            "Z": "00aa5bb79b33e389fa58ceadc047197f14e73712f452caa9fc4c9adb369348b\
 81507392f1a86ddfdb7c4ff8231c4bd0f44e44a1b55b1404747a9e2e753f55ef05a2d",
-         "sharedinfo_length": 128,
-         "sharedinfo": "e3b5b4c1b0d5cf1d2b3a2f9937895d31",
-         "key_data_length": 1024,
-         "key_data": "4463f869f3cc18769b52264b0112b5858f7ad32a5a2d96d8cffabf7f\
+            "sharedinfo_length": 128,
+            "sharedinfo": "e3b5b4c1b0d5cf1d2b3a2f9937895d31",
+            "key_data_length": 1024,
+            "key_data": "4463f869f3cc18769b52264b0112b5858f7ad32a5a2d96d8cffabf7f\
 a733633d6e4dd2a599acceb3ea54a6217ce0b50eef4f6b40a5c30250a5a8eeee208002267089db\
 f351f3f5022aa9638bf1ee419dea9c4ff745a25ac27bda33ca08bd56dd1a59b4106cf2dbbc0ab2\
-aa8e2efa7b17902d34276951ceccab87f9661c3e8816"},
+aa8e2efa7b17902d34276951ceccab87f9661c3e8816",
+        },
     ]
 
 
 def test_load_kbkdf_vectors():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     # CAVS 14.4
     # "SP800-108 - KDF" information for "test1"
     # KDF Mode Supported: Counter Mode
@@ -3523,50 +4169,58 @@
         instring = 7f50fc1f77c3ac752443154c1577d3c47b86fccffe82ff43aa1b91eeb5\
 730d7e9e6aab78374d854aecb7143faba6b1eb90d3d9e7a2f6d78dd9a6c4a701
     KO = b8894c6133a46701909b5c8a84322dec
-    """).splitlines()
+    """
+    ).splitlines()
 
     assert load_nist_kbkdf_vectors(vector_data) == [
-        {'prf': 'hmac_sha1',
-         'ctrlocation': 'before_fixed',
-         'rlen': 8,
-         'l': 128,
-         'ki': b'00a39bd547fb88b2d98727cf64c195c61e1cad6c',
-         'fixedinputdatabytelen': b'60',
-         'fixedinputdata': b'98132c1ffaf59ae5cbc0a3133d84c551bb97e0c75ecaddfc\
-30056f6876f59803009bffc7d75c4ed46f40b8f80426750d15bc1ddb14ac5dcb69a68242',
-         'binary rep of i': b'01',
-         'instring': b'0198132c1ffaf59ae5cbc0a3133d84c551bb97e0c75ecaddfc3005\
-6f6876f59803009bffc7d75c4ed46f40b8f80426750d15bc1ddb14ac5dcb69a68242',
-         'ko': b'0611e1903609b47ad7a5fc2c82e47702'},
-        {'prf': 'hmac_sha1',
-         'ctrlocation': 'before_fixed',
-         'rlen': 8,
-         'l': 128,
-         'ki': b'a39bdf744ed7e33fdec060c8736e9725179885a8',
-         'fixedinputdatabytelen': b'60',
-         'fixedinputdata': b'af71b44940acff98949ad17f1ca20e8fdb3957cacdcd41e9\
-c591e18235019f90b9f8ee6e75700bcab2f8407525a104799b3e9725e27d738a9045e832',
-         'binary rep of i': b'01',
-         'instring': b'01af71b44940acff98949ad17f1ca20e8fdb3957cacdcd41e9c591\
-e18235019f90b9f8ee6e75700bcab2f8407525a104799b3e9725e27d738a9045e832',
-         'ko': b'51dc4668947e3685099bc3b5f8527468'},
-        {'prf': 'hmac_sha224',
-         'ctrlocation': 'after_fixed',
-         'rlen': 8,
-         'l': 128,
-         'ki': b'ab56556b107a3a79fe084df0f1bb3ad049a6cc1490f20da4b3df282c',
-         'fixedinputdatabytelen': b'60',
-         'fixedinputdata': b'7f50fc1f77c3ac752443154c1577d3c47b86fccffe82ff43\
-aa1b91eeb5730d7e9e6aab78374d854aecb7143faba6b1eb90d3d9e7a2f6d78dd9a6c4a7',
-         'binary rep of i': b'01',
-         'instring': b'7f50fc1f77c3ac752443154c1577d3c47b86fccffe82ff43aa1b91\
-eeb5730d7e9e6aab78374d854aecb7143faba6b1eb90d3d9e7a2f6d78dd9a6c4a701',
-         'ko': b'b8894c6133a46701909b5c8a84322dec'}
+        {
+            "prf": "hmac_sha1",
+            "ctrlocation": "before_fixed",
+            "rlen": 8,
+            "l": 128,
+            "ki": b"00a39bd547fb88b2d98727cf64c195c61e1cad6c",
+            "fixedinputdatabytelen": b"60",
+            "fixedinputdata": b"98132c1ffaf59ae5cbc0a3133d84c551bb97e0c75ecaddfc\
+30056f6876f59803009bffc7d75c4ed46f40b8f80426750d15bc1ddb14ac5dcb69a68242",
+            "binary rep of i": b"01",
+            "instring": b"0198132c1ffaf59ae5cbc0a3133d84c551bb97e0c75ecaddfc3005\
+6f6876f59803009bffc7d75c4ed46f40b8f80426750d15bc1ddb14ac5dcb69a68242",
+            "ko": b"0611e1903609b47ad7a5fc2c82e47702",
+        },
+        {
+            "prf": "hmac_sha1",
+            "ctrlocation": "before_fixed",
+            "rlen": 8,
+            "l": 128,
+            "ki": b"a39bdf744ed7e33fdec060c8736e9725179885a8",
+            "fixedinputdatabytelen": b"60",
+            "fixedinputdata": b"af71b44940acff98949ad17f1ca20e8fdb3957cacdcd41e9\
+c591e18235019f90b9f8ee6e75700bcab2f8407525a104799b3e9725e27d738a9045e832",
+            "binary rep of i": b"01",
+            "instring": b"01af71b44940acff98949ad17f1ca20e8fdb3957cacdcd41e9c591\
+e18235019f90b9f8ee6e75700bcab2f8407525a104799b3e9725e27d738a9045e832",
+            "ko": b"51dc4668947e3685099bc3b5f8527468",
+        },
+        {
+            "prf": "hmac_sha224",
+            "ctrlocation": "after_fixed",
+            "rlen": 8,
+            "l": 128,
+            "ki": b"ab56556b107a3a79fe084df0f1bb3ad049a6cc1490f20da4b3df282c",
+            "fixedinputdatabytelen": b"60",
+            "fixedinputdata": b"7f50fc1f77c3ac752443154c1577d3c47b86fccffe82ff43\
+aa1b91eeb5730d7e9e6aab78374d854aecb7143faba6b1eb90d3d9e7a2f6d78dd9a6c4a7",
+            "binary rep of i": b"01",
+            "instring": b"7f50fc1f77c3ac752443154c1577d3c47b86fccffe82ff43aa1b91\
+eeb5730d7e9e6aab78374d854aecb7143faba6b1eb90d3d9e7a2f6d78dd9a6c4a701",
+            "ko": b"b8894c6133a46701909b5c8a84322dec",
+        },
     ]
 
 
 def test_load_nist_ccm_vectors_dvpt():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     #  CAVS 11.0
     #  "CCM-DVPT" information
     #  AES Keylen: 128
@@ -3606,61 +4260,63 @@
     Adata = 00
     CT = 3a65e03af37b81d05acc7ec1bc39deb0
     Result = Fail
-    """).splitlines()
+    """
+    ).splitlines()
     assert load_nist_ccm_vectors(vector_data) == [
         {
-            'key': b'4ae701103c63deca5b5a3939d7d05992',
-            'alen': 0,
-            'plen': 0,
-            'nlen': 7,
-            'tlen': 4,
-            'nonce': b'5a8aa485c316e9',
-            'adata': b'00',
-            'ct': b'02209f55',
-            'fail': False,
-            'payload': b'00'
+            "key": b"4ae701103c63deca5b5a3939d7d05992",
+            "alen": 0,
+            "plen": 0,
+            "nlen": 7,
+            "tlen": 4,
+            "nonce": b"5a8aa485c316e9",
+            "adata": b"00",
+            "ct": b"02209f55",
+            "fail": False,
+            "payload": b"00",
         },
         {
-            'key': b'4ae701103c63deca5b5a3939d7d05992',
-            'alen': 0,
-            'plen': 0,
-            'nlen': 7,
-            'tlen': 4,
-            'nonce': b'3796cf51b87266',
-            'adata': b'00',
-            'ct': b'9a04c241',
-            'fail': True,
-            'payload': b'00'
+            "key": b"4ae701103c63deca5b5a3939d7d05992",
+            "alen": 0,
+            "plen": 0,
+            "nlen": 7,
+            "tlen": 4,
+            "nonce": b"3796cf51b87266",
+            "adata": b"00",
+            "ct": b"9a04c241",
+            "fail": True,
+            "payload": b"00",
         },
         {
-            'key': b'4bb3c4a4f893ad8c9bdc833c325d62b3',
-            'alen': 0,
-            'plen': 0,
-            'nlen': 7,
-            'tlen': 16,
-            'nonce': b'5a8aa485c316e9',
-            'adata': b'00',
-            'ct': b'75d582db43ce9b13ab4b6f7f14341330',
-            'fail': False,
-            'payload': b'00'
+            "key": b"4bb3c4a4f893ad8c9bdc833c325d62b3",
+            "alen": 0,
+            "plen": 0,
+            "nlen": 7,
+            "tlen": 16,
+            "nonce": b"5a8aa485c316e9",
+            "adata": b"00",
+            "ct": b"75d582db43ce9b13ab4b6f7f14341330",
+            "fail": False,
+            "payload": b"00",
         },
         {
-            'key': b'4bb3c4a4f893ad8c9bdc833c325d62b3',
-            'alen': 0,
-            'plen': 0,
-            'nlen': 7,
-            'tlen': 16,
-            'nonce': b'3796cf51b87266',
-            'adata': b'00',
-            'ct': b'3a65e03af37b81d05acc7ec1bc39deb0',
-            'fail': True,
-            'payload': b'00'
-        }
+            "key": b"4bb3c4a4f893ad8c9bdc833c325d62b3",
+            "alen": 0,
+            "plen": 0,
+            "nlen": 7,
+            "tlen": 16,
+            "nonce": b"3796cf51b87266",
+            "adata": b"00",
+            "ct": b"3a65e03af37b81d05acc7ec1bc39deb0",
+            "fail": True,
+            "payload": b"00",
+        },
     ]
 
 
 def test_load_nist_ccm_vectors_vadt():
-    vector_data = textwrap.dedent("""
+    vector_data = textwrap.dedent(
+        """
     #  CAVS 11.0
     #  "CCM-VADT" information
     #  AES Keylen: 128
@@ -3700,52 +4356,53 @@
     Adata = c5
     Payload = 032fee9dbffccc751e6a1ee6d07bb218b3a7ec6bf5740ead
     CT = f0828917020651c085e42459c544ec52e99372005362baf308ebe
-    """).splitlines()
+    """
+    ).splitlines()
     assert load_nist_ccm_vectors(vector_data) == [
         {
-            'plen': 24,
-            'nlen': 13,
-            'tlen': 16,
-            'alen': 0,
-            'key': b'd24a3d3dde8c84830280cb87abad0bb3',
-            'nonce': b'f1100035bb24a8d26004e0e24b',
-            'adata': b'00',
-            'payload': b'7c86135ed9c2a515aaae0e9a208133897269220f30870006',
-            'ct': b'1faeb0ee2ca2cd52f0aa3966578344f24e69b742c4ab37ab11233'
+            "plen": 24,
+            "nlen": 13,
+            "tlen": 16,
+            "alen": 0,
+            "key": b"d24a3d3dde8c84830280cb87abad0bb3",
+            "nonce": b"f1100035bb24a8d26004e0e24b",
+            "adata": b"00",
+            "payload": b"7c86135ed9c2a515aaae0e9a208133897269220f30870006",
+            "ct": b"1faeb0ee2ca2cd52f0aa3966578344f24e69b742c4ab37ab11233",
         },
         {
-            'plen': 24,
-            'nlen': 13,
-            'tlen': 16,
-            'alen': 0,
-            'key': b'd24a3d3dde8c84830280cb87abad0bb3',
-            'nonce': b'f1100035bb24a8d26004e0e24b',
-            'adata': b'00',
-            'payload': b'48df73208cdc63d716752df7794807b1b2a80794a2433455',
-            'ct': b'642145210f947bc4a0b1e678fd8c990c2c1d89d4110a95c954d61'
+            "plen": 24,
+            "nlen": 13,
+            "tlen": 16,
+            "alen": 0,
+            "key": b"d24a3d3dde8c84830280cb87abad0bb3",
+            "nonce": b"f1100035bb24a8d26004e0e24b",
+            "adata": b"00",
+            "payload": b"48df73208cdc63d716752df7794807b1b2a80794a2433455",
+            "ct": b"642145210f947bc4a0b1e678fd8c990c2c1d89d4110a95c954d61",
         },
         {
-            'plen': 24,
-            'nlen': 13,
-            'tlen': 16,
-            'alen': 1,
-            'key': b'08b0da255d2083808a1b4d367090bacc',
-            'nonce': b'777828b13679a9e2ca89568233',
-            'adata': b'dd',
-            'payload': b'1b156d7e2bf7c9a25ad91cff7b0b02161cb78ff9162286b0',
-            'ct': b'e8b80af4960d5417c15726406e345c5c46831192b03432eed16b6'
+            "plen": 24,
+            "nlen": 13,
+            "tlen": 16,
+            "alen": 1,
+            "key": b"08b0da255d2083808a1b4d367090bacc",
+            "nonce": b"777828b13679a9e2ca89568233",
+            "adata": b"dd",
+            "payload": b"1b156d7e2bf7c9a25ad91cff7b0b02161cb78ff9162286b0",
+            "ct": b"e8b80af4960d5417c15726406e345c5c46831192b03432eed16b6",
         },
         {
-            'plen': 24,
-            'nlen': 13,
-            'tlen': 16,
-            'alen': 1,
-            'key': b'08b0da255d2083808a1b4d367090bacc',
-            'nonce': b'777828b13679a9e2ca89568233',
-            'adata': b'c5',
-            'payload': b'032fee9dbffccc751e6a1ee6d07bb218b3a7ec6bf5740ead',
-            'ct': b'f0828917020651c085e42459c544ec52e99372005362baf308ebe'
-        }
+            "plen": 24,
+            "nlen": 13,
+            "tlen": 16,
+            "alen": 1,
+            "key": b"08b0da255d2083808a1b4d367090bacc",
+            "nonce": b"777828b13679a9e2ca89568233",
+            "adata": b"c5",
+            "payload": b"032fee9dbffccc751e6a1ee6d07bb218b3a7ec6bf5740ead",
+            "ct": b"f0828917020651c085e42459c544ec52e99372005362baf308ebe",
+        },
     ]
 
 
@@ -3767,16 +4424,15 @@
     # Check that it fails if the wrong reason code is raised.
     with pytest.raises(AssertionError):
         with raises_unsupported_algorithm(None):
-            raise UnsupportedAlgorithm("An error.",
-                                       _Reasons.BACKEND_MISSING_INTERFACE)
+            raise UnsupportedAlgorithm(
+                "An error.", _Reasons.BACKEND_MISSING_INTERFACE
+            )
 
 
 def test_raises_unsupported_no_exc():
     # Check that it fails if no exception is raised.
     with pytest.raises(pytest.fail.Exception):
-        with raises_unsupported_algorithm(
-            _Reasons.BACKEND_MISSING_INTERFACE
-        ):
+        with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE):
             pass
 
 
@@ -3785,6 +4441,7 @@
     with raises_unsupported_algorithm(
         _Reasons.BACKEND_MISSING_INTERFACE
     ) as exc_info:
-        raise UnsupportedAlgorithm("An error.",
-                                   _Reasons.BACKEND_MISSING_INTERFACE)
+        raise UnsupportedAlgorithm(
+            "An error.", _Reasons.BACKEND_MISSING_INTERFACE
+        )
     assert exc_info.type is UnsupportedAlgorithm
diff --git a/tests/test_warnings.py b/tests/test_warnings.py
index d27e757..073c699 100644
--- a/tests/test_warnings.py
+++ b/tests/test_warnings.py
@@ -21,7 +21,7 @@
             value=1,
             module_name=mod.__name__,
             message="deprecated message text",
-            warning_class=DeprecationWarning
+            warning_class=DeprecationWarning,
         )
         mod.Y = deprecated(
             value=2,
@@ -55,7 +55,7 @@
             value=1,
             module_name=mod.__name__,
             message="deprecated message text",
-            warning_class=DeprecationWarning
+            warning_class=DeprecationWarning,
         )
         mod.Y = deprecated(
             value=2,
diff --git a/tests/utils.py b/tests/utils.py
index b481280..497fde8 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -7,7 +7,6 @@
 import binascii
 import collections
 import json
-import math
 import os
 import re
 from contextlib import contextmanager
@@ -30,9 +29,7 @@
 def check_backend_support(backend, item):
     for mark in item.node.iter_markers("supported"):
         if not mark.kwargs["only_if"](backend):
-            pytest.skip("{0} ({1})".format(
-                mark.kwargs["skip_message"], backend
-            ))
+            pytest.skip("{} ({})".format(mark.kwargs["skip_message"], backend))
 
 
 @contextmanager
@@ -56,8 +53,11 @@
         line = line.strip()
 
         # Blank lines, comments, and section headers are ignored
-        if not line or line.startswith("#") or (line.startswith("[") and
-                                                line.endswith("]")):
+        if (
+            not line
+            or line.startswith("#")
+            or (line.startswith("[") and line.endswith("]"))
+        ):
             continue
 
         if line.strip() == "FAIL":
@@ -102,11 +102,9 @@
             ct = line.split(" : ")[1].replace(" ", "").encode("ascii")
             # after a C is found the K+P+C tuple is complete
             # there are many P+C pairs for each K
-            cryptrec_list.append({
-                "key": key,
-                "plaintext": pt,
-                "ciphertext": ct
-            })
+            cryptrec_list.append(
+                {"key": key, "plaintext": pt, "ciphertext": ct}
+            )
         else:
             raise ValueError("Invalid line in file '{}'".format(line))
     return cryptrec_list
@@ -164,9 +162,9 @@
     vectors = []
     for line in vector_data:
         if (
-            line.startswith("# PSS Example") or
-            line.startswith("# OAEP Example") or
-            line.startswith("# PKCS#1 v1.5")
+            line.startswith("# PSS Example")
+            or line.startswith("# OAEP Example")
+            or line.startswith("# PKCS#1 v1.5")
         ):
             if example_vector:
                 for key, value in six.iteritems(example_vector):
@@ -192,9 +190,8 @@
         elif line.startswith("# Encryption"):
             attr = "encryption"
             continue
-        elif (
-            example_vector and
-            line.startswith("# =============================================")
+        elif example_vector and line.startswith(
+            "# ============================================="
         ):
             for key, value in six.iteritems(example_vector):
                 hex_str = "".join(value).replace(" ", "").encode("ascii")
@@ -209,9 +206,8 @@
                 example_vector[attr].append(line.strip())
                 continue
 
-        if (
-            line.startswith("# Example") or
-            line.startswith("# =============================================")
+        if line.startswith("# Example") or line.startswith(
+            "# ============================================="
         ):
             if key:
                 assert private_key_vector
@@ -229,18 +225,16 @@
                 examples = []
 
                 assert (
-                    private_key_vector['public_exponent'] ==
-                    public_key_vector['public_exponent']
+                    private_key_vector["public_exponent"]
+                    == public_key_vector["public_exponent"]
                 )
 
                 assert (
-                    private_key_vector['modulus'] ==
-                    public_key_vector['modulus']
+                    private_key_vector["modulus"]
+                    == public_key_vector["modulus"]
                 )
 
-                vectors.append(
-                    (private_key_vector, public_key_vector)
-                )
+                vectors.append((private_key_vector, public_key_vector))
 
             public_key_vector = collections.defaultdict(list)
             private_key_vector = collections.defaultdict(list)
@@ -322,15 +316,10 @@
                     "public_exponent": e,
                     "salt_length": salt_length,
                     "algorithm": value,
-                    "fail": False
+                    "fail": False,
                 }
             else:
-                test_data = {
-                    "modulus": n,
-                    "p": p,
-                    "q": q,
-                    "algorithm": value
-                }
+                test_data = {"modulus": n, "p": p, "q": q, "algorithm": value}
                 if salt_length is not None:
                     test_data["salt_length"] = salt_length
             data.append(test_data)
@@ -360,21 +349,24 @@
             continue
 
         if line.startswith("P"):
-            vectors.append({'p': int(line.split("=")[1], 16)})
+            vectors.append({"p": int(line.split("=")[1], 16)})
         elif line.startswith("Q"):
-            vectors[-1]['q'] = int(line.split("=")[1], 16)
+            vectors[-1]["q"] = int(line.split("=")[1], 16)
         elif line.startswith("G"):
-            vectors[-1]['g'] = int(line.split("=")[1], 16)
-        elif line.startswith("X") and 'x' not in vectors[-1]:
-            vectors[-1]['x'] = int(line.split("=")[1], 16)
-        elif line.startswith("X") and 'x' in vectors[-1]:
-            vectors.append({'p': vectors[-1]['p'],
-                            'q': vectors[-1]['q'],
-                            'g': vectors[-1]['g'],
-                            'x': int(line.split("=")[1], 16)
-                            })
+            vectors[-1]["g"] = int(line.split("=")[1], 16)
+        elif line.startswith("X") and "x" not in vectors[-1]:
+            vectors[-1]["x"] = int(line.split("=")[1], 16)
+        elif line.startswith("X") and "x" in vectors[-1]:
+            vectors.append(
+                {
+                    "p": vectors[-1]["p"],
+                    "q": vectors[-1]["q"],
+                    "g": vectors[-1]["g"],
+                    "x": int(line.split("=")[1], 16),
+                }
+            )
         elif line.startswith("Y"):
-            vectors[-1]['y'] = int(line.split("=")[1], 16)
+            vectors[-1]["y"] = int(line.split("=")[1], 16)
 
     return vectors
 
@@ -396,7 +388,7 @@
 
         sha_match = sha_regex.match(line)
         if sha_match:
-            digest_algorithm = "SHA-{0}".format(sha_match.group("sha"))
+            digest_algorithm = "SHA-{}".format(sha_match.group("sha"))
 
         if line.startswith("[mod"):
             continue
@@ -404,33 +396,37 @@
         name, value = [c.strip() for c in line.split("=")]
 
         if name == "P":
-            vectors.append({'p': int(value, 16),
-                            'digest_algorithm': digest_algorithm})
+            vectors.append(
+                {"p": int(value, 16), "digest_algorithm": digest_algorithm}
+            )
         elif name == "Q":
-            vectors[-1]['q'] = int(value, 16)
+            vectors[-1]["q"] = int(value, 16)
         elif name == "G":
-            vectors[-1]['g'] = int(value, 16)
-        elif name == "Msg" and 'msg' not in vectors[-1]:
+            vectors[-1]["g"] = int(value, 16)
+        elif name == "Msg" and "msg" not in vectors[-1]:
             hexmsg = value.strip().encode("ascii")
-            vectors[-1]['msg'] = binascii.unhexlify(hexmsg)
-        elif name == "Msg" and 'msg' in vectors[-1]:
+            vectors[-1]["msg"] = binascii.unhexlify(hexmsg)
+        elif name == "Msg" and "msg" in vectors[-1]:
             hexmsg = value.strip().encode("ascii")
-            vectors.append({'p': vectors[-1]['p'],
-                            'q': vectors[-1]['q'],
-                            'g': vectors[-1]['g'],
-                            'digest_algorithm':
-                            vectors[-1]['digest_algorithm'],
-                            'msg': binascii.unhexlify(hexmsg)})
+            vectors.append(
+                {
+                    "p": vectors[-1]["p"],
+                    "q": vectors[-1]["q"],
+                    "g": vectors[-1]["g"],
+                    "digest_algorithm": vectors[-1]["digest_algorithm"],
+                    "msg": binascii.unhexlify(hexmsg),
+                }
+            )
         elif name == "X":
-            vectors[-1]['x'] = int(value, 16)
+            vectors[-1]["x"] = int(value, 16)
         elif name == "Y":
-            vectors[-1]['y'] = int(value, 16)
+            vectors[-1]["y"] = int(value, 16)
         elif name == "R":
-            vectors[-1]['r'] = int(value, 16)
+            vectors[-1]["r"] = int(value, 16)
         elif name == "S":
-            vectors[-1]['s'] = int(value, 16)
+            vectors[-1]["s"] = int(value, 16)
         elif name == "Result":
-            vectors[-1]['result'] = value.split("(")[0].strip()
+            vectors[-1]["result"] = value.split("(")[0].strip()
 
     return vectors
 
@@ -442,14 +438,12 @@
     "P-256": "secp256r1",
     "P-384": "secp384r1",
     "P-521": "secp521r1",
-
     "K-163": "sect163k1",
     "K-233": "sect233k1",
     "K-256": "secp256k1",
     "K-283": "sect283k1",
     "K-409": "sect409k1",
     "K-571": "sect571k1",
-
     "B-163": "sect163r2",
     "B-233": "sect233r1",
     "B-283": "sect283r1",
@@ -477,10 +471,7 @@
             if key_data is not None:
                 vectors.append(key_data)
 
-            key_data = {
-                "curve": curve_name,
-                "d": int(line.split("=")[1], 16)
-            }
+            key_data = {"curve": curve_name, "d": int(line.split("=")[1], 16)}
 
         elif key_data is not None:
             if line.startswith("Qx = "):
@@ -511,7 +502,7 @@
         curve_match = curve_rx.match(line)
         if curve_match:
             curve_name = _ECDSA_CURVE_NAMES[curve_match.group("curve")]
-            digest_name = "SHA-{0}".format(curve_match.group("sha"))
+            digest_name = "SHA-{}".format(curve_match.group("sha"))
 
         elif line.startswith("Msg = "):
             if data is not None:
@@ -522,7 +513,7 @@
             data = {
                 "curve": curve_name,
                 "digest_algorithm": digest_name,
-                "message": binascii.unhexlify(hexmsg)
+                "message": binascii.unhexlify(hexmsg),
             }
 
         elif data is not None:
@@ -552,10 +543,7 @@
     result_rx = re.compile(r"([FP]) \(([0-9]+) -")
 
     vectors = []
-    data = {
-        "fail_z": False,
-        "fail_agree": False
-    }
+    data = {"fail_z": False, "fail_agree": False}
 
     for line in vector_data:
         line = line.strip()
@@ -597,7 +585,7 @@
                 "q": data["q"],
                 "g": data["g"],
                 "fail_z": False,
-                "fail_agree": False
+                "fail_agree": False,
             }
 
     return vectors
@@ -647,7 +635,7 @@
             tag = line
             curve = None
         elif line.startswith("[Curve selected:"):
-            curve = curve_name_map[line.split(':')[1].strip()[:-1]]
+            curve = curve_name_map[line.split(":")[1].strip()[:-1]]
 
         if tag is not None and curve is not None:
             sets[tag.strip("[]")] = curve
@@ -744,15 +732,15 @@
             vector["key_data_length"] = key_data_len
         elif line.startswith("Z"):
             vector["Z"] = line.split("=")[1].strip()
-            assert math.ceil(shared_secret_len / 8) * 2 == len(vector["Z"])
+            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()
                 silen = len(vector["sharedinfo"])
-                assert math.ceil(shared_info_len / 8) * 2 == silen
+                assert ((shared_info_len + 7) // 8) * 2 == silen
         elif line.startswith("key_data"):
             vector["key_data"] = line.split("=")[1].strip()
-            assert math.ceil(key_data_len / 8) * 2 == len(vector["key_data"])
+            assert ((key_data_len + 7) // 8) * 2 == len(vector["key_data"])
             vectors.append(vector)
             vector = {}
 
@@ -776,14 +764,14 @@
         if line.startswith("[") and line.endswith("]"):
             tag_data = line[1:-1]
             name, value = [c.strip() for c in tag_data.split("=")]
-            if value.endswith('_BITS'):
-                value = int(value.split('_')[0])
+            if value.endswith("_BITS"):
+                value = int(value.split("_")[0])
                 tag.update({name.lower(): value})
                 continue
 
             tag.update({name.lower(): value.lower()})
         elif line.startswith("COUNT="):
-            test_data = dict()
+            test_data = {}
             test_data.update(tag)
             vectors.append(test_data)
         elif line.startswith("L"):
@@ -799,17 +787,19 @@
 def load_ed25519_vectors(vector_data):
     data = []
     for line in vector_data:
-        secret_key, public_key, message, signature, _ = line.split(':')
+        secret_key, public_key, message, signature, _ = line.split(":")
         # In the vectors the first element is secret key + public key
         secret_key = secret_key[0:64]
         # In the vectors the signature section is signature + message
         signature = signature[0:128]
-        data.append({
-            "secret_key": secret_key,
-            "public_key": public_key,
-            "message": message,
-            "signature": signature
-        })
+        data.append(
+            {
+                "secret_key": secret_key,
+                "public_key": public_key,
+                "message": message,
+                "signature": signature,
+            }
+        )
     return data
 
 
@@ -887,13 +877,17 @@
 
 
 class WycheproofTest(object):
-    def __init__(self, testgroup, testcase):
+    def __init__(self, testfiledata, testgroup, testcase):
+        self.testfiledata = testfiledata
         self.testgroup = testgroup
         self.testcase = testcase
 
     def __repr__(self):
-        return "<WycheproofTest({!r}, {!r}, tcId={})>".format(
-            self.testgroup, self.testcase, self.testcase["tcId"],
+        return "<WycheproofTest({!r}, {!r}, {!r}, tcId={})>".format(
+            self.testfiledata,
+            self.testgroup,
+            self.testcase,
+            self.testcase["tcId"],
         )
 
     @property
@@ -912,18 +906,11 @@
         return flag in self.testcase["flags"]
 
 
-def skip_if_wycheproof_none(wycheproof):
-    # This is factored into its own function so we can easily test both
-    # branches
-    if wycheproof is None:
-        pytest.skip("--wycheproof-root not provided")
-
-
 def load_wycheproof_tests(wycheproof, test_file):
     path = os.path.join(wycheproof, "testvectors", test_file)
     with open(path) as f:
         data = json.load(f)
-        for group in data["testGroups"]:
+        for group in data.pop("testGroups"):
             cases = group.pop("tests")
             for c in cases:
-                yield WycheproofTest(group, c)
+                yield WycheproofTest(data, group, c)
diff --git a/tests/wycheproof/test_aes.py b/tests/wycheproof/test_aes.py
index 55e4545..9992095 100644
--- a/tests/wycheproof/test_aes.py
+++ b/tests/wycheproof/test_aes.py
@@ -11,9 +11,7 @@
 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 import Cipher, algorithms, modes
 from cryptography.hazmat.primitives.ciphers.aead import AESCCM, AESGCM
 
 from ..hazmat.primitives.test_aead import _aead_supported
@@ -31,8 +29,9 @@
 
     cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend)
     enc = cipher.encryptor()
-    computed_ct = enc.update(
-        padder.update(msg) + padder.finalize()) + enc.finalize()
+    computed_ct = (
+        enc.update(padder.update(msg) + padder.finalize()) + enc.finalize()
+    )
     dec = cipher.decryptor()
     padded_msg = dec.update(ct) + dec.finalize()
     unpadder = padding.PKCS7(128).unpadder()
@@ -55,6 +54,15 @@
     msg = binascii.unhexlify(wycheproof.testcase["msg"])
     ct = binascii.unhexlify(wycheproof.testcase["ct"])
     tag = binascii.unhexlify(wycheproof.testcase["tag"])
+    if len(iv) < 8 or len(iv) > 128:
+        pytest.skip(
+            "Less than 64-bit IVs (and greater than 1024-bit) are no longer "
+            "supported"
+        )
+    if backend._fips_enabled and len(iv) != 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.")
     if wycheproof.valid or wycheproof.acceptable:
         enc = Cipher(algorithms.AES(key), modes.GCM(iv), backend).encryptor()
         enc.authenticate_additional_data(aad)
@@ -65,19 +73,16 @@
         dec = Cipher(
             algorithms.AES(key),
             modes.GCM(iv, tag, min_tag_length=len(tag)),
-            backend
+            backend,
         ).decryptor()
         dec.authenticate_additional_data(aad)
         computed_msg = dec.update(ct) + dec.finalize()
         assert computed_msg == msg
-    elif len(iv) == 0:
-        with pytest.raises(ValueError):
-            Cipher(algorithms.AES(key), modes.GCM(iv), backend)
     else:
         dec = Cipher(
             algorithms.AES(key),
             modes.GCM(iv, tag, min_tag_length=len(tag)),
-            backend
+            backend,
         ).decryptor()
         dec.authenticate_additional_data(aad)
         dec.update(ct)
@@ -94,15 +99,22 @@
     msg = binascii.unhexlify(wycheproof.testcase["msg"])
     ct = binascii.unhexlify(wycheproof.testcase["ct"])
     tag = binascii.unhexlify(wycheproof.testcase["tag"])
+    if len(iv) < 8 or len(iv) > 128:
+        pytest.skip(
+            "Less than 64-bit IVs (and greater than 1024-bit) are no longer "
+            "supported"
+        )
+
+    if backend._fips_enabled and len(iv) != 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.")
     aesgcm = AESGCM(key)
     if wycheproof.valid or wycheproof.acceptable:
         computed_ct = aesgcm.encrypt(iv, msg, aad)
         assert computed_ct == ct + tag
         computed_msg = aesgcm.decrypt(iv, ct + tag, aad)
         assert computed_msg == msg
-    elif len(iv) == 0:
-        with pytest.raises(ValueError):
-            aesgcm.encrypt(iv, msg, aad)
     else:
         with pytest.raises(InvalidTag):
             aesgcm.decrypt(iv, ct + tag, aad)
@@ -123,8 +135,8 @@
     tag = binascii.unhexlify(wycheproof.testcase["tag"])
 
     if (
-        wycheproof.invalid and
-        wycheproof.testcase["comment"] == "Invalid tag size"
+        wycheproof.invalid
+        and wycheproof.testcase["comment"] == "Invalid tag size"
     ):
         with pytest.raises(ValueError):
             AESCCM(key, tag_length=wycheproof.testgroup["tagSize"] // 8)
diff --git a/tests/wycheproof/test_chacha20poly1305.py b/tests/wycheproof/test_chacha20poly1305.py
index deef5a0..48023ca 100644
--- a/tests/wycheproof/test_chacha20poly1305.py
+++ b/tests/wycheproof/test_chacha20poly1305.py
@@ -17,7 +17,7 @@
 
 @pytest.mark.skipif(
     not _aead_supported(ChaCha20Poly1305),
-    reason="Requires OpenSSL with ChaCha20Poly1305 support"
+    reason="Requires OpenSSL with ChaCha20Poly1305 support",
 )
 @pytest.mark.requires_backend_interface(interface=CipherBackend)
 @pytest.mark.wycheproof_tests("chacha20_poly1305_test.json")
diff --git a/tests/wycheproof/test_dsa.py b/tests/wycheproof/test_dsa.py
index 3dc3056..9185b3e 100644
--- a/tests/wycheproof/test_dsa.py
+++ b/tests/wycheproof/test_dsa.py
@@ -23,6 +23,10 @@
 @pytest.mark.requires_backend_interface(interface=DSABackend)
 @pytest.mark.wycheproof_tests(
     "dsa_test.json",
+    "dsa_2048_224_sha224_test.json",
+    "dsa_2048_224_sha256_test.json",
+    "dsa_2048_256_sha256_test.json",
+    "dsa_3072_256_sha256_test.json",
 )
 def test_dsa_signature(backend, wycheproof):
     key = serialization.load_der_public_key(
@@ -30,10 +34,8 @@
     )
     digest = _DIGESTS[wycheproof.testgroup["sha"]]
 
-    if (
-        wycheproof.valid or (
-            wycheproof.acceptable and not wycheproof.has_flag("NoLeadingZero")
-        )
+    if wycheproof.valid or (
+        wycheproof.acceptable and not wycheproof.has_flag("NoLeadingZero")
     ):
         key.verify(
             binascii.unhexlify(wycheproof.testcase["sig"]),
diff --git a/tests/wycheproof/test_ecdh.py b/tests/wycheproof/test_ecdh.py
index 5fcc45b..b89dc68 100644
--- a/tests/wycheproof/test_ecdh.py
+++ b/tests/wycheproof/test_ecdh.py
@@ -21,6 +21,7 @@
     "secp256r1": ec.SECP256R1(),
     "secp384r1": ec.SECP384R1(),
     "secp521r1": ec.SECP521R1(),
+    "secp224k1": None,
     "secp256k1": ec.SECP256K1(),
     "brainpoolP224r1": None,
     "brainpoolP256r1": ec.BrainpoolP256R1(),
diff --git a/tests/wycheproof/test_ecdsa.py b/tests/wycheproof/test_ecdsa.py
index 5214052..802bb9f 100644
--- a/tests/wycheproof/test_ecdsa.py
+++ b/tests/wycheproof/test_ecdsa.py
@@ -20,6 +20,10 @@
     "SHA-256": hashes.SHA256(),
     "SHA-384": hashes.SHA384(),
     "SHA-512": hashes.SHA512(),
+    "SHA3-224": hashes.SHA3_224(),
+    "SHA3-256": hashes.SHA3_256(),
+    "SHA3-384": hashes.SHA3_384(),
+    "SHA3-512": hashes.SHA3_512(),
 }
 
 
@@ -34,13 +38,23 @@
     "ecdsa_secp224r1_sha224_test.json",
     "ecdsa_secp224r1_sha256_test.json",
     "ecdsa_secp224r1_sha512_test.json",
+    "ecdsa_secp224r1_sha3_224_test.json",
+    "ecdsa_secp224r1_sha3_256_test.json",
+    "ecdsa_secp224r1_sha3_512_test.json",
     "ecdsa_secp256k1_sha256_test.json",
     "ecdsa_secp256k1_sha512_test.json",
+    "ecdsa_secp256k1_sha3_256_test.json",
+    "ecdsa_secp256k1_sha3_512_test.json",
     "ecdsa_secp256r1_sha256_test.json",
     "ecdsa_secp256r1_sha512_test.json",
+    "ecdsa_secp256r1_sha3_256_test.json",
+    "ecdsa_secp256r1_sha3_512_test.json",
     "ecdsa_secp384r1_sha384_test.json",
     "ecdsa_secp384r1_sha512_test.json",
+    "ecdsa_secp384r1_sha3_384_test.json",
+    "ecdsa_secp384r1_sha3_512_test.json",
     "ecdsa_secp521r1_sha512_test.json",
+    "ecdsa_secp521r1_sha3_512_test.json",
 )
 def test_ecdsa_signature(backend, wycheproof):
     try:
@@ -48,9 +62,9 @@
             binascii.unhexlify(wycheproof.testgroup["keyDer"]), backend
         )
     except (UnsupportedAlgorithm, ValueError):
-        # In OpenSSL 1.0.1, some keys fail to load with ValueError, instead of
-        # Unsupported Algorithm. We can remove handling for that exception
-        # when we drop support.
+        # In some OpenSSL 1.0.2s, some keys fail to load with ValueError,
+        # instead of  Unsupported Algorithm. We can remove handling for that
+        # exception when we drop support.
         pytest.skip(
             "unable to load key (curve {})".format(
                 wycheproof.testgroup["key"]["curve"]
@@ -58,9 +72,11 @@
         )
     digest = _DIGESTS[wycheproof.testgroup["sha"]]
 
-    if (
-        wycheproof.valid or
-        (wycheproof.acceptable and not wycheproof.has_flag("MissingZero"))
+    if not backend.hash_supported(digest):
+        pytest.skip("Hash {} not supported".format(digest))
+
+    if wycheproof.valid or (
+        wycheproof.acceptable and not wycheproof.has_flag("MissingZero")
     ):
         key.verify(
             binascii.unhexlify(wycheproof.testcase["sig"]),
diff --git a/tests/wycheproof/test_eddsa.py b/tests/wycheproof/test_eddsa.py
new file mode 100644
index 0000000..42c1498
--- /dev/null
+++ b/tests/wycheproof/test_eddsa.py
@@ -0,0 +1,63 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+
+import pytest
+
+from cryptography.exceptions import InvalidSignature
+from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
+from cryptography.hazmat.primitives.asymmetric.ed448 import Ed448PublicKey
+
+
+@pytest.mark.supported(
+    only_if=lambda backend: backend.ed25519_supported(),
+    skip_message="Requires OpenSSL with Ed25519 support",
+)
+@pytest.mark.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.
+    assert wycheproof.testgroup["key"]["curve"] == "edwards25519"
+
+    key = Ed25519PublicKey.from_public_bytes(
+        binascii.unhexlify(wycheproof.testgroup["key"]["pk"])
+    )
+
+    if wycheproof.valid or wycheproof.acceptable:
+        key.verify(
+            binascii.unhexlify(wycheproof.testcase["sig"]),
+            binascii.unhexlify(wycheproof.testcase["msg"]),
+        )
+    else:
+        with pytest.raises(InvalidSignature):
+            key.verify(
+                binascii.unhexlify(wycheproof.testcase["sig"]),
+                binascii.unhexlify(wycheproof.testcase["msg"]),
+            )
+
+
+@pytest.mark.supported(
+    only_if=lambda backend: backend.ed448_supported(),
+    skip_message="Requires OpenSSL with Ed448 support",
+)
+@pytest.mark.wycheproof_tests("ed448_test.json")
+def test_ed448_signature(backend, wycheproof):
+    key = Ed448PublicKey.from_public_bytes(
+        binascii.unhexlify(wycheproof.testgroup["key"]["pk"])
+    )
+
+    if wycheproof.valid or wycheproof.acceptable:
+        key.verify(
+            binascii.unhexlify(wycheproof.testcase["sig"]),
+            binascii.unhexlify(wycheproof.testcase["msg"]),
+        )
+    else:
+        with pytest.raises(InvalidSignature):
+            key.verify(
+                binascii.unhexlify(wycheproof.testcase["sig"]),
+                binascii.unhexlify(wycheproof.testcase["msg"]),
+            )
diff --git a/tests/wycheproof/test_hkdf.py b/tests/wycheproof/test_hkdf.py
new file mode 100644
index 0000000..3e1687e
--- /dev/null
+++ b/tests/wycheproof/test_hkdf.py
@@ -0,0 +1,50 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+
+import pytest
+
+from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives.kdf.hkdf import HKDF
+
+
+_HASH_ALGORITHMS = {
+    "HKDF-SHA-1": hashes.SHA1(),
+    "HKDF-SHA-256": hashes.SHA256(),
+    "HKDF-SHA-384": hashes.SHA384(),
+    "HKDF-SHA-512": hashes.SHA512(),
+}
+
+
+@pytest.mark.wycheproof_tests(
+    "hkdf_sha1_test.json",
+    "hkdf_sha256_test.json",
+    "hkdf_sha384_test.json",
+    "hkdf_sha512_test.json",
+)
+def test_hkdf(backend, wycheproof):
+    hash_algo = _HASH_ALGORITHMS[wycheproof.testfiledata["algorithm"]]
+    if wycheproof.invalid:
+        with pytest.raises(ValueError):
+            HKDF(
+                algorithm=hash_algo,
+                length=wycheproof.testcase["size"],
+                salt=binascii.unhexlify(wycheproof.testcase["salt"]),
+                info=binascii.unhexlify(wycheproof.testcase["info"]),
+                backend=backend,
+            )
+        return
+
+    h = HKDF(
+        algorithm=hash_algo,
+        length=wycheproof.testcase["size"],
+        salt=binascii.unhexlify(wycheproof.testcase["salt"]),
+        info=binascii.unhexlify(wycheproof.testcase["info"]),
+        backend=backend,
+    )
+    result = h.derive(binascii.unhexlify(wycheproof.testcase["ikm"]))
+    assert result == binascii.unhexlify(wycheproof.testcase["okm"])
diff --git a/tests/wycheproof/test_hmac.py b/tests/wycheproof/test_hmac.py
new file mode 100644
index 0000000..0cf908f
--- /dev/null
+++ b/tests/wycheproof/test_hmac.py
@@ -0,0 +1,66 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+
+import pytest
+
+from cryptography.exceptions import InvalidSignature
+from cryptography.hazmat.primitives import hashes, hmac
+
+
+_HMAC_ALGORITHMS = {
+    "HMACSHA1": hashes.SHA1(),
+    "HMACSHA224": hashes.SHA224(),
+    "HMACSHA256": hashes.SHA256(),
+    "HMACSHA384": hashes.SHA384(),
+    "HMACSHA512": hashes.SHA512(),
+    "HMACSHA3-224": hashes.SHA3_224(),
+    "HMACSHA3-256": hashes.SHA3_256(),
+    "HMACSHA3-384": hashes.SHA3_384(),
+    "HMACSHA3-512": hashes.SHA3_512(),
+}
+
+
+@pytest.mark.wycheproof_tests(
+    "hmac_sha1_test.json",
+    "hmac_sha224_test.json",
+    "hmac_sha256_test.json",
+    "hmac_sha384_test.json",
+    "hmac_sha3_224_test.json",
+    "hmac_sha3_256_test.json",
+    "hmac_sha3_384_test.json",
+    "hmac_sha3_512_test.json",
+    "hmac_sha512_test.json",
+)
+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):
+        pytest.skip("Hash {} not supported".format(hash_algo.name))
+
+    h = hmac.HMAC(
+        key=binascii.unhexlify(wycheproof.testcase["key"]),
+        algorithm=hash_algo,
+        backend=backend,
+    )
+    h.update(binascii.unhexlify(wycheproof.testcase["msg"]))
+
+    if wycheproof.invalid:
+        with pytest.raises(InvalidSignature):
+            h.verify(binascii.unhexlify(wycheproof.testcase["tag"]))
+    else:
+        tag = h.finalize()
+        assert tag == binascii.unhexlify(wycheproof.testcase["tag"])
+
+        h = hmac.HMAC(
+            key=binascii.unhexlify(wycheproof.testcase["key"]),
+            algorithm=hash_algo,
+            backend=backend,
+        )
+        h.update(binascii.unhexlify(wycheproof.testcase["msg"]))
+        h.verify(binascii.unhexlify(wycheproof.testcase["tag"]))
diff --git a/tests/wycheproof/test_keywrap.py b/tests/wycheproof/test_keywrap.py
index 5f694e4..9c7d522 100644
--- a/tests/wycheproof/test_keywrap.py
+++ b/tests/wycheproof/test_keywrap.py
@@ -44,11 +44,9 @@
     key_to_wrap = binascii.unhexlify(wycheproof.testcase["msg"])
     expected = binascii.unhexlify(wycheproof.testcase["ct"])
 
-    if (
-        wycheproof.valid or (
-            wycheproof.acceptable and
-            wycheproof.testcase["comment"] != "invalid size of wrapped key"
-        )
+    if wycheproof.valid or (
+        wycheproof.acceptable
+        and wycheproof.testcase["comment"] != "invalid size of wrapped key"
     ):
         result = keywrap.aes_key_wrap(wrapping_key, key_to_wrap, backend)
         assert result == expected
diff --git a/tests/wycheproof/test_rsa.py b/tests/wycheproof/test_rsa.py
index 3d35f42..926bb44 100644
--- a/tests/wycheproof/test_rsa.py
+++ b/tests/wycheproof/test_rsa.py
@@ -20,6 +20,13 @@
     "SHA-256": hashes.SHA256(),
     "SHA-384": hashes.SHA384(),
     "SHA-512": hashes.SHA512(),
+    # Not supported by OpenSSL for RSA signing
+    "SHA-512/224": None,
+    "SHA-512/256": None,
+    "SHA3-224": hashes.SHA3_224(),
+    "SHA3-256": hashes.SHA3_256(),
+    "SHA3-384": hashes.SHA3_384(),
+    "SHA3-512": hashes.SHA3_512(),
 }
 
 
@@ -28,39 +35,34 @@
         return True
 
     if wycheproof.acceptable:
-        if (
-            backend._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER and
-            wycheproof.has_flag("MissingNull")
-        ):
-            return False
-        return True
+        return not wycheproof.has_flag("MissingNull")
 
     return False
 
 
 @pytest.mark.requires_backend_interface(interface=RSABackend)
-@pytest.mark.supported(
-    only_if=lambda backend: (
-        # TODO: this also skips on LibreSSL, which is ok for now, since these
-        # don't pass on Libre, but we'll need to fix this when LibreSSL 2.8 is
-        # released.
-        not backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102
-    ),
-    skip_message=(
-        "Many of these tests fail on OpenSSL < 1.0.2 and since upstream isn't"
-        " maintaining it, they'll never be fixed."
-    ),
-)
 @pytest.mark.wycheproof_tests(
     "rsa_signature_test.json",
     "rsa_signature_2048_sha224_test.json",
     "rsa_signature_2048_sha256_test.json",
+    "rsa_signature_2048_sha384_test.json",
     "rsa_signature_2048_sha512_test.json",
+    "rsa_signature_2048_sha512_224_test.json",
+    "rsa_signature_2048_sha512_256_test.json",
+    "rsa_signature_2048_sha3_224_test.json",
+    "rsa_signature_2048_sha3_256_test.json",
+    "rsa_signature_2048_sha3_384_test.json",
+    "rsa_signature_2048_sha3_512_test.json",
     "rsa_signature_3072_sha256_test.json",
     "rsa_signature_3072_sha384_test.json",
     "rsa_signature_3072_sha512_test.json",
+    "rsa_signature_3072_sha512_256_test.json",
+    "rsa_signature_3072_sha3_256_test.json",
+    "rsa_signature_3072_sha3_384_test.json",
+    "rsa_signature_3072_sha3_512_test.json",
     "rsa_signature_4096_sha384_test.json",
     "rsa_signature_4096_sha512_test.json",
+    "rsa_signature_4096_sha512_256_test.json",
 )
 def test_rsa_pkcs1v15_signature(backend, wycheproof):
     key = serialization.load_der_public_key(
@@ -68,6 +70,11 @@
     )
     digest = _DIGESTS[wycheproof.testgroup["sha"]]
 
+    if digest is None or not backend.hash_supported(digest):
+        pytest.skip(
+            "Hash {} not supported".format(wycheproof.testgroup["sha"])
+        )
+
     if should_verify(backend, wycheproof):
         key.verify(
             binascii.unhexlify(wycheproof.testcase["sig"]),
@@ -85,11 +92,30 @@
             )
 
 
+@pytest.mark.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(),
+        password=None,
+        backend=backend,
+    )
+    digest = _DIGESTS[wycheproof.testgroup["sha"]]
+
+    sig = key.sign(
+        binascii.unhexlify(wycheproof.testcase["msg"]),
+        padding.PKCS1v15(),
+        digest,
+    )
+    assert sig == binascii.unhexlify(wycheproof.testcase["sig"])
+
+
 @pytest.mark.requires_backend_interface(interface=RSABackend)
 @pytest.mark.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",
+    "rsa_pss_2048_sha512_256_mgf1_28_test.json",
+    "rsa_pss_2048_sha512_256_mgf1_32_test.json",
     "rsa_pss_3072_sha256_mgf1_32_test.json",
     "rsa_pss_4096_sha256_mgf1_32_test.json",
     "rsa_pss_4096_sha512_mgf1_32_test.json",
@@ -102,15 +128,23 @@
     digest = _DIGESTS[wycheproof.testgroup["sha"]]
     mgf_digest = _DIGESTS[wycheproof.testgroup["mgfSha"]]
 
+    if digest is None or mgf_digest is None:
+        pytest.skip(
+            "PSS with digest={} and MGF digest={} not supported".format(
+                wycheproof.testgroup["sha"],
+                wycheproof.testgroup["mgfSha"],
+            )
+        )
+
     if wycheproof.valid or wycheproof.acceptable:
         key.verify(
             binascii.unhexlify(wycheproof.testcase["sig"]),
             binascii.unhexlify(wycheproof.testcase["msg"]),
             padding.PSS(
                 mgf=padding.MGF1(mgf_digest),
-                salt_length=wycheproof.testgroup["sLen"]
+                salt_length=wycheproof.testgroup["sLen"],
             ),
-            digest
+            digest,
         )
     else:
         with pytest.raises(InvalidSignature):
@@ -119,7 +153,88 @@
                 binascii.unhexlify(wycheproof.testcase["msg"]),
                 padding.PSS(
                     mgf=padding.MGF1(mgf_digest),
-                    salt_length=wycheproof.testgroup["sLen"]
+                    salt_length=wycheproof.testgroup["sLen"],
                 ),
-                digest
+                digest,
+            )
+
+
+@pytest.mark.requires_backend_interface(interface=RSABackend)
+@pytest.mark.wycheproof_tests(
+    "rsa_oaep_2048_sha1_mgf1sha1_test.json",
+    "rsa_oaep_2048_sha224_mgf1sha1_test.json",
+    "rsa_oaep_2048_sha224_mgf1sha224_test.json",
+    "rsa_oaep_2048_sha256_mgf1sha1_test.json",
+    "rsa_oaep_2048_sha256_mgf1sha256_test.json",
+    "rsa_oaep_2048_sha384_mgf1sha1_test.json",
+    "rsa_oaep_2048_sha384_mgf1sha384_test.json",
+    "rsa_oaep_2048_sha512_mgf1sha1_test.json",
+    "rsa_oaep_2048_sha512_mgf1sha512_test.json",
+    "rsa_oaep_3072_sha256_mgf1sha1_test.json",
+    "rsa_oaep_3072_sha256_mgf1sha256_test.json",
+    "rsa_oaep_3072_sha512_mgf1sha1_test.json",
+    "rsa_oaep_3072_sha512_mgf1sha512_test.json",
+    "rsa_oaep_4096_sha256_mgf1sha1_test.json",
+    "rsa_oaep_4096_sha256_mgf1sha256_test.json",
+    "rsa_oaep_4096_sha512_mgf1sha1_test.json",
+    "rsa_oaep_4096_sha512_mgf1sha512_test.json",
+    "rsa_oaep_misc_test.json",
+)
+def test_rsa_oaep_encryption(backend, wycheproof):
+    key = serialization.load_pem_private_key(
+        wycheproof.testgroup["privateKeyPem"].encode("ascii"),
+        password=None,
+        backend=backend,
+    )
+    digest = _DIGESTS[wycheproof.testgroup["sha"]]
+    mgf_digest = _DIGESTS[wycheproof.testgroup["mgfSha"]]
+
+    padding_algo = padding.OAEP(
+        mgf=padding.MGF1(algorithm=mgf_digest),
+        algorithm=digest,
+        label=binascii.unhexlify(wycheproof.testcase["label"]),
+    )
+
+    if not backend.rsa_padding_supported(padding_algo):
+        pytest.skip(
+            "OAEP with digest={} and MGF digest={} not supported".format(
+                wycheproof.testgroup["sha"],
+                wycheproof.testgroup["mgfSha"],
+            )
+        )
+
+    if wycheproof.valid or wycheproof.acceptable:
+        pt = key.decrypt(
+            binascii.unhexlify(wycheproof.testcase["ct"]), padding_algo
+        )
+        assert pt == binascii.unhexlify(wycheproof.testcase["msg"])
+    else:
+        with pytest.raises(ValueError):
+            key.decrypt(
+                binascii.unhexlify(wycheproof.testcase["ct"]), padding_algo
+            )
+
+
+@pytest.mark.wycheproof_tests(
+    "rsa_pkcs1_2048_test.json",
+    "rsa_pkcs1_3072_test.json",
+    "rsa_pkcs1_4096_test.json",
+)
+def test_rsa_pkcs1_encryption(backend, wycheproof):
+    key = serialization.load_pem_private_key(
+        wycheproof.testgroup["privateKeyPem"].encode("ascii"),
+        password=None,
+        backend=backend,
+    )
+
+    if wycheproof.valid:
+        pt = key.decrypt(
+            binascii.unhexlify(wycheproof.testcase["ct"]), padding.PKCS1v15()
+        )
+        assert pt == binascii.unhexlify(wycheproof.testcase["msg"])
+    else:
+        with pytest.raises(ValueError):
+            key.decrypt(
+                binascii.unhexlify(wycheproof.testcase["ct"]),
+                padding.PKCS1v15(),
             )
diff --git a/tests/wycheproof/test_utils.py b/tests/wycheproof/test_utils.py
index 82c0a35..593d26b 100644
--- a/tests/wycheproof/test_utils.py
+++ b/tests/wycheproof/test_utils.py
@@ -4,18 +4,9 @@
 
 from __future__ import absolute_import, division, print_function
 
-import pytest
-
-from ..utils import WycheproofTest, skip_if_wycheproof_none
+from ..utils import WycheproofTest
 
 
 def test_wycheproof_test_repr():
-    wycheproof = WycheproofTest({}, {"tcId": 3})
-    assert repr(wycheproof) == "<WycheproofTest({}, {'tcId': 3}, tcId=3)>"
-
-
-def test_skip_if_wycheproof_none():
-    with pytest.raises(pytest.skip.Exception):
-        skip_if_wycheproof_none(None)
-
-    skip_if_wycheproof_none("abc")
+    wycheproof = WycheproofTest({}, {}, {"tcId": 3})
+    assert repr(wycheproof) == "<WycheproofTest({}, {}, {'tcId': 3}, tcId=3)>"
diff --git a/tests/wycheproof/test_x25519.py b/tests/wycheproof/test_x25519.py
index 0727ec3..ce2a965 100644
--- a/tests/wycheproof/test_x25519.py
+++ b/tests/wycheproof/test_x25519.py
@@ -8,20 +8,22 @@
 
 import pytest
 
-from cryptography.hazmat.backends.interfaces import DHBackend
 from cryptography.hazmat.primitives.asymmetric.x25519 import (
-    X25519PrivateKey, X25519PublicKey
+    X25519PrivateKey,
+    X25519PublicKey,
 )
 
 
 @pytest.mark.supported(
     only_if=lambda backend: backend.x25519_supported(),
-    skip_message="Requires OpenSSL with X25519 support"
+    skip_message="Requires OpenSSL with X25519 support",
 )
-@pytest.mark.requires_backend_interface(interface=DHBackend)
 @pytest.mark.wycheproof_tests("x25519_test.json")
 def test_x25519(backend, wycheproof):
-    assert list(wycheproof.testgroup.items()) == [("curve", "curve25519")]
+    assert set(wycheproof.testgroup.items()) == {
+        ("curve", "curve25519"),
+        ("type", "XdhComp"),
+    }
 
     private_key = X25519PrivateKey.from_private_bytes(
         binascii.unhexlify(wycheproof.testcase["private"])
diff --git a/tests/wycheproof/test_x448.py b/tests/wycheproof/test_x448.py
new file mode 100644
index 0000000..fcac809
--- /dev/null
+++ b/tests/wycheproof/test_x448.py
@@ -0,0 +1,50 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+
+import pytest
+
+from cryptography.hazmat.primitives.asymmetric.x448 import (
+    X448PrivateKey,
+    X448PublicKey,
+)
+
+
+@pytest.mark.supported(
+    only_if=lambda backend: backend.x448_supported(),
+    skip_message="Requires OpenSSL with X448 support",
+)
+@pytest.mark.wycheproof_tests("x448_test.json")
+def test_x448(backend, wycheproof):
+    assert set(wycheproof.testgroup.items()) == {
+        ("curve", "curve448"),
+        ("type", "XdhComp"),
+    }
+
+    private_key = X448PrivateKey.from_private_bytes(
+        binascii.unhexlify(wycheproof.testcase["private"])
+    )
+    public_key_bytes = binascii.unhexlify(wycheproof.testcase["public"])
+    if len(public_key_bytes) == 57:
+        assert wycheproof.acceptable
+        assert wycheproof.has_flag("NonCanonicalPublic")
+        with pytest.raises(ValueError):
+            X448PublicKey.from_public_bytes(public_key_bytes)
+        return
+
+    public_key = X448PublicKey.from_public_bytes(public_key_bytes)
+
+    assert wycheproof.valid or wycheproof.acceptable
+
+    expected = binascii.unhexlify(wycheproof.testcase["shared"])
+    if expected == b"\x00" * 56:
+        assert wycheproof.acceptable
+        # OpenSSL returns an error on all zeros shared key
+        with pytest.raises(ValueError):
+            private_key.exchange(public_key)
+    else:
+        assert private_key.exchange(public_key) == expected
diff --git a/tests/x509/test_ocsp.py b/tests/x509/test_ocsp.py
index 3abaff5..b649402 100644
--- a/tests/x509/test_ocsp.py
+++ b/tests/x509/test_ocsp.py
@@ -13,7 +13,7 @@
 from cryptography import x509
 from cryptography.exceptions import UnsupportedAlgorithm
 from cryptography.hazmat.primitives import hashes, serialization
-from cryptography.hazmat.primitives.asymmetric import ec
+from cryptography.hazmat.primitives.asymmetric import ec, ed25519, ed448
 from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15
 from cryptography.x509 import ocsp
 
@@ -24,51 +24,52 @@
 
 def _load_data(filename, loader):
     return load_vectors_from_file(
-        filename=filename,
-        loader=lambda data: loader(data.read()),
-        mode="rb"
+        filename=filename, loader=lambda data: loader(data.read()), mode="rb"
     )
 
 
 def _cert_and_issuer():
     from cryptography.hazmat.backends.openssl.backend import backend
+
     cert = _load_cert(
         os.path.join("x509", "cryptography.io.pem"),
         x509.load_pem_x509_certificate,
-        backend
+        backend,
     )
     issuer = _load_cert(
         os.path.join("x509", "rapidssl_sha256_ca_g3.pem"),
         x509.load_pem_x509_certificate,
-        backend
+        backend,
     )
     return cert, issuer
 
 
-def _generate_root():
+def _generate_root(private_key=None, algorithm=hashes.SHA256()):
     from cryptography.hazmat.backends.openssl.backend import backend
 
-    private_key = EC_KEY_SECP256R1.private_key(backend)
-    subject = x509.Name([
-        x509.NameAttribute(x509.NameOID.COUNTRY_NAME, u'US'),
-        x509.NameAttribute(x509.NameOID.COMMON_NAME, u'Cryptography CA'),
-    ])
+    if private_key is None:
+        private_key = EC_KEY_SECP256R1.private_key(backend)
 
-    builder = x509.CertificateBuilder().serial_number(
-        123456789
-    ).issuer_name(
-        subject
-    ).subject_name(
-        subject
-    ).public_key(
-        private_key.public_key()
-    ).not_valid_before(
-        datetime.datetime.now()
-    ).not_valid_after(
-        datetime.datetime.now() + datetime.timedelta(days=3650)
+    subject = x509.Name(
+        [
+            x509.NameAttribute(x509.NameOID.COUNTRY_NAME, u"US"),
+            x509.NameAttribute(x509.NameOID.COMMON_NAME, u"Cryptography CA"),
+        ]
     )
 
-    cert = builder.sign(private_key, hashes.SHA256(), backend)
+    builder = (
+        x509.CertificateBuilder()
+        .serial_number(123456789)
+        .issuer_name(subject)
+        .subject_name(subject)
+        .public_key(private_key.public_key())
+        .not_valid_before(datetime.datetime.now())
+        .not_valid_after(
+            datetime.datetime.now() + datetime.timedelta(days=3650)
+        )
+    )
+
+    cert = builder.sign(private_key, algorithm, backend)
     return cert, private_key
 
 
@@ -82,10 +83,12 @@
             os.path.join("x509", "ocsp", "req-sha1.der"),
             ocsp.load_der_ocsp_request,
         )
-        assert req.issuer_name_hash == (b"8\xcaF\x8c\x07D\x8d\xf4\x81\x96"
-                                        b"\xc7mmLpQ\x9e`\xa7\xbd")
-        assert req.issuer_key_hash == (b"yu\xbb\x84:\xcb,\xdez\t\xbe1"
-                                       b"\x1bC\xbc\x1c*MSX")
+        assert req.issuer_name_hash == (
+            b"8\xcaF\x8c\x07D\x8d\xf4\x81\x96" b"\xc7mmLpQ\x9e`\xa7\xbd"
+        )
+        assert req.issuer_key_hash == (
+            b"yu\xbb\x84:\xcb,\xdez\t\xbe1" b"\x1bC\xbc\x1c*MSX"
+        )
         assert isinstance(req.hash_algorithm, hashes.SHA1)
         assert req.serial_number == int(
             "98D9E5C0B4C373552DF77C5D0F1EB5128E4945F9", 16
@@ -123,7 +126,7 @@
         req_bytes = load_vectors_from_file(
             filename=os.path.join("x509", "ocsp", "req-sha1.der"),
             loader=lambda data: data.read(),
-            mode="rb"
+            mode="rb",
         )
         req = ocsp.load_der_ocsp_request(req_bytes)
         assert req.public_bytes(serialization.Encoding.DER) == req_bytes
@@ -194,16 +197,14 @@
         [
             [x509.OCSPNonce(b"0000"), False],
             [x509.OCSPNonce(b"\x00\x01\x02"), True],
-        ]
+        ],
     )
     def test_create_ocsp_request_with_extension(self, ext, critical):
         cert, issuer = _cert_and_issuer()
         builder = ocsp.OCSPRequestBuilder()
         builder = builder.add_certificate(
             cert, issuer, hashes.SHA1()
-        ).add_extension(
-            ext, critical
-        )
+        ).add_extension(ext, critical)
         req = builder.build()
         assert len(req.extensions) == 1
         assert req.extensions[0].value == ext
@@ -217,13 +218,25 @@
         time = datetime.datetime.now()
         builder = ocsp.OCSPResponseBuilder()
         builder = builder.add_response(
-            cert, issuer, hashes.SHA256(), ocsp.OCSPCertStatus.GOOD, time,
-            time, None, None
+            cert,
+            issuer,
+            hashes.SHA256(),
+            ocsp.OCSPCertStatus.GOOD,
+            time,
+            time,
+            None,
+            None,
         )
         with pytest.raises(ValueError):
             builder.add_response(
-                cert, issuer, hashes.SHA256(), ocsp.OCSPCertStatus.GOOD, time,
-                time, None, None
+                cert,
+                issuer,
+                hashes.SHA256(),
+                ocsp.OCSPCertStatus.GOOD,
+                time,
+                time,
+                None,
+                None,
             )
 
     def test_invalid_add_response(self):
@@ -233,28 +246,58 @@
         builder = ocsp.OCSPResponseBuilder()
         with pytest.raises(TypeError):
             builder.add_response(
-                'bad', issuer, hashes.SHA256(), ocsp.OCSPCertStatus.GOOD,
-                time, time, None, None
+                "bad",
+                issuer,
+                hashes.SHA256(),
+                ocsp.OCSPCertStatus.GOOD,
+                time,
+                time,
+                None,
+                None,
             )
         with pytest.raises(TypeError):
             builder.add_response(
-                cert, 'bad', hashes.SHA256(), ocsp.OCSPCertStatus.GOOD,
-                time, time, None, None
+                cert,
+                "bad",
+                hashes.SHA256(),
+                ocsp.OCSPCertStatus.GOOD,
+                time,
+                time,
+                None,
+                None,
             )
         with pytest.raises(ValueError):
             builder.add_response(
-                cert, issuer, 'notahash', ocsp.OCSPCertStatus.GOOD,
-                time, time, None, None
+                cert,
+                issuer,
+                "notahash",
+                ocsp.OCSPCertStatus.GOOD,
+                time,
+                time,
+                None,
+                None,
             )
         with pytest.raises(TypeError):
             builder.add_response(
-                cert, issuer, hashes.SHA256(), ocsp.OCSPCertStatus.GOOD,
-                'bad', time, None, None
+                cert,
+                issuer,
+                hashes.SHA256(),
+                ocsp.OCSPCertStatus.GOOD,
+                "bad",
+                time,
+                None,
+                None,
             )
         with pytest.raises(TypeError):
             builder.add_response(
-                cert, issuer, hashes.SHA256(), ocsp.OCSPCertStatus.GOOD,
-                time, 'bad', None, None
+                cert,
+                issuer,
+                hashes.SHA256(),
+                ocsp.OCSPCertStatus.GOOD,
+                time,
+                "bad",
+                None,
+                None,
             )
 
         with pytest.raises(TypeError):
@@ -263,28 +306,58 @@
             )
         with pytest.raises(ValueError):
             builder.add_response(
-                cert, issuer, hashes.SHA256(), ocsp.OCSPCertStatus.GOOD,
-                time, time, time, None
+                cert,
+                issuer,
+                hashes.SHA256(),
+                ocsp.OCSPCertStatus.GOOD,
+                time,
+                time,
+                time,
+                None,
             )
         with pytest.raises(ValueError):
             builder.add_response(
-                cert, issuer, hashes.SHA256(), ocsp.OCSPCertStatus.GOOD,
-                time, time, None, reason
+                cert,
+                issuer,
+                hashes.SHA256(),
+                ocsp.OCSPCertStatus.GOOD,
+                time,
+                time,
+                None,
+                reason,
             )
         with pytest.raises(TypeError):
             builder.add_response(
-                cert, issuer, hashes.SHA256(), ocsp.OCSPCertStatus.REVOKED,
-                time, time, None, reason
+                cert,
+                issuer,
+                hashes.SHA256(),
+                ocsp.OCSPCertStatus.REVOKED,
+                time,
+                time,
+                None,
+                reason,
             )
         with pytest.raises(TypeError):
             builder.add_response(
-                cert, issuer, hashes.SHA256(), ocsp.OCSPCertStatus.REVOKED,
-                time, time, time, 0
+                cert,
+                issuer,
+                hashes.SHA256(),
+                ocsp.OCSPCertStatus.REVOKED,
+                time,
+                time,
+                time,
+                0,
             )
         with pytest.raises(ValueError):
             builder.add_response(
-                cert, issuer, hashes.SHA256(), ocsp.OCSPCertStatus.REVOKED,
-                time, time, time - datetime.timedelta(days=36500), None
+                cert,
+                issuer,
+                hashes.SHA256(),
+                ocsp.OCSPCertStatus.REVOKED,
+                time,
+                time,
+                time - datetime.timedelta(days=36500),
+                None,
             )
 
     def test_invalid_certificates(self):
@@ -292,9 +365,9 @@
         with pytest.raises(ValueError):
             builder.certificates([])
         with pytest.raises(TypeError):
-            builder.certificates(['notacert'])
+            builder.certificates(["notacert"])
         with pytest.raises(TypeError):
-            builder.certificates('invalid')
+            builder.certificates("invalid")
 
         _, issuer = _cert_and_issuer()
         builder = builder.certificates([issuer])
@@ -305,9 +378,9 @@
         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")
         with pytest.raises(TypeError):
-            builder.responder_id('notanenum', cert)
+            builder.responder_id("notanenum", cert)
 
         builder = builder.responder_id(ocsp.OCSPResponderEncoding.NAME, cert)
         with pytest.raises(ValueError):
@@ -335,8 +408,14 @@
         this_update = current_time - datetime.timedelta(days=1)
         next_update = this_update + datetime.timedelta(days=7)
         builder = builder.add_response(
-            cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.GOOD, this_update,
-            next_update, None, None
+            cert,
+            issuer,
+            hashes.SHA1(),
+            ocsp.OCSPCertStatus.GOOD,
+            this_update,
+            next_update,
+            None,
+            None,
         )
         with pytest.raises(ValueError):
             builder.sign(private_key, hashes.SHA256())
@@ -351,11 +430,17 @@
         builder = builder.responder_id(
             ocsp.OCSPResponderEncoding.NAME, root_cert
         ).add_response(
-            cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.GOOD, this_update,
-            next_update, None, None
+            cert,
+            issuer,
+            hashes.SHA1(),
+            ocsp.OCSPCertStatus.GOOD,
+            this_update,
+            next_update,
+            None,
+            None,
         )
         with pytest.raises(TypeError):
-            builder.sign(private_key, 'notahash')
+            builder.sign(private_key, "notahash")
 
     def test_sign_good_cert(self):
         builder = ocsp.OCSPResponseBuilder()
@@ -367,15 +452,23 @@
         builder = builder.responder_id(
             ocsp.OCSPResponderEncoding.NAME, root_cert
         ).add_response(
-            cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.GOOD, this_update,
-            next_update, None, None
+            cert,
+            issuer,
+            hashes.SHA1(),
+            ocsp.OCSPCertStatus.GOOD,
+            this_update,
+            next_update,
+            None,
+            None,
         )
         resp = builder.sign(private_key, hashes.SHA256())
         assert resp.responder_name == root_cert.subject
         assert resp.responder_key_hash is None
         assert (current_time - resp.produced_at).total_seconds() < 10
-        assert (resp.signature_algorithm_oid ==
-                x509.SignatureAlgorithmOID.ECDSA_WITH_SHA256)
+        assert (
+            resp.signature_algorithm_oid
+            == x509.SignatureAlgorithmOID.ECDSA_WITH_SHA256
+        )
         assert resp.certificate_status == ocsp.OCSPCertStatus.GOOD
         assert resp.revocation_time is None
         assert resp.revocation_reason is None
@@ -396,8 +489,14 @@
         builder = builder.responder_id(
             ocsp.OCSPResponderEncoding.NAME, root_cert
         ).add_response(
-            cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.REVOKED,
-            this_update, next_update, revoked_date, None
+            cert,
+            issuer,
+            hashes.SHA1(),
+            ocsp.OCSPCertStatus.REVOKED,
+            this_update,
+            next_update,
+            revoked_date,
+            None,
         )
         resp = builder.sign(private_key, hashes.SHA256())
         assert resp.certificate_status == ocsp.OCSPCertStatus.REVOKED
@@ -416,13 +515,19 @@
         current_time = datetime.datetime.utcnow().replace(microsecond=0)
         this_update = current_time - datetime.timedelta(days=1)
         next_update = this_update + datetime.timedelta(days=7)
-        builder = builder.responder_id(
-            ocsp.OCSPResponderEncoding.NAME, root_cert
-        ).add_response(
-            cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.GOOD, this_update,
-            next_update, None, None
-        ).certificates(
-            [root_cert]
+        builder = (
+            builder.responder_id(ocsp.OCSPResponderEncoding.NAME, root_cert)
+            .add_response(
+                cert,
+                issuer,
+                hashes.SHA1(),
+                ocsp.OCSPCertStatus.GOOD,
+                this_update,
+                next_update,
+                None,
+                None,
+            )
+            .certificates([root_cert])
         )
         resp = builder.sign(private_key, hashes.SHA256())
         assert resp.certificates == [root_cert]
@@ -437,8 +542,14 @@
         builder = builder.responder_id(
             ocsp.OCSPResponderEncoding.NAME, root_cert
         ).add_response(
-            cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.REVOKED,
-            this_update, None, revoked_date, None
+            cert,
+            issuer,
+            hashes.SHA1(),
+            ocsp.OCSPCertStatus.REVOKED,
+            this_update,
+            None,
+            revoked_date,
+            None,
         )
         resp = builder.sign(private_key, hashes.SHA256())
         assert resp.certificate_status == ocsp.OCSPCertStatus.REVOKED
@@ -461,9 +572,14 @@
         builder = builder.responder_id(
             ocsp.OCSPResponderEncoding.NAME, root_cert
         ).add_response(
-            cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.REVOKED,
-            this_update, next_update, revoked_date,
-            x509.ReasonFlags.key_compromise
+            cert,
+            issuer,
+            hashes.SHA1(),
+            ocsp.OCSPCertStatus.REVOKED,
+            this_update,
+            next_update,
+            revoked_date,
+            x509.ReasonFlags.key_compromise,
         )
         resp = builder.sign(private_key, hashes.SHA256())
         assert resp.certificate_status == ocsp.OCSPCertStatus.REVOKED
@@ -485,13 +601,19 @@
         builder = builder.responder_id(
             ocsp.OCSPResponderEncoding.HASH, root_cert
         ).add_response(
-            cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.GOOD, this_update,
-            next_update, None, None
+            cert,
+            issuer,
+            hashes.SHA1(),
+            ocsp.OCSPCertStatus.GOOD,
+            this_update,
+            next_update,
+            None,
+            None,
         )
         resp = builder.sign(private_key, hashes.SHA256())
         assert resp.responder_name is None
         assert resp.responder_key_hash == (
-            b'\x8ca\x94\xe0\x948\xed\x89\xd8\xd4N\x89p\t\xd6\xf9^_\xec}'
+            b"\x8ca\x94\xe0\x948\xed\x89\xd8\xd4N\x89p\t\xd6\xf9^_\xec}"
         )
         private_key.public_key().verify(
             resp.signature, resp.tbs_response_bytes, ec.ECDSA(hashes.SHA256())
@@ -507,10 +629,17 @@
         builder = builder.responder_id(
             ocsp.OCSPResponderEncoding.HASH, root_cert
         ).add_response(
-            cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.GOOD, this_update,
-            next_update, None, None
+            cert,
+            issuer,
+            hashes.SHA1(),
+            ocsp.OCSPCertStatus.GOOD,
+            this_update,
+            next_update,
+            None,
+            None,
         )
         from cryptography.hazmat.backends.openssl.backend import backend
+
         diff_key = ec.generate_private_key(ec.SECP256R1(), backend)
         with pytest.raises(ValueError):
             builder.sign(diff_key, hashes.SHA256())
@@ -522,13 +651,19 @@
         current_time = datetime.datetime.utcnow().replace(microsecond=0)
         this_update = current_time - datetime.timedelta(days=1)
         next_update = this_update + datetime.timedelta(days=7)
-        builder = builder.responder_id(
-            ocsp.OCSPResponderEncoding.HASH, root_cert
-        ).add_response(
-            cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.GOOD, this_update,
-            next_update, None, None
-        ).add_extension(
-            x509.OCSPNonce(b"012345"), False
+        builder = (
+            builder.responder_id(ocsp.OCSPResponderEncoding.HASH, root_cert)
+            .add_response(
+                cert,
+                issuer,
+                hashes.SHA1(),
+                ocsp.OCSPCertStatus.GOOD,
+                this_update,
+                next_update,
+                None,
+                None,
+            )
+            .add_extension(x509.OCSPNonce(b"012345"), False)
         )
         resp = builder.sign(private_key, hashes.SHA256())
         assert len(resp.extensions) == 1
@@ -546,7 +681,7 @@
             (ocsp.OCSPResponseStatus.TRY_LATER, b"0\x03\n\x01\x03"),
             (ocsp.OCSPResponseStatus.SIG_REQUIRED, b"0\x03\n\x01\x05"),
             (ocsp.OCSPResponseStatus.UNAUTHORIZED, b"0\x03\n\x01\x06"),
-        ]
+        ],
     )
     def test_build_non_successful_statuses(self, status, der):
         resp = ocsp.OCSPResponseBuilder.build_unsuccessful(status)
@@ -564,6 +699,92 @@
             )
 
 
+class TestSignedCertificateTimestampsExtension(object):
+    def test_init(self):
+        with pytest.raises(TypeError):
+            x509.SignedCertificateTimestamps([object()])
+
+    def test_repr(self):
+        assert repr(x509.SignedCertificateTimestamps([])) == (
+            "<SignedCertificateTimestamps([])>"
+        )
+
+    @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(
+                os.path.join("x509", "ocsp", "resp-sct-extension.der"),
+                ocsp.load_der_ocsp_response,
+            )
+            .single_extensions.get_extension_for_class(
+                x509.SignedCertificateTimestamps
+            )
+            .value
+        )
+        sct2 = (
+            _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 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(
+                os.path.join("x509", "ocsp", "resp-sct-extension.der"),
+                ocsp.load_der_ocsp_response,
+            )
+            .single_extensions.get_extension_for_class(
+                x509.SignedCertificateTimestamps
+            )
+            .value
+        )
+        sct2 = x509.SignedCertificateTimestamps([])
+        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(
+                os.path.join("x509", "ocsp", "resp-sct-extension.der"),
+                ocsp.load_der_ocsp_response,
+            )
+            .single_extensions.get_extension_for_class(
+                x509.SignedCertificateTimestamps
+            )
+            .value
+        )
+        sct2 = (
+            _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
+        )
+        sct3 = x509.SignedCertificateTimestamps([])
+        assert hash(sct1) == hash(sct2)
+        assert hash(sct1) != hash(sct3)
+
+
 class TestOCSPResponse(object):
     def test_bad_response(self):
         with pytest.raises(ValueError):
@@ -575,14 +796,17 @@
             ocsp.load_der_ocsp_response,
         )
         from cryptography.hazmat.backends.openssl.backend import backend
+
         issuer = _load_cert(
             os.path.join("x509", "letsencryptx3.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         assert resp.response_status == ocsp.OCSPResponseStatus.SUCCESSFUL
-        assert (resp.signature_algorithm_oid ==
-                x509.SignatureAlgorithmOID.RSA_WITH_SHA256)
+        assert (
+            resp.signature_algorithm_oid
+            == x509.SignatureAlgorithmOID.RSA_WITH_SHA256
+        )
         assert isinstance(resp.signature_hash_algorithm, hashes.SHA256)
         assert resp.signature == base64.b64decode(
             b"I9KUlyLV/2LbNCVu1BQphxdNlU/jBzXsPYVscPjW5E93pCrSO84GkIWoOJtqsnt"
@@ -603,7 +827,7 @@
             resp.signature,
             resp.tbs_response_bytes,
             PKCS1v15(),
-            resp.signature_hash_algorithm
+            resp.signature_hash_algorithm,
         )
         assert resp.certificates == []
         assert resp.responder_key_hash is None
@@ -615,15 +839,22 @@
         assert resp.this_update == datetime.datetime(2018, 8, 30, 11, 0)
         assert resp.next_update == datetime.datetime(2018, 9, 6, 11, 0)
         assert resp.issuer_key_hash == (
-            b'\xa8Jjc\x04}\xdd\xba\xe6\xd19\xb7\xa6Ee\xef\xf3\xa8\xec\xa1'
+            b"\xa8Jjc\x04}\xdd\xba\xe6\xd19\xb7\xa6Ee\xef\xf3\xa8\xec\xa1"
         )
         assert resp.issuer_name_hash == (
-            b'~\xe6j\xe7r\x9a\xb3\xfc\xf8\xa2 dl\x16\xa1-`q\x08]'
+            b"~\xe6j\xe7r\x9a\xb3\xfc\xf8\xa2 dl\x16\xa1-`q\x08]"
         )
         assert isinstance(resp.hash_algorithm, hashes.SHA1)
         assert resp.serial_number == 271024907440004808294641238224534273948400
         assert len(resp.extensions) == 0
 
+    def test_load_multi_valued_response(self):
+        with pytest.raises(ValueError):
+            _load_data(
+                os.path.join("x509", "ocsp", "ocsp-army.deps.mil-resp.der"),
+                ocsp.load_der_ocsp_response,
+            )
+
     def test_load_unauthorized(self):
         resp = _load_data(
             os.path.join("x509", "ocsp", "resp-unauthorized.der"),
@@ -705,7 +936,7 @@
         )
         assert resp.responder_name is None
         assert resp.responder_key_hash == (
-            b'\x0f\x80a\x1c\x821a\xd5/(\xe7\x8dF8\xb4,\xe1\xc6\xd9\xe2'
+            b"\x0f\x80a\x1c\x821a\xd5/(\xe7\x8dF8\xb4,\xe1\xc6\xd9\xe2"
         )
 
     def test_load_revoked_reason(self):
@@ -739,7 +970,7 @@
         resp_bytes = load_vectors_from_file(
             filename=os.path.join("x509", "ocsp", "resp-revoked.der"),
             loader=lambda data: data.read(),
-            mode="rb"
+            mode="rb",
         )
         resp = ocsp.load_der_ocsp_response(resp_bytes)
         assert resp.public_bytes(serialization.Encoding.DER) == resp_bytes
@@ -753,3 +984,161 @@
             resp.public_bytes("invalid")
         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"),
+            ocsp.load_der_ocsp_response,
+        )
+        assert len(resp.single_extensions) == 1
+        ext = resp.single_extensions[0]
+        assert ext.oid == x509.ObjectIdentifier("1.3.6.1.4.1.11129.2.4.5")
+        assert len(ext.value) == 4
+        log_ids = [base64.b64encode(sct.log_id) for sct in ext.value]
+        assert log_ids == [
+            b"RJRlLrDuzq/EQAfYqP4owNrmgr7YyzG1P9MzlrW2gag=",
+            b"b1N2rDHwMRnYmQCkURX/dxUcEdkCwQApBo2yCJo32RM=",
+            b"u9nfvB+KcbWTlCOXqpJ7RzhXlQqrUugakJZkNo4e0YU=",
+            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"),
+            ocsp.load_der_ocsp_response,
+        )
+        assert len(resp.single_extensions) == 1
+        ext = resp.single_extensions[0]
+        assert ext.oid == x509.CRLReason.oid
+        assert ext.value == x509.CRLReason(x509.ReasonFlags.unspecified)
+
+
+class TestOCSPEdDSA(object):
+    @pytest.mark.supported(
+        only_if=lambda backend: backend.ed25519_supported(),
+        skip_message="Requires OpenSSL with Ed25519 support / OCSP",
+    )
+    def test_invalid_algorithm(self, backend):
+        builder = ocsp.OCSPResponseBuilder()
+        cert, issuer = _cert_and_issuer()
+        private_key = ed25519.Ed25519PrivateKey.generate()
+        root_cert, _ = _generate_root(private_key, None)
+        current_time = datetime.datetime.utcnow().replace(microsecond=0)
+        this_update = current_time - datetime.timedelta(days=1)
+        next_update = this_update + datetime.timedelta(days=7)
+        revoked_date = this_update - datetime.timedelta(days=300)
+        builder = builder.responder_id(
+            ocsp.OCSPResponderEncoding.NAME, root_cert
+        ).add_response(
+            cert,
+            issuer,
+            hashes.SHA1(),
+            ocsp.OCSPCertStatus.REVOKED,
+            this_update,
+            next_update,
+            revoked_date,
+            x509.ReasonFlags.key_compromise,
+        )
+        with pytest.raises(ValueError):
+            builder.sign(private_key, hashes.SHA256())
+
+    @pytest.mark.supported(
+        only_if=lambda backend: backend.ed25519_supported(),
+        skip_message="Requires OpenSSL with Ed25519 support / OCSP",
+    )
+    def test_sign_ed25519(self, backend):
+        builder = ocsp.OCSPResponseBuilder()
+        cert, issuer = _cert_and_issuer()
+        private_key = ed25519.Ed25519PrivateKey.generate()
+        root_cert, _ = _generate_root(private_key, None)
+        current_time = datetime.datetime.utcnow().replace(microsecond=0)
+        this_update = current_time - datetime.timedelta(days=1)
+        next_update = this_update + datetime.timedelta(days=7)
+        revoked_date = this_update - datetime.timedelta(days=300)
+        builder = builder.responder_id(
+            ocsp.OCSPResponderEncoding.NAME, root_cert
+        ).add_response(
+            cert,
+            issuer,
+            hashes.SHA1(),
+            ocsp.OCSPCertStatus.REVOKED,
+            this_update,
+            next_update,
+            revoked_date,
+            x509.ReasonFlags.key_compromise,
+        )
+        resp = builder.sign(private_key, None)
+        assert resp.certificate_status == ocsp.OCSPCertStatus.REVOKED
+        assert resp.revocation_time == revoked_date
+        assert resp.revocation_reason is x509.ReasonFlags.key_compromise
+        assert resp.this_update == this_update
+        assert resp.next_update == next_update
+        assert resp.signature_hash_algorithm is None
+        assert (
+            resp.signature_algorithm_oid == x509.SignatureAlgorithmOID.ED25519
+        )
+        private_key.public_key().verify(
+            resp.signature, resp.tbs_response_bytes
+        )
+
+    @pytest.mark.supported(
+        only_if=lambda backend: backend.ed448_supported(),
+        skip_message="Requires OpenSSL with Ed448 support / OCSP",
+    )
+    def test_sign_ed448(self, backend):
+        builder = ocsp.OCSPResponseBuilder()
+        cert, issuer = _cert_and_issuer()
+        private_key = ed448.Ed448PrivateKey.generate()
+        root_cert, _ = _generate_root(private_key, None)
+        current_time = datetime.datetime.utcnow().replace(microsecond=0)
+        this_update = current_time - datetime.timedelta(days=1)
+        next_update = this_update + datetime.timedelta(days=7)
+        revoked_date = this_update - datetime.timedelta(days=300)
+        builder = builder.responder_id(
+            ocsp.OCSPResponderEncoding.NAME, root_cert
+        ).add_response(
+            cert,
+            issuer,
+            hashes.SHA1(),
+            ocsp.OCSPCertStatus.REVOKED,
+            this_update,
+            next_update,
+            revoked_date,
+            x509.ReasonFlags.key_compromise,
+        )
+        resp = builder.sign(private_key, None)
+        assert resp.certificate_status == ocsp.OCSPCertStatus.REVOKED
+        assert resp.revocation_time == revoked_date
+        assert resp.revocation_reason is x509.ReasonFlags.key_compromise
+        assert resp.this_update == this_update
+        assert resp.next_update == next_update
+        assert resp.signature_hash_algorithm is None
+        assert resp.signature_algorithm_oid == x509.SignatureAlgorithmOID.ED448
+        private_key.public_key().verify(
+            resp.signature, resp.tbs_response_bytes
+        )
diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py
index c8c863f..146619b 100644
--- a/tests/x509/test_x509.py
+++ b/tests/x509/test_x509.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-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.
@@ -5,12 +6,12 @@
 from __future__ import absolute_import, division, print_function
 
 import binascii
+import collections
+import copy
 import datetime
 import ipaddress
 import os
 
-from asn1crypto.x509 import Certificate
-
 import pytest
 
 import pytz
@@ -19,25 +20,54 @@
 
 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.backends.interfaces import (
-    DSABackend, EllipticCurveBackend, RSABackend, X509Backend
+    DSABackend,
+    EllipticCurveBackend,
+    RSABackend,
+    X509Backend,
 )
 from cryptography.hazmat.primitives import hashes, serialization
-from cryptography.hazmat.primitives.asymmetric import dsa, ec, padding, rsa
-from cryptography.hazmat.primitives.asymmetric.utils import (
-    decode_dss_signature
+from cryptography.hazmat.primitives.asymmetric import (
+    dh,
+    dsa,
+    ec,
+    ed25519,
+    ed448,
+    padding,
+    rsa,
 )
+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, ExtendedKeyUsageOID, ExtensionOID,
-    NameOID, SignatureAlgorithmOID
+    AuthorityInformationAccessOID,
+    ExtendedKeyUsageOID,
+    ExtensionOID,
+    NameOID,
+    SignatureAlgorithmOID,
+    SubjectInformationAccessOID,
 )
 
 from ..hazmat.primitives.fixtures_dsa import DSA_KEY_2048
 from ..hazmat.primitives.fixtures_ec import EC_KEY_SECP256R1
 from ..hazmat.primitives.fixtures_rsa import RSA_KEY_2048, RSA_KEY_512
 from ..hazmat.primitives.test_ec import _skip_curve_unsupported
-from ..utils import load_vectors_from_file
+from ..utils import load_nist_vectors, load_vectors_from_file
 
 
 @utils.register_interface(x509.ExtensionType)
@@ -57,18 +87,64 @@
     cert = load_vectors_from_file(
         filename=filename,
         loader=lambda pemfile: loader(pemfile.read(), backend),
-        mode="rb"
+        mode="rb",
     )
     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 | CONSTRUCTED | 1)
+        # Skip subjectUniqueID
+        _ = tbs_cert.read_optional_element(CONTEXT_SPECIFIC | CONSTRUCTED | 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,
+    )
+
+
 @pytest.mark.requires_backend_interface(interface=X509Backend)
 class TestCertificateRevocationList(object):
     def test_load_pem_crl(self, backend):
         crl = _load_cert(
             os.path.join("x509", "custom", "crl_all_reasons.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
 
         assert isinstance(crl, x509.CertificateRevocationList)
@@ -76,15 +152,15 @@
         assert fingerprint == b"3234b0cb4c0cedf6423724b736729dcfc9e441ef"
         assert isinstance(crl.signature_hash_algorithm, hashes.SHA256)
         assert (
-            crl.signature_algorithm_oid ==
-            SignatureAlgorithmOID.RSA_WITH_SHA256
+            crl.signature_algorithm_oid
+            == SignatureAlgorithmOID.RSA_WITH_SHA256
         )
 
     def test_load_der_crl(self, backend):
         crl = _load_cert(
             os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
             x509.load_der_x509_crl,
-            backend
+            backend,
         )
 
         assert isinstance(crl, x509.CertificateRevocationList)
@@ -106,48 +182,48 @@
                 "x509", "custom", "crl_md2_unknown_crit_entry_ext.pem"
             ),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
 
         with pytest.raises(UnsupportedAlgorithm):
-                crl.signature_hash_algorithm()
+            crl.signature_hash_algorithm()
 
     def test_issuer(self, backend):
         crl = _load_cert(
             os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
             x509.load_der_x509_crl,
-            backend
+            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, u"US"),
             x509.NameAttribute(
-                x509.OID_ORGANIZATION_NAME, u'Test Certificates 2011'
+                x509.OID_ORGANIZATION_NAME, u"Test Certificates 2011"
             ),
-            x509.NameAttribute(x509.OID_COMMON_NAME, u'Good CA')
+            x509.NameAttribute(x509.OID_COMMON_NAME, u"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, u"Good CA")
         ]
 
     def test_equality(self, backend):
         crl1 = _load_cert(
             os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
             x509.load_der_x509_crl,
-            backend
+            backend,
         )
 
         crl2 = _load_cert(
             os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
             x509.load_der_x509_crl,
-            backend
+            backend,
         )
 
         crl3 = _load_cert(
             os.path.join("x509", "custom", "crl_all_reasons.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
 
         assert crl1 == crl2
@@ -158,7 +234,7 @@
         crl = _load_cert(
             os.path.join("x509", "custom", "crl_all_reasons.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
 
         assert isinstance(crl.next_update, datetime.datetime)
@@ -171,7 +247,7 @@
         crl = _load_cert(
             os.path.join("x509", "custom", "crl_all_reasons.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
 
         for r in crl:
@@ -183,9 +259,10 @@
     def test_get_revoked_certificate_by_serial_number(self, backend):
         crl = _load_cert(
             os.path.join(
-                "x509", "PKITS_data", "crls", "LongSerialNumberCACRL.crl"),
+                "x509", "PKITS_data", "crls", "LongSerialNumberCACRL.crl"
+            ),
             x509.load_der_x509_crl,
-            backend
+            backend,
         )
         serial_number = 725064303890588110203033396814564464046290047507
         revoked = crl.get_revoked_certificate_by_serial_number(serial_number)
@@ -201,7 +278,7 @@
         revoked = _load_cert(
             os.path.join("x509", "custom", "crl_all_reasons.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )[11]
         assert revoked.revocation_date == datetime.datetime(2015, 1, 1, 0, 0)
         assert revoked.serial_number == 11
@@ -210,7 +287,7 @@
         crl = _load_cert(
             os.path.join("x509", "custom", "crl_ian_aia_aki.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
 
         crl_number = crl.extensions.get_extension_for_oid(
@@ -228,40 +305,40 @@
         assert crl_number.value == x509.CRLNumber(1)
         assert crl_number.critical is False
         assert aki.value == x509.AuthorityKeyIdentifier(
-            key_identifier=(
-                b'yu\xbb\x84:\xcb,\xdez\t\xbe1\x1bC\xbc\x1c*MSX'
-            ),
+            key_identifier=(b"yu\xbb\x84:\xcb,\xdez\t\xbe1\x1bC\xbc\x1c*MSX"),
             authority_cert_issuer=None,
-            authority_cert_serial_number=None
+            authority_cert_serial_number=None,
         )
-        assert aia.value == x509.AuthorityInformationAccess([
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.CA_ISSUERS,
-                x509.DNSName(u"cryptography.io")
-            )
-        ])
-        assert ian.value == x509.IssuerAlternativeName([
-            x509.UniformResourceIdentifier(u"https://cryptography.io"),
-        ])
+        assert aia.value == x509.AuthorityInformationAccess(
+            [
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.CA_ISSUERS,
+                    x509.DNSName(u"cryptography.io"),
+                )
+            ]
+        )
+        assert ian.value == x509.IssuerAlternativeName(
+            [x509.UniformResourceIdentifier(u"https://cryptography.io")]
+        )
 
     def test_delta_crl_indicator(self, backend):
         crl = _load_cert(
             os.path.join("x509", "custom", "crl_delta_crl_indicator.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
 
         dci = crl.extensions.get_extension_for_oid(
             ExtensionOID.DELTA_CRL_INDICATOR
         )
         assert dci.value == x509.DeltaCRLIndicator(12345678901234567890)
-        assert dci.critical is False
+        assert dci.critical is True
 
     def test_signature(self, backend):
         crl = _load_cert(
             os.path.join("x509", "custom", "crl_all_reasons.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
 
         assert crl.signature == binascii.unhexlify(
@@ -280,31 +357,36 @@
         crl = _load_cert(
             os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
             x509.load_der_x509_crl,
-            backend
+            backend,
         )
 
         ca_cert = _load_cert(
             os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
 
         ca_cert.public_key().verify(
-            crl.signature, crl.tbs_certlist_bytes,
-            padding.PKCS1v15(), crl.signature_hash_algorithm
+            crl.signature,
+            crl.tbs_certlist_bytes,
+            padding.PKCS1v15(),
+            crl.signature_hash_algorithm,
         )
 
     def test_public_bytes_pem(self, backend):
         crl = _load_cert(
             os.path.join("x509", "custom", "crl_empty.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
 
         # Encode it to PEM and load it back.
-        crl = x509.load_pem_x509_crl(crl.public_bytes(
-            encoding=serialization.Encoding.PEM,
-        ), backend)
+        crl = x509.load_pem_x509_crl(
+            crl.public_bytes(
+                encoding=serialization.Encoding.PEM,
+            ),
+            backend,
+        )
 
         assert len(crl) == 0
         assert crl.last_update == datetime.datetime(2015, 12, 20, 23, 44, 47)
@@ -314,13 +396,16 @@
         crl = _load_cert(
             os.path.join("x509", "custom", "crl_all_reasons.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
 
         # Encode it to DER and load it back.
-        crl = x509.load_der_x509_crl(crl.public_bytes(
-            encoding=serialization.Encoding.DER,
-        ), backend)
+        crl = x509.load_der_x509_crl(
+            crl.public_bytes(
+                encoding=serialization.Encoding.DER,
+            ),
+            backend,
+        )
 
         assert len(crl) == 12
         assert crl.last_update == datetime.datetime(2015, 1, 1, 0, 0, 0)
@@ -339,10 +424,11 @@
                 x509.load_der_x509_crl,
                 serialization.Encoding.DER,
             ),
-        ]
+        ],
     )
-    def test_public_bytes_match(self, cert_path, loader_func, encoding,
-                                backend):
+    def test_public_bytes_match(
+        self, cert_path, loader_func, encoding, backend
+    ):
         crl_bytes = load_vectors_from_file(
             cert_path, lambda pemfile: pemfile.read(), mode="rb"
         )
@@ -354,22 +440,22 @@
         crl = _load_cert(
             os.path.join("x509", "custom", "crl_empty.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
 
         with pytest.raises(TypeError):
-            crl.public_bytes('NotAnEncoding')
+            crl.public_bytes("NotAnEncoding")
 
     def test_verify_bad(self, backend):
         crl = _load_cert(
             os.path.join("x509", "custom", "invalid_signature.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
         crt = _load_cert(
             os.path.join("x509", "custom", "invalid_signature.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
 
         assert not crl.is_signature_valid(crt.public_key())
@@ -378,12 +464,12 @@
         crl = _load_cert(
             os.path.join("x509", "custom", "valid_signature.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
         crt = _load_cert(
             os.path.join("x509", "custom", "valid_signature.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
 
         assert crl.is_signature_valid(crt.public_key())
@@ -392,7 +478,7 @@
         crl = _load_cert(
             os.path.join("x509", "custom", "valid_signature.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
 
         with pytest.raises(TypeError):
@@ -408,7 +494,7 @@
         crl = _load_cert(
             os.path.join("x509", "custom", "crl_all_reasons.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
 
         for i, rev in enumerate(crl):
@@ -424,14 +510,20 @@
         crl = _load_cert(
             os.path.join("x509", "custom", "crl_all_reasons.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
 
         exp_issuer = [
-            x509.DirectoryName(x509.Name([
-                x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US"),
-                x509.NameAttribute(x509.OID_COMMON_NAME, u"cryptography.io"),
-            ]))
+            x509.DirectoryName(
+                x509.Name(
+                    [
+                        x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US"),
+                        x509.NameAttribute(
+                            x509.OID_COMMON_NAME, u"cryptography.io"
+                        ),
+                    ]
+                )
+            )
         ]
 
         # First revoked cert doesn't have extensions, test if it is handled
@@ -451,16 +543,17 @@
         rev1 = crl[1]
         assert isinstance(rev1.extensions, x509.Extensions)
 
-        reason = rev1.extensions.get_extension_for_class(
-            x509.CRLReason).value
+        reason = rev1.extensions.get_extension_for_class(x509.CRLReason).value
         assert reason == x509.CRLReason(x509.ReasonFlags.unspecified)
 
         issuer = rev1.extensions.get_extension_for_class(
-            x509.CertificateIssuer).value
+            x509.CertificateIssuer
+        ).value
         assert issuer == x509.CertificateIssuer(exp_issuer)
 
         date = rev1.extensions.get_extension_for_class(
-            x509.InvalidityDate).value
+            x509.InvalidityDate
+        ).value
         assert date == x509.InvalidityDate(datetime.datetime(2015, 1, 1, 0, 0))
 
         # Check if all reason flags can be found in the CRL.
@@ -480,7 +573,7 @@
         crl = _load_cert(
             os.path.join("x509", "custom", "crl_empty.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
         assert len(crl) == 0
 
@@ -488,7 +581,7 @@
         crl = _load_cert(
             os.path.join("x509", "custom", "crl_dup_entry_ext.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
 
         with pytest.raises(x509.DuplicateExtension):
@@ -500,7 +593,7 @@
                 "x509", "custom", "crl_md2_unknown_crit_entry_ext.pem"
             ),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
 
         ext = crl[0].extensions.get_extension_for_oid(
@@ -510,11 +603,9 @@
 
     def test_unsupported_reason(self, backend):
         crl = _load_cert(
-            os.path.join(
-                "x509", "custom", "crl_unsupported_reason.pem"
-            ),
+            os.path.join("x509", "custom", "crl_unsupported_reason.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
 
         with pytest.raises(ValueError):
@@ -526,7 +617,7 @@
                 "x509", "custom", "crl_inval_cert_issuer_entry_ext.pem"
             ),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
 
         with pytest.raises(ValueError):
@@ -536,7 +627,7 @@
         crl = _load_cert(
             os.path.join("x509", "custom", "crl_all_reasons.pem"),
             x509.load_pem_x509_crl,
-            backend
+            backend,
         )
 
         with pytest.raises(IndexError):
@@ -553,21 +644,27 @@
         private_key = RSA_KEY_2048.private_key(backend)
         last_update = datetime.datetime(2002, 1, 1, 12, 1)
         next_update = datetime.datetime(2030, 1, 1, 12, 1)
-        builder = x509.CertificateRevocationListBuilder().issuer_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
-            ])
-        ).last_update(
-            last_update
-        ).next_update(
-            next_update
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_update)
+            .next_update(next_update)
         )
         for i in [2, 500, 3, 49, 7, 1]:
-            revoked_cert = x509.RevokedCertificateBuilder().serial_number(
-                i
-            ).revocation_date(
-                datetime.datetime(2012, 1, 1, 1, 1)
-            ).build(backend)
+            revoked_cert = (
+                x509.RevokedCertificateBuilder()
+                .serial_number(i)
+                .revocation_date(datetime.datetime(2012, 1, 1, 1, 1))
+                .build(backend)
+            )
             builder = builder.add_revoked_certificate(revoked_cert)
         crl = builder.sign(private_key, hashes.SHA256(), backend)
         assert crl[0].serial_number == 2
@@ -586,7 +683,7 @@
         cert = _load_cert(
             os.path.join("x509", "custom", "post2000utctime.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         assert isinstance(cert, x509.Certificate)
         assert cert.serial_number == 11559813051657483483
@@ -597,44 +694,31 @@
             cert.signature_algorithm_oid == SignatureAlgorithmOID.RSA_WITH_SHA1
         )
 
+    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
+
     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,
-            backend
+            backend,
         )
         assert isinstance(cert.signature_hash_algorithm, hashes.SHA1)
         assert (
-            cert.signature_algorithm_oid ==
-            SignatureAlgorithmOID._RSA_WITH_SHA1
+            cert.signature_algorithm_oid
+            == SignatureAlgorithmOID._RSA_WITH_SHA1
         )
 
-    def test_cert_serial_number(self, backend):
-        cert = _load_cert(
-            os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
-            x509.load_der_x509_certificate,
-            backend
-        )
-
-        with pytest.warns(utils.CryptographyDeprecationWarning):
-            assert cert.serial == 2
-            assert cert.serial_number == 2
-
-    def test_cert_serial_warning(self, backend):
-        cert = _load_cert(
-            os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
-            x509.load_der_x509_certificate,
-            backend
-        )
-
-        with pytest.warns(utils.CryptographyDeprecationWarning):
-            cert.serial
-
     def test_load_der_cert(self, backend):
         cert = _load_cert(
             os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
         assert isinstance(cert, x509.Certificate)
         assert cert.serial_number == 2
@@ -646,7 +730,7 @@
         cert = _load_cert(
             os.path.join("x509", "custom", "post2000utctime.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         assert cert.signature == binascii.unhexlify(
             b"8e0f72fcbebe4755abcaf76c8ce0bae17cde4db16291638e1b1ce04a93cdb4c"
@@ -665,7 +749,7 @@
         cert = _load_cert(
             os.path.join("x509", "custom", "post2000utctime.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         assert cert.tbs_certificate_bytes == binascii.unhexlify(
             b"308202d8a003020102020900a06cb4b955f7f4db300d06092a864886f70d010"
@@ -694,132 +778,126 @@
             b"3040530030101ff"
         )
         cert.public_key().verify(
-            cert.signature, cert.tbs_certificate_bytes,
-            padding.PKCS1v15(), cert.signature_hash_algorithm
+            cert.signature,
+            cert.tbs_certificate_bytes,
+            padding.PKCS1v15(),
+            cert.signature_hash_algorithm,
         )
 
     def test_issuer(self, backend):
         cert = _load_cert(
             os.path.join(
-                "x509", "PKITS_data", "certs",
-                "Validpre2000UTCnotBeforeDateTest3EE.crt"
+                "x509",
+                "PKITS_data",
+                "certs",
+                "Validpre2000UTCnotBeforeDateTest3EE.crt",
             ),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
         issuer = cert.issuer
         assert isinstance(issuer, x509.Name)
         assert list(issuer) == [
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
+            x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
             x509.NameAttribute(
-                NameOID.ORGANIZATION_NAME, u'Test Certificates 2011'
+                NameOID.ORGANIZATION_NAME, u"Test Certificates 2011"
             ),
-            x509.NameAttribute(NameOID.COMMON_NAME, u'Good CA')
+            x509.NameAttribute(NameOID.COMMON_NAME, u"Good CA"),
         ]
         assert issuer.get_attributes_for_oid(NameOID.COMMON_NAME) == [
-            x509.NameAttribute(NameOID.COMMON_NAME, u'Good CA')
+            x509.NameAttribute(NameOID.COMMON_NAME, u"Good CA")
         ]
 
     def test_all_issuer_name_types(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom",
-                "all_supported_names.pem"
-            ),
+            os.path.join("x509", "custom", "all_supported_names.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         issuer = cert.issuer
 
         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, 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"),
         ]
 
     def test_subject(self, backend):
         cert = _load_cert(
             os.path.join(
-                "x509", "PKITS_data", "certs",
-                "Validpre2000UTCnotBeforeDateTest3EE.crt"
+                "x509",
+                "PKITS_data",
+                "certs",
+                "Validpre2000UTCnotBeforeDateTest3EE.crt",
             ),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
         subject = cert.subject
         assert isinstance(subject, x509.Name)
         assert list(subject) == [
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
+            x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
             x509.NameAttribute(
-                NameOID.ORGANIZATION_NAME, u'Test Certificates 2011'
+                NameOID.ORGANIZATION_NAME, u"Test Certificates 2011"
             ),
             x509.NameAttribute(
                 NameOID.COMMON_NAME,
-                u'Valid pre2000 UTC notBefore Date EE Certificate Test3'
-            )
+                u"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'
+                u"Valid pre2000 UTC notBefore Date EE Certificate Test3",
             )
         ]
 
     def test_unicode_name(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom",
-                "utf8_common_name.pem"
-            ),
+            os.path.join("x509", "custom", "utf8_common_name.pem"),
             x509.load_pem_x509_certificate,
-            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, u"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, u"We heart UTF8!\u2122")
         ]
 
     def test_non_ascii_dns_name(self, backend):
         cert = _load_cert(
             os.path.join("x509", "utf8-dnsname.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         san = cert.extensions.get_extension_for_class(
             x509.SubjectAlternativeName
@@ -828,64 +906,65 @@
         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'
+            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",
         ]
 
     def test_all_subject_name_types(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom",
-                "all_supported_names.pem"
-            ),
+            os.path.join("x509", "custom", "all_supported_names.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            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, 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.ORGANIZATIONAL_UNIT_NAME, u'Engineering 0'
+                NameOID.ORGANIZATIONAL_UNIT_NAME, u"Engineering 0"
             ),
             x509.NameAttribute(
-                NameOID.ORGANIZATIONAL_UNIT_NAME, u'Engineering 1'
+                NameOID.ORGANIZATIONAL_UNIT_NAME, u"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, 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"),
         ]
 
     def test_load_good_ca_cert(self, backend):
         cert = _load_cert(
             os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
 
         assert cert.not_valid_before == datetime.datetime(2010, 1, 1, 8, 30)
@@ -900,11 +979,13 @@
     def test_utc_pre_2000_not_before_cert(self, backend):
         cert = _load_cert(
             os.path.join(
-                "x509", "PKITS_data", "certs",
-                "Validpre2000UTCnotBeforeDateTest3EE.crt"
+                "x509",
+                "PKITS_data",
+                "certs",
+                "Validpre2000UTCnotBeforeDateTest3EE.crt",
             ),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
 
         assert cert.not_valid_before == datetime.datetime(1950, 1, 1, 12, 1)
@@ -912,11 +993,13 @@
     def test_pre_2000_utc_not_after_cert(self, backend):
         cert = _load_cert(
             os.path.join(
-                "x509", "PKITS_data", "certs",
-                "Invalidpre2000UTCEEnotAfterDateTest7EE.crt"
+                "x509",
+                "PKITS_data",
+                "certs",
+                "Invalidpre2000UTCEEnotAfterDateTest7EE.crt",
             ),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
 
         assert cert.not_valid_after == datetime.datetime(1999, 1, 1, 12, 1)
@@ -925,7 +1008,7 @@
         cert = _load_cert(
             os.path.join("x509", "custom", "post2000utctime.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         assert cert.not_valid_before == datetime.datetime(
             2014, 11, 26, 21, 41, 20
@@ -937,11 +1020,13 @@
     def test_generalized_time_not_before_cert(self, backend):
         cert = _load_cert(
             os.path.join(
-                "x509", "PKITS_data", "certs",
-                "ValidGeneralizedTimenotBeforeDateTest4EE.crt"
+                "x509",
+                "PKITS_data",
+                "certs",
+                "ValidGeneralizedTimenotBeforeDateTest4EE.crt",
             ),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
         assert cert.not_valid_before == datetime.datetime(2002, 1, 1, 12, 1)
         assert cert.not_valid_after == datetime.datetime(2030, 12, 31, 8, 30)
@@ -950,24 +1035,25 @@
     def test_generalized_time_not_after_cert(self, backend):
         cert = _load_cert(
             os.path.join(
-                "x509", "PKITS_data", "certs",
-                "ValidGeneralizedTimenotAfterDateTest8EE.crt"
+                "x509",
+                "PKITS_data",
+                "certs",
+                "ValidGeneralizedTimenotAfterDateTest8EE.crt",
             ),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
         assert cert.not_valid_before == datetime.datetime(2010, 1, 1, 8, 30)
         assert cert.not_valid_after == datetime.datetime(2050, 1, 1, 12, 1)
         assert cert.version is x509.Version.v3
 
     def test_invalid_version_cert(self, backend):
-        cert = _load_cert(
-            os.path.join("x509", "custom", "invalid_version.pem"),
-            x509.load_pem_x509_certificate,
-            backend
-        )
         with pytest.raises(x509.InvalidVersion) as exc:
-            cert.version
+            _load_cert(
+                os.path.join("x509", "custom", "invalid_version.pem"),
+                x509.load_pem_x509_certificate,
+                backend,
+            )
 
         assert exc.value.parsed_version == 7
 
@@ -975,12 +1061,12 @@
         cert = _load_cert(
             os.path.join("x509", "custom", "post2000utctime.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         cert2 = _load_cert(
             os.path.join("x509", "custom", "post2000utctime.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         assert cert == cert2
 
@@ -988,15 +1074,17 @@
         cert = _load_cert(
             os.path.join("x509", "custom", "post2000utctime.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         cert2 = _load_cert(
             os.path.join(
-                "x509", "PKITS_data", "certs",
-                "ValidGeneralizedTimenotAfterDateTest8EE.crt"
+                "x509",
+                "PKITS_data",
+                "certs",
+                "ValidGeneralizedTimenotAfterDateTest8EE.crt",
             ),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
         assert cert != cert2
         assert cert != object()
@@ -1005,20 +1093,22 @@
         cert1 = _load_cert(
             os.path.join("x509", "custom", "post2000utctime.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         cert2 = _load_cert(
             os.path.join("x509", "custom", "post2000utctime.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         cert3 = _load_cert(
             os.path.join(
-                "x509", "PKITS_data", "certs",
-                "ValidGeneralizedTimenotAfterDateTest8EE.crt"
+                "x509",
+                "PKITS_data",
+                "certs",
+                "ValidGeneralizedTimenotAfterDateTest8EE.crt",
             ),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
 
         assert hash(cert1) == hash(cert2)
@@ -1028,7 +1118,7 @@
         cert = _load_cert(
             os.path.join("x509", "v1_cert.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         assert cert.version is x509.Version.v1
 
@@ -1044,7 +1134,7 @@
         cert = _load_cert(
             os.path.join("x509", "verisign_md2_root.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         with pytest.raises(UnsupportedAlgorithm):
             cert.signature_hash_algorithm
@@ -1054,13 +1144,16 @@
         cert = _load_cert(
             os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
 
         # Encode it to PEM and load it back.
-        cert = x509.load_pem_x509_certificate(cert.public_bytes(
-            encoding=serialization.Encoding.PEM,
-        ), backend)
+        cert = x509.load_pem_x509_certificate(
+            cert.public_bytes(
+                encoding=serialization.Encoding.PEM,
+            ),
+            backend,
+        )
 
         # We should recover what we had to start with.
         assert cert.not_valid_before == datetime.datetime(2010, 1, 1, 8, 30)
@@ -1077,13 +1170,16 @@
         cert = _load_cert(
             os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
 
         # Encode it to DER and load it back.
-        cert = x509.load_der_x509_certificate(cert.public_bytes(
-            encoding=serialization.Encoding.DER,
-        ), backend)
+        cert = x509.load_der_x509_certificate(
+            cert.public_bytes(
+                encoding=serialization.Encoding.DER,
+            ),
+            backend,
+        )
 
         # We should recover what we had to start with.
         assert cert.not_valid_before == datetime.datetime(2010, 1, 1, 8, 30)
@@ -1099,11 +1195,11 @@
         cert = _load_cert(
             os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
 
         with pytest.raises(TypeError):
-            cert.public_bytes('NotAnEncoding')
+            cert.public_bytes("NotAnEncoding")
 
     @pytest.mark.parametrize(
         ("cert_path", "loader_func", "encoding"),
@@ -1118,10 +1214,11 @@
                 x509.load_der_x509_certificate,
                 serialization.Encoding.DER,
             ),
-        ]
+        ],
     )
-    def test_public_bytes_match(self, cert_path, loader_func, encoding,
-                                backend):
+    def test_public_bytes_match(
+        self, cert_path, loader_func, encoding, backend
+    ):
         cert_bytes = load_vectors_from_file(
             cert_path, lambda pemfile: pemfile.read(), mode="rb"
         )
@@ -1131,11 +1228,9 @@
 
     def test_certificate_repr(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "cryptography.io.pem"
-            ),
+            os.path.join("x509", "cryptography.io.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         assert repr(cert) == (
             "<Certificate(subject=<Name(OU=GT48742965,OU=See www.rapidssl.com"
@@ -1147,7 +1242,7 @@
         cert = _load_cert(
             os.path.join("x509", "tls-feature-ocsp-staple.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_class(x509.TLSFeature)
         assert ext.critical is False
@@ -1164,39 +1259,99 @@
         [
             [
                 os.path.join("x509", "requests", "rsa_sha1.pem"),
-                x509.load_pem_x509_csr
+                x509.load_pem_x509_csr,
             ],
             [
                 os.path.join("x509", "requests", "rsa_sha1.der"),
-                x509.load_der_x509_csr
+                x509.load_der_x509_csr,
             ],
-        ]
+        ],
     )
     def test_load_rsa_certificate_request(self, path, loader_func, backend):
         request = _load_cert(path, loader_func, backend)
         assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
         assert (
-            request.signature_algorithm_oid ==
-            SignatureAlgorithmOID.RSA_WITH_SHA1
+            request.signature_algorithm_oid
+            == SignatureAlgorithmOID.RSA_WITH_SHA1
         )
         public_key = request.public_key()
         assert isinstance(public_key, rsa.RSAPublicKey)
         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, 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"),
         ]
         extensions = request.extensions
         assert isinstance(extensions, x509.Extensions)
         assert list(extensions) == []
 
+    def test_get_attribute_for_oid_challenge(self, backend):
+        request = _load_cert(
+            os.path.join("x509", "requests", "challenge.pem"),
+            x509.load_pem_x509_csr,
+            backend,
+        )
+        assert (
+            request.get_attribute_for_oid(
+                x509.oid.AttributeOID.CHALLENGE_PASSWORD
+            )
+            == b"challenge me!"
+        )
+
+    def test_get_attribute_for_oid_multiple(self, backend):
+        request = _load_cert(
+            os.path.join("x509", "requests", "challenge-unstructured.pem"),
+            x509.load_pem_x509_csr,
+            backend,
+        )
+        assert (
+            request.get_attribute_for_oid(
+                x509.oid.AttributeOID.CHALLENGE_PASSWORD
+            )
+            == b"beauty"
+        )
+        assert (
+            request.get_attribute_for_oid(
+                x509.oid.AttributeOID.UNSTRUCTURED_NAME
+            )
+            == b"an unstructured field"
+        )
+
+    def test_invalid_attribute_for_oid(self, backend):
+        """
+        This test deliberately triggers a ValueError because to parse
+        CSR attributes we need to do a C cast. If we're wrong about the
+        type that would be Very Bad so this test confirms we properly explode
+        in the presence of the wrong types.
+        """
+        request = _load_cert(
+            os.path.join("x509", "requests", "challenge-invalid.der"),
+            x509.load_der_x509_csr,
+            backend,
+        )
+        with pytest.raises(ValueError):
+            request.get_attribute_for_oid(
+                x509.oid.AttributeOID.CHALLENGE_PASSWORD
+            )
+
+    def test_no_challenge_password(self, backend):
+        request = _load_cert(
+            os.path.join("x509", "requests", "rsa_sha256.pem"),
+            x509.load_pem_x509_csr,
+            backend,
+        )
+        with pytest.raises(x509.AttributeNotFound) as exc:
+            request.get_attribute_for_oid(
+                x509.oid.AttributeOID.CHALLENGE_PASSWORD
+            )
+        assert exc.value.oid == x509.oid.AttributeOID.CHALLENGE_PASSWORD
+
     @pytest.mark.parametrize(
-        "loader_func",
-        [x509.load_pem_x509_csr, x509.load_der_x509_csr]
+        "loader_func", [x509.load_pem_x509_csr, x509.load_der_x509_csr]
     )
     def test_invalid_certificate_request(self, loader_func, backend):
         with pytest.raises(ValueError):
@@ -1206,18 +1361,16 @@
         request = _load_cert(
             os.path.join("x509", "requests", "rsa_md4.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
         with pytest.raises(UnsupportedAlgorithm):
             request.signature_hash_algorithm
 
     def test_duplicate_extension(self, backend):
         request = _load_cert(
-            os.path.join(
-                "x509", "requests", "two_basic_constraints.pem"
-            ),
+            os.path.join("x509", "requests", "two_basic_constraints.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
         with pytest.raises(x509.DuplicateExtension) as exc:
             request.extensions
@@ -1230,20 +1383,18 @@
                 "x509", "requests", "unsupported_extension_critical.pem"
             ),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
         ext = request.extensions.get_extension_for_oid(
-            x509.ObjectIdentifier('1.2.3.4')
+            x509.ObjectIdentifier("1.2.3.4")
         )
         assert ext.value.value == b"value"
 
     def test_unsupported_extension(self, backend):
         request = _load_cert(
-            os.path.join(
-                "x509", "requests", "unsupported_extension.pem"
-            ),
+            os.path.join("x509", "requests", "unsupported_extension.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
         extensions = request.extensions
         assert len(extensions) == 1
@@ -1254,11 +1405,9 @@
 
     def test_request_basic_constraints(self, backend):
         request = _load_cert(
-            os.path.join(
-                "x509", "requests", "basic_constraints.pem"
-            ),
+            os.path.join("x509", "requests", "basic_constraints.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
         extensions = request.extensions
         assert isinstance(extensions, x509.Extensions)
@@ -1289,13 +1438,16 @@
         request = _load_cert(
             os.path.join("x509", "requests", "rsa_sha1.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
 
         # Encode it to PEM and load it back.
-        request = x509.load_pem_x509_csr(request.public_bytes(
-            encoding=serialization.Encoding.PEM,
-        ), backend)
+        request = x509.load_pem_x509_csr(
+            request.public_bytes(
+                encoding=serialization.Encoding.PEM,
+            ),
+            backend,
+        )
 
         # We should recover what we had to start with.
         assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
@@ -1304,11 +1456,11 @@
         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, 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"),
         ]
 
     def test_public_bytes_der(self, backend):
@@ -1316,13 +1468,16 @@
         request = _load_cert(
             os.path.join("x509", "requests", "rsa_sha1.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
 
         # Encode it to DER and load it back.
-        request = x509.load_der_x509_csr(request.public_bytes(
-            encoding=serialization.Encoding.DER,
-        ), backend)
+        request = x509.load_der_x509_csr(
+            request.public_bytes(
+                encoding=serialization.Encoding.DER,
+            ),
+            backend,
+        )
 
         # We should recover what we had to start with.
         assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
@@ -1331,18 +1486,18 @@
         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, 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"),
         ]
 
     def test_signature(self, backend):
         request = _load_cert(
             os.path.join("x509", "requests", "rsa_sha1.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
         assert request.signature == binascii.unhexlify(
             b"8364c86ffbbfe0bfc9a21f831256658ca8989741b80576d36f08a934603a43b1"
@@ -1359,7 +1514,7 @@
         request = _load_cert(
             os.path.join("x509", "requests", "rsa_sha1.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
         assert request.tbs_certrequest_bytes == binascii.unhexlify(
             b"308201840201003057310b3009060355040613025553310e300c060355040813"
@@ -1380,24 +1535,24 @@
             request.signature,
             request.tbs_certrequest_bytes,
             padding.PKCS1v15(),
-            request.signature_hash_algorithm
+            request.signature_hash_algorithm,
         )
 
     def test_public_bytes_invalid_encoding(self, backend):
         request = _load_cert(
             os.path.join("x509", "requests", "rsa_sha1.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
 
         with pytest.raises(TypeError):
-            request.public_bytes('NotAnEncoding')
+            request.public_bytes("NotAnEncoding")
 
     def test_signature_invalid(self, backend):
         request = _load_cert(
             os.path.join("x509", "requests", "invalid_signature.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
         assert not request.is_signature_valid
 
@@ -1405,7 +1560,7 @@
         request = _load_cert(
             os.path.join("x509", "requests", "rsa_sha256.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
         assert request.is_signature_valid
 
@@ -1422,10 +1577,11 @@
                 x509.load_der_x509_csr,
                 serialization.Encoding.DER,
             ),
-        ]
+        ],
     )
-    def test_public_bytes_match(self, request_path, loader_func, encoding,
-                                backend):
+    def test_public_bytes_match(
+        self, request_path, loader_func, encoding, backend
+    ):
         request_bytes = load_vectors_from_file(
             request_path, lambda pemfile: pemfile.read(), mode="rb"
         )
@@ -1437,12 +1593,12 @@
         request1 = _load_cert(
             os.path.join("x509", "requests", "rsa_sha1.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
         request2 = _load_cert(
             os.path.join("x509", "requests", "rsa_sha1.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
 
         assert request1 == request2
@@ -1451,12 +1607,12 @@
         request1 = _load_cert(
             os.path.join("x509", "requests", "rsa_sha1.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
         request2 = _load_cert(
             os.path.join("x509", "requests", "san_rsa_sha1.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
 
         assert request1 != request2
@@ -1466,17 +1622,17 @@
         request1 = _load_cert(
             os.path.join("x509", "requests", "rsa_sha1.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
         request2 = _load_cert(
             os.path.join("x509", "requests", "rsa_sha1.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
         request3 = _load_cert(
             os.path.join("x509", "requests", "san_rsa_sha1.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
 
         assert hash(request1) == hash(request2)
@@ -1489,31 +1645,52 @@
         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, 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'),
-        ])).subject_name(x509.Name([
-            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'),
-        ])).public_key(
-            subject_private_key.public_key()
-        ).add_extension(
-            x509.BasicConstraints(ca=False, path_length=None), True,
-        ).add_extension(
-            x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]),
-            critical=False,
-        ).not_valid_before(
-            not_valid_before
-        ).not_valid_after(
-            not_valid_after
+        builder = (
+            x509.CertificateBuilder()
+            .serial_number(777)
+            .issuer_name(
+                x509.Name(
+                    [
+                        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"
+                        ),
+                    ]
+                )
+            )
+            .subject_name(
+                x509.Name(
+                    [
+                        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"
+                        ),
+                    ]
+                )
+            )
+            .public_key(subject_private_key.public_key())
+            .add_extension(
+                x509.BasicConstraints(ca=False, path_length=None),
+                True,
+            )
+            .add_extension(
+                x509.SubjectAlternativeName(
+                    [x509.DNSName(u"cryptography.io")]
+                ),
+                critical=False,
+            )
+            .not_valid_before(not_valid_before)
+            .not_valid_after(not_valid_after)
         )
 
         cert = builder.sign(issuer_private_key, hashes.SHA1(), backend)
@@ -1538,37 +1715,49 @@
         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)
-        name = x509.Name([
-            x509.NameAttribute(
-                NameOID.STATE_OR_PROVINCE_NAME, u'Texas',
-                _ASN1Type.PrintableString),
-            x509.NameAttribute(NameOID.LOCALITY_NAME, u'Austin'),
-            x509.NameAttribute(
-                NameOID.COMMON_NAME, u'cryptography.io', _ASN1Type.IA5String),
-        ])
-        builder = x509.CertificateBuilder().serial_number(
-            777
-        ).issuer_name(
-            name
-        ).subject_name(
-            name
-        ).public_key(
-            subject_private_key.public_key()
-        ).not_valid_before(
-            not_valid_before
-        ).not_valid_after(not_valid_after)
+        name = x509.Name(
+            [
+                x509.NameAttribute(
+                    NameOID.STATE_OR_PROVINCE_NAME,
+                    u"Texas",
+                    _ASN1Type.PrintableString,
+                ),
+                x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
+                x509.NameAttribute(
+                    NameOID.COMMON_NAME,
+                    u"cryptography.io",
+                    _ASN1Type.IA5String,
+                ),
+            ]
+        )
+        builder = (
+            x509.CertificateBuilder()
+            .serial_number(777)
+            .issuer_name(name)
+            .subject_name(name)
+            .public_key(subject_private_key.public_key())
+            .not_valid_before(not_valid_before)
+            .not_valid_after(not_valid_after)
+        )
         cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
 
         for dn in (cert.subject, cert.issuer):
-            assert dn.get_attributes_for_oid(
-                NameOID.STATE_OR_PROVINCE_NAME
-            )[0]._type == _ASN1Type.PrintableString
-            assert dn.get_attributes_for_oid(
-                NameOID.STATE_OR_PROVINCE_NAME
-            )[0]._type == _ASN1Type.PrintableString
-            assert dn.get_attributes_for_oid(
-                NameOID.LOCALITY_NAME
-            )[0]._type == _ASN1Type.UTF8String
+            assert (
+                dn.get_attributes_for_oid(NameOID.STATE_OR_PROVINCE_NAME)[
+                    0
+                ]._type
+                == _ASN1Type.PrintableString
+            )
+            assert (
+                dn.get_attributes_for_oid(NameOID.STATE_OR_PROVINCE_NAME)[
+                    0
+                ]._type
+                == _ASN1Type.PrintableString
+            )
+            assert (
+                dn.get_attributes_for_oid(NameOID.LOCALITY_NAME)[0]._type
+                == _ASN1Type.UTF8String
+            )
 
     def test_build_cert_printable_string_country_name(self, backend):
         issuer_private_key = RSA_KEY_2048.private_key(backend)
@@ -1577,41 +1766,65 @@
         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, u'US'),
-            x509.NameAttribute(NameOID.JURISDICTION_COUNTRY_NAME, u'US'),
-            x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
-        ])).subject_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-            x509.NameAttribute(NameOID.JURISDICTION_COUNTRY_NAME, u'US'),
-            x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
-        ])).public_key(
-            subject_private_key.public_key()
-        ).not_valid_before(
-            not_valid_before
-        ).not_valid_after(
-            not_valid_after
+        builder = (
+            x509.CertificateBuilder()
+            .serial_number(777)
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+                        x509.NameAttribute(
+                            NameOID.JURISDICTION_COUNTRY_NAME, u"US"
+                        ),
+                        x509.NameAttribute(
+                            NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
+                        ),
+                    ]
+                )
+            )
+            .subject_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+                        x509.NameAttribute(
+                            NameOID.JURISDICTION_COUNTRY_NAME, u"US"
+                        ),
+                        x509.NameAttribute(
+                            NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
+                        ),
+                    ]
+                )
+            )
+            .public_key(subject_private_key.public_key())
+            .not_valid_before(not_valid_before)
+            .not_valid_after(not_valid_after)
         )
 
         cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
 
-        parsed = Certificate.load(
-            cert.public_bytes(serialization.Encoding.DER))
+        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
 
         # Check that each value was encoded as an ASN.1 PRINTABLESTRING.
-        assert parsed.subject.chosen[0][0]['value'].chosen.tag == 19
-        assert parsed.issuer.chosen[0][0]['value'].chosen.tag == 19
+        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+
-            backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER or (
-                backend._lib.CRYPTOGRAPHY_OPENSSL_102L_OR_GREATER and
-                not backend._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
-            )
+            backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER
         ):
-            assert parsed.subject.chosen[1][0]['value'].chosen.tag == 19
-            assert parsed.issuer.chosen[1][0]['value'].chosen.tag == 19
+            assert read_next_rdn_value_tag(subject) == PRINTABLE_STRING
+            assert read_next_rdn_value_tag(issuer) == PRINTABLE_STRING
 
 
 class TestCertificateBuilder(object):
@@ -1619,20 +1832,19 @@
     @pytest.mark.requires_backend_interface(interface=X509Backend)
     def test_checks_for_unsupported_extensions(self, backend):
         private_key = RSA_KEY_2048.private_key(backend)
-        builder = x509.CertificateBuilder().subject_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).issuer_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).public_key(
-            private_key.public_key()
-        ).serial_number(
-            777
-        ).not_valid_before(
-            datetime.datetime(1999, 1, 1)
-        ).not_valid_after(
-            datetime.datetime(2020, 1, 1)
-        ).add_extension(
-            DummyExtension(), False
+        builder = (
+            x509.CertificateBuilder()
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .public_key(private_key.public_key())
+            .serial_number(777)
+            .not_valid_before(datetime.datetime(1999, 1, 1))
+            .not_valid_after(datetime.datetime(2020, 1, 1))
+            .add_extension(DummyExtension(), False)
         )
 
         with pytest.raises(NotImplementedError):
@@ -1643,133 +1855,163 @@
     def test_encode_nonstandard_aia(self, backend):
         private_key = RSA_KEY_2048.private_key(backend)
 
-        aia = x509.AuthorityInformationAccess([
-            x509.AccessDescription(
-                x509.ObjectIdentifier("2.999.7"),
-                x509.UniformResourceIdentifier(u"http://example.com")
-            ),
-        ])
+        aia = x509.AuthorityInformationAccess(
+            [
+                x509.AccessDescription(
+                    x509.ObjectIdentifier("2.999.7"),
+                    x509.UniformResourceIdentifier(u"http://example.com"),
+                ),
+            ]
+        )
 
-        builder = x509.CertificateBuilder().subject_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).issuer_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).public_key(
-            private_key.public_key()
-        ).serial_number(
-            777
-        ).not_valid_before(
-            datetime.datetime(1999, 1, 1)
-        ).not_valid_after(
-            datetime.datetime(2020, 1, 1)
-        ).add_extension(
-            aia, False
+        builder = (
+            x509.CertificateBuilder()
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .public_key(private_key.public_key())
+            .serial_number(777)
+            .not_valid_before(datetime.datetime(1999, 1, 1))
+            .not_valid_after(datetime.datetime(2020, 1, 1))
+            .add_extension(aia, False)
         )
 
         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)
+
+        sia = x509.SubjectInformationAccess(
+            [
+                x509.AccessDescription(
+                    x509.ObjectIdentifier("2.999.7"),
+                    x509.UniformResourceIdentifier(u"http://example.com"),
+                ),
+            ]
+        )
+
+        builder = (
+            x509.CertificateBuilder()
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .public_key(private_key.public_key())
+            .serial_number(777)
+            .not_valid_before(datetime.datetime(2015, 1, 1))
+            .not_valid_after(datetime.datetime(2040, 1, 1))
+            .add_extension(sia, False)
+        )
+
+        cert = builder.sign(private_key, hashes.SHA256(), backend)
+        ext = cert.extensions.get_extension_for_oid(
+            ExtensionOID.SUBJECT_INFORMATION_ACCESS
+        )
+        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)
 
-        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.JURISDICTION_LOCALITY_NAME, u"value"),
-            x509.NameAttribute(
-                NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME, u"value"
-            ),
-            x509.NameAttribute(NameOID.BUSINESS_CATEGORY, u"value"),
-            x509.NameAttribute(NameOID.POSTAL_ADDRESS, u"value"),
-            x509.NameAttribute(NameOID.POSTAL_CODE, u"value"),
-        ])
-        cert = x509.CertificateBuilder().subject_name(
-            name
-        ).issuer_name(
-            name
-        ).public_key(
-            private_key.public_key()
-        ).serial_number(
-            777
-        ).not_valid_before(
-            datetime.datetime(1999, 1, 1)
-        ).not_valid_after(
-            datetime.datetime(2020, 1, 1)
-        ).sign(private_key, hashes.SHA256(), 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.JURISDICTION_LOCALITY_NAME, u"value"
+                ),
+                x509.NameAttribute(
+                    NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME, u"value"
+                ),
+                x509.NameAttribute(NameOID.BUSINESS_CATEGORY, u"value"),
+                x509.NameAttribute(NameOID.POSTAL_ADDRESS, u"value"),
+                x509.NameAttribute(NameOID.POSTAL_CODE, u"value"),
+            ]
+        )
+        cert = (
+            x509.CertificateBuilder()
+            .subject_name(name)
+            .issuer_name(name)
+            .public_key(private_key.public_key())
+            .serial_number(777)
+            .not_valid_before(datetime.datetime(1999, 1, 1))
+            .not_valid_after(datetime.datetime(2020, 1, 1))
+            .sign(private_key, hashes.SHA256(), backend)
+        )
 
         for dn in (cert.subject, cert.issuer):
             for oid, asn1_type in TestNameAttribute.EXPECTED_TYPES:
-                assert dn.get_attributes_for_oid(
-                    oid
-                )[0]._type == asn1_type
+                assert dn.get_attributes_for_oid(oid)[0]._type == asn1_type
 
     @pytest.mark.parametrize(
         ("not_valid_before", "not_valid_after"),
         [
             [datetime.datetime(1970, 2, 1), datetime.datetime(9999, 1, 1)],
             [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 = x509.CertificateBuilder().subject_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).issuer_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).public_key(
-            private_key.public_key()
-        ).serial_number(
-            777
-        ).not_valid_before(
-            not_valid_before
-        ).not_valid_after(
-            not_valid_after
+        builder = (
+            x509.CertificateBuilder()
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .public_key(private_key.public_key())
+            .serial_number(777)
+            .not_valid_before(not_valid_before)
+            .not_valid_after(not_valid_after)
         )
         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 = Certificate.load(
-            cert.public_bytes(serialization.Encoding.DER)
-        )
-        not_before = parsed['tbs_certificate']['validity']['not_before']
-        not_after = parsed['tbs_certificate']['validity']['not_after']
-        assert not_before.chosen.tag == 23  # UTCTime
-        assert not_after.chosen.tag == 24  # GeneralizedTime
+        parsed = _parse_cert(cert.public_bytes(serialization.Encoding.DER))
+        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 = x509.CertificateBuilder().serial_number(
-            777
-        ).issuer_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).public_key(
-            subject_private_key.public_key()
-        ).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, u"US")])
+            )
+            .public_key(subject_private_key.public_key())
+            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+            .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
         )
         with pytest.raises(ValueError):
             builder.sign(subject_private_key, hashes.SHA256(), backend)
@@ -1778,16 +2020,15 @@
     @pytest.mark.requires_backend_interface(interface=X509Backend)
     def test_no_issuer_name(self, backend):
         subject_private_key = RSA_KEY_2048.private_key(backend)
-        builder = x509.CertificateBuilder().serial_number(
-            777
-        ).subject_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).public_key(
-            subject_private_key.public_key()
-        ).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)
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .public_key(subject_private_key.public_key())
+            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+            .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
         )
         with pytest.raises(ValueError):
             builder.sign(subject_private_key, hashes.SHA256(), backend)
@@ -1796,16 +2037,17 @@
     @pytest.mark.requires_backend_interface(interface=X509Backend)
     def test_no_public_key(self, backend):
         subject_private_key = RSA_KEY_2048.private_key(backend)
-        builder = x509.CertificateBuilder().serial_number(
-            777
-        ).issuer_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).subject_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).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, u"US")])
+            )
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+            .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
         )
         with pytest.raises(ValueError):
             builder.sign(subject_private_key, hashes.SHA256(), backend)
@@ -1814,16 +2056,17 @@
     @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 = x509.CertificateBuilder().serial_number(
-            777
-        ).issuer_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).subject_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).public_key(
-            subject_private_key.public_key()
-        ).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, u"US")])
+            )
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .public_key(subject_private_key.public_key())
+            .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
         )
         with pytest.raises(ValueError):
             builder.sign(subject_private_key, hashes.SHA256(), backend)
@@ -1832,16 +2075,17 @@
     @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 = x509.CertificateBuilder().serial_number(
-            777
-        ).issuer_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).subject_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).public_key(
-            subject_private_key.public_key()
-        ).not_valid_before(
-            datetime.datetime(2002, 1, 1, 12, 1)
+        builder = (
+            x509.CertificateBuilder()
+            .serial_number(777)
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .public_key(subject_private_key.public_key())
+            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
         )
         with pytest.raises(ValueError):
             builder.sign(subject_private_key, hashes.SHA256(), backend)
@@ -1850,16 +2094,17 @@
     @pytest.mark.requires_backend_interface(interface=X509Backend)
     def test_no_serial_number(self, backend):
         subject_private_key = RSA_KEY_2048.private_key(backend)
-        builder = x509.CertificateBuilder().issuer_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).subject_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).public_key(
-            subject_private_key.public_key()
-        ).not_valid_before(
-            datetime.datetime(2002, 1, 1, 12, 1)
-        ).not_valid_after(
-            datetime.datetime(2030, 12, 31, 8, 30)
+        builder = (
+            x509.CertificateBuilder()
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .public_key(subject_private_key.public_key())
+            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+            .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
         )
         with pytest.raises(ValueError):
             builder.sign(subject_private_key, hashes.SHA256(), backend)
@@ -1874,9 +2119,7 @@
             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, u"US")])
         builder = x509.CertificateBuilder().issuer_name(name)
 
         with pytest.raises(ValueError):
@@ -1892,9 +2135,7 @@
             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, u"US")])
         builder = x509.CertificateBuilder().subject_name(name)
 
         with pytest.raises(ValueError):
@@ -1903,13 +2144,9 @@
     def test_not_valid_before_after_not_valid_after(self):
         builder = x509.CertificateBuilder()
 
-        builder = builder.not_valid_after(
-            datetime.datetime(2002, 1, 1, 12, 1)
-        )
+        builder = builder.not_valid_after(datetime.datetime(2002, 1, 1, 12, 1))
         with pytest.raises(ValueError):
-            builder.not_valid_before(
-                datetime.datetime(2003, 1, 1, 12, 1)
-            )
+            builder.not_valid_before(datetime.datetime(2003, 1, 1, 12, 1))
 
     def test_not_valid_after_before_not_valid_before(self):
         builder = x509.CertificateBuilder()
@@ -1918,9 +2155,7 @@
             datetime.datetime(2002, 1, 1, 12, 1)
         )
         with pytest.raises(ValueError):
-            builder.not_valid_after(
-                datetime.datetime(2001, 1, 1, 12, 1)
-            )
+            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)
@@ -1957,18 +2192,18 @@
     @pytest.mark.requires_backend_interface(interface=X509Backend)
     def test_minimal_serial_number(self, backend):
         subject_private_key = RSA_KEY_2048.private_key(backend)
-        builder = x509.CertificateBuilder().serial_number(
-            1
-        ).subject_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'RU'),
-        ])).issuer_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'RU'),
-        ])).public_key(
-            subject_private_key.public_key()
-        ).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(1)
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"RU")])
+            )
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"RU")])
+            )
+            .public_key(subject_private_key.public_key())
+            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+            .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
         )
         cert = builder.sign(subject_private_key, hashes.SHA256(), backend)
         assert cert.serial_number == 1
@@ -1977,18 +2212,18 @@
     @pytest.mark.requires_backend_interface(interface=X509Backend)
     def test_biggest_serial_number(self, backend):
         subject_private_key = RSA_KEY_2048.private_key(backend)
-        builder = x509.CertificateBuilder().serial_number(
-            (1 << 159) - 1
-        ).subject_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'RU'),
-        ])).issuer_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'RU'),
-        ])).public_key(
-            subject_private_key.public_key()
-        ).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((1 << 159) - 1)
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"RU")])
+            )
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"RU")])
+            )
+            .public_key(subject_private_key.public_key())
+            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+            .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
         )
         cert = builder.sign(subject_private_key, hashes.SHA256(), backend)
         assert cert.serial_number == (1 << 159) - 1
@@ -2012,16 +2247,16 @@
         utc_time = datetime.datetime(2012, 1, 17, 6, 43)
         private_key = RSA_KEY_2048.private_key(backend)
         cert_builder = x509.CertificateBuilder().not_valid_after(time)
-        cert_builder = cert_builder.subject_name(
-            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
-        ).issuer_name(
-            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
-        ).serial_number(
-            1
-        ).public_key(
-            private_key.public_key()
-        ).not_valid_before(
-            utc_time - datetime.timedelta(days=365)
+        cert_builder = (
+            cert_builder.subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .serial_number(1)
+            .public_key(private_key.public_key())
+            .not_valid_before(utc_time - datetime.timedelta(days=365))
         )
 
         cert = cert_builder.sign(private_key, hashes.SHA256(), backend)
@@ -2032,29 +2267,25 @@
     def test_earliest_time(self, backend):
         time = datetime.datetime(1950, 1, 1)
         private_key = RSA_KEY_2048.private_key(backend)
-        cert_builder = x509.CertificateBuilder().subject_name(
-            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
-        ).issuer_name(
-            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
-        ).serial_number(
-            1
-        ).public_key(
-            private_key.public_key()
-        ).not_valid_before(
-            time
-        ).not_valid_after(
-            time
+        cert_builder = (
+            x509.CertificateBuilder()
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .serial_number(1)
+            .public_key(private_key.public_key())
+            .not_valid_before(time)
+            .not_valid_after(time)
         )
         cert = cert_builder.sign(private_key, hashes.SHA256(), backend)
         assert cert.not_valid_before == time
         assert cert.not_valid_after == time
-        parsed = Certificate.load(
-            cert.public_bytes(serialization.Encoding.DER)
-        )
-        not_before = parsed['tbs_certificate']['validity']['not_before']
-        not_after = parsed['tbs_certificate']['validity']['not_after']
-        assert not_before.chosen.tag == 23  # UTCTime
-        assert not_after.chosen.tag == 23  # UTCTime
+        parsed = _parse_cert(cert.public_bytes(serialization.Encoding.DER))
+        assert parsed.not_before_tag == UTC_TIME
+        assert parsed.not_after_tag == UTC_TIME
 
     def test_invalid_not_valid_after(self):
         with pytest.raises(TypeError):
@@ -2074,9 +2305,7 @@
         )
 
         with pytest.raises(ValueError):
-            builder.not_valid_after(
-                datetime.datetime.now()
-            )
+            builder.not_valid_after(datetime.datetime.now())
 
     @pytest.mark.requires_backend_interface(interface=RSABackend)
     @pytest.mark.requires_backend_interface(interface=X509Backend)
@@ -2087,16 +2316,16 @@
         utc_time = datetime.datetime(2012, 1, 17, 6, 43)
         private_key = RSA_KEY_2048.private_key(backend)
         cert_builder = x509.CertificateBuilder().not_valid_before(time)
-        cert_builder = cert_builder.subject_name(
-            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
-        ).issuer_name(
-            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
-        ).serial_number(
-            1
-        ).public_key(
-            private_key.public_key()
-        ).not_valid_after(
-            utc_time + datetime.timedelta(days=366)
+        cert_builder = (
+            cert_builder.subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .serial_number(1)
+            .public_key(private_key.public_key())
+            .not_valid_after(utc_time + datetime.timedelta(days=366))
         )
 
         cert = cert_builder.sign(private_key, hashes.SHA256(), backend)
@@ -2120,18 +2349,18 @@
         )
 
         with pytest.raises(ValueError):
-            builder.not_valid_before(
-                datetime.datetime.now()
-            )
+            builder.not_valid_before(datetime.datetime.now())
 
     def test_add_extension_checks_for_duplicates(self):
         builder = x509.CertificateBuilder().add_extension(
-            x509.BasicConstraints(ca=False, path_length=None), True,
+            x509.BasicConstraints(ca=False, path_length=None),
+            True,
         )
 
         with pytest.raises(ValueError):
             builder.add_extension(
-                x509.BasicConstraints(ca=False, path_length=None), True,
+                x509.BasicConstraints(ca=False, path_length=None),
+                True,
             )
 
     def test_add_invalid_extension_type(self):
@@ -2142,86 +2371,143 @@
 
     @pytest.mark.requires_backend_interface(interface=RSABackend)
     @pytest.mark.requires_backend_interface(interface=X509Backend)
-    def test_sign_with_unsupported_hash(self, backend):
+    @pytest.mark.parametrize("algorithm", [object(), None])
+    def test_sign_with_unsupported_hash(self, algorithm, backend):
         private_key = RSA_KEY_2048.private_key(backend)
         builder = x509.CertificateBuilder()
-        builder = builder.subject_name(
-            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
-        ).issuer_name(
-            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
-        ).serial_number(
-            1
-        ).public_key(
-            private_key.public_key()
-        ).not_valid_before(
-            datetime.datetime(2002, 1, 1, 12, 1)
-        ).not_valid_after(
-            datetime.datetime(2032, 1, 1, 12, 1)
+        builder = (
+            builder.subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .serial_number(1)
+            .public_key(private_key.public_key())
+            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+            .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1))
         )
 
         with pytest.raises(TypeError):
-            builder.sign(private_key, object(), backend)
+            builder.sign(private_key, algorithm, backend)
+
+    @pytest.mark.supported(
+        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 = (
+            x509.CertificateBuilder()
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .serial_number(1)
+            .public_key(private_key.public_key())
+            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+            .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1))
+        )
+
+        with pytest.raises(ValueError):
+            builder.sign(private_key, hashes.SHA256(), backend)
+
+    @pytest.mark.supported(
+        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 = (
+            x509.CertificateBuilder()
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .serial_number(1)
+            .public_key(private_key.public_key())
+            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+            .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1))
+        )
+
+        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",
+    )
     def test_sign_rsa_with_md5(self, backend):
         private_key = RSA_KEY_2048.private_key(backend)
         builder = x509.CertificateBuilder()
-        builder = builder.subject_name(
-            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
-        ).issuer_name(
-            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
-        ).serial_number(
-            1
-        ).public_key(
-            private_key.public_key()
-        ).not_valid_before(
-            datetime.datetime(2002, 1, 1, 12, 1)
-        ).not_valid_after(
-            datetime.datetime(2032, 1, 1, 12, 1)
+        builder = (
+            builder.subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .serial_number(1)
+            .public_key(private_key.public_key())
+            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+            .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1))
         )
         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",
+    )
     def test_sign_dsa_with_md5(self, backend):
         private_key = DSA_KEY_2048.private_key(backend)
         builder = x509.CertificateBuilder()
-        builder = builder.subject_name(
-            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
-        ).issuer_name(
-            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
-        ).serial_number(
-            1
-        ).public_key(
-            private_key.public_key()
-        ).not_valid_before(
-            datetime.datetime(2002, 1, 1, 12, 1)
-        ).not_valid_after(
-            datetime.datetime(2032, 1, 1, 12, 1)
+        builder = (
+            builder.subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .serial_number(1)
+            .public_key(private_key.public_key())
+            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+            .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1))
         )
         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",
+    )
     def test_sign_ec_with_md5(self, backend):
         _skip_curve_unsupported(backend, ec.SECP256R1())
         private_key = EC_KEY_SECP256R1.private_key(backend)
         builder = x509.CertificateBuilder()
-        builder = builder.subject_name(
-            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
-        ).issuer_name(
-            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
-        ).serial_number(
-            1
-        ).public_key(
-            private_key.public_key()
-        ).not_valid_before(
-            datetime.datetime(2002, 1, 1, 12, 1)
-        ).not_valid_after(
-            datetime.datetime(2032, 1, 1, 12, 1)
+        builder = (
+            builder.subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .serial_number(1)
+            .public_key(private_key.public_key())
+            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+            .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1))
         )
         with pytest.raises(ValueError):
             builder.sign(private_key, hashes.MD5(), backend)
@@ -2235,23 +2521,28 @@
         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, u'US'),
-        ])).subject_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).public_key(
-            subject_private_key.public_key()
-        ).add_extension(
-            x509.BasicConstraints(ca=False, path_length=None), True,
-        ).add_extension(
-            x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]),
-            critical=False,
-        ).not_valid_before(
-            not_valid_before
-        ).not_valid_after(
-            not_valid_after
+        builder = (
+            x509.CertificateBuilder()
+            .serial_number(777)
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .public_key(subject_private_key.public_key())
+            .add_extension(
+                x509.BasicConstraints(ca=False, path_length=None),
+                True,
+            )
+            .add_extension(
+                x509.SubjectAlternativeName(
+                    [x509.DNSName(u"cryptography.io")]
+                ),
+                critical=False,
+            )
+            .not_valid_before(not_valid_before)
+            .not_valid_after(not_valid_after)
         )
 
         cert = builder.sign(issuer_private_key, hashes.SHA1(), backend)
@@ -2281,23 +2572,28 @@
         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, u'US'),
-        ])).subject_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).public_key(
-            subject_private_key.public_key()
-        ).add_extension(
-            x509.BasicConstraints(ca=False, path_length=None), True,
-        ).add_extension(
-            x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]),
-            critical=False,
-        ).not_valid_before(
-            not_valid_before
-        ).not_valid_after(
-            not_valid_after
+        builder = (
+            x509.CertificateBuilder()
+            .serial_number(777)
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .public_key(subject_private_key.public_key())
+            .add_extension(
+                x509.BasicConstraints(ca=False, path_length=None),
+                True,
+            )
+            .add_extension(
+                x509.SubjectAlternativeName(
+                    [x509.DNSName(u"cryptography.io")]
+                ),
+                critical=False,
+            )
+            .not_valid_before(not_valid_before)
+            .not_valid_after(not_valid_after)
         )
 
         cert = builder.sign(issuer_private_key, hashes.SHA1(), backend)
@@ -2317,6 +2613,202 @@
             x509.DNSName(u"cryptography.io"),
         ]
 
+    @pytest.mark.supported(
+        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()
+
+        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, u"US")])
+            )
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .public_key(subject_private_key.public_key())
+            .add_extension(
+                x509.BasicConstraints(ca=False, path_length=None),
+                True,
+            )
+            .add_extension(
+                x509.SubjectAlternativeName(
+                    [x509.DNSName(u"cryptography.io")]
+                ),
+                critical=False,
+            )
+            .not_valid_before(not_valid_before)
+            .not_valid_after(not_valid_after)
+        )
+
+        cert = builder.sign(issuer_private_key, None, backend)
+        issuer_private_key.public_key().verify(
+            cert.signature, cert.tbs_certificate_bytes
+        )
+        assert cert.signature_algorithm_oid == SignatureAlgorithmOID.ED25519
+        assert cert.signature_hash_algorithm is None
+        assert isinstance(cert.public_key(), ed25519.Ed25519PublicKey)
+        assert cert.version is x509.Version.v3
+        assert cert.not_valid_before == not_valid_before
+        assert cert.not_valid_after == not_valid_after
+        basic_constraints = cert.extensions.get_extension_for_oid(
+            ExtensionOID.BASIC_CONSTRAINTS
+        )
+        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 list(subject_alternative_name.value) == [
+            x509.DNSName(u"cryptography.io"),
+        ]
+
+    @pytest.mark.supported(
+        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()
+
+        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, u"US")])
+            )
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .public_key(subject_private_key.public_key())
+            .not_valid_before(not_valid_before)
+            .not_valid_after(not_valid_after)
+        )
+
+        cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
+        issuer_private_key.public_key().verify(
+            cert.signature,
+            cert.tbs_certificate_bytes,
+            padding.PKCS1v15(),
+            cert.signature_hash_algorithm,
+        )
+        assert cert.signature_algorithm_oid == (
+            SignatureAlgorithmOID.RSA_WITH_SHA256
+        )
+        assert isinstance(cert.signature_hash_algorithm, hashes.SHA256)
+        assert isinstance(cert.public_key(), ed25519.Ed25519PublicKey)
+
+    @pytest.mark.supported(
+        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()
+
+        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, u"US")])
+            )
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .public_key(subject_private_key.public_key())
+            .add_extension(
+                x509.BasicConstraints(ca=False, path_length=None),
+                True,
+            )
+            .add_extension(
+                x509.SubjectAlternativeName(
+                    [x509.DNSName(u"cryptography.io")]
+                ),
+                critical=False,
+            )
+            .not_valid_before(not_valid_before)
+            .not_valid_after(not_valid_after)
+        )
+
+        cert = builder.sign(issuer_private_key, None, backend)
+        issuer_private_key.public_key().verify(
+            cert.signature, cert.tbs_certificate_bytes
+        )
+        assert cert.signature_algorithm_oid == SignatureAlgorithmOID.ED448
+        assert cert.signature_hash_algorithm is None
+        assert isinstance(cert.public_key(), ed448.Ed448PublicKey)
+        assert cert.version is x509.Version.v3
+        assert cert.not_valid_before == not_valid_before
+        assert cert.not_valid_after == not_valid_after
+        basic_constraints = cert.extensions.get_extension_for_oid(
+            ExtensionOID.BASIC_CONSTRAINTS
+        )
+        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 list(subject_alternative_name.value) == [
+            x509.DNSName(u"cryptography.io"),
+        ]
+
+    @pytest.mark.supported(
+        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()
+
+        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, u"US")])
+            )
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .public_key(subject_private_key.public_key())
+            .not_valid_before(not_valid_before)
+            .not_valid_after(not_valid_after)
+        )
+
+        cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
+        issuer_private_key.public_key().verify(
+            cert.signature,
+            cert.tbs_certificate_bytes,
+            padding.PKCS1v15(),
+            cert.signature_hash_algorithm,
+        )
+        assert cert.signature_algorithm_oid == (
+            SignatureAlgorithmOID.RSA_WITH_SHA256
+        )
+        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):
@@ -2326,18 +2818,18 @@
         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, u'US'),
-        ])).subject_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).public_key(
-            subject_private_key.public_key()
-        ).not_valid_before(
-            not_valid_before
-        ).not_valid_after(
-            not_valid_after
+        builder = (
+            x509.CertificateBuilder()
+            .serial_number(777)
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .public_key(subject_private_key.public_key())
+            .not_valid_before(not_valid_before)
+            .not_valid_after(not_valid_after)
         )
 
         with pytest.raises(ValueError):
@@ -2352,85 +2844,105 @@
                 [
                     # 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(u"a\xedt\xe1s.test"),
                     x509.RFC822Name._init_without_validation(
-                        u'test@a\xedt\xe1s.test'
+                        u"test@a\xedt\xe1s.test"
                     ),
                     x509.UniformResourceIdentifier._init_without_validation(
-                        u'http://a\xedt\xe1s.test'
+                        u"http://a\xedt\xe1s.test"
                     ),
                 ]
             ),
-            x509.CertificatePolicies([
-                x509.PolicyInformation(
-                    x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
-                    [u"http://other.com/cps"]
-                )
-            ]),
-            x509.CertificatePolicies([
-                x509.PolicyInformation(
-                    x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
-                    None
-                )
-            ]),
-            x509.CertificatePolicies([
-                x509.PolicyInformation(
-                    x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
-                    [
-                        u"http://example.com/cps",
-                        u"http://other.com/cps",
-                        x509.UserNotice(
-                            x509.NoticeReference(u"my org", [1, 2, 3, 4]),
-                            u"thing"
-                        )
-                    ]
-                )
-            ]),
-            x509.CertificatePolicies([
-                x509.PolicyInformation(
-                    x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
-                    [
-                        u"http://example.com/cps",
-                        x509.UserNotice(
-                            x509.NoticeReference(u"UTF8\u2122'", [1, 2, 3, 4]),
-                            u"We heart UTF8!\u2122"
-                        )
-                    ]
-                )
-            ]),
-            x509.CertificatePolicies([
-                x509.PolicyInformation(
-                    x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
-                    [x509.UserNotice(None, u"thing")]
-                )
-            ]),
-            x509.CertificatePolicies([
-                x509.PolicyInformation(
-                    x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
-                    [
-                        x509.UserNotice(
-                            x509.NoticeReference(u"my org", [1, 2, 3, 4]),
-                            None
-                        )
-                    ]
-                )
-            ]),
-            x509.IssuerAlternativeName([
-                x509.DNSName(u"myissuer"),
-                x509.RFC822Name(u"email@domain.com"),
-            ]),
-            x509.ExtendedKeyUsage([
-                ExtendedKeyUsageOID.CLIENT_AUTH,
-                ExtendedKeyUsageOID.SERVER_AUTH,
-                ExtendedKeyUsageOID.CODE_SIGNING,
-            ]),
+            x509.CertificatePolicies(
+                [
+                    x509.PolicyInformation(
+                        x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+                        [u"http://other.com/cps"],
+                    )
+                ]
+            ),
+            x509.CertificatePolicies(
+                [
+                    x509.PolicyInformation(
+                        x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+                        None,
+                    )
+                ]
+            ),
+            x509.CertificatePolicies(
+                [
+                    x509.PolicyInformation(
+                        x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+                        [
+                            u"http://example.com/cps",
+                            u"http://other.com/cps",
+                            x509.UserNotice(
+                                x509.NoticeReference(u"my org", [1, 2, 3, 4]),
+                                u"thing",
+                            ),
+                        ],
+                    )
+                ]
+            ),
+            x509.CertificatePolicies(
+                [
+                    x509.PolicyInformation(
+                        x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+                        [
+                            u"http://example.com/cps",
+                            x509.UserNotice(
+                                x509.NoticeReference(
+                                    u"UTF8\u2122'", [1, 2, 3, 4]
+                                ),
+                                u"We heart UTF8!\u2122",
+                            ),
+                        ],
+                    )
+                ]
+            ),
+            x509.CertificatePolicies(
+                [
+                    x509.PolicyInformation(
+                        x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+                        [x509.UserNotice(None, u"thing")],
+                    )
+                ]
+            ),
+            x509.CertificatePolicies(
+                [
+                    x509.PolicyInformation(
+                        x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+                        [
+                            x509.UserNotice(
+                                x509.NoticeReference(u"my org", [1, 2, 3, 4]),
+                                None,
+                            )
+                        ],
+                    )
+                ]
+            ),
+            x509.IssuerAlternativeName(
+                [
+                    x509.DNSName(u"myissuer"),
+                    x509.RFC822Name(u"email@domain.com"),
+                ]
+            ),
+            x509.ExtendedKeyUsage(
+                [
+                    ExtendedKeyUsageOID.CLIENT_AUTH,
+                    ExtendedKeyUsageOID.SERVER_AUTH,
+                    ExtendedKeyUsageOID.CODE_SIGNING,
+                ]
+            ),
             x509.InhibitAnyPolicy(3),
             x509.TLSFeature([x509.TLSFeatureType.status_request]),
             x509.TLSFeature([x509.TLSFeatureType.status_request_v2]),
-            x509.TLSFeature([
-                x509.TLSFeatureType.status_request,
-                x509.TLSFeatureType.status_request_v2
-            ]),
+            x509.TLSFeature(
+                [
+                    x509.TLSFeatureType.status_request,
+                    x509.TLSFeatureType.status_request_v2,
+                ]
+            ),
             x509.NameConstraints(
                 permitted_subtrees=[
                     x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.0/24")),
@@ -2445,192 +2957,252 @@
                         ipaddress.IPv6Network(u"FF:FF:0:0:0:0:0:0/128")
                     ),
                 ],
-                excluded_subtrees=[x509.DNSName(u"name.local")]
+                excluded_subtrees=[x509.DNSName(u"name.local")],
             ),
             x509.NameConstraints(
                 permitted_subtrees=[
                     x509.IPAddress(ipaddress.IPv4Network(u"0.0.0.0/0")),
                 ],
-                excluded_subtrees=None
+                excluded_subtrees=None,
             ),
             x509.NameConstraints(
                 permitted_subtrees=None,
-                excluded_subtrees=[x509.DNSName(u"name.local")]
+                excluded_subtrees=[x509.DNSName(u"name.local")],
             ),
             x509.PolicyConstraints(
-                require_explicit_policy=None,
-                inhibit_policy_mapping=1
+                require_explicit_policy=None, inhibit_policy_mapping=1
             ),
             x509.PolicyConstraints(
-                require_explicit_policy=3,
-                inhibit_policy_mapping=1
+                require_explicit_policy=3, inhibit_policy_mapping=1
             ),
             x509.PolicyConstraints(
-                require_explicit_policy=0,
-                inhibit_policy_mapping=None
+                require_explicit_policy=0, inhibit_policy_mapping=None
             ),
-            x509.CRLDistributionPoints([
-                x509.DistributionPoint(
-                    full_name=None,
-                    relative_name=x509.RelativeDistinguishedName([
-                        x509.NameAttribute(
-                            NameOID.COMMON_NAME,
-                            u"indirect CRL for indirectCRL CA3"
+            x509.CRLDistributionPoints(
+                [
+                    x509.DistributionPoint(
+                        full_name=None,
+                        relative_name=x509.RelativeDistinguishedName(
+                            [
+                                x509.NameAttribute(
+                                    NameOID.COMMON_NAME,
+                                    u"indirect CRL for indirectCRL CA3",
+                                ),
+                            ]
                         ),
-                    ]),
-                    reasons=None,
-                    crl_issuer=[x509.DirectoryName(
-                        x509.Name([
-                            x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
-                            x509.NameAttribute(
-                                NameOID.ORGANIZATION_NAME,
-                                u"Test Certificates 2011"
+                        reasons=None,
+                        crl_issuer=[
+                            x509.DirectoryName(
+                                x509.Name(
+                                    [
+                                        x509.NameAttribute(
+                                            NameOID.COUNTRY_NAME, u"US"
+                                        ),
+                                        x509.NameAttribute(
+                                            NameOID.ORGANIZATION_NAME,
+                                            u"Test Certificates 2011",
+                                        ),
+                                        x509.NameAttribute(
+                                            NameOID.ORGANIZATIONAL_UNIT_NAME,
+                                            u"indirectCRL CA3 cRLIssuer",
+                                        ),
+                                    ]
+                                )
+                            )
+                        ],
+                    )
+                ]
+            ),
+            x509.CRLDistributionPoints(
+                [
+                    x509.DistributionPoint(
+                        full_name=[
+                            x509.DirectoryName(
+                                x509.Name(
+                                    [
+                                        x509.NameAttribute(
+                                            NameOID.COUNTRY_NAME, u"US"
+                                        ),
+                                    ]
+                                )
+                            )
+                        ],
+                        relative_name=None,
+                        reasons=None,
+                        crl_issuer=[
+                            x509.DirectoryName(
+                                x509.Name(
+                                    [
+                                        x509.NameAttribute(
+                                            NameOID.ORGANIZATION_NAME,
+                                            u"cryptography Testing",
+                                        ),
+                                    ]
+                                )
+                            )
+                        ],
+                    )
+                ]
+            ),
+            x509.CRLDistributionPoints(
+                [
+                    x509.DistributionPoint(
+                        full_name=[
+                            x509.UniformResourceIdentifier(
+                                u"http://myhost.com/myca.crl"
                             ),
-                            x509.NameAttribute(
-                                NameOID.ORGANIZATIONAL_UNIT_NAME,
-                                u"indirectCRL CA3 cRLIssuer"
+                            x509.UniformResourceIdentifier(
+                                u"http://backup.myhost.com/myca.crl"
                             ),
-                        ])
-                    )],
-                )
-            ]),
-            x509.CRLDistributionPoints([
-                x509.DistributionPoint(
-                    full_name=[x509.DirectoryName(
-                        x509.Name([
-                            x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
-                        ])
-                    )],
-                    relative_name=None,
-                    reasons=None,
-                    crl_issuer=[x509.DirectoryName(
-                        x509.Name([
-                            x509.NameAttribute(
-                                NameOID.ORGANIZATION_NAME,
-                                u"cryptography Testing"
-                            ),
-                        ])
-                    )],
-                )
-            ]),
-            x509.CRLDistributionPoints([
-                x509.DistributionPoint(
-                    full_name=[
-                        x509.UniformResourceIdentifier(
-                            u"http://myhost.com/myca.crl"
+                        ],
+                        relative_name=None,
+                        reasons=frozenset(
+                            [
+                                x509.ReasonFlags.key_compromise,
+                                x509.ReasonFlags.ca_compromise,
+                            ]
                         ),
-                        x509.UniformResourceIdentifier(
-                            u"http://backup.myhost.com/myca.crl"
-                        )
-                    ],
-                    relative_name=None,
-                    reasons=frozenset([
-                        x509.ReasonFlags.key_compromise,
-                        x509.ReasonFlags.ca_compromise
-                    ]),
-                    crl_issuer=[x509.DirectoryName(
-                        x509.Name([
-                            x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
-                            x509.NameAttribute(
-                                NameOID.COMMON_NAME, u"cryptography CA"
-                            ),
-                        ])
-                    )],
-                )
-            ]),
-            x509.CRLDistributionPoints([
-                x509.DistributionPoint(
-                    full_name=[x509.UniformResourceIdentifier(
-                        u"http://domain.com/some.crl"
-                    )],
-                    relative_name=None,
-                    reasons=frozenset([
-                        x509.ReasonFlags.key_compromise,
-                        x509.ReasonFlags.ca_compromise,
-                        x509.ReasonFlags.affiliation_changed,
-                        x509.ReasonFlags.superseded,
-                        x509.ReasonFlags.privilege_withdrawn,
-                        x509.ReasonFlags.cessation_of_operation,
-                        x509.ReasonFlags.aa_compromise,
-                        x509.ReasonFlags.certificate_hold,
-                    ]),
-                    crl_issuer=None
-                )
-            ]),
-            x509.CRLDistributionPoints([
-                x509.DistributionPoint(
-                    full_name=None,
-                    relative_name=None,
-                    reasons=None,
-                    crl_issuer=[x509.DirectoryName(
-                        x509.Name([
-                            x509.NameAttribute(
-                                NameOID.COMMON_NAME, u"cryptography CA"
-                            ),
-                        ])
-                    )],
-                )
-            ]),
-            x509.CRLDistributionPoints([
-                x509.DistributionPoint(
-                    full_name=[x509.UniformResourceIdentifier(
-                        u"http://domain.com/some.crl"
-                    )],
-                    relative_name=None,
-                    reasons=frozenset([x509.ReasonFlags.aa_compromise]),
-                    crl_issuer=None
-                )
-            ]),
-            x509.FreshestCRL([
-                x509.DistributionPoint(
-                    full_name=[x509.UniformResourceIdentifier(
-                        u"http://domain.com/some.crl"
-                    )],
-                    relative_name=None,
-                    reasons=frozenset([
-                        x509.ReasonFlags.key_compromise,
-                        x509.ReasonFlags.ca_compromise,
-                        x509.ReasonFlags.affiliation_changed,
-                        x509.ReasonFlags.superseded,
-                        x509.ReasonFlags.privilege_withdrawn,
-                        x509.ReasonFlags.cessation_of_operation,
-                        x509.ReasonFlags.aa_compromise,
-                        x509.ReasonFlags.certificate_hold,
-                    ]),
-                    crl_issuer=None
-                )
-            ]),
-            x509.FreshestCRL([
-                x509.DistributionPoint(
-                    full_name=None,
-                    relative_name=x509.RelativeDistinguishedName([
-                        x509.NameAttribute(
-                            NameOID.COMMON_NAME,
-                            u"indirect CRL for indirectCRL CA3"
+                        crl_issuer=[
+                            x509.DirectoryName(
+                                x509.Name(
+                                    [
+                                        x509.NameAttribute(
+                                            NameOID.COUNTRY_NAME, u"US"
+                                        ),
+                                        x509.NameAttribute(
+                                            NameOID.COMMON_NAME,
+                                            u"cryptography CA",
+                                        ),
+                                    ]
+                                )
+                            )
+                        ],
+                    )
+                ]
+            ),
+            x509.CRLDistributionPoints(
+                [
+                    x509.DistributionPoint(
+                        full_name=[
+                            x509.UniformResourceIdentifier(
+                                u"http://domain.com/some.crl"
+                            )
+                        ],
+                        relative_name=None,
+                        reasons=frozenset(
+                            [
+                                x509.ReasonFlags.key_compromise,
+                                x509.ReasonFlags.ca_compromise,
+                                x509.ReasonFlags.affiliation_changed,
+                                x509.ReasonFlags.superseded,
+                                x509.ReasonFlags.privilege_withdrawn,
+                                x509.ReasonFlags.cessation_of_operation,
+                                x509.ReasonFlags.aa_compromise,
+                                x509.ReasonFlags.certificate_hold,
+                            ]
                         ),
-                    ]),
-                    reasons=None,
-                    crl_issuer=None,
-                )
-            ]),
-            x509.FreshestCRL([
-                x509.DistributionPoint(
-                    full_name=None,
-                    relative_name=x509.RelativeDistinguishedName([
-                        x509.NameAttribute(
-                            NameOID.COMMON_NAME,
-                            u"indirect CRL for indirectCRL CA3"
+                        crl_issuer=None,
+                    )
+                ]
+            ),
+            x509.CRLDistributionPoints(
+                [
+                    x509.DistributionPoint(
+                        full_name=None,
+                        relative_name=None,
+                        reasons=None,
+                        crl_issuer=[
+                            x509.DirectoryName(
+                                x509.Name(
+                                    [
+                                        x509.NameAttribute(
+                                            NameOID.COMMON_NAME,
+                                            u"cryptography CA",
+                                        ),
+                                    ]
+                                )
+                            )
+                        ],
+                    )
+                ]
+            ),
+            x509.CRLDistributionPoints(
+                [
+                    x509.DistributionPoint(
+                        full_name=[
+                            x509.UniformResourceIdentifier(
+                                u"http://domain.com/some.crl"
+                            )
+                        ],
+                        relative_name=None,
+                        reasons=frozenset([x509.ReasonFlags.aa_compromise]),
+                        crl_issuer=None,
+                    )
+                ]
+            ),
+            x509.FreshestCRL(
+                [
+                    x509.DistributionPoint(
+                        full_name=[
+                            x509.UniformResourceIdentifier(
+                                u"http://domain.com/some.crl"
+                            )
+                        ],
+                        relative_name=None,
+                        reasons=frozenset(
+                            [
+                                x509.ReasonFlags.key_compromise,
+                                x509.ReasonFlags.ca_compromise,
+                                x509.ReasonFlags.affiliation_changed,
+                                x509.ReasonFlags.superseded,
+                                x509.ReasonFlags.privilege_withdrawn,
+                                x509.ReasonFlags.cessation_of_operation,
+                                x509.ReasonFlags.aa_compromise,
+                                x509.ReasonFlags.certificate_hold,
+                            ]
                         ),
-                        x509.NameAttribute(
-                            NameOID.COUNTRY_NAME,
-                            u"US"
+                        crl_issuer=None,
+                    )
+                ]
+            ),
+            x509.FreshestCRL(
+                [
+                    x509.DistributionPoint(
+                        full_name=None,
+                        relative_name=x509.RelativeDistinguishedName(
+                            [
+                                x509.NameAttribute(
+                                    NameOID.COMMON_NAME,
+                                    u"indirect CRL for indirectCRL CA3",
+                                ),
+                            ]
                         ),
-                    ]),
-                    reasons=None,
-                    crl_issuer=None,
-                )
-            ]),
-        ]
+                        reasons=None,
+                        crl_issuer=None,
+                    )
+                ]
+            ),
+            x509.FreshestCRL(
+                [
+                    x509.DistributionPoint(
+                        full_name=None,
+                        relative_name=x509.RelativeDistinguishedName(
+                            [
+                                x509.NameAttribute(
+                                    NameOID.COMMON_NAME,
+                                    u"indirect CRL for indirectCRL CA3",
+                                ),
+                                x509.NameAttribute(
+                                    NameOID.COUNTRY_NAME, u"US"
+                                ),
+                            ]
+                        ),
+                        reasons=None,
+                        crl_issuer=None,
+                    )
+                ]
+            ),
+        ],
     )
     def test_ext(self, add_ext, backend):
         issuer_private_key = RSA_KEY_2048.private_key(backend)
@@ -2639,21 +3211,21 @@
         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, u'US')])
-        ).issuer_name(
-            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'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(
-            add_ext, critical=False
-        ).sign(issuer_private_key, hashes.SHA256(), backend)
+        cert = (
+            x509.CertificateBuilder()
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"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(add_ext, critical=False)
+            .sign(issuer_private_key, hashes.SHA256(), backend)
+        )
 
         ext = cert.extensions.get_extension_for_class(type(add_ext))
         assert ext.critical is False
@@ -2668,32 +3240,34 @@
         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, u'US')])
-        ).issuer_name(
-            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'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)
+        cert = (
+            x509.CertificateBuilder()
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"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
@@ -2706,7 +3280,7 @@
             key_cert_sign=True,
             crl_sign=False,
             encipher_only=False,
-            decipher_only=False
+            decipher_only=False,
         )
 
     @pytest.mark.requires_backend_interface(interface=RSABackend)
@@ -2714,14 +3288,18 @@
     def test_build_ca_request_with_path_length_none(self, backend):
         private_key = RSA_KEY_2048.private_key(backend)
 
-        request = x509.CertificateSigningRequestBuilder().subject_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.ORGANIZATION_NAME,
-                                   u'PyCA'),
-            ])
-        ).add_extension(
-            x509.BasicConstraints(ca=True, path_length=None), critical=True
-        ).sign(private_key, hashes.SHA1(), backend)
+        request = (
+            x509.CertificateSigningRequestBuilder()
+            .subject_name(
+                x509.Name(
+                    [x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")]
+                )
+            )
+            .add_extension(
+                x509.BasicConstraints(ca=True, path_length=None), critical=True
+            )
+            .sign(private_key, hashes.SHA1(), backend)
+        )
 
         loaded_request = x509.load_pem_x509_csr(
             request.public_bytes(encoding=serialization.Encoding.PEM), backend
@@ -2734,33 +3312,34 @@
         assert basic_constraints.value.path_length is None
 
     @pytest.mark.parametrize(
-        "unrecognized", [
+        "unrecognized",
+        [
             x509.UnrecognizedExtension(
                 x509.ObjectIdentifier("1.2.3.4.5"),
                 b"abcdef",
             )
-        ]
+        ],
     )
     @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)
 
-        cert = x509.CertificateBuilder().subject_name(
-            x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US')])
-        ).issuer_name(
-            x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US')])
-        ).not_valid_before(
-            datetime.datetime(2002, 1, 1, 12, 1)
-        ).not_valid_after(
-            datetime.datetime(2030, 12, 31, 8, 30)
-        ).public_key(
-            private_key.public_key()
-        ).serial_number(
-            123
-        ).add_extension(
-            unrecognized, critical=False
-        ).sign(private_key, hashes.SHA256(), backend)
+        cert = (
+            x509.CertificateBuilder()
+            .subject_name(
+                x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US")])
+            )
+            .issuer_name(
+                x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US")])
+            )
+            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+            .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
+            .public_key(private_key.public_key())
+            .serial_number(123)
+            .add_extension(unrecognized, critical=False)
+            .sign(private_key, hashes.SHA256(), backend)
+        )
 
         ext = cert.extensions.get_extension_for_oid(unrecognized.oid)
 
@@ -2777,39 +3356,73 @@
             x509.Name([])
         )
         with pytest.raises(TypeError):
-            builder.sign(private_key, 'NotAHash', backend)
+            builder.sign(private_key, "NotAHash", backend)
+
+    @pytest.mark.supported(
+        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(
+            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+        )
+
+        with pytest.raises(ValueError):
+            builder.sign(private_key, hashes.SHA256(), backend)
+
+    @pytest.mark.supported(
+        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(
+            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+        )
+
+        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",
+    )
     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, u"PyCA")])
         )
         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",
+    )
     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, u"PyCA")])
         )
         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",
+    )
     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, u"PyCA")])
         )
         with pytest.raises(ValueError):
             builder.sign(private_key, hashes.MD5(), backend)
@@ -2826,13 +3439,18 @@
     def test_build_ca_request_with_rsa(self, backend):
         private_key = RSA_KEY_2048.private_key(backend)
 
-        request = x509.CertificateSigningRequestBuilder().subject_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
-            ])
-        ).add_extension(
-            x509.BasicConstraints(ca=True, path_length=2), critical=True
-        ).sign(private_key, hashes.SHA1(), backend)
+        request = (
+            x509.CertificateSigningRequestBuilder()
+            .subject_name(
+                x509.Name(
+                    [x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")]
+                )
+            )
+            .add_extension(
+                x509.BasicConstraints(ca=True, path_length=2), critical=True
+            )
+            .sign(private_key, hashes.SHA1(), backend)
+        )
 
         assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
         public_key = request.public_key()
@@ -2840,7 +3458,7 @@
         subject = request.subject
         assert isinstance(subject, x509.Name)
         assert list(subject) == [
-            x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
+            x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
         ]
         basic_constraints = request.extensions.get_extension_for_oid(
             ExtensionOID.BASIC_CONSTRAINTS
@@ -2852,14 +3470,22 @@
     def test_build_ca_request_with_unicode(self, backend):
         private_key = RSA_KEY_2048.private_key(backend)
 
-        request = x509.CertificateSigningRequestBuilder().subject_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.ORGANIZATION_NAME,
-                                   u'PyCA\U0001f37a'),
-            ])
-        ).add_extension(
-            x509.BasicConstraints(ca=True, path_length=2), critical=True
-        ).sign(private_key, hashes.SHA1(), backend)
+        request = (
+            x509.CertificateSigningRequestBuilder()
+            .subject_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.ORGANIZATION_NAME, u"PyCA\U0001f37a"
+                        ),
+                    ]
+                )
+            )
+            .add_extension(
+                x509.BasicConstraints(ca=True, path_length=2), critical=True
+            )
+            .sign(private_key, hashes.SHA1(), backend)
+        )
 
         loaded_request = x509.load_pem_x509_csr(
             request.public_bytes(encoding=serialization.Encoding.PEM), backend
@@ -2867,67 +3493,95 @@
         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, u"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)
 
-        request = x509.CertificateSigningRequestBuilder().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.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.JURISDICTION_LOCALITY_NAME, u"value"
-                ),
-                x509.NameAttribute(
-                    NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME, u"value"
-                ),
-                x509.NameAttribute(NameOID.BUSINESS_CATEGORY, u"value"),
-                x509.NameAttribute(NameOID.POSTAL_ADDRESS, u"value"),
-                x509.NameAttribute(NameOID.POSTAL_CODE, u"value"),
-            ])
-        ).sign(private_key, hashes.SHA256(), backend)
+        request = (
+            x509.CertificateSigningRequestBuilder()
+            .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.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.JURISDICTION_LOCALITY_NAME, u"value"
+                        ),
+                        x509.NameAttribute(
+                            NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME,
+                            u"value",
+                        ),
+                        x509.NameAttribute(
+                            NameOID.BUSINESS_CATEGORY, u"value"
+                        ),
+                        x509.NameAttribute(NameOID.POSTAL_ADDRESS, u"value"),
+                        x509.NameAttribute(NameOID.POSTAL_CODE, u"value"),
+                    ]
+                )
+            )
+            .sign(private_key, hashes.SHA256(), backend)
+        )
         for oid, asn1_type in TestNameAttribute.EXPECTED_TYPES:
-            assert request.subject.get_attributes_for_oid(
-                oid
-            )[0]._type == asn1_type
+            assert (
+                request.subject.get_attributes_for_oid(oid)[0]._type
+                == 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([
-            x509.RelativeDistinguishedName([
-                x509.NameAttribute(NameOID.TITLE, u'Test'),
-                x509.NameAttribute(NameOID.COMMON_NAME, u'Multivalue'),
-                x509.NameAttribute(NameOID.SURNAME, u'RDNs'),
-            ]),
-            x509.RelativeDistinguishedName([
-                x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA')
-            ]),
-        ])
+        subject = x509.Name(
+            [
+                x509.RelativeDistinguishedName(
+                    [
+                        x509.NameAttribute(NameOID.TITLE, u"Test"),
+                        x509.NameAttribute(NameOID.COMMON_NAME, u"Multivalue"),
+                        x509.NameAttribute(NameOID.SURNAME, u"RDNs"),
+                    ]
+                ),
+                x509.RelativeDistinguishedName(
+                    [x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")]
+                ),
+            ]
+        )
 
-        request = x509.CertificateSigningRequestBuilder().subject_name(
-            subject
-        ).sign(private_key, hashes.SHA1(), backend)
+        request = (
+            x509.CertificateSigningRequestBuilder()
+            .subject_name(subject)
+            .sign(private_key, hashes.SHA1(), backend)
+        )
 
         loaded_request = x509.load_pem_x509_csr(
             request.public_bytes(encoding=serialization.Encoding.PEM), backend
@@ -2939,13 +3593,17 @@
     def test_build_nonca_request_with_rsa(self, backend):
         private_key = RSA_KEY_2048.private_key(backend)
 
-        request = x509.CertificateSigningRequestBuilder().subject_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-            ])
-        ).add_extension(
-            x509.BasicConstraints(ca=False, path_length=None), critical=True,
-        ).sign(private_key, hashes.SHA1(), backend)
+        request = (
+            x509.CertificateSigningRequestBuilder()
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .add_extension(
+                x509.BasicConstraints(ca=False, path_length=None),
+                critical=True,
+            )
+            .sign(private_key, hashes.SHA1(), backend)
+        )
 
         assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
         public_key = request.public_key()
@@ -2953,7 +3611,7 @@
         subject = request.subject
         assert isinstance(subject, x509.Name)
         assert list(subject) == [
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
+            x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
         ]
         basic_constraints = request.extensions.get_extension_for_oid(
             ExtensionOID.BASIC_CONSTRAINTS
@@ -2966,13 +3624,22 @@
         _skip_curve_unsupported(backend, ec.SECP256R1())
         private_key = ec.generate_private_key(ec.SECP256R1(), backend)
 
-        request = x509.CertificateSigningRequestBuilder().subject_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
-            ])
-        ).add_extension(
-            x509.BasicConstraints(ca=True, path_length=2), critical=True
-        ).sign(private_key, hashes.SHA1(), backend)
+        request = (
+            x509.CertificateSigningRequestBuilder()
+            .subject_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
+                        ),
+                    ]
+                )
+            )
+            .add_extension(
+                x509.BasicConstraints(ca=True, path_length=2), critical=True
+            )
+            .sign(private_key, hashes.SHA1(), backend)
+        )
 
         assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
         public_key = request.public_key()
@@ -2980,7 +3647,85 @@
         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, u"Texas"),
+        ]
+        basic_constraints = request.extensions.get_extension_for_oid(
+            ExtensionOID.BASIC_CONSTRAINTS
+        )
+        assert basic_constraints.value.ca is True
+        assert basic_constraints.value.path_length == 2
+
+    @pytest.mark.supported(
+        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()
+
+        request = (
+            x509.CertificateSigningRequestBuilder()
+            .subject_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
+                        ),
+                    ]
+                )
+            )
+            .add_extension(
+                x509.BasicConstraints(ca=True, path_length=2), critical=True
+            )
+            .sign(private_key, None, backend)
+        )
+
+        assert request.signature_hash_algorithm is None
+        public_key = request.public_key()
+        assert isinstance(public_key, ed25519.Ed25519PublicKey)
+        subject = request.subject
+        assert isinstance(subject, x509.Name)
+        assert list(subject) == [
+            x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
+        ]
+        basic_constraints = request.extensions.get_extension_for_oid(
+            ExtensionOID.BASIC_CONSTRAINTS
+        )
+        assert basic_constraints.value.ca is True
+        assert basic_constraints.value.path_length == 2
+
+    @pytest.mark.supported(
+        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()
+
+        request = (
+            x509.CertificateSigningRequestBuilder()
+            .subject_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
+                        ),
+                    ]
+                )
+            )
+            .add_extension(
+                x509.BasicConstraints(ca=True, path_length=2), critical=True
+            )
+            .sign(private_key, None, backend)
+        )
+
+        assert request.signature_hash_algorithm is None
+        public_key = request.public_key()
+        assert isinstance(public_key, ed448.Ed448PublicKey)
+        subject = request.subject
+        assert isinstance(subject, x509.Name)
+        assert list(subject) == [
+            x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
         ]
         basic_constraints = request.extensions.get_extension_for_oid(
             ExtensionOID.BASIC_CONSTRAINTS
@@ -2992,13 +3737,16 @@
     def test_build_ca_request_with_dsa(self, backend):
         private_key = DSA_KEY_2048.private_key(backend)
 
-        request = x509.CertificateSigningRequestBuilder().subject_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-            ])
-        ).add_extension(
-            x509.BasicConstraints(ca=True, path_length=2), critical=True
-        ).sign(private_key, hashes.SHA1(), backend)
+        request = (
+            x509.CertificateSigningRequestBuilder()
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .add_extension(
+                x509.BasicConstraints(ca=True, path_length=2), critical=True
+            )
+            .sign(private_key, hashes.SHA1(), backend)
+        )
 
         assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
         public_key = request.public_key()
@@ -3006,7 +3754,7 @@
         subject = request.subject
         assert isinstance(subject, x509.Name)
         assert list(subject) == [
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
+            x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
         ]
         basic_constraints = request.extensions.get_extension_for_oid(
             ExtensionOID.BASIC_CONSTRAINTS
@@ -3016,17 +3764,19 @@
 
     def test_add_duplicate_extension(self):
         builder = x509.CertificateSigningRequestBuilder().add_extension(
-            x509.BasicConstraints(True, 2), critical=True,
+            x509.BasicConstraints(True, 2),
+            critical=True,
         )
         with pytest.raises(ValueError):
             builder.add_extension(
-                x509.BasicConstraints(True, 2), critical=True,
+                x509.BasicConstraints(True, 2),
+                critical=True,
             )
 
     def test_set_invalid_subject(self):
         builder = x509.CertificateSigningRequestBuilder()
         with pytest.raises(TypeError):
-            builder.subject_name('NotAName')
+            builder.subject_name("NotAName")
 
     def test_add_invalid_extension_type(self):
         builder = x509.CertificateSigningRequestBuilder()
@@ -3037,15 +3787,17 @@
     def test_add_unsupported_extension(self, backend):
         private_key = RSA_KEY_2048.private_key(backend)
         builder = x509.CertificateSigningRequestBuilder()
-        builder = builder.subject_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-            ])
-        ).add_extension(
-            x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]),
-            critical=False,
-        ).add_extension(
-            DummyExtension(), False
+        builder = (
+            builder.subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .add_extension(
+                x509.SubjectAlternativeName(
+                    [x509.DNSName(u"cryptography.io")]
+                ),
+                critical=False,
+            )
+            .add_extension(DummyExtension(), False)
         )
         with pytest.raises(NotImplementedError):
             builder.sign(private_key, hashes.SHA256(), backend)
@@ -3053,24 +3805,26 @@
     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, u'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)
+        request = (
+            builder.subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"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
@@ -3083,30 +3837,32 @@
             key_cert_sign=True,
             crl_sign=False,
             encipher_only=False,
-            decipher_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, u'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)
+        request = (
+            builder.subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"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
@@ -3119,20 +3875,27 @@
             key_cert_sign=True,
             crl_sign=False,
             encipher_only=False,
-            decipher_only=True
+            decipher_only=True,
         )
 
     def test_add_two_extensions(self, backend):
         private_key = RSA_KEY_2048.private_key(backend)
         builder = x509.CertificateSigningRequestBuilder()
-        request = builder.subject_name(
-            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
-        ).add_extension(
-            x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]),
-            critical=False,
-        ).add_extension(
-            x509.BasicConstraints(ca=True, path_length=2), critical=True
-        ).sign(private_key, hashes.SHA1(), backend)
+        request = (
+            builder.subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .add_extension(
+                x509.SubjectAlternativeName(
+                    [x509.DNSName(u"cryptography.io")]
+                ),
+                critical=False,
+            )
+            .add_extension(
+                x509.BasicConstraints(ca=True, path_length=2), critical=True
+            )
+            .sign(private_key, hashes.SHA1(), backend)
+        )
 
         assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
         public_key = request.public_key()
@@ -3147,58 +3910,129 @@
         )
         assert list(ext.value) == [x509.DNSName(u"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)
+        challenge_password = b"challenge me!"
+        unstructured_name = b"no structure, for shame"
+        locality = b"this shouldn't even be an X509 attribute"
+
+        request = (
+            x509.CertificateSigningRequestBuilder()
+            .subject_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
+                        ),
+                    ]
+                )
+            )
+            .add_attribute(
+                x509.oid.AttributeOID.CHALLENGE_PASSWORD, challenge_password
+            )
+            .add_attribute(
+                x509.oid.AttributeOID.UNSTRUCTURED_NAME, unstructured_name
+            )
+            .add_attribute(x509.oid.NameOID.LOCALITY_NAME, locality)
+            .sign(private_key, hashes.SHA256(), backend)
+        )
+
+        assert (
+            request.get_attribute_for_oid(
+                x509.oid.AttributeOID.CHALLENGE_PASSWORD
+            )
+            == challenge_password
+        )
+        assert (
+            request.get_attribute_for_oid(
+                x509.oid.AttributeOID.UNSTRUCTURED_NAME
+            )
+            == unstructured_name
+        )
+        assert (
+            request.get_attribute_for_oid(x509.oid.NameOID.LOCALITY_NAME)
+            == locality
+        )
+
+    def test_add_attribute_bad_types(self, backend):
+        request = x509.CertificateSigningRequestBuilder()
+        with pytest.raises(TypeError):
+            request.add_attribute(b"not an oid", b"val")
+
+        with pytest.raises(TypeError):
+            request.add_attribute(
+                x509.oid.AttributeOID.CHALLENGE_PASSWORD, 383
+            )
+
+    def test_duplicate_attribute(self, backend):
+        request = x509.CertificateSigningRequestBuilder().add_attribute(
+            x509.oid.AttributeOID.CHALLENGE_PASSWORD, b"val"
+        )
+        with pytest.raises(ValueError):
+            request.add_attribute(
+                x509.oid.AttributeOID.CHALLENGE_PASSWORD, b"val2"
+            )
+
     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, u"US")])
         )
         with pytest.raises(ValueError):
             builder.subject_name(
-                x509.Name([
-                    x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-                ])
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
             )
 
     def test_subject_alt_names(self, backend):
         private_key = RSA_KEY_2048.private_key(backend)
 
-        san = x509.SubjectAlternativeName([
-            x509.DNSName(u"example.com"),
-            x509.DNSName(u"*.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.ORGANIZATION_NAME, u'We heart UTF8!\u2122'
-                )
-            ])),
-            x509.IPAddress(ipaddress.ip_address(u"127.0.0.1")),
-            x509.IPAddress(ipaddress.ip_address(u"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.UniformResourceIdentifier(
-                u"https://xn--80ato2c.cryptography"
-            ),
-            x509.UniformResourceIdentifier(
-                u"gopher://cryptography:70/some/path"
-            ),
-        ])
+        san = x509.SubjectAlternativeName(
+            [
+                x509.DNSName(u"example.com"),
+                x509.DNSName(u"*.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.ORGANIZATION_NAME,
+                                u"We heart UTF8!\u2122",
+                            ),
+                        ]
+                    )
+                ),
+                x509.IPAddress(ipaddress.ip_address(u"127.0.0.1")),
+                x509.IPAddress(ipaddress.ip_address(u"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.UniformResourceIdentifier(
+                    u"https://xn--80ato2c.cryptography"
+                ),
+                x509.UniformResourceIdentifier(
+                    u"gopher://cryptography:70/some/path"
+                ),
+            ]
+        )
 
-        csr = x509.CertificateSigningRequestBuilder().subject_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"SAN"),
-            ])
-        ).add_extension(
-            san,
-            critical=False,
-        ).sign(private_key, hashes.SHA256(), backend)
+        csr = (
+            x509.CertificateSigningRequestBuilder()
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"SAN")])
+            )
+            .add_extension(
+                san,
+                critical=False,
+            )
+            .sign(private_key, hashes.SHA256(), backend)
+        )
 
         assert len(csr.extensions) == 1
         ext = csr.extensions.get_extension_for_oid(
@@ -3211,18 +4045,22 @@
     def test_invalid_asn1_othername(self, backend):
         private_key = RSA_KEY_2048.private_key(backend)
 
-        builder = x509.CertificateSigningRequestBuilder().subject_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"SAN"),
-            ])
-        ).add_extension(
-            x509.SubjectAlternativeName([
-                x509.OtherName(
-                    type_id=x509.ObjectIdentifier("1.2.3.3.3.3"),
-                    value=b"\x01\x02\x01\x05"
+        builder = (
+            x509.CertificateSigningRequestBuilder()
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"SAN")])
+            )
+            .add_extension(
+                x509.SubjectAlternativeName(
+                    [
+                        x509.OtherName(
+                            type_id=x509.ObjectIdentifier("1.2.3.3.3.3"),
+                            value=b"\x01\x02\x01\x05",
+                        ),
+                    ]
                 ),
-            ]),
-            critical=False,
+                critical=False,
+            )
         )
         with pytest.raises(ValueError):
             builder.sign(private_key, hashes.SHA256(), backend)
@@ -3230,13 +4068,15 @@
     def test_subject_alt_name_unsupported_general_name(self, backend):
         private_key = RSA_KEY_2048.private_key(backend)
 
-        builder = x509.CertificateSigningRequestBuilder().subject_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"SAN"),
-            ])
-        ).add_extension(
-            x509.SubjectAlternativeName([FakeGeneralName("")]),
-            critical=False,
+        builder = (
+            x509.CertificateSigningRequestBuilder()
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"SAN")])
+            )
+            .add_extension(
+                x509.SubjectAlternativeName([FakeGeneralName("")]),
+                critical=False,
+            )
         )
 
         with pytest.raises(ValueError):
@@ -3244,17 +4084,21 @@
 
     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,
-        ])
+        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, u'US')])
-        ).add_extension(
-            eku, critical=False
-        ).sign(private_key, hashes.SHA256(), backend)
+        request = (
+            builder.subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .add_extension(eku, critical=False)
+            .sign(private_key, hashes.SHA256(), backend)
+        )
 
         ext = request.extensions.get_extension_for_oid(
             ExtensionOID.EXTENDED_KEY_USAGE
@@ -3264,17 +4108,15 @@
 
     @pytest.mark.requires_backend_interface(interface=RSABackend)
     def test_rsa_key_too_small(self, backend):
-        private_key = rsa.generate_private_key(65537, 512, 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, u"US")])
         )
 
-        with pytest.raises(ValueError) as exc:
+        with pytest.raises(ValueError):
             builder.sign(private_key, hashes.SHA512(), backend)
 
-        assert str(exc.value) == "Digest too big for RSA key"
-
     @pytest.mark.requires_backend_interface(interface=RSABackend)
     @pytest.mark.requires_backend_interface(interface=X509Backend)
     def test_build_cert_with_aia(self, backend):
@@ -3284,31 +4126,34 @@
         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(u"http://ocsp.domain.com")
-            ),
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.CA_ISSUERS,
-                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
-            )
-        ])
+        aia = x509.AuthorityInformationAccess(
+            [
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.OCSP,
+                    x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+                ),
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.CA_ISSUERS,
+                    x509.UniformResourceIdentifier(
+                        u"http://domain.com/ca.crt"
+                    ),
+                ),
+            ]
+        )
 
-        builder = x509.CertificateBuilder().serial_number(
-            777
-        ).issuer_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).subject_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'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
+        builder = (
+            x509.CertificateBuilder()
+            .serial_number(777)
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"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.SHA1(), backend)
@@ -3320,6 +4165,46 @@
 
     @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)
+
+        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(u"http://ca.domain.com"),
+                ),
+            ]
+        )
+
+        builder = (
+            x509.CertificateBuilder()
+            .serial_number(777)
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"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
+
+    @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)
@@ -3331,20 +4216,19 @@
             subject_private_key.public_key()
         )
 
-        builder = x509.CertificateBuilder().serial_number(
-            777
-        ).issuer_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
-        ])).subject_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'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
+        builder = (
+            x509.CertificateBuilder()
+            .serial_number(777)
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"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.SHA1(), backend)
@@ -3361,42 +4245,46 @@
                 b"\xc3\x9c\xf3\xfc\xd3F\x084\xbb\xceF\x7f\xa0|[\xf3\xe2\x08"
                 b"\xcbY",
                 None,
-                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, u"PyCA"
-                            ),
-                            x509.NameAttribute(
-                                NameOID.COMMON_NAME, u"cryptography CA"
-                            )
-                        ])
+                        x509.Name(
+                            [
+                                x509.NameAttribute(
+                                    NameOID.ORGANIZATION_NAME, u"PyCA"
+                                ),
+                                x509.NameAttribute(
+                                    NameOID.COMMON_NAME, u"cryptography CA"
+                                ),
+                            ]
+                        )
                     )
                 ],
-                333
+                333,
             ),
             x509.AuthorityKeyIdentifier(
                 None,
                 [
                     x509.DirectoryName(
-                        x509.Name([
-                            x509.NameAttribute(
-                                NameOID.ORGANIZATION_NAME, u"PyCA"
-                            ),
-                            x509.NameAttribute(
-                                NameOID.COMMON_NAME, u"cryptography CA"
-                            )
-                        ])
+                        x509.Name(
+                            [
+                                x509.NameAttribute(
+                                    NameOID.ORGANIZATION_NAME, u"PyCA"
+                                ),
+                                x509.NameAttribute(
+                                    NameOID.COMMON_NAME, u"cryptography CA"
+                                ),
+                            ]
+                        )
                     )
                 ],
-                333
+                333,
             ),
-        ]
+        ],
     )
     @pytest.mark.requires_backend_interface(interface=RSABackend)
     @pytest.mark.requires_backend_interface(interface=X509Backend)
@@ -3407,20 +4295,19 @@
         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, u'US'),
-        ])).subject_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'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
+        builder = (
+            x509.CertificateBuilder()
+            .serial_number(777)
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"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)
@@ -3437,27 +4324,24 @@
         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, u'US'),
-        ])).subject_name(x509.Name([
-            x509.NameAttribute(NameOID.COUNTRY_NAME, u'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
+        builder = (
+            x509.CertificateBuilder()
+            .serial_number(777)
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"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
-        )
+        ext = cert.extensions.get_extension_for_oid(ExtensionOID.OCSP_NO_CHECK)
         assert isinstance(ext.value, x509.OCSPNoCheck)
 
 
@@ -3468,7 +4352,7 @@
         cert = _load_cert(
             os.path.join("x509", "custom", "dsa_selfsigned_ca.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         assert isinstance(cert.signature_hash_algorithm, hashes.SHA1)
         public_key = cert.public_key()
@@ -3483,7 +4367,8 @@
             "1b4bb7b81c2783da97cea62df67af5e85991fdc13aff10fc60e06586386"
             "b96bb78d65750f542f86951e05a6d81baadbcd35a2e5cad4119923ae6a2"
             "002091a3d17017f93c52970113cdc119970b9074ca506eac91c3dd37632"
-            "5df4af6b3911ef267d26623a5a1c5df4a6d13f1c", 16
+            "5df4af6b3911ef267d26623a5a1c5df4a6d13f1c",
+            16,
         )
         assert num.parameter_numbers.g == int(
             "4b7ced71dc353965ecc10d441a9a06fc24943a32d66429dd5ef44d43e67"
@@ -3494,7 +4379,8 @@
             "3fbfa136205f130bee2cf5b9c38dc1095d4006f2e73335c07352c64130a"
             "1ab2b89f13b48f628d3cc3868beece9bb7beade9f830eacc6fa241425c0"
             "b3fcc0df416a0c89f7bf35668d765ec95cdcfbe9caff49cfc156c668c76"
-            "fa6247676a6d3ac945844a083509c6a1b436baca", 16
+            "fa6247676a6d3ac945844a083509c6a1b436baca",
+            16,
         )
         assert num.parameter_numbers.p == int(
             "bfade6048e373cd4e48b677e878c8e5b08c02102ae04eb2cb5c46a523a3"
@@ -3505,7 +4391,8 @@
             "e703313743d86caa885930f62ed5bf342d8165627681e9cc3244ba72aa2"
             "2148400a6bbe80154e855d042c9dc2a3405f1e517be9dea50562f56da93"
             "f6085f844a7e705c1f043e65751c583b80d29103e590ccb26efdaa0893d"
-            "833e36468f3907cfca788a3cb790f0341c8a31bf", 16
+            "833e36468f3907cfca788a3cb790f0341c8a31bf",
+            16,
         )
         assert num.parameter_numbers.q == int(
             "822ff5d234e073b901cf5941f58e1f538e71d40d", 16
@@ -3515,7 +4402,7 @@
         cert = _load_cert(
             os.path.join("x509", "custom", "dsa_selfsigned_ca.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         assert cert.signature == binascii.unhexlify(
             b"302c021425c4a84a936ab311ee017d3cbd9a3c650bb3ae4a02145d30c64b4326"
@@ -3529,7 +4416,7 @@
         cert = _load_cert(
             os.path.join("x509", "custom", "dsa_selfsigned_ca.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         assert cert.tbs_certificate_bytes == binascii.unhexlify(
             b"3082051aa003020102020900a37352e0b2142f86300906072a8648ce3804033"
@@ -3576,8 +4463,9 @@
             b"0b2142f86300c0603551d13040530030101ff"
         )
         cert.public_key().verify(
-            cert.signature, cert.tbs_certificate_bytes,
-            cert.signature_hash_algorithm
+            cert.signature,
+            cert.tbs_certificate_bytes,
+            cert.signature_hash_algorithm,
         )
 
 
@@ -3589,13 +4477,13 @@
         [
             [
                 os.path.join("x509", "requests", "dsa_sha1.pem"),
-                x509.load_pem_x509_csr
+                x509.load_pem_x509_csr,
             ],
             [
                 os.path.join("x509", "requests", "dsa_sha1.der"),
-                x509.load_der_x509_csr
+                x509.load_der_x509_csr,
             ],
-        ]
+        ],
     )
     def test_load_dsa_request(self, path, loader_func, backend):
         request = _load_cert(path, loader_func, backend)
@@ -3605,18 +4493,18 @@
         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, 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"),
         ]
 
     def test_signature(self, backend):
         request = _load_cert(
             os.path.join("x509", "requests", "dsa_sha1.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
         assert request.signature == binascii.unhexlify(
             b"302c021461d58dc028d0110818a7d817d74235727c4acfdf0214097b52e198e"
@@ -3627,7 +4515,7 @@
         request = _load_cert(
             os.path.join("x509", "requests", "dsa_sha1.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
         assert request.tbs_certrequest_bytes == binascii.unhexlify(
             b"3082021802010030573118301606035504030c0f63727970746f677261706879"
@@ -3651,7 +4539,7 @@
         request.public_key().verify(
             request.signature,
             request.tbs_certrequest_bytes,
-            request.signature_hash_algorithm
+            request.signature_hash_algorithm,
         )
 
 
@@ -3663,7 +4551,7 @@
         cert = _load_cert(
             os.path.join("x509", "ecdsa_root.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         assert isinstance(cert.signature_hash_algorithm, hashes.SHA384)
         public_key = cert.public_key()
@@ -3671,11 +4559,13 @@
         num = public_key.public_numbers()
         assert num.x == int(
             "dda7d9bb8ab80bfb0b7f21d2f0bebe73f3335d1abc34eadec69bbcd095f"
-            "6f0ccd00bba615b51467e9e2d9fee8e630c17", 16
+            "6f0ccd00bba615b51467e9e2d9fee8e630c17",
+            16,
         )
         assert num.y == int(
             "ec0770f5cf842e40839ce83f416d3badd3a4145936789d0343ee10136c7"
-            "2deae88a7a16bb543ce67dc23ff031ca3e23e", 16
+            "2deae88a7a16bb543ce67dc23ff031ca3e23e",
+            16,
         )
         assert isinstance(num.curve, ec.SECP384R1)
 
@@ -3683,7 +4573,7 @@
         cert = _load_cert(
             os.path.join("x509", "ecdsa_root.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         assert cert.signature == binascii.unhexlify(
             b"3065023100adbcf26c3f124ad12d39c30a099773f488368c8827bbe6888d5085"
@@ -3695,12 +4585,12 @@
         assert r == int(
             "adbcf26c3f124ad12d39c30a099773f488368c8827bbe6888d5085a763f99e32"
             "de66930ff1ccb1098fdd6cabfa6b7fa0",
-            16
+            16,
         )
         assert s == int(
             "39665bc2648db89e50dca8d549a2edc7dcd1497f1701b8c8868f4e8c882ba89a"
             "a98ac5d100bdf854e29ae55b7cb32717",
-            16
+            16,
         )
 
     def test_tbs_certificate_bytes(self, backend):
@@ -3708,7 +4598,7 @@
         cert = _load_cert(
             os.path.join("x509", "ecdsa_root.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         assert cert.tbs_certificate_bytes == binascii.unhexlify(
             b"308201c5a0030201020210055556bcf25ea43535c3a40fd5ab4572300a06082"
@@ -3728,8 +4618,9 @@
             b"f9a1c5d8ae3641cc1163696229bc4bc6"
         )
         cert.public_key().verify(
-            cert.signature, cert.tbs_certificate_bytes,
-            ec.ECDSA(cert.signature_hash_algorithm)
+            cert.signature,
+            cert.tbs_certificate_bytes,
+            ec.ECDSA(cert.signature_hash_algorithm),
         )
 
     def test_load_ecdsa_no_named_curve(self, backend):
@@ -3737,7 +4628,7 @@
         cert = _load_cert(
             os.path.join("x509", "custom", "ec_no_named_curve.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         with pytest.raises(NotImplementedError):
             cert.public_key()
@@ -3751,13 +4642,13 @@
         [
             [
                 os.path.join("x509", "requests", "ec_sha256.pem"),
-                x509.load_pem_x509_csr
+                x509.load_pem_x509_csr,
             ],
             [
                 os.path.join("x509", "requests", "ec_sha256.der"),
-                x509.load_der_x509_csr
+                x509.load_der_x509_csr,
             ],
-        ]
+        ],
     )
     def test_load_ecdsa_certificate_request(self, path, loader_func, backend):
         _skip_curve_unsupported(backend, ec.SECP384R1())
@@ -3768,11 +4659,11 @@
         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, 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"),
         ]
 
     def test_signature(self, backend):
@@ -3780,7 +4671,7 @@
         request = _load_cert(
             os.path.join("x509", "requests", "ec_sha256.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
         assert request.signature == binascii.unhexlify(
             b"306502302c1a9f7de8c1787332d2307a886b476a59f172b9b0e250262f3238b1"
@@ -3794,7 +4685,7 @@
         request = _load_cert(
             os.path.join("x509", "requests", "ec_sha256.pem"),
             x509.load_pem_x509_csr,
-            backend
+            backend,
         )
         assert request.tbs_certrequest_bytes == binascii.unhexlify(
             b"3081d602010030573118301606035504030c0f63727970746f6772617068792"
@@ -3806,8 +4697,9 @@
             b"accff0ffaf7155812909d3726bd59fde001cff4bb9b2f5af8cbaa000"
         )
         request.public_key().verify(
-            request.signature, request.tbs_certrequest_bytes,
-            ec.ECDSA(request.signature_hash_algorithm)
+            request.signature,
+            request.tbs_certrequest_bytes,
+            ec.ECDSA(request.signature_hash_algorithm),
         )
 
 
@@ -3827,14 +4719,12 @@
 
     def test_bad_time_in_validity(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "badasn1time.pem"
-            ),
+            os.path.join("x509", "badasn1time.pem"),
             x509.load_pem_x509_certificate,
             backend,
         )
 
-        with pytest.raises(ValueError, match='19020701025736Z'):
+        with pytest.raises(ValueError, match="19020701025736Z"):
             cert.not_valid_after
 
 
@@ -3860,10 +4750,7 @@
         (NameOID.EMAIL_ADDRESS, _ASN1Type.IA5String),
         (NameOID.JURISDICTION_COUNTRY_NAME, _ASN1Type.PrintableString),
         (NameOID.JURISDICTION_LOCALITY_NAME, _ASN1Type.UTF8String),
-        (
-            NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME,
-            _ASN1Type.UTF8String
-        ),
+        (NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME, _ASN1Type.UTF8String),
         (NameOID.BUSINESS_CATEGORY, _ASN1Type.UTF8String),
         (NameOID.POSTAL_ADDRESS, _ASN1Type.UTF8String),
         (NameOID.POSTAL_CODE, _ASN1Type.UTF8String),
@@ -3882,32 +4769,23 @@
 
     def test_init_bad_oid(self):
         with pytest.raises(TypeError):
-            x509.NameAttribute(None, u'value')
+            x509.NameAttribute(None, u"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")
+
+    def test_init_none_value(self):
+        with pytest.raises(TypeError):
+            x509.NameAttribute(NameOID.ORGANIZATION_NAME, None)
 
     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, u"United States")
 
         # unicode string of length 2, but > 2 bytes
         with pytest.raises(ValueError):
-            x509.NameAttribute(
-                NameOID.COUNTRY_NAME,
-                u'\U0001F37A\U0001F37A'
-            )
-
-    def test_init_empty_value(self):
-        with pytest.raises(ValueError):
-            x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'')
+            x509.NameAttribute(NameOID.COUNTRY_NAME, u"\U0001F37A\U0001F37A")
 
     def test_invalid_type(self):
         with pytest.raises(TypeError):
@@ -3915,28 +4793,23 @@
 
     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"), u"value"
+        ) == x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"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"), u"value"
+        ) != x509.NameAttribute(x509.ObjectIdentifier("2.5.4.5"), u"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"), u"value"
+        ) != x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value2")
+        assert (
+            x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value")
+            != object()
         )
-        assert x509.NameAttribute(
-            x509.ObjectIdentifier('2.999.2'), u'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"), u"value")
         if not six.PY2:
             assert repr(na) == (
                 "<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commo"
@@ -3951,14 +4824,19 @@
     def test_distinugished_name(self):
         # Escaping
         na = x509.NameAttribute(NameOID.COMMON_NAME, u'James "Jim" Smith, III')
-        assert na.rfc4514_string() == r'CN=James \"Jim\" Smith\, III'
-        na = x509.NameAttribute(NameOID.USER_ID, u'# escape+,;\0this ')
-        assert na.rfc4514_string() == r'UID=\# escape\+\,\;\00this\ '
+        assert na.rfc4514_string() == r"CN=James \"Jim\" Smith\, III"
+        na = x509.NameAttribute(NameOID.USER_ID, u"# escape+,;\0this ")
+        assert na.rfc4514_string() == r"UID=\# escape\+\,\;\00this\ "
 
         # Nonstandard attribute OID
-        na = x509.NameAttribute(NameOID.EMAIL_ADDRESS, u'somebody@example.com')
-        assert (na.rfc4514_string() ==
-                '1.2.840.113549.1.9.1=somebody@example.com')
+        na = x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"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"")
+        assert na.rfc4514_string() == r"ST="
 
 
 class TestRelativeDistinguishedName(object):
@@ -3972,78 +4850,126 @@
 
     def test_init_duplicate_attribute(self):
         with pytest.raises(ValueError):
-            x509.RelativeDistinguishedName([
-                x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'val1'),
-                x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'val1'),
-            ])
+            x509.RelativeDistinguishedName(
+                [
+                    x509.NameAttribute(
+                        x509.ObjectIdentifier("2.999.1"), u"val1"
+                    ),
+                    x509.NameAttribute(
+                        x509.ObjectIdentifier("2.999.1"), u"val1"
+                    ),
+                ]
+            )
 
     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'),
-        ])
-        rdn2 = x509.RelativeDistinguishedName([
-            x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'),
-            x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'),
-        ])
-        rdn3 = x509.RelativeDistinguishedName([
-            x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'),
-            x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value3'),
-        ])
+        rdn1 = x509.RelativeDistinguishedName(
+            [
+                x509.NameAttribute(
+                    x509.ObjectIdentifier("2.999.1"), u"value1"
+                ),
+                x509.NameAttribute(
+                    x509.ObjectIdentifier("2.999.2"), u"value2"
+                ),
+            ]
+        )
+        rdn2 = x509.RelativeDistinguishedName(
+            [
+                x509.NameAttribute(
+                    x509.ObjectIdentifier("2.999.2"), u"value2"
+                ),
+                x509.NameAttribute(
+                    x509.ObjectIdentifier("2.999.1"), u"value1"
+                ),
+            ]
+        )
+        rdn3 = x509.RelativeDistinguishedName(
+            [
+                x509.NameAttribute(
+                    x509.ObjectIdentifier("2.999.1"), u"value1"
+                ),
+                x509.NameAttribute(
+                    x509.ObjectIdentifier("2.999.2"), u"value3"
+                ),
+            ]
+        )
         assert hash(rdn1) == hash(rdn2)
         assert hash(rdn1) != hash(rdn3)
 
     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'),
-        ])
-        rdn2 = x509.RelativeDistinguishedName([
-            x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'),
-            x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'),
-        ])
+        rdn1 = x509.RelativeDistinguishedName(
+            [
+                x509.NameAttribute(
+                    x509.ObjectIdentifier("2.999.1"), u"value1"
+                ),
+                x509.NameAttribute(
+                    x509.ObjectIdentifier("2.999.2"), u"value2"
+                ),
+            ]
+        )
+        rdn2 = x509.RelativeDistinguishedName(
+            [
+                x509.NameAttribute(
+                    x509.ObjectIdentifier("2.999.2"), u"value2"
+                ),
+                x509.NameAttribute(
+                    x509.ObjectIdentifier("2.999.1"), u"value1"
+                ),
+            ]
+        )
         assert rdn1 == rdn2
 
     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'),
-        ])
-        rdn2 = x509.RelativeDistinguishedName([
-            x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'),
-            x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value3'),
-        ])
+        rdn1 = x509.RelativeDistinguishedName(
+            [
+                x509.NameAttribute(
+                    x509.ObjectIdentifier("2.999.1"), u"value1"
+                ),
+                x509.NameAttribute(
+                    x509.ObjectIdentifier("2.999.2"), u"value2"
+                ),
+            ]
+        )
+        rdn2 = x509.RelativeDistinguishedName(
+            [
+                x509.NameAttribute(
+                    x509.ObjectIdentifier("2.999.1"), u"value1"
+                ),
+                x509.NameAttribute(
+                    x509.ObjectIdentifier("2.999.2"), u"value3"
+                ),
+            ]
+        )
         assert rdn1 != rdn2
         assert rdn1 != object()
 
     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"), u"value1"),
+            x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value2"),
+            x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value3"),
         ]
         rdn = x509.RelativeDistinguishedName(iter(attrs))
         assert list(rdn) == attrs
         assert list(rdn) == attrs
 
     def test_get_attributes_for_oid(self):
-        oid = x509.ObjectIdentifier('2.999.1')
-        attr = x509.NameAttribute(oid, u'value1')
+        oid = x509.ObjectIdentifier("2.999.1")
+        attr = x509.NameAttribute(oid, u"value1")
         rdn = x509.RelativeDistinguishedName([attr])
         assert rdn.get_attributes_for_oid(oid) == [attr]
-        assert rdn.get_attributes_for_oid(x509.ObjectIdentifier('1.2.3')) == []
+        assert rdn.get_attributes_for_oid(x509.ObjectIdentifier("1.2.3")) == []
 
 
 class TestObjectIdentifier(object):
     def test_eq(self):
-        oid1 = x509.ObjectIdentifier('2.999.1')
-        oid2 = x509.ObjectIdentifier('2.999.1')
+        oid1 = x509.ObjectIdentifier("2.999.1")
+        oid2 = x509.ObjectIdentifier("2.999.1")
         assert oid1 == oid2
 
     def test_ne(self):
-        oid1 = x509.ObjectIdentifier('2.999.1')
-        assert oid1 != x509.ObjectIdentifier('2.999.2')
+        oid1 = x509.ObjectIdentifier("2.999.1")
+        assert oid1 != x509.ObjectIdentifier("2.999.2")
         assert oid1 != object()
 
     def test_repr(self):
@@ -4054,9 +4980,9 @@
 
     def test_name_property(self):
         oid = x509.ObjectIdentifier("2.5.4.3")
-        assert oid._name == 'commonName'
+        assert oid._name == "commonName"
         oid = x509.ObjectIdentifier("2.999.1")
-        assert oid._name == 'Unknown OID'
+        assert oid._name == "Unknown OID"
 
     def test_too_short(self):
         with pytest.raises(ValueError):
@@ -4084,21 +5010,23 @@
 
 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"), u"value1")
+        ava2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2")
         name1 = x509.Name([ava1, ava2])
-        name2 = x509.Name([
-            x509.RelativeDistinguishedName([ava1]),
-            x509.RelativeDistinguishedName([ava2]),
-        ])
+        name2 = x509.Name(
+            [
+                x509.RelativeDistinguishedName([ava1]),
+                x509.RelativeDistinguishedName([ava2]),
+            ]
+        )
         name3 = x509.Name([x509.RelativeDistinguishedName([ava1, ava2])])
         name4 = x509.Name([x509.RelativeDistinguishedName([ava2, ava1])])
         assert name1 == name2
         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"), u"value1")
+        ava2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2")
         name1 = x509.Name([ava1, ava2])
         name2 = x509.Name([ava2, ava1])
         name3 = x509.Name([x509.RelativeDistinguishedName([ava1, ava2])])
@@ -4107,13 +5035,15 @@
         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"), u"value1")
+        ava2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2")
         name1 = x509.Name([ava1, ava2])
-        name2 = x509.Name([
-            x509.RelativeDistinguishedName([ava1]),
-            x509.RelativeDistinguishedName([ava2]),
-        ])
+        name2 = x509.Name(
+            [
+                x509.RelativeDistinguishedName([ava1]),
+                x509.RelativeDistinguishedName([ava2]),
+            ]
+        )
         name3 = x509.Name([ava2, ava1])
         name4 = x509.Name([x509.RelativeDistinguishedName([ava1, ava2])])
         name5 = x509.Name([x509.RelativeDistinguishedName([ava2, ava1])])
@@ -4124,15 +5054,15 @@
 
     def test_iter_input(self):
         attrs = [
-            x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1')
+            x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"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"), u"value1")
+        rdn2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2")
         name1 = x509.Name([rdn1, rdn2])
         assert name1.rdns == [
             x509.RelativeDistinguishedName([rdn1]),
@@ -4141,29 +5071,63 @@
         name2 = x509.Name([x509.RelativeDistinguishedName([rdn1, rdn2])])
         assert name2.rdns == [x509.RelativeDistinguishedName([rdn1, rdn2])]
 
-    def test_repr(self):
-        name = x509.Name([
-            x509.NameAttribute(NameOID.COMMON_NAME, u'cryptography.io'),
-            x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
-        ])
+    @pytest.mark.parametrize(
+        ("common_name", "org_name", "expected_repr"),
+        [
+            (
+                u"cryptography.io",
+                u"PyCA",
+                "<Name(CN=cryptography.io,O=PyCA)>",
+            ),
+            (
+                u"Certificación",
+                u"Certificación",
+                "<Name(CN=Certificación,O=Certificación)>",
+            ),
+        ],
+    )
+    def test_repr(self, common_name, org_name, expected_repr):
+        name = x509.Name(
+            [
+                x509.NameAttribute(NameOID.COMMON_NAME, common_name),
+                x509.NameAttribute(NameOID.ORGANIZATION_NAME, org_name),
+            ]
+        )
 
-        assert repr(name) == "<Name(CN=cryptography.io,O=PyCA)>"
+        assert repr(name) == expected_repr
 
     def test_rfc4514_string(self):
-        n = x509.Name([
-            x509.RelativeDistinguishedName([
-                x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u'Sales'),
-                x509.NameAttribute(NameOID.COMMON_NAME, u'J.  Smith'),
-            ]),
-            x509.RelativeDistinguishedName([
-                x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u'example'),
-            ]),
-            x509.RelativeDistinguishedName([
-                x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u'net'),
-            ]),
-        ])
-        assert (n.rfc4514_string() ==
-                'OU=Sales+CN=J.  Smith,DC=example,DC=net')
+        n = x509.Name(
+            [
+                x509.RelativeDistinguishedName(
+                    [x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"net")]
+                ),
+                x509.RelativeDistinguishedName(
+                    [x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"example")]
+                ),
+                x509.RelativeDistinguishedName(
+                    [
+                        x509.NameAttribute(
+                            NameOID.ORGANIZATIONAL_UNIT_NAME, u"Sales"
+                        ),
+                        x509.NameAttribute(NameOID.COMMON_NAME, u"J.  Smith"),
+                    ]
+                ),
+            ]
+        )
+        assert n.rfc4514_string() == "OU=Sales+CN=J.  Smith,DC=example,DC=net"
+
+    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"),
+            ]
+        )
+        assert n.rfc4514_string() == "CN=cryptography.io,O=PyCA,L=,ST=,C=US"
 
     def test_not_nameattribute(self):
         with pytest.raises(TypeError):
@@ -4171,10 +5135,12 @@
 
     @pytest.mark.requires_backend_interface(interface=X509Backend)
     def test_bytes(self, backend):
-        name = x509.Name([
-            x509.NameAttribute(NameOID.COMMON_NAME, u'cryptography.io'),
-            x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
-        ])
+        name = x509.Name(
+            [
+                x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"),
+                x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
+            ]
+        )
         assert name.public_bytes(backend) == binascii.unhexlify(
             b"30293118301606035504030c0f63727970746f6772617068792e696f310d300"
             b"b060355040a0c0450794341"
@@ -4185,19 +5151,150 @@
         # 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
         # you pass an odd length string without encoding it properly first.
-        name = x509.Name([
-            x509.NameAttribute(
-                NameOID.COMMON_NAME,
-                u'cryptography.io',
-                _ASN1Type.BMPString
-            ),
-            x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
-        ])
+        name = x509.Name(
+            [
+                x509.NameAttribute(
+                    NameOID.COMMON_NAME,
+                    u"cryptography.io",
+                    _ASN1Type.BMPString,
+                ),
+                x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
+            ]
+        )
         assert name.public_bytes(backend) == binascii.unhexlify(
             b"30383127302506035504031e1e00630072007900700074006f00670072006100"
             b"7000680079002e0069006f310d300b060355040a0c0450794341"
         )
 
+    @pytest.mark.requires_backend_interface(interface=X509Backend)
+    def test_universalstring_bytes(self, backend):
+        # UniversalString is UCS-4
+        name = x509.Name(
+            [
+                x509.NameAttribute(
+                    NameOID.COMMON_NAME,
+                    u"cryptography.io",
+                    _ASN1Type.UniversalString,
+                ),
+                x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
+            ]
+        )
+        assert name.public_bytes(backend) == binascii.unhexlify(
+            b"30563145304306035504031c3c00000063000000720000007900000070000000"
+            b"740000006f000000670000007200000061000000700000006800000079000000"
+            b"2e000000690000006f310d300b060355040a0c0450794341"
+        )
+
+
+@pytest.mark.supported(
+    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(
+            os.path.join("x509", "ed25519", "root-ed25519.pem"),
+            x509.load_pem_x509_certificate,
+            backend,
+        )
+        # self-signed, so this will work
+        cert.public_key().verify(cert.signature, cert.tbs_certificate_bytes)
+        assert isinstance(cert, x509.Certificate)
+        assert cert.serial_number == 9579446940964433301
+        assert cert.signature_hash_algorithm is None
+        assert cert.signature_algorithm_oid == SignatureAlgorithmOID.ED25519
+
+    def test_deepcopy(self, backend):
+        cert = _load_cert(
+            os.path.join("x509", "ed25519", "root-ed25519.pem"),
+            x509.load_pem_x509_certificate,
+            backend,
+        )
+        assert copy.deepcopy(cert) is cert
+
+
+@pytest.mark.supported(
+    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(
+            os.path.join("x509", "ed448", "root-ed448.pem"),
+            x509.load_pem_x509_certificate,
+            backend,
+        )
+        # self-signed, so this will work
+        cert.public_key().verify(cert.signature, cert.tbs_certificate_bytes)
+        assert isinstance(cert, x509.Certificate)
+        assert cert.serial_number == 448
+        assert cert.signature_hash_algorithm is None
+        assert cert.signature_algorithm_oid == SignatureAlgorithmOID.ED448
+
+
+@pytest.mark.requires_backend_interface(interface=X509Backend)
+class TestSignatureRejection(object):
+    """Test if signing rejects DH keys properly."""
+
+    def load_key(self, backend):
+        vector = load_vectors_from_file(
+            os.path.join("asymmetric", "DH", "rfc3526.txt"),
+            load_nist_vectors,
+        )[1]
+        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()
+
+    def test_crt_signing_check(self, backend):
+        issuer_private_key = self.load_key(backend)
+        public_key = RSA_KEY_2048.private_key(backend).public_key()
+        not_valid_before = datetime.datetime(2020, 1, 1, 1, 1)
+        not_valid_after = datetime.datetime(2050, 12, 31, 8, 30)
+        builder = (
+            x509.CertificateBuilder()
+            .serial_number(777)
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .subject_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .public_key(public_key)
+            .not_valid_before(not_valid_before)
+            .not_valid_after(not_valid_after)
+        )
+
+        with pytest.raises(TypeError):
+            builder.sign(issuer_private_key, hashes.SHA256(), 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")])
+        )
+
+        with pytest.raises(TypeError):
+            builder.sign(private_key, hashes.SHA256(), backend)
+
+    def test_crl_signing_check(self, backend):
+        private_key = self.load_key(backend)
+        last_time = datetime.datetime.utcnow().replace(microsecond=0)
+        next_time = last_time
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"CA")])
+            )
+            .last_update(last_time)
+            .next_update(next_time)
+        )
+
+        with pytest.raises(TypeError):
+            builder.sign(private_key, hashes.SHA256(), backend)
+
 
 def test_random_serial_number(monkeypatch):
     sample_data = os.urandom(20)
@@ -4210,7 +5307,5 @@
 
     serial_number = x509.random_serial_number()
 
-    assert (
-        serial_number == utils.int_from_bytes(sample_data, "big") >> 1
-    )
+    assert serial_number == utils.int_from_bytes(sample_data, "big") >> 1
     assert serial_number.bit_length() < 160
diff --git a/tests/x509/test_x509_crlbuilder.py b/tests/x509/test_x509_crlbuilder.py
index 5f220bc..922d249 100644
--- a/tests/x509/test_x509_crlbuilder.py
+++ b/tests/x509/test_x509_crlbuilder.py
@@ -12,11 +12,18 @@
 
 from cryptography import x509
 from cryptography.hazmat.backends.interfaces import (
-    DSABackend, EllipticCurveBackend, RSABackend, X509Backend
+    DSABackend,
+    EllipticCurveBackend,
+    RSABackend,
+    X509Backend,
 )
 from cryptography.hazmat.primitives import hashes
-from cryptography.hazmat.primitives.asymmetric import ec
-from cryptography.x509.oid import AuthorityInformationAccessOID, NameOID
+from cryptography.hazmat.primitives.asymmetric import ec, ed25519, ed448
+from cryptography.x509.oid import (
+    AuthorityInformationAccessOID,
+    NameOID,
+    SignatureAlgorithmOID,
+)
 
 from ..hazmat.primitives.fixtures_dsa import DSA_KEY_2048
 from ..hazmat.primitives.fixtures_ec import EC_KEY_SECP256R1
@@ -32,11 +39,11 @@
 
     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, u"US")])
         )
         with pytest.raises(ValueError):
             builder.issuer_name(
-                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
             )
 
     @pytest.mark.requires_backend_interface(interface=RSABackend)
@@ -48,11 +55,20 @@
         utc_last = datetime.datetime(2012, 1, 17, 6, 43)
         next_time = datetime.datetime(2022, 1, 17, 6, 43)
         private_key = RSA_KEY_2048.private_key(backend)
-        builder = x509.CertificateRevocationListBuilder().issuer_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
-            ])
-        ).last_update(last_time).next_update(next_time)
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_time)
+            .next_update(next_time)
+        )
 
         crl = builder.sign(private_key, hashes.SHA256(), backend)
         assert crl.last_update == utc_last
@@ -83,11 +99,20 @@
         utc_next = datetime.datetime(2022, 1, 17, 6, 43)
         last_time = datetime.datetime(2012, 1, 17, 6, 43)
         private_key = RSA_KEY_2048.private_key(backend)
-        builder = x509.CertificateRevocationListBuilder().issuer_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
-            ])
-        ).last_update(last_time).next_update(next_time)
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_time)
+            .next_update(next_time)
+        )
 
         crl = builder.sign(private_key, hashes.SHA256(), backend)
         assert crl.next_update == utc_next
@@ -112,18 +137,14 @@
     def test_last_update_after_next_update(self):
         builder = x509.CertificateRevocationListBuilder()
 
-        builder = builder.next_update(
-            datetime.datetime(2002, 1, 1, 12, 1)
-        )
+        builder = builder.next_update(datetime.datetime(2002, 1, 1, 12, 1))
         with pytest.raises(ValueError):
             builder.last_update(datetime.datetime(2003, 1, 1, 12, 1))
 
     def test_next_update_after_last_update(self):
         builder = x509.CertificateRevocationListBuilder()
 
-        builder = builder.last_update(
-            datetime.datetime(2002, 1, 1, 12, 1)
-        )
+        builder = builder.last_update(datetime.datetime(2002, 1, 1, 12, 1))
         with pytest.raises(ValueError):
             builder.next_update(datetime.datetime(2001, 1, 1, 12, 1))
 
@@ -139,9 +160,7 @@
         builder = x509.CertificateRevocationListBuilder()
 
         with pytest.raises(TypeError):
-            builder.add_extension(
-                object(), False
-            )
+            builder.add_extension(object(), False)
 
     def test_add_invalid_revoked_certificate(self):
         builder = x509.CertificateRevocationListBuilder()
@@ -153,10 +172,10 @@
     @pytest.mark.requires_backend_interface(interface=X509Backend)
     def test_no_issuer_name(self, backend):
         private_key = RSA_KEY_2048.private_key(backend)
-        builder = x509.CertificateRevocationListBuilder().last_update(
-            datetime.datetime(2002, 1, 1, 12, 1)
-        ).next_update(
-            datetime.datetime(2030, 1, 1, 12, 1)
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .last_update(datetime.datetime(2002, 1, 1, 12, 1))
+            .next_update(datetime.datetime(2030, 1, 1, 12, 1))
         )
 
         with pytest.raises(ValueError):
@@ -166,10 +185,12 @@
     @pytest.mark.requires_backend_interface(interface=X509Backend)
     def test_no_last_update(self, backend):
         private_key = RSA_KEY_2048.private_key(backend)
-        builder = x509.CertificateRevocationListBuilder().issuer_name(
-            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
-        ).next_update(
-            datetime.datetime(2030, 1, 1, 12, 1)
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .next_update(datetime.datetime(2030, 1, 1, 12, 1))
         )
 
         with pytest.raises(ValueError):
@@ -179,10 +200,12 @@
     @pytest.mark.requires_backend_interface(interface=X509Backend)
     def test_no_next_update(self, backend):
         private_key = RSA_KEY_2048.private_key(backend)
-        builder = x509.CertificateRevocationListBuilder().issuer_name(
-            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
-        ).last_update(
-            datetime.datetime(2030, 1, 1, 12, 1)
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+            )
+            .last_update(datetime.datetime(2030, 1, 1, 12, 1))
         )
 
         with pytest.raises(ValueError):
@@ -194,11 +217,20 @@
         private_key = RSA_KEY_2048.private_key(backend)
         last_update = datetime.datetime(2002, 1, 1, 12, 1)
         next_update = datetime.datetime(2030, 1, 1, 12, 1)
-        builder = x509.CertificateRevocationListBuilder().issuer_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
-            ])
-        ).last_update(last_update).next_update(next_update)
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_update)
+            .next_update(next_update)
+        )
 
         crl = builder.sign(private_key, hashes.SHA256(), backend)
         assert len(crl) == 0
@@ -214,18 +246,20 @@
                 b"\xc3\x9c\xf3\xfc\xd3F\x084\xbb\xceF\x7f\xa0|[\xf3\xe2\x08"
                 b"\xcbY",
                 None,
-                None
+                None,
             ),
-            x509.AuthorityInformationAccess([
-                x509.AccessDescription(
-                    AuthorityInformationAccessOID.CA_ISSUERS,
-                    x509.DNSName(u"cryptography.io")
-                )
-            ]),
-            x509.IssuerAlternativeName([
-                x509.UniformResourceIdentifier(u"https://cryptography.io"),
-            ])
-        ]
+            x509.AuthorityInformationAccess(
+                [
+                    x509.AccessDescription(
+                        AuthorityInformationAccessOID.CA_ISSUERS,
+                        x509.DNSName(u"cryptography.io"),
+                    )
+                ]
+            ),
+            x509.IssuerAlternativeName(
+                [x509.UniformResourceIdentifier(u"https://cryptography.io")]
+            ),
+        ],
     )
     @pytest.mark.requires_backend_interface(interface=RSABackend)
     @pytest.mark.requires_backend_interface(interface=X509Backend)
@@ -233,16 +267,20 @@
         private_key = RSA_KEY_2048.private_key(backend)
         last_update = datetime.datetime(2002, 1, 1, 12, 1)
         next_update = datetime.datetime(2030, 1, 1, 12, 1)
-        builder = x509.CertificateRevocationListBuilder().issuer_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
-            ])
-        ).last_update(
-            last_update
-        ).next_update(
-            next_update
-        ).add_extension(
-            extension, False
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_update)
+            .next_update(next_update)
+            .add_extension(extension, False)
         )
 
         crl = builder.sign(private_key, hashes.SHA256(), backend)
@@ -258,22 +296,25 @@
         private_key = RSA_KEY_2048.private_key(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"),
-        ])
+        ian = x509.IssuerAlternativeName(
+            [x509.UniformResourceIdentifier(u"https://cryptography.io")]
+        )
         crl_number = x509.CRLNumber(13)
-        builder = x509.CertificateRevocationListBuilder().issuer_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
-            ])
-        ).last_update(
-            last_update
-        ).next_update(
-            next_update
-        ).add_extension(
-            crl_number, False
-        ).add_extension(
-            ian, True
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_update)
+            .next_update(next_update)
+            .add_extension(crl_number, False)
+            .add_extension(ian, True)
         )
 
         crl = builder.sign(private_key, hashes.SHA256(), backend)
@@ -290,20 +331,66 @@
 
     @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)
+        next_update = datetime.datetime(2030, 1, 1, 12, 1)
+        freshest = x509.FreshestCRL(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"http://d.om/delta")],
+                    None,
+                    None,
+                    None,
+                )
+            ]
+        )
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_update)
+            .next_update(next_update)
+            .add_extension(freshest, False)
+        )
+
+        crl = builder.sign(private_key, hashes.SHA256(), backend)
+        assert len(crl) == 0
+        assert len(crl.extensions) == 1
+        ext1 = crl.extensions.get_extension_for_class(x509.FreshestCRL)
+        assert ext1.critical is False
+        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"
+
+    @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)
         next_update = datetime.datetime(2030, 1, 1, 12, 1)
-        builder = x509.CertificateRevocationListBuilder().issuer_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
-            ])
-        ).last_update(
-            last_update
-        ).next_update(
-            next_update
-        ).add_extension(
-            x509.OCSPNoCheck(), False
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_update)
+            .next_update(next_update)
+            .add_extension(x509.OCSPNoCheck(), False)
         )
         with pytest.raises(NotImplementedError):
             builder.sign(private_key, hashes.SHA256(), backend)
@@ -314,14 +401,19 @@
         private_key = RSA_KEY_512.private_key(backend)
         last_update = datetime.datetime(2002, 1, 1, 12, 1)
         next_update = datetime.datetime(2030, 1, 1, 12, 1)
-        builder = x509.CertificateRevocationListBuilder().issuer_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
-            ])
-        ).last_update(
-            last_update
-        ).next_update(
-            next_update
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_update)
+            .next_update(next_update)
         )
 
         with pytest.raises(ValueError):
@@ -333,19 +425,82 @@
         private_key = RSA_KEY_2048.private_key(backend)
         last_update = datetime.datetime(2002, 1, 1, 12, 1)
         next_update = datetime.datetime(2030, 1, 1, 12, 1)
-        builder = x509.CertificateRevocationListBuilder().issuer_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
-            ])
-        ).last_update(
-            last_update
-        ).next_update(
-            next_update
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_update)
+            .next_update(next_update)
         )
 
         with pytest.raises(TypeError):
             builder.sign(private_key, object(), backend)
 
+    @pytest.mark.supported(
+        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)
+        next_update = datetime.datetime(2030, 1, 1, 12, 1)
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_update)
+            .next_update(next_update)
+        )
+
+        with pytest.raises(ValueError):
+            builder.sign(private_key, object(), backend)
+        with pytest.raises(ValueError):
+            builder.sign(private_key, hashes.SHA256(), backend)
+
+    @pytest.mark.supported(
+        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)
+        next_update = datetime.datetime(2030, 1, 1, 12, 1)
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_update)
+            .next_update(next_update)
+        )
+
+        with pytest.raises(ValueError):
+            builder.sign(private_key, object(), 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):
@@ -353,36 +508,42 @@
         invalidity_date = x509.InvalidityDate(
             datetime.datetime(2002, 1, 1, 0, 0)
         )
-        ian = x509.IssuerAlternativeName([
-            x509.UniformResourceIdentifier(u"https://cryptography.io"),
-        ])
-        revoked_cert0 = x509.RevokedCertificateBuilder().serial_number(
-            2
-        ).revocation_date(
-            datetime.datetime(2012, 1, 1, 1, 1)
-        ).add_extension(
-            invalidity_date, False
-        ).build(backend)
+        ian = x509.IssuerAlternativeName(
+            [x509.UniformResourceIdentifier(u"https://cryptography.io")]
+        )
+        revoked_cert0 = (
+            x509.RevokedCertificateBuilder()
+            .serial_number(2)
+            .revocation_date(datetime.datetime(2012, 1, 1, 1, 1))
+            .add_extension(invalidity_date, False)
+            .build(backend)
+        )
         last_update = datetime.datetime(2002, 1, 1, 12, 1)
         next_update = datetime.datetime(2030, 1, 1, 12, 1)
-        builder = x509.CertificateRevocationListBuilder().issuer_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
-            ])
-        ).last_update(
-            last_update
-        ).next_update(
-            next_update
-        ).add_revoked_certificate(
-            revoked_cert0
-        ).add_extension(
-            ian, False
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_update)
+            .next_update(next_update)
+            .add_revoked_certificate(revoked_cert0)
+            .add_extension(ian, False)
         )
 
         crl = builder.sign(private_key, hashes.SHA256(), backend)
-        assert crl.extensions.get_extension_for_class(
-            x509.IssuerAlternativeName
-        ).value == ian
+        assert (
+            crl.extensions.get_extension_for_class(
+                x509.IssuerAlternativeName
+            ).value
+            == ian
+        )
         assert crl[0].serial_number == revoked_cert0.serial_number
         assert crl[0].revocation_date == revoked_cert0.revocation_date
         assert len(crl[0].extensions) == 1
@@ -398,36 +559,152 @@
         invalidity_date = x509.InvalidityDate(
             datetime.datetime(2002, 1, 1, 0, 0)
         )
-        ian = x509.IssuerAlternativeName([
-            x509.UniformResourceIdentifier(u"https://cryptography.io"),
-        ])
-        revoked_cert0 = x509.RevokedCertificateBuilder().serial_number(
-            2
-        ).revocation_date(
-            datetime.datetime(2012, 1, 1, 1, 1)
-        ).add_extension(
-            invalidity_date, False
-        ).build(backend)
+        ian = x509.IssuerAlternativeName(
+            [x509.UniformResourceIdentifier(u"https://cryptography.io")]
+        )
+        revoked_cert0 = (
+            x509.RevokedCertificateBuilder()
+            .serial_number(2)
+            .revocation_date(datetime.datetime(2012, 1, 1, 1, 1))
+            .add_extension(invalidity_date, False)
+            .build(backend)
+        )
         last_update = datetime.datetime(2002, 1, 1, 12, 1)
         next_update = datetime.datetime(2030, 1, 1, 12, 1)
-        builder = x509.CertificateRevocationListBuilder().issuer_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
-            ])
-        ).last_update(
-            last_update
-        ).next_update(
-            next_update
-        ).add_revoked_certificate(
-            revoked_cert0
-        ).add_extension(
-            ian, False
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_update)
+            .next_update(next_update)
+            .add_revoked_certificate(revoked_cert0)
+            .add_extension(ian, False)
         )
 
         crl = builder.sign(private_key, hashes.SHA256(), backend)
-        assert crl.extensions.get_extension_for_class(
-            x509.IssuerAlternativeName
-        ).value == ian
+        assert (
+            crl.extensions.get_extension_for_class(
+                x509.IssuerAlternativeName
+            ).value
+            == ian
+        )
+        assert crl[0].serial_number == revoked_cert0.serial_number
+        assert crl[0].revocation_date == revoked_cert0.revocation_date
+        assert len(crl[0].extensions) == 1
+        ext = crl[0].extensions.get_extension_for_class(x509.InvalidityDate)
+        assert ext.critical is False
+        assert ext.value == invalidity_date
+
+    @pytest.mark.supported(
+        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(
+            datetime.datetime(2002, 1, 1, 0, 0)
+        )
+        ian = x509.IssuerAlternativeName(
+            [x509.UniformResourceIdentifier(u"https://cryptography.io")]
+        )
+        revoked_cert0 = (
+            x509.RevokedCertificateBuilder()
+            .serial_number(2)
+            .revocation_date(datetime.datetime(2012, 1, 1, 1, 1))
+            .add_extension(invalidity_date, False)
+            .build(backend)
+        )
+        last_update = datetime.datetime(2002, 1, 1, 12, 1)
+        next_update = datetime.datetime(2030, 1, 1, 12, 1)
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_update)
+            .next_update(next_update)
+            .add_revoked_certificate(revoked_cert0)
+            .add_extension(ian, False)
+        )
+
+        crl = builder.sign(private_key, None, backend)
+        assert crl.signature_hash_algorithm is None
+        assert crl.signature_algorithm_oid == SignatureAlgorithmOID.ED25519
+        assert (
+            crl.extensions.get_extension_for_class(
+                x509.IssuerAlternativeName
+            ).value
+            == ian
+        )
+        assert crl[0].serial_number == revoked_cert0.serial_number
+        assert crl[0].revocation_date == revoked_cert0.revocation_date
+        assert len(crl[0].extensions) == 1
+        ext = crl[0].extensions.get_extension_for_class(x509.InvalidityDate)
+        assert ext.critical is False
+        assert ext.value == invalidity_date
+
+    @pytest.mark.supported(
+        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(
+            datetime.datetime(2002, 1, 1, 0, 0)
+        )
+        ian = x509.IssuerAlternativeName(
+            [x509.UniformResourceIdentifier(u"https://cryptography.io")]
+        )
+        revoked_cert0 = (
+            x509.RevokedCertificateBuilder()
+            .serial_number(2)
+            .revocation_date(datetime.datetime(2012, 1, 1, 1, 1))
+            .add_extension(invalidity_date, False)
+            .build(backend)
+        )
+        last_update = datetime.datetime(2002, 1, 1, 12, 1)
+        next_update = datetime.datetime(2030, 1, 1, 12, 1)
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_update)
+            .next_update(next_update)
+            .add_revoked_certificate(revoked_cert0)
+            .add_extension(ian, False)
+        )
+
+        crl = builder.sign(private_key, None, backend)
+        assert crl.signature_hash_algorithm is None
+        assert crl.signature_algorithm_oid == SignatureAlgorithmOID.ED448
+        assert (
+            crl.extensions.get_extension_for_class(
+                x509.IssuerAlternativeName
+            ).value
+            == ian
+        )
         assert crl[0].serial_number == revoked_cert0.serial_number
         assert crl[0].revocation_date == revoked_cert0.revocation_date
         assert len(crl[0].extensions) == 1
@@ -441,11 +718,20 @@
         private_key = DSA_KEY_2048.private_key(backend)
         last_time = datetime.datetime(2012, 1, 16, 22, 43)
         next_time = datetime.datetime(2022, 1, 17, 6, 43)
-        builder = x509.CertificateRevocationListBuilder().issuer_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
-            ])
-        ).last_update(last_time).next_update(next_time)
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_time)
+            .next_update(next_time)
+        )
 
         with pytest.raises(ValueError):
             builder.sign(private_key, hashes.MD5(), backend)
@@ -457,11 +743,20 @@
         private_key = EC_KEY_SECP256R1.private_key(backend)
         last_time = datetime.datetime(2012, 1, 16, 22, 43)
         next_time = datetime.datetime(2022, 1, 17, 6, 43)
-        builder = x509.CertificateRevocationListBuilder().issuer_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
-            ])
-        ).last_update(last_time).next_update(next_time)
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_time)
+            .next_update(next_time)
+        )
 
         with pytest.raises(ValueError):
             builder.sign(private_key, hashes.MD5(), backend)
@@ -475,30 +770,34 @@
         invalidity_date = x509.InvalidityDate(
             datetime.datetime(2002, 1, 1, 0, 0)
         )
-        revoked_cert0 = x509.RevokedCertificateBuilder().serial_number(
-            38
-        ).revocation_date(
-            datetime.datetime(2011, 1, 1, 1, 1)
-        ).build(backend)
-        revoked_cert1 = x509.RevokedCertificateBuilder().serial_number(
-            2
-        ).revocation_date(
-            datetime.datetime(2012, 1, 1, 1, 1)
-        ).add_extension(
-            invalidity_date, False
-        ).build(backend)
-        builder = x509.CertificateRevocationListBuilder().issuer_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
-            ])
-        ).last_update(
-            last_update
-        ).next_update(
-            next_update
-        ).add_revoked_certificate(
-            revoked_cert0
-        ).add_revoked_certificate(
-            revoked_cert1
+        revoked_cert0 = (
+            x509.RevokedCertificateBuilder()
+            .serial_number(38)
+            .revocation_date(datetime.datetime(2011, 1, 1, 1, 1))
+            .build(backend)
+        )
+        revoked_cert1 = (
+            x509.RevokedCertificateBuilder()
+            .serial_number(2)
+            .revocation_date(datetime.datetime(2012, 1, 1, 1, 1))
+            .add_extension(invalidity_date, False)
+            .build(backend)
+        )
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_update)
+            .next_update(next_update)
+            .add_revoked_certificate(revoked_cert0)
+            .add_revoked_certificate(revoked_cert1)
         )
 
         crl = builder.sign(private_key, hashes.SHA256(), backend)
diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py
index 6de105f..8e2b402 100644
--- a/tests/x509/test_x509_ext.py
+++ b/tests/x509/test_x509_ext.py
@@ -9,53 +9,52 @@
 import ipaddress
 import os
 
+import pretend
+
 import pytest
 
 import six
 
-from cryptography import utils, x509
+from cryptography import x509
 from cryptography.hazmat.backends.interfaces import (
-    DSABackend, EllipticCurveBackend, RSABackend, X509Backend
+    DSABackend,
+    EllipticCurveBackend,
+    RSABackend,
+    X509Backend,
 )
 from cryptography.hazmat.primitives import hashes
 from cryptography.hazmat.primitives.asymmetric import ec
 from cryptography.x509 import DNSName, NameConstraints, SubjectAlternativeName
-from cryptography.x509.general_name import _lazy_import_idna
+from cryptography.x509.extensions import _key_identifier_from_public_key
 from cryptography.x509.oid import (
-    AuthorityInformationAccessOID, ExtendedKeyUsageOID, ExtensionOID,
-    NameOID, ObjectIdentifier
+    AuthorityInformationAccessOID,
+    ExtendedKeyUsageOID,
+    ExtensionOID,
+    NameOID,
+    ObjectIdentifier,
+    SubjectInformationAccessOID,
+    _OID_NAMES,
 )
 
 from .test_x509 import _load_cert
 from ..hazmat.primitives.fixtures_rsa import RSA_KEY_2048
 from ..hazmat.primitives.test_ec import _skip_curve_unsupported
+from ..utils import load_vectors_from_file
 
 
 def _make_certbuilder(private_key):
-    name = x509.Name(
-        [x509.NameAttribute(NameOID.COMMON_NAME, u'example.org')])
+    name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"example.org")])
     return (
         x509.CertificateBuilder()
-            .subject_name(name)
-            .issuer_name(name)
-            .public_key(private_key.public_key())
-            .serial_number(777)
-            .not_valid_before(datetime.datetime(1999, 1, 1))
-            .not_valid_after(datetime.datetime(2020, 1, 1))
+        .subject_name(name)
+        .issuer_name(name)
+        .public_key(private_key.public_key())
+        .serial_number(777)
+        .not_valid_before(datetime.datetime(1999, 1, 1))
+        .not_valid_after(datetime.datetime(2020, 1, 1))
     )
 
 
-def test_lazy_idna_import():
-    try:
-        __import__("idna")
-        pytest.skip("idna is installed")
-    except ImportError:
-        pass
-
-    with pytest.raises(ImportError):
-        _lazy_import_idna()
-
-
 class TestExtension(object):
     def test_not_an_oid(self):
         bc = x509.BasicConstraints(ca=False, path_length=None)
@@ -77,26 +76,16 @@
         )
 
     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, "value")
+        ext2 = x509.Extension(x509.ObjectIdentifier("1.2.3.4"), False, "value")
         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, "value")
+        ext2 = x509.Extension(x509.ObjectIdentifier("1.2.3.5"), False, "value")
+        ext3 = x509.Extension(x509.ObjectIdentifier("1.2.3.4"), True, "value")
         ext4 = x509.Extension(
-            x509.ObjectIdentifier('1.2.3.4'), False, 'value4'
+            x509.ObjectIdentifier("1.2.3.4"), False, "value4"
         )
         assert ext1 != ext2
         assert ext1 != ext3
@@ -107,17 +96,17 @@
         ext1 = x509.Extension(
             ExtensionOID.BASIC_CONSTRAINTS,
             False,
-            x509.BasicConstraints(ca=False, path_length=None)
+            x509.BasicConstraints(ca=False, path_length=None),
         )
         ext2 = x509.Extension(
             ExtensionOID.BASIC_CONSTRAINTS,
             False,
-            x509.BasicConstraints(ca=False, path_length=None)
+            x509.BasicConstraints(ca=False, path_length=None),
         )
         ext3 = x509.Extension(
             ExtensionOID.BASIC_CONSTRAINTS,
             False,
-            x509.BasicConstraints(ca=True, path_length=None)
+            x509.BasicConstraints(ca=True, path_length=None),
         )
         assert hash(ext1) == hash(ext2)
         assert hash(ext1) != hash(ext3)
@@ -146,10 +135,12 @@
     def test_ne(self):
         ext1 = x509.TLSFeature([x509.TLSFeatureType.status_request])
         ext2 = x509.TLSFeature([x509.TLSFeatureType.status_request_v2])
-        ext3 = x509.TLSFeature([
-            x509.TLSFeatureType.status_request,
-            x509.TLSFeatureType.status_request_v2
-        ])
+        ext3 = x509.TLSFeature(
+            [
+                x509.TLSFeatureType.status_request,
+                x509.TLSFeatureType.status_request_v2,
+            ]
+        )
         assert ext1 != ext2
         assert ext1 != ext3
         assert ext1 != object()
@@ -157,10 +148,12 @@
     def test_hash(self):
         ext1 = x509.TLSFeature([x509.TLSFeatureType.status_request])
         ext2 = x509.TLSFeature([x509.TLSFeatureType.status_request])
-        ext3 = x509.TLSFeature([
-            x509.TLSFeatureType.status_request,
-            x509.TLSFeatureType.status_request_v2
-        ])
+        ext3 = x509.TLSFeature(
+            [
+                x509.TLSFeatureType.status_request,
+                x509.TLSFeatureType.status_request_v2,
+            ]
+        )
         assert hash(ext1) == hash(ext2)
         assert hash(ext1) != hash(ext3)
 
@@ -178,10 +171,12 @@
         assert list(ext2) == ext2_features
 
     def test_indexing(self):
-        ext = x509.TLSFeature([
-            x509.TLSFeatureType.status_request,
-            x509.TLSFeatureType.status_request_v2,
-        ])
+        ext = x509.TLSFeature(
+            [
+                x509.TLSFeatureType.status_request,
+                x509.TLSFeatureType.status_request_v2,
+            ]
+        )
         assert ext[-1] == ext[1]
         assert ext[0] == x509.TLSFeatureType.status_request
 
@@ -245,10 +240,9 @@
 
 class TestCertificateIssuer(object):
     def test_iter_names(self):
-        ci = x509.CertificateIssuer([
-            x509.DNSName(u"cryptography.io"),
-            x509.DNSName(u"crypto.local"),
-        ])
+        ci = x509.CertificateIssuer(
+            [x509.DNSName(u"cryptography.io"), x509.DNSName(u"crypto.local")]
+        )
         assert len(ci) == 2
         assert list(ci) == [
             x509.DNSName(u"cryptography.io"),
@@ -256,13 +250,15 @@
         ]
 
     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"),
-        ])
+        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"),
+            ]
+        )
         assert ci[-1] == ci[4]
         assert ci[2:6:2] == [ci[2], ci[4]]
 
@@ -291,9 +287,7 @@
             )
 
     def test_get_values_for_type(self):
-        ci = x509.CertificateIssuer(
-            [x509.DNSName(u"cryptography.io")]
-        )
+        ci = x509.CertificateIssuer([x509.DNSName(u"cryptography.io")])
         names = ci.get_values_for_type(x509.DNSName)
         assert names == [u"cryptography.io"]
 
@@ -333,9 +327,7 @@
 
     def test_repr(self):
         reason1 = x509.CRLReason(x509.ReasonFlags.unspecified)
-        assert repr(reason1) == (
-            "<CRLReason(reason=ReasonFlags.unspecified)>"
-        )
+        assert repr(reason1) == ("<CRLReason(reason=ReasonFlags.unspecified)>")
 
 
 class TestDeltaCRLIndicator(object):
@@ -356,9 +348,7 @@
 
     def test_repr(self):
         delta1 = x509.DeltaCRLIndicator(2)
-        assert repr(delta1) == (
-            "<DeltaCRLIndicator(crl_number=2)>"
-        )
+        assert repr(delta1) == ("<DeltaCRLIndicator(crl_number=2)>")
 
     def test_hash(self):
         delta1 = x509.DeltaCRLIndicator(1)
@@ -541,11 +531,11 @@
     def test_eq(self):
         pi = x509.PolicyInformation(
             x509.ObjectIdentifier("1.2.3"),
-            [u"string", x509.UserNotice(None, u"hi")]
+            [u"string", x509.UserNotice(None, u"hi")],
         )
         pi2 = x509.PolicyInformation(
             x509.ObjectIdentifier("1.2.3"),
-            [u"string", x509.UserNotice(None, u"hi")]
+            [u"string", x509.UserNotice(None, u"hi")],
         )
         assert pi == pi2
 
@@ -566,11 +556,11 @@
     def test_hash(self):
         pi = x509.PolicyInformation(
             x509.ObjectIdentifier("1.2.3"),
-            [u"string", x509.UserNotice(None, u"hi")]
+            [u"string", x509.UserNotice(None, u"hi")],
         )
         pi2 = x509.PolicyInformation(
             x509.ObjectIdentifier("1.2.3"),
-            [u"string", x509.UserNotice(None, u"hi")]
+            [u"string", x509.UserNotice(None, u"hi")],
         )
         pi3 = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), None)
         assert hash(pi) == hash(pi2)
@@ -658,10 +648,9 @@
         cert = _load_cert(
             os.path.join("x509", "bigoid.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
-        ext = cert.extensions.get_extension_for_class(
-            x509.CertificatePolicies)
+        ext = cert.extensions.get_extension_for_class(x509.CertificatePolicies)
 
         oid = x509.ObjectIdentifier(
             "1.3.6.1.4.1.311.21.8.8950086.10656446.2706058"
@@ -694,19 +683,21 @@
         cert = _load_cert(
             os.path.join("x509", "custom", "cp_cps_uri.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
 
         cp = cert.extensions.get_extension_for_oid(
             ExtensionOID.CERTIFICATE_POLICIES
         ).value
 
-        assert cp == x509.CertificatePolicies([
-            x509.PolicyInformation(
-                x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
-                [u"http://other.com/cps"]
-            )
-        ])
+        assert cp == x509.CertificatePolicies(
+            [
+                x509.PolicyInformation(
+                    x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+                    [u"http://other.com/cps"],
+                )
+            ]
+        )
 
     def test_user_notice_with_notice_reference(self, backend):
         cert = _load_cert(
@@ -714,26 +705,28 @@
                 "x509", "custom", "cp_user_notice_with_notice_reference.pem"
             ),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
 
         cp = cert.extensions.get_extension_for_oid(
             ExtensionOID.CERTIFICATE_POLICIES
         ).value
 
-        assert cp == x509.CertificatePolicies([
-            x509.PolicyInformation(
-                x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
-                [
-                    u"http://example.com/cps",
-                    u"http://other.com/cps",
-                    x509.UserNotice(
-                        x509.NoticeReference(u"my org", [1, 2, 3, 4]),
-                        u"thing"
-                    )
-                ]
-            )
-        ])
+        assert cp == x509.CertificatePolicies(
+            [
+                x509.PolicyInformation(
+                    x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+                    [
+                        u"http://example.com/cps",
+                        u"http://other.com/cps",
+                        x509.UserNotice(
+                            x509.NoticeReference(u"my org", [1, 2, 3, 4]),
+                            u"thing",
+                        ),
+                    ],
+                )
+            ]
+        )
 
     def test_user_notice_with_explicit_text(self, backend):
         cert = _load_cert(
@@ -741,19 +734,21 @@
                 "x509", "custom", "cp_user_notice_with_explicit_text.pem"
             ),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
 
         cp = cert.extensions.get_extension_for_oid(
             ExtensionOID.CERTIFICATE_POLICIES
         ).value
 
-        assert cp == x509.CertificatePolicies([
-            x509.PolicyInformation(
-                x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
-                [x509.UserNotice(None, u"thing")]
-            )
-        ])
+        assert cp == x509.CertificatePolicies(
+            [
+                x509.PolicyInformation(
+                    x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+                    [x509.UserNotice(None, u"thing")],
+                )
+            ]
+        )
 
     def test_user_notice_no_explicit_text(self, backend):
         cert = _load_cert(
@@ -761,24 +756,25 @@
                 "x509", "custom", "cp_user_notice_no_explicit_text.pem"
             ),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
 
         cp = cert.extensions.get_extension_for_oid(
             ExtensionOID.CERTIFICATE_POLICIES
         ).value
 
-        assert cp == x509.CertificatePolicies([
-            x509.PolicyInformation(
-                x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
-                [
-                    x509.UserNotice(
-                        x509.NoticeReference(u"my org", [1, 2, 3, 4]),
-                        None
-                    )
-                ]
-            )
-        ])
+        assert cp == x509.CertificatePolicies(
+            [
+                x509.PolicyInformation(
+                    x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+                    [
+                        x509.UserNotice(
+                            x509.NoticeReference(u"my org", [1, 2, 3, 4]), None
+                        )
+                    ],
+                )
+            ]
+        )
 
 
 class TestKeyUsage(object):
@@ -793,7 +789,7 @@
                 key_cert_sign=False,
                 crl_sign=False,
                 encipher_only=True,
-                decipher_only=False
+                decipher_only=False,
             )
 
         with pytest.raises(ValueError):
@@ -806,7 +802,7 @@
                 key_cert_sign=False,
                 crl_sign=False,
                 encipher_only=True,
-                decipher_only=True
+                decipher_only=True,
             )
 
         with pytest.raises(ValueError):
@@ -819,7 +815,7 @@
                 key_cert_sign=False,
                 crl_sign=False,
                 encipher_only=False,
-                decipher_only=True
+                decipher_only=True,
             )
 
     def test_properties_key_agreement_true(self):
@@ -832,7 +828,7 @@
             key_cert_sign=True,
             crl_sign=False,
             encipher_only=False,
-            decipher_only=False
+            decipher_only=False,
         )
         assert ku.digital_signature is True
         assert ku.content_commitment is True
@@ -852,7 +848,7 @@
             key_cert_sign=False,
             crl_sign=False,
             encipher_only=False,
-            decipher_only=True
+            decipher_only=True,
         )
         assert ku.key_agreement is True
         assert ku.encipher_only is False
@@ -868,7 +864,7 @@
             key_cert_sign=False,
             crl_sign=False,
             encipher_only=False,
-            decipher_only=False
+            decipher_only=False,
         )
         assert ku.key_agreement is False
         with pytest.raises(ValueError):
@@ -887,13 +883,13 @@
             key_cert_sign=True,
             crl_sign=False,
             encipher_only=False,
-            decipher_only=False
+            decipher_only=False,
         )
         assert repr(ku) == (
             "<KeyUsage(digital_signature=True, content_commitment=True, key_en"
             "cipherment=False, data_encipherment=False, key_agreement=False, k"
-            "ey_cert_sign=True, crl_sign=False, encipher_only=None, decipher_o"
-            "nly=None)>"
+            "ey_cert_sign=True, crl_sign=False, encipher_only=False, decipher_"
+            "only=False)>"
         )
 
     def test_repr_key_agreement_true(self):
@@ -906,7 +902,7 @@
             key_cert_sign=True,
             crl_sign=False,
             encipher_only=False,
-            decipher_only=False
+            decipher_only=False,
         )
         assert repr(ku) == (
             "<KeyUsage(digital_signature=True, content_commitment=True, key_en"
@@ -925,7 +921,7 @@
             key_cert_sign=False,
             crl_sign=False,
             encipher_only=False,
-            decipher_only=True
+            decipher_only=True,
         )
         ku2 = x509.KeyUsage(
             digital_signature=False,
@@ -936,7 +932,7 @@
             key_cert_sign=False,
             crl_sign=False,
             encipher_only=False,
-            decipher_only=True
+            decipher_only=True,
         )
         assert ku == ku2
 
@@ -950,7 +946,7 @@
             key_cert_sign=False,
             crl_sign=False,
             encipher_only=False,
-            decipher_only=True
+            decipher_only=True,
         )
         ku2 = x509.KeyUsage(
             digital_signature=False,
@@ -961,7 +957,7 @@
             key_cert_sign=False,
             crl_sign=False,
             encipher_only=False,
-            decipher_only=False
+            decipher_only=False,
         )
         assert ku != ku2
         assert ku != object()
@@ -976,7 +972,7 @@
             key_cert_sign=False,
             crl_sign=False,
             encipher_only=False,
-            decipher_only=True
+            decipher_only=True,
         )
         ku2 = x509.KeyUsage(
             digital_signature=False,
@@ -987,7 +983,7 @@
             key_cert_sign=False,
             crl_sign=False,
             encipher_only=False,
-            decipher_only=True
+            decipher_only=True,
         )
         ku3 = x509.KeyUsage(
             digital_signature=False,
@@ -998,7 +994,7 @@
             key_cert_sign=False,
             crl_sign=False,
             encipher_only=False,
-            decipher_only=False
+            decipher_only=False,
         )
         assert hash(ku) == hash(ku2)
         assert hash(ku) != hash(ku3)
@@ -1019,15 +1015,15 @@
             assert repr(ext) == (
                 "<Extension(oid=<ObjectIdentifier(oid=2.5.29.14, name=subjectK"
                 "eyIdentifier)>, critical=False, value=<SubjectKeyIdentifier(d"
-                "igest=b\'\\t#\\x84\\x93\"0I\\x8b\\xc9\\x80\\xaa\\x80\\x98Eoo"
-                "\\xf7\\xff:\\xc9\')>)>"
+                "igest=b'\\t#\\x84\\x93\"0I\\x8b\\xc9\\x80\\xaa\\x80\\x98Eoo"
+                "\\xf7\\xff:\\xc9')>)>"
             )
         else:
             assert repr(ext) == (
                 "<Extension(oid=<ObjectIdentifier(oid=2.5.29.14, name=subjectK"
                 "eyIdentifier)>, critical=False, value=<SubjectKeyIdentifier(d"
-                "igest=\'\\t#\\x84\\x93\"0I\\x8b\\xc9\\x80\\xaa\\x80\\x98Eoo"
-                "\\xf7\\xff:\\xc9\')>)>"
+                "igest='\\t#\\x84\\x93\"0I\\x8b\\xc9\\x80\\xaa\\x80\\x98Eoo"
+                "\\xf7\\xff:\\xc9')>)>"
             )
 
     def test_eq(self):
@@ -1070,16 +1066,16 @@
 
     def test_authority_cert_serial_number_not_integer(self):
         dirname = x509.DirectoryName(
-            x509.Name([
-                x509.NameAttribute(
-                    x509.ObjectIdentifier('2.999.1'),
-                    u'value1'
-                ),
-                x509.NameAttribute(
-                    x509.ObjectIdentifier('2.999.2'),
-                    u'value2'
-                ),
-            ])
+            x509.Name(
+                [
+                    x509.NameAttribute(
+                        x509.ObjectIdentifier("2.999.1"), u"value1"
+                    ),
+                    x509.NameAttribute(
+                        x509.ObjectIdentifier("2.999.2"), u"value2"
+                    ),
+                ]
+            )
         )
         with pytest.raises(TypeError):
             x509.AuthorityKeyIdentifier(b"identifier", [dirname], "notanint")
@@ -1090,16 +1086,16 @@
 
     def test_authority_issuer_not_none_serial_none(self):
         dirname = x509.DirectoryName(
-            x509.Name([
-                x509.NameAttribute(
-                    x509.ObjectIdentifier('2.999.1'),
-                    u'value1'
-                ),
-                x509.NameAttribute(
-                    x509.ObjectIdentifier('2.999.2'),
-                    u'value2'
-                ),
-            ])
+            x509.Name(
+                [
+                    x509.NameAttribute(
+                        x509.ObjectIdentifier("2.999.1"), u"value1"
+                    ),
+                    x509.NameAttribute(
+                        x509.ObjectIdentifier("2.999.2"), u"value2"
+                    ),
+                ]
+            )
         )
         with pytest.raises(ValueError):
             x509.AuthorityKeyIdentifier(b"identifier", [dirname], None)
@@ -1120,7 +1116,7 @@
     def test_iter_input(self):
         dirnames = [
             x509.DirectoryName(
-                x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'myCN')])
+                x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")])
             )
         ]
         aki = x509.AuthorityKeyIdentifier(b"digest", iter(dirnames), 1234)
@@ -1128,7 +1124,7 @@
 
     def test_repr(self):
         dirname = x509.DirectoryName(
-            x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'myCN')])
+            x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")])
         )
         aki = x509.AuthorityKeyIdentifier(b"digest", [dirname], 1234)
 
@@ -1147,21 +1143,21 @@
 
     def test_eq(self):
         dirname = x509.DirectoryName(
-            x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'myCN')])
+            x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")])
         )
         aki = x509.AuthorityKeyIdentifier(b"digest", [dirname], 1234)
         dirname2 = x509.DirectoryName(
-            x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'myCN')])
+            x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")])
         )
         aki2 = x509.AuthorityKeyIdentifier(b"digest", [dirname2], 1234)
         assert aki == aki2
 
     def test_ne(self):
         dirname = x509.DirectoryName(
-            x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'myCN')])
+            x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")])
         )
         dirname5 = x509.DirectoryName(
-            x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'aCN')])
+            x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"aCN")])
         )
         aki = x509.AuthorityKeyIdentifier(b"digest", [dirname], 1234)
         aki2 = x509.AuthorityKeyIdentifier(b"diges", [dirname], 1234)
@@ -1176,7 +1172,7 @@
 
     def test_hash(self):
         dirname = x509.DirectoryName(
-            x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'myCN')])
+            x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")])
         )
         aki1 = x509.AuthorityKeyIdentifier(b"digest", [dirname], 1234)
         aki2 = x509.AuthorityKeyIdentifier(b"digest", [dirname], 1234)
@@ -1207,9 +1203,7 @@
 
     def test_repr(self):
         na = x509.BasicConstraints(ca=True, path_length=None)
-        assert repr(na) == (
-            "<BasicConstraints(ca=True, path_length=None)>"
-        )
+        assert repr(na) == ("<BasicConstraints(ca=True, path_length=None)>")
 
     def test_hash(self):
         na = x509.BasicConstraints(ca=True, path_length=None)
@@ -1238,14 +1232,16 @@
             x509.ExtendedKeyUsage(["notoid"])
 
     def test_iter_len(self):
-        eku = x509.ExtendedKeyUsage([
-            x509.ObjectIdentifier("1.3.6.1.5.5.7.3.1"),
-            x509.ObjectIdentifier("1.3.6.1.5.5.7.3.2"),
-        ])
+        eku = x509.ExtendedKeyUsage(
+            [
+                x509.ObjectIdentifier("1.3.6.1.5.5.7.3.1"),
+                x509.ObjectIdentifier("1.3.6.1.5.5.7.3.2"),
+            ]
+        )
         assert len(eku) == 2
         assert list(eku) == [
             ExtendedKeyUsageOID.SERVER_AUTH,
-            ExtendedKeyUsageOID.CLIENT_AUTH
+            ExtendedKeyUsageOID.CLIENT_AUTH,
         ]
 
     def test_iter_input(self):
@@ -1257,10 +1253,12 @@
         assert list(aia) == usages
 
     def test_repr(self):
-        eku = x509.ExtendedKeyUsage([
-            x509.ObjectIdentifier("1.3.6.1.5.5.7.3.1"),
-            x509.ObjectIdentifier("1.3.6.1.5.5.7.3.2"),
-        ])
+        eku = x509.ExtendedKeyUsage(
+            [
+                x509.ObjectIdentifier("1.3.6.1.5.5.7.3.1"),
+                x509.ObjectIdentifier("1.3.6.1.5.5.7.3.2"),
+            ]
+        )
         assert repr(eku) == (
             "<ExtendedKeyUsage([<ObjectIdentifier(oid=1.3.6.1.5.5.7.3.1, name="
             "serverAuth)>, <ObjectIdentifier(oid=1.3.6.1.5.5.7.3.2, name=clien"
@@ -1268,12 +1266,12 @@
         )
 
     def test_eq(self):
-        eku = x509.ExtendedKeyUsage([
-            x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")
-        ])
-        eku2 = x509.ExtendedKeyUsage([
-            x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")
-        ])
+        eku = x509.ExtendedKeyUsage(
+            [x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")]
+        )
+        eku2 = x509.ExtendedKeyUsage(
+            [x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")]
+        )
         assert eku == eku2
 
     def test_ne(self):
@@ -1283,12 +1281,12 @@
         assert eku != object()
 
     def test_hash(self):
-        eku = x509.ExtendedKeyUsage([
-            x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")
-        ])
-        eku2 = x509.ExtendedKeyUsage([
-            x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")
-        ])
+        eku = x509.ExtendedKeyUsage(
+            [x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")]
+        )
+        eku2 = x509.ExtendedKeyUsage(
+            [x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")]
+        )
         eku3 = x509.ExtendedKeyUsage([x509.ObjectIdentifier("1.3.6")])
         assert hash(eku) == hash(eku2)
         assert hash(eku) != hash(eku3)
@@ -1301,7 +1299,7 @@
         cert = _load_cert(
             os.path.join("x509", "verisign_md2_root.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions
         assert len(ext) == 0
@@ -1317,7 +1315,7 @@
                 "x509", "custom", "basic_constraints_not_critical.pem"
             ),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         extensions = cert.extensions
         ext = extensions.get_extension_for_oid(ExtensionOID.BASIC_CONSTRAINTS)
@@ -1326,11 +1324,9 @@
 
     def test_duplicate_extension(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "two_basic_constraints.pem"
-            ),
+            os.path.join("x509", "custom", "two_basic_constraints.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         with pytest.raises(x509.DuplicateExtension) as exc:
             cert.extensions
@@ -1343,7 +1339,7 @@
                 "x509", "custom", "unsupported_extension_critical.pem"
             ),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             x509.ObjectIdentifier("1.2.3.4")
@@ -1353,11 +1349,9 @@
     @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"
-            ),
+            os.path.join("x509", "custom", "unsupported_extension_2.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         extensions = cert.extensions
         assert len(extensions) == 2
@@ -1367,24 +1361,21 @@
         )
         assert extensions[0].value == x509.UnrecognizedExtension(
             x509.ObjectIdentifier("1.3.6.1.4.1.41482.2"),
-            b"1.3.6.1.4.1.41482.1.2"
+            b"1.3.6.1.4.1.41482.1.2",
         )
         assert extensions[1].critical is False
         assert extensions[1].oid == x509.ObjectIdentifier(
             "1.3.6.1.4.1.45724.2.1.1"
         )
         assert extensions[1].value == x509.UnrecognizedExtension(
-            x509.ObjectIdentifier("1.3.6.1.4.1.45724.2.1.1"),
-            b"\x03\x02\x040"
+            x509.ObjectIdentifier("1.3.6.1.4.1.45724.2.1.1"), b"\x03\x02\x040"
         )
 
     def test_no_extensions_get_for_class(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "cryptography.io.pem"
-            ),
+            os.path.join("x509", "cryptography.io.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         exts = cert.extensions
         with pytest.raises(x509.ExtensionNotFound) as exc:
@@ -1400,7 +1391,7 @@
         cert = _load_cert(
             os.path.join("x509", "cryptography.io.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         exts = cert.extensions
         assert exts[-1] == exts[7]
@@ -1412,7 +1403,7 @@
                 "x509", "custom", "basic_constraints_not_critical.pem"
             ),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_class(x509.BasicConstraints)
         assert ext is not None
@@ -1424,7 +1415,7 @@
                 "x509", "custom", "basic_constraints_not_critical.pem"
             ),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         assert repr(cert.extensions) == (
             "<Extensions([<Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name"
@@ -1442,7 +1433,7 @@
                 "x509", "PKITS_data", "certs", "pathLenConstraint6CACert.crt"
             ),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.BASIC_CONSTRAINTS
@@ -1456,7 +1447,7 @@
         cert = _load_cert(
             os.path.join("x509", "custom", "bc_path_length_zero.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.BASIC_CONSTRAINTS
@@ -1470,7 +1461,7 @@
         cert = _load_cert(
             os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.BASIC_CONSTRAINTS
@@ -1484,7 +1475,7 @@
         cert = _load_cert(
             os.path.join("x509", "cryptography.io.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.BASIC_CONSTRAINTS
@@ -1500,10 +1491,10 @@
                 "x509",
                 "PKITS_data",
                 "certs",
-                "ValidCertificatePathTest1EE.crt"
+                "ValidCertificatePathTest1EE.crt",
             ),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
         with pytest.raises(x509.ExtensionNotFound):
             cert.extensions.get_extension_for_oid(
@@ -1516,7 +1507,7 @@
                 "x509", "custom", "basic_constraints_not_critical.pem"
             ),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.BASIC_CONSTRAINTS
@@ -1533,7 +1524,7 @@
         cert = _load_cert(
             os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.SUBJECT_KEY_IDENTIFIER
@@ -1551,7 +1542,7 @@
         cert = _load_cert(
             os.path.join("x509", "custom", "bc_path_length_zero.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         with pytest.raises(x509.ExtensionNotFound):
             cert.extensions.get_extension_for_oid(
@@ -1564,14 +1555,12 @@
         cert = _load_cert(
             os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.SUBJECT_KEY_IDENTIFIER
         )
-        ski = x509.SubjectKeyIdentifier.from_public_key(
-            cert.public_key()
-        )
+        ski = x509.SubjectKeyIdentifier.from_public_key(cert.public_key())
         assert ext.value == ski
 
     @pytest.mark.requires_backend_interface(interface=DSABackend)
@@ -1580,17 +1569,49 @@
         cert = _load_cert(
             os.path.join("x509", "custom", "dsa_selfsigned_ca.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
 
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.SUBJECT_KEY_IDENTIFIER
         )
-        ski = x509.SubjectKeyIdentifier.from_public_key(
-            cert.public_key()
-        )
+        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(
+                "asymmetric",
+                "DER_Serialization",
+                "dsa_public_key_invalid_bit_string.der",
+            ),
+            loader=lambda data: data.read(),
+            mode="rb",
+        )
+        pretend_key = pretend.stub(public_bytes=lambda x, y: data)
+        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(
+                "asymmetric",
+                "DER_Serialization",
+                "dsa_public_key_no_params.der",
+            ),
+            loader=lambda data: data.read(),
+            mode="rb",
+        )
+        pretend_key = pretend.stub(public_bytes=lambda x, y: data)
+        key_identifier = _key_identifier_from_public_key(pretend_key)
+        assert key_identifier == binascii.unhexlify(
+            b"24c0133a6a492f2c48a18c7648e515db5ac76749"
+        )
+
     @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
     @pytest.mark.requires_backend_interface(interface=X509Backend)
     def test_from_ec_public_key(self, backend):
@@ -1598,15 +1619,49 @@
         cert = _load_cert(
             os.path.join("x509", "ecdsa_root.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
 
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.SUBJECT_KEY_IDENTIFIER
         )
-        ski = x509.SubjectKeyIdentifier.from_public_key(
-            cert.public_key()
+        ski = x509.SubjectKeyIdentifier.from_public_key(cert.public_key())
+        assert ext.value == ski
+
+    @pytest.mark.supported(
+        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"),
+            x509.load_pem_x509_certificate,
+            backend,
         )
+
+        ext = cert.extensions.get_extension_for_oid(
+            ExtensionOID.SUBJECT_KEY_IDENTIFIER
+        )
+        ski = x509.SubjectKeyIdentifier.from_public_key(cert.public_key())
+        assert ext.value == ski
+
+    @pytest.mark.supported(
+        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"),
+            x509.load_pem_x509_certificate,
+            backend,
+        )
+
+        ext = cert.extensions.get_extension_for_oid(
+            ExtensionOID.SUBJECT_KEY_IDENTIFIER
+        )
+        ski = x509.SubjectKeyIdentifier.from_public_key(cert.public_key())
         assert ext.value == ski
 
 
@@ -1617,7 +1672,7 @@
         cert = _load_cert(
             os.path.join("x509", "verisign_md2_root.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions
         with pytest.raises(x509.ExtensionNotFound) as exc:
@@ -1627,11 +1682,9 @@
 
     def test_all_purposes(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "all_key_usages.pem"
-            ),
+            os.path.join("x509", "custom", "all_key_usages.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         extensions = cert.extensions
         ext = extensions.get_extension_for_oid(ExtensionOID.KEY_USAGE)
@@ -1654,7 +1707,7 @@
                 "x509", "PKITS_data", "certs", "pathLenConstraint6CACert.crt"
             ),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(ExtensionOID.KEY_USAGE)
         assert ext is not None
@@ -1671,15 +1724,9 @@
 
 
 class TestDNSName(object):
-    def test_init_deprecated(self):
-        pytest.importorskip("idna")
-        with pytest.warns(utils.DeprecatedIn21):
-            name = x509.DNSName(u".\xf5\xe4\xf6\xfc.example.com")
-        assert name.value == u".xn--4ca7aey.example.com"
-
-        with pytest.warns(utils.DeprecatedIn21):
-            name = x509.DNSName(u"\xf5\xe4\xf6\xfc.example.com")
-        assert name.value == u"xn--4ca7aey.example.com"
+    def test_non_a_label(self):
+        with pytest.raises(ValueError):
+            x509.DNSName(u".\xf5\xe4\xf6\xfc.example.com")
 
     def test_init(self):
         name = x509.DNSName(u"*.xn--4ca7aey.example.com")
@@ -1715,40 +1762,40 @@
             x509.DirectoryName(1.3)
 
     def test_repr(self):
-        name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'value1')])
+        name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"value1")])
         gn = x509.DirectoryName(name)
         assert repr(gn) == "<DirectoryName(value=<Name(CN=value1)>)>"
 
     def test_eq(self):
-        name = x509.Name([
-            x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1')
-        ])
-        name2 = x509.Name([
-            x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1')
-        ])
+        name = x509.Name(
+            [x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")]
+        )
+        name2 = x509.Name(
+            [x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")]
+        )
         gn = x509.DirectoryName(name)
         gn2 = x509.DirectoryName(name2)
         assert gn == gn2
 
     def test_ne(self):
-        name = x509.Name([
-            x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1')
-        ])
-        name2 = x509.Name([
-            x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2')
-        ])
+        name = x509.Name(
+            [x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")]
+        )
+        name2 = x509.Name(
+            [x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2")]
+        )
         gn = x509.DirectoryName(name)
         gn2 = x509.DirectoryName(name2)
         assert gn != gn2
         assert gn != object()
 
     def test_hash(self):
-        name = x509.Name([
-            x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1')
-        ])
-        name2 = x509.Name([
-            x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2')
-        ])
+        name = x509.Name(
+            [x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")]
+        )
+        name2 = x509.Name(
+            [x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2")]
+        )
         gn = x509.DirectoryName(name)
         gn2 = x509.DirectoryName(name)
         gn3 = x509.DirectoryName(name2)
@@ -1790,15 +1837,9 @@
         gn = x509.RFC822Name(u"administrator")
         assert gn.value == u"administrator"
 
-    def test_idna(self):
-        pytest.importorskip("idna")
-        with pytest.warns(utils.DeprecatedIn21):
-            gn = x509.RFC822Name(u"email@em\xe5\xefl.com")
-
-        assert gn.value == u"email@xn--eml-vla4c.com"
-
-        gn2 = x509.RFC822Name(u"email@xn--eml-vla4c.com")
-        assert gn2.value == u"email@xn--eml-vla4c.com"
+    def test_non_a_label(self):
+        with pytest.raises(ValueError):
+            x509.RFC822Name(u"email@em\xe5\xefl.com")
 
     def test_hash(self):
         g1 = x509.RFC822Name(u"email@host.com")
@@ -1830,41 +1871,16 @@
         gn = x509.UniformResourceIdentifier(u"singlelabel:443/test")
         assert gn.value == u"singlelabel:443/test"
 
-    def test_idna_no_port(self):
-        pytest.importorskip("idna")
-        with pytest.warns(utils.DeprecatedIn21):
-            gn = x509.UniformResourceIdentifier(
+    def test_non_a_label(self):
+        with pytest.raises(ValueError):
+            x509.UniformResourceIdentifier(
                 u"http://\u043f\u044b\u043a\u0430.cryptography"
             )
 
-        assert gn.value == u"http://xn--80ato2c.cryptography"
-
-    def test_idna_with_port(self):
-        pytest.importorskip("idna")
-        with pytest.warns(utils.DeprecatedIn21):
-            gn = x509.UniformResourceIdentifier(
-                u"gopher://\u043f\u044b\u043a\u0430.cryptography:70/some/path"
-            )
-
-        assert gn.value == (
-            u"gopher://xn--80ato2c.cryptography:70/some/path"
-        )
-
     def test_empty_hostname(self):
         gn = x509.UniformResourceIdentifier(u"ldap:///some-nonsense")
         assert gn.value == "ldap:///some-nonsense"
 
-    def test_query_and_fragment(self):
-        pytest.importorskip("idna")
-        with pytest.warns(utils.DeprecatedIn21):
-            gn = x509.UniformResourceIdentifier(
-                u"ldap://\u043f\u044b\u043a\u0430.cryptography:90/path?query="
-                u"true#somedata"
-            )
-        assert gn.value == (
-            u"ldap://xn--80ato2c.cryptography:90/path?query=true#somedata"
-        )
-
     def test_hash(self):
         g1 = x509.UniformResourceIdentifier(u"http://host.com")
         g2 = x509.UniformResourceIdentifier(u"http://host.com")
@@ -1876,13 +1892,9 @@
     def test_repr(self):
         gn = x509.UniformResourceIdentifier(u"string")
         if not six.PY2:
-            assert repr(gn) == (
-                "<UniformResourceIdentifier(value='string')>"
-            )
+            assert repr(gn) == ("<UniformResourceIdentifier(value='string')>")
         else:
-            assert repr(gn) == (
-                "<UniformResourceIdentifier(value=u'string')>"
-            )
+            assert repr(gn) == ("<UniformResourceIdentifier(value=u'string')>")
 
 
 class TestRegisteredID(object):
@@ -2017,17 +2029,14 @@
 
 class TestGeneralNames(object):
     def test_get_values_for_type(self):
-        gns = x509.GeneralNames(
-            [x509.DNSName(u"cryptography.io")]
-        )
+        gns = x509.GeneralNames([x509.DNSName(u"cryptography.io")])
         names = gns.get_values_for_type(x509.DNSName)
         assert names == [u"cryptography.io"]
 
     def test_iter_names(self):
-        gns = x509.GeneralNames([
-            x509.DNSName(u"cryptography.io"),
-            x509.DNSName(u"crypto.local"),
-        ])
+        gns = x509.GeneralNames(
+            [x509.DNSName(u"cryptography.io"), x509.DNSName(u"crypto.local")]
+        )
         assert len(gns) == 2
         assert list(gns) == [
             x509.DNSName(u"cryptography.io"),
@@ -2043,28 +2052,24 @@
         assert list(gns) == names
 
     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"),
-        ])
+        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"),
+            ]
+        )
         assert gn[-1] == gn[4]
         assert gn[2:6:2] == [gn[2], gn[4]]
 
     def test_invalid_general_names(self):
         with pytest.raises(TypeError):
-            x509.GeneralNames(
-                [x509.DNSName(u"cryptography.io"), "invalid"]
-            )
+            x509.GeneralNames([x509.DNSName(u"cryptography.io"), "invalid"])
 
     def test_repr(self):
-        gns = x509.GeneralNames(
-            [
-                x509.DNSName(u"cryptography.io")
-            ]
-        )
+        gns = x509.GeneralNames([x509.DNSName(u"cryptography.io")])
         if not six.PY2:
             assert repr(gns) == (
                 "<GeneralNames([<DNSName(value='cryptography.io')>])>"
@@ -2075,21 +2080,13 @@
             )
 
     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(u"cryptography.io")])
+        gns2 = x509.GeneralNames([x509.DNSName(u"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(u"cryptography.io")])
+        gns2 = x509.GeneralNames([x509.RFC822Name(u"admin@cryptography.io")])
         assert gns != gns2
         assert gns != object()
 
@@ -2103,17 +2100,14 @@
 
 class TestIssuerAlternativeName(object):
     def test_get_values_for_type(self):
-        san = x509.IssuerAlternativeName(
-            [x509.DNSName(u"cryptography.io")]
-        )
+        san = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")])
         names = san.get_values_for_type(x509.DNSName)
         assert names == [u"cryptography.io"]
 
     def test_iter_names(self):
-        san = x509.IssuerAlternativeName([
-            x509.DNSName(u"cryptography.io"),
-            x509.DNSName(u"crypto.local"),
-        ])
+        san = x509.IssuerAlternativeName(
+            [x509.DNSName(u"cryptography.io"), x509.DNSName(u"crypto.local")]
+        )
         assert len(san) == 2
         assert list(san) == [
             x509.DNSName(u"cryptography.io"),
@@ -2121,13 +2115,15 @@
         ]
 
     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"),
-        ])
+        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"),
+            ]
+        )
         assert ian[-1] == ian[4]
         assert ian[2:6:2] == [ian[2], ian[4]]
 
@@ -2138,11 +2134,7 @@
             )
 
     def test_repr(self):
-        san = x509.IssuerAlternativeName(
-            [
-                x509.DNSName(u"cryptography.io")
-            ]
-        )
+        san = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")])
         if not six.PY2:
             assert repr(san) == (
                 "<IssuerAlternativeName("
@@ -2155,18 +2147,12 @@
             )
 
     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(u"cryptography.io")])
+        san2 = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")])
         assert san == san2
 
     def test_ne(self):
-        san = x509.IssuerAlternativeName(
-            [x509.DNSName(u"cryptography.io")]
-        )
+        san = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")])
         san2 = x509.IssuerAlternativeName(
             [x509.RFC822Name(u"admin@cryptography.io")]
         )
@@ -2228,17 +2214,14 @@
 
 class TestSubjectAlternativeName(object):
     def test_get_values_for_type(self):
-        san = x509.SubjectAlternativeName(
-            [x509.DNSName(u"cryptography.io")]
-        )
+        san = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")])
         names = san.get_values_for_type(x509.DNSName)
         assert names == [u"cryptography.io"]
 
     def test_iter_names(self):
-        san = x509.SubjectAlternativeName([
-            x509.DNSName(u"cryptography.io"),
-            x509.DNSName(u"crypto.local"),
-        ])
+        san = x509.SubjectAlternativeName(
+            [x509.DNSName(u"cryptography.io"), x509.DNSName(u"crypto.local")]
+        )
         assert len(san) == 2
         assert list(san) == [
             x509.DNSName(u"cryptography.io"),
@@ -2246,13 +2229,15 @@
         ]
 
     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"),
-        ])
+        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"),
+            ]
+        )
         assert san[-1] == san[4]
         assert san[2:6:2] == [san[2], san[4]]
 
@@ -2263,11 +2248,7 @@
             )
 
     def test_repr(self):
-        san = x509.SubjectAlternativeName(
-            [
-                x509.DNSName(u"cryptography.io")
-            ]
-        )
+        san = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")])
         if not six.PY2:
             assert repr(san) == (
                 "<SubjectAlternativeName("
@@ -2280,18 +2261,12 @@
             )
 
     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(u"cryptography.io")])
+        san2 = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")])
         assert san == san2
 
     def test_ne(self):
-        san = x509.SubjectAlternativeName(
-            [x509.DNSName(u"cryptography.io")]
-        )
+        san = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")])
         san2 = x509.SubjectAlternativeName(
             [x509.RFC822Name(u"admin@cryptography.io")]
         )
@@ -2315,7 +2290,7 @@
         cert = _load_cert(
             os.path.join("x509", "cryptography.io.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.SUBJECT_ALTERNATIVE_NAME
@@ -2332,7 +2307,7 @@
         cert = _load_cert(
             os.path.join("x509", "wildcard_san.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.SUBJECT_ALTERNATIVE_NAME
@@ -2340,45 +2315,43 @@
 
         dns = ext.value.get_values_for_type(x509.DNSName)
         assert dns == [
-            u'*.langui.sh',
-            u'langui.sh',
-            u'*.saseliminator.com',
-            u'saseliminator.com'
+            u"*.langui.sh",
+            u"langui.sh",
+            u"*.saseliminator.com",
+            u"saseliminator.com",
         ]
 
     def test_san_empty_hostname(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "san_empty_hostname.pem"
-            ),
+            os.path.join("x509", "custom", "san_empty_hostname.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         san = cert.extensions.get_extension_for_oid(
             ExtensionOID.SUBJECT_ALTERNATIVE_NAME
         )
 
         dns = san.value.get_values_for_type(x509.DNSName)
-        assert dns == [u'']
+        assert dns == [u""]
 
     def test_san_wildcard_idna_dns_name(self, backend):
         cert = _load_cert(
             os.path.join("x509", "custom", "san_wildcard_idna.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.SUBJECT_ALTERNATIVE_NAME
         )
 
         dns = ext.value.get_values_for_type(x509.DNSName)
-        assert dns == [u'*.xn--80ato2c.cryptography']
+        assert dns == [u"*.xn--80ato2c.cryptography"]
 
     def test_unsupported_gn(self, backend):
         cert = _load_cert(
             os.path.join("x509", "san_x400address.der"),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
         with pytest.raises(x509.UnsupportedGeneralNameType) as exc:
             cert.extensions
@@ -2387,11 +2360,9 @@
 
     def test_registered_id(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "san_registered_id.pem"
-            ),
+            os.path.join("x509", "custom", "san_registered_id.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.SUBJECT_ALTERNATIVE_NAME
@@ -2405,32 +2376,25 @@
 
     def test_uri(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "san_uri_with_port.pem"
-            ),
+            os.path.join("x509", "custom", "san_uri_with_port.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.SUBJECT_ALTERNATIVE_NAME
         )
         assert ext is not None
-        uri = ext.value.get_values_for_type(
-            x509.UniformResourceIdentifier
-        )
+        uri = ext.value.get_values_for_type(x509.UniformResourceIdentifier)
         assert uri == [
-            u"gopher://xn--80ato2c.cryptography:70/path?q=s#hel"
-            u"lo",
+            u"gopher://xn--80ato2c.cryptography:70/path?q=s#hel" u"lo",
             u"http://someregulardomain.com",
         ]
 
     def test_ipaddress(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "san_ipaddr.pem"
-            ),
+            os.path.join("x509", "custom", "san_ipaddr.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.SUBJECT_ALTERNATIVE_NAME
@@ -2443,16 +2407,14 @@
         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(u"ff::"),
         ] == ip
 
     def test_dirname(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "san_dirname.pem"
-            ),
+            os.path.join("x509", "custom", "san_dirname.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.SUBJECT_ALTERNATIVE_NAME
@@ -2464,20 +2426,22 @@
 
         dirname = san.get_values_for_type(x509.DirectoryName)
         assert [
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u'test'),
-                x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'Org'),
-                x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
-            ])
+            x509.Name(
+                [
+                    x509.NameAttribute(NameOID.COMMON_NAME, u"test"),
+                    x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Org"),
+                    x509.NameAttribute(
+                        NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
+                    ),
+                ]
+            )
         ] == dirname
 
     def test_rfc822name(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "san_rfc822_idna.pem"
-            ),
+            os.path.join("x509", "custom", "san_rfc822_idna.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.SUBJECT_ALTERNATIVE_NAME
@@ -2492,11 +2456,9 @@
 
     def test_idna2003_invalid(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "san_idna2003_dnsname.pem"
-            ),
+            os.path.join("x509", "custom", "san_idna2003_dnsname.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         san = cert.extensions.get_extension_for_class(
             x509.SubjectAlternativeName
@@ -2508,11 +2470,9 @@
 
     def test_unicode_rfc822_name_dns_name_uri(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "san_idna_names.pem"
-            ),
+            os.path.join("x509", "custom", "san_idna_names.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.SUBJECT_ALTERNATIVE_NAME
@@ -2527,11 +2487,9 @@
 
     def test_rfc822name_dnsname_ipaddress_directoryname_uri(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "san_email_dns_ip_dirname_uri.pem"
-            ),
+            os.path.join("x509", "custom", "san_email_dns_ip_dirname_uri.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.SUBJECT_ALTERNATIVE_NAME
@@ -2550,42 +2508,43 @@
         assert [u"https://cryptography.io"] == uri
         assert [u"cryptography.io"] == dns
         assert [
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u'dirCN'),
-                x509.NameAttribute(
-                    NameOID.ORGANIZATION_NAME, u'Cryptographic Authority'
-                ),
-            ])
+            x509.Name(
+                [
+                    x509.NameAttribute(NameOID.COMMON_NAME, u"dirCN"),
+                    x509.NameAttribute(
+                        NameOID.ORGANIZATION_NAME, u"Cryptographic Authority"
+                    ),
+                ]
+            )
         ] == dirname
         assert [
             ipaddress.ip_address(u"127.0.0.1"),
-            ipaddress.ip_address(u"ff::")
+            ipaddress.ip_address(u"ff::"),
         ] == ip
 
     def test_invalid_rfc822name(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "san_rfc822_names.pem"
-            ),
+            os.path.join("x509", "custom", "san_rfc822_names.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         san = cert.extensions.get_extension_for_class(
             x509.SubjectAlternativeName
         ).value
         values = san.get_values_for_type(x509.RFC822Name)
         assert values == [
-            u'email', u'email <email>', u'email <email@email>',
-            u'email <email@xn--eml-vla4c.com>', u'myemail:'
+            u"email",
+            u"email <email>",
+            u"email <email@email>",
+            u"email <email@xn--eml-vla4c.com>",
+            u"myemail:",
         ]
 
     def test_other_name(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "san_other_name.pem"
-            ),
+            os.path.join("x509", "custom", "san_other_name.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
 
         ext = cert.extensions.get_extension_for_oid(
@@ -2594,8 +2553,9 @@
         assert ext is not None
         assert ext.critical is False
 
-        expected = x509.OtherName(x509.ObjectIdentifier("1.2.3.4"),
-                                  b'\x16\x0bHello World')
+        expected = x509.OtherName(
+            x509.ObjectIdentifier("1.2.3.4"), b"\x16\x0bHello World"
+        )
         assert len(ext.value) == 1
         assert list(ext.value)[0] == expected
 
@@ -2603,12 +2563,16 @@
         assert othernames == [expected]
 
     def test_certbuilder(self, backend):
-        sans = [u'*.example.org', u'*.xn--4ca7aey.example.com',
-                u'foobar.example.net']
+        sans = [
+            u"*.example.org",
+            u"*.xn--4ca7aey.example.com",
+            u"foobar.example.net",
+        ]
         private_key = RSA_KEY_2048.private_key(backend)
         builder = _make_certbuilder(private_key)
         builder = builder.add_extension(
-            SubjectAlternativeName(list(map(DNSName, sans))), True)
+            SubjectAlternativeName(list(map(DNSName, sans))), True
+        )
 
         cert = builder.sign(private_key, hashes.SHA1(), backend)
         result = [
@@ -2625,11 +2589,9 @@
 class TestExtendedKeyUsageExtension(object):
     def test_eku(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "extended_key_usage.pem"
-            ),
+            os.path.join("x509", "custom", "extended_key_usage.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.EXTENDED_KEY_USAGE
@@ -2663,14 +2625,14 @@
     def test_valid_nonstandard_method(self):
         ad = x509.AccessDescription(
             ObjectIdentifier("2.999.1"),
-            x509.UniformResourceIdentifier(u"http://example.com")
+            x509.UniformResourceIdentifier(u"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(u"http://ocsp.domain.com"),
         )
         if not six.PY2:
             assert repr(ad) == (
@@ -2688,26 +2650,26 @@
     def test_eq(self):
         ad = x509.AccessDescription(
             AuthorityInformationAccessOID.OCSP,
-            x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+            x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
         )
         ad2 = x509.AccessDescription(
             AuthorityInformationAccessOID.OCSP,
-            x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+            x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
         )
         assert ad == ad2
 
     def test_ne(self):
         ad = x509.AccessDescription(
             AuthorityInformationAccessOID.OCSP,
-            x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+            x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
         )
         ad2 = x509.AccessDescription(
             AuthorityInformationAccessOID.CA_ISSUERS,
-            x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+            x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
         )
         ad3 = x509.AccessDescription(
             AuthorityInformationAccessOID.OCSP,
-            x509.UniformResourceIdentifier(u"http://notthesame")
+            x509.UniformResourceIdentifier(u"http://notthesame"),
         )
         assert ad != ad2
         assert ad != ad3
@@ -2716,15 +2678,15 @@
     def test_hash(self):
         ad = x509.AccessDescription(
             AuthorityInformationAccessOID.OCSP,
-            x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+            x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
         )
         ad2 = x509.AccessDescription(
             AuthorityInformationAccessOID.OCSP,
-            x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+            x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
         )
         ad3 = x509.AccessDescription(
             AuthorityInformationAccessOID.CA_ISSUERS,
-            x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+            x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
         )
         assert hash(ad) == hash(ad2)
         assert hash(ad) != hash(ad3)
@@ -2779,7 +2741,7 @@
         cert = _load_cert(
             os.path.join("x509", "department-of-state-root.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.POLICY_CONSTRAINTS,
@@ -2787,21 +2749,23 @@
         assert ext.critical is True
 
         assert ext.value == x509.PolicyConstraints(
-            require_explicit_policy=None, inhibit_policy_mapping=0,
+            require_explicit_policy=None,
+            inhibit_policy_mapping=0,
         )
 
     def test_require_explicit_policy(self, backend):
         cert = _load_cert(
             os.path.join("x509", "custom", "policy_constraints_explicit.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.POLICY_CONSTRAINTS
         )
         assert ext.critical is True
         assert ext.value == x509.PolicyConstraints(
-            require_explicit_policy=1, inhibit_policy_mapping=None,
+            require_explicit_policy=1,
+            inhibit_policy_mapping=None,
         )
 
 
@@ -2811,49 +2775,57 @@
             x509.AuthorityInformationAccess(["notanAccessDescription"])
 
     def test_iter_len(self):
-        aia = x509.AuthorityInformationAccess([
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.OCSP,
-                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
-            ),
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.CA_ISSUERS,
-                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
-            )
-        ])
+        aia = x509.AuthorityInformationAccess(
+            [
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.OCSP,
+                    x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+                ),
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.CA_ISSUERS,
+                    x509.UniformResourceIdentifier(
+                        u"http://domain.com/ca.crt"
+                    ),
+                ),
+            ]
+        )
         assert len(aia) == 2
         assert list(aia) == [
             x509.AccessDescription(
                 AuthorityInformationAccessOID.OCSP,
-                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+                x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
             ),
             x509.AccessDescription(
                 AuthorityInformationAccessOID.CA_ISSUERS,
-                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
-            )
+                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt"),
+            ),
         ]
 
     def test_iter_input(self):
         desc = [
             x509.AccessDescription(
                 AuthorityInformationAccessOID.OCSP,
-                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+                x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
             )
         ]
         aia = x509.AuthorityInformationAccess(iter(desc))
         assert list(aia) == desc
 
     def test_repr(self):
-        aia = x509.AuthorityInformationAccess([
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.OCSP,
-                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
-            ),
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.CA_ISSUERS,
-                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
-            )
-        ])
+        aia = x509.AuthorityInformationAccess(
+            [
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.OCSP,
+                    x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+                ),
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.CA_ISSUERS,
+                    x509.UniformResourceIdentifier(
+                        u"http://domain.com/ca.crt"
+                    ),
+                ),
+            ]
+        )
         if not six.PY2:
             assert repr(aia) == (
                 "<AuthorityInformationAccess([<AccessDescription(access_method"
@@ -2876,110 +2848,356 @@
             )
 
     def test_eq(self):
-        aia = x509.AuthorityInformationAccess([
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.OCSP,
-                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
-            ),
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.CA_ISSUERS,
-                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
-            )
-        ])
-        aia2 = x509.AuthorityInformationAccess([
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.OCSP,
-                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
-            ),
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.CA_ISSUERS,
-                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
-            )
-        ])
+        aia = x509.AuthorityInformationAccess(
+            [
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.OCSP,
+                    x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+                ),
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.CA_ISSUERS,
+                    x509.UniformResourceIdentifier(
+                        u"http://domain.com/ca.crt"
+                    ),
+                ),
+            ]
+        )
+        aia2 = x509.AuthorityInformationAccess(
+            [
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.OCSP,
+                    x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+                ),
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.CA_ISSUERS,
+                    x509.UniformResourceIdentifier(
+                        u"http://domain.com/ca.crt"
+                    ),
+                ),
+            ]
+        )
         assert aia == aia2
 
     def test_ne(self):
-        aia = x509.AuthorityInformationAccess([
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.OCSP,
-                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
-            ),
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.CA_ISSUERS,
-                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
-            )
-        ])
-        aia2 = x509.AuthorityInformationAccess([
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.OCSP,
-                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
-            ),
-        ])
+        aia = x509.AuthorityInformationAccess(
+            [
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.OCSP,
+                    x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+                ),
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.CA_ISSUERS,
+                    x509.UniformResourceIdentifier(
+                        u"http://domain.com/ca.crt"
+                    ),
+                ),
+            ]
+        )
+        aia2 = x509.AuthorityInformationAccess(
+            [
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.OCSP,
+                    x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+                ),
+            ]
+        )
 
         assert aia != aia2
         assert aia != object()
 
     def test_indexing(self):
-        aia = x509.AuthorityInformationAccess([
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.OCSP,
-                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
-            ),
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.CA_ISSUERS,
-                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
-            ),
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.OCSP,
-                x509.UniformResourceIdentifier(u"http://ocsp2.domain.com")
-            ),
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.OCSP,
-                x509.UniformResourceIdentifier(u"http://ocsp3.domain.com")
-            ),
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.OCSP,
-                x509.UniformResourceIdentifier(u"http://ocsp4.domain.com")
-            ),
-        ])
+        aia = x509.AuthorityInformationAccess(
+            [
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.OCSP,
+                    x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+                ),
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.CA_ISSUERS,
+                    x509.UniformResourceIdentifier(
+                        u"http://domain.com/ca.crt"
+                    ),
+                ),
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.OCSP,
+                    x509.UniformResourceIdentifier(u"http://ocsp2.domain.com"),
+                ),
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.OCSP,
+                    x509.UniformResourceIdentifier(u"http://ocsp3.domain.com"),
+                ),
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.OCSP,
+                    x509.UniformResourceIdentifier(u"http://ocsp4.domain.com"),
+                ),
+            ]
+        )
         assert aia[-1] == aia[4]
         assert aia[2:6:2] == [aia[2], aia[4]]
 
     def test_hash(self):
-        aia = x509.AuthorityInformationAccess([
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.OCSP,
-                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
-            ),
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.CA_ISSUERS,
-                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
-            )
-        ])
-        aia2 = x509.AuthorityInformationAccess([
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.OCSP,
-                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
-            ),
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.CA_ISSUERS,
-                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
-            )
-        ])
-        aia3 = x509.AuthorityInformationAccess([
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.OCSP,
-                x509.UniformResourceIdentifier(u"http://ocsp.other.com")
-            ),
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.CA_ISSUERS,
-                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
-            )
-        ])
+        aia = x509.AuthorityInformationAccess(
+            [
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.OCSP,
+                    x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+                ),
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.CA_ISSUERS,
+                    x509.UniformResourceIdentifier(
+                        u"http://domain.com/ca.crt"
+                    ),
+                ),
+            ]
+        )
+        aia2 = x509.AuthorityInformationAccess(
+            [
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.OCSP,
+                    x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+                ),
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.CA_ISSUERS,
+                    x509.UniformResourceIdentifier(
+                        u"http://domain.com/ca.crt"
+                    ),
+                ),
+            ]
+        )
+        aia3 = x509.AuthorityInformationAccess(
+            [
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.OCSP,
+                    x509.UniformResourceIdentifier(u"http://ocsp.other.com"),
+                ),
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.CA_ISSUERS,
+                    x509.UniformResourceIdentifier(
+                        u"http://domain.com/ca.crt"
+                    ),
+                ),
+            ]
+        )
         assert hash(aia) == hash(aia2)
         assert hash(aia) != hash(aia3)
 
 
+class TestSubjectInformationAccess(object):
+    def test_invalid_descriptions(self):
+        with pytest.raises(TypeError):
+            x509.SubjectInformationAccess(["notanAccessDescription"])
+
+    def test_iter_len(self):
+        sia = x509.SubjectInformationAccess(
+            [
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+                ),
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca2.domain.com"),
+                ),
+            ]
+        )
+        assert len(sia) == 2
+        assert list(sia) == [
+            x509.AccessDescription(
+                SubjectInformationAccessOID.CA_REPOSITORY,
+                x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+            ),
+            x509.AccessDescription(
+                SubjectInformationAccessOID.CA_REPOSITORY,
+                x509.UniformResourceIdentifier(u"http://ca2.domain.com"),
+            ),
+        ]
+
+    def test_iter_input(self):
+        desc = [
+            x509.AccessDescription(
+                SubjectInformationAccessOID.CA_REPOSITORY,
+                x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+            )
+        ]
+        sia = x509.SubjectInformationAccess(iter(desc))
+        assert list(sia) == desc
+
+    def test_repr(self):
+        sia = x509.SubjectInformationAccess(
+            [
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+                )
+            ]
+        )
+        if not six.PY2:
+            assert repr(sia) == (
+                "<SubjectInformationAccess([<AccessDescription(access_method"
+                "=<ObjectIdentifier(oid=1.3.6.1.5.5.7.48.5, name=caRepositor"
+                "y)>, access_location=<UniformResourceIdentifier(value='http"
+                "://ca.domain.com')>)>])>"
+            )
+        else:
+            assert repr(sia) == (
+                "<SubjectInformationAccess([<AccessDescription(access_method"
+                "=<ObjectIdentifier(oid=1.3.6.1.5.5.7.48.5, name=caRepositor"
+                "y)>, access_location=<UniformResourceIdentifier(value=u'htt"
+                "p://ca.domain.com')>)>])>"
+            )
+
+    def test_eq(self):
+        sia = x509.SubjectInformationAccess(
+            [
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+                ),
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca2.domain.com"),
+                ),
+            ]
+        )
+        sia2 = x509.SubjectInformationAccess(
+            [
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+                ),
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca2.domain.com"),
+                ),
+            ]
+        )
+        assert sia == sia2
+
+    def test_ne(self):
+        sia = x509.SubjectInformationAccess(
+            [
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+                ),
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca2.domain.com"),
+                ),
+            ]
+        )
+        sia2 = x509.SubjectInformationAccess(
+            [
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+                ),
+            ]
+        )
+
+        assert sia != sia2
+        assert sia != object()
+
+    def test_indexing(self):
+        sia = x509.SubjectInformationAccess(
+            [
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+                ),
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca2.domain.com"),
+                ),
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca3.domain.com"),
+                ),
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca4.domain.com"),
+                ),
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca5.domain.com"),
+                ),
+            ]
+        )
+        assert sia[-1] == sia[4]
+        assert sia[2:6:2] == [sia[2], sia[4]]
+
+    def test_hash(self):
+        sia = x509.SubjectInformationAccess(
+            [
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+                ),
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca2.domain.com"),
+                ),
+            ]
+        )
+        sia2 = x509.SubjectInformationAccess(
+            [
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+                ),
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca2.domain.com"),
+                ),
+            ]
+        )
+        sia3 = x509.SubjectInformationAccess(
+            [
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+                ),
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"http://ca3.domain.com"),
+                ),
+            ]
+        )
+        assert hash(sia) == hash(sia2)
+        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(
+            os.path.join("x509", "custom", "sia.pem"),
+            x509.load_pem_x509_certificate,
+            backend,
+        )
+        ext = cert.extensions.get_extension_for_oid(
+            ExtensionOID.SUBJECT_INFORMATION_ACCESS
+        )
+        assert ext is not None
+        assert ext.critical is False
+
+        assert ext.value == x509.SubjectInformationAccess(
+            [
+                x509.AccessDescription(
+                    SubjectInformationAccessOID.CA_REPOSITORY,
+                    x509.UniformResourceIdentifier(u"https://my.ca.issuer/"),
+                ),
+                x509.AccessDescription(
+                    x509.ObjectIdentifier("2.999.7"),
+                    x509.UniformResourceIdentifier(
+                        u"gopher://info-mac-archive"
+                    ),
+                ),
+            ]
+        )
+
+
 @pytest.mark.requires_backend_interface(interface=RSABackend)
 @pytest.mark.requires_backend_interface(interface=X509Backend)
 class TestAuthorityInformationAccessExtension(object):
@@ -2987,7 +3205,7 @@
         cert = _load_cert(
             os.path.join("x509", "cryptography.io.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.AUTHORITY_INFORMATION_ACCESS
@@ -2995,22 +3213,26 @@
         assert ext is not None
         assert ext.critical is False
 
-        assert ext.value == x509.AuthorityInformationAccess([
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.OCSP,
-                x509.UniformResourceIdentifier(u"http://gv.symcd.com")
-            ),
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.CA_ISSUERS,
-                x509.UniformResourceIdentifier(u"http://gv.symcb.com/gv.crt")
-            ),
-        ])
+        assert ext.value == x509.AuthorityInformationAccess(
+            [
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.OCSP,
+                    x509.UniformResourceIdentifier(u"http://gv.symcd.com"),
+                ),
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.CA_ISSUERS,
+                    x509.UniformResourceIdentifier(
+                        u"http://gv.symcb.com/gv.crt"
+                    ),
+                ),
+            ]
+        )
 
     def test_aia_multiple_ocsp_ca_issuers(self, backend):
         cert = _load_cert(
             os.path.join("x509", "custom", "aia_ocsp_ca_issuers.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.AUTHORITY_INFORMATION_ACCESS
@@ -3018,30 +3240,39 @@
         assert ext is not None
         assert ext.critical is False
 
-        assert ext.value == x509.AuthorityInformationAccess([
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.OCSP,
-                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
-            ),
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.OCSP,
-                x509.UniformResourceIdentifier(u"http://ocsp2.domain.com")
-            ),
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.CA_ISSUERS,
-                x509.DirectoryName(x509.Name([
-                    x509.NameAttribute(NameOID.COMMON_NAME, u"myCN"),
-                    x509.NameAttribute(NameOID.ORGANIZATION_NAME,
-                                       u"some Org"),
-                ]))
-            ),
-        ])
+        assert ext.value == x509.AuthorityInformationAccess(
+            [
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.OCSP,
+                    x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+                ),
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.OCSP,
+                    x509.UniformResourceIdentifier(u"http://ocsp2.domain.com"),
+                ),
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.CA_ISSUERS,
+                    x509.DirectoryName(
+                        x509.Name(
+                            [
+                                x509.NameAttribute(
+                                    NameOID.COMMON_NAME, u"myCN"
+                                ),
+                                x509.NameAttribute(
+                                    NameOID.ORGANIZATION_NAME, u"some Org"
+                                ),
+                            ]
+                        )
+                    ),
+                ),
+            ]
+        )
 
     def test_aia_ocsp_only(self, backend):
         cert = _load_cert(
             os.path.join("x509", "custom", "aia_ocsp.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.AUTHORITY_INFORMATION_ACCESS
@@ -3049,18 +3280,20 @@
         assert ext is not None
         assert ext.critical is False
 
-        assert ext.value == x509.AuthorityInformationAccess([
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.OCSP,
-                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
-            ),
-        ])
+        assert ext.value == x509.AuthorityInformationAccess(
+            [
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.OCSP,
+                    x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+                ),
+            ]
+        )
 
     def test_aia_ca_issuers_only(self, backend):
         cert = _load_cert(
             os.path.join("x509", "custom", "aia_ca_issuers.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.AUTHORITY_INFORMATION_ACCESS
@@ -3068,16 +3301,25 @@
         assert ext is not None
         assert ext.critical is False
 
-        assert ext.value == x509.AuthorityInformationAccess([
-            x509.AccessDescription(
-                AuthorityInformationAccessOID.CA_ISSUERS,
-                x509.DirectoryName(x509.Name([
-                    x509.NameAttribute(NameOID.COMMON_NAME, u"myCN"),
-                    x509.NameAttribute(NameOID.ORGANIZATION_NAME,
-                                       u"some Org"),
-                ]))
-            ),
-        ])
+        assert ext.value == x509.AuthorityInformationAccess(
+            [
+                x509.AccessDescription(
+                    AuthorityInformationAccessOID.CA_ISSUERS,
+                    x509.DirectoryName(
+                        x509.Name(
+                            [
+                                x509.NameAttribute(
+                                    NameOID.COMMON_NAME, u"myCN"
+                                ),
+                                x509.NameAttribute(
+                                    NameOID.ORGANIZATION_NAME, u"some Org"
+                                ),
+                            ]
+                        )
+                    ),
+                ),
+            ]
+        )
 
 
 @pytest.mark.requires_backend_interface(interface=RSABackend)
@@ -3085,11 +3327,9 @@
 class TestAuthorityKeyIdentifierExtension(object):
     def test_aki_keyid(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "cryptography.io.pem"
-            ),
+            os.path.join("x509", "cryptography.io.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.AUTHORITY_KEY_IDENTIFIER
@@ -3105,11 +3345,9 @@
 
     def test_aki_all_fields(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "authority_key_identifier.pem"
-            ),
+            os.path.join("x509", "custom", "authority_key_identifier.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.AUTHORITY_KEY_IDENTIFIER
@@ -3122,14 +3360,14 @@
         )
         assert ext.value.authority_cert_issuer == [
             x509.DirectoryName(
-                x509.Name([
-                    x509.NameAttribute(
-                        NameOID.ORGANIZATION_NAME, u"PyCA"
-                    ),
-                    x509.NameAttribute(
-                        NameOID.COMMON_NAME, u"cryptography.io"
-                    )
-                ])
+                x509.Name(
+                    [
+                        x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io"
+                        ),
+                    ]
+                )
             )
         ]
         assert ext.value.authority_cert_serial_number == 3
@@ -3140,7 +3378,7 @@
                 "x509", "custom", "authority_key_identifier_no_keyid.pem"
             ),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.AUTHORITY_KEY_IDENTIFIER
@@ -3151,14 +3389,14 @@
         assert ext.value.key_identifier is None
         assert ext.value.authority_cert_issuer == [
             x509.DirectoryName(
-                x509.Name([
-                    x509.NameAttribute(
-                        NameOID.ORGANIZATION_NAME, u"PyCA"
-                    ),
-                    x509.NameAttribute(
-                        NameOID.COMMON_NAME, u"cryptography.io"
-                    )
-                ])
+                x509.Name(
+                    [
+                        x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io"
+                        ),
+                    ]
+                )
             )
         ]
         assert ext.value.authority_cert_serial_number == 3
@@ -3167,12 +3405,12 @@
         issuer_cert = _load_cert(
             os.path.join("x509", "rapidssl_sha256_ca_g3.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         cert = _load_cert(
             os.path.join("x509", "cryptography.io.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.AUTHORITY_KEY_IDENTIFIER
@@ -3186,21 +3424,21 @@
         issuer_cert = _load_cert(
             os.path.join("x509", "rapidssl_sha256_ca_g3.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         cert = _load_cert(
             os.path.join("x509", "cryptography.io.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         ext = cert.extensions.get_extension_for_oid(
             ExtensionOID.AUTHORITY_KEY_IDENTIFIER
         )
-        ski = issuer_cert.extensions.get_extension_for_class(
+        ski_ext = issuer_cert.extensions.get_extension_for_class(
             x509.SubjectKeyIdentifier
         )
         aki = x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
-            ski
+            ski_ext.value
         )
         assert ext.value == aki
 
@@ -3212,7 +3450,7 @@
                 permitted_subtrees=[
                     x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1"))
                 ],
-                excluded_subtrees=None
+                excluded_subtrees=None,
             )
 
         with pytest.raises(TypeError):
@@ -3220,15 +3458,14 @@
                 permitted_subtrees=None,
                 excluded_subtrees=[
                     x509.IPAddress(ipaddress.IPv4Address(u"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"))]
         nc = x509.NameConstraints(
-            permitted_subtrees=permitted,
-            excluded_subtrees=excluded
+            permitted_subtrees=permitted, excluded_subtrees=excluded
         )
         assert nc.permitted_subtrees == permitted
         assert nc.excluded_subtrees == excluded
@@ -3270,8 +3507,7 @@
     def test_repr(self):
         permitted = [x509.DNSName(u"name.local"), x509.DNSName(u"name2.local")]
         nc = x509.NameConstraints(
-            permitted_subtrees=permitted,
-            excluded_subtrees=None
+            permitted_subtrees=permitted, excluded_subtrees=None
         )
         if not six.PY2:
             assert repr(nc) == (
@@ -3289,26 +3525,26 @@
     def test_eq(self):
         nc = x509.NameConstraints(
             permitted_subtrees=[x509.DNSName(u"name.local")],
-            excluded_subtrees=[x509.DNSName(u"name2.local")]
+            excluded_subtrees=[x509.DNSName(u"name2.local")],
         )
         nc2 = x509.NameConstraints(
             permitted_subtrees=[x509.DNSName(u"name.local")],
-            excluded_subtrees=[x509.DNSName(u"name2.local")]
+            excluded_subtrees=[x509.DNSName(u"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")]
+            excluded_subtrees=[x509.DNSName(u"name2.local")],
         )
         nc2 = x509.NameConstraints(
             permitted_subtrees=[x509.DNSName(u"name.local")],
-            excluded_subtrees=None
+            excluded_subtrees=None,
         )
         nc3 = x509.NameConstraints(
             permitted_subtrees=None,
-            excluded_subtrees=[x509.DNSName(u"name2.local")]
+            excluded_subtrees=[x509.DNSName(u"name2.local")],
         )
 
         assert nc != nc2
@@ -3318,19 +3554,19 @@
     def test_hash(self):
         nc = x509.NameConstraints(
             permitted_subtrees=[x509.DNSName(u"name.local")],
-            excluded_subtrees=[x509.DNSName(u"name2.local")]
+            excluded_subtrees=[x509.DNSName(u"name2.local")],
         )
         nc2 = x509.NameConstraints(
             permitted_subtrees=[x509.DNSName(u"name.local")],
-            excluded_subtrees=[x509.DNSName(u"name2.local")]
+            excluded_subtrees=[x509.DNSName(u"name2.local")],
         )
         nc3 = x509.NameConstraints(
             permitted_subtrees=[x509.DNSName(u"name.local")],
-            excluded_subtrees=None
+            excluded_subtrees=None,
         )
         nc4 = x509.NameConstraints(
             permitted_subtrees=None,
-            excluded_subtrees=[x509.DNSName(u"name.local")]
+            excluded_subtrees=[x509.DNSName(u"name.local")],
         )
         assert hash(nc) == hash(nc2)
         assert hash(nc) != hash(nc3)
@@ -3342,51 +3578,43 @@
 class TestNameConstraintsExtension(object):
     def test_permitted_excluded(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "nc_permitted_excluded_2.pem"
-            ),
+            os.path.join("x509", "custom", "nc_permitted_excluded_2.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         nc = cert.extensions.get_extension_for_oid(
             ExtensionOID.NAME_CONSTRAINTS
         ).value
         assert nc == x509.NameConstraints(
-            permitted_subtrees=[
-                x509.DNSName(u"zombo.local"),
-            ],
+            permitted_subtrees=[x509.DNSName(u"zombo.local")],
             excluded_subtrees=[
-                x509.DirectoryName(x509.Name([
-                    x509.NameAttribute(NameOID.COMMON_NAME, u"zombo")
-                ]))
-            ]
+                x509.DirectoryName(
+                    x509.Name(
+                        [x509.NameAttribute(NameOID.COMMON_NAME, u"zombo")]
+                    )
+                )
+            ],
         )
 
     def test_permitted(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "nc_permitted_2.pem"
-            ),
+            os.path.join("x509", "custom", "nc_permitted_2.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         nc = cert.extensions.get_extension_for_oid(
             ExtensionOID.NAME_CONSTRAINTS
         ).value
         assert nc == x509.NameConstraints(
-            permitted_subtrees=[
-                x509.DNSName(u"zombo.local"),
-            ],
-            excluded_subtrees=None
+            permitted_subtrees=[x509.DNSName(u"zombo.local")],
+            excluded_subtrees=None,
         )
 
     def test_permitted_with_leading_period(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "nc_permitted.pem"
-            ),
+            os.path.join("x509", "custom", "nc_permitted.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         nc = cert.extensions.get_extension_for_oid(
             ExtensionOID.NAME_CONSTRAINTS
@@ -3394,18 +3622,16 @@
         assert nc == x509.NameConstraints(
             permitted_subtrees=[
                 x509.DNSName(u".cryptography.io"),
-                x509.UniformResourceIdentifier(u"ftp://cryptography.test")
+                x509.UniformResourceIdentifier(u"ftp://cryptography.test"),
             ],
-            excluded_subtrees=None
+            excluded_subtrees=None,
         )
 
     def test_excluded_with_leading_period(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "nc_excluded.pem"
-            ),
+            os.path.join("x509", "custom", "nc_excluded.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         nc = cert.extensions.get_extension_for_oid(
             ExtensionOID.NAME_CONSTRAINTS
@@ -3414,17 +3640,15 @@
             permitted_subtrees=None,
             excluded_subtrees=[
                 x509.DNSName(u".cryptography.io"),
-                x509.UniformResourceIdentifier(u"gopher://cryptography.test")
-            ]
+                x509.UniformResourceIdentifier(u"gopher://cryptography.test"),
+            ],
         )
 
     def test_permitted_excluded_with_ips(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "nc_permitted_excluded.pem"
-            ),
+            os.path.join("x509", "custom", "nc_permitted_excluded.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         nc = cert.extensions.get_extension_for_oid(
             ExtensionOID.NAME_CONSTRAINTS
@@ -3437,16 +3661,14 @@
             excluded_subtrees=[
                 x509.DNSName(u".domain.com"),
                 x509.UniformResourceIdentifier(u"http://test.local"),
-            ]
+            ],
         )
 
     def test_single_ip_netmask(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "nc_single_ip_netmask.pem"
-            ),
+            os.path.join("x509", "custom", "nc_single_ip_netmask.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         nc = cert.extensions.get_extension_for_oid(
             ExtensionOID.NAME_CONSTRAINTS
@@ -3456,16 +3678,14 @@
                 x509.IPAddress(ipaddress.IPv6Network(u"FF:0:0:0:0:0:0:0/128")),
                 x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.1/32")),
             ],
-            excluded_subtrees=None
+            excluded_subtrees=None,
         )
 
     def test_invalid_netmask(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "nc_invalid_ip_netmask.pem"
-            ),
+            os.path.join("x509", "custom", "nc_invalid_ip_netmask.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         with pytest.raises(ValueError):
             cert.extensions.get_extension_for_oid(
@@ -3473,13 +3693,20 @@
             )
 
     def test_certbuilder(self, backend):
-        permitted = [u'.example.org', u'.xn--4ca7aey.example.com',
-                     u'foobar.example.net']
+        permitted = [
+            u".example.org",
+            u".xn--4ca7aey.example.com",
+            u"foobar.example.net",
+        ]
         private_key = RSA_KEY_2048.private_key(backend)
         builder = _make_certbuilder(private_key)
         builder = builder.add_extension(
-            NameConstraints(permitted_subtrees=list(map(DNSName, permitted)),
-                            excluded_subtrees=[]), True)
+            NameConstraints(
+                permitted_subtrees=list(map(DNSName, permitted)),
+                excluded_subtrees=[],
+            ),
+            True,
+        )
 
         cert = builder.sign(private_key, hashes.SHA1(), backend)
         result = [
@@ -3514,7 +3741,7 @@
                 [x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
                 None,
                 frozenset(["notreasonflags"]),
-                None
+                None,
             )
 
     def test_reason_not_frozenset(self):
@@ -3523,7 +3750,7 @@
                 [x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
                 None,
                 [x509.ReasonFlags.ca_compromise],
-                None
+                None,
             )
 
     def test_disallowed_reasons(self):
@@ -3532,7 +3759,7 @@
                 [x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
                 None,
                 frozenset([x509.ReasonFlags.unspecified]),
-                None
+                None,
             )
 
         with pytest.raises(ValueError):
@@ -3540,16 +3767,13 @@
                 [x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
                 None,
                 frozenset([x509.ReasonFlags.remove_from_crl]),
-                None
+                None,
             )
 
     def test_reason_only(self):
         with pytest.raises(ValueError):
             x509.DistributionPoint(
-                None,
-                None,
-                frozenset([x509.ReasonFlags.aa_compromise]),
-                None
+                None, None, frozenset([x509.ReasonFlags.aa_compromise]), None
             )
 
     def test_eq(self):
@@ -3559,11 +3783,13 @@
             frozenset([x509.ReasonFlags.superseded]),
             [
                 x509.DirectoryName(
-                    x509.Name([
-                        x509.NameAttribute(
-                            NameOID.COMMON_NAME, u"Important CA"
-                        )
-                    ])
+                    x509.Name(
+                        [
+                            x509.NameAttribute(
+                                NameOID.COMMON_NAME, u"Important CA"
+                            )
+                        ]
+                    )
                 )
             ],
         )
@@ -3573,11 +3799,13 @@
             frozenset([x509.ReasonFlags.superseded]),
             [
                 x509.DirectoryName(
-                    x509.Name([
-                        x509.NameAttribute(
-                            NameOID.COMMON_NAME, u"Important CA"
-                        )
-                    ])
+                    x509.Name(
+                        [
+                            x509.NameAttribute(
+                                NameOID.COMMON_NAME, u"Important CA"
+                            )
+                        ]
+                    )
                 )
             ],
         )
@@ -3590,11 +3818,13 @@
             frozenset([x509.ReasonFlags.superseded]),
             [
                 x509.DirectoryName(
-                    x509.Name([
-                        x509.NameAttribute(
-                            NameOID.COMMON_NAME, u"Important CA"
-                        )
-                    ])
+                    x509.Name(
+                        [
+                            x509.NameAttribute(
+                                NameOID.COMMON_NAME, u"Important CA"
+                            )
+                        ]
+                    )
                 )
             ],
         )
@@ -3602,7 +3832,7 @@
             [x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
             None,
             None,
-            None
+            None,
         )
         assert dp != dp2
         assert dp != object()
@@ -3611,9 +3841,9 @@
         name = [x509.UniformResourceIdentifier(u"http://crypt.og/crl")]
         issuer = [
             x509.DirectoryName(
-                x509.Name([
-                    x509.NameAttribute(NameOID.COMMON_NAME, u"Important CA")
-                ])
+                x509.Name(
+                    [x509.NameAttribute(NameOID.COMMON_NAME, u"Important CA")]
+                )
             )
         ]
         dp = x509.DistributionPoint(
@@ -3628,17 +3858,19 @@
     def test_repr(self):
         dp = x509.DistributionPoint(
             None,
-            x509.RelativeDistinguishedName([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")
-            ]),
+            x509.RelativeDistinguishedName(
+                [x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")]
+            ),
             frozenset([x509.ReasonFlags.ca_compromise]),
             [
                 x509.DirectoryName(
-                    x509.Name([
-                        x509.NameAttribute(
-                            NameOID.COMMON_NAME, u"Important CA"
-                        )
-                    ])
+                    x509.Name(
+                        [
+                            x509.NameAttribute(
+                                NameOID.COMMON_NAME, u"Important CA"
+                            )
+                        ]
+                    )
                 )
             ],
         )
@@ -3664,11 +3896,13 @@
             frozenset([x509.ReasonFlags.superseded]),
             [
                 x509.DirectoryName(
-                    x509.Name([
-                        x509.NameAttribute(
-                            NameOID.COMMON_NAME, u"Important CA"
-                        )
-                    ])
+                    x509.Name(
+                        [
+                            x509.NameAttribute(
+                                NameOID.COMMON_NAME, u"Important CA"
+                            )
+                        ]
+                    )
                 )
             ],
         )
@@ -3678,19 +3912,21 @@
             frozenset([x509.ReasonFlags.superseded]),
             [
                 x509.DirectoryName(
-                    x509.Name([
-                        x509.NameAttribute(
-                            NameOID.COMMON_NAME, u"Important CA"
-                        )
-                    ])
+                    x509.Name(
+                        [
+                            x509.NameAttribute(
+                                NameOID.COMMON_NAME, u"Important CA"
+                            )
+                        ]
+                    )
                 )
             ],
         )
         dp3 = x509.DistributionPoint(
             None,
-            x509.RelativeDistinguishedName([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")
-            ]),
+            x509.RelativeDistinguishedName(
+                [x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")]
+            ),
             None,
             None,
         )
@@ -3704,17 +3940,23 @@
             x509.FreshestCRL(["notadistributionpoint"])
 
     def test_iter_len(self):
-        fcrl = x509.FreshestCRL([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"http://domain")],
-                None, None, None
-            ),
-        ])
+        fcrl = x509.FreshestCRL(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"http://domain")],
+                    None,
+                    None,
+                    None,
+                ),
+            ]
+        )
         assert len(fcrl) == 1
         assert list(fcrl) == [
             x509.DistributionPoint(
                 [x509.UniformResourceIdentifier(u"http://domain")],
-                None, None, None
+                None,
+                None,
+                None,
             ),
         ]
 
@@ -3722,21 +3964,25 @@
         points = [
             x509.DistributionPoint(
                 [x509.UniformResourceIdentifier(u"http://domain")],
-                None, None, None
+                None,
+                None,
+                None,
             ),
         ]
         fcrl = x509.FreshestCRL(iter(points))
         assert list(fcrl) == points
 
     def test_repr(self):
-        fcrl = x509.FreshestCRL([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain")],
-                None,
-                frozenset([x509.ReasonFlags.key_compromise]),
-                None
-            ),
-        ])
+        fcrl = x509.FreshestCRL(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain")],
+                    None,
+                    frozenset([x509.ReasonFlags.key_compromise]),
+                    None,
+                ),
+            ]
+        )
         if not six.PY2:
             assert repr(fcrl) == (
                 "<FreshestCRL([<DistributionPoint(full_name=[<Unifo"
@@ -3753,134 +3999,178 @@
             )
 
     def test_eq(self):
-        fcrl = x509.FreshestCRL([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain")],
-                None,
-                frozenset([
-                    x509.ReasonFlags.key_compromise,
-                    x509.ReasonFlags.ca_compromise,
-                ]),
-                [x509.UniformResourceIdentifier(u"uri://thing")],
-            ),
-        ])
-        fcrl2 = x509.FreshestCRL([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain")],
-                None,
-                frozenset([
-                    x509.ReasonFlags.key_compromise,
-                    x509.ReasonFlags.ca_compromise,
-                ]),
-                [x509.UniformResourceIdentifier(u"uri://thing")],
-            ),
-        ])
+        fcrl = x509.FreshestCRL(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain")],
+                    None,
+                    frozenset(
+                        [
+                            x509.ReasonFlags.key_compromise,
+                            x509.ReasonFlags.ca_compromise,
+                        ]
+                    ),
+                    [x509.UniformResourceIdentifier(u"uri://thing")],
+                ),
+            ]
+        )
+        fcrl2 = x509.FreshestCRL(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain")],
+                    None,
+                    frozenset(
+                        [
+                            x509.ReasonFlags.key_compromise,
+                            x509.ReasonFlags.ca_compromise,
+                        ]
+                    ),
+                    [x509.UniformResourceIdentifier(u"uri://thing")],
+                ),
+            ]
+        )
         assert fcrl == fcrl2
 
     def test_ne(self):
-        fcrl = x509.FreshestCRL([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain")],
-                None,
-                frozenset([
-                    x509.ReasonFlags.key_compromise,
-                    x509.ReasonFlags.ca_compromise,
-                ]),
-                [x509.UniformResourceIdentifier(u"uri://thing")],
-            ),
-        ])
-        fcrl2 = x509.FreshestCRL([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain2")],
-                None,
-                frozenset([
-                    x509.ReasonFlags.key_compromise,
-                    x509.ReasonFlags.ca_compromise,
-                ]),
-                [x509.UniformResourceIdentifier(u"uri://thing")],
-            ),
-        ])
-        fcrl3 = x509.FreshestCRL([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain")],
-                None,
-                frozenset([x509.ReasonFlags.key_compromise]),
-                [x509.UniformResourceIdentifier(u"uri://thing")],
-            ),
-        ])
-        fcrl4 = x509.FreshestCRL([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain")],
-                None,
-                frozenset([
-                    x509.ReasonFlags.key_compromise,
-                    x509.ReasonFlags.ca_compromise,
-                ]),
-                [x509.UniformResourceIdentifier(u"uri://thing2")],
-            ),
-        ])
+        fcrl = x509.FreshestCRL(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain")],
+                    None,
+                    frozenset(
+                        [
+                            x509.ReasonFlags.key_compromise,
+                            x509.ReasonFlags.ca_compromise,
+                        ]
+                    ),
+                    [x509.UniformResourceIdentifier(u"uri://thing")],
+                ),
+            ]
+        )
+        fcrl2 = x509.FreshestCRL(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain2")],
+                    None,
+                    frozenset(
+                        [
+                            x509.ReasonFlags.key_compromise,
+                            x509.ReasonFlags.ca_compromise,
+                        ]
+                    ),
+                    [x509.UniformResourceIdentifier(u"uri://thing")],
+                ),
+            ]
+        )
+        fcrl3 = x509.FreshestCRL(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain")],
+                    None,
+                    frozenset([x509.ReasonFlags.key_compromise]),
+                    [x509.UniformResourceIdentifier(u"uri://thing")],
+                ),
+            ]
+        )
+        fcrl4 = x509.FreshestCRL(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain")],
+                    None,
+                    frozenset(
+                        [
+                            x509.ReasonFlags.key_compromise,
+                            x509.ReasonFlags.ca_compromise,
+                        ]
+                    ),
+                    [x509.UniformResourceIdentifier(u"uri://thing2")],
+                ),
+            ]
+        )
         assert fcrl != fcrl2
         assert fcrl != fcrl3
         assert fcrl != fcrl4
         assert fcrl != object()
 
     def test_hash(self):
-        fcrl = x509.FreshestCRL([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain")],
-                None,
-                frozenset([
-                    x509.ReasonFlags.key_compromise,
-                    x509.ReasonFlags.ca_compromise,
-                ]),
-                [x509.UniformResourceIdentifier(u"uri://thing")],
-            ),
-        ])
-        fcrl2 = x509.FreshestCRL([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain")],
-                None,
-                frozenset([
-                    x509.ReasonFlags.key_compromise,
-                    x509.ReasonFlags.ca_compromise,
-                ]),
-                [x509.UniformResourceIdentifier(u"uri://thing")],
-            ),
-        ])
-        fcrl3 = x509.FreshestCRL([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain")],
-                None,
-                frozenset([x509.ReasonFlags.key_compromise]),
-                [x509.UniformResourceIdentifier(u"uri://thing")],
-            ),
-        ])
+        fcrl = x509.FreshestCRL(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain")],
+                    None,
+                    frozenset(
+                        [
+                            x509.ReasonFlags.key_compromise,
+                            x509.ReasonFlags.ca_compromise,
+                        ]
+                    ),
+                    [x509.UniformResourceIdentifier(u"uri://thing")],
+                ),
+            ]
+        )
+        fcrl2 = x509.FreshestCRL(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain")],
+                    None,
+                    frozenset(
+                        [
+                            x509.ReasonFlags.key_compromise,
+                            x509.ReasonFlags.ca_compromise,
+                        ]
+                    ),
+                    [x509.UniformResourceIdentifier(u"uri://thing")],
+                ),
+            ]
+        )
+        fcrl3 = x509.FreshestCRL(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain")],
+                    None,
+                    frozenset([x509.ReasonFlags.key_compromise]),
+                    [x509.UniformResourceIdentifier(u"uri://thing")],
+                ),
+            ]
+        )
         assert hash(fcrl) == hash(fcrl2)
         assert hash(fcrl) != hash(fcrl3)
 
     def test_indexing(self):
-        fcrl = x509.FreshestCRL([
-            x509.DistributionPoint(
-                None, None, None,
-                [x509.UniformResourceIdentifier(u"uri://thing")],
-            ),
-            x509.DistributionPoint(
-                None, None, None,
-                [x509.UniformResourceIdentifier(u"uri://thing2")],
-            ),
-            x509.DistributionPoint(
-                None, None, None,
-                [x509.UniformResourceIdentifier(u"uri://thing3")],
-            ),
-            x509.DistributionPoint(
-                None, None, None,
-                [x509.UniformResourceIdentifier(u"uri://thing4")],
-            ),
-            x509.DistributionPoint(
-                None, None, None,
-                [x509.UniformResourceIdentifier(u"uri://thing5")],
-            ),
-        ])
+        fcrl = x509.FreshestCRL(
+            [
+                x509.DistributionPoint(
+                    None,
+                    None,
+                    None,
+                    [x509.UniformResourceIdentifier(u"uri://thing")],
+                ),
+                x509.DistributionPoint(
+                    None,
+                    None,
+                    None,
+                    [x509.UniformResourceIdentifier(u"uri://thing2")],
+                ),
+                x509.DistributionPoint(
+                    None,
+                    None,
+                    None,
+                    [x509.UniformResourceIdentifier(u"uri://thing3")],
+                ),
+                x509.DistributionPoint(
+                    None,
+                    None,
+                    None,
+                    [x509.UniformResourceIdentifier(u"uri://thing4")],
+                ),
+                x509.DistributionPoint(
+                    None,
+                    None,
+                    None,
+                    [x509.UniformResourceIdentifier(u"uri://thing5")],
+                ),
+            ]
+        )
         assert fcrl[-1] == fcrl[4]
         assert fcrl[2:6:2] == [fcrl[2], fcrl[4]]
 
@@ -3891,39 +4181,45 @@
             x509.CRLDistributionPoints(["notadistributionpoint"])
 
     def test_iter_len(self):
-        cdp = x509.CRLDistributionPoints([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"http://domain")],
-                None,
-                None,
-                None
-            ),
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain")],
-                None,
-                frozenset([
-                    x509.ReasonFlags.key_compromise,
-                    x509.ReasonFlags.ca_compromise,
-                ]),
-                None
-            ),
-        ])
+        cdp = x509.CRLDistributionPoints(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"http://domain")],
+                    None,
+                    None,
+                    None,
+                ),
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain")],
+                    None,
+                    frozenset(
+                        [
+                            x509.ReasonFlags.key_compromise,
+                            x509.ReasonFlags.ca_compromise,
+                        ]
+                    ),
+                    None,
+                ),
+            ]
+        )
         assert len(cdp) == 2
         assert list(cdp) == [
             x509.DistributionPoint(
                 [x509.UniformResourceIdentifier(u"http://domain")],
                 None,
                 None,
-                None
+                None,
             ),
             x509.DistributionPoint(
                 [x509.UniformResourceIdentifier(u"ftp://domain")],
                 None,
-                frozenset([
-                    x509.ReasonFlags.key_compromise,
-                    x509.ReasonFlags.ca_compromise,
-                ]),
-                None
+                frozenset(
+                    [
+                        x509.ReasonFlags.key_compromise,
+                        x509.ReasonFlags.ca_compromise,
+                    ]
+                ),
+                None,
             ),
         ]
 
@@ -3933,21 +4229,23 @@
                 [x509.UniformResourceIdentifier(u"http://domain")],
                 None,
                 None,
-                None
+                None,
             ),
         ]
         cdp = x509.CRLDistributionPoints(iter(points))
         assert list(cdp) == points
 
     def test_repr(self):
-        cdp = x509.CRLDistributionPoints([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain")],
-                None,
-                frozenset([x509.ReasonFlags.key_compromise]),
-                None
-            ),
-        ])
+        cdp = x509.CRLDistributionPoints(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain")],
+                    None,
+                    frozenset([x509.ReasonFlags.key_compromise]),
+                    None,
+                ),
+            ]
+        )
         if not six.PY2:
             assert repr(cdp) == (
                 "<CRLDistributionPoints([<DistributionPoint(full_name=[<Unifo"
@@ -3964,134 +4262,178 @@
             )
 
     def test_eq(self):
-        cdp = x509.CRLDistributionPoints([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain")],
-                None,
-                frozenset([
-                    x509.ReasonFlags.key_compromise,
-                    x509.ReasonFlags.ca_compromise,
-                ]),
-                [x509.UniformResourceIdentifier(u"uri://thing")],
-            ),
-        ])
-        cdp2 = x509.CRLDistributionPoints([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain")],
-                None,
-                frozenset([
-                    x509.ReasonFlags.key_compromise,
-                    x509.ReasonFlags.ca_compromise,
-                ]),
-                [x509.UniformResourceIdentifier(u"uri://thing")],
-            ),
-        ])
+        cdp = x509.CRLDistributionPoints(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain")],
+                    None,
+                    frozenset(
+                        [
+                            x509.ReasonFlags.key_compromise,
+                            x509.ReasonFlags.ca_compromise,
+                        ]
+                    ),
+                    [x509.UniformResourceIdentifier(u"uri://thing")],
+                ),
+            ]
+        )
+        cdp2 = x509.CRLDistributionPoints(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain")],
+                    None,
+                    frozenset(
+                        [
+                            x509.ReasonFlags.key_compromise,
+                            x509.ReasonFlags.ca_compromise,
+                        ]
+                    ),
+                    [x509.UniformResourceIdentifier(u"uri://thing")],
+                ),
+            ]
+        )
         assert cdp == cdp2
 
     def test_ne(self):
-        cdp = x509.CRLDistributionPoints([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain")],
-                None,
-                frozenset([
-                    x509.ReasonFlags.key_compromise,
-                    x509.ReasonFlags.ca_compromise,
-                ]),
-                [x509.UniformResourceIdentifier(u"uri://thing")],
-            ),
-        ])
-        cdp2 = x509.CRLDistributionPoints([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain2")],
-                None,
-                frozenset([
-                    x509.ReasonFlags.key_compromise,
-                    x509.ReasonFlags.ca_compromise,
-                ]),
-                [x509.UniformResourceIdentifier(u"uri://thing")],
-            ),
-        ])
-        cdp3 = x509.CRLDistributionPoints([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain")],
-                None,
-                frozenset([x509.ReasonFlags.key_compromise]),
-                [x509.UniformResourceIdentifier(u"uri://thing")],
-            ),
-        ])
-        cdp4 = x509.CRLDistributionPoints([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain")],
-                None,
-                frozenset([
-                    x509.ReasonFlags.key_compromise,
-                    x509.ReasonFlags.ca_compromise,
-                ]),
-                [x509.UniformResourceIdentifier(u"uri://thing2")],
-            ),
-        ])
+        cdp = x509.CRLDistributionPoints(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain")],
+                    None,
+                    frozenset(
+                        [
+                            x509.ReasonFlags.key_compromise,
+                            x509.ReasonFlags.ca_compromise,
+                        ]
+                    ),
+                    [x509.UniformResourceIdentifier(u"uri://thing")],
+                ),
+            ]
+        )
+        cdp2 = x509.CRLDistributionPoints(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain2")],
+                    None,
+                    frozenset(
+                        [
+                            x509.ReasonFlags.key_compromise,
+                            x509.ReasonFlags.ca_compromise,
+                        ]
+                    ),
+                    [x509.UniformResourceIdentifier(u"uri://thing")],
+                ),
+            ]
+        )
+        cdp3 = x509.CRLDistributionPoints(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain")],
+                    None,
+                    frozenset([x509.ReasonFlags.key_compromise]),
+                    [x509.UniformResourceIdentifier(u"uri://thing")],
+                ),
+            ]
+        )
+        cdp4 = x509.CRLDistributionPoints(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain")],
+                    None,
+                    frozenset(
+                        [
+                            x509.ReasonFlags.key_compromise,
+                            x509.ReasonFlags.ca_compromise,
+                        ]
+                    ),
+                    [x509.UniformResourceIdentifier(u"uri://thing2")],
+                ),
+            ]
+        )
         assert cdp != cdp2
         assert cdp != cdp3
         assert cdp != cdp4
         assert cdp != object()
 
     def test_hash(self):
-        cdp = x509.CRLDistributionPoints([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain")],
-                None,
-                frozenset([
-                    x509.ReasonFlags.key_compromise,
-                    x509.ReasonFlags.ca_compromise,
-                ]),
-                [x509.UniformResourceIdentifier(u"uri://thing")],
-            ),
-        ])
-        cdp2 = x509.CRLDistributionPoints([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain")],
-                None,
-                frozenset([
-                    x509.ReasonFlags.key_compromise,
-                    x509.ReasonFlags.ca_compromise,
-                ]),
-                [x509.UniformResourceIdentifier(u"uri://thing")],
-            ),
-        ])
-        cdp3 = x509.CRLDistributionPoints([
-            x509.DistributionPoint(
-                [x509.UniformResourceIdentifier(u"ftp://domain")],
-                None,
-                frozenset([x509.ReasonFlags.key_compromise]),
-                [x509.UniformResourceIdentifier(u"uri://thing")],
-            ),
-        ])
+        cdp = x509.CRLDistributionPoints(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain")],
+                    None,
+                    frozenset(
+                        [
+                            x509.ReasonFlags.key_compromise,
+                            x509.ReasonFlags.ca_compromise,
+                        ]
+                    ),
+                    [x509.UniformResourceIdentifier(u"uri://thing")],
+                ),
+            ]
+        )
+        cdp2 = x509.CRLDistributionPoints(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain")],
+                    None,
+                    frozenset(
+                        [
+                            x509.ReasonFlags.key_compromise,
+                            x509.ReasonFlags.ca_compromise,
+                        ]
+                    ),
+                    [x509.UniformResourceIdentifier(u"uri://thing")],
+                ),
+            ]
+        )
+        cdp3 = x509.CRLDistributionPoints(
+            [
+                x509.DistributionPoint(
+                    [x509.UniformResourceIdentifier(u"ftp://domain")],
+                    None,
+                    frozenset([x509.ReasonFlags.key_compromise]),
+                    [x509.UniformResourceIdentifier(u"uri://thing")],
+                ),
+            ]
+        )
         assert hash(cdp) == hash(cdp2)
         assert hash(cdp) != hash(cdp3)
 
     def test_indexing(self):
-        ci = x509.CRLDistributionPoints([
-            x509.DistributionPoint(
-                None, None, None,
-                [x509.UniformResourceIdentifier(u"uri://thing")],
-            ),
-            x509.DistributionPoint(
-                None, None, None,
-                [x509.UniformResourceIdentifier(u"uri://thing2")],
-            ),
-            x509.DistributionPoint(
-                None, None, None,
-                [x509.UniformResourceIdentifier(u"uri://thing3")],
-            ),
-            x509.DistributionPoint(
-                None, None, None,
-                [x509.UniformResourceIdentifier(u"uri://thing4")],
-            ),
-            x509.DistributionPoint(
-                None, None, None,
-                [x509.UniformResourceIdentifier(u"uri://thing5")],
-            ),
-        ])
+        ci = x509.CRLDistributionPoints(
+            [
+                x509.DistributionPoint(
+                    None,
+                    None,
+                    None,
+                    [x509.UniformResourceIdentifier(u"uri://thing")],
+                ),
+                x509.DistributionPoint(
+                    None,
+                    None,
+                    None,
+                    [x509.UniformResourceIdentifier(u"uri://thing2")],
+                ),
+                x509.DistributionPoint(
+                    None,
+                    None,
+                    None,
+                    [x509.UniformResourceIdentifier(u"uri://thing3")],
+                ),
+                x509.DistributionPoint(
+                    None,
+                    None,
+                    None,
+                    [x509.UniformResourceIdentifier(u"uri://thing4")],
+                ),
+                x509.DistributionPoint(
+                    None,
+                    None,
+                    None,
+                    [x509.UniformResourceIdentifier(u"uri://thing5")],
+                ),
+            ]
+        )
         assert ci[-1] == ci[4]
         assert ci[2:6:2] == [ci[2], ci[4]]
 
@@ -4105,49 +4447,63 @@
                 "x509", "PKITS_data", "certs", "ValidcRLIssuerTest28EE.crt"
             ),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
 
         cdps = cert.extensions.get_extension_for_oid(
             ExtensionOID.CRL_DISTRIBUTION_POINTS
         ).value
 
-        assert cdps == x509.CRLDistributionPoints([
-            x509.DistributionPoint(
-                full_name=[x509.DirectoryName(
-                    x509.Name([
-                        x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
-                        x509.NameAttribute(
-                            NameOID.ORGANIZATION_NAME,
-                            u"Test Certificates 2011"
-                        ),
-                        x509.NameAttribute(
-                            NameOID.ORGANIZATIONAL_UNIT_NAME,
-                            u"indirectCRL CA3 cRLIssuer"
-                        ),
-                        x509.NameAttribute(
-                            NameOID.COMMON_NAME,
-                            u"indirect CRL for indirectCRL CA3"
-                        ),
-                    ])
-                )],
-                relative_name=None,
-                reasons=None,
-                crl_issuer=[x509.DirectoryName(
-                    x509.Name([
-                        x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
-                        x509.NameAttribute(
-                            NameOID.ORGANIZATION_NAME,
-                            u"Test Certificates 2011"
-                        ),
-                        x509.NameAttribute(
-                            NameOID.ORGANIZATIONAL_UNIT_NAME,
-                            u"indirectCRL CA3 cRLIssuer"
-                        ),
-                    ])
-                )],
-            )
-        ])
+        assert cdps == x509.CRLDistributionPoints(
+            [
+                x509.DistributionPoint(
+                    full_name=[
+                        x509.DirectoryName(
+                            x509.Name(
+                                [
+                                    x509.NameAttribute(
+                                        NameOID.COUNTRY_NAME, u"US"
+                                    ),
+                                    x509.NameAttribute(
+                                        NameOID.ORGANIZATION_NAME,
+                                        u"Test Certificates 2011",
+                                    ),
+                                    x509.NameAttribute(
+                                        NameOID.ORGANIZATIONAL_UNIT_NAME,
+                                        u"indirectCRL CA3 cRLIssuer",
+                                    ),
+                                    x509.NameAttribute(
+                                        NameOID.COMMON_NAME,
+                                        u"indirect CRL for indirectCRL CA3",
+                                    ),
+                                ]
+                            )
+                        )
+                    ],
+                    relative_name=None,
+                    reasons=None,
+                    crl_issuer=[
+                        x509.DirectoryName(
+                            x509.Name(
+                                [
+                                    x509.NameAttribute(
+                                        NameOID.COUNTRY_NAME, u"US"
+                                    ),
+                                    x509.NameAttribute(
+                                        NameOID.ORGANIZATION_NAME,
+                                        u"Test Certificates 2011",
+                                    ),
+                                    x509.NameAttribute(
+                                        NameOID.ORGANIZATIONAL_UNIT_NAME,
+                                        u"indirectCRL CA3 cRLIssuer",
+                                    ),
+                                ]
+                            )
+                        )
+                    ],
+                )
+            ]
+        )
 
     def test_relativename_and_crl_issuer(self, backend):
         cert = _load_cert(
@@ -4155,38 +4511,48 @@
                 "x509", "PKITS_data", "certs", "ValidcRLIssuerTest29EE.crt"
             ),
             x509.load_der_x509_certificate,
-            backend
+            backend,
         )
 
         cdps = cert.extensions.get_extension_for_oid(
             ExtensionOID.CRL_DISTRIBUTION_POINTS
         ).value
 
-        assert cdps == x509.CRLDistributionPoints([
-            x509.DistributionPoint(
-                full_name=None,
-                relative_name=x509.RelativeDistinguishedName([
-                    x509.NameAttribute(
-                        NameOID.COMMON_NAME,
-                        u"indirect CRL for indirectCRL CA3"
+        assert cdps == x509.CRLDistributionPoints(
+            [
+                x509.DistributionPoint(
+                    full_name=None,
+                    relative_name=x509.RelativeDistinguishedName(
+                        [
+                            x509.NameAttribute(
+                                NameOID.COMMON_NAME,
+                                u"indirect CRL for indirectCRL CA3",
+                            ),
+                        ]
                     ),
-                ]),
-                reasons=None,
-                crl_issuer=[x509.DirectoryName(
-                    x509.Name([
-                        x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
-                        x509.NameAttribute(
-                            NameOID.ORGANIZATION_NAME,
-                            u"Test Certificates 2011"
-                        ),
-                        x509.NameAttribute(
-                            NameOID.ORGANIZATIONAL_UNIT_NAME,
-                            u"indirectCRL CA3 cRLIssuer"
-                        ),
-                    ])
-                )],
-            )
-        ])
+                    reasons=None,
+                    crl_issuer=[
+                        x509.DirectoryName(
+                            x509.Name(
+                                [
+                                    x509.NameAttribute(
+                                        NameOID.COUNTRY_NAME, u"US"
+                                    ),
+                                    x509.NameAttribute(
+                                        NameOID.ORGANIZATION_NAME,
+                                        u"Test Certificates 2011",
+                                    ),
+                                    x509.NameAttribute(
+                                        NameOID.ORGANIZATIONAL_UNIT_NAME,
+                                        u"indirectCRL CA3 cRLIssuer",
+                                    ),
+                                ]
+                            )
+                        )
+                    ],
+                )
+            ]
+        )
 
     def test_fullname_crl_issuer_reasons(self, backend):
         cert = _load_cert(
@@ -4194,145 +4560,169 @@
                 "x509", "custom", "cdp_fullname_reasons_crl_issuer.pem"
             ),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
 
         cdps = cert.extensions.get_extension_for_oid(
             ExtensionOID.CRL_DISTRIBUTION_POINTS
         ).value
 
-        assert cdps == x509.CRLDistributionPoints([
-            x509.DistributionPoint(
-                full_name=[x509.UniformResourceIdentifier(
-                    u"http://myhost.com/myca.crl"
-                )],
-                relative_name=None,
-                reasons=frozenset([
-                    x509.ReasonFlags.key_compromise,
-                    x509.ReasonFlags.ca_compromise
-                ]),
-                crl_issuer=[x509.DirectoryName(
-                    x509.Name([
-                        x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
-                        x509.NameAttribute(
-                            NameOID.ORGANIZATION_NAME, u"PyCA"
-                        ),
-                        x509.NameAttribute(
-                            NameOID.COMMON_NAME, u"cryptography CA"
-                        ),
-                    ])
-                )],
-            )
-        ])
+        assert cdps == x509.CRLDistributionPoints(
+            [
+                x509.DistributionPoint(
+                    full_name=[
+                        x509.UniformResourceIdentifier(
+                            u"http://myhost.com/myca.crl"
+                        )
+                    ],
+                    relative_name=None,
+                    reasons=frozenset(
+                        [
+                            x509.ReasonFlags.key_compromise,
+                            x509.ReasonFlags.ca_compromise,
+                        ]
+                    ),
+                    crl_issuer=[
+                        x509.DirectoryName(
+                            x509.Name(
+                                [
+                                    x509.NameAttribute(
+                                        NameOID.COUNTRY_NAME, u"US"
+                                    ),
+                                    x509.NameAttribute(
+                                        NameOID.ORGANIZATION_NAME, u"PyCA"
+                                    ),
+                                    x509.NameAttribute(
+                                        NameOID.COMMON_NAME, u"cryptography CA"
+                                    ),
+                                ]
+                            )
+                        )
+                    ],
+                )
+            ]
+        )
 
     def test_all_reasons(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "cdp_all_reasons.pem"
-            ),
+            os.path.join("x509", "custom", "cdp_all_reasons.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
 
         cdps = cert.extensions.get_extension_for_oid(
             ExtensionOID.CRL_DISTRIBUTION_POINTS
         ).value
 
-        assert cdps == x509.CRLDistributionPoints([
-            x509.DistributionPoint(
-                full_name=[x509.UniformResourceIdentifier(
-                    u"http://domain.com/some.crl"
-                )],
-                relative_name=None,
-                reasons=frozenset([
-                    x509.ReasonFlags.key_compromise,
-                    x509.ReasonFlags.ca_compromise,
-                    x509.ReasonFlags.affiliation_changed,
-                    x509.ReasonFlags.superseded,
-                    x509.ReasonFlags.privilege_withdrawn,
-                    x509.ReasonFlags.cessation_of_operation,
-                    x509.ReasonFlags.aa_compromise,
-                    x509.ReasonFlags.certificate_hold,
-                ]),
-                crl_issuer=None
-            )
-        ])
+        assert cdps == x509.CRLDistributionPoints(
+            [
+                x509.DistributionPoint(
+                    full_name=[
+                        x509.UniformResourceIdentifier(
+                            u"http://domain.com/some.crl"
+                        )
+                    ],
+                    relative_name=None,
+                    reasons=frozenset(
+                        [
+                            x509.ReasonFlags.key_compromise,
+                            x509.ReasonFlags.ca_compromise,
+                            x509.ReasonFlags.affiliation_changed,
+                            x509.ReasonFlags.superseded,
+                            x509.ReasonFlags.privilege_withdrawn,
+                            x509.ReasonFlags.cessation_of_operation,
+                            x509.ReasonFlags.aa_compromise,
+                            x509.ReasonFlags.certificate_hold,
+                        ]
+                    ),
+                    crl_issuer=None,
+                )
+            ]
+        )
 
     def test_single_reason(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "cdp_reason_aa_compromise.pem"
-            ),
+            os.path.join("x509", "custom", "cdp_reason_aa_compromise.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
 
         cdps = cert.extensions.get_extension_for_oid(
             ExtensionOID.CRL_DISTRIBUTION_POINTS
         ).value
 
-        assert cdps == x509.CRLDistributionPoints([
-            x509.DistributionPoint(
-                full_name=[x509.UniformResourceIdentifier(
-                    u"http://domain.com/some.crl"
-                )],
-                relative_name=None,
-                reasons=frozenset([x509.ReasonFlags.aa_compromise]),
-                crl_issuer=None
-            )
-        ])
+        assert cdps == x509.CRLDistributionPoints(
+            [
+                x509.DistributionPoint(
+                    full_name=[
+                        x509.UniformResourceIdentifier(
+                            u"http://domain.com/some.crl"
+                        )
+                    ],
+                    relative_name=None,
+                    reasons=frozenset([x509.ReasonFlags.aa_compromise]),
+                    crl_issuer=None,
+                )
+            ]
+        )
 
     def test_crl_issuer_only(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "cdp_crl_issuer.pem"
-            ),
+            os.path.join("x509", "custom", "cdp_crl_issuer.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
 
         cdps = cert.extensions.get_extension_for_oid(
             ExtensionOID.CRL_DISTRIBUTION_POINTS
         ).value
 
-        assert cdps == x509.CRLDistributionPoints([
-            x509.DistributionPoint(
-                full_name=None,
-                relative_name=None,
-                reasons=None,
-                crl_issuer=[x509.DirectoryName(
-                    x509.Name([
-                        x509.NameAttribute(
-                            NameOID.COMMON_NAME, u"cryptography CA"
-                        ),
-                    ])
-                )],
-            )
-        ])
+        assert cdps == x509.CRLDistributionPoints(
+            [
+                x509.DistributionPoint(
+                    full_name=None,
+                    relative_name=None,
+                    reasons=None,
+                    crl_issuer=[
+                        x509.DirectoryName(
+                            x509.Name(
+                                [
+                                    x509.NameAttribute(
+                                        NameOID.COMMON_NAME, u"cryptography CA"
+                                    ),
+                                ]
+                            )
+                        )
+                    ],
+                )
+            ]
+        )
 
     def test_crl_empty_hostname(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "cdp_empty_hostname.pem"
-            ),
+            os.path.join("x509", "custom", "cdp_empty_hostname.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
 
         cdps = cert.extensions.get_extension_for_oid(
             ExtensionOID.CRL_DISTRIBUTION_POINTS
         ).value
 
-        assert cdps == x509.CRLDistributionPoints([
-            x509.DistributionPoint(
-                full_name=[x509.UniformResourceIdentifier(
-                    u"ldap:///CN=A,OU=B,dc=C,DC=D?E?F?G?H=I"
-                )],
-                relative_name=None,
-                reasons=None,
-                crl_issuer=None
-            )
-        ])
+        assert cdps == x509.CRLDistributionPoints(
+            [
+                x509.DistributionPoint(
+                    full_name=[
+                        x509.UniformResourceIdentifier(
+                            u"ldap:///CN=A,OU=B,dc=C,DC=D?E?F?G?H=I"
+                        )
+                    ],
+                    relative_name=None,
+                    reasons=None,
+                    crl_issuer=None,
+                )
+            ]
+        )
 
 
 @pytest.mark.requires_backend_interface(interface=RSABackend)
@@ -4340,39 +4730,47 @@
 class TestFreshestCRLExtension(object):
     def test_vector(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "freshestcrl.pem"
-            ),
+            os.path.join("x509", "custom", "freshestcrl.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
 
         fcrl = cert.extensions.get_extension_for_class(x509.FreshestCRL).value
-        assert fcrl == x509.FreshestCRL([
-            x509.DistributionPoint(
-                full_name=[
-                    x509.UniformResourceIdentifier(
-                        u'http://myhost.com/myca.crl'
-                    ),
-                    x509.UniformResourceIdentifier(
-                        u'http://backup.myhost.com/myca.crl'
-                    )
-                ],
-                relative_name=None,
-                reasons=frozenset([
-                    x509.ReasonFlags.ca_compromise,
-                    x509.ReasonFlags.key_compromise
-                ]),
-                crl_issuer=[x509.DirectoryName(
-                    x509.Name([
-                        x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
-                        x509.NameAttribute(
-                            NameOID.COMMON_NAME, u"cryptography CA"
+        assert fcrl == x509.FreshestCRL(
+            [
+                x509.DistributionPoint(
+                    full_name=[
+                        x509.UniformResourceIdentifier(
+                            u"http://myhost.com/myca.crl"
                         ),
-                    ])
-                )]
-            )
-        ])
+                        x509.UniformResourceIdentifier(
+                            u"http://backup.myhost.com/myca.crl"
+                        ),
+                    ],
+                    relative_name=None,
+                    reasons=frozenset(
+                        [
+                            x509.ReasonFlags.ca_compromise,
+                            x509.ReasonFlags.key_compromise,
+                        ]
+                    ),
+                    crl_issuer=[
+                        x509.DirectoryName(
+                            x509.Name(
+                                [
+                                    x509.NameAttribute(
+                                        NameOID.COUNTRY_NAME, u"US"
+                                    ),
+                                    x509.NameAttribute(
+                                        NameOID.COMMON_NAME, u"cryptography CA"
+                                    ),
+                                ]
+                            )
+                        )
+                    ],
+                )
+            ]
+        )
 
 
 @pytest.mark.requires_backend_interface(interface=RSABackend)
@@ -4380,17 +4778,38 @@
 class TestOCSPNoCheckExtension(object):
     def test_nocheck(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "ocsp_nocheck.pem"
-            ),
+            os.path.join("x509", "custom", "ocsp_nocheck.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
-        ext = cert.extensions.get_extension_for_oid(
-            ExtensionOID.OCSP_NO_CHECK
-        )
+        ext = cert.extensions.get_extension_for_oid(ExtensionOID.OCSP_NO_CHECK)
         assert isinstance(ext.value, x509.OCSPNoCheck)
 
+    def test_eq(self):
+        onc1 = x509.OCSPNoCheck()
+        onc2 = x509.OCSPNoCheck()
+
+        assert onc1 == onc2
+
+    def test_hash(self):
+        onc1 = x509.OCSPNoCheck()
+        onc2 = x509.OCSPNoCheck()
+
+        assert hash(onc1) == hash(onc2)
+
+    def test_ne(self):
+        onc1 = x509.OCSPNoCheck()
+        onc2 = x509.OCSPNoCheck()
+
+        assert onc1 == onc2
+        assert (onc1 != onc2) is False
+        assert onc1 != object()
+
+    def test_repr(self):
+        onc = x509.OCSPNoCheck()
+
+        assert repr(onc) == "<OCSPNoCheck()>"
+
 
 class TestInhibitAnyPolicy(object):
     def test_not_int(self):
@@ -4429,11 +4848,9 @@
 class TestInhibitAnyPolicyExtension(object):
     def test_inhibit_any_policy(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "inhibit_any_policy_5.pem"
-            ),
+            os.path.join("x509", "custom", "inhibit_any_policy_5.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         iap = cert.extensions.get_extension_for_oid(
             ExtensionOID.INHIBIT_ANY_POLICY
@@ -4450,7 +4867,8 @@
                 x509.IssuingDistributionPoint(
                     full_name=[
                         x509.UniformResourceIdentifier(
-                            u"http://myhost.com/myca.crl")
+                            u"http://myhost.com/myca.crl"
+                        )
                     ],
                     relative_name=None,
                     only_contains_user_certs=False,
@@ -4458,14 +4876,15 @@
                     only_some_reasons=None,
                     indirect_crl=True,
                     only_contains_attribute_certs=False,
-                )
+                ),
             ),
             (
                 "crl_idp_fullname_only.pem",
                 x509.IssuingDistributionPoint(
                     full_name=[
                         x509.UniformResourceIdentifier(
-                            u"http://myhost.com/myca.crl")
+                            u"http://myhost.com/myca.crl"
+                        )
                     ],
                     relative_name=None,
                     only_contains_user_certs=False,
@@ -4473,14 +4892,15 @@
                     only_some_reasons=None,
                     indirect_crl=False,
                     only_contains_attribute_certs=False,
-                )
+                ),
             ),
             (
                 "crl_idp_fullname_only_aa.pem",
                 x509.IssuingDistributionPoint(
                     full_name=[
                         x509.UniformResourceIdentifier(
-                            u"http://myhost.com/myca.crl")
+                            u"http://myhost.com/myca.crl"
+                        )
                     ],
                     relative_name=None,
                     only_contains_user_certs=False,
@@ -4488,14 +4908,15 @@
                     only_some_reasons=None,
                     indirect_crl=False,
                     only_contains_attribute_certs=True,
-                )
+                ),
             ),
             (
                 "crl_idp_fullname_only_user.pem",
                 x509.IssuingDistributionPoint(
                     full_name=[
                         x509.UniformResourceIdentifier(
-                            u"http://myhost.com/myca.crl")
+                            u"http://myhost.com/myca.crl"
+                        )
                     ],
                     relative_name=None,
                     only_contains_user_certs=True,
@@ -4503,23 +4924,26 @@
                     only_some_reasons=None,
                     indirect_crl=False,
                     only_contains_attribute_certs=False,
-                )
+                ),
             ),
             (
                 "crl_idp_only_ca.pem",
                 x509.IssuingDistributionPoint(
                     full_name=None,
-                    relative_name=x509.RelativeDistinguishedName([
-                        x509.NameAttribute(
-                            oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
-                        )
-                    ]),
+                    relative_name=x509.RelativeDistinguishedName(
+                        [
+                            x509.NameAttribute(
+                                oid=x509.NameOID.ORGANIZATION_NAME,
+                                value=u"PyCA",
+                            )
+                        ]
+                    ),
                     only_contains_user_certs=False,
                     only_contains_ca_certs=True,
                     only_some_reasons=None,
                     indirect_crl=False,
                     only_contains_attribute_certs=False,
-                )
+                ),
             ),
             (
                 "crl_idp_reasons_only.pem",
@@ -4528,62 +4952,71 @@
                     relative_name=None,
                     only_contains_user_certs=False,
                     only_contains_ca_certs=False,
-                    only_some_reasons=frozenset([
-                        x509.ReasonFlags.key_compromise
-                    ]),
+                    only_some_reasons=frozenset(
+                        [x509.ReasonFlags.key_compromise]
+                    ),
                     indirect_crl=False,
                     only_contains_attribute_certs=False,
-                )
+                ),
             ),
             (
                 "crl_idp_relative_user_all_reasons.pem",
                 x509.IssuingDistributionPoint(
                     full_name=None,
-                    relative_name=x509.RelativeDistinguishedName([
-                        x509.NameAttribute(
-                            oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
-                        )
-                    ]),
+                    relative_name=x509.RelativeDistinguishedName(
+                        [
+                            x509.NameAttribute(
+                                oid=x509.NameOID.ORGANIZATION_NAME,
+                                value=u"PyCA",
+                            )
+                        ]
+                    ),
                     only_contains_user_certs=True,
                     only_contains_ca_certs=False,
-                    only_some_reasons=frozenset([
-                        x509.ReasonFlags.key_compromise,
-                        x509.ReasonFlags.ca_compromise,
-                        x509.ReasonFlags.affiliation_changed,
-                        x509.ReasonFlags.superseded,
-                        x509.ReasonFlags.cessation_of_operation,
-                        x509.ReasonFlags.certificate_hold,
-                        x509.ReasonFlags.privilege_withdrawn,
-                        x509.ReasonFlags.aa_compromise,
-                    ]),
+                    only_some_reasons=frozenset(
+                        [
+                            x509.ReasonFlags.key_compromise,
+                            x509.ReasonFlags.ca_compromise,
+                            x509.ReasonFlags.affiliation_changed,
+                            x509.ReasonFlags.superseded,
+                            x509.ReasonFlags.cessation_of_operation,
+                            x509.ReasonFlags.certificate_hold,
+                            x509.ReasonFlags.privilege_withdrawn,
+                            x509.ReasonFlags.aa_compromise,
+                        ]
+                    ),
                     indirect_crl=False,
                     only_contains_attribute_certs=False,
-                )
+                ),
             ),
             (
                 "crl_idp_relativename_only.pem",
                 x509.IssuingDistributionPoint(
                     full_name=None,
-                    relative_name=x509.RelativeDistinguishedName([
-                        x509.NameAttribute(
-                            oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
-                        )
-                    ]),
+                    relative_name=x509.RelativeDistinguishedName(
+                        [
+                            x509.NameAttribute(
+                                oid=x509.NameOID.ORGANIZATION_NAME,
+                                value=u"PyCA",
+                            )
+                        ]
+                    ),
                     only_contains_user_certs=False,
                     only_contains_ca_certs=False,
                     only_some_reasons=None,
                     indirect_crl=False,
                     only_contains_attribute_certs=False,
-                )
+                ),
             ),
-        ]
+        ],
     )
     @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),
-            x509.load_pem_x509_crl, backend
+            x509.load_pem_x509_crl,
+            backend,
         )
         idp = crl.extensions.get_extension_for_class(
             x509.IssuingDistributionPoint
@@ -4592,51 +5025,96 @@
 
     @pytest.mark.parametrize(
         (
-            "error", "only_contains_user_certs", "only_contains_ca_certs",
-            "indirect_crl", "only_contains_attribute_certs",
-            "only_some_reasons", "full_name", "relative_name"
+            "error",
+            "only_contains_user_certs",
+            "only_contains_ca_certs",
+            "indirect_crl",
+            "only_contains_attribute_certs",
+            "only_some_reasons",
+            "full_name",
+            "relative_name",
         ),
         [
             (
-                TypeError, False, False, False, False, 'notafrozenset', None,
-                None
+                TypeError,
+                False,
+                False,
+                False,
+                False,
+                "notafrozenset",
+                None,
+                None,
             ),
             (
-                TypeError, False, False, False, False, frozenset(['bad']),
-                None, None
+                TypeError,
+                False,
+                False,
+                False,
+                False,
+                frozenset(["bad"]),
+                None,
+                None,
             ),
             (
-                ValueError, False, False, False, False,
-                frozenset([x509.ReasonFlags.unspecified]), None, None
+                ValueError,
+                False,
+                False,
+                False,
+                False,
+                frozenset([x509.ReasonFlags.unspecified]),
+                None,
+                None,
             ),
             (
-                ValueError, False, False, False, False,
-                frozenset([x509.ReasonFlags.remove_from_crl]), None, None
+                ValueError,
+                False,
+                False,
+                False,
+                False,
+                frozenset([x509.ReasonFlags.remove_from_crl]),
+                None,
+                None,
             ),
-            (TypeError, 'notabool', False, False, False, None, None, None),
-            (TypeError, False, 'notabool', False, False, None, None, None),
-            (TypeError, False, False, 'notabool', False, None, None, None),
-            (TypeError, False, False, False, 'notabool', None, None, None),
+            (TypeError, "notabool", False, False, False, None, None, None),
+            (TypeError, False, "notabool", False, False, None, None, None),
+            (TypeError, False, False, "notabool", False, None, None, None),
+            (TypeError, False, False, False, "notabool", None, None, None),
             (ValueError, True, True, False, False, None, None, None),
             (ValueError, False, False, True, True, None, None, None),
             (ValueError, False, False, False, False, None, None, None),
-        ]
+        ],
     )
-    def test_invalid_init(self, error, only_contains_user_certs,
-                          only_contains_ca_certs, indirect_crl,
-                          only_contains_attribute_certs, only_some_reasons,
-                          full_name, relative_name):
+    def test_invalid_init(
+        self,
+        error,
+        only_contains_user_certs,
+        only_contains_ca_certs,
+        indirect_crl,
+        only_contains_attribute_certs,
+        only_some_reasons,
+        full_name,
+        relative_name,
+    ):
         with pytest.raises(error):
             x509.IssuingDistributionPoint(
-                full_name, relative_name, only_contains_user_certs,
-                only_contains_ca_certs, only_some_reasons, indirect_crl,
-                only_contains_attribute_certs
+                full_name,
+                relative_name,
+                only_contains_user_certs,
+                only_contains_ca_certs,
+                only_some_reasons,
+                indirect_crl,
+                only_contains_attribute_certs,
             )
 
     def test_repr(self):
         idp = x509.IssuingDistributionPoint(
-            None, None, False, False,
-            frozenset([x509.ReasonFlags.key_compromise]), False, False
+            None,
+            None,
+            False,
+            False,
+            frozenset([x509.ReasonFlags.key_compromise]),
+            False,
+            False,
         )
         if not six.PY2:
             assert repr(idp) == (
@@ -4663,10 +5141,13 @@
             only_contains_attribute_certs=False,
             only_some_reasons=None,
             full_name=None,
-            relative_name=x509.RelativeDistinguishedName([
-                x509.NameAttribute(
-                    oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA")
-            ])
+            relative_name=x509.RelativeDistinguishedName(
+                [
+                    x509.NameAttribute(
+                        oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
+                    )
+                ]
+            ),
         )
         idp2 = x509.IssuingDistributionPoint(
             only_contains_user_certs=False,
@@ -4675,10 +5156,13 @@
             only_contains_attribute_certs=False,
             only_some_reasons=None,
             full_name=None,
-            relative_name=x509.RelativeDistinguishedName([
-                x509.NameAttribute(
-                    oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA")
-            ])
+            relative_name=x509.RelativeDistinguishedName(
+                [
+                    x509.NameAttribute(
+                        oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
+                    )
+                ]
+            ),
         )
         assert idp1 == idp2
 
@@ -4690,10 +5174,13 @@
             only_contains_attribute_certs=False,
             only_some_reasons=None,
             full_name=None,
-            relative_name=x509.RelativeDistinguishedName([
-                x509.NameAttribute(
-                    oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA")
-            ])
+            relative_name=x509.RelativeDistinguishedName(
+                [
+                    x509.NameAttribute(
+                        oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
+                    )
+                ]
+            ),
         )
         idp2 = x509.IssuingDistributionPoint(
             only_contains_user_certs=True,
@@ -4702,10 +5189,13 @@
             only_contains_attribute_certs=False,
             only_some_reasons=None,
             full_name=None,
-            relative_name=x509.RelativeDistinguishedName([
-                x509.NameAttribute(
-                    oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA")
-            ])
+            relative_name=x509.RelativeDistinguishedName(
+                [
+                    x509.NameAttribute(
+                        oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
+                    )
+                ]
+            ),
         )
         assert idp1 != idp2
         assert idp1 != object()
@@ -4719,11 +5209,18 @@
         )
         idp3 = x509.IssuingDistributionPoint(
             None,
-            x509.RelativeDistinguishedName([
-                x509.NameAttribute(
-                    oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA")
-            ]),
-            True, False, None, False, False
+            x509.RelativeDistinguishedName(
+                [
+                    x509.NameAttribute(
+                        oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
+                    )
+                ]
+            ),
+            True,
+            False,
+            None,
+            False,
+            False,
         )
         assert hash(idp1) == hash(idp2)
         assert hash(idp1) != hash(idp3)
@@ -4787,11 +5284,13 @@
             ),
             x509.IssuingDistributionPoint(
                 full_name=None,
-                relative_name=x509.RelativeDistinguishedName([
-                    x509.NameAttribute(
-                        oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
-                    )
-                ]),
+                relative_name=x509.RelativeDistinguishedName(
+                    [
+                        x509.NameAttribute(
+                            oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
+                        )
+                    ]
+                ),
                 only_contains_user_certs=False,
                 only_contains_ca_certs=True,
                 only_some_reasons=None,
@@ -4809,53 +5308,65 @@
             ),
             x509.IssuingDistributionPoint(
                 full_name=None,
-                relative_name=x509.RelativeDistinguishedName([
-                    x509.NameAttribute(
-                        oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"),
-                    x509.NameAttribute(
-                        oid=x509.NameOID.COMMON_NAME, value=u"cryptography")
-                ]),
+                relative_name=x509.RelativeDistinguishedName(
+                    [
+                        x509.NameAttribute(
+                            oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
+                        ),
+                        x509.NameAttribute(
+                            oid=x509.NameOID.COMMON_NAME, value=u"cryptography"
+                        ),
+                    ]
+                ),
                 only_contains_user_certs=True,
                 only_contains_ca_certs=False,
-                only_some_reasons=frozenset([
-                    x509.ReasonFlags.key_compromise,
-                    x509.ReasonFlags.ca_compromise,
-                    x509.ReasonFlags.affiliation_changed,
-                    x509.ReasonFlags.privilege_withdrawn,
-                    x509.ReasonFlags.aa_compromise,
-                ]),
+                only_some_reasons=frozenset(
+                    [
+                        x509.ReasonFlags.key_compromise,
+                        x509.ReasonFlags.ca_compromise,
+                        x509.ReasonFlags.affiliation_changed,
+                        x509.ReasonFlags.privilege_withdrawn,
+                        x509.ReasonFlags.aa_compromise,
+                    ]
+                ),
                 indirect_crl=False,
                 only_contains_attribute_certs=False,
             ),
             x509.IssuingDistributionPoint(
                 full_name=None,
-                relative_name=x509.RelativeDistinguishedName([
-                    x509.NameAttribute(
-                        oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
-                    )
-                ]),
+                relative_name=x509.RelativeDistinguishedName(
+                    [
+                        x509.NameAttribute(
+                            oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
+                        )
+                    ]
+                ),
                 only_contains_user_certs=False,
                 only_contains_ca_certs=False,
                 only_some_reasons=None,
                 indirect_crl=False,
                 only_contains_attribute_certs=False,
             ),
-        ]
+        ],
     )
     def test_generate(self, idp, backend):
         key = RSA_KEY_2048.private_key(backend)
         last_update = datetime.datetime(2002, 1, 1, 12, 1)
         next_update = datetime.datetime(2030, 1, 1, 12, 1)
-        builder = x509.CertificateRevocationListBuilder().issuer_name(
-            x509.Name([
-                x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
-            ])
-        ).last_update(
-            last_update
-        ).next_update(
-            next_update
-        ).add_extension(
-            idp, True
+        builder = (
+            x509.CertificateRevocationListBuilder()
+            .issuer_name(
+                x509.Name(
+                    [
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"cryptography.io CA"
+                        )
+                    ]
+                )
+            )
+            .last_update(last_update)
+            .next_update(next_update)
+            .add_extension(idp, True)
         )
 
         crl = builder.sign(key, hashes.SHA256(), backend)
@@ -4873,7 +5384,7 @@
         cert = _load_cert(
             os.path.join("x509", "cryptography.io.precert.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         poison = cert.extensions.get_extension_for_oid(
             ExtensionOID.PRECERT_POISON
@@ -4886,90 +5397,142 @@
 
     def test_generate(self, backend):
         private_key = RSA_KEY_2048.private_key(backend)
-        cert = _make_certbuilder(private_key).add_extension(
-            x509.PrecertPoison(), critical=True
-        ).sign(private_key, hashes.SHA256(), backend)
+        cert = (
+            _make_certbuilder(private_key)
+            .add_extension(x509.PrecertPoison(), critical=True)
+            .sign(private_key, hashes.SHA256(), backend)
+        )
         poison = cert.extensions.get_extension_for_oid(
             ExtensionOID.PRECERT_POISON
         ).value
         assert isinstance(poison, x509.PrecertPoison)
 
+    def test_eq(self):
+        pcp1 = x509.PrecertPoison()
+        pcp2 = x509.PrecertPoison()
+
+        assert pcp1 == pcp2
+
+    def test_hash(self):
+        pcp1 = x509.PrecertPoison()
+        pcp2 = x509.PrecertPoison()
+
+        assert hash(pcp1) == hash(pcp2)
+
+    def test_ne(self):
+        pcp1 = x509.PrecertPoison()
+        pcp2 = x509.PrecertPoison()
+
+        assert pcp1 == pcp2
+        assert (pcp1 != pcp2) is False
+        assert pcp1 != object()
+
+    def test_repr(self):
+        pcp = x509.PrecertPoison()
+
+        assert repr(pcp) == "<PrecertPoison()>"
+
 
 @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_OPENSSL_110F_OR_GREATER),
-        skip_message="Requires OpenSSL 1.1.0f+",
+        only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT),
+        skip_message="Requires CT support",
     )
     def test_eq(self, backend):
-        sct = _load_cert(
-            os.path.join("x509", "badssl-sct.pem"),
-            x509.load_pem_x509_certificate,
-            backend
-        ).extensions.get_extension_for_class(
-            x509.PrecertificateSignedCertificateTimestamps
-        ).value[0]
-        sct2 = _load_cert(
-            os.path.join("x509", "badssl-sct.pem"),
-            x509.load_pem_x509_certificate,
-            backend
-        ).extensions.get_extension_for_class(
-            x509.PrecertificateSignedCertificateTimestamps
-        ).value[0]
+        sct = (
+            _load_cert(
+                os.path.join("x509", "badssl-sct.pem"),
+                x509.load_pem_x509_certificate,
+                backend,
+            )
+            .extensions.get_extension_for_class(
+                x509.PrecertificateSignedCertificateTimestamps
+            )
+            .value[0]
+        )
+        sct2 = (
+            _load_cert(
+                os.path.join("x509", "badssl-sct.pem"),
+                x509.load_pem_x509_certificate,
+                backend,
+            )
+            .extensions.get_extension_for_class(
+                x509.PrecertificateSignedCertificateTimestamps
+            )
+            .value[0]
+        )
         assert sct == sct2
 
     @pytest.mark.supported(
-        only_if=lambda backend: (
-            backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
-        skip_message="Requires OpenSSL 1.1.0f+",
+        only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT),
+        skip_message="Requires CT support",
     )
     def test_ne(self, backend):
-        sct = _load_cert(
-            os.path.join("x509", "badssl-sct.pem"),
-            x509.load_pem_x509_certificate,
-            backend
-        ).extensions.get_extension_for_class(
-            x509.PrecertificateSignedCertificateTimestamps
-        ).value[0]
-        sct2 = _load_cert(
-            os.path.join("x509", "cryptography-scts.pem"),
-            x509.load_pem_x509_certificate,
-            backend
-        ).extensions.get_extension_for_class(
-            x509.PrecertificateSignedCertificateTimestamps
-        ).value[0]
+        sct = (
+            _load_cert(
+                os.path.join("x509", "badssl-sct.pem"),
+                x509.load_pem_x509_certificate,
+                backend,
+            )
+            .extensions.get_extension_for_class(
+                x509.PrecertificateSignedCertificateTimestamps
+            )
+            .value[0]
+        )
+        sct2 = (
+            _load_cert(
+                os.path.join("x509", "cryptography-scts.pem"),
+                x509.load_pem_x509_certificate,
+                backend,
+            )
+            .extensions.get_extension_for_class(
+                x509.PrecertificateSignedCertificateTimestamps
+            )
+            .value[0]
+        )
         assert sct != sct2
         assert sct != object()
 
     @pytest.mark.supported(
-        only_if=lambda backend: (
-            backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
-        skip_message="Requires OpenSSL 1.1.0f+",
+        only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT),
+        skip_message="Requires CT support",
     )
     def test_hash(self, backend):
-        sct = _load_cert(
-            os.path.join("x509", "badssl-sct.pem"),
-            x509.load_pem_x509_certificate,
-            backend
-        ).extensions.get_extension_for_class(
-            x509.PrecertificateSignedCertificateTimestamps
-        ).value[0]
-        sct2 = _load_cert(
-            os.path.join("x509", "badssl-sct.pem"),
-            x509.load_pem_x509_certificate,
-            backend
-        ).extensions.get_extension_for_class(
-            x509.PrecertificateSignedCertificateTimestamps
-        ).value[0]
-        sct3 = _load_cert(
-            os.path.join("x509", "cryptography-scts.pem"),
-            x509.load_pem_x509_certificate,
-            backend
-        ).extensions.get_extension_for_class(
-            x509.PrecertificateSignedCertificateTimestamps
-        ).value[0]
+        sct = (
+            _load_cert(
+                os.path.join("x509", "badssl-sct.pem"),
+                x509.load_pem_x509_certificate,
+                backend,
+            )
+            .extensions.get_extension_for_class(
+                x509.PrecertificateSignedCertificateTimestamps
+            )
+            .value[0]
+        )
+        sct2 = (
+            _load_cert(
+                os.path.join("x509", "badssl-sct.pem"),
+                x509.load_pem_x509_certificate,
+                backend,
+            )
+            .extensions.get_extension_for_class(
+                x509.PrecertificateSignedCertificateTimestamps
+            )
+            .value[0]
+        )
+        sct3 = (
+            _load_cert(
+                os.path.join("x509", "cryptography-scts.pem"),
+                x509.load_pem_x509_certificate,
+                backend,
+            )
+            .extensions.get_extension_for_class(
+                x509.PrecertificateSignedCertificateTimestamps
+            )
+            .value[0]
+        )
         assert hash(sct) == hash(sct2)
         assert hash(sct) != hash(sct3)
 
@@ -4987,90 +5550,114 @@
         )
 
     @pytest.mark.supported(
-        only_if=lambda backend: (
-            backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
-        skip_message="Requires OpenSSL 1.1.0f+",
+        only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT),
+        skip_message="Requires CT support",
     )
     def test_eq(self, backend):
-        psct1 = _load_cert(
-            os.path.join("x509", "badssl-sct.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
+        psct1 = (
+            _load_cert(
+                os.path.join("x509", "badssl-sct.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
+        )
         assert psct1 == psct2
 
     @pytest.mark.supported(
-        only_if=lambda backend: (
-            backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
-        skip_message="Requires OpenSSL 1.1.0f+",
+        only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT),
+        skip_message="Requires CT support",
     )
     def test_ne(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
+        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
+        )
         assert psct1 != psct2
         assert psct1 != object()
 
     @pytest.mark.supported(
-        only_if=lambda backend: (
-            backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
-        skip_message="Requires OpenSSL 1.1.0f+",
+        only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT),
+        skip_message="Requires CT support",
     )
     def test_hash(self, backend):
-        psct1 = _load_cert(
-            os.path.join("x509", "badssl-sct.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
-        psct3 = _load_cert(
-            os.path.join("x509", "cryptography-scts.pem"),
-            x509.load_pem_x509_certificate,
-            backend
-        ).extensions.get_extension_for_class(
-            x509.PrecertificateSignedCertificateTimestamps
-        ).value
+        psct1 = (
+            _load_cert(
+                os.path.join("x509", "badssl-sct.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
+        )
+        psct3 = (
+            _load_cert(
+                os.path.join("x509", "cryptography-scts.pem"),
+                x509.load_pem_x509_certificate,
+                backend,
+            )
+            .extensions.get_extension_for_class(
+                x509.PrecertificateSignedCertificateTimestamps
+            )
+            .value
+        )
         assert hash(psct1) == hash(psct2)
         assert hash(psct1) != hash(psct3)
 
     @pytest.mark.supported(
-        only_if=lambda backend: (
-            backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
-        skip_message="Requires OpenSSL 1.1.0f+",
+        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"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         scts = cert.extensions.get_extension_for_class(
             x509.PrecertificateSignedCertificateTimestamps
@@ -5087,20 +5674,46 @@
             2016, 11, 17, 1, 56, 25, 396000
         )
         assert (
-            sct.entry_type ==
-            x509.certificate_transparency.LogEntryType.PRE_CERTIFICATE
+            sct.entry_type
+            == x509.certificate_transparency.LogEntryType.PRE_CERTIFICATE
         )
 
     @pytest.mark.supported(
-        only_if=lambda backend: (
-            not backend._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER),
-        skip_message="Requires OpenSSL < 1.1.0",
+        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"),
+            x509.load_pem_x509_certificate,
+            backend,
+        )
+        scts = cert.extensions.get_extension_for_class(
+            x509.PrecertificateSignedCertificateTimestamps
+        ).value
+        assert len(scts) == 1
+        [sct] = scts
+
+        private_key = RSA_KEY_2048.private_key(backend)
+        builder = _make_certbuilder(private_key).add_extension(
+            x509.PrecertificateSignedCertificateTimestamps([sct]),
+            critical=False,
+        )
+        cert = builder.sign(private_key, hashes.SHA256(), backend)
+        ext = cert.extensions.get_extension_for_class(
+            x509.PrecertificateSignedCertificateTimestamps
+        ).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
+            backend,
         )
         assert len(cert.extensions) == 10
         with pytest.raises(x509.ExtensionNotFound):
@@ -5119,11 +5732,9 @@
 class TestInvalidExtension(object):
     def test_invalid_certificate_policies_data(self, backend):
         cert = _load_cert(
-            os.path.join(
-                "x509", "custom", "cp_invalid.pem"
-            ),
+            os.path.join("x509", "custom", "cp_invalid.pem"),
             x509.load_pem_x509_certificate,
-            backend
+            backend,
         )
         with pytest.raises(ValueError):
             cert.extensions
@@ -5158,3 +5769,10 @@
         nonce3 = x509.OCSPNonce(b"1" * 5)
         assert hash(nonce1) == hash(nonce2)
         assert hash(nonce1) != hash(nonce3)
+
+
+def test_all_extension_oid_members_have_names_defined():
+    for oid in dir(ExtensionOID):
+        if oid.startswith("__"):
+            continue
+        assert getattr(ExtensionOID, oid) in _OID_NAMES
diff --git a/tests/x509/test_x509_revokedcertbuilder.py b/tests/x509/test_x509_revokedcertbuilder.py
index 75c6b26..0db6d2a 100644
--- a/tests/x509/test_x509_revokedcertbuilder.py
+++ b/tests/x509/test_x509_revokedcertbuilder.py
@@ -30,10 +30,10 @@
     @pytest.mark.requires_backend_interface(interface=X509Backend)
     def test_minimal_serial_number(self, backend):
         revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
-        builder = x509.RevokedCertificateBuilder().serial_number(
-            1
-        ).revocation_date(
-            revocation_date
+        builder = (
+            x509.RevokedCertificateBuilder()
+            .serial_number(1)
+            .revocation_date(revocation_date)
         )
 
         revoked_certificate = builder.build(backend)
@@ -42,10 +42,10 @@
     @pytest.mark.requires_backend_interface(interface=X509Backend)
     def test_biggest_serial_number(self, backend):
         revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
-        builder = x509.RevokedCertificateBuilder().serial_number(
-            (1 << 159) - 1
-        ).revocation_date(
-            revocation_date
+        builder = (
+            x509.RevokedCertificateBuilder()
+            .serial_number((1 << 159) - 1)
+            .revocation_date(revocation_date)
         )
 
         revoked_certificate = builder.build(backend)
@@ -67,10 +67,10 @@
         time = tz.localize(time)
         utc_time = datetime.datetime(2012, 1, 17, 6, 43)
         serial_number = 333
-        builder = x509.RevokedCertificateBuilder().serial_number(
-            serial_number
-        ).revocation_date(
-            time
+        builder = (
+            x509.RevokedCertificateBuilder()
+            .serial_number(serial_number)
+            .revocation_date(time)
         )
 
         revoked_certificate = builder.build(backend)
@@ -129,10 +129,10 @@
     def test_create_revoked(self, backend):
         serial_number = 333
         revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
-        builder = x509.RevokedCertificateBuilder().serial_number(
-            serial_number
-        ).revocation_date(
-            revocation_date
+        builder = (
+            x509.RevokedCertificateBuilder()
+            .serial_number(serial_number)
+            .revocation_date(revocation_date)
         )
 
         revoked_certificate = builder.build(backend)
@@ -145,21 +145,18 @@
         [
             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(u"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)
-        builder = x509.RevokedCertificateBuilder().serial_number(
-            serial_number
-        ).revocation_date(
-            revocation_date
-        ).add_extension(
-            extension, False
+        builder = (
+            x509.RevokedCertificateBuilder()
+            .serial_number(serial_number)
+            .revocation_date(revocation_date)
+            .add_extension(extension, False)
         )
 
         revoked_certificate = builder.build(backend)
@@ -179,20 +176,17 @@
         invalidity_date = x509.InvalidityDate(
             datetime.datetime(2015, 1, 1, 0, 0)
         )
-        certificate_issuer = x509.CertificateIssuer([
-            x509.DNSName(u"cryptography.io"),
-        ])
+        certificate_issuer = x509.CertificateIssuer(
+            [x509.DNSName(u"cryptography.io")]
+        )
         crl_reason = x509.CRLReason(x509.ReasonFlags.aa_compromise)
-        builder = x509.RevokedCertificateBuilder().serial_number(
-            serial_number
-        ).revocation_date(
-            revocation_date
-        ).add_extension(
-            invalidity_date, True
-        ).add_extension(
-            crl_reason, True
-        ).add_extension(
-            certificate_issuer, True
+        builder = (
+            x509.RevokedCertificateBuilder()
+            .serial_number(serial_number)
+            .revocation_date(revocation_date)
+            .add_extension(invalidity_date, True)
+            .add_extension(crl_reason, True)
+            .add_extension(certificate_issuer, True)
         )
 
         revoked_certificate = builder.build(backend)
diff --git a/tox.ini b/tox.ini
index d4c3022..e6e0457 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,20 +1,22 @@
 [tox]
 minversion = 2.4
-envlist = py27,pypy,py34,py35,py36,py37,docs,pep8,py3pep8
+envlist = py27,pypy,py36,py37,py38,py39,docs,pep8,packaging
+isolated_build = True
 
 [testenv]
 extras =
-   test
-   idna: idna
+    test
+    ssh: ssh
 deps =
-    # This must be kept in sync with Jenkinsfile and .travis/install.sh
+    # This must be kept in sync with .github/workflows/ci.yml
     coverage
     ./vectors
-passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH USERNAME
+    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/py34/lib/python3.4/site-packages/cryptography/__init__.py
+    # 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 combine
@@ -42,10 +44,10 @@
     docstest
 basepython = python3
 commands =
-    sphinx-build -j4 -T -W -b html -d {envtmpdir}/doctrees docs docs/_build/html
-    sphinx-build -j4 -T -W -b latex -d {envtmpdir}/doctrees docs docs/_build/latex
-    sphinx-build -j4 -T -W -b doctest -d {envtmpdir}/doctrees docs docs/_build/html
-    sphinx-build -j4 -T -W -b spelling docs docs/_build/html
+    sphinx-build -T -W -b html -d {envtmpdir}/doctrees docs docs/_build/html
+    sphinx-build -T -W -b latex -d {envtmpdir}/doctrees docs docs/_build/latex
+    sphinx-build -T -W -b doctest -d {envtmpdir}/doctrees docs docs/_build/html
+    sphinx-build -T -W -b spelling docs docs/_build/html
     doc8 --allow-long-titles README.rst CHANGELOG.rst docs/ --ignore-path docs/_build/
     python setup.py sdist
     twine check dist/*
@@ -53,26 +55,26 @@
 [testenv:docs-linkcheck]
 extras =
     docs
-basepython = python2.7
+basepython = python3
 commands =
     sphinx-build -W -b linkcheck docs docs/_build/html
 
 [testenv:pep8]
 basepython = python3
 extras =
-   pep8test
+    pep8test
 commands =
     flake8 .
+    black --check .
 
-[testenv:randomorder]
+[testenv:packaging]
 deps =
-    {[testenv]deps}
-    pytest-random
+    check-manifest
 commands =
-    pytest --capture=no --strict --random {posargs}
+    check-manifest
 
 [flake8]
-ignore = W504
+ignore = E203,E211,W503,W504
 exclude = .tox,*.egg,.git,_build,.hypothesis
 select = E,W,F,N,I
 application-import-names = cryptography,cryptography_vectors,tests
@@ -84,5 +86,6 @@
 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/vectors/cryptography_vectors/__about__.py b/vectors/cryptography_vectors/__about__.py
index 6fcb314..dc069d5 100644
--- a/vectors/cryptography_vectors/__about__.py
+++ b/vectors/cryptography_vectors/__about__.py
@@ -5,8 +5,14 @@
 from __future__ import absolute_import, division, print_function
 
 __all__ = [
-    "__title__", "__summary__", "__uri__", "__version__", "__author__",
-    "__email__", "__license__", "__copyright__",
+    "__title__",
+    "__summary__",
+    "__uri__",
+    "__version__",
+    "__author__",
+    "__email__",
+    "__license__",
+    "__copyright__",
 ]
 
 __title__ = "cryptography_vectors"
@@ -14,10 +20,10 @@
 
 __uri__ = "https://github.com/pyca/cryptography"
 
-__version__ = "2.5"
+__version__ = "3.3.2"
 
 __author__ = "The cryptography developers"
 __email__ = "cryptography-dev@python.org"
 
 __license__ = "BSD or Apache License, Version 2.0"
-__copyright__ = "Copyright 2013-2017 %s" % __author__
+__copyright__ = "Copyright 2013-2021 %s" % __author__
diff --git a/vectors/cryptography_vectors/__init__.py b/vectors/cryptography_vectors/__init__.py
index abcfe14..f39ffe0 100644
--- a/vectors/cryptography_vectors/__init__.py
+++ b/vectors/cryptography_vectors/__init__.py
@@ -7,14 +7,26 @@
 import os
 
 from cryptography_vectors.__about__ import (
-    __author__, __copyright__, __email__, __license__, __summary__, __title__,
-    __uri__, __version__
+    __author__,
+    __copyright__,
+    __email__,
+    __license__,
+    __summary__,
+    __title__,
+    __uri__,
+    __version__,
 )
 
 
 __all__ = [
-    "__title__", "__summary__", "__uri__", "__version__", "__author__",
-    "__email__", "__license__", "__copyright__",
+    "__title__",
+    "__summary__",
+    "__uri__",
+    "__version__",
+    "__author__",
+    "__email__",
+    "__license__",
+    "__copyright__",
 ]
 
 
diff --git a/vectors/cryptography_vectors/asymmetric/DER_Serialization/dsa_public_key_invalid_bit_string.der b/vectors/cryptography_vectors/asymmetric/DER_Serialization/dsa_public_key_invalid_bit_string.der
new file mode 100644
index 0000000..7358bc1
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/DER_Serialization/dsa_public_key_invalid_bit_string.der
Binary files differ
diff --git a/vectors/cryptography_vectors/asymmetric/DER_Serialization/dsa_public_key_no_params.der b/vectors/cryptography_vectors/asymmetric/DER_Serialization/dsa_public_key_no_params.der
new file mode 100644
index 0000000..0270ac1
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/DER_Serialization/dsa_public_key_no_params.der
Binary files differ
diff --git a/vectors/cryptography_vectors/asymmetric/DH/dh_key_256.pem b/vectors/cryptography_vectors/asymmetric/DH/dh_key_256.pem
new file mode 100644
index 0000000..1c01dd3
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/DH/dh_key_256.pem
@@ -0,0 +1,4 @@
+-----BEGIN PRIVATE KEY-----
+MFwCAQAwMwYJKoZIhvcNAQMBMCYCIQCBPg6BS+5nbb09nSjtc9NnNdIf9kVyNvaN
+PWFFVgwPqwIBAgQiAiBmJ3qBbu72ZnUxnCrr8ujWFU7jWTcOjhsZSqobmiD6vA==
+-----END PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8-enc.der b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8-enc.der
new file mode 100644
index 0000000..f268ed1
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8-enc.der
Binary files differ
diff --git a/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8-enc.pem b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8-enc.pem
new file mode 100644
index 0000000..d4bcdb2
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8-enc.pem
@@ -0,0 +1,6 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIGbMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAhDgfwSFbYckgICCAAw
+DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEFR6pN0F5UEPFF/Z8RB0maoEQG0i
+za5Fgv9/c8H9med7ttjbbh8T73t+Rq2dcFT2kcUM2HJWGrWMvDpTEPEy0hduYFDh
+YMcDjtOCKyUTwPovQI0=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8.der b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8.der
new file mode 100644
index 0000000..71783b7
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8.der
Binary files differ
diff --git a/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8.pem b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8.pem
new file mode 100644
index 0000000..7cf2b72
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8.pem
@@ -0,0 +1,3 @@
+-----BEGIN PRIVATE KEY-----
+MC4CAQAwBQYDK2VwBCIEIJ1hsZ3v/VpguoRK9JLsLMREScVpezJpGXA7rAMcrn9g
+-----END PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pub.der b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pub.der
new file mode 100644
index 0000000..5b33e75
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pub.der
Binary files differ
diff --git a/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pub.pem b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pub.pem
new file mode 100644
index 0000000..9749b69
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pub.pem
@@ -0,0 +1,3 @@
+-----BEGIN PUBLIC KEY-----
+MCowBQYDK2VwAyEA11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo=
+-----END PUBLIC KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8-enc.der b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8-enc.der
new file mode 100644
index 0000000..0ac1c26
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8-enc.der
Binary files differ
diff --git a/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8-enc.pem b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8-enc.pem
new file mode 100644
index 0000000..c1911db
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8-enc.pem
@@ -0,0 +1,6 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIGrMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAi70Zc5kmb1BQICCAAw
+DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEKLz9IxrHtLE/xwZXVFlzxcEUIdP
+7Z+POIUbdwM2TT9GsYoh/RoHzbSszd873muKzCE6YclamsDhLL8HCS82tGN9ZzgK
+IuNWwcPeskw1i21MLoPJiS76RfncGROVDiz3CKCp
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8.der b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8.der
new file mode 100644
index 0000000..5718a54
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8.der
Binary files differ
diff --git a/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8.pem b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8.pem
new file mode 100644
index 0000000..98af164
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8.pem
@@ -0,0 +1,4 @@
+-----BEGIN PRIVATE KEY-----
+MEcCAQAwBQYDK2VxBDsEOWyCpWLLgI0Q1jK+ichRPr9skp803fqMn2PJlg7240ij
+UoyKP8wvBE45o/xblEkvjwMudUmiAJj5Ww==
+-----END PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pub.der b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pub.der
new file mode 100644
index 0000000..bd2a955
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pub.der
Binary files differ
diff --git a/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pub.pem b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pub.pem
new file mode 100644
index 0000000..640da6f
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pub.pem
@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MEMwBQYDK2VxAzoAX9dEm1m0Yf0s54fsYWrUah2hNCSFpw4fig6nXYDpZ3jt8SR2
+m0bHBhvWeD3x5Q9s0foavq/oJWGA
+-----END PUBLIC KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key
new file mode 100644
index 0000000..edb6961
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key
@@ -0,0 +1,21 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsgAAAAdzc2gtZH
+NzAAAAgQDRqiBQV8QY6a/5fUvFCs5koeJgXj1v2D6dlSqEBEEu8aRA/sJQZmSx6Xzoi9gl
+nvyrS0/Sjf0Y4J5iU1D0gYsNzBhxZFFyrg6LExwSfqMcWWBw8pdcMcOjVfrcWohvqF/Na2
+EnzTZgSOX3WbXA8ikw1Irak5MvD7luNDLX2ZKi7wAAABUA9x8+++PeaLuNjNUvbaDXhvmw
+jbcAAACBAKlkeJEdFVDpZDmMG2Ob8KXy8hrqfEwZHR1B0HPWmZoOpw+TpY/oYEwuA9mXSG
+0EeDVcQlBIaAtu4ZfmZQnRQ5cZ+cBX8VnxAAR6JUQw5R00U6cbiDSYXDn93sLW+D27f1jn
+NShsyz43F66LrsXWTLmoFtMKXw+YBL5cL7Mfk6OcAAAAgHqgOmrZJRmNiRJAY/0ylOB9pc
+S0OfYSj3MXIgbkS0qRvR+Llv1QpFCqykzTEFONosZb75Jb3FuIqw1WdZBOM8ZF5dIBdHAs
+Q01NoTZiHJRQlFwBqMZ4DCs3txDuM1GZmDaYWIRdzVnrq8USqBSo2t1BvXbZXFLcmHsIyh
+xh9CusAAAB6BxKLVkcSi1ZAAAAB3NzaC1kc3MAAACBANGqIFBXxBjpr/l9S8UKzmSh4mBe
+PW/YPp2VKoQEQS7xpED+wlBmZLHpfOiL2CWe/KtLT9KN/RjgnmJTUPSBiw3MGHFkUXKuDo
+sTHBJ+oxxZYHDyl1wxw6NV+txaiG+oX81rYSfNNmBI5fdZtcDyKTDUitqTky8PuW40MtfZ
+kqLvAAAAFQD3Hz77495ou42M1S9toNeG+bCNtwAAAIEAqWR4kR0VUOlkOYwbY5vwpfLyGu
+p8TBkdHUHQc9aZmg6nD5Olj+hgTC4D2ZdIbQR4NVxCUEhoC27hl+ZlCdFDlxn5wFfxWfEA
+BHolRDDlHTRTpxuINJhcOf3ewtb4Pbt/WOc1KGzLPjcXrouuxdZMuagW0wpfD5gEvlwvsx
++To5wAAACAeqA6atklGY2JEkBj/TKU4H2lxLQ59hKPcxciBuRLSpG9H4uW/VCkUKrKTNMQ
+U42ixlvvklvcW4irDVZ1kE4zxkXl0gF0cCxDTU2hNmIclFCUXAGoxngMKze3EO4zUZmYNp
+hYhF3NWeurxRKoFKja3UG9dtlcUtyYewjKHGH0K6wAAAAVAMS2BFSZWFdWHlyYZscEHEEv
+TkRNAAAADWRzYS1ub3Bzdy5rZXkBAgME
+-----END OPENSSH PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key-cert.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key-cert.pub
new file mode 100644
index 0000000..753989d
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key-cert.pub
@@ -0,0 +1 @@
+ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgT/srHasDLk3rB8bDZK7rP6miircgVvnVrTghYfkmZsEAAACBANGqIFBXxBjpr/l9S8UKzmSh4mBePW/YPp2VKoQEQS7xpED+wlBmZLHpfOiL2CWe/KtLT9KN/RjgnmJTUPSBiw3MGHFkUXKuDosTHBJ+oxxZYHDyl1wxw6NV+txaiG+oX81rYSfNNmBI5fdZtcDyKTDUitqTky8PuW40MtfZkqLvAAAAFQD3Hz77495ou42M1S9toNeG+bCNtwAAAIEAqWR4kR0VUOlkOYwbY5vwpfLyGup8TBkdHUHQc9aZmg6nD5Olj+hgTC4D2ZdIbQR4NVxCUEhoC27hl+ZlCdFDlxn5wFfxWfEABHolRDDlHTRTpxuINJhcOf3ewtb4Pbt/WOc1KGzLPjcXrouuxdZMuagW0wpfD5gEvlwvsx+To5wAAACAeqA6atklGY2JEkBj/TKU4H2lxLQ59hKPcxciBuRLSpG9H4uW/VCkUKrKTNMQU42ixlvvklvcW4irDVZ1kE4zxkXl0gF0cCxDTU2hNmIclFCUXAGoxngMKze3EO4zUZmYNphYhF3NWeurxRKoFKja3UG9dtlcUtyYewjKHGH0K6wAAAAAAAAAAQAAAAEAAAAEbmFtZQAAAAAAAAAASz3OqAAAAAEFdF0oAAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAAbIAAAAHc3NoLWRzcwAAAIEA0aogUFfEGOmv+X1LxQrOZKHiYF49b9g+nZUqhARBLvGkQP7CUGZksel86IvYJZ78q0tP0o39GOCeYlNQ9IGLDcwYcWRRcq4OixMcEn6jHFlgcPKXXDHDo1X63FqIb6hfzWthJ802YEjl91m1wPIpMNSK2pOTLw+5bjQy19mSou8AAAAVAPcfPvvj3mi7jYzVL22g14b5sI23AAAAgQCpZHiRHRVQ6WQ5jBtjm/Cl8vIa6nxMGR0dQdBz1pmaDqcPk6WP6GBMLgPZl0htBHg1XEJQSGgLbuGX5mUJ0UOXGfnAV/FZ8QAEeiVEMOUdNFOnG4g0mFw5/d7C1vg9u39Y5zUobMs+Nxeui67F1ky5qBbTCl8PmAS+XC+zH5OjnAAAAIB6oDpq2SUZjYkSQGP9MpTgfaXEtDn2Eo9zFyIG5EtKkb0fi5b9UKRQqspM0xBTjaLGW++SW9xbiKsNVnWQTjPGReXSAXRwLENNTaE2YhyUUJRcAajGeAwrN7cQ7jNRmZg2mFiEXc1Z66vFEqgUqNrdQb122VxS3Jh7CMocYfQrrAAAADcAAAAHc3NoLWRzcwAAAChGJhskBvKjziUaQuE3Kd3A+3WqQduqROikisQyJqTEmD9CqCrV2tuQ dsa-nopsw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key.pub
new file mode 100644
index 0000000..b50e534
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBANGqIFBXxBjpr/l9S8UKzmSh4mBePW/YPp2VKoQEQS7xpED+wlBmZLHpfOiL2CWe/KtLT9KN/RjgnmJTUPSBiw3MGHFkUXKuDosTHBJ+oxxZYHDyl1wxw6NV+txaiG+oX81rYSfNNmBI5fdZtcDyKTDUitqTky8PuW40MtfZkqLvAAAAFQD3Hz77495ou42M1S9toNeG+bCNtwAAAIEAqWR4kR0VUOlkOYwbY5vwpfLyGup8TBkdHUHQc9aZmg6nD5Olj+hgTC4D2ZdIbQR4NVxCUEhoC27hl+ZlCdFDlxn5wFfxWfEABHolRDDlHTRTpxuINJhcOf3ewtb4Pbt/WOc1KGzLPjcXrouuxdZMuagW0wpfD5gEvlwvsx+To5wAAACAeqA6atklGY2JEkBj/TKU4H2lxLQ59hKPcxciBuRLSpG9H4uW/VCkUKrKTNMQU42ixlvvklvcW4irDVZ1kE4zxkXl0gF0cCxDTU2hNmIclFCUXAGoxngMKze3EO4zUZmYNphYhF3NWeurxRKoFKja3UG9dtlcUtyYewjKHGH0K6w= dsa-nopsw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-psw.key b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-psw.key
new file mode 100644
index 0000000..ee6d1e1
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-psw.key
@@ -0,0 +1,22 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABCOodUQio
+9QarE9NbbQUAuXAAAAEAAAAAEAAAGyAAAAB3NzaC1kc3MAAACBAMHOI6HG+xy8RLV6C1JS
+k3dldozdE3SJjK1n0UTdBFo/r1ZMnnH/IZOk5+TkRXplfkVAcmmH++Zm4yb4SzxiDMY8XB
+Tn0COzgPOfJJUV6TKLgAF8QsvlhDrbRgLk1ANPQRY3YIPrVGcF4oUZcyUkIcjl4kycGwMy
+E8wm0FckDKitAAAAFQC5WH7VkaACexO69dQapzGy05mb0QAAAIASiv/QUqr9zGVgiLj/Ge
+KlF7nZLJNCTRoIYGEdARQM23052a/aPMoxaHk3SKHZZmGU87Gp0vl4z6zwRYTp7pzwLqU3
+6gprOqcrFDrPhEq0xkU8+AKClLZ31BUyxN2u6kpBiwQI4Mme3z3PDLVSME+NMEn+sdZKQp
+L0Y0ctXBMtSQAAAIEAmahTrRyoQ32qVX3GKqHElryPfMjWIJsrGByxUNf3hn+IhTs4u858
+oHTiLsZWqrkxFqIGHSSrXclxVkvz9WxKO7D6tcECK7nCqmtEmgXGW+ayVUkeMRlv1VYHKx
+ePsLxOOip14A00vqY5MkZJ8zFFrHxFV0Ej8cKaxJ4SLmvAkM0AAAHwvffrsyCVDHxWqAg2
+KQEm+3ebumLdoLkGgDiSaO1jwJr3R1VnzQTtqveg4rm5agmeHKvUmDTd1lTyTWWk6zX6Bx
+Ww+63V+c3Byv0DlexJToQKo99ZayioWyJjF0/bRXJE34aIYzbDFCQTJdGQ2pEXAnyWBVOB
+j44w/P6VvdhTDvfIYk2ZLpnEPbBi38Hs3n2a2VSp/dNctfE4yfnf2aVntXPoJPRbOYNZs6
+AmcPacbkBXNV2LJeTP2dnXFM4mnReBRVF9Eqd4SsfEXDvC1beBBf9rZN3c/JKXohG97iPi
+PO4Bv34xMKVw64+RtyIN8gTE4Sp/ChqgESIGqCo034YQ5PYLlSX7JxzbfOkBZHAcg2MVsO
+npL1HizQp/l5JzxNrFhjg9ZtIwa5mmPapQ1T/IWQQ5lrtev5cWcfEYonhyvjn2F9Rd5Eem
+jajVfzUS37IGEN2vZaNyLmvMdemJMSkIQwHiHpsdcDfdR7m4hAIWnBYpj2+z5C4WuAFAqE
+UeHjiw9PIMNFK6JTo3QbEUddJw5jgdlx9nctM26JWwKBAOYINCOv5f/2gjR13DzkLL5Xca
+dSO1zHzdIZzrNpD/SFJFeHxlVuaCg6MefhYRMfxVZUAKYdw0qNhhTLecCfChQL6t2NdEOm
+q9f9gN2+a0fnO2lA==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-psw.key.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-psw.key.pub
new file mode 100644
index 0000000..a9a8d56
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-psw.key.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAMHOI6HG+xy8RLV6C1JSk3dldozdE3SJjK1n0UTdBFo/r1ZMnnH/IZOk5+TkRXplfkVAcmmH++Zm4yb4SzxiDMY8XBTn0COzgPOfJJUV6TKLgAF8QsvlhDrbRgLk1ANPQRY3YIPrVGcF4oUZcyUkIcjl4kycGwMyE8wm0FckDKitAAAAFQC5WH7VkaACexO69dQapzGy05mb0QAAAIASiv/QUqr9zGVgiLj/GeKlF7nZLJNCTRoIYGEdARQM23052a/aPMoxaHk3SKHZZmGU87Gp0vl4z6zwRYTp7pzwLqU36gprOqcrFDrPhEq0xkU8+AKClLZ31BUyxN2u6kpBiwQI4Mme3z3PDLVSME+NMEn+sdZKQpL0Y0ctXBMtSQAAAIEAmahTrRyoQ32qVX3GKqHElryPfMjWIJsrGByxUNf3hn+IhTs4u858oHTiLsZWqrkxFqIGHSSrXclxVkvz9WxKO7D6tcECK7nCqmtEmgXGW+ayVUkeMRlv1VYHKxePsLxOOip14A00vqY5MkZJ8zFFrHxFV0Ej8cKaxJ4SLmvAkM0= dsa-psw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key
new file mode 100644
index 0000000..4c0a8bf
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key
@@ -0,0 +1,9 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
+1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQQmVkbOBmCBxiacl7qr3xRljePXZyUZ
+GSSw5Bax3+pjR4SDCN77ay3wmcMT0n5wmFiumKH7LGdRWAOk5FSavF4vAAAAqGb/L/dm/y
+/3AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCZWRs4GYIHGJpyX
+uqvfFGWN49dnJRkZJLDkFrHf6mNHhIMI3vtrLfCZwxPSfnCYWK6YofssZ1FYA6TkVJq8Xi
+8AAAAgcFJtJbq8YCNzbVBuGxtFkMo6E7L6thbRA0FqV4+2MbAAAAAPZWNkc2Etbm9wc3cu
+a2V5AQ==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key-cert.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key-cert.pub
new file mode 100644
index 0000000..ce1626b
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key-cert.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg7ohu2h3ZSjGNlNGn5wmDHarKBT8q+6Yl23V+s3MNjzEAAAAIbmlzdHAyNTYAAABBBCZWRs4GYIHGJpyXuqvfFGWN49dnJRkZJLDkFrHf6mNHhIMI3vtrLfCZwxPSfnCYWK6YofssZ1FYA6TkVJq8Xi8AAAAAAAAAAAAAAAIAAAAEbmFtZQAAABYAAAAHZG9tYWluMQAAAAdkb21haW4yAAAAAAAAAAD//////////wAAAAAAAAAAAAAAAAAAAGgAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAAhuaXN0cDI1NgAAAEEEJlZGzgZggcYmnJe6q98UZY3j12clGRkksOQWsd/qY0eEgwje+2st8JnDE9J+cJhYrpih+yxnUVgDpORUmrxeLwAAAGMAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAEgAAAAhAOSy1UooQNXaxG4cbZTQVnC7uSJlLuk4w9Z5XvbfzzmSAAAAH2QDu0n+WcXzDEsXeaH6IV0drX99PYLeiabxYeUha/o= ecdsa-nopsw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key.pub
new file mode 100644
index 0000000..17f28a6
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCZWRs4GYIHGJpyXuqvfFGWN49dnJRkZJLDkFrHf6mNHhIMI3vtrLfCZwxPSfnCYWK6YofssZ1FYA6TkVJq8Xi8= ecdsa-nopsw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-psw.key b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-psw.key
new file mode 100644
index 0000000..35eb881
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-psw.key
@@ -0,0 +1,11 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABBNPqCdPL
+3HMhcAs6vsUbVEAAAAEAAAAAEAAACIAAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlz
+dHAzODQAAABhBKoqSCpmO6pLIjBokwga14onc/XOkRZ9WPKfFf/d0Aq6HOjL5Vm4ZxxRP3
+mjyLI/flOjrx5aMVAed5xkX6shh+zN4mb2xajuPTwqbvsVvIyglrFbKKQO3DQnkbbeqBHL
+PAAAAOCTdP9vi3Go06Z/wni2pxYNgJK9V8nFfmVceblZYMdAfP0WFAKK/i84Nodl2t72g0
+xAkCOimLPGI7xHL6ZVPe6IOzvaW3wx7L8DSXfoqhKLzJwPVG+iH1m4AyUTU7osswSHzVHv
+nZsU+HPcetVahWWfbswLB4hjbyoQpxc2B0qk0UQJ8E1FsPpjMcpgHOtKEWrmbpHChSI9p3
+KyVGlMtL9CII0hTu61KKm1AgcX+WykIFLjqTpG2PY2X/uuW56nhYrDJqPXL4CPYTwxTRCN
+MOV9toMiqAQHz1JqadMsbdviEQ==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-psw.key.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-psw.key.pub
new file mode 100644
index 0000000..3ea1b8e
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-psw.key.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBKoqSCpmO6pLIjBokwga14onc/XOkRZ9WPKfFf/d0Aq6HOjL5Vm4ZxxRP3mjyLI/flOjrx5aMVAed5xkX6shh+zN4mb2xajuPTwqbvsVvIyglrFbKKQO3DQnkbbeqBHLPA== ecdsa-psw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key
new file mode 100644
index 0000000..34565db
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACDdZgztgAFFC7T5PifrUy/kMu0Pnwq1au3vStKHe7FFMAAAAJhNWbUCTVm1
+AgAAAAtzc2gtZWQyNTUxOQAAACDdZgztgAFFC7T5PifrUy/kMu0Pnwq1au3vStKHe7FFMA
+AAAECQxzIh6s9TpOOlHcnFpjQIdZWmrhsU3eTq05iGHQejl91mDO2AAUULtPk+J+tTL+Qy
+7Q+fCrVq7e9K0od7sUUwAAAAEWVkMjU1MTktbm9wc3cua2V5AQIDBA==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key-cert.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key-cert.pub
new file mode 100644
index 0000000..b0240b3
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key-cert.pub
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJjE7jTtIuJ68m5zBEtn0bCWKUXcMdAOau0hO3FTMpeAAAAAIN1mDO2AAUULtPk+J+tTL+Qy7Q+fCrVq7e9K0od7sUUwAAAAAAAAAAAAAAABAAAABG5hbWUAAAAAAAAAAAAAAAD//////////wAAAAAAAABkAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIN1mDO2AAUULtPk+J+tTL+Qy7Q+fCrVq7e9K0od7sUUwAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEAqewM0LFjD4qQUdGNmF/W512ogcjh5xDchw9h2GjhFstttkQVfEOATyafZ5/vWGegMjSnGWHHTxv1A5bqzA+UE ed25519-nopsw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key.pub
new file mode 100644
index 0000000..21ead37
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN1mDO2AAUULtPk+J+tTL+Qy7Q+fCrVq7e9K0od7sUUw ed25519-nopsw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-psw.key b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-psw.key
new file mode 100644
index 0000000..f1c7563
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-psw.key
@@ -0,0 +1,8 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABCX39wD02
+J9++SP9d3vlnxuAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIFpz5PWWlJVx/imA
+hJjv57fg4eTGFVHf4WcFfbXPNo+/AAAAoM+Bu9OvuVW6elNfhl4AxM/p7Oy02ptuWR+LNV
+Y9Sjp/ADM+aTHb77DbZFD8WqzXhioUcOcej1EdAr4NFP7YRC1TIDHuzKgePDjewMMK7lCw
+9qZgZbBUYN8q0/V42L9Tc9w8rjkewtd6r5u+5UOLv7Ct7WxSESAAC1KC5TnnU0CCZ1ZFXN
+NOsxE0VLn5e+SDyILFF8fGt3mGk0S1D50zVzY=
+-----END OPENSSH PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-psw.key.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-psw.key.pub
new file mode 100644
index 0000000..4c3d949
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-psw.key.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFpz5PWWlJVx/imAhJjv57fg4eTGFVHf4WcFfbXPNo+/ ed25519-psw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/gen.sh b/vectors/cryptography_vectors/asymmetric/OpenSSH/gen.sh
new file mode 100755
index 0000000..b18c338
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/gen.sh
@@ -0,0 +1,62 @@
+#! /bin/sh
+
+rm *.key *.pub
+
+# avoid having too many files
+ecbits="ecbits.txt"
+echo 521 > "$ecbits"
+getecbits() {
+    last=$(cat $ecbits)
+    case "$last" in
+    256) last=384;;
+    384) last=521;;
+    521) last=256;;
+    esac
+    echo $last > "$ecbits"
+    echo $last
+}
+
+genkey() {
+    fn="$1"
+    args="-f $fn -C $fn"
+    case "$fn" in
+    ecdsa-*) args="$args -t ecdsa -b $(getecbits)" ;;
+    rsa-*) args="$args -t rsa" ;;
+    dsa-*) args="$args -t dsa" ;;
+    ed25519-*) args="$args -t ed25519" ;;
+    esac
+    password=''
+    case "$fn" in
+    *-psw.*) password="password" ;;
+    esac
+    ssh-keygen -q -o $args -N "$password"
+}
+
+# generate private key files
+for ktype in rsa dsa ecdsa ed25519; do
+    for psw in nopsw psw; do
+        genkey "${ktype}-${psw}.key"
+    done
+done
+
+# generate public key files
+for fn in *.key; do
+  ssh-keygen -q -y -f "$fn" > /dev/null
+done
+
+rm -f "$ecbits"
+
+# generate public key files with certificate
+ssh-keygen -q -s "dsa-nopsw.key" -I "name" \
+    -z 1 -V 20100101123000:21090101123000 \
+    "dsa-nopsw.key.pub"
+ssh-keygen -q -s "rsa-nopsw.key" -I "name" \
+    -z 2 -n user1,user2 -t rsa-sha2-512 \
+    "rsa-nopsw.key.pub"
+ssh-keygen -q -s "ecdsa-nopsw.key" -I "name" \
+    -h -n domain1,domain2 \
+    "ecdsa-nopsw.key.pub"
+ssh-keygen -q -s "ed25519-nopsw.key" -I "name" \
+    -O no-port-forwarding \
+    "ed25519-nopsw.key.pub"
+
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key
new file mode 100644
index 0000000..9d755e8
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key
@@ -0,0 +1,27 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
+NhAAAAAwEAAQAAAQEAq2QdSm22QEsm+GtpAwN4qk0exDIxwxUb8jJ6LLLo19KJR9ySQw+d
+Ajp9WIUumXM2OPYi0qqtN6JKMsDrVSR87RoK7V2W4lHYljZBODGYA8bfpqaLt5HMvkJpsk
+MEBqJkZtwO8G/J3QDOFByiGOxeeL4/2vnM5XwN/ff6SKABxfU60gDmlofFlZqCD9exWO52
+dg5BQ/gN5qJLBKBZmC3jWnAkrblvfPxwfp9WC3gMrFIILytCWvRu9YKM+nQZoqo0yCbzDy
+7GRK5XZJlHfw+jV3MWMSXS7GSirOmTtmyygCtkphA3Y8HAQlibhdg+5jZDWRdDXIU2uOET
+iHc8qvxM8wAAA8jQzBt60MwbegAAAAdzc2gtcnNhAAABAQCrZB1KbbZASyb4a2kDA3iqTR
+7EMjHDFRvyMnossujX0olH3JJDD50COn1YhS6ZczY49iLSqq03okoywOtVJHztGgrtXZbi
+UdiWNkE4MZgDxt+mpou3kcy+QmmyQwQGomRm3A7wb8ndAM4UHKIY7F54vj/a+czlfA399/
+pIoAHF9TrSAOaWh8WVmoIP17FY7nZ2DkFD+A3moksEoFmYLeNacCStuW98/HB+n1YLeAys
+UggvK0Ja9G71goz6dBmiqjTIJvMPLsZErldkmUd/D6NXcxYxJdLsZKKs6ZO2bLKAK2SmED
+djwcBCWJuF2D7mNkNZF0NchTa44ROIdzyq/EzzAAAAAwEAAQAAAQAYxAivfpb9R17EOtEb
+zF6dTTOK6i3ioKQ/JSgeWWPn+9Y2ehrwccsgTU9bgTMwnUNSi86QXnVVOrA6EUJwNSuQH1
+lA32s0HNuNKR3XfuMWeKBMtngt+HV7cKFRTvm/86tKabYG7EBhHQKqSVDrBQzJqcQUYlBH
+QNvMvQ5/fA+FiSN5RT/Hv0iJy9WFQyqN8W1KwWUnFnXgEw9ZFBlhjugcKDS1l+fyoDN0p8
+/Lm0ojn2I7I9SH9tXKb330zhO3CfXMVtjnpyi8wQALT6nEarfBwzGK6R0xWX3Xm+i2fQBb
+sIBDr5r3WWpQlnPnFx1lSntQeoUVLJEimRklQJVL41fhAAAAgG923QGfsC61Fp22Q+rVb8
+0N66qxCfnXnQDbtT7ZdFK7tjXdKVA/GU+vU/pgFarixYcGS5gDKbAJM2R6XLz9cE5UVzaw
+TrJab6bHG9bX8xh2kSKcY0GW1/QWp9pv6IWrCQziXiDP7uxDndxolfnHXsjT3QVfNQV+J8
+gtkjP3aCy1AAAAgQDZOcREo87MzWwbEoVAETZ8uVqWspTwJtAvIuqHePvHa1wvc5fWqr1Z
+1wUN/Wl/DKhOjydBXQSa/SfKdsIx0JRkia06bYvS1eoL08+y3aHFkIR+WOp6bVYH/p3HzH
+9qdMx7IHpAco7ZtBmQ4O2nZamVBRX5FnxkcmkCHccENSh9OwAAAIEAyfvp/f6ka1FH/mW0
+MqRxAhzB8SoUGbvnGhgBxTWgCH7iMbtUwVsi3TbJr0gYBYQoFH61rAGvOfUTb9cd9+bowR
+j9m3oBOwSJBJG25hrmsqyFuZQlSMAv/AXjjLNUF1AQkpRZZMcEd6rTffprogiwkGdrRTMe
++tjRZCCgQaN+06kAAAANcnNhLW5vcHN3LmtleQECAwQFBg==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key-cert.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key-cert.pub
new file mode 100644
index 0000000..35b0c2b
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key-cert.pub
@@ -0,0 +1 @@
+ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgtL8iJdlD7w2obBZdlxyqu06uLR78fvDASlnR3RRk/eMAAAADAQABAAABAQCrZB1KbbZASyb4a2kDA3iqTR7EMjHDFRvyMnossujX0olH3JJDD50COn1YhS6ZczY49iLSqq03okoywOtVJHztGgrtXZbiUdiWNkE4MZgDxt+mpou3kcy+QmmyQwQGomRm3A7wb8ndAM4UHKIY7F54vj/a+czlfA399/pIoAHF9TrSAOaWh8WVmoIP17FY7nZ2DkFD+A3moksEoFmYLeNacCStuW98/HB+n1YLeAysUggvK0Ja9G71goz6dBmiqjTIJvMPLsZErldkmUd/D6NXcxYxJdLsZKKs6ZO2bLKAK2SmEDdjwcBCWJuF2D7mNkNZF0NchTa44ROIdzyq/EzzAAAAAAAAAAIAAAABAAAABG5hbWUAAAASAAAABXVzZXIxAAAABXVzZXIyAAAAAAAAAAD//////////wAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQCrZB1KbbZASyb4a2kDA3iqTR7EMjHDFRvyMnossujX0olH3JJDD50COn1YhS6ZczY49iLSqq03okoywOtVJHztGgrtXZbiUdiWNkE4MZgDxt+mpou3kcy+QmmyQwQGomRm3A7wb8ndAM4UHKIY7F54vj/a+czlfA399/pIoAHF9TrSAOaWh8WVmoIP17FY7nZ2DkFD+A3moksEoFmYLeNacCStuW98/HB+n1YLeAysUggvK0Ja9G71goz6dBmiqjTIJvMPLsZErldkmUd/D6NXcxYxJdLsZKKs6ZO2bLKAK2SmEDdjwcBCWJuF2D7mNkNZF0NchTa44ROIdzyq/EzzAAABFAAAAAxyc2Etc2hhMi01MTIAAAEAC13gJgpzMrO3fGM7lNpLLBDUa6GxB4Lr/RSHLxG5v9+Ym7z5aIYmneYifbNQ9qIPDxpuBQvN97NgV4ImSMjfIaaQi/PxyHKC+mxMXAonT5c5d+zhZHQ95/uxIt6iba1ej3MRVYw+biQlnIHhOUeJNV3W8UOry0XQlJzjTBR2/1Y+Xk89NbZ3F6QQ9UZpT/FvbERghElBauTz1UhtSlMCrn66tEOGxreVHraoM92pJaygginwb5iVU0SPWhWG3Qyh8P6uKzqSKIr+6BfaiIoWJXOLLEtSfmuK8dTuE8fNeU4PQlkJBqfcWbpD934QsP1dXWhan5Y4iFMK4IjcPNu7iA== rsa-nopsw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key.pub
new file mode 100644
index 0000000..00c01e2
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCrZB1KbbZASyb4a2kDA3iqTR7EMjHDFRvyMnossujX0olH3JJDD50COn1YhS6ZczY49iLSqq03okoywOtVJHztGgrtXZbiUdiWNkE4MZgDxt+mpou3kcy+QmmyQwQGomRm3A7wb8ndAM4UHKIY7F54vj/a+czlfA399/pIoAHF9TrSAOaWh8WVmoIP17FY7nZ2DkFD+A3moksEoFmYLeNacCStuW98/HB+n1YLeAysUggvK0Ja9G71goz6dBmiqjTIJvMPLsZErldkmUd/D6NXcxYxJdLsZKKs6ZO2bLKAK2SmEDdjwcBCWJuF2D7mNkNZF0NchTa44ROIdzyq/Ezz rsa-nopsw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-psw.key b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-psw.key
new file mode 100644
index 0000000..cd1f38f
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-psw.key
@@ -0,0 +1,28 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABChvLeROo
+MQfWAC6b7jds47AAAAEAAAAAEAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQCek3p8wNo1
+5l7Ihy4yaGjWScJpjh/Lq7WS7f64KxXKodBe35fLl8lu9Ds4Y06XWeHZdGxC+qp4QoxGYI
+Ft2Awm8sz2wRbPY7d322tG9VnT59bQlvKtq77y9ZYefsdVwh2Uf7otdUZOEz6KuKc1CXXb
+FfBFY6YB1lZ4YkQ2YHsYau22RHDjaHi55VoFokyk7cVnuhaIXCrppAH5+AMoqVtrAb/48G
+2gGdQSo90heqglW7QLXPx2sCijp+62coXzbfViYzARdc5rbcih7zAfxEHMi+1HZmdvNKvd
+2Vy+jPFD+FvvHUDl58XChAjJVmgrsqbZanpgIDD4/48dSnHSH0OxAAADwOuiaWL5LLLt5D
+8bC7i0soG4LUSlwn0GlYhYyeMTBDswEcm+BGt+S1vgHO6f6oA+v+A/npxgwN7OrCJoq5Ls
+iJZ//KCB+GCXXF0wXldwFcNtMoylG2FVo8Gx+Jckm+wSy+Uk73Sk+D+4UiHNGeFuQ85PbX
+ceyne4iayry3PkiWHkfCVUy2UgW2L3YKtoDfXZ5QK3JVPxfMvQnDnP47r3L48rVCfvYVVy
+SX+YnKgwMJPa4DX6mF8E6MPtntzZoN2MUwIJRlRZl1KqzmsIKl/XWsxsQuosvMT1wdDGIf
+uT3uVtabeMyybM4tzPwXdzgnh9Mv2PmcOV15XCmxBFQP81yB8AkuUTWuekEbgypIvppQiL
+vlmiSdWsAZvBqYN7lpuIJloRH3PCyzKSBLDJ6gSpb+ysX9s+Z2of3arBo0wAipZzl+S65R
+guK7IxZu4fynOKojRjL97w6FN0GpaMOC0QiDNfSIg3wk3FJ8c6DFRjKDgaXSk90aMNEGLX
+kOidZ3lQJI3K3KODDt28F9mKfOS6lyUWe9+4CQO+oJkY9EdUgiT3ZSbbQAWjCGSh4A6/Z8
+VHKYb7UCBHYf431VF95yY+2u31Amr76iHuhVZ+G5tcwytvHjuheZQttXSkvvst7J5fxPBT
+kLXfm75RUH9ajveDR9mZq4SmJzlOHPkAn8qZ6QeLGvtsp0Lde8dKu6bo2eqtilbVMr6fi1
+9U+il6J+K+DiAcMh1vOAp0nhecstlabMN+NnENnWy2s+zyQYLKMUACYge7vWxbgJ0PFNkF
+8RM6vC8/IIP81VSp/ako1Dsjh26uhAF92/HHCkAgFiUeBXACjvDo8/FSFbdbutlyl4bvOE
+miKQfSLWqh5lxjDySYOzhGerAivmRCNUviseFTTGP/qE/+s0VZjuMt3afE4H/9baftyt+O
+Iz1OGaMKXPD40mWhj4LUdD+opzGtjexojUPCCzYMzKsEz+WFE3//TWmcM3jq6lSDwbgbVI
+82MGXf0htD7RtB9Gy3pE793LiRecCMygp/gF0ViPa6mwIxMOTy1mp0F5bCddRsNWGA91kF
+XcSjUo/1mpFADMgUcrEsUCK69oxl1D/hPrkvvGEG/U/6z0gS9/cTeIim/6wg+XSULNfOgG
+l0Ate1oHdrZ8XVjHq8e05L5VbYvXMvc9ETnB786kxAuJKc+60KPQS5KHZFiZEAvEcFnd7s
+vCjY0NEf8s8Ofn0jI50UiMn5Ge0YEhtypQOb11kawG1L9UIgL3HJsm7e8osYdGig3ejFHL
+teHHc5kg==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-psw.key.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-psw.key.pub
new file mode 100644
index 0000000..ad94f95
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-psw.key.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCek3p8wNo15l7Ihy4yaGjWScJpjh/Lq7WS7f64KxXKodBe35fLl8lu9Ds4Y06XWeHZdGxC+qp4QoxGYIFt2Awm8sz2wRbPY7d322tG9VnT59bQlvKtq77y9ZYefsdVwh2Uf7otdUZOEz6KuKc1CXXbFfBFY6YB1lZ4YkQ2YHsYau22RHDjaHi55VoFokyk7cVnuhaIXCrppAH5+AMoqVtrAb/48G2gGdQSo90heqglW7QLXPx2sCijp+62coXzbfViYzARdc5rbcih7zAfxEHMi+1HZmdvNKvd2Vy+jPFD+FvvHUDl58XChAjJVmgrsqbZanpgIDD4/48dSnHSH0Ox rsa-psw.key
diff --git a/vectors/cryptography_vectors/asymmetric/PEM_Serialization/dsa_4096.pem b/vectors/cryptography_vectors/asymmetric/PEM_Serialization/dsa_4096.pem
new file mode 100644
index 0000000..af14d24
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/PEM_Serialization/dsa_4096.pem
@@ -0,0 +1,36 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIGVQIBAAKCAgEAy8x5LsdCM2fSykikHtoZZPXcZIRm6ZQQTdpkOHyX9AAqVVpc
+kXqUltbd1rLCPLrii/Syg1XBwsna7fUEci13xUHDk/97TLG9Z0qIH7NgdBQSFGTL
+GWLRbp83nE1Hc+/b0htaABTT5AV5q54xoDED8AuP1b2l7SxrgJz/uDsvZcmHM0y3
+AxTiFkPCqNM+nHN7w3A5NJmFlvm3pl/8B9DCvLXILqiFYpKwewa4f3RUIqCuKlgJ
+y1Yj5BtjiWzJV6153vuAuFaD86G7Pck6VQDEpaY8u0LrjAAgzjaUvD45uDgkw2HT
+/sJDAkIWjpyPEEvXNUmgC8Eh52GCeJkT5iG04a83k67VPbbS3dENRgzrfYpmRIlJ
+lfoxtIpFEkDT8jpioDIzven7JNIhNND0Y/bs3pxnkIjrs3jPGpW9dtoeP2RYSlle
+QGqhu/B8lIEpruy94/Ujz7nVYnNSHZGY/Xk2pLR78B1tzk/mojcgTGtq76GHuY4+
+p2I49qThgWOGBT8b9ysYgI2momHcDkauYDq+l0dLg6h6XPPsXU/8qHL2e5bCW1ub
+uMb0T4NwbLwl9rHc2gcKxfdqnK0S4hgfWR5nhDsLyBl04mBqnZaoQ/1Re5Kp1ZPU
+a8/CR0oktwh8ZP0TmUbExSd8s/kAUJl49Fp2EGxFX3pF2u+mucbd7iDLVzMCIQC8
+2B6GLZaBrH0OZX2UWz8A10CuSHAqib45GIwrcEqVawKCAgALNtzq+Ap3IPQrjnsv
+H9VLVoLx2X37UF6DQbX9ZMcnKNwooVNxkLPXokMIbVPcsegavw1ECgiCu/Ung+aM
+Whd5w4iMMxq82I9nd8M2GUvg2QYYz5WOLsbJTk1kcV0WF+MzMrWCAuXiuCfYj90X
+/TT4Dhd037fVfktjwzJFtox/NKKAM96/wm1MHfwy4s7L1cTe1IZZocZDB/4l9Ciw
+zNAc/VlNfmheAp2RlrdY2waHVCdU/AJt3SNghUqLAn5dJELKyY37Kl9OHxlnWhTl
+dTBzC6VFo4Gkro28/C2kY/PYkShEXPT1c8D63lbYdUt5dgnfkDpddjRvgXGLOltJ
+1/iogrMq2EKYECoXtNzM7xXu4vxMNERjbyuhWg9qw0mczFgel1R7UWeMAz5a7J5S
+fHs2p94/iyQZPHHzR4DEXC/dcuUer5koPJvdIO6hbqMtfcWEusOEdOxRapjrzaLN
+bCaL4c33j8y7FOK2JC+FAz4ljI9AIsomt73tyrRK0PFUrlh147cuOKZAGYHQJlaX
+z6R/W8z71vO00/VvIZuzHOYiGZQdQ9FUiilQfrhGTF+SOyjBMSSantUUVUoYRC7E
+Tc83vQEQnpe5VjX+naSCk/zv1JFGSSpmWn45aDSswmA9EjyKxg1Ae0MrshB8a80M
+eqRrfGtlLuGT0KiYKse9z90VTAKCAgBFBTIdD1g7KRadTcyhoXw5+zMv9vVb4kDx
+UAyuqPulh3xadD1FUMukQWjCzJDtx8xDSOj1U9Tal/DsUBtzS+MyPAQdsXhs4oYq
+ska/OWc8287dtX2U511de2bd5GS9rI++HKLHES9RBkAhuo7l5cc+TGJ8XeFgbmdF
+DStjyLy4ABLG0Fkk70nMHIIGal/axBz0kYhSf1W1XO2y2PAY8/sNwdHwI7TimEcL
+qxakgneBjLn7L+SO3N5IRI1eLwl/0sj6ZUoaV6ZpPuTNDTo+7PQlMP+OqIL77R/M
+2rsJSE186CI8IR99K7PylS2Gk+RWv6NcYnZCOcP4UdXEg7/cECjWaSKqn20q2Jrs
+ZuVrRoVF4XsHmcItYj8JyeFcGUgUSlPVNMvO9L11IMvvgo9EQ5OU0UHiBZRoWWu6
+GWx7VqqNU078z2jL+q8MFcqNzqXM64DtVDc1sjdZSLcNzKRWiMrnek4MB+aL1l7G
+hXdDRkj3qTRrkvzHBfxDm2u4lpMInFci1Lu0oxgqLEISYAGdyb1we+OMeqR12YUr
+QP5/DtJdntE0hKMIWGkAYHvIowu2ZOUPs6mdgJZ/IL3qJsvLG2ZFpe3aBnbL8qj7
+/ezCts5E509IwRiVhvEik6ZKUjSYojkcWL88p4PGZsP1/iG8KQgMnCrPIOjYVTVM
+Qs3D7GFsYAIgAhium9LrIx3luKDOsxS4nX9f8xChr+Z1Ej8xgaqp96Y=
+-----END DSA PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/ciphers/Blowfish/bf-cbc.txt b/vectors/cryptography_vectors/ciphers/Blowfish/bf-cbc.txt
index 184d956..ad3fa0c 100644
--- a/vectors/cryptography_vectors/ciphers/Blowfish/bf-cbc.txt
+++ b/vectors/cryptography_vectors/ciphers/Blowfish/bf-cbc.txt
@@ -1,4 +1,4 @@
-# Reformatted from https://www.schneier.com/code/vectors.txt
+# Reformatted from https://www.schneier.com/wp-content/uploads/2015/12/vectors-2.txt
 # to look like the NIST vectors
 
 [ENCRYPT]
diff --git a/vectors/cryptography_vectors/ciphers/Blowfish/bf-cfb.txt b/vectors/cryptography_vectors/ciphers/Blowfish/bf-cfb.txt
index 8a326f5..cd2f58f 100644
--- a/vectors/cryptography_vectors/ciphers/Blowfish/bf-cfb.txt
+++ b/vectors/cryptography_vectors/ciphers/Blowfish/bf-cfb.txt
@@ -1,4 +1,4 @@
-# Reformatted from https://www.schneier.com/code/vectors.txt
+# Reformatted from https://www.schneier.com/wp-content/uploads/2015/12/vectors-2.txt
 # to look like the NIST vectors
 
 [ENCRYPT]
diff --git a/vectors/cryptography_vectors/ciphers/Blowfish/bf-ecb.txt b/vectors/cryptography_vectors/ciphers/Blowfish/bf-ecb.txt
index bb18a5a..70c1c03 100644
--- a/vectors/cryptography_vectors/ciphers/Blowfish/bf-ecb.txt
+++ b/vectors/cryptography_vectors/ciphers/Blowfish/bf-ecb.txt
@@ -1,4 +1,4 @@
-# Reformatted from https://www.schneier.com/code/vectors.txt
+# Reformatted from https://www.schneier.com/wp-content/uploads/2015/12/vectors-2.txt
 # to look like the NIST vectors
 
 [ENCRYPT]
diff --git a/vectors/cryptography_vectors/ciphers/Blowfish/bf-ofb.txt b/vectors/cryptography_vectors/ciphers/Blowfish/bf-ofb.txt
index 21a7421..f87609a 100644
--- a/vectors/cryptography_vectors/ciphers/Blowfish/bf-ofb.txt
+++ b/vectors/cryptography_vectors/ciphers/Blowfish/bf-ofb.txt
@@ -1,4 +1,4 @@
-# Reformatted from https://www.schneier.com/code/vectors.txt
+# Reformatted from https://www.schneier.com/wp-content/uploads/2015/12/vectors-2.txt
 # to look like the NIST vectors
 
 [ENCRYPT]
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_224LongMsg.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_224LongMsg.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_224Monte.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_224Monte.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_224ShortMsg.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_224ShortMsg.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_256LongMsg.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_256LongMsg.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_256Monte.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_256Monte.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_256ShortMsg.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_256ShortMsg.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_384LongMsg.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_384LongMsg.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_384Monte.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_384Monte.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_384ShortMsg.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_384ShortMsg.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_512LongMsg.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_512LongMsg.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_512Monte.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_512Monte.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_512ShortMsg.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_512ShortMsg.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128LongMsg.rsp b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128LongMsg.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128Monte.rsp b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128Monte.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128ShortMsg.rsp b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128ShortMsg.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128VariableOut.rsp b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128VariableOut.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256LongMsg.rsp b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256LongMsg.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256Monte.rsp b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256Monte.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256ShortMsg.rsp b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256ShortMsg.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256VariableOut.rsp b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256VariableOut.rsp
old mode 100755
new mode 100644
diff --git a/vectors/cryptography_vectors/pkcs7/amazon-roots.p7b b/vectors/cryptography_vectors/pkcs7/amazon-roots.p7b
new file mode 100644
index 0000000..cb027da
--- /dev/null
+++ b/vectors/cryptography_vectors/pkcs7/amazon-roots.p7b
Binary files differ
diff --git a/vectors/cryptography_vectors/pkcs7/enveloped.pem b/vectors/cryptography_vectors/pkcs7/enveloped.pem
new file mode 100644
index 0000000..7c7d5b7
--- /dev/null
+++ b/vectors/cryptography_vectors/pkcs7/enveloped.pem
@@ -0,0 +1,91 @@
+-----BEGIN PKCS7-----
+MIIQjQYJKoZIhvcNAQcDoIIQfjCCEHoCAQAxggLCMIIBXQIBADBFMC0xKzApBgNV
+BAMTIlNhbXBsZSBMQU1QUyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkCFCJT7jBtAgsf
+As31ycE+Ot95phvCMA0GCSqGSIb3DQEBAQUABIIBAFbDR6j4ZB/Mo9BQygYItwFc
+P+4rO4d1ak51hc1DpSqyhiMcGahA3yxDRbZ4W1rbmC/s3d5+OWXKYgs1nNMQJ48F
+f45BtNTNslPZ1+NZVbkoVJO8Bxv1rjB8/qWuSUsroqzn9enS8DUBxxPL5aSWKQQN
+G2IaH9BUkMXLPUYA46GATly94IS4fZqwBtNNBP5eiIIPc9Ogjy+7At5GG7rVMN0M
+G5FL0oq52SYUe1167jp378JI+2dkA1q5+Cru/ZE2Rdw3DrMDAFO5GwC7fWKg4zPm
+IHZj92caVj1IyfTmGogT2o5tLMqn61BkptqxZwHDr3FI/aYo4vcHgmlKR/TdbHww
+ggFdAgEAMEUwLTErMCkGA1UEAxMiU2FtcGxlIExBTVBTIENlcnRpZmljYXRlIEF1
+dGhvcml0eQIUZ4K0WXNSS8H0cUcZavD9EYqqTAswDQYJKoZIhvcNAQEBBQAEggEA
+hXeYVSUsT1EBZ/+AjwyEcnlM0kuFMaNvGlBMhAZzAsy012rrZTWbqWkcA3abgm/M
+CuZX7mQL0I79KZdmClGpLx6gQFjLemHaClQV0ZNdX4DxakWuME/kCMqbo4MZXStT
+a0MHlKUdoMt72Rz4YBzNQCL7ePaii5w6Nd2KD7yJAirLYUMJEjVweVaMI9y9LmbO
+vb0g0iuoUe0vp9B20LRcIX37nN5D1GG4tHLPjBD43gC8iqxZQf0uah2cWD1mAG5R
+oBgIDKXPy2eVbcMdSaOirDKYZ49WFe9Lad9q3mHHbFs6K6/yuBm/thMEdCJKZTHo
+jiPvYdYF8IJfEd368I+DujCCDa0GCSqGSIb3DQEHATAUBggqhkiG9w0DBwQIsb1a
+JX/RU9aAgg2I0VXWfs5fc/Yad2qvawUVNX+LObjA6/+t9WxuV2emOeBYzQGjo7q+
+xaIXQwbbF1ej27efGhxUYDwBNS56c0uI0Ta7jxv5OFZhzQGLRzoFp0bbZ+uVC4eP
+bFHarRQiPzlg900XASO0RW+UOtqN5raZ3Ry2lKwXxuStZ0pX666Rz4c8PrmMb4/B
+aQYn6iKcT6fDU2TpSbWY9iph6kZczSeewK+pIj9nXfjDKXScs8D2Raezev2ciq/V
+ZRpRH8JxieimI2yeBmEzTCq11TDYycDfMHB6reGaiCGX//8kAWtskzRyNlV61unY
+ZKSNhVKLwKmCQh1V1Nd3oLApT41EeM2oWedUqNBYqB+XGCD4DUYdm1e+4h73d4dn
+JTkCdadxEn+9RRvZ4YMlw3mvT997Dy3rTXT29dj14TstZZf2O63pY0TpYy0HZy6Z
+Jug1qoe/vdcJ9SPOSfJE6VWCeVjxB+eGgheFLKqzK8Hs/Bm0/wDKpSFgEpOPnkJ4
+HJ2Uzgn1Emo6gBDJt+qn3s2UnowcMsTgellhKvgzVq59LTyRyWL5U8XMBsXT4qjm
+0LkRvDkOIjMQH7kqvWbpPlnWpLKo/VVoxifldEegWAqFVrP7f5Y+nNQttAYV79uk
+MXvR+5YFkvmQAerfllPqXBJdbB65ovikSVsy/kAboGpRG1oAZ4ODdwdGyiGIzyyc
+lE0x/8+gY8BqWzRtWX4GySKyZ50/+xkJe5ss0IXPCgq/09bdihsRn57v4V4SpdDO
+k3g/Dce+LzCRL8uTbUhrhZnjKSjRc3fFaD/BpLYjEDbnGF0ICslN3vb2xWUK1u4M
+uUH9r7lH/DCb0+TxIBtxOnP7W02bz8gGJAxEVEqk6pjxxOYqfS9/uBrrAY8P21Y9
+PFLdeHzEdYemq3il+4S7OU3uNUuAYijxmCRs7JQxZ9puA0iaTME9gK1yikzsLtVZ
+f+9osk2nYgfXvlL0AiYabd5cU2GNW33TkdDMNBsB7lx77J9erVLZpPKNo4vgHA7b
+owrDaYe0AgcZm79fvmR0RdtIZI91MouEhkdhaPiXmypmszjR/M0Ot3Y+oU/ks+yV
+Sle0S0h4V8wJRJYG/9VVurm8012ke2U3EGFlVnSv/IYtpssC+U4McRCmakKCrGU7
+OhL5JKBQN/DFTu4pV39IQlLLhg3wzA2FSkyIL5gEbS6sP9GTPo5LlNm2nYfJQX9A
+sHKSrfh68dvjSNExxi/8hdmFnnRwbAnUCI/WObGOkKdheOfdQ1AAHtLO7G65X1Cx
+RctbAJWa93M+iRUN6qnB+vIbPPnI1Mc7i6mPYzgtPrM9bYqEZz69pQtHcGTfxOrU
+tm+/h36CRzJBfXodBZbwQ9mZAzfkKdlArlZYIeBUw3ORQnQ7UlJgG8KsZpUhTxCc
+gvMoExtlvkXcYLRUBFfZWyOi6FePzQjuCK1w58OdweJgXprEAWSvyxhmVdg4jUpX
+MYKE0tZI9xwujyWjACO0myYqTdmsqyds+BgfBn96XiA9OFUH2C0/GAomhNs8uPSO
+T3Gt7Ld/FByxEVrtl9A37X6bAwZO01j5tHmdXFPmMVep0R8zsWtPn3RyGAjcgcq6
+50wJRwhvofdI7wilZ0KUBsAaPj3MK52cRyD19VXKNNwt2bLDV6gcWQ8+QEMusxfp
+1Dc9N9DSs+w3lGsFfpoeQ53/fXcVNJm6Bv89bH9anLGYdCdRGvZsvw+xRuglykqb
+xLtL2lB6wzlRFREJoWTzCVsdpIZ8znPmk1cB0wDlbMeu6sddHmv+6fpyuvQfQmdj
+D8WLRTuyxax94TmBlhJCFYxmO/y4Ivlx5C60GIRTkHpBYL/M0RjrbIszXEqcogzU
+bdwjLIhdEnpJ5vy0uXwhltce8BDpenmHE7y1kHvPBiUG3vB7AIXqhohFsJU3AYUj
+d1TvFKS2AsizUTLuq0Ydbnz3AxMfmnZe8qYkNu2zRygL2xTa58f/MwsHKakk3OmS
+9JFZLrkkVWZKXoARctuahYtWBAsykaWVNnB6zGcdX1MGVccl930Z6QWHyydtZpQc
+ivNdEGdGv9B0K7/ngNdVgD5Wd29AMMFnS8+55mLfRZDCjUmshSySaf6Ein4HD9Hr
+vk6dJvBPjnI5UjeUPjmH+wcZKIjLHW/aV/6/zoxzBh61rWFlr/daec+CFZE/+epr
+LRRYSmv8oY47fF4duDDhoexcvP/CH+A2Hr40OfciL4vKy3nuUDCNa59xO9JWv4NL
+n3MQypC9bcaVPkXa7TK3ECq1Jgv8gwfdh5/ovG5OdZA4uIcO+aqcskt/PD252c63
+0Znww3RXXf46KT4GdKO5A377ixkUMkznnCMvottmkPxjnhQjAsQg3bJeQk8EoX8f
+Pq0If4i7SRBSDtb2OH1pPmk0RVPtxlRDTVj3vS3Lci4xADFgC09n9nIvPO/55aau
+O6StbJtLmpubS5giuDH3uftwuyRiLqm3gtbSKPdoTk+dJhHXbbpBknL4XYTPxSsR
+IIaRds6w30vf7/IscyunMcquJlsO929SSa93UevKEIZbqbV9oGIqwkiUMdVZK09g
+rW0F//Ts4a5nYdEQth/fq3JnwqeHvvUfKdasK4TtrTnUBX7qZk/K3Y1fZwjKdd/8
+t9t1z7Kb2d9hWwtY7xP8liDluVFTsq8NM54ZC2218X5ViWz1yFmF2LXvRixsmYJv
+Tz8lUUnC2B/Etm1kkU4zrYK0/L77EikKVl+B7BXfEqx6ow41j7e1YZYaqmZ9mph+
+UieSdzqVYxhPwT25DrkU3r74iS28gKsbFhUaNklaFOO5iDWsKgBXT+wdZqlYQ6Fo
+oPe66025iJMwK8t+d53jEduHezHO2sTMAuf2hpdaZo7+rP/hRTReAR6CmI7nkWhP
+z5Kno9S+XhiSP+WTSpsoA4ubx0T94mL8NOVvSZA76TZ3ObVAP5VI/bwv6Grighor
+Kpsjt7dhSJRv+RHv95sAWBeW1Fgv8XOPSAZOmpJV2qc3x3Qmj0MXIR+7+3GlUr8+
+Dit3CE1hwtxgOW0tc8kuBTfQD+wNSa9r0eUyFscEBBljpEVbLjgjVdNv4Hc+fsbT
+g1JzZuUIDQZoEO2xLjxD+I7vLZKQa0J1JeZ7O+NqmSxsvSnwCWtJEWNMMxYNfwsP
+rdj1zPLqn3rzSBqhroNbaDGn86BTwIqfhr+AKbvevxS6bI8IbyKm9u3BFr9cuawx
+Sp1QM3NtqNStV67qR4A6U/ZyPUJdO1bxo8F3oRmJqOt7Jc93rFgkhBJ2+eMtrA75
+Om5tB9LBVSl5U5yLP0COO1QE5pqk5yuhJLT9Dyss8bWDRbSWKj83e4YXhPnq71Bm
+001czylLVNUlDc69Tf7FXjtIxh2yjvOT3zeLBPXOjU0it+gAma4vgrh8/mMXnNiq
+OLsVow8aKqm+Ofd6m13K5riDFgXgNI9lbvPKUSWlEqDMEqXk1oAqD4Nb5NTGSFpQ
+Q4G+cHAxJCu7vcXBaZnP8uMP5IAkdg5jIPvvMRwg/aqkl/KbL98oYZ5+1xrOMuKA
+LT1uCJ4MMB0lWsa1He4jPe8LneSupw7vAXlbo2VzcOI6oCSY5hV+cGQRY+LjW81q
+Cu5nLq8bwgnZMSlPmwr0YrKmvh8YKyGOrmTadxykC5IC+XbrLDsw2Jd9mLIjUQ/V
+4ibjeb+e0QGob22WOplCLnHGW/SnYei8KG1dxs/ahS+8vQdrI880ZJx2QJnrz0Ej
+ux6tKv4mvUkqYA5hlTFeT3PTr54yA+YLcCLMfBDx4ykPQnYUBj7ONHuNSUYt1CJy
+faZ7cWAbhgH+wlTFdVBVeW5D4FRbM8dMTPXyfC5ygwTJOiDu3vQKyyDkmiX7sEaC
+P1JN2V55uacyR8ZAG5+Mlc4ZMx83kAIZZXTCdqa1EX8yda31FI2rDHmvW/82bmjL
+pvI4Nnn9+zzJtDVCJ0B2VAZ3Edov5GzPikm3un4+mvyhUZpH4sbT0+VhPCsr1+zn
+bDJyNw4AswxaaJKh2+7wBiU6h+9TP/lI8SAJHtZL7zHBH8tD10ptksLRWDs9vYqp
+/3T86S2vxJL5DvLFJSAZrYOE3InS+keGmTMCdAl9I8zIworC/8uQp0N8ESebEVjA
+aHotBk59lj/OW4JZ3tQkcdQWkpnUfW/x9xE2wthacHlRzYDDsFByjEqkQr0MU8VF
+EGij9RCC97zyFrhv0xJm1C6wX0pcuEcuPTNBf38WyBTIfmVHHz/I5YKk5cdWG7Hq
+fmccV5GKrs2BseR683HM+/u50sq0km9UrqjgFR1DjfDoRKp0guP9PqkJAnwG2nv1
+hmNtXumzkF0otP5LDKLJ84MGP8Wnb006iEdD48Lra+clRAIIuLX4A0wRQjViDp7n
+OByI6ZcQd4DTMHnFPRvMkNMLYn13LghD6P9TTjQZ0KCOCwmc2TMCIhJlvzOYX6Cc
+wJZYLO1ltgfnHEuh8ijv0u3d/BUpsknYKBSJGUyMEZ9iUtbFPVfXBGSTi3gcWHtl
+IrM7wjswJwHWSvZKWUs+YWWJTwj0apG6ViGllwOAqR9C48uLKgFWPbMoTpolnp69
+eiij5ZHxB0i7SI80D+r65b+fqaFzVIJXVEI0zu/mIilbYBnGkhLI/Naw1m2e1qVJ
+mi1JBjXLAT3pEJDh8b3Lpgw=
+-----END PKCS7-----
diff --git a/vectors/cryptography_vectors/pkcs7/isrg.pem b/vectors/cryptography_vectors/pkcs7/isrg.pem
new file mode 100644
index 0000000..63698aa
--- /dev/null
+++ b/vectors/cryptography_vectors/pkcs7/isrg.pem
@@ -0,0 +1,33 @@
+-----BEGIN PKCS7-----
+MIIFngYJKoZIhvcNAQcCoIIFjzCCBYsCAQExADAPBgkqhkiG9w0BBwGgAgQAoIIF
+bzCCBWswggNToAMCAQICEQCCEM+w0kDjWURj4LtjgosAMA0GCSqGSIb3DQEBCwUA
+ME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5ldCBTZWN1cml0eSBSZXNl
+YXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgxMB4XDTE1MDYwNDExMDQz
+OFoXDTM1MDYwNDExMDQzOFowTzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVy
+bmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3Qg
+WDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1co
+HIe+3LffOJCMbjzmV6B493XCov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZsh
+ftEzPLpI9d1537O4/xLxIZpLwYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+
+lAOf00eXfJlII1PoOK5PCm+DLtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vr
+Fk/CjhFLfs8L6P+1dy70sntK4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6s
+hweU9GNx7C7ib1uYgeGJXDR5bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98fl
+AgeYjzYIlefiN5YNNnWe+w5ysR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81
+LygXbNKYwagJZHduRze6zqxZXmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1
+pzpRboY7nn1ypxIFeFntPlF4FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0
+544fAQjQMNRbcTa0B7rBMDBcSLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K2
+8Kh8hjtGqEgqiNx2mna/H2qlPRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdw
+iK1O5tmLOsbdJ1Fu/7xk9TNDTwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUebRZ5nu25eQBc4AIiMgaWPbpm24wDQYJ
+KoZIhvcNAQELBQADggIBAFUfWKm8sqhQ0Ayx2BppICcpCKxhdVyKbviC5Wkv1fZW
+S7m4cxBZ0yGXfudMcfuy0mCtOagL6hchVoXxUA5Z687gWem6yRXvhp2PhID25OmR
+kNwXm2IbRfBmldJ8b8LqO+8fz8vWrifxqbDIrv19fpr6IgTr/9l/6pErIrEXDo/y
+ijRbWNj8AclUubgmzIqIM4lMLYQ8gt/ullcFuiy798S3x047gr4xyCJzc5LRwoCk
+OTkQMyOCTDyfhrJVmB2+KYaMIpue4ms7VzqCcE3cCceJywoHTWzoXY7J786rx7u1
+K05F1krQJszlcsoIaqWV4xWh96TtySxfpfv/rCgCLr7Xe7vjcXuQFtMHXkZTfDcH
+QozTxJac1Zm1KuCVGoBIrkw5B87MR6RSlSu6uPut0jNTfeUdTW3VobHHQm/mQCc1
+XKMotweN540zkOcjn/tQnHlsRtW0FbOWbn6bDJY6uFItP9Zb4fsIwoT+JKijidqs
+auEYKrGoQ2Fb0x/cO4128i3ojXXfFzNsPVP7e8tBX//cotBhOOGWuKxdizfXddUz
+wJkRrp1BwXJ1hL4CQUJfZyRIlNGbJ74HP7m4T4F0UeF6t+2dI+K+4NUoBBM8MQOe
+3Xpsj8YHGMZ/3keOPyieBAbPpVQ0d73siZvpF0PfW9tf/o4eV6LNQJ1+YiLa3hgn
+MQA=
+-----END PKCS7-----
diff --git a/vectors/cryptography_vectors/poly1305/rfc7539.txt b/vectors/cryptography_vectors/poly1305/rfc7539.txt
new file mode 100644
index 0000000..9ad13a5
--- /dev/null
+++ b/vectors/cryptography_vectors/poly1305/rfc7539.txt
@@ -0,0 +1,56 @@
+# These vectors converted into NIST form from RFC 7539
+
+COUNT = 0
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+MSG = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+TAG = 00000000000000000000000000000000
+
+COUNT = 1
+KEY = 0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e
+MSG = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f
+TAG = 36e5f6b5c5e06070f0efca96227a863e
+
+COUNT = 2
+KEY = 36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000
+MSG = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f
+TAG = f3477e7cd95417af89a6b8794c310cf0
+
+COUNT = 3
+KEY = 1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0
+MSG = 2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e642067696d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e6420746865206d6f6d65207261746873206f757467726162652e
+TAG = 4541669a7eaaee61e708dc7cbcc5eb62
+
+COUNT = 4
+KEY = 0200000000000000000000000000000000000000000000000000000000000000
+MSG = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+TAG = 03000000000000000000000000000000
+
+COUNT = 5
+KEY = 02000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+MSG = 02000000000000000000000000000000
+TAG = 03000000000000000000000000000000
+
+COUNT = 6
+KEY = 0100000000000000000000000000000000000000000000000000000000000000
+MSG = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11000000000000000000000000000000
+TAG = 05000000000000000000000000000000
+
+COUNT = 7
+KEY = 0100000000000000000000000000000000000000000000000000000000000000
+MSG = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE01010101010101010101010101010101
+TAG = 00000000000000000000000000000000
+
+COUNT = 8
+KEY = 0200000000000000000000000000000000000000000000000000000000000000
+MSG = FDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+TAG = FAFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+
+COUNT = 9
+KEY = 0100000000000000040000000000000000000000000000000000000000000000
+MSG = E33594D7505E43B900000000000000003394D7505E4379CD01000000000000000000000000000000000000000000000001000000000000000000000000000000
+TAG = 14000000000000005500000000000000
+
+COUNT = 10
+KEY = 0100000000000000040000000000000000000000000000000000000000000000
+MSG = E33594D7505E43B900000000000000003394D7505E4379CD010000000000000000000000000000000000000000000000
+TAG = 13000000000000000000000000000000
diff --git a/vectors/cryptography_vectors/x509/custom/ca/rsa_ca.pem b/vectors/cryptography_vectors/x509/custom/ca/rsa_ca.pem
new file mode 100644
index 0000000..089bcce
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/custom/ca/rsa_ca.pem
@@ -0,0 +1,28 @@
+-----BEGIN CERTIFICATE-----
+MIIExzCCAq+gAwIBAgIJAOcS06ClbtbJMA0GCSqGSIb3DQEBCwUAMBoxGDAWBgNV
+BAMMD2NyeXB0b2dyYXBoeSBDQTAeFw0yMDA5MTQyMTQwNDJaFw00ODAxMzEyMTQw
+NDJaMBoxGDAWBgNVBAMMD2NyeXB0b2dyYXBoeSBDQTCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBANBIheRc1HT4MzV5GvUbDk9CFU6DTomRApNqRmizriRq
+m6OY4Ht3d71BXog6/IBkqAnZ4/XJQ40G4sVDb52k11oPvfJ/F5pc+6UqPBL+QGzY
+GkJoubAqXFpI6ow0qayFNQLv0T9o4yh0QQOoGvgCmv91qmitLrZNXu4U9S76G+Di
+GST+QyMkMxj+VsGRsRRBufV1urcnvFWjU6Q2+cr2cp0mMAG96NTyIskYiJ8vL03W
+z4DX4klO4X47fPmDnU/OMn4SbvMZ896j1L0J04S+uVThTkxQWcFcqXhX5qM8kzcj
+JUmybFlbf150j3WiucW48K/j7fJ0x9q3iUo4Gva0coScglJWcgo/BBCwFDw8NVba
+7npxSRMiaS3qTv0dEFcRnvByc+7hyGxxlWdTE9tHisUI1eZVk9P9ziqNOZKscY8Z
+X1+/C4M9X69Y7A8I74F5dO27IRycEgOrSo2z1NhfSwbqJr9a2TBtRsFinn8rjKBI
+zNn0E5p9jO1WjxtkcjHfXXpLN8FFMvoYI9l/K+ZWDm9sboaF8jrgozSc004AFemA
+H79mmCGVRKXn1vDAo4DLC6p3NiBFYQcYbW9V+beGD6srsF6xJtuY/UwtPROLWSzu
+CCrZ/4BlmpNsR0ehIFFvzEKjX6rR2yp3YKlguDbMBMKMpfSGxAFwcZ7OiaxR20UH
+AgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBADSveDS4
+y2V/N6Li2n9ChGNdCMr/45M0cl+GpL55aA36AWYMRLv0wip7MWV3yOj4mkjGBlTE
+awKHH1FtetsE6B4a7M2hHhOXyXE60uUdptEx6ckGrJ1iyqu5cQUX1P+VnXbmOxfF
+bl+Ugzjbgirx239rA4ezkDRuOvKcCbDOFV/gw3ZHfJ/IQeRXIQRl/y51wcnFUvFM
+JEESYiijeDbEcY8r1/phmVQL0CO7WLMmTxlFj4X/TR3MTZWJQIap9GiLs5+n3QiO
+jsZ3GuFOomB8oTebYkXniwbNu5hgLP/seRQzGA7B9VDZryAhCtvGgjtQh0eW2Qxt
+sgmDJGOPKnKT3O5U0v3+IPLEYpe8JSzgAhhh6H1rAJRUNwP2gRcO4eOUJSkdl218
+fRNT0ILzosuWxwprER9ciMQF8q0JJKMhcfHRMH0S5mWVJAIkj68KY05oCy2zNyYa
+oruopKSWXe0Bzr40znm40P7xIkui2BGQMlDPpbCaEfLsLqyctfbdmMlxac/QgIfY
+TltrbqmI3MNy5uqGViGFpWPCB+kD8EsJF9nlKJXlu/i55qgUr/2/2CdeWlZDBP8A
+1fdzmpYpWnwhE0KobzLS2z3AwDxiY/RSWUfypLZA0K/lpaEtYB6UHMDZ0/8WqgZV
+gNucCuty0cA4Kf7eX1TlAKVwH8hTkVmJc2rX
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/custom/ca/rsa_key.pem b/vectors/cryptography_vectors/x509/custom/ca/rsa_key.pem
new file mode 100644
index 0000000..97e39a5
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/custom/ca/rsa_key.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDQSIXkXNR0+DM1
+eRr1Gw5PQhVOg06JkQKTakZos64kapujmOB7d3e9QV6IOvyAZKgJ2eP1yUONBuLF
+Q2+dpNdaD73yfxeaXPulKjwS/kBs2BpCaLmwKlxaSOqMNKmshTUC79E/aOModEED
+qBr4Apr/daporS62TV7uFPUu+hvg4hkk/kMjJDMY/lbBkbEUQbn1dbq3J7xVo1Ok
+NvnK9nKdJjABvejU8iLJGIifLy9N1s+A1+JJTuF+O3z5g51PzjJ+Em7zGfPeo9S9
+CdOEvrlU4U5MUFnBXKl4V+ajPJM3IyVJsmxZW39edI91ornFuPCv4+3ydMfat4lK
+OBr2tHKEnIJSVnIKPwQQsBQ8PDVW2u56cUkTImkt6k79HRBXEZ7wcnPu4chscZVn
+UxPbR4rFCNXmVZPT/c4qjTmSrHGPGV9fvwuDPV+vWOwPCO+BeXTtuyEcnBIDq0qN
+s9TYX0sG6ia/WtkwbUbBYp5/K4ygSMzZ9BOafYztVo8bZHIx3116SzfBRTL6GCPZ
+fyvmVg5vbG6GhfI64KM0nNNOABXpgB+/ZpghlUSl59bwwKOAywuqdzYgRWEHGG1v
+Vfm3hg+rK7BesSbbmP1MLT0Ti1ks7ggq2f+AZZqTbEdHoSBRb8xCo1+q0dsqd2Cp
+YLg2zATCjKX0hsQBcHGezomsUdtFBwIDAQABAoICAQDH6YQRvwPwzTWhkn7MWU6v
+xjbbJ+7e3T9CrNOttSBlNanzKU31U6KrFS4dxbgLqBEde3Rwud/LYZuRSPu9rLVC
+bS+crF3EPJEQY2xLspu1nOn/abMoolAIHEp7jiR5QVWzXulRWmQFtSed0eEowJ9y
+qMaKOAdI1RRToev/TfIqM/l8Z0ubVChzSdONcUAsuDU7ouc22r3K2Lv0Nwwkwc0a
+hse3NEdg9JNsvs6LM2fM52w9N3ircjm+xmxatPft3HTcSucREIzg2hDb7K2HkOQj
+0ykq2Eh97ml+56eocADBAEvO46FZVxf2WhxEBY8Xdz4VJMmDWJFmnZj5ksZWmrX6
+U5BfFY7DZvE2EpoZ5ph1Fm6dcXrJFkaZEyJLlzFKehXMipVenjCanIPpEEUvIz+p
+m0QVoNJRj/GcNyIEZ0BCXedBOUWU4XE1pG4r6oZqwUvcjsVrqXP5kbJMVybiS6Kd
+6T8ve+4qsn3ZvGRVKjInqf2WI0Wvum2sTF+4OAkYvFel9dKNjpYnnj4tLFc/EKWz
+9+pE/Zz5fMOyMD9qXM6bdVkPjWjy1vXmNW4qFCZljrb395hTvsAPMsO6bbAM+lu6
+YcdOAf8k7awTb79kPMrPcbCygyKSGN9C9T3a/Nhrbr3TPi9SD9hC5Q8bL9uSHcR2
+hgRQcApxsfDRrGwy2lheEQKCAQEA/Hrynao+k6sYtlDc/ueCjb323EzsuhOxPqUZ
+fKtGeFkJzKuaKTtymasvVpAAqJBEhTALrptGWlJQ0Y/EVaPpZ9pmk791EWNXdXsX
+wwufbHxm6K9aOeogev8cd+B/9wUAQPQVotyRzCcOfbVe7t81cBNktqam5Zb9Y4Zr
+qu63gBB1UttdmIF5qitl3JcFztlBjiza2UrqgVdKE+d9vLR84IBRy3dyQIOi6C1c
+y37GNgObjx8ZcUVV54/KgvoVvDkvN6TEbUdC9eQz7FW7DA7MMVqyDvWZrSjBzVhK
+2bTrd+Pi6S4n/ETvA6XRufHC8af4bdE2hzuq5VZO1kkgH37djwKCAQEA0y/YU0b4
+vCYpZ1MNhBFI6J9346DHD55Zu5dWFRqNkC0PiO6xEMUaUMbG4gxkiQPNT5WvddQs
+EbRQTnd4FFdqB7XWoH+wERN7zjbT+BZVrHVC4gxEEy33s5oXGn7/ATxaowo7I4oq
+15MwgZu3hBNxVUtuePZ6D9/ePNGOGOUtdMRrusmVX7gZEXxwvlLJXyVepl2V4JV1
+otI8EZCcoRhSfeYNEs4VhN0WmfMSV7ge0eFfVb6Lb+6PCcasYED8S0tBN2vjzvol
+zCMv8skPATm7SopqBDoBPcXCHwN/gUFXHf/lrvE6bbeX1ZMxnRYKdQLLNYyQK9cr
+nCUJXuNM21tVCQKCAQBapCkFwWDF0t8EVPOB78tG57QAUv2JsBgpzUvhHfwmqJCE
+Efc+ZkE2Oea8xOX3nhN7XUxUWxpewr6Q/XQW6smYpye8UzfMDkYPvylAtKN/Zwnq
+70kNEainf37Q6qAGJp14tCgwV89f44WoS7zRNQESQ2QczqeMNTCy0kdFDn6CU2ZL
+YMWxQopTNVFUaEOFhympySCoceTOmm/VxX22iXVrg6XZzgAOeTO69s4hoFm4eoMW
+Vqvjpmi4wT6K1w2GjWEOMPDz6ml3rX2WkxCbu5RDA7R4+mM5bzBkcBYvImyGliGY
+ZSGlx3mnbZhlkQ3Tg+IESt+wnRM1Uk7rT0VhCUKxAoIBABWYuPibM2iaRnWoiqNM
+2TXgyPPgRzsTqH2ElmsGEiACW6pXLohWf8Bu83u+ZLGWT/Kpjg3wqqkM1YGQuhjq
+b49mSxKSvECiy3BlLvwZ3J0MSNCxDG0hsEkPovk0r4NC1soBi9awlH0DMlyuve+l
+xVtBoYSBQC5LaICztWJaXXGpfJLXdo0ZWIbvQOBVuv4d5jYBMAiNgEAsW7Q4I6xd
+vmHdmsyngo/ZxCvuLZwG2jAAai1slPnXXY1UYeBeBO72PS8bu2o5LpBXsNmVMhGg
+A8U1rm3MOMBGbvmY8/sV4YDR4H0pch4yPja7HMHBtUQOCxXoz/2LvYv0RacMe5mb
+F3ECggEAWxQZnT8pObxKrISZpHSKi54VxuLYbemS63Tdr4HE/KuiFAvbM6AeZOki
+jbiMnqrCTOhJRS/i9HV78zSxRZZyVm961tnsjqMyaamX/S4yD7v3Vzu1mfsdVCa2
+Sl+JUUxsEgs/G3Fu6I/0TsCSn/HgNLM8b3f8TDkbpnOqKX165ddojXqSCfxjuYau
+Szih/+jF1dz2/zBye1ARkLRdY/SzlzGl0cVn8bfkE0YEde7wvQ624Biy7r9i1o40
+7cy/8EQBR2FcXpOAZ7UgOqgGLNhXnd4FPsX4ldKOf5De8FErQOFirJ8pCUxFGr0U
+fDWXtBuybAb5u+ZaVwHgqaaPCkKkVQ==
+-----END PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/x509/custom/crl_delta_crl_indicator.pem b/vectors/cryptography_vectors/x509/custom/crl_delta_crl_indicator.pem
index f49da4c..d919c37 100644
--- a/vectors/cryptography_vectors/x509/custom/crl_delta_crl_indicator.pem
+++ b/vectors/cryptography_vectors/x509/custom/crl_delta_crl_indicator.pem
@@ -1,11 +1,11 @@
 -----BEGIN X509 CRL-----
-MIIBfTBnAgEBMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMMEmNyeXB0b2dyYXBo
-eS5pbyBDQRcNMDIwMTAxMTIwMTAwWhcNMzAwMTAxMTIwMTAwWqAWMBQwEgYDVR0b
-BAsCCQCrVKmM6x8K0jANBgkqhkiG9w0BAQsFAAOCAQEAUEE3Z8rgIZYo1YK0wZ2X
-bz9NnnE/X1YZQZ/IO/mSsz/k2d5XhLwa53zMlvX7J3UFEjEp+82b+gCMvgpJzTBq
-a/XnifnA8lnFJmPiLB1JgRm2/GsXxkws3ziH5D/6yRdV3MDRQzRg610GayF+LfrF
-74kMns0a1TaOfRhw1APiDvJLngElvcutBS3/mgr+SPPdDgFJ++PSrWOdAw4vo4HH
-TTxduelWWDag2Bg0L90Td8Cdv57jgbCjSwWPSLqfwq674cDxotYABqtLg1Q5jeg2
-GIzEZqYXWvxMc87pQLRwrxG2+U4p+hDpx3TTIn2uyxDTihXvWKmiqzpOiXJKixe5
-Jw==
+MIIBlDB+AgEBMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMMEmNyeXB0b2dyYXBo
+eS5pbyBDQRcNMDIwMTAxMTIwMTAwWhcNMzAwMTAxMTIwMTAwWqAtMCswEgYDVR0U
+BAsCCQCrVKmM6x8K0zAVBgNVHRsBAf8ECwIJAKtUqYzrHwrSMA0GCSqGSIb3DQEB
+CwUAA4IBAQBQQTdnyuAhlijVgrTBnZdvP02ecT9fVhlBn8g7+ZKzP+TZ3leEvBrn
+fMyW9fsndQUSMSn7zZv6AIy+CknNMGpr9eeJ+cDyWcUmY+IsHUmBGbb8axfGTCzf
+OIfkP/rJF1XcwNFDNGDrXQZrIX4t+sXviQyezRrVNo59GHDUA+IO8kueASW9y60F
+Lf+aCv5I890OAUn749KtY50DDi+jgcdNPF256VZYNqDYGDQv3RN3wJ2/nuOBsKNL
+BY9Iup/CrrvhwPGi1gAGq0uDVDmN6DYYjMRmphda/ExzzulAtHCvEbb5Tin6EOnH
+dNMifa7LENOKFe9YqaKrOk6JckqLF7kn
 -----END X509 CRL-----
diff --git a/vectors/cryptography_vectors/x509/custom/negative_serial.pem b/vectors/cryptography_vectors/x509/custom/negative_serial.pem
new file mode 100644
index 0000000..0994f9a
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/custom/negative_serial.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIELDCCAxSgAwIBAgIF+86ZbBMwDQYJKoZIhvcNAQELBQAwUjELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDU1vdGhlciBOYXR1cmUxEzARBgNVBAsTCkV2ZXJ5dGhpbmcx
+FjAUBgNVBAMTDU1vdGhlciBOYXR1cmUwHhcNMTYwNzA2MTgzNDA2WhcNMTYwOTE4
+MTgzNDA2WjCBmTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkZMMRQwEgYDVQQHEwtU
+YWxsYWhhc3NlZTEcMBoGA1UECRMTMzIxMCBIb2xseSBNaWxsIFJ1bjEOMAwGA1UE
+ERMFMzAwNjIxGDAWBgNVBAoTD0V4dHJlbWUgRGlzY29yZDEOMAwGA1UECxMFQ2hh
+b3MxDzANBgNVBAMTBmdvdi51czCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAMu6VH/JvcG/foNel5R3NHz/OeI9fqHyoPB6d/wQ1k/aVGNotSzVaDCJPY3J
+xmr1KCnNjzGmViuaLXyZWZEMum2R8D0+LX1PHBQl2vbrXSOMDu97c323QOdTUwMY
+C2LmaFP3fa5SV5Q+8+4f/B97wXExOjp1z5z7VafYj2MoY72GitoSfJ/LrkKEksey
+fTflVxKEvZqW3wUN6F2Kj4Jo1N45Ym+lIrz/VQKDOSpc/p0dJ1PghDZZ2d2b3iuj
+5rCMTw9533WS3wueYfn70jJY9DKoFj9Ly6AG0AB2o7cqTv8j+3slVfAR3ufwgyx2
+ckUDBWCZaZdnhRxaj/G9MMYGEV0CAwEAAaOBwDCBvTAPBgNVHRMBAf8EBTADAQH/
+MA4GA1UdIwQHMAWAAwECAzANBgNVHQ4EBgQEBAMCATAbBgNVHREEFDASgggqLmdv
+di51c4IGZ292LnVzMAsGA1UdDwQEAwIBhjAgBgNVHSUBAf8EFjAUBggrBgEFBQcD
+AQYIKwYBBQUHAwIwPwYDVR0fAQH/BDUwMzAxoC+gLYYraHR0cDovL2NybC5zdGFy
+ZmllbGR0ZWNoLmNvbS9zZmlnMnMxLTE3LmNybDANBgkqhkiG9w0BAQsFAAOCAQEA
+bfqYztTkJPRPAJ1WItmU3RZIGRx1VkCABouAor6tVH6wGVCwWgaG8li6AujHMfYv
+y6QUPhhIyNjTe21ne72BY1XXd9haGdMwXtUCNfeGBXKsR9EN0kDyOAXGZWj3Fqpu
+S9WjluPAjQWHFoRwlQBSxCVuRgIrjXhJndvW9ySAaI51epRAr5kwylvTD7qy363C
+xDANx5XVFEktclI25DSrxmiJyawVGFjnwaYBFTe2ZINoZvs68EEl1b18+VGF21e9
+BAQGlcsIfbDAAEQFJ+5A+o8zy9M7CVsNVgw3TRJbjVTZSEg5PAEX+3C5V6wzrQi1
+nqzaNa/5DxGWILelZclgvA==
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/custom/rsa_pss.pem b/vectors/cryptography_vectors/x509/custom/rsa_pss.pem
new file mode 100644
index 0000000..cdbc34d
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/custom/rsa_pss.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDLTCCAhWgAwIBAgIUCD6ZpVYd5vCgzRh5ZIqYupE2VKIwDQYJKoZIhvcNAQEK
+MAAwJTESMBAGA1UECgwJYm9vdHN0cmFwMQ8wDQYDVQQDDAZyb290Y2EwHhcNMTYw
+MTAxMDAwMDAwWhcNNDAwMTAxMDAwMDAwWjAlMRIwEAYDVQQKDAlib290c3RyYXAx
+DzANBgNVBAMMBnJvb3RjYTCCAVYwQQYJKoZIhvcNAQEKMDSgDzANBglghkgBZQME
+AgEFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgEFAKIDAgEgA4IBDwAwggEK
+AoIBAQCuXwLURTDREKWTeBxUQWQvj/hDVc0+PruZtBF5voNAZCjKSOKHFLasmCDw
+JuEHjj7ZHDF1JWZVGUbz3p5P+TiFmO/c1Wgb5IyAxdiDUGZvSVX3uC/X8EG/1MQz
+bwcDpqiadoIjL59jUJ0g2BJnx81NvpNgpe0rmK7aU52sPKJme31Ttd/lO8VJ3Mps
+lzpH0qzDJEcE3+lBF+AOJf2XDbPTFlbuPvDZHE5tVmdYC2IOad8U0Q/FLOhpMFOX
+j0n6tKf+Z14+7+xu7RV3gj/NMm0CXWG3ibTSOSrbyvreI0dHgZL57RdqCSE9scjA
+/1tD0a7UINhPBDZc6HaUqQUsQCPhAgMBAAGjITAfMB0GA1UdDgQWBBSpiALqV+wo
+zwcvMEvwYFLKe/vDPzANBgkqhkiG9w0BAQowAAOCAQEAEdp7sFyQA9g3Vk1KsrAB
+UFKqEe1a0azE4TRz2SRktRCswgv7iae0CiBGtPrzBNS6MlketixTfF1npEi7wuDn
+/00XRdgHCBIRGvemATx8oSP4qVrHUud2y/DLZOZBGYiasSHHgybsnikFZppGFp7m
+1D3Tti+GEsaANwRH5GW7h8f9hTMluwXlnNwyT/83yKq9Uih0eFEWHtf8hFswpCEK
+4swEBwBHUiCZs1O702H36xEnoayOWnIWAkV8ZccEjfbCHs+rnU+nGI5UfXg86VRb
+9iqcII7xyzPxb/HZRBusI9Uu/xiiqLjWqmx/ZMeadhiQndCoOj2yR8YT+G1BqcLa
+pA==
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/custom/sia.pem b/vectors/cryptography_vectors/x509/custom/sia.pem
new file mode 100644
index 0000000..f745674
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/custom/sia.pem
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC7TCCAdWgAwIBAgICAwkwDQYJKoZIhvcNAQELBQAwDTELMAkGA1UEBhMCVVMw
+HhcNMTUwMTAxMDAwMDAwWhcNNDAwMTAxMDAwMDAwWjANMQswCQYDVQQGEwJVUzCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMF6/H53R0yqWqgwNhWKP/v3
+tSFoUboiMOXWq/zBxs/vWekj6hMwvFk7c4Aqtgim5KMwZSOjEWulqjlmFFF04Tts
+Sem3gGLkSdcu+xD9SekfoIuW0FHngun1q8W1pveYSCetuOc9oA8isu/c23bqtG7a
+2Y7WVmJ0P9xsDjNqXQzbqn3CnlNjXiTIelssQhWWgGPN62ipcrq7wePP8A+5qA43
+Kk0MLJINHozuMzzkcNwugUWtsFvymu4dJPFB6Mx4SYnFh/xvus2Xnz8hY8HXKZs2
+W8cv/ihI6Weu0eSNzFFbOlDtTeBP0FOEbKEKIjsQzIQcyA/evuRPMRTBPohq9YMC
+AwEAAaNXMFUwUwYIKwYBBQUHAQsERzBFMCEGCCsGAQUFBzAFhhVodHRwczovL215
+LmNhLmlzc3Vlci8wIAYDiDcHhhlnb3BoZXI6Ly9pbmZvLW1hYy1hcmNoaXZlMA0G
+CSqGSIb3DQEBCwUAA4IBAQB4AdYx02aXDJURPbZNi3j7FnK3LRVvJcq8vRHaG9b4
+soD/7qA8RJX11WTFNDY7g5OQhYT+WBc8OUinJaqJOPvEzgp5Prgq5AlAtcImvNX7
+dI3lr9esZ5gBWbsMK9saNEERhEZDUCSYW/GRMN4yxdUgTDPsfNr8N6bwfnGRR0xM
+EBr+p+fT1xth4uren7J/edYrY9a171y6bMdZQ1iVnFH2dFO25D+3k9sM6FRWWsWu
+mmrcg79QAl6jqC/6SkqVzpBPzi7dgGYluaKJjREC8e/cMcpphW1TP+8rZ161BmDk
+hk5/PrWguFuguWUyEkPH5oqFqoZuqeM0fULxHh2JiqOx
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/ed25519/ed25519-rfc8410.pem b/vectors/cryptography_vectors/x509/ed25519/ed25519-rfc8410.pem
new file mode 100644
index 0000000..3f4b5b2
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/ed25519/ed25519-rfc8410.pem
@@ -0,0 +1,9 @@
+-----BEGIN CERTIFICATE-----
+MIIBLDCB36ADAgECAghWAUdKKo3DMDAFBgMrZXAwGTEXMBUGA1UEAwwOSUVURiBUZX
+N0IERlbW8wHhcNMTYwODAxMTIxOTI0WhcNNDAxMjMxMjM1OTU5WjAZMRcwFQYDVQQD
+DA5JRVRGIFRlc3QgRGVtbzAqMAUGAytlbgMhAIUg8AmJMKdUdIt93LQ+91oNvzoNJj
+ga9OukqY6qm05qo0UwQzAPBgNVHRMBAf8EBTADAQEAMA4GA1UdDwEBAAQEAwIDCDAg
+BgNVHQ4BAQAEFgQUmx9e7e0EM4Xk97xiPFl1uQvIuzswBQYDK2VwA0EAryMB/t3J5v
+/BzKc9dNZIpDmAgs3babFOTQbs+BolzlDUwsPrdGxO3YNGhW7Ibz3OGhhlxXrCe1Cg
+w1AH9efZBw==
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/ed25519/root-ed25519.pem b/vectors/cryptography_vectors/x509/ed25519/root-ed25519.pem
new file mode 100644
index 0000000..e509d54
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/ed25519/root-ed25519.pem
@@ -0,0 +1,9 @@
+-----BEGIN CERTIFICATE-----
+MIIBODCB66ADAgECAgkAhPEIPRzjLZUwBQYDK2VwMBkxFzAVBgNVBAMMDklFVEYg
+VGVzdCBEZW1vMB4XDTE3MDQxOTIxMzYzOVoXDTQxMDIxMjIxMzYzOVowGTEXMBUG
+A1UEAwwOSUVURiBUZXN0IERlbW8wKjAFBgMrZXADIQAZv0QJaYTN/oVBusFn3DuW
+yFCGqjC2tssMXDitcDFm4aNQME4wHQYDVR0OBBYEFKKMwfhuWWDT4DrnXJYsl6jU
+SCk8MB8GA1UdIwQYMBaAFKKMwfhuWWDT4DrnXJYsl6jUSCk8MAwGA1UdEwQFMAMB
+Af8wBQYDK2VwA0EAa6iEoQZBWB1MhCzASv5HuFM7fR5Nz2/KM7GxYjQWsfvK2Ds1
+jaPSG7Lx4uywIndMafp5CoPoFr6yLBkt+NZLAg==
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/ed25519/server-ed25519-cert.pem b/vectors/cryptography_vectors/x509/ed25519/server-ed25519-cert.pem
new file mode 100644
index 0000000..729ccfb
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/ed25519/server-ed25519-cert.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICHTCCAQWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290
+IENBMCAXDTE3MDYxNDIzMzExOVoYDzIxMTcwNjE1MjMzMTE5WjASMRAwDgYDVQQD
+DAdFZDI1NTE5MCowBQYDK2VwAyEACkEMj+SRLjZSth3SIrG013cyYVN9frrVnfbN
+M2IqaT6jdjB0MB0GA1UdDgQWBBQqd22ipNHF0d+yJjFDgI/Jruq3rjAfBgNVHSME
+GDAWgBRwfy6ug2hZmAQjKs3rPhfNJN0BSTAJBgNVHRMEAjAAMBMGA1UdJQQMMAoG
+CCsGAQUFBwMBMBIGA1UdEQQLMAmCB0VkMjU1MTkwDQYJKoZIhvcNAQELBQADggEB
+AIdNMPRa2sgUW/qtCBWxmi0iVRoazl5pjU35cRl/ahBpI4pL5+fDVYuBzSOgEh7W
+6FUVix9mGvY9CK3ZkqrXCGRKeWnKrmdql5jrra5Qew43B+aZqa63639TGWqtm7Rk
+rWT14P7gma4K9Ea8eiXcT5NJ8sT7D2BOL0sL2alUmRT+k3YDUxiih7AiTkpo7f2Q
+x5l9f8qoRb6Skec+kuMQ4hIjBIe/3C+j4nqq9kDkJs8+VEaW7+7shSQzv0tnzBOl
+v5ty89x7LYAbGKvZNi8Z3814AWBWbYTskF0kW2/f6aZDpt239llYDazdErU1dEsS
+cc1gKHOG3zgz9wfih55M0dE=
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/ed448/root-ed448.pem b/vectors/cryptography_vectors/x509/ed448/root-ed448.pem
new file mode 100644
index 0000000..d1d4eaa
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/ed448/root-ed448.pem
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE-----
+MIIBgDCCAQCgAwIBAgICAcAwBQYDK2VxMBgxFjAUBgNVBAMMDUVkNDQ4IERlbW8g
+Q0EwIBcNMTkwODE1MTkzNzU2WhgPMjExOTA3MjIxOTM3NTZaMBgxFjAUBgNVBAMM
+DUVkNDQ4IERlbW8gQ0EwQzAFBgMrZXEDOgBf10SbWbRh/Sznh+xhatRqHaE0JIWn
+Dh+KDqddgOlneO3xJHabRscGG9Z4PfHlD2zR+hq+r+glYYCjUzBRMB0GA1UdDgQW
+BBRt4IpyNR7xrevKLNfx/aaRVK36TzAfBgNVHSMEGDAWgBRt4IpyNR7xrevKLNfx
+/aaRVK36TzAPBgNVHRMBAf8EBTADAQH/MAUGAytlcQNzAHx1CfZgc40PRGSiZTWC
+P8HQAFgAMwIh34cE4WSrb1m8fxv8/uMG0bIvIez/+PMx/ErKPMtyBC2+ACJCCL0Q
+In1OC28cIlpXIcQUFXamiGdg1Pd4NqAYl1BVNGWymHxf1AM/NNBPUhYxs1Qw1ape
+dJIjAA==
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/ed448/server-ed448-cert.pem b/vectors/cryptography_vectors/x509/ed448/server-ed448-cert.pem
new file mode 100644
index 0000000..740f275
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/ed448/server-ed448-cert.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICHTCCAQWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290
+IENBMCAXDTE4MDIyNzE1MDcxM1oYDzIxMTgwMjI4MTUwNzEzWjAQMQ4wDAYDVQQD
+DAVFZDQ0ODBDMAUGAytlcQM6ABBicYlhG1s3AoG5BFmY3r50lJzjQoER4zwuieEe
+QTvKxLEV06vGh79UWO6yQ5FxqmxvM1F/Xw7RAKNfMF0wHQYDVR0OBBYEFAwa1L4m
+3pwA8+IEJ7K/4izrjJIHMB8GA1UdIwQYMBaAFHB/Lq6DaFmYBCMqzes+F80k3QFJ
+MAkGA1UdEwQCMAAwEAYDVR0RBAkwB4IFRWQ0NDgwDQYJKoZIhvcNAQELBQADggEB
+AAugH2aE6VvArnOVjKBtalqtHlx+NCC3+S65sdWc9A9sNgI1ZiN7dn76TKn5d0T7
+NqV8nY1rwQg6WPGrCD6Eh63qhotytqYIxltppb4MOUJcz/Zf0ZwhB5bUfwNB//Ih
+5aZT86FpXVuyMnwUTWPcISJqpZiBv95yzZFMpniHFvecvV445ly4TFW5y6VURh40
+Tg4tMgjPTE7ADw+dX4FvnTWY3blxT1GzGxGvqWW4HgP8dOETnjmAwCzN0nUVmH9s
+7ybHORcSljcpe0XH6L/K7mbI+r8mVLsAoIzUeDwUdKKJZ2uGEtdhQDmJBp4EjOXE
+3qIn3wEQQ6ax4NIwkZihdLI=
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/ocsp/ocsp-army.deps.mil-resp.der b/vectors/cryptography_vectors/x509/ocsp/ocsp-army.deps.mil-resp.der
new file mode 100644
index 0000000..08125f0
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/ocsp/ocsp-army.deps.mil-resp.der
Binary files differ
diff --git a/vectors/cryptography_vectors/x509/ocsp/resp-sct-extension.der b/vectors/cryptography_vectors/x509/ocsp/resp-sct-extension.der
new file mode 100644
index 0000000..8018e2b
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/ocsp/resp-sct-extension.der
Binary files differ
diff --git a/vectors/cryptography_vectors/x509/ocsp/resp-single-extension-reason.der b/vectors/cryptography_vectors/x509/ocsp/resp-single-extension-reason.der
new file mode 100644
index 0000000..f89060d
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/ocsp/resp-single-extension-reason.der
Binary files differ
diff --git a/vectors/cryptography_vectors/x509/requests/challenge-invalid.der b/vectors/cryptography_vectors/x509/requests/challenge-invalid.der
new file mode 100644
index 0000000..dfea502
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/requests/challenge-invalid.der
Binary files differ
diff --git a/vectors/cryptography_vectors/x509/requests/challenge-unstructured.pem b/vectors/cryptography_vectors/x509/requests/challenge-unstructured.pem
new file mode 100644
index 0000000..95a92ec
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/requests/challenge-unstructured.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICljCCAX4CAQAwFDESMBAGA1UEAwwJc29tZXRoaW5nMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEApDAVEIXi90VT6Q8sCYl0sdzZaxIW5fGtk5M8Vmoe
+iQbpWJtYZwQzOjOhgo9/+f/+Heg5gUI4+zUWyZMjh90KB5WrdTGO1x0yEUGjT15/
+VARFPmhyVniClEXPj4pANYVR00jMyvlLJuigKZbYR7VBTuE8oKOn2lu3eXuPFf6s
+8bLjSHLuTS7t13LDlrO1jh2RvSKeQDwQP7ZHWzjTASW3H6bZla8lSx/6Xhvk5aJQ
+JSMcEIYwPp7tP6+HV8E+FNjU19UZ3TsvGm60ZdoaCyFocgRFFju2wNSegmKzm00k
+bAum7RR4dcso58vrkUz5AbZchdQ3dh9rRsggxgV/F5lMkwIDAQABoD0wFQYJKoZI
+hvcNAQkHMQgMBmJlYXV0eTAkBgkqhkiG9w0BCQIxFwwVYW4gdW5zdHJ1Y3R1cmVk
+IGZpZWxkMA0GCSqGSIb3DQEBCwUAA4IBAQA3lwNp3HtDQjzkqxv9SvUCH6C9UEh0
+6+SWklP2ce2IWmoHHnfYW2SyPAhzR1q2gSu7IVZhM3WMEJRoiqN2ZFQed++0b91n
+LdUdCnDob8EFuX0AP7I4A9LI7G2bMS6mpzQBDXoo5hAlJV8I7Zq7NIby54bQiTgn
+B8cYopnmrLfCn1H8Su8oBgPNg3glOQSAkvZfqhHNTJyAnN+5+boFWpReAe8p/cfr
+kZh+fS8TcP7GbSLMnDlNwCAEIYRfAW7MVXJZ0l0tuDo7XdPImQgjjHYCk0tKPbeb
+LVyIAPNkMYLu7II79OOi8h1cZfU6wWwUIIhjMzjLpdZBPyhhGnUQzfuZ
+-----END CERTIFICATE REQUEST-----
+
diff --git a/vectors/cryptography_vectors/x509/requests/challenge.pem b/vectors/cryptography_vectors/x509/requests/challenge.pem
new file mode 100644
index 0000000..71ff39f
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/requests/challenge.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICcDCCAVgCAQAwDTELMAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQCb+ec0zYAYLzk/MDdDJYvzdvEO2ZUrBYM6z1r8NedwpJfxUWqC
+hvK1cpc9EbQeCwS1eooTIGoNveeCrwL+pWdmf1sh6gz7SsxdN/07nyhSM8M6Xkec
++tGrjyi1H/N1afwWXox3WcvBNbxu3Df5RKLDb0yt9aqhmJylbl/tbvgJesXymwmp
+Rc1vXL0fOedUtuAJ3xQ15M0pgLF8qDn4lySJz25x76pMYPeN5/a7x+SR/jj81kep
+VaVpuh/2hePV5uwUX3uWoj5sAkrBCifi4NPge0Npd6KeKVvXytLOymH/4+WvV719
+wCO+MyrkhpdHSakJDTIaQIxsqVeVVKdPLAPJAgMBAAGgHjAcBgkqhkiG9w0BCQcx
+DwwNY2hhbGxlbmdlIG1lITANBgkqhkiG9w0BAQsFAAOCAQEAMmgeSa8szbjPFD/4
+vcPBr/vBEROFGgL8mX3o5pF9gpr7nRjhLKBkgJvlRm6Ma3Xvdfc/r5Hp2ZBTA7sZ
+ZYhyeezGfCQN/Qhda1v+sCwG58IjvGfCSS7Y5tGlEBQ4MDf0Q7PYPSxaNUEBH7vo
++M7U+nFuNSmyWlt6SFBSkohZkWoVSGx3KsAO+SAHYZ7JtqsAS/dm7Dflp8KxeDg7
+wzGBDQRpGF4CpI1VQjGSJQXSEdD+J7mtvBEOD34abRfV6zOUGzOOo3NWE6wNpYgt
+0A7gVlzSYpdwqjBdvACfXR2r/mu+4KkAvYh8WwCiTcYgGjl2pT1bO4hEmcJ0RSWy
+/fGD8Q==
+-----END CERTIFICATE REQUEST-----
diff --git a/vectors/setup.cfg b/vectors/setup.cfg
index 5e40900..2a9acf1 100644
--- a/vectors/setup.cfg
+++ b/vectors/setup.cfg
@@ -1,2 +1,2 @@
-[wheel]
+[bdist_wheel]
 universal = 1
diff --git a/vectors/setup.py b/vectors/setup.py
index bf02e38..482c01b 100644
--- a/vectors/setup.py
+++ b/vectors/setup.py
@@ -15,20 +15,18 @@
 
 about = {}
 with open(os.path.join(base_dir, "cryptography_vectors", "__about__.py")) as f:
-    exec(f.read(), about)
+    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
+    include_package_data=True,
 )