Skip to content

Commit 9ee84a1

Browse files
authored
Hack support for terrible RSA key-lengths in cryptography 43.0 (#4290)
1 parent ca56748 commit 9ee84a1

File tree

1 file changed

+39
-6
lines changed

1 file changed

+39
-6
lines changed

scapy/layers/tls/cert.py

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,27 @@
4444
from scapy.layers.tls.crypto.pkcs1 import pkcs_os2ip, _get_hash, \
4545
_EncryptAndVerifyRSA, _DecryptAndSignRSA
4646
from scapy.compat import raw, bytes_encode
47+
4748
if conf.crypto_valid:
4849
from cryptography.exceptions import InvalidSignature
4950
from cryptography.hazmat.backends import default_backend
5051
from cryptography.hazmat.primitives import serialization
5152
from cryptography.hazmat.primitives.asymmetric import rsa, ec
5253

54+
# cryptography raised the minimum RSA key length to 1024 in 43.0+
55+
# https://github.com/pyca/cryptography/pull/10278
56+
# but we need still 512 for EXPORT40 ciphers (yes EXPORT is terrible)
57+
# https://datatracker.ietf.org/doc/html/rfc2246#autoid-66
58+
# The following detects the change and hacks around it using the backend
59+
60+
try:
61+
rsa.generate_private_key(public_exponent=65537, key_size=512)
62+
_RSA_512_SUPPORTED = True
63+
except ValueError:
64+
# cryptography > 43.0
65+
_RSA_512_SUPPORTED = False
66+
from cryptography.hazmat.primitives.asymmetric.rsa import rust_openssl
67+
5368

5469
# Maximum allowed size in bytes for a certificate file, to avoid
5570
# loading huge file when importing a cert
@@ -263,9 +278,18 @@ def fill_and_store(self, modulus=None, modulusLen=None, pubExp=None):
263278
pubExp = pubExp or 65537
264279
if not modulus:
265280
real_modulusLen = modulusLen or 2048
266-
private_key = rsa.generate_private_key(public_exponent=pubExp,
267-
key_size=real_modulusLen,
268-
backend=default_backend())
281+
if real_modulusLen < 1024 and not _RSA_512_SUPPORTED:
282+
# cryptography > 43.0 compatibility
283+
private_key = rust_openssl.rsa.generate_private_key(
284+
public_exponent=pubExp,
285+
key_size=real_modulusLen,
286+
)
287+
else:
288+
private_key = rsa.generate_private_key(
289+
public_exponent=pubExp,
290+
key_size=real_modulusLen,
291+
backend=default_backend(),
292+
)
269293
self.pubkey = private_key.public_key()
270294
else:
271295
real_modulusLen = len(binrepr(modulus))
@@ -470,9 +494,18 @@ def fill_and_store(self, modulus=None, modulusLen=None, pubExp=None,
470494
# in order to call RSAPrivateNumbers(...)
471495
# if one of these is missing, we generate a whole new key
472496
real_modulusLen = modulusLen or 2048
473-
self.key = rsa.generate_private_key(public_exponent=pubExp,
474-
key_size=real_modulusLen,
475-
backend=default_backend())
497+
if real_modulusLen < 1024 and not _RSA_512_SUPPORTED:
498+
# cryptography > 43.0 compatibility
499+
self.key = rust_openssl.rsa.generate_private_key(
500+
public_exponent=pubExp,
501+
key_size=real_modulusLen,
502+
)
503+
else:
504+
self.key = rsa.generate_private_key(
505+
public_exponent=pubExp,
506+
key_size=real_modulusLen,
507+
backend=default_backend(),
508+
)
476509
self.pubkey = self.key.public_key()
477510
else:
478511
real_modulusLen = len(binrepr(modulus))

0 commit comments

Comments
 (0)