Skip to content

Commit 1937220

Browse files
committed
Deprecate short TripleDES key lengths
TripleDES now emits a deprecation warning when 8-byte (single DES) or 16-byte (two-key) keys are passed. In a future release, only 24-byte (192-bit) keys will be accepted. Users needing single DES or two-key Triple DES compatibility should expand the key themselves: - Single DES (8 bytes): key + key + key - Two-key 3DES (16 bytes): key + key[:8]
1 parent a3b0bd8 commit 1937220

File tree

7 files changed

+72
-19
lines changed

7 files changed

+72
-19
lines changed

CHANGELOG.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ Changelog
2727
such keys are impossible to process in a constant-time manner. We do not
2828
believe keys with this problem are in wide use, however we may revert this
2929
change based on the feedback we receive.
30+
* Deprecated passing 64-bit (8-byte) and 128-bit (16-byte) keys to
31+
:class:`~cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES`. In a
32+
future release, only 192-bit (24-byte) keys will be accepted. Users should
33+
expand shorter keys themselves (e.g., for single DES: ``key + key + key``,
34+
for two-key: ``key + key[:8]``).
3035
* Updated the minimum supported Rust version (MSRV) to 1.83.0, from 1.74.0.
3136
* Added support for loading elliptic curve keys that contain explicit encodings
3237
of the curves ``secp256r1``, ``secp384r1``, and ``secp521r1``.

