Skip to content

Commit

Permalink
migrate ARC4 and TripleDES to decrepit (#10286)
Browse files Browse the repository at this point in the history
  • Loading branch information
reaperhulk committed Jan 30, 2024
1 parent 46655d7 commit 722a639
Show file tree
Hide file tree
Showing 15 changed files with 202 additions and 113 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ Changelog
:class:`~cryptography.hazmat.primitives.ciphers.algorithms.SEED`,
:class:`~cryptography.hazmat.primitives.ciphers.algorithms.IDEA`, and
:class:`~cryptography.hazmat.primitives.ciphers.algorithms.Blowfish`, which were
deprecated in 37.0.0, have been added to this module.
deprecated in 37.0.0, have been added to this module. They will be removed
from the ``cipher`` module in 45.0.0.
* Moved :class:`~cryptography.hazmat.primitives.ciphers.algorithms.TripleDES`
and :class:`~cryptography.hazmat.primitives.ciphers.algorithms.ARC4` into
:doc:`/hazmat/decrepit/index` and deprecated them in the ``cipher`` module.
They will be removed from the ``cipher`` module in 48.0.0.

.. _v42-0-1:

Expand Down
40 changes: 40 additions & 0 deletions docs/hazmat/decrepit/ciphers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,46 @@ compatibility or interoperability with legacy systems. Their use is
These algorithms require you to use a :class:`~cryptography.hazmat.primitives.ciphers.Cipher`
object along with the appropriate :mod:`~cryptography.hazmat.primitives.ciphers.modes`.

.. class:: ARC4(key)

ARC4 (Alleged RC4) is a stream cipher with serious weaknesses in its
initial stream output. Its use is strongly discouraged. ARC4 does not use
mode constructions.

:param key: The secret key. This must be kept secret. Either ``40``,
``56``, ``64``, ``80``, ``128``, ``192``, or ``256`` :term:`bits` in
length.
:type key: :term:`bytes-like`

.. doctest::

>>> import os
>>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
>>> key = os.urandom(16)
>>> algorithm = algorithms.ARC4(key)
>>> cipher = Cipher(algorithm, mode=None)
>>> encryptor = cipher.encryptor()
>>> ct = encryptor.update(b"a secret message")
>>> decryptor = cipher.decryptor()
>>> decryptor.update(ct)
b'a secret message'

.. class:: TripleDES(key)

Triple DES (Data Encryption Standard), sometimes referred to as 3DES, is a
block cipher standardized by NIST. Triple DES has known crypto-analytic
flaws, however none of them currently enable a practical attack.
Nonetheless, Triple DES is not recommended for new applications because it
is incredibly slow; old applications should consider moving away from it.

:param key: The secret key. This must be kept secret. Either ``64``,
``128``, or ``192`` :term:`bits` long. DES only uses ``56``, ``112``,
or ``168`` bits of the key as there is a parity byte in each component
of the key. Some writing refers to there being up to three separate
keys that are each ``56`` bits long, they can simply be concatenated
to produce the full key.
:type key: :term:`bytes-like`

.. class:: CAST5(key)

.. versionadded:: 43.0.0
Expand Down
8 changes: 7 additions & 1 deletion docs/hazmat/primitives/symmetric-encryption.rst
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,12 @@ Algorithms

.. class:: TripleDES(key)

.. warning::

This algorithm has been deprecated and moved to the :doc:`/hazmat/decrepit/index`
module. If you need to continue using it then update your code to
use the new module path. It will be removed from this namespace in 48.0.0.

Triple DES (Data Encryption Standard), sometimes referred to as 3DES, is a
block cipher standardized by NIST. Triple DES has known crypto-analytic
flaws, however none of them currently enable a practical attack.
Expand Down Expand Up @@ -284,7 +290,7 @@ Weak ciphers

This algorithm has been deprecated and moved to the :doc:`/hazmat/decrepit/index`
module. If you need to continue using it then update your code to
use the new module path. It will be removed from this namespace in 45.0.0.
use the new module path. It will be removed from this namespace in 48.0.0.

ARC4 (Alleged RC4) is a stream cipher with serious weaknesses in its
initial stream output. Its use is strongly discouraged. ARC4 does not use
Expand Down
4 changes: 2 additions & 2 deletions src/cryptography/hazmat/backends/openssl/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
from cryptography.hazmat.bindings._rust import openssl as rust_openssl
from cryptography.hazmat.bindings.openssl import binding
from cryptography.hazmat.decrepit.ciphers.algorithms import (
ARC4,
CAST5,
IDEA,
SEED,
Blowfish,
TripleDES,
)
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives._asymmetric import AsymmetricPadding
Expand All @@ -40,11 +42,9 @@
AES,
AES128,
AES256,
ARC4,
SM4,
Camellia,
ChaCha20,
TripleDES,
)
from cryptography.hazmat.primitives.ciphers.modes import (
CBC,
Expand Down
30 changes: 30 additions & 0 deletions src/cryptography/hazmat/decrepit/ciphers/algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,40 @@

from cryptography.hazmat.primitives._cipheralgorithm import (
BlockCipherAlgorithm,
CipherAlgorithm,
_verify_key_size,
)


class ARC4(CipherAlgorithm):
name = "RC4"
key_sizes = frozenset([40, 56, 64, 80, 128, 160, 192, 256])

def __init__(self, key: bytes):
self.key = _verify_key_size(self, key)

@property
def key_size(self) -> int:
return len(self.key) * 8


class TripleDES(BlockCipherAlgorithm):
name = "3DES"
block_size = 64
key_sizes = frozenset([64, 128, 192])

def __init__(self, key: bytes):
if len(key) == 8:
key += key + key
elif len(key) == 16:
key += key[:8]
self.key = _verify_key_size(self, key)

@property
def key_size(self) -> int:
return len(self.key) * 8


class Blowfish(BlockCipherAlgorithm):
name = "Blowfish"
block_size = 64
Expand Down
50 changes: 24 additions & 26 deletions src/cryptography/hazmat/primitives/ciphers/algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
from __future__ import annotations

from cryptography import utils
from cryptography.hazmat.decrepit.ciphers.algorithms import (
ARC4 as ARC4,
)
from cryptography.hazmat.decrepit.ciphers.algorithms import (
CAST5 as CAST5,
)
Expand All @@ -17,6 +20,9 @@
from cryptography.hazmat.decrepit.ciphers.algorithms import (
Blowfish as Blowfish,
)
from cryptography.hazmat.decrepit.ciphers.algorithms import (
TripleDES as TripleDES,
)
from cryptography.hazmat.primitives._cipheralgorithm import _verify_key_size
from cryptography.hazmat.primitives.ciphers import (
BlockCipherAlgorithm,
Expand Down Expand Up @@ -71,22 +77,26 @@ def key_size(self) -> int:
return len(self.key) * 8


class TripleDES(BlockCipherAlgorithm):
name = "3DES"
block_size = 64
key_sizes = frozenset([64, 128, 192])

def __init__(self, key: bytes):
if len(key) == 8:
key += key + key
elif len(key) == 16:
key += key[:8]
self.key = _verify_key_size(self, key)
utils.deprecated(
ARC4,
__name__,
"ARC4 has been moved to "
"cryptography.hazmat.decrepit.ciphers.algorithms.ARC4 and "
"will be removed from this module in 48.0.0.",
utils.DeprecatedIn43,
name="ARC4",
)

@property
def key_size(self) -> int:
return len(self.key) * 8

utils.deprecated(
TripleDES,
__name__,
"TripleDES has been moved to "
"cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and "
"will be removed from this module in 48.0.0.",
utils.DeprecatedIn43,
name="TripleDES",
)

utils.deprecated(
Blowfish,
Expand All @@ -110,18 +120,6 @@ def key_size(self) -> int:
)


class ARC4(CipherAlgorithm):
name = "RC4"
key_sizes = frozenset([40, 56, 64, 80, 128, 160, 192, 256])

def __init__(self, key: bytes):
self.key = _verify_key_size(self, key)

@property
def key_size(self) -> int:
return len(self.key) * 8


utils.deprecated(
IDEA,
__name__,
Expand Down
1 change: 1 addition & 0 deletions src/cryptography/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class CryptographyDeprecationWarning(UserWarning):
DeprecatedIn40 = CryptographyDeprecationWarning
DeprecatedIn41 = CryptographyDeprecationWarning
DeprecatedIn42 = CryptographyDeprecationWarning
DeprecatedIn43 = CryptographyDeprecationWarning


def _check_bytes(name: str, value: bytes) -> None:
Expand Down
2 changes: 1 addition & 1 deletion src/rust/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ pub static BLOCK_CIPHER_ALGORITHM: LazyPyImport = LazyPyImport::new(
);

pub static TRIPLE_DES: LazyPyImport = LazyPyImport::new(
"cryptography.hazmat.primitives.ciphers.algorithms",
"cryptography.hazmat.decrepit.ciphers.algorithms",
&["TripleDES"],
);
pub static AES: LazyPyImport = LazyPyImport::new(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@

import pytest

from cryptography.hazmat.primitives.ciphers import algorithms, modes
from cryptography.hazmat.decrepit.ciphers import algorithms
from cryptography.hazmat.primitives.ciphers import modes

from ...utils import load_nist_vectors
from .utils import generate_encrypt_test
from ....utils import load_nist_vectors
from ..utils import generate_encrypt_test


@pytest.mark.supported(
Expand Down
67 changes: 66 additions & 1 deletion tests/hazmat/primitives/decrepit/test_algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,83 @@

import pytest

from cryptography.exceptions import _Reasons
from cryptography.hazmat.decrepit.ciphers.algorithms import (
ARC4,
CAST5,
IDEA,
SEED,
Blowfish,
TripleDES,
)
from cryptography.hazmat.primitives import ciphers
from cryptography.hazmat.primitives.ciphers import modes

from ....utils import load_nist_vectors
from ....utils import load_nist_vectors, raises_unsupported_algorithm
from ..utils import generate_encrypt_test


class TestARC4:
@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

def test_invalid_key_size(self):
with pytest.raises(ValueError):
ARC4(binascii.unhexlify(b"0" * 34))

def test_invalid_key_type(self):
with pytest.raises(TypeError, match="key must be bytes"):
ARC4("0" * 10) # type: ignore[arg-type]


def test_invalid_mode_algorithm():
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER):
ciphers.Cipher(
ARC4(b"\x00" * 16),
modes.GCM(b"\x00" * 12),
)

with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER):
ciphers.Cipher(
ARC4(b"\x00" * 16),
modes.CBC(b"\x00" * 12),
)

with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER):
ciphers.Cipher(
ARC4(b"\x00" * 16),
modes.CTR(b"\x00" * 12),
)


class TestTripleDES:
@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

def test_invalid_key_size(self):
with pytest.raises(ValueError):
TripleDES(binascii.unhexlify(b"0" * 12))

def test_invalid_key_type(self):
with pytest.raises(TypeError, match="key must be bytes"):
TripleDES("0" * 16) # type: ignore[arg-type]


class TestBlowfish:
@pytest.mark.parametrize(
("key", "keysize"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@

import pytest

from cryptography.hazmat.primitives.ciphers import algorithms
from cryptography.hazmat.decrepit.ciphers import algorithms

from ...utils import load_nist_vectors
from .utils import generate_stream_encryption_test
from ....utils import load_nist_vectors
from ..utils import generate_stream_encryption_test


@pytest.mark.supported(
Expand Down

0 comments on commit 722a639

Please sign in to comment.