From df92be8d64c0b1d41bcea6e11dbc85c38b14a10a Mon Sep 17 00:00:00 2001 From: Joachim Metz Date: Sun, 14 Jan 2024 20:58:25 +0100 Subject: [PATCH] Changes for CI tests and replaced Cryptography #713 --- .github/workflows/test_docker.yml | 4 +- .github/workflows/test_docs.yml | 2 +- .github/workflows/test_tox.yml | 6 +- .pylintrc | 2 +- config/appveyor/install.ps1 | 2 +- config/dpkg/control | 2 +- dependencies.ini | 14 +++-- dfvfs/encryption/aes_decrypter.py | 72 +++++++++++++++++++--- dfvfs/encryption/blowfish_decrypter.py | 2 +- dfvfs/encryption/decrypter.py | 84 -------------------------- dfvfs/encryption/des3_decrypter.py | 2 +- dfvfs/encryption/rc4_decrypter.py | 2 +- dfvfs/file_io/encrypted_stream_io.py | 7 ++- docs/sources/Supported-formats.md | 8 +-- requirements.txt | 2 +- setup.cfg | 2 +- tests/encryption/aes_decrypter.py | 6 +- tests/encryption/decrypter.py | 44 +------------- 18 files changed, 97 insertions(+), 166 deletions(-) diff --git a/.github/workflows/test_docker.yml b/.github/workflows/test_docker.yml index 951e3ec6..436dadad 100644 --- a/.github/workflows/test_docker.yml +++ b/.github/workflows/test_docker.yml @@ -18,7 +18,7 @@ jobs: - name: Install dependencies run: | dnf copr -y enable @gift/dev - dnf install -y @development-tools python3 python3-devel libbde-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-cffi python3-cryptography python3-dfdatetime python3-dtfabric python3-idna python3-pytsk3 python3-pyyaml python3-setuptools python3-xattr + dnf install -y @development-tools python3 python3-devel libbde-python3 libcaes-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-cffi python3-dfdatetime python3-dtfabric python3-idna python3-pytsk3 python3-pyyaml python3-setuptools python3-xattr - name: Run tests env: LANG: C.utf8 @@ -58,7 +58,7 @@ jobs: run: | add-apt-repository -y ppa:gift/dev apt-get update -q - apt-get install -y build-essential python3 python3-dev libbde-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-cffi-backend python3-cryptography python3-dfdatetime python3-distutils python3-dtfabric python3-idna python3-pip python3-pytsk3 python3-setuptools python3-wheel python3-xattr python3-yaml + apt-get install -y build-essential python3 python3-dev libbde-python3 libcaes-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-cffi-backend python3-dfdatetime python3-distutils python3-dtfabric python3-idna python3-pip python3-pytsk3 python3-setuptools python3-wheel python3-xattr python3-yaml - name: Run tests env: LANG: en_US.UTF-8 diff --git a/.github/workflows/test_docs.yml b/.github/workflows/test_docs.yml index ef9cdb32..8b2bedb1 100644 --- a/.github/workflows/test_docs.yml +++ b/.github/workflows/test_docs.yml @@ -36,7 +36,7 @@ jobs: add-apt-repository -y ppa:deadsnakes/ppa add-apt-repository -y ppa:gift/dev apt-get update -q - apt-get install -y build-essential git libffi-dev python${{ matrix.python-version }} python${{ matrix.python-version }}-dev python${{ matrix.python-version }}-venv libbde-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-cffi-backend python3-cryptography python3-dfdatetime python3-distutils python3-dtfabric python3-idna python3-pip python3-pytsk3 python3-setuptools python3-xattr python3-yaml + apt-get install -y build-essential git libffi-dev python${{ matrix.python-version }} python${{ matrix.python-version }}-dev python${{ matrix.python-version }}-venv libbde-python3 libcaes-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-cffi-backend python3-dfdatetime python3-distutils python3-dtfabric python3-idna python3-pip python3-pytsk3 python3-setuptools python3-xattr python3-yaml - name: Install tox run: | python3 -m pip install tox diff --git a/.github/workflows/test_tox.yml b/.github/workflows/test_tox.yml index 473c7299..c693053a 100644 --- a/.github/workflows/test_tox.yml +++ b/.github/workflows/test_tox.yml @@ -46,7 +46,7 @@ jobs: add-apt-repository -y ppa:deadsnakes/ppa add-apt-repository -y ppa:gift/dev apt-get update -q - apt-get install -y build-essential git libffi-dev python${{ matrix.python-version }} python${{ matrix.python-version }}-dev python${{ matrix.python-version }}-venv libbde-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-cffi-backend python3-cryptography python3-dfdatetime python3-distutils python3-dtfabric python3-idna python3-pip python3-pytsk3 python3-setuptools python3-xattr python3-yaml + apt-get install -y build-essential git libffi-dev python${{ matrix.python-version }} python${{ matrix.python-version }}-dev python${{ matrix.python-version }}-venv libbde-python3 libcaes-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-cffi-backend python3-dfdatetime python3-distutils python3-dtfabric python3-idna python3-pip python3-pytsk3 python3-setuptools python3-xattr python3-yaml - name: Install tox run: | python3 -m pip install tox @@ -82,7 +82,7 @@ jobs: add-apt-repository -y ppa:deadsnakes/ppa add-apt-repository -y ppa:gift/dev apt-get update -q - apt-get install -y build-essential git libffi-dev python${{ matrix.python-version }} python${{ matrix.python-version }}-dev python${{ matrix.python-version }}-venv libbde-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-cffi-backend python3-cryptography python3-dfdatetime python3-distutils python3-dtfabric python3-idna python3-pip python3-pytsk3 python3-setuptools python3-xattr python3-yaml + apt-get install -y build-essential git libffi-dev python${{ matrix.python-version }} python${{ matrix.python-version }}-dev python${{ matrix.python-version }}-venv libbde-python3 libcaes-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-cffi-backend python3-dfdatetime python3-distutils python3-dtfabric python3-idna python3-pip python3-pytsk3 python3-setuptools python3-xattr python3-yaml - name: Install tox run: | python3 -m pip install tox @@ -120,7 +120,7 @@ jobs: add-apt-repository -y ppa:deadsnakes/ppa add-apt-repository -y ppa:gift/dev apt-get update -q - apt-get install -y build-essential git libffi-dev python${{ matrix.python-version }} python${{ matrix.python-version }}-dev python${{ matrix.python-version }}-venv libbde-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-cffi-backend python3-cryptography python3-dfdatetime python3-distutils python3-dtfabric python3-idna python3-pip python3-pytsk3 python3-setuptools python3-xattr python3-yaml + apt-get install -y build-essential git libffi-dev python${{ matrix.python-version }} python${{ matrix.python-version }}-dev python${{ matrix.python-version }}-venv libbde-python3 libcaes-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-cffi-backend python3-dfdatetime python3-distutils python3-dtfabric python3-idna python3-pip python3-pytsk3 python3-setuptools python3-xattr python3-yaml - name: Install tox run: | python3 -m pip install tox diff --git a/.pylintrc b/.pylintrc index d8cf2dc5..7cb4eb3f 100644 --- a/.pylintrc +++ b/.pylintrc @@ -29,7 +29,7 @@ clear-cache-post-run=no # A comma-separated list of package or module names from where C extensions may # be loaded. Extensions are loading into the active Python interpreter and may # run arbitrary code. -extension-pkg-allow-list=pybde,pyewf,pyfcrypto,pyfsapfs,pyfsext,pyfsfat,pyfshfs,pyfsntfs,pyfsxfs,pyfvde,pyfwnt,pyluksde,pymodi,pyphdi,pyqcow,pysigscan,pysmdev,pysmraw,pytsk3,pyvhdi,pyvmdk,pyvsapm,pyvsgpt,pyvshadow,pyvslvm,xattr +extension-pkg-allow-list=pybde,pycaes,pyewf,pyfcrypto,pyfsapfs,pyfsext,pyfsfat,pyfshfs,pyfsntfs,pyfsxfs,pyfvde,pyfwnt,pyluksde,pymodi,pyphdi,pyqcow,pysigscan,pysmdev,pysmraw,pytsk3,pyvhdi,pyvmdk,pyvsapm,pyvsgpt,pyvshadow,pyvslvm,xattr # A comma-separated list of package or module names from where C extensions may # be loaded. Extensions are loading into the active Python interpreter and may diff --git a/config/appveyor/install.ps1 b/config/appveyor/install.ps1 index 5f4fd829..1475caba 100644 --- a/config/appveyor/install.ps1 +++ b/config/appveyor/install.ps1 @@ -1,6 +1,6 @@ # Script to set up tests on AppVeyor Windows. -$Dependencies = "PyYAML cffi cryptography dfdatetime dtfabric idna libbde libewf libfcrypto libfsapfs libfsext libfsfat libfshfs libfsntfs libfsxfs libfvde libfwnt libluksde libmodi libphdi libqcow libsigscan libsmdev libsmraw libvhdi libvmdk libvsapm libvsgpt libvshadow libvslvm pytsk3 xattr" +$Dependencies = "PyYAML cffi dfdatetime dtfabric idna libbde libcaes libewf libfcrypto libfsapfs libfsext libfsfat libfshfs libfsntfs libfsxfs libfvde libfwnt libluksde libmodi libphdi libqcow libsigscan libsmdev libsmraw libvhdi libvmdk libvsapm libvsgpt libvshadow libvslvm pytsk3 xattr" If ($Dependencies.Length -gt 0) { diff --git a/config/dpkg/control b/config/dpkg/control index cf698b46..bfc849ee 100644 --- a/config/dpkg/control +++ b/config/dpkg/control @@ -9,7 +9,7 @@ Homepage: https://github.com/log2timeline/dfvfs Package: python3-dfvfs Architecture: all -Depends: libbde-python3 (>= 20220121), libewf-python3 (>= 20131210), libfcrypto-python3 (>= 20240114), libfsapfs-python3 (>= 20220709), libfsext-python3 (>= 20220829), libfsfat-python3 (>= 20220925), libfshfs-python3 (>= 20220831), libfsntfs-python3 (>= 20211229), libfsxfs-python3 (>= 20220829), libfvde-python3 (>= 20220121), libfwnt-python3 (>= 20210717), libluksde-python3 (>= 20220121), libmodi-python3 (>= 20210405), libphdi-python3 (>= 20220228), libqcow-python3 (>= 20201213), libsigscan-python3 (>= 20230109), libsmdev-python3 (>= 20140529), libsmraw-python3 (>= 20140612), libvhdi-python3 (>= 20201014), libvmdk-python3 (>= 20140421), libvsapm-python3 (>= 20230506), libvsgpt-python3 (>= 20211115), libvshadow-python3 (>= 20160109), libvslvm-python3 (>= 20160109), python3-cffi-backend (>= 1.9.1), python3-cryptography (>= 2.0.2), python3-dfdatetime (>= 20221112), python3-dtfabric (>= 20230518), python3-idna (>= 2.5), python3-pytsk3 (>= 20210419), python3-xattr (>= 0.7.2), python3-yaml (>= 3.10), ${misc:Depends} +Depends: libbde-python3 (>= 20220121), libcaes-python3 (>= 20240114), libewf-python3 (>= 20131210), libfcrypto-python3 (>= 20240114), libfsapfs-python3 (>= 20220709), libfsext-python3 (>= 20220829), libfsfat-python3 (>= 20220925), libfshfs-python3 (>= 20220831), libfsntfs-python3 (>= 20211229), libfsxfs-python3 (>= 20220829), libfvde-python3 (>= 20220121), libfwnt-python3 (>= 20210717), libluksde-python3 (>= 20220121), libmodi-python3 (>= 20210405), libphdi-python3 (>= 20220228), libqcow-python3 (>= 20201213), libsigscan-python3 (>= 20230109), libsmdev-python3 (>= 20140529), libsmraw-python3 (>= 20140612), libvhdi-python3 (>= 20201014), libvmdk-python3 (>= 20140421), libvsapm-python3 (>= 20230506), libvsgpt-python3 (>= 20211115), libvshadow-python3 (>= 20160109), libvslvm-python3 (>= 20160109), python3-cffi-backend (>= 1.9.1), python3-dfdatetime (>= 20221112), python3-dtfabric (>= 20230518), python3-idna (>= 2.5), python3-pytsk3 (>= 20210419), python3-xattr (>= 0.7.2), python3-yaml (>= 3.10), ${misc:Depends} Description: Python 3 module of dfVFS dfVFS, or Digital Forensics Virtual File System, provides read-only access to file-system objects from various storage media types and file formats. The goal diff --git a/dependencies.ini b/dependencies.ini index bed015e5..5d57584b 100644 --- a/dependencies.ini +++ b/dependencies.ini @@ -5,12 +5,6 @@ minimum_version: 1.9.1 rpm_name: python3-cffi version_property: __version__ -[cryptography] -dpkg_name: python3-cryptography -minimum_version: 2.0.2 -rpm_name: python3-cryptography -version_property: __version__ - [dfdatetime] dpkg_name: python3-dfdatetime minimum_version: 20221112 @@ -31,6 +25,14 @@ minimum_version: 2.5 rpm_name: python3-idna version_property: __version__ +[pycaes] +dpkg_name: libcaes-python3 +l2tbinaries_name: libcaes +minimum_version: 20240114 +pypi_name: libcaes-python +rpm_name: libcaes-python3 +version_property: get_version() + [pybde] dpkg_name: libbde-python3 l2tbinaries_name: libbde diff --git a/dfvfs/encryption/aes_decrypter.py b/dfvfs/encryption/aes_decrypter.py index d3636212..e713529d 100644 --- a/dfvfs/encryption/aes_decrypter.py +++ b/dfvfs/encryption/aes_decrypter.py @@ -1,23 +1,25 @@ # -*- coding: utf-8 -*- """The AES decrypter implementation.""" -from cryptography.hazmat.primitives.ciphers import algorithms +import pycaes from dfvfs.encryption import decrypter from dfvfs.encryption import manager from dfvfs.lib import definitions -class AESDecrypter(decrypter.CryptographyBlockCipherDecrypter): - """AES decrypter using Cryptography.""" +class AESDecrypter(decrypter.Decrypter): + """AES decrypter using pycaes.""" ENCRYPTION_METHOD = definitions.ENCRYPTION_METHOD_AES + _BLOCK_SIZE = 16 + + # TODO: add CFB and OFB support + _ENCRYPTION_MODES = frozenset([ definitions.ENCRYPTION_MODE_CBC, - definitions.ENCRYPTION_MODE_CFB, - definitions.ENCRYPTION_MODE_ECB, - definitions.ENCRYPTION_MODE_OFB]) + definitions.ENCRYPTION_MODE_ECB]) def __init__( self, cipher_mode=None, initialization_vector=None, key=None, **kwargs): @@ -38,11 +40,61 @@ def __init__( if cipher_mode not in self._ENCRYPTION_MODES: raise ValueError(f'Unsupported cipher mode: {cipher_mode!s}') - algorithm = algorithms.AES(key) + if (cipher_mode != definitions.ENCRYPTION_MODE_ECB and + not initialization_vector): + raise ValueError('Missing initialization vector.') + + if initialization_vector and not isinstance(initialization_vector, bytes): + raise TypeError('Unsupported initialization vector type.') + + if initialization_vector and len(initialization_vector) != self._BLOCK_SIZE: + raise ValueError('Unsupported initialization vector size.') + + super(AESDecrypter, self).__init__() + self._aes_context = pycaes.context() + self._cipher_mode = cipher_mode + self._initialization_vector = initialization_vector + + self._aes_context.set_key(pycaes.crypt_modes.DECRYPT, key) + + def Decrypt(self, encrypted_data, finalize=False): + """Decrypts the encrypted data. + + Args: + encrypted_data (bytes): encrypted data. + finalize (Optional[bool]): True if the end of data has been reached and + the cipher context should be finalized. + + Returns: + tuple[bytes, bytes]: decrypted data and remaining encrypted data. + """ + encrypted_data_size = len(encrypted_data) + + _, block_offset = divmod(encrypted_data_size, self._BLOCK_SIZE) + + remaining_encrypted_data = b'' + if block_offset > 0: + if finalize: + block_padding_size = self._BLOCK_SIZE - block_offset + encrypted_data = b''.join([ + encrypted_data, b'\x00' * block_padding_size]) + else: + remaining_encrypted_data = encrypted_data[-block_offset:] + encrypted_data = encrypted_data[:-block_offset] + + if self._cipher_mode == definitions.ENCRYPTION_MODE_CBC: + decrypted_data = pycaes.crypt_cbc( + self._aes_context, pycaes.crypt_modes.DECRYPT, + self._initialization_vector, encrypted_data) + + self._initialization_vector = encrypted_data[-self._BLOCK_SIZE:] + + elif self._cipher_mode == definitions.ENCRYPTION_MODE_ECB: + decrypted_data = pycaes.crypt_ecb( + self._aes_context, pycaes.crypt_modes.DECRYPT, encrypted_data) - super(AESDecrypter, self).__init__( - algorithm=algorithm, cipher_mode=cipher_mode, - initialization_vector=initialization_vector, **kwargs) + decrypted_data_size = encrypted_data_size - block_offset + return decrypted_data[:decrypted_data_size], remaining_encrypted_data manager.EncryptionManager.RegisterDecrypter(AESDecrypter) diff --git a/dfvfs/encryption/blowfish_decrypter.py b/dfvfs/encryption/blowfish_decrypter.py index 6f8794c6..528e0972 100644 --- a/dfvfs/encryption/blowfish_decrypter.py +++ b/dfvfs/encryption/blowfish_decrypter.py @@ -9,7 +9,7 @@ class BlowfishDecrypter(decrypter.Decrypter): - """Blowfish decrypter using Cryptography.""" + """Blowfish decrypter using pyfcrypto.""" ENCRYPTION_METHOD = definitions.ENCRYPTION_METHOD_BLOWFISH diff --git a/dfvfs/encryption/decrypter.py b/dfvfs/encryption/decrypter.py index 2338b343..2eff06f4 100644 --- a/dfvfs/encryption/decrypter.py +++ b/dfvfs/encryption/decrypter.py @@ -3,13 +3,6 @@ import abc -from cryptography.hazmat import backends -from cryptography.hazmat.primitives import ciphers -from cryptography.hazmat.primitives.ciphers import modes - -from dfvfs.lib import definitions -from dfvfs.lib import errors - class Decrypter(object): """Decrypter interface.""" @@ -42,80 +35,3 @@ def Decrypt(self, encrypted_data, finalize=False): Returns: tuple[bytes, bytes]: decrypted data and remaining encrypted data. """ - - -class CryptographyBlockCipherDecrypter(Decrypter): - """Block cipher decrypter using Cryptography.""" - - def __init__( - self, algorithm=None, cipher_mode=None, initialization_vector=None, - **kwargs): - """Initializes a decrypter. - - Args: - algorithm (Optional[Cryptography.CipherAlgorithm]): cipher algorithm. - cipher_mode (Optional[str]): cipher mode. - initialization_vector (Optional[bytes]): initialization vector. - kwargs (dict): keyword arguments depending on the decrypter. - - Raises: - BackEndError: when the cryptography backend cannot be initialized. - ValueError: if the initialization_vector is required and not set. - """ - if (cipher_mode != definitions.ENCRYPTION_MODE_ECB and - not initialization_vector): - raise ValueError('Missing initialization vector.') - - if cipher_mode == definitions.ENCRYPTION_MODE_CBC: - mode = modes.CBC(initialization_vector) - elif cipher_mode == definitions.ENCRYPTION_MODE_CFB: - mode = modes.CFB(initialization_vector) - elif cipher_mode == definitions.ENCRYPTION_MODE_ECB: - mode = modes.ECB() - elif cipher_mode == definitions.ENCRYPTION_MODE_OFB: - mode = modes.OFB(initialization_vector) - - try: - backend = backends.default_backend() - except ImportError as exception: - raise errors.BackEndError(exception) - - cipher = ciphers.Cipher(algorithm, mode=mode, backend=backend) - - super(CryptographyBlockCipherDecrypter, self).__init__() - self._algorithm = algorithm - self._cipher_context = cipher.decryptor() - - def Decrypt(self, encrypted_data, finalize=False): - """Decrypts the encrypted data. - - Args: - encrypted_data (bytes): encrypted data. - finalize (Optional[bool]): True if the end of data has been reached and - the cipher context should be finalized. - - Returns: - tuple[bytes, bytes]: decrypted data and remaining encrypted data. - """ - encrypted_data_size = len(encrypted_data) - - _, block_offset = divmod(encrypted_data_size, self._algorithm.block_size) - - remaining_encrypted_data = b'' - if not finalize and block_offset > 0: - remaining_encrypted_data = encrypted_data[-block_offset:] - encrypted_data = encrypted_data[:-block_offset] - - decrypted_data = self._cipher_context.update(encrypted_data) - - if finalize: - if block_offset > 0: - block_padding_size = self._algorithm.block_size - block_offset - block_padding = b'\x00' * block_padding_size - - decrypted_data += self._cipher_context.update(block_padding) - - decrypted_data += self._cipher_context.finalize() - decrypted_data = decrypted_data[:encrypted_data_size] - - return decrypted_data, remaining_encrypted_data diff --git a/dfvfs/encryption/des3_decrypter.py b/dfvfs/encryption/des3_decrypter.py index 5485e3e5..79aba574 100644 --- a/dfvfs/encryption/des3_decrypter.py +++ b/dfvfs/encryption/des3_decrypter.py @@ -9,7 +9,7 @@ class DES3Decrypter(decrypter.Decrypter): - """Triple DES decrypter using Cryptography.""" + """Triple DES decrypter using pyfcrypto.""" ENCRYPTION_METHOD = definitions.ENCRYPTION_METHOD_DES3 diff --git a/dfvfs/encryption/rc4_decrypter.py b/dfvfs/encryption/rc4_decrypter.py index fb22bd32..82355f67 100644 --- a/dfvfs/encryption/rc4_decrypter.py +++ b/dfvfs/encryption/rc4_decrypter.py @@ -9,7 +9,7 @@ class RC4Decrypter(decrypter.Decrypter): - """RC4 decrypter using Cryptography.""" + """RC4 decrypter using pyfcrypto.""" ENCRYPTION_METHOD = definitions.ENCRYPTION_METHOD_RC4 diff --git a/dfvfs/file_io/encrypted_stream_io.py b/dfvfs/file_io/encrypted_stream_io.py index 9496d109..865a4146 100644 --- a/dfvfs/file_io/encrypted_stream_io.py +++ b/dfvfs/file_io/encrypted_stream_io.py @@ -160,8 +160,11 @@ def _ReadEncryptedData(self, read_size, finalize=False): self._encrypted_data = b''.join([self._encrypted_data, encrypted_data]) - self._decrypted_data, self._encrypted_data = self._decrypter.Decrypt( - self._encrypted_data, finalize=finalize) + if self._encrypted_data: + self._decrypted_data, self._encrypted_data = self._decrypter.Decrypt( + self._encrypted_data, finalize=finalize) + else: + self._decrypted_data = b'' self._decrypted_data_size = len(self._decrypted_data) diff --git a/docs/sources/Supported-formats.md b/docs/sources/Supported-formats.md index 18cd1b70..8c4de2ef 100644 --- a/docs/sources/Supported-formats.md +++ b/docs/sources/Supported-formats.md @@ -59,10 +59,10 @@ The information below is based of version 20230503 ### Encrypted stream file types -* AES-CBC, AES-CFB, AES-ECB, AES-OFB (Requires: [Cryptography.io](https://cryptography.io/en/latest/)) -* Blowfish (Requires: [Cryptography.io](https://cryptography.io/en/latest/)) -* DES3 (Requires: [Cryptography.io](https://cryptography.io/en/latest/)) -* RC4 (Requires: [Cryptography.io](https://cryptography.io/en/latest/)) +* AES-CBC, AES-CFB, AES-ECB, AES-OFB (Requires: [libcaes/pycaes](https://github.com/libyal/libcaes)) +* Blowfish (Requires: [libfcrypto/pyfcrypto](https://github.com/libyal/libfcrypto)) +* DES3 (Requires: [libfcrypto/pyfcrypto](https://github.com/libyal/libfcrypto)) +* RC4 (Requires: [libfcrypto/pyfcrypto](https://github.com/libyal/libfcrypto)) ### Archive file types diff --git a/requirements.txt b/requirements.txt index 1977ad7a..af72d9ae 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,9 @@ PyYAML >= 3.10 cffi >= 1.9.1 -cryptography >= 2.0.2 dfdatetime >= 20221112 dtfabric >= 20230518 libbde-python >= 20220121 +libcaes-python >= 20240114 libewf-python >= 20131210 libfcrypto-python >= 20240114 libfsapfs-python >= 20220709 diff --git a/setup.cfg b/setup.cfg index c0dc6b5e..fa9b7df8 100644 --- a/setup.cfg +++ b/setup.cfg @@ -55,6 +55,7 @@ doc_files = build_requires = python3-setuptools requires = libbde-python3 >= 20220121 + libcaes-python3 >= 20240114 libewf-python3 >= 20131210 libfcrypto-python3 >= 20240114 libfsapfs-python3 >= 20220709 @@ -79,7 +80,6 @@ requires = libvshadow-python3 >= 20160109 libvslvm-python3 >= 20160109 python3-cffi >= 1.9.1 - python3-cryptography >= 2.0.2 python3-dfdatetime >= 20221112 python3-dtfabric >= 20230518 python3-idna >= 2.5 diff --git a/tests/encryption/aes_decrypter.py b/tests/encryption/aes_decrypter.py index a35866e1..905f7d0c 100644 --- a/tests/encryption/aes_decrypter.py +++ b/tests/encryption/aes_decrypter.py @@ -43,7 +43,7 @@ def testInitialization(self): # Test incorrect key size. with self.assertRaises(ValueError): aes_decrypter.AESDecrypter( - cipher_mode=definitions.ENCRYPTION_MODE_ECB, key=b'Wrong key size') + cipher_mode=definitions.ENCRYPTION_MODE_ECB, key=b'Wrong key size.') # Test incorrect initialization vector type. with self.assertRaises(TypeError): @@ -92,8 +92,8 @@ def testDecrypt(self): decrypted_data, remaining_encrypted_data = decrypter.Decrypt( partial_encrypted_data) - self.assertEqual(decrypted_data, b'') - self.assertEqual(remaining_encrypted_data, partial_encrypted_data) + self.assertEqual(decrypted_data, b'This is secret e') + self.assertEqual(remaining_encrypted_data, b'B\x01\xdb8E7\xfe') if __name__ == '__main__': diff --git a/tests/encryption/decrypter.py b/tests/encryption/decrypter.py index 76cef1cc..abb07b0b 100644 --- a/tests/encryption/decrypter.py +++ b/tests/encryption/decrypter.py @@ -1,14 +1,10 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -"""Tests for the RC4 decrypter object.""" +"""Tests for the decrypter interface.""" import unittest -from cryptography.hazmat.primitives.ciphers import algorithms - from dfvfs.encryption import decrypter -from dfvfs.lib import definitions -from dfvfs.lib import errors from tests.encryption import test_lib @@ -25,43 +21,5 @@ def testInitialize(self): decrypter.Decrypter(key=b'test1') -class CryptographyBlockCipherDecrypterTest(test_lib.DecrypterTestCase): - """Tests for the block cipher decrypter using Cryptography.""" - - _DES3_INITIALIZATION_VECTOR = b'This IV!' - _DES3_KEY = b'This is a key123' - - def testInitialize(self): - """Tests the __init__ method.""" - algorithm = algorithms.TripleDES(self._DES3_KEY) - - try: - test_decrypter = decrypter.CryptographyBlockCipherDecrypter( - algorithm=algorithm, cipher_mode=definitions.ENCRYPTION_MODE_CBC, - initialization_vector=self._DES3_INITIALIZATION_VECTOR) - except errors.BackEndError: - raise unittest.SkipTest('missing cryptograpy triple DES support') - - self.assertIsNotNone(test_decrypter) - - test_decrypter = decrypter.CryptographyBlockCipherDecrypter( - algorithm=algorithm, cipher_mode=definitions.ENCRYPTION_MODE_CFB, - initialization_vector=self._DES3_INITIALIZATION_VECTOR) - self.assertIsNotNone(test_decrypter) - - test_decrypter = decrypter.CryptographyBlockCipherDecrypter( - algorithm=algorithm, cipher_mode=definitions.ENCRYPTION_MODE_ECB) - self.assertIsNotNone(test_decrypter) - - test_decrypter = decrypter.CryptographyBlockCipherDecrypter( - algorithm=algorithm, cipher_mode=definitions.ENCRYPTION_MODE_OFB, - initialization_vector=self._DES3_INITIALIZATION_VECTOR) - self.assertIsNotNone(test_decrypter) - - with self.assertRaises(ValueError): - decrypter.CryptographyBlockCipherDecrypter( - algorithm=algorithm, cipher_mode=definitions.ENCRYPTION_MODE_CBC) - - if __name__ == '__main__': unittest.main()