diff --git a/.github/workflows/github-ci.yaml b/.github/workflows/github-ci.yaml index 2d61ac418..cfdb35fb1 100644 --- a/.github/workflows/github-ci.yaml +++ b/.github/workflows/github-ci.yaml @@ -22,11 +22,13 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] - use-crypto-lib: ["pycryptodome"] + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] + use-crypto-lib: ["cryptography"] include: + - python-version: "3.6" + use-crypto-lib: "pycryptodome" - python-version: "3.9" - use-crypto-lib: "cryptography" + use-crypto-lib: "pycryptodome" - python-version: "3.10" use-crypto-lib: "" steps: @@ -72,14 +74,17 @@ jobs: run: | pip install -r requirements/ci-3.11.txt if: matrix.python-version == '3.11' || matrix.python-version == '3.12' - - name: Remove pycryptodome + - name: Remove pycryptodome and cryptography run: | - pip uninstall pycryptodome -y - if: matrix.use-crypto-lib != 'pycryptodome' + pip uninstall pycryptodome cryptography -y - name: Install cryptography run: | pip install cryptography if: matrix.use-crypto-lib == 'cryptography' + - name: Install pycryptodome + run: | + pip install pycryptodome + if: matrix.use-crypto-lib == 'pycryptodome' - name: Install pypdf run: | pip install . diff --git a/pypdf/_crypt_providers/_fallback.py b/pypdf/_crypt_providers/_fallback.py index 53f4a8905..3b52fbd32 100644 --- a/pypdf/_crypt_providers/_fallback.py +++ b/pypdf/_crypt_providers/_fallback.py @@ -28,7 +28,7 @@ from pypdf._crypt_providers._base import CryptBase from pypdf.errors import DependencyError -_DEPENDENCY_ERROR_STR = "PyCryptodome is required for AES algorithm" +_DEPENDENCY_ERROR_STR = "cryptography>=3.1 is required for AES algorithm" crypt_provider = ("local_crypt_fallback", "0.0.0") diff --git a/tests/test_encryption.py b/tests/test_encryption.py index 918992abe..f5fe747e0 100644 --- a/tests/test_encryption.py +++ b/tests/test_encryption.py @@ -6,25 +6,14 @@ import pypdf from pypdf import PasswordType, PdfReader, PdfWriter +from pypdf._crypt_providers import crypt_provider +from pypdf._crypt_providers._fallback import _DEPENDENCY_ERROR_STR from pypdf._encryption import AlgV5, CryptAES, CryptRC4 from pypdf.errors import DependencyError, PdfReadError -try: - from Crypto.Cipher import AES # noqa: F401 - - HAS_PYCRYPTODOME = True -except ImportError: - HAS_PYCRYPTODOME = False - -try: - from cryptography.hazmat.primitives import padding # noqa: F401 - - HAS_CRYPTOGRAPHY = True -except ImportError: - HAS_CRYPTOGRAPHY = False - - -HAS_AES = HAS_CRYPTOGRAPHY or HAS_PYCRYPTODOME +USE_CRYPTOGRAPHY = crypt_provider[0] == "cryptography" +USE_PYCRYPTODOME = crypt_provider[0] == "pycryptodome" +HAS_AES = USE_CRYPTOGRAPHY or USE_PYCRYPTODOME TESTS_ROOT = Path(__file__).parent.resolve() PROJECT_ROOT = TESTS_ROOT.parent RESOURCE_ROOT = PROJECT_ROOT / "resources" @@ -95,7 +84,7 @@ def test_encryption(name, requires_aes): ipdf = pypdf.PdfReader(inputfile) ipdf.decrypt("asdfzxcv") dd = dict(ipdf.metadata) - assert exc.value.args[0] == "PyCryptodome is required for AES algorithm" + assert exc.value.args[0] == _DEPENDENCY_ERROR_STR return else: ipdf = pypdf.PdfReader(inputfile) @@ -193,7 +182,7 @@ def test_merge_encrypted_pdfs(names): @pytest.mark.skipif( - HAS_CRYPTOGRAPHY, + USE_CRYPTOGRAPHY, reason="Limitations of cryptography. see https://github.com/pyca/cryptography/issues/2494", ) @pytest.mark.parametrize( @@ -286,7 +275,7 @@ def test_pdf_encrypt(pdf_file_path, alg, requires_aes): ) with open(pdf_file_path, "wb") as output_stream: writer.write(output_stream) - assert exc.value.args[0] == "PyCryptodome is required for AES algorithm" + assert exc.value.args[0] == _DEPENDENCY_ERROR_STR return writer.encrypt( diff --git a/tests/test_reader.py b/tests/test_reader.py index 82761d51c..8afb45737 100644 --- a/tests/test_reader.py +++ b/tests/test_reader.py @@ -7,6 +7,7 @@ import pytest from pypdf import PdfReader +from pypdf._crypt_providers import crypt_provider from pypdf._reader import convert_to_int, convertToInt from pypdf.constants import ImageAttributes as IA from pypdf.constants import PageAttributes as PG @@ -29,13 +30,7 @@ from . import get_data_from_url, normalize_warnings -try: - from Crypto.Cipher import AES # noqa: F401 - - HAS_PYCRYPTODOME = True -except ImportError: - HAS_PYCRYPTODOME = False - +HAS_AES = crypt_provider[0] in ["pycryptodome", "cryptography"] TESTS_ROOT = Path(__file__).parent.resolve() PROJECT_ROOT = TESTS_ROOT.parent RESOURCE_ROOT = PROJECT_ROOT / "resources" @@ -834,7 +829,7 @@ def test_read_not_binary_mode(caplog): @pytest.mark.enable_socket() -@pytest.mark.skipif(not HAS_PYCRYPTODOME, reason="No pycryptodome") +@pytest.mark.skipif(not HAS_AES, reason="No AES algorithm available") def test_read_form_416(): url = ( "https://www.fda.gov/downloads/AboutFDA/ReportsManualsForms/Forms/UCM074728.pdf"