docs/hazmat/decrepit/ciphers.rst

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,16 @@ object along with the appropriate :mod:`~cryptography.hazmat.primitives.ciphers.
5454
:param key: The secret key. This must be kept secret. Either ``64``,
5555
``128``, or ``192`` :term:`bits` long. DES only uses ``56``, ``112``,
5656
or ``168`` bits of the key as there is a parity byte in each component
57-
of the key. Some writing refers to there being up to three separate
57+
of the key. Some writing refers to there being up to three separate
5858
keys that are each ``56`` bits long, they can simply be concatenated
5959
to produce the full key.
60+
61+
.. deprecated:: 47.0.0
62+
63+
Passing 64-bit or 128-bit keys is deprecated. In a future release,
64+
only 192-bit (24-byte) keys will be accepted. Users should expand
65+
shorter keys themselves (e.g., for single DES: ``key + key + key``,
66+
for two-key: ``key + key[:8]``).
6067
:type key: :term:`bytes-like`
6168

6269
.. class:: CAST5(key)

src/cryptography/hazmat/decrepit/ciphers/algorithms.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
from __future__ import annotations
66

7+
import warnings
8+
9+
from cryptography import utils
710
from cryptography.hazmat.primitives._cipheralgorithm import (
811
BlockCipherAlgorithm,
912
CipherAlgorithm,
@@ -30,9 +33,23 @@ class TripleDES(BlockCipherAlgorithm):
3033

3134
def __init__(self, key: bytes):
3235
if len(key) == 8:
33-
key += key + key
36+
warnings.warn(
37+
"Single-key TripleDES (8-byte keys) is deprecated and "
38+
"support will be removed in a future release. Use 24-byte "
39+
"keys instead (e.g., key + key + key).",
40+
utils.DeprecatedIn47,
41+
stacklevel=2,
42+
)
43+
key = key + key + key
3444
elif len(key) == 16:
35-
key += key[:8]
45+
warnings.warn(
46+
"Two-key TripleDES (16-byte keys) is deprecated and "
47+
"support will be removed in a future release. Use 24-byte "
48+
"keys instead (e.g., key + key[:8]).",
49+
utils.DeprecatedIn47,
50+
stacklevel=2,
51+
)
52+
key = key + key[:8]
3653
self.key = _verify_key_size(self, key)
3754

3855
@property

tests/hazmat/primitives/decrepit/test_3des.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
@pytest.mark.supported(
2323
only_if=lambda backend: backend.cipher_supported(
24-
algorithms.TripleDES(b"\x00" * 8), modes.CBC(b"\x00" * 8)
24+
algorithms.TripleDES(b"\x00" * 24), modes.CBC(b"\x00" * 8)
2525
),
2626
skip_message="Does not support TripleDES CBC",
2727
)
@@ -36,7 +36,9 @@ class TestTripleDESModeCBC:
3636
"TCBCvarkey.rsp",
3737
"TCBCvartext.rsp",
3838
],
39-
lambda keys, **kwargs: algorithms.TripleDES(binascii.unhexlify(keys)),
39+
lambda keys, **kwargs: algorithms.TripleDES(
40+
binascii.unhexlify(keys) * 3
41+
),
4042
lambda iv, **kwargs: modes.CBC(binascii.unhexlify(iv)),
4143
)
4244

@@ -53,7 +55,7 @@ class TestTripleDESModeCBC:
5355

5456
@pytest.mark.supported(
5557
only_if=lambda backend: backend.cipher_supported(
56-
algorithms.TripleDES(b"\x00" * 8), OFB(b"\x00" * 8)
58+
algorithms.TripleDES(b"\x00" * 24), OFB(b"\x00" * 8)
5759
),
5860
skip_message="Does not support TripleDES OFB",
5961
)
@@ -68,7 +70,9 @@ class TestTripleDESModeOFB:
6870
"TOFBvartext.rsp",
6971
"TOFBinvperm.rsp",
7072
],
71-
lambda keys, **kwargs: algorithms.TripleDES(binascii.unhexlify(keys)),
73+
lambda keys, **kwargs: algorithms.TripleDES(
74+
binascii.unhexlify(keys) * 3
75+
),
7276
lambda iv, **kwargs: OFB(binascii.unhexlify(iv)),
7377
)
7478

@@ -85,7 +89,7 @@ class TestTripleDESModeOFB:
8589

8690
@pytest.mark.supported(
8791
only_if=lambda backend: backend.cipher_supported(
88-
algorithms.TripleDES(b"\x00" * 8), CFB(b"\x00" * 8)
92+
algorithms.TripleDES(b"\x00" * 24), CFB(b"\x00" * 8)
8993
),
9094
skip_message="Does not support TripleDES CFB",
9195
)
@@ -100,7 +104,9 @@ class TestTripleDESModeCFB:
100104
"TCFB64varkey.rsp",
101105
"TCFB64vartext.rsp",
102106
],
103-
lambda keys, **kwargs: algorithms.TripleDES(binascii.unhexlify(keys)),
107+
lambda keys, **kwargs: algorithms.TripleDES(
108+
binascii.unhexlify(keys) * 3
109+
),
104110
lambda iv, **kwargs: CFB(binascii.unhexlify(iv)),
105111
)
106112

@@ -117,7 +123,7 @@ class TestTripleDESModeCFB:
117123

118124
@pytest.mark.supported(
119125
only_if=lambda backend: backend.cipher_supported(
120-
algorithms.TripleDES(b"\x00" * 8), CFB8(b"\x00" * 8)
126+
algorithms.TripleDES(b"\x00" * 24), CFB8(b"\x00" * 8)
121127
),
122128
skip_message="Does not support TripleDES CFB8",
123129
)
@@ -132,7 +138,9 @@ class TestTripleDESModeCFB8:
132138
"TCFB8varkey.rsp",
133139
"TCFB8vartext.rsp",
134140
],
135-
lambda keys, **kwargs: algorithms.TripleDES(binascii.unhexlify(keys)),
141+
lambda keys, **kwargs: algorithms.TripleDES(
142+
binascii.unhexlify(keys) * 3
143+
),
136144
lambda iv, **kwargs: CFB8(binascii.unhexlify(iv)),
137145
)
138146

@@ -149,7 +157,7 @@ class TestTripleDESModeCFB8:
149157

150158
@pytest.mark.supported(
151159
only_if=lambda backend: backend.cipher_supported(
152-
algorithms.TripleDES(b"\x00" * 8), modes.ECB()
160+
algorithms.TripleDES(b"\x00" * 24), modes.ECB()
153161
),
154162
skip_message="Does not support TripleDES ECB",
155163
)
@@ -164,7 +172,9 @@ class TestTripleDESModeECB:
164172
"TECBvarkey.rsp",
165173
"TECBvartext.rsp",
166174
],
167-
lambda keys, **kwargs: algorithms.TripleDES(binascii.unhexlify(keys)),
175+
lambda keys, **kwargs: algorithms.TripleDES(
176+
binascii.unhexlify(keys) * 3
177+
),
168178
lambda **kwargs: modes.ECB(),
169179
)
170180

tests/hazmat/primitives/decrepit/test_algorithms.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import pytest
1010

11+
from cryptography import utils
1112
from cryptography.exceptions import _Reasons
1213
from cryptography.hazmat.decrepit.ciphers.algorithms import (
1314
ARC4,
@@ -72,9 +73,8 @@ def test_invalid_mode_algorithm():
7273

7374

7475
class TestTripleDES:
75-
@pytest.mark.parametrize("key", [b"0" * 16, b"0" * 32, b"0" * 48])
76-
def test_key_size(self, key):
77-
cipher = TripleDES(binascii.unhexlify(key))
76+
def test_key_size(self):
77+
cipher = TripleDES(binascii.unhexlify(b"0" * 48))
7878
assert cipher.key_size == 192
7979

8080
def test_invalid_key_size(self):
@@ -85,6 +85,16 @@ def test_invalid_key_type(self):
8585
with pytest.raises(TypeError, match="key must be bytes"):
8686
TripleDES("0" * 16) # type: ignore[arg-type]
8787

88+
def test_single_key_deprecated(self):
89+
with pytest.warns(utils.DeprecatedIn47):
90+
cipher = TripleDES(binascii.unhexlify(b"0" * 16))
91+
assert cipher.key_size == 192
92+
93+
def test_two_key_deprecated(self):
94+
with pytest.warns(utils.DeprecatedIn47):
95+
cipher = TripleDES(binascii.unhexlify(b"0" * 32))
96+
assert cipher.key_size == 192
97+
8898

8999
class TestBlowfish:
90100
@pytest.mark.parametrize(

tests/hazmat/primitives/test_cmac.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def test_aes_verify(self, backend, params):
8181

8282
@pytest.mark.supported(
8383
only_if=lambda backend: backend.cmac_algorithm_supported(
84-
TripleDES(fake_key)
84+
TripleDES(b"\x00" * 24)
8585
),
8686
skip_message="Does not support CMAC.",
8787
)
@@ -102,7 +102,7 @@ def test_3des_generate(self, backend, params):
102102

103103
@pytest.mark.supported(
104104
only_if=lambda backend: backend.cmac_algorithm_supported(
105-
TripleDES(fake_key)
105+
TripleDES(b"\x00" * 24)
106106
),
107107
skip_message="Does not support CMAC.",
108108
)

tests/hazmat/primitives/utils.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,11 @@ def _kbkdf_cmac_counter_mode_test(backend, prf, ctr_loc, brk_loc, params):
448448
break_location=brk_loc,
449449
)
450450

451-
ko = ctrkdf.derive(binascii.unhexlify(params["ki"]))
451+
ki = binascii.unhexlify(params["ki"])
452+
# TripleDES requires 24-byte keys. Expand 16-byte (2-key) to 24-byte.
453+
if prf == "cmac_tdes2":
454+
ki = ki + ki[:8]
455+
ko = ctrkdf.derive(ki)
452456
assert binascii.hexlify(ko) == params["ko"]
453457

454458

0 commit comments

Comments
 (0